= 2
+ORDER BY flower.title DESC
+SQL;
+
+ $this->assertEquals($data, $this->loadToData($sql));
+ }
+
+ /**
+ * Method to test addTable().
+ *
+ * @return void
+ *
+ * @covers Windwalker\DataMapper\RelationDataMapper::addTable
+ */
+ public function testAddTable()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test removeTable().
+ *
+ * @return void
+ *
+ * @covers Windwalker\DataMapper\RelationDataMapper::removeTable
+ * @TODO Implement testRemoveTable().
+ */
+ public function testRemoveTable()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/Test/Stub/StubDataMapperListener.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/Test/Stub/StubDataMapperListener.php
new file mode 100644
index 00000000..e263baae
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/Test/Stub/StubDataMapperListener.php
@@ -0,0 +1,363 @@
+events[__FUNCTION__] = clone $event;
+
+ $event->setArgument('limit', 20);
+ }
+
+ /**
+ * onAfterFind
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onAfterFind(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['result'][] = array('method' => 'After');
+ }
+
+ /**
+ * onBeforeFindAll
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onBeforeFindAll(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['limit'] = 20;
+ }
+
+ /**
+ * onAfterFindAll
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onAfterFindAll(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['result'][] = array('method' => 'After');
+ }
+
+ /**
+ * onBeforeFindOne
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onBeforeFindOne(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['order'] = 'id';
+ }
+
+ /**
+ * onAfterFindOne
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onAfterFindOne(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['result']->foo = 'after';
+ }
+
+ /**
+ * onBeforeFindColumn
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onBeforeFindColumn(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['column'] = 'bar';
+ }
+
+ /**
+ * onAfterFindColumn
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onAfterFindColumn(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['result'] = 'After';
+ }
+
+ /**
+ * onBeforeCreate
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onBeforeCreate(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['dataset'] = array();
+ }
+
+ /**
+ * onAfterCreate
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onAfterCreate(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['result'] = 'after';
+ }
+
+ /**
+ * onBeforeCreateOne
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onBeforeCreateOne(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['data'] = array();
+ }
+
+ /**
+ * onAfterCreateOne
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onAfterCreateOne(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['result'] = 'after';
+ }
+
+ /**
+ * onBeforeUpdate
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onBeforeUpdate(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['confFields'] = 'state';
+ }
+
+ /**
+ * onAfterUpdate
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onAfterUpdate(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['result'] = 'after';
+ }
+
+ /**
+ * onBeforeUpdateOne
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onBeforeUpdateOne(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['confFields'] = 'state';
+ }
+
+ /**
+ * onAfterUpdateOne
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onAfterUpdateOne(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['result'] = 'after';
+ }
+
+ /**
+ * onBeforeSave
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onBeforeSave(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['confFields'] = 'state';
+ }
+
+ /**
+ * onAfterSave
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onAfterSave(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['result'] = 'after';
+ }
+
+ /**
+ * onBeforeSaveOne
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onBeforeSaveOne(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['confFields'] = 'state';
+ }
+
+ /**
+ * onAfterSaveOne
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onAfterSaveOne(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['result'] = 'after';
+ }
+
+ /**
+ * onBeforeFlush
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onBeforeFlush(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['conditions'] = array('state' => 1);
+ }
+
+ /**
+ * onAfterFlush
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onAfterFlush(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['result'] = 'after';
+ }
+
+ /**
+ * onBeforeDelete
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onBeforeDelete(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['conditions'] = array('state' => 1);
+ }
+
+ /**
+ * onAfterDelete
+ *
+ * @param Event $event
+ *
+ * @return void
+ */
+ public function onAfterDelete(Event $event)
+ {
+ $this->events[__FUNCTION__] = clone $event;
+
+ $event['result'] = 'after';
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/Test/Stub/StubDispatcherAwareDatamapper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/Test/Stub/StubDispatcherAwareDatamapper.php
new file mode 100644
index 00000000..843cf8fe
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/Test/Stub/StubDispatcherAwareDatamapper.php
@@ -0,0 +1,110 @@
+args = func_get_args();
+
+ return new DataSet(array(array('method' => __FUNCTION__)));
+ }
+
+ /**
+ * Do create action, this method should be override by sub class.
+ *
+ * @param mixed $dataset The data set contains data we want to store.
+ *
+ * @return mixed Data set data with inserted id.
+ */
+ protected function doCreate($dataset)
+ {
+ return new DataSet(array(array('method' => __FUNCTION__)));
+ }
+
+ /**
+ * Do update action, this method should be override by sub class.
+ *
+ * @param mixed $dataset Data set contain data we want to update.
+ * @param array $condFields The where condition tell us record exists or not, if not set,
+ * will use primary key instead.
+ * @param bool $updateNulls Update empty fields or not.
+ *
+ * @return mixed Updated data set.
+ */
+ protected function doUpdate($dataset, array $condFields, $updateNulls = false)
+ {
+ return new DataSet(array(array('method' => __FUNCTION__)));
+ }
+
+ /**
+ * Do updateAll action, this method should be override by sub class.
+ *
+ * @param mixed $data The data we want to update to every rows.
+ * @param mixed $conditions Where conditions, you can use array or Compare object.
+ *
+ * @return boolean
+ */
+ protected function doUpdateAll($data, array $conditions)
+ {
+ return true;
+ }
+
+ /**
+ * Do flush action, this method should be override by sub class.
+ *
+ * @param mixed $dataset Data set contain data we want to update.
+ * @param mixed $conditions Where conditions, you can use array or Compare object.
+ *
+ * @return mixed Updated data set.
+ */
+ protected function doFlush($dataset, array $conditions)
+ {
+ return new DataSet(array(array('method' => __FUNCTION__)));
+ }
+
+ /**
+ * Do delete action, this method should be override by sub class.
+ *
+ * @param mixed $conditions Where conditions, you can use array or Compare object.
+ *
+ * @return boolean Will be always true.
+ */
+ protected function doDelete(array $conditions)
+ {
+ return true;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/Test/Stub/data.sql b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/Test/Stub/data.sql
new file mode 100644
index 00000000..8d0447c4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/Test/Stub/data.sql
@@ -0,0 +1,110 @@
+
+CREATE TABLE IF NOT EXISTS `ww_categories` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
+ `ordering` int(11) NOT NULL,
+ `params` text COLLATE utf8_unicode_ci NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ;
+
+INSERT INTO `ww_categories` (`id`, `title`, `ordering`, `params`) VALUES
+ (1, 'Foo', 1, ''),
+ (2, 'Bar', 2, '');
+
+CREATE TABLE IF NOT EXISTS `ww_flower` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `catid` int(11) NOT NULL,
+ `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
+ `meaning` text COLLATE utf8_unicode_ci NOT NULL,
+ `ordering` int(11) NOT NULL,
+ `state` tinyint(1) NOT NULL,
+ `params` text COLLATE utf8_unicode_ci NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=86 ;
+
+INSERT INTO `ww_flower` (`id`, `catid`, `title`, `meaning`, `ordering`, `state`, `params`) VALUES
+ (1, 2, 'Alstroemeria', 'aspiring', 1, 0, ''),
+ (2, 2, 'Amaryllis', 'dramatic', 2, 0, ''),
+ (3, 1, 'Anemone', 'fragile', 3, 0, ''),
+ (4, 1, 'Apple Blossom', 'promis', 4, 1, ''),
+ (5, 2, 'Aster', 'contentment', 5, 1, ''),
+ (6, 2, 'Azalea', 'abundance', 6, 0, ''),
+ (7, 1, 'Baby''s Breath', 'festivity', 7, 1, ''),
+ (8, 2, 'Bachelor Button', 'anticipation', 8, 0, ''),
+ (9, 2, 'Begonia', 'deep thoughts', 9, 0, ''),
+ (10, 2, 'Black-Eyed Susan', 'encouragement', 10, 0, ''),
+ (11, 1, 'Camellia', 'graciousness', 11, 1, ''),
+ (12, 1, 'Carnation', '', 12, 1, ''),
+ (13, 1, 'pink', 'gratitude', 13, 1, ''),
+ (14, 1, 'red', 'flashy', 14, 1, ''),
+ (15, 1, 'striped', 'refusal', 15, 1, ''),
+ (16, 1, 'white', 'remembrance', 16, 1, ''),
+ (17, 1, 'yellow', 'cheerful', 17, 1, ''),
+ (18, 1, 'Chrysanthemum', '', 18, 0, ''),
+ (19, 2, 'bronze', 'excitement', 19, 1, ''),
+ (20, 1, 'white', 'truth', 20, 0, ''),
+ (21, 1, 'red', 'sharing', 21, 1, ''),
+ (22, 1, 'yellow', 'secret admirer', 22, 0, ''),
+ (23, 1, 'Cosmos', 'peaceful', 23, 0, ''),
+ (24, 1, 'Crocus', 'foresight', 24, 0, ''),
+ (25, 1, 'Daffodil', 'chivalry', 25, 1, ''),
+ (26, 2, 'Delphinium', 'boldness', 26, 0, ''),
+ (27, 2, 'Daisy', 'innocence', 27, 0, ''),
+ (28, 1, 'Freesia', 'spirited', 28, 0, ''),
+ (29, 2, 'Forget-Me-Not', 'remember me forever', 29, 1, ''),
+ (30, 2, 'Gardenia', 'joy', 30, 1, ''),
+ (31, 2, 'Geranium', 'comfort', 31, 1, ''),
+ (32, 2, 'Ginger', 'proud', 32, 1, ''),
+ (33, 2, 'Gladiolus', 'strength of character', 33, 0, ''),
+ (34, 1, 'Heather', 'solitude', 34, 1, ''),
+ (35, 2, 'Hibiscus', 'delicate beauty', 35, 0, ''),
+ (36, 1, 'Holly', 'domestic happiness', 36, 1, ''),
+ (37, 1, 'Hyacinth', 'sincerity', 37, 0, ''),
+ (38, 1, 'Hydrangea', 'perseverance', 38, 1, ''),
+ (39, 2, 'Iris', 'inspiration', 39, 0, ''),
+ (40, 1, 'Ivy', 'fidelity', 40, 0, ''),
+ (41, 1, 'Jasmine', 'grace and elegance', 41, 0, ''),
+ (42, 1, 'Larkspur', 'beautiful spirit', 42, 0, ''),
+ (43, 1, 'Lavender', 'distrust', 43, 0, ''),
+ (44, 1, 'Lilac', 'first love', 44, 1, ''),
+ (45, 1, 'Lily', '', 45, 0, ''),
+ (46, 1, 'Calla', 'regal', 46, 1, ''),
+ (47, 1, 'Casablanca', 'celebration', 47, 1, ''),
+ (48, 2, 'Day', 'enthusiasm', 48, 1, ''),
+ (49, 1, 'Stargazer', 'ambition', 49, 0, ''),
+ (50, 1, 'Lisianthus', 'calming', 50, 1, ''),
+ (51, 2, 'Magnolia', 'dignity', 51, 0, ''),
+ (52, 1, 'Marigold', 'desire for riches', 52, 0, ''),
+ (53, 1, 'Nasturtium', 'patriotism', 53, 0, ''),
+ (54, 2, 'Orange Blossom', 'fertility', 54, 1, ''),
+ (55, 1, 'Orchid', 'delicate beauty', 55, 0, ''),
+ (56, 2, 'Pansy', 'loving thoughts', 56, 0, ''),
+ (57, 1, 'Passion flower', 'passion', 57, 1, ''),
+ (58, 2, 'Peony', 'healing', 58, 1, ''),
+ (59, 2, 'Poppy', 'consolation', 59, 0, ''),
+ (60, 1, 'Queen Anne''s Lace', 'delicate femininity', 60, 0, ''),
+ (61, 1, 'Ranunculus', 'radiant', 61, 1, ''),
+ (62, 1, 'Rhododendron', 'beware', 62, 0, ''),
+ (63, 1, 'Rose', '', 63, 1, ''),
+ (64, 2, 'pink', 'admiration/appreciation', 64, 0, ''),
+ (65, 2, 'red', 'passionate love', 65, 1, ''),
+ (66, 1, 'red & white', 'unity', 66, 1, ''),
+ (67, 1, 'white', 'purity', 67, 1, ''),
+ (68, 1, 'yellow', 'friendship', 68, 1, ''),
+ (69, 2, 'Snapdragon', 'presumptuous', 69, 1, ''),
+ (70, 1, 'Star of Bethlehem', 'hope', 70, 1, ''),
+ (71, 1, 'Stephanotis', 'good luck', 71, 1, ''),
+ (72, 2, 'Statice', 'success', 72, 1, ''),
+ (73, 2, 'Sunflower', 'adoration', 73, 0, ''),
+ (74, 1, 'Sweetpea', 'shyness', 74, 1, ''),
+ (75, 2, 'Tuberose', 'pleasure', 75, 1, ''),
+ (76, 1, 'Tulip', '', 76, 1, ''),
+ (77, 2, 'pink', 'caring', 77, 1, ''),
+ (78, 1, 'purple', 'royalty', 78, 0, ''),
+ (79, 1, 'red', 'declaration of love', 79, 1, ''),
+ (80, 1, 'white', 'forgiveness', 80, 0, ''),
+ (81, 1, 'yellow', 'hopelessly in love', 81, 0, ''),
+ (82, 2, 'Violet', 'faithfulness', 82, 1, ''),
+ (83, 2, 'Wisteria', 'steadfast', 83, 0, ''),
+ (84, 1, 'Yarrow', 'good health', 84, 1, ''),
+ (85, 2, 'Zinnia', 'thoughts of friends', 85, 1, '');
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/Test/WindwalkerAdapterTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/Test/WindwalkerAdapterTest.php
new file mode 100644
index 00000000..0182e114
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/Test/WindwalkerAdapterTest.php
@@ -0,0 +1,191 @@
+instance = new WindwalkerAdapter;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test find().
+ *
+ * @return void
+ *
+ * @covers Windwalker\DataMapper\Adapter\WindwalkerAdapter::find
+ * @TODO Implement testFind().
+ */
+ public function testFind()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test create().
+ *
+ * @return void
+ *
+ * @covers Windwalker\DataMapper\Adapter\WindwalkerAdapter::create
+ * @TODO Implement testCreate().
+ */
+ public function testCreate()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test updateOne().
+ *
+ * @return void
+ *
+ * @covers Windwalker\DataMapper\Adapter\WindwalkerAdapter::updateOne
+ * @TODO Implement testUpdateOne().
+ */
+ public function testUpdateOne()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test updateAll().
+ *
+ * @return void
+ *
+ * @covers Windwalker\DataMapper\Adapter\WindwalkerAdapter::updateAll
+ * @TODO Implement testUpdateAll().
+ */
+ public function testUpdateAll()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test delete().
+ *
+ * @return void
+ *
+ * @covers Windwalker\DataMapper\Adapter\WindwalkerAdapter::delete
+ * @TODO Implement testDelete().
+ */
+ public function testDelete()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getFields().
+ *
+ * @return void
+ *
+ * @covers Windwalker\DataMapper\Adapter\WindwalkerAdapter::getFields
+ * @TODO Implement testGetFields().
+ */
+ public function testGetFields()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test transactionStart().
+ *
+ * @return void
+ *
+ * @covers Windwalker\DataMapper\Adapter\WindwalkerAdapter::transactionStart
+ * @TODO Implement testTransactionStart().
+ */
+ public function testTransactionStart()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test transactionCommit().
+ *
+ * @return void
+ *
+ * @covers Windwalker\DataMapper\Adapter\WindwalkerAdapter::transactionCommit
+ * @TODO Implement testTransactionCommit().
+ */
+ public function testTransactionCommit()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test transactionRollback().
+ *
+ * @return void
+ *
+ * @covers Windwalker\DataMapper\Adapter\WindwalkerAdapter::transactionRollback
+ * @TODO Implement testTransactionRollback().
+ */
+ public function testTransactionRollback()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/composer.json b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/composer.json
new file mode 100644
index 00000000..2947daac
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/composer.json
@@ -0,0 +1,34 @@
+{
+ "name": "windwalker/datamapper",
+ "type": "windwalker-package",
+ "description": "Windwalker DataMapper package",
+ "keywords": ["windwalker", "framework", "datamapper"],
+ "homepage": "https://github.com/ventoviro/windwalker-datamapper",
+ "license": "LGPL-2.0+",
+ "require": {
+ "php": ">=5.3.10",
+ "windwalker/data": "~2.0"
+ },
+ "require-dev": {
+ "windwalker/database": "~2.0",
+ "windwalker/test": "~2.0",
+ "windwalker/compare": "~2.0",
+ "windwalker/event": "~2.0"
+ },
+ "suggest": {
+ "windwalker/database": "Install 2.* if you want Windwalker Database.",
+ "windwalker/event": "Install 2.* if you want to use hooks.",
+ "windwalker/compare": "Install 2.* if you want to use Compare object."
+ },
+ "minimum-stability": "beta",
+ "autoload": {
+ "psr-4": {
+ "Windwalker\\DataMapper\\": ""
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/phpunit.travis.xml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/phpunit.travis.xml
new file mode 100644
index 00000000..690ec926
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/phpunit.travis.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/phpunit.xml.dist b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/phpunit.xml.dist
new file mode 100644
index 00000000..e4b0f4ee
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/datamapper/phpunit.xml.dist
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/.gitignore b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/.gitignore
new file mode 100644
index 00000000..84718b5d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/.gitignore
@@ -0,0 +1,11 @@
+# Development system files #
+.*
+!/.gitignore
+!/.travis.yml
+
+# Composer #
+vendor/*
+composer.lock
+
+# Test #
+phpunit.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/.travis.yml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/.travis.yml
new file mode 100644
index 00000000..5420e5c4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/.travis.yml
@@ -0,0 +1,16 @@
+language: php
+
+sudo: false
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+
+before_script:
+ - composer update --dev
+
+script:
+ - phpunit --configuration phpunit.travis.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Builder/DomBuilder.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Builder/DomBuilder.php
new file mode 100644
index 00000000..c77df7ca
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Builder/DomBuilder.php
@@ -0,0 +1,90 @@
+' . $content . '' . $name . '>';
+ }
+ else
+ {
+ $tag .= $forcePair ? '>' . $name . '>' : ' />';
+ }
+
+ return $tag;
+ }
+
+ /**
+ * buildAttributes
+ *
+ * @param array $attribs
+ *
+ * @return string
+ */
+ public static function buildAttributes($attribs)
+ {
+ $string = '';
+
+ foreach ((array) $attribs as $key => $value)
+ {
+ if ($value === true)
+ {
+ $string .= ' ' . $key;
+
+ continue;
+ }
+
+ if ($value === null || $value === false)
+ {
+ continue;
+ }
+
+ $string .= ' ' . $key . '=' . static::quote($value);
+ }
+
+ return $string;
+ }
+
+ /**
+ * quote
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ public static function quote($value)
+ {
+ return '"' . $value . '"';
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Builder/HtmlBuilder.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Builder/HtmlBuilder.php
new file mode 100644
index 00000000..24e374b9
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Builder/HtmlBuilder.php
@@ -0,0 +1,87 @@
+ 'readonly',
+ 'disabled' => 'disabled',
+ 'multiple' => 'true',
+ 'checked' => 'checked',
+ 'selected' => 'selected'
+ );
+
+ /**
+ * Create a html element.
+ *
+ * @param string $name Element tag name.
+ * @param mixed $content Element content.
+ * @param array $attribs Element attributes.
+ * @param bool $forcePair Force pair it.
+ *
+ * @return string Created element string.
+ */
+ public static function create($name, $content = '', $attribs = array(), $forcePair = false)
+ {
+ $paired = $forcePair ? : !in_array(strtolower($name), static::$unpairedElements);
+
+ return parent::create($name, $content, $attribs, $paired);
+ }
+
+ /**
+ * buildAttributes
+ *
+ * @param array $attribs
+ *
+ * @return string
+ */
+ public static function buildAttributes($attribs)
+ {
+ $attribs = static::mapAttrValues($attribs);
+
+ return parent::buildAttributes($attribs);
+ }
+
+ /**
+ * mapAttrValues
+ *
+ * @param array $attribs
+ *
+ * @return mixed
+ */
+ protected static function mapAttrValues($attribs)
+ {
+ foreach (static::$trueValueMapping as $key => $value)
+ {
+ $attribs[$key] = !empty($attribs[$key]) ? $value : null;
+ }
+
+ return $attribs;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/DomElement.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/DomElement.php
new file mode 100644
index 00000000..855fdcd5
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/DomElement.php
@@ -0,0 +1,261 @@
+name = $name;
+ $this->attribs = $attribs;
+ $this->content = $content;
+ }
+
+ /**
+ * toString
+ *
+ * @param boolean $forcePair
+ *
+ * @return string
+ */
+ public function toString($forcePair = false)
+ {
+ return DomBuilder::create($this->name, $this->content, $this->attribs, $forcePair);
+ }
+
+ /**
+ * Alias of toString()
+ *
+ * @param boolean $forcePair
+ *
+ * @return string
+ */
+ public function render($forcePair = false)
+ {
+ return $this->toString($forcePair);
+ }
+
+ /**
+ * Convert this object to string.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ try
+ {
+ return $this->toString();
+ }
+ catch (\Exception $e)
+ {
+ return (string) $e;
+ }
+ }
+
+ /**
+ * Get content.
+ *
+ * @return mixed
+ */
+ public function getContent()
+ {
+ return $this->content;
+ }
+
+ /**
+ * Set content.
+ *
+ * @param mixed $content Element content.
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setContent($content)
+ {
+ $this->content = $content;
+
+ return $this;
+ }
+
+ /**
+ * Get attributes.
+ *
+ * @param string $name Attribute name.
+ * @param mixed $default Default value.
+ *
+ * @return string The attribute value.
+ */
+ public function getAttribute($name, $default = null)
+ {
+ if (empty($this->attribs[$name]))
+ {
+ return $default;
+ }
+
+ return $this->attribs[$name];
+ }
+
+ /**
+ * Set attribute value.
+ *
+ * @param string $name Attribute name.
+ * @param string $value The value to set into attribute.
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setAttribute($name, $value)
+ {
+ $this->attribs[$name] = $value;
+
+ return $this;
+ }
+
+ /**
+ * Get all attributes.
+ *
+ * @return array All attributes.
+ */
+ public function getAttributes()
+ {
+ return $this->attribs;
+ }
+
+ /**
+ * Set all attributes.
+ *
+ * @param array $attribs All attributes.
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setAttributes($attribs)
+ {
+ $this->attribs = $attribs;
+
+ return $this;
+ }
+
+ /**
+ * Get element tag name.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Set element tag name.
+ *
+ * @param string $name Set element tag name.
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ /**
+ * Whether a offset exists
+ *
+ * @param mixed $offset An offset to check for.
+ *
+ * @return boolean True on success or false on failure.
+ * The return value will be casted to boolean if non-boolean was returned.
+ */
+ public function offsetExists($offset)
+ {
+ return isset($this->attribs[$offset]);
+ }
+
+ /**
+ * Offset to retrieve
+ *
+ * @param mixed $offset The offset to retrieve.
+ *
+ * @return mixed Can return all value types.
+ */
+ public function offsetGet($offset)
+ {
+ if (!$this->offsetExists($offset))
+ {
+ return null;
+ }
+
+ return $this->attribs[$offset];
+ }
+
+ /**
+ * Offset to set
+ *
+ * @param mixed $offset The offset to assign the value to.
+ * @param mixed $value The value to set.
+ *
+ * @return void
+ */
+ public function offsetSet($offset, $value)
+ {
+ $this->attribs[$offset] = $value;
+ }
+
+ /**
+ * Offset to unset
+ *
+ * @param mixed $offset The offset to unset.
+ *
+ * @return void
+ */
+ public function offsetUnset($offset)
+ {
+ unset($this->attribs[$offset]);
+ }
+}
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/DomElements.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/DomElements.php
new file mode 100644
index 00000000..c13d18bb
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/DomElements.php
@@ -0,0 +1,199 @@
+elements = (array) $elements;
+ $this->strict = $strict;
+ }
+
+ /**
+ * Convert all elements to string.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $return = '';
+
+ foreach ($this as $element)
+ {
+ $return .= (string) $element;
+ }
+
+ return $return;
+ }
+
+ /**
+ * Retrieve an external iterator
+ *
+ * @return \Traversable
+ */
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->elements);
+ }
+
+ /**
+ * Whether a offset exists
+ *
+ * @param mixed $offset An offset to check for.
+ *
+ * @return boolean true on success or false on failure.
+ */
+ public function offsetExists($offset)
+ {
+ return isset($this->elements[$offset]);
+ }
+
+ /**
+ * Offset to retrieve
+ *
+ * @param mixed $offset The offset to retrieve.
+ *
+ * @return mixed Can return all value types.
+ */
+ public function offsetGet($offset)
+ {
+ if (!$this->strict && !$this->offsetExists($offset))
+ {
+ return null;
+ }
+
+ return $this->elements[$offset];
+ }
+
+ /**
+ * Offset to set
+ *
+ * @param mixed $offset The offset to assign the value to.
+ * @param mixed $value The value to set.
+ *
+ * @return void
+ */
+ public function offsetSet($offset, $value)
+ {
+ if ($offset === '' || $offset === null)
+ {
+ array_push($this->elements, $value);
+
+ return;
+ }
+
+ $this->elements[$offset] = $value;
+ }
+
+ /**
+ * Offset to unset
+ *
+ * @param mixed $offset The offset to unset.
+ *
+ * @return void
+ */
+ public function offsetUnset($offset)
+ {
+ if (!$this->strict && !$this->offsetExists($offset))
+ {
+ return;
+ }
+
+ unset($this->elements[$offset]);
+ }
+
+ /**
+ * Count elements of an object
+ *
+ * @return int The custom count as an integer.
+ */
+ public function count()
+ {
+ return count($this->elements);
+ }
+
+ /**
+ * Method to get property Strict
+ *
+ * @return boolean
+ */
+ public function getStrict()
+ {
+ return $this->strict;
+ }
+
+ /**
+ * Method to set property strict
+ *
+ * @param boolean $strict
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setStrict($strict)
+ {
+ $this->strict = $strict;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property Elements
+ *
+ * @return \mixed[]|HtmlElement[]
+ */
+ public function getElements()
+ {
+ return $this->elements;
+ }
+
+ /**
+ * Method to set property elements
+ *
+ * @param \mixed[]|HtmlElement[] $elements
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setElements($elements)
+ {
+ $this->elements = $elements;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Format/DomFormatter.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Format/DomFormatter.php
new file mode 100644
index 00000000..9ffa688d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Format/DomFormatter.php
@@ -0,0 +1,272 @@
+ ' '
+ );
+
+ const ELEMENT_TYPE_BLOCK = 0;
+ const ELEMENT_TYPE_INLINE = 1;
+
+ const MATCH_INDENT_NO = 0;
+ const MATCH_INDENT_DECREASE = 1;
+ const MATCH_INDENT_INCREASE = 2;
+ const MATCH_DISCARD = 3;
+
+ /**
+ * Property instance.
+ *
+ * @var static[]
+ */
+ protected static $instance;
+
+ /**
+ * getInstance
+ *
+ * @return static
+ */
+ public static function getInstance()
+ {
+ if (empty(static::$instance))
+ {
+ static::$instance = new static;
+ }
+
+ return static::$instance;
+ }
+
+ /**
+ * Method to set property instance
+ *
+ * @param static $instance
+ *
+ * @return void
+ */
+ public static function setInstance($instance)
+ {
+ static::$instance = $instance;
+ }
+
+ /**
+ * format
+ *
+ * @param string $buffer
+ *
+ * @return string Formatted Html string.
+ */
+ public static function format($buffer)
+ {
+ return static::getInstance()->indent($buffer);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param array $options
+ */
+ public function __construct(array $options = array())
+ {
+ foreach ($options as $name => $value)
+ {
+ if (!array_key_exists($name, $this->options))
+ {
+ throw new \InvalidArgumentException('Unrecognized option.');
+ }
+
+ $this->options[$name] = $value;
+ }
+ }
+
+ /**
+ * indent
+ *
+ * @param string $input
+ *
+ * @return string
+ */
+ public function indent($input)
+ {
+ $this->log = array();
+
+ $input = $this->removeDoubleWhiteSpace($input);
+
+ $output = $this->doIndent($input);
+
+ return trim($output);
+ }
+
+ /**
+ * Format Dom.
+ *
+ * @param string $input Dom input.
+ *
+ * @return string Indented Dom.
+ */
+ public function doIndent($input)
+ {
+ $subject = $input;
+
+ $output = '';
+
+ $nextLineIndentationLevel = 0;
+
+ do
+ {
+ $indentationLevel = $nextLineIndentationLevel;
+
+ $patterns = $this->getTagPatterns();
+
+ $rules = array('NO', 'DECREASE', 'INCREASE', 'DISCARD');
+
+ $match = array();
+
+ foreach ($patterns as $pattern => $rule)
+ {
+ if ($match = preg_match($pattern, $subject, $matches))
+ {
+ $this->log[] = array(
+ 'rule' => $rules[$rule],
+ 'pattern' => $pattern,
+ 'subject' => $subject,
+ 'match' => $matches[0]
+ );
+
+ $subject = mb_substr($subject, mb_strlen($matches[0]));
+
+ if ($rule === static::MATCH_DISCARD)
+ {
+ break;
+ }
+
+ if ($rule === static::MATCH_INDENT_NO)
+ {
+
+ }
+ else
+ {
+ if ($rule === static::MATCH_INDENT_DECREASE)
+ {
+ $nextLineIndentationLevel--;
+ $indentationLevel--;
+ }
+ else
+ {
+ $nextLineIndentationLevel++;
+ }
+ }
+
+ if ($indentationLevel < 0)
+ {
+ $indentationLevel = 0;
+ }
+
+ $output .= str_repeat($this->options['indentation_character'], $indentationLevel) . $matches[0] . "\n";
+
+ break;
+ }
+ }
+ }
+ while ($match);
+
+ $interpretedInput = '';
+
+ foreach ($this->log as $e)
+ {
+ $interpretedInput .= $e['match'];
+ }
+
+ if ($interpretedInput !== $input)
+ {
+ throw new \RuntimeException('Did not reproduce the exact input.');
+ }
+
+ $output = preg_replace('/(<(\w+)[^>]*>)\s*(<\/\2>)/', '\\1\\3', $output);
+
+ return $output;
+ }
+
+ /**
+ * removeDoubleWhiteSpace
+ *
+ * @param string $input
+ *
+ * @return string
+ */
+ protected function removeDoubleWhiteSpace($input)
+ {
+ /*
+ * Removing double whitespaces to make the source code easier to read.
+ * With exception of / CSS white-space changing the default behaviour,
+ * double whitespace is meaningless in HTML output.
+ *
+ * This reason alone is sufficient not to use Dindent in production.
+ */
+ $input = str_replace("\t", '', $input);
+ $input = preg_replace('/\s{2,}/', ' ', $input);
+
+ return $input;
+ }
+
+ /**
+ * getTagPatterns
+ *
+ * @return array
+ */
+ protected function getTagPatterns()
+ {
+ return array(
+ // block tag
+ '/^(<([a-z]+)(?:[^>]*)>(?:[^<]*)<\/(?:\2)>)/' => static::MATCH_INDENT_NO,
+ // DOCTYPE
+ '/^]*)>/' => static::MATCH_INDENT_NO,
+ // opening tag
+ '/^<[^\/]([^>]*)>/' => static::MATCH_INDENT_INCREASE,
+ // closing tag
+ '/^<\/([^>]*)>/' => static::MATCH_INDENT_DECREASE,
+ // self-closing tag
+ '/^<(.+)\/>/' => static::MATCH_INDENT_DECREASE,
+ // whitespace
+ '/^(\s+)/' => static::MATCH_DISCARD,
+ // text node
+ '/([^<]+)/' => static::MATCH_INDENT_NO
+ );
+ }
+
+ /**
+ * Debugging utility. Get log for the last indent operation.
+ *
+ * @return array
+ */
+ public function getLog()
+ {
+ return $this->log;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Format/HtmlFormatter.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Format/HtmlFormatter.php
new file mode 100644
index 00000000..077d4bbf
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Format/HtmlFormatter.php
@@ -0,0 +1,276 @@
+log = array();
+
+ $input = $this->tempScripts($input);
+
+ $input = $this->removeDoubleWhiteSpace($input);
+
+ $input = $this->tempInlineElements($input);
+
+ $output = $this->doIndent($input);
+
+ $output = $this->restoreScripts($output);
+
+ $output = $this->restoreInlineElements($output);
+
+ return trim($output);
+ }
+
+ /**
+ * tempScripts
+ *
+ * @param string $input
+ *
+ * @return string
+ */
+ protected function tempScripts($input)
+ {
+ // Dindent does not indent ', $input);
+ }
+ }
+
+ return $input;
+ }
+
+ /**
+ * restoreScripts
+ *
+ * @param string $output
+ *
+ * @return string
+ */
+ protected function restoreScripts($output)
+ {
+ foreach ($this->temporaryReplacementsScript as $i => $original)
+ {
+ $output = str_replace('', $original, $output);
+ }
+
+ return $output;
+ }
+
+ /**
+ * tempInlineElements
+ *
+ * @param string $input
+ *
+ * @return string
+ */
+ protected function tempInlineElements($input)
+ {
+ // Remove inline elements and replace them with text entities.
+ if (preg_match_all('/<(' . implode('|', $this->inlineElements) . ')[^>]*>(?:[^<]*)<\/\1>/', $input, $matches))
+ {
+ $this->temporaryReplacementsInline = $matches[0];
+
+ foreach ($matches[0] as $i => $match)
+ {
+ $input = str_replace($match, 'ᐃ' . ($i + 1) . 'ᐃ', $input);
+ }
+ }
+
+ return $input;
+ }
+
+ /**
+ * restoreInlineElements
+ *
+ * @param string $output
+ *
+ * @return string
+ */
+ protected function restoreInlineElements($output)
+ {
+ foreach ($this->temporaryReplacementsInline as $i => $original)
+ {
+ $output = str_replace('ᐃ' . ($i + 1) . 'ᐃ', $original, $output);
+ }
+
+ return $output;
+ }
+
+ /**
+ * Method to set property inlineElements
+ *
+ * @param array $inlineElements
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setInlineElements($inlineElements)
+ {
+ $this->inlineElements = (array) $inlineElements;
+
+ return $this;
+ }
+
+ /**
+ * getTagPatterns
+ *
+ * @return array
+ */
+ protected function getTagPatterns()
+ {
+ return array(
+ // block tag
+ '/^(<([a-z]+)(?:[^>]*)>(?:[^<]*)<\/(?:\2)>)/' => static::MATCH_INDENT_NO,
+ // DOCTYPE
+ '/^]*)>/' => static::MATCH_INDENT_NO,
+ // tag with implied closing
+ '/^<(' . $this->getUnpairedElements(true) . ')([^>]*)>/' => static::MATCH_INDENT_NO,
+ // opening tag
+ '/^<[^\/]([^>]*)>/' => static::MATCH_INDENT_INCREASE,
+ // closing tag
+ '/^<\/([^>]*)>/' => static::MATCH_INDENT_DECREASE,
+ // self-closing tag
+ '/^<(.+)\/>/' => static::MATCH_INDENT_DECREASE,
+ // whitespace
+ '/^(\s+)/' => static::MATCH_DISCARD,
+ // text node
+ '/([^<]+)/' => static::MATCH_INDENT_NO
+ );
+ }
+
+ /**
+ * @param string $elementName Element name, e.g. "b".
+ * @param integer $type
+ *
+ * @return void
+ */
+ public function setElementType($elementName, $type)
+ {
+ if ($type === static::ELEMENT_TYPE_BLOCK)
+ {
+ $this->inlineElements = array_diff($this->inlineElements, array($elementName));
+ }
+ else
+ {
+ if ($type === static::ELEMENT_TYPE_INLINE)
+ {
+ $this->inlineElements[] = $elementName;
+ }
+ else
+ {
+ throw new \InvalidArgumentException('Unrecognized element type.');
+ }
+ }
+
+ $this->inlineElements = array_unique($this->inlineElements);
+ }
+
+ /**
+ * addInlineElement
+ *
+ * @param string $element
+ *
+ * @return static
+ */
+ public function addInlineElement($element)
+ {
+ $this->inlineElements[] = trim(strtolower($element));
+
+ return $this;
+ }
+
+ /**
+ * addUnpairedElement
+ *
+ * @param string $element
+ *
+ * @return static
+ */
+ public function addUnpairedElement($element)
+ {
+ $this->unpairedElements[] = trim(strtolower($element));
+
+ return $this;
+ }
+
+ /**
+ * Method to set property unpairedElements
+ *
+ * @param array $unpairedElements
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setUnpairedElements($unpairedElements)
+ {
+ $this->unpairedElements = (array) $unpairedElements;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property UnpairedElements
+ *
+ * @return array
+ */
+ public function getUnpairedElements($implode = false)
+ {
+ return $implode ? implode('|', $this->unpairedElements) : $this->unpairedElements;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Helper/DomHelper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Helper/DomHelper.php
new file mode 100644
index 00000000..7c55d926
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Helper/DomHelper.php
@@ -0,0 +1,50 @@
+[^\S ]+/s',
+
+ // Strip whitespaces before tags, except space
+ '/[^\S ]+\',
+ '<',
+ '\\1'
+ );
+
+ $buffer = preg_replace($search, $replace, $buffer);
+
+ return $buffer;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/HtmlElement.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/HtmlElement.php
new file mode 100644
index 00000000..37decb42
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/HtmlElement.php
@@ -0,0 +1,32 @@
+name, $this->content, $this->attribs, $forcePair);
+ }
+}
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/HtmlElements.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/HtmlElements.php
new file mode 100644
index 00000000..5fe80987
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/HtmlElements.php
@@ -0,0 +1,18 @@
+ 'foo', 'class' => 'bar');
+
+echo $dom = (string) new DomElement('field', 'Content', $attrs);
+```
+
+Output:
+
+``` xml
+Content
+```
+
+Add Children
+
+``` php
+use Windwalker\Dom\DomElement;
+
+$attrs = array('id' => 'foo', 'class' => 'bar');
+
+$content = array(
+ new DomElement('option', 'Yes', array('value' => 1)),
+ new DomElement('option', 'No', array('value' => 0))
+);
+
+echo $dom = (string) new DomElement('field', $content, $attrs);
+```
+
+The output will be:
+
+``` xml
+
+ Yes
+ No
+
+```
+
+### HtmlElement
+
+HtmlElement is use to create HTML elements, some specific tags will force to unpaired.
+
+``` php
+use Windwalker\Dom\HtmlElement;
+
+$attrs = array(
+ 'class' => 'btn btn-mini',
+ 'onclick' => 'return false;'
+);
+
+$html = (string) new HtmlElement('button', 'Click', $attrs);
+```
+
+Then we will get this HTML:
+
+``` html
+Click
+```
+
+#### Get Attributes by Array Access
+
+``` php
+$class = $html['class'];
+```
+
+### DomElements & HtmlElements
+
+It is a collection of HtmlElement set.
+
+``` php
+$html = new HtmlElements(
+ array(
+ new HtmlElement('p', $content, $attrs),
+ new HtmlElement('div', $content, $attrs),
+ new HtmlElement('a', $content, $attrs)
+ )
+);
+
+echo $html;
+```
+
+OR we can iterate it:
+
+``` php
+foreach ($html as $element)
+{
+ echo $element;
+}
+```
+
+### Attributes
+
+``` php
+$html = new HtmlElement('input', array(
+ 'data-string' => 'string',
+ 'data-empty' => '',
+ 'data-true' => true,
+ 'data-false' => false,
+ 'data-null' => null,
+
+ // Special attributes
+ 'checked' => 'checked',
+ 'disabled' => true,
+ 'readonly' => false
+));
+
+echo $html;
+```
+
+Result
+
+``` html
+
+```
+
+## Formatter
+
+`DomFormatter` and `HtmlFormatter` will help us format `XML` / `HTML` string.
+
+``` php
+$xml = 'Yes No ';
+
+DomFormatter::format($xml);
+```
+
+Result
+
+``` xml
+
+ Yes
+ No
+
+```
+
+`HtmlFormatter` will convert some tags to unpaired element, e.g. ` `.
+
+## XmlHelper
+
+`XmlHelper` using on get attributes of `SimpleXmlElement`.
+
+### Get Attributes
+
+``` php
+use Windwalker\Dom\SimpleXml\XmlHelper;
+
+$xml = <<
+
+
+
+
+XML;
+
+$xml = simple_xml_load_string($xml);
+
+$element = $xml->xpath('field');
+
+$name = XmlHelper::getAttribute($element, 'name'); // result: foo
+
+// Same as get()
+$name = XmlHelper::get($element, 'name'); // result: foo
+```
+
+### Get Boolean
+
+`getBool()` can help us convert some string link `true`, `1`, `yes` to boolean `TRUE` and `no`, `false`, `disabled`, `null`, `none`, `0` string to booleand `FALSE`.
+
+``` php
+$bool = XmlHelper::getBool($element, 'readonly'); // result: (boolean) TRUE
+```
+
+### Get False
+
+Just an alias of `getBool()` but FALSE will return `TRUE`.
+
+### Set Default
+
+If this attribute not exists, use this value as default, or we use original value from xml.
+
+``` php
+XmlHelper::def($element, 'class', 'input');
+```
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/SimpleXml/XmlHelper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/SimpleXml/XmlHelper.php
new file mode 100644
index 00000000..710798cd
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/SimpleXml/XmlHelper.php
@@ -0,0 +1,147 @@
+attributes() as $name => $value)
+ {
+ $attributes[$name] = (string) $value;
+ }
+
+ return $attributes;
+ }
+
+ /**
+ * If this attribute not exists, use this value as default, or we use original value from xml.
+ *
+ * @param \SimpleXMLElement $xml A SimpleXMLElement object.
+ * @param string $attr The attribute name.
+ * @param string $value The value to set as default.
+ *
+ * @return void
+ */
+ public static function def(\SimpleXMLElement $xml, $attr, $value)
+ {
+ $value = (string) $value;
+ $attr = (string) $attr;
+
+ $xml[$attr] = isset($xml[$attr]) ? (string) $xml[$attr] : (string) $value;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/AbstractDomTestCase.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/AbstractDomTestCase.php
new file mode 100644
index 00000000..9000545b
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/AbstractDomTestCase.php
@@ -0,0 +1,97 @@
+assertEquals(
+ TestDomHelper::minify((string) $expected),
+ TestDomHelper::minify((string) $actual),
+ $message,
+ $delta,
+ $maxDepth,
+ $canonicalize,
+ $ignoreCase
+ );
+ }
+
+ /**
+ * Asserts that two variables are equal.
+ *
+ * @param mixed $expected
+ * @param mixed $actual
+ * @param string $message
+ * @param float $delta
+ * @param integer $maxDepth
+ * @param boolean $canonicalize
+ * @param boolean $ignoreCase
+ */
+ public function assertDomFormatEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10,
+ $canonicalize = FALSE, $ignoreCase = FALSE)
+ {
+ $this->assertEquals(
+ DomFormatter::format((string) $expected),
+ DomFormatter::format((string) $actual),
+ $message,
+ $delta,
+ $maxDepth,
+ $canonicalize,
+ $ignoreCase
+ );
+ }
+
+ /**
+ * Asserts that two variables are equal.
+ *
+ * @param mixed $expected
+ * @param mixed $actual
+ * @param string $message
+ * @param float $delta
+ * @param integer $maxDepth
+ * @param boolean $canonicalize
+ * @param boolean $ignoreCase
+ */
+ public function assertHtmlFormatEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10,
+ $canonicalize = FALSE, $ignoreCase = FALSE)
+ {
+ $this->assertEquals(
+ HtmlFormatter::format((string) $expected),
+ HtmlFormatter::format((string) $actual),
+ $message,
+ $delta,
+ $maxDepth,
+ $canonicalize,
+ $ignoreCase
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/DomBuilderTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/DomBuilderTest.php
new file mode 100644
index 00000000..f7e2cbd6
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/DomBuilderTest.php
@@ -0,0 +1,134 @@
+',
+ 'field',
+ null,
+ array(),
+ false
+ ),
+ array(
+ 'case2',
+ 'Some Data ',
+ 'field',
+ 'Some Data',
+ array(),
+ false
+ ),
+ array(
+ 'case3',
+ ' ',
+ 'field',
+ null,
+ array('id' => 'foo', 'class' => 'bar'),
+ false
+ ),
+ array(
+ 'case4',
+ '
+ Yes
+ No
+ ',
+ 'field',
+ DomBuilder::create('option', 'Yes', array('value' => 1))
+ . DomBuilder::create('option', 'No', array('value' => 0)),
+ array('id' => 'foo', 'class' => 'bar'),
+ false
+ ),
+ array(
+ 'case5_force_paired',
+ ' ',
+ 'field',
+ null,
+ array(),
+ true
+ ),
+ );
+ }
+
+ /**
+ * Method to test create().
+ *
+ * @param string $name
+ * @param string $expect
+ * @param string $tag
+ * @param string $content
+ * @param array $attribs
+ * @param boolean $forcePaired
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\Builder\DomBuilder::create
+ *
+ * @dataProvider domTestCase
+ */
+ public function testCreate($name, $expect, $tag, $content, $attribs, $forcePaired)
+ {
+ $this->assertDomFormatEquals(
+ $expect,
+ DomBuilder::create($tag, $content, $attribs, $forcePaired),
+ 'Dom build case fail: ' . $name
+ );
+ }
+
+ /**
+ * Method to test quote().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\Builder\DomBuilder::quote
+ */
+ public function testQuote()
+ {
+ $this->assertEquals('"foo"', DomBuilder::quote('foo'));
+ }
+
+ /**
+ * testPrepareAttributes
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\Builder\DomBuilder::buildAttributes
+ */
+ public function testBuildAttributes()
+ {
+ $attrs = array(
+ 'foo' => 'bar',
+ 'data' => true,
+ 'bar' => false,
+ 'empty' => '',
+ 'selected' => true,
+ 'checked' => false
+ );
+
+ $this->assertEquals(' foo="bar" data empty="" selected', DomBuilder::buildAttributes($attrs));
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/DomElementTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/DomElementTest.php
new file mode 100644
index 00000000..a83b1cd2
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/DomElementTest.php
@@ -0,0 +1,325 @@
+',
+ 'field',
+ null,
+ array(),
+ false
+ ),
+ array(
+ 'case2',
+ 'Some Data ',
+ 'field',
+ 'Some Data',
+ array(),
+ false
+ ),
+ array(
+ 'case3',
+ ' ',
+ 'field',
+ null,
+ array('id' => 'foo', 'class' => 'bar'),
+ false
+ ),
+ array(
+ 'case4',
+ '
+ Yes
+ No
+ ',
+ 'field',
+ array(
+ new DomElement('option', 'Yes', array('value' => 1)),
+ new DomElement('option', 'No', array('value' => 0))
+ ),
+ array('id' => 'foo', 'class' => 'bar'),
+ false
+ ),
+ array(
+ 'case5_force_paired',
+ ' ',
+ 'field',
+ null,
+ array(),
+ true
+ ),
+ );
+ }
+
+ /**
+ * Method to test create().
+ *
+ * @param string $name
+ * @param string $expect
+ * @param string $tag
+ * @param string $content
+ * @param array $attribs
+ * @param boolean $forcePaired
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\Builder\DomBuilder::create
+ *
+ * @dataProvider domTestCase
+ */
+ public function testCreate($name, $expect, $tag, $content, $attribs, $forcePaired)
+ {
+ $element = new DomElement($tag, $content, $attribs);
+
+ $this->assertDomFormatEquals(
+ $expect,
+ $element->toString($forcePaired),
+ 'Dom build case fail: ' . $name
+ );
+ }
+
+ /**
+ * Method to test __toString().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElement::__toString
+ */
+ public function test__toString()
+ {
+ $this->assertDomFormatEquals(
+ 'data ',
+ new DomElement('field', 'data', array('id' => 'foo'))
+ );
+ }
+
+ /**
+ * Method to test getContent().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElement::getContent
+ */
+ public function testGetContent()
+ {
+ $element = new DomElement('field', 'data', array('id' => 'foo'));
+
+ $this->assertEquals('data', $element->getContent());
+ }
+
+ /**
+ * Method to test setContent().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElement::setContent
+ */
+ public function testSetContent()
+ {
+ $element = new DomElement('field', 'data', array('id' => 'foo'));
+
+ $element->setContent('bar');
+
+ $this->assertEquals(
+ DomHelper::minify('bar '),
+ DomHelper::minify($element)
+ );
+ }
+
+ /**
+ * Method to test getAttribute().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElement::getAttribute
+ */
+ public function testGetAttribute()
+ {
+ $element = new DomElement('field', 'data', array('id' => 'foo'));
+
+ $this->assertEquals('foo', $element->getAttribute('id'));
+ }
+
+ /**
+ * Method to test setAttribute().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElement::setAttribute
+ */
+ public function testSetAttribute()
+ {
+ $element = new DomElement('field', 'data', array('id' => 'foo'));
+
+ $element->setAttribute('id', 'bar');
+ $element->setAttribute('class', 'yoo');
+
+ $this->assertEquals(
+ DomHelper::minify('data '),
+ DomHelper::minify($element)
+ );
+ }
+
+ /**
+ * Method to test getAttributes().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElement::getAttributes
+ */
+ public function testGetAttributes()
+ {
+ $element = new DomElement('field', 'data', array('id' => 'foo'));
+
+ $this->assertEquals(array('id' => 'foo'), $element->getAttributes());
+ }
+
+ /**
+ * Method to test setAttributes().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElement::setAttributes
+ */
+ public function testSetAttributes()
+ {
+ $element = new DomElement('field', 'data', array('id' => 'foo'));
+
+ $element->setAttributes(array('a' => 'b'));
+
+ $this->assertEquals(array('a' => 'b'), $element->getAttributes());
+
+ $this->assertEquals(
+ DomHelper::minify('data '),
+ DomHelper::minify($element)
+ );
+ }
+
+ /**
+ * Method to test getName().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElement::getName
+ */
+ public function testGetName()
+ {
+ $element = new DomElement('field', 'data', array('id' => 'foo'));
+
+ $this->assertEquals('field', $element->getName());
+ }
+
+ /**
+ * Method to test setName().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElement::setName
+ */
+ public function testSetName()
+ {
+ $element = new DomElement('field', 'data', array('id' => 'foo'));
+
+ $element->setName('div');
+
+ $this->assertEquals('div', $element->getName());
+
+ $this->assertEquals(
+ DomHelper::minify('data
'),
+ DomHelper::minify($element)
+ );
+ }
+
+ /**
+ * Method to test offsetExists().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElement::offsetExists
+ */
+ public function testOffsetExists()
+ {
+ $element = new DomElement('field', 'data', array('id' => 'foo'));
+
+ $this->assertTrue(isset($element['id']));
+ $this->assertFalse(isset($element['class']));
+ }
+
+ /**
+ * Method to test offsetGet().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElement::offsetGet
+ */
+ public function testOffsetGet()
+ {
+ $element = new DomElement('field', 'data', array('id' => 'foo'));
+
+ $this->assertEquals('foo', $element['id']);
+ }
+
+ /**
+ * Method to test offsetSet().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElement::offsetSet
+ */
+ public function testOffsetSet()
+ {
+ $element = new DomElement('field', 'data', array('id' => 'foo'));
+
+ $element['id'] = 'bar';
+ $element['class'] = 'yoo';
+
+ $this->assertEquals(
+ DomHelper::minify('data '),
+ DomHelper::minify($element)
+ );
+ }
+
+ /**
+ * Method to test offsetUnset().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElement::offsetUnset
+ */
+ public function testOffsetUnset()
+ {
+ $element = new DomElement('field', 'data', array('id' => 'foo'));
+
+ unset($element['id']);
+
+ $this->assertEquals(
+ DomHelper::minify('data '),
+ DomHelper::minify($element)
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/DomElementsTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/DomElementsTest.php
new file mode 100644
index 00000000..98d56ea8
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/DomElementsTest.php
@@ -0,0 +1,164 @@
+instance = new DomElements($elements);
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ $this->instance = null;
+ }
+
+ /**
+ * Method to test __toString().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElements::__toString
+ */
+ public function test__toString()
+ {
+ $expect = <<foo
+bar
+
+
+ Simon
+
+
+DOM;
+
+ $this->assertEquals(
+ DomHelper::minify($expect),
+ DomHelper::minify($this->instance)
+ );
+ }
+
+ /**
+ * Method to test getIterator().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElements::getIterator
+ */
+ public function testGetIterator()
+ {
+ $iterator = $this->instance->getIterator();
+
+ $this->assertInstanceOf('ArrayIterator', $iterator);
+
+ $this->assertEquals(
+ DomHelper::minify('foo '),
+ DomHelper::minify($iterator[0])
+ );
+ }
+
+ /**
+ * Method to test offsetExists().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElements::offsetExists
+ */
+ public function testOffsetExists()
+ {
+ $this->assertTrue(isset($this->instance[1]));
+ }
+
+ /**
+ * Method to test offsetGet().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElements::offsetGet
+ */
+ public function testOffsetGet()
+ {
+ $this->assertEquals('rdf:metaData', $this->instance[2]->getName());
+ }
+
+ /**
+ * Method to test offsetSet().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElements::offsetSet
+ */
+ public function testOffsetSet()
+ {
+ $this->instance[0]->setName('foo:bar');
+
+ $this->assertEquals('foo:bar', $this->instance[0]->getName());
+ }
+
+ /**
+ * Method to test offsetUnset().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElements::offsetUnset
+ */
+ public function testOffsetUnset()
+ {
+ unset($this->instance[2]);
+
+ $this->assertNull($this->instance[2]);
+ }
+
+ /**
+ * Method to test count().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElements::count
+ */
+ public function testCount()
+ {
+ $this->assertEquals(3, count($this->instance));
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/HtmlBuilderTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/HtmlBuilderTest.php
new file mode 100644
index 00000000..25259ebb
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/HtmlBuilderTest.php
@@ -0,0 +1,145 @@
+',
+ 'a',
+ null,
+ array(),
+ false
+ ),
+ array(
+ 'case2_div',
+ 'Some Data
',
+ 'div',
+ 'Some Data',
+ array(),
+ false
+ ),
+ array(
+ 'case3_div_no_content',
+ '
',
+ 'div',
+ null,
+ array('id' => 'foo', 'class' => 'bar'),
+ false
+ ),
+ array(
+ 'case4_ul',
+ '',
+ 'ul',
+ HtmlBuilder::create('option', 'Yes', array('value' => 1))
+ . HtmlBuilder::create('option', 'No', array('value' => 0)),
+ array('id' => 'foo', 'class' => 'bar'),
+ false
+ ),
+ array(
+ 'case5_force_paired',
+ ' ',
+ 'a',
+ null,
+ array(),
+ true
+ ),
+ array(
+ 'case6_ul',
+ ' ',
+ 'hr',
+ null,
+ array(),
+ false
+ ),
+ array(
+ 'case7_empty_content',
+ ' ',
+ 'hr',
+ '',
+ array(),
+ false
+ ),
+ array(
+ 'case8_attr_only_tag',
+ ' ',
+ 'video',
+ '',
+ array('controls' => true, 'muted' => true),
+ false
+ )
+ );
+ }
+
+ /**
+ * Method to test create().
+ *
+ * @param string $name
+ * @param string $expect
+ * @param string $tag
+ * @param string $content
+ * @param array $attribs
+ * @param boolean $forcePaired
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\Builder\HtmlBuilder::create
+ *
+ * @dataProvider domTestCase
+ */
+ public function testCreate($name, $expect, $tag, $content, $attribs, $forcePaired)
+ {
+ $this->assertEquals(
+ DomHelper::minify($expect),
+ DomHelper::minify(HtmlBuilder::create($tag, $content, $attribs, $forcePaired)),
+ 'Dom build case fail: ' . $name
+ );
+ }
+
+ /**
+ * testPrepareAttributes
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\Builder\HtmlBuilder::buildAttributes
+ */
+ public function testBuildAttributes()
+ {
+ $attrs = array(
+ 'foo' => 'bar',
+ 'data' => true,
+ 'bar' => false,
+ 'empty' => '',
+ 'selected' => true,
+ 'checked' => false
+ );
+
+ $this->assertEquals(' foo="bar" data empty="" selected="selected"', HtmlBuilder::buildAttributes($attrs));
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/HtmlElementTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/HtmlElementTest.php
new file mode 100644
index 00000000..894b90eb
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/HtmlElementTest.php
@@ -0,0 +1,118 @@
+',
+ 'a',
+ null,
+ array(),
+ false
+ ),
+ array(
+ 'case2_div',
+ 'Some Data
',
+ 'div',
+ 'Some Data',
+ array(),
+ false
+ ),
+ array(
+ 'case3_div_no_content',
+ '
',
+ 'div',
+ null,
+ array('id' => 'foo', 'class' => 'bar'),
+ false
+ ),
+ array(
+ 'case4_ul',
+ '',
+ 'ul',
+ new HtmlElement('option', 'Yes', array('value' => 1))
+ . new HtmlElement('option', 'No', array('value' => 0)),
+ array('id' => 'foo', 'class' => 'bar'),
+ false
+ ),
+ array(
+ 'case5_force_paired',
+ ' ',
+ 'a',
+ null,
+ array(),
+ true
+ ),
+ array(
+ 'case6_ul',
+ ' ',
+ 'hr',
+ null,
+ array(),
+ false
+ ),
+ array(
+ 'case7_empty_content',
+ ' ',
+ 'hr',
+ '',
+ array(),
+ false
+ )
+ );
+ }
+
+ /**
+ * Method to test create().
+ *
+ * @param string $name
+ * @param string $expect
+ * @param string $tag
+ * @param string $content
+ * @param array $attribs
+ * @param boolean $forcePaired
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\Builder\HtmlBuilder::create
+ *
+ * @dataProvider domTestCase
+ */
+ public function testCreate($name, $expect, $tag, $content, $attribs, $forcePaired)
+ {
+ $element = new HtmlElement($tag, $content, $attribs, $forcePaired);
+
+ $this->assertEquals(
+ DomHelper::minify($expect),
+ DomHelper::minify($element->toString($forcePaired)),
+ 'Dom build case fail: ' . $name
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/HtmlElementsTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/HtmlElementsTest.php
new file mode 100644
index 00000000..c936423a
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/HtmlElementsTest.php
@@ -0,0 +1,80 @@
+ 'fly')),
+ );
+
+ $this->instance = new HtmlElements($elements);
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test __toString().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\DomElements::__toString
+ */
+ public function test__toString()
+ {
+ $expect = <<foo
+
+yoo
+DOM;
+
+ $this->assertEquals(
+ DomHelper::minify($expect),
+ DomHelper::minify($this->instance)
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/XmlHelperTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/XmlHelperTest.php
new file mode 100644
index 00000000..5e9e9705
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/Test/XmlHelperTest.php
@@ -0,0 +1,257 @@
+
+
+
+ Yes
+ No
+
+
+XML;
+
+ $xml = simplexml_load_string($xml);
+
+ $this->xml = $xml->field;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test getAttribute().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\SimpleXml\XmlHelper::getAttribute
+ */
+ public function testGetAttribute()
+ {
+ $this->assertEquals('sun', XmlHelper::getAttribute($this->xml, 'class'));
+ $this->assertEquals('default', XmlHelper::getAttribute($this->xml, 'cloud', 'default'));
+ $this->assertEquals(null, XmlHelper::getAttribute($this->xml, 'cloud'));
+ }
+
+ /**
+ * Method to test get().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\SimpleXml\XmlHelper::get
+ */
+ public function testGet()
+ {
+ $this->assertEquals('sun', XmlHelper::get($this->xml, 'class'));
+ $this->assertEquals('default', XmlHelper::get($this->xml, 'cloud', 'default'));
+ $this->assertEquals(null, XmlHelper::get($this->xml, 'cloud'));
+ }
+
+ /**
+ * boolCases
+ *
+ * @return array
+ */
+ public function boolCases()
+ {
+ return array(
+ array(
+ 1,
+ 'required',
+ true,
+ null
+ ),
+ array(
+ 2,
+ 'disabled',
+ false,
+ null
+ ),
+ array(
+ 3,
+ 'boolTrue1',
+ true,
+ null
+ ),
+ array(
+ 4,
+ 'boolTrue2',
+ true,
+ null
+ ),
+ array(
+ 5,
+ 'boolTrue3',
+ true,
+ null
+ ),
+ array(
+ 6,
+ 'boolFalse1',
+ false,
+ null
+ ),
+ array(
+ 7,
+ 'boolFalse2',
+ false,
+ null
+ ),
+ array(
+ 8,
+ 'boolFalse3',
+ false,
+ null
+ ),
+ array(
+ 10,
+ 'boolFalse4',
+ false,
+ null
+ ),
+ array(
+ 11,
+ 'boolFalse5',
+ false,
+ null
+ ),
+ array(
+ '12_default',
+ 'flower',
+ false,
+ false
+ )
+ );
+ }
+
+ /**
+ * Method to test getBool().
+ *
+ * @param string|int $id
+ * @param string $name
+ * @param boolean $expect
+ * @param boolean $default
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\SimpleXml\XmlHelper::getBool
+ *
+ * @dataProvider boolCases
+ */
+ public function testGetBool($id, $name, $expect, $default)
+ {
+ $this->assertEquals($expect, XmlHelper::getBool($this->xml, $name, $default), 'Case fail: case_' . $id);
+ }
+
+ /**
+ * Method to test getFalse().
+ *
+ * @param string|int $id
+ * @param string $name
+ * @param boolean $expect
+ * @param boolean $default
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\SimpleXml\XmlHelper::getFalse
+ *
+ * @dataProvider boolCases
+ */
+ public function testGetFalse($id, $name, $expect, $default)
+ {
+ $this->assertEquals(!$expect, XmlHelper::getFalse($this->xml, $name, $default), 'Case fail: case_' . $id);
+ }
+
+ /**
+ * Method to test getAttributes().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\SimpleXml\XmlHelper::getAttributes
+ */
+ public function testGetAttributes()
+ {
+ $attributes = array();
+
+ foreach ($this->xml->attributes() as $name => $value)
+ {
+ $attributes[$name] = (string) $value;
+ }
+
+ $this->assertEquals($attributes, XmlHelper::getAttributes($this->xml));
+ }
+
+ /**
+ * Method to test def().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Dom\SimpleXml\XmlHelper::def
+ */
+ public function testDef()
+ {
+ XmlHelper::def($this->xml, 'flower', 'rose');
+ XmlHelper::def($this->xml, 'name', 'Play');
+
+ $this->assertEquals('rose', XmlHelper::get($this->xml, 'flower'));
+ $this->assertEquals('List', XmlHelper::get($this->xml, 'name'));
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/composer.json b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/composer.json
new file mode 100644
index 00000000..6124df2c
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/composer.json
@@ -0,0 +1,25 @@
+{
+ "name": "windwalker/dom",
+ "type": "windwalker-package",
+ "description": "Windwalker Dom package",
+ "keywords": ["windwalker", "framework", "filesystem"],
+ "homepage": "https://github.com/ventoviro/windwalker-dom",
+ "license": "LGPL-2.0+",
+ "require": {
+ "php": ">=5.3.10"
+ },
+ "require-dev": {
+ "windwalker/test": "~2.0"
+ },
+ "minimum-stability": "beta",
+ "autoload": {
+ "psr-4": {
+ "Windwalker\\Dom\\": ""
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/phpunit.travis.xml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/phpunit.travis.xml
new file mode 100644
index 00000000..690ec926
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/dom/phpunit.travis.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/.gitignore b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/.gitignore
new file mode 100644
index 00000000..84718b5d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/.gitignore
@@ -0,0 +1,11 @@
+# Development system files #
+.*
+!/.gitignore
+!/.travis.yml
+
+# Composer #
+vendor/*
+composer.lock
+
+# Test #
+phpunit.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/.travis.yml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/.travis.yml
new file mode 100644
index 00000000..5420e5c4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/.travis.yml
@@ -0,0 +1,16 @@
+language: php
+
+sudo: false
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+
+before_script:
+ - composer update --dev
+
+script:
+ - phpunit --configuration phpunit.travis.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Environment.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Environment.php
new file mode 100644
index 00000000..4c52eaf1
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Environment.php
@@ -0,0 +1,58 @@
+server = $server ? : new Server;
+ }
+
+ /**
+ * Method to get property Server
+ *
+ * @return \Windwalker\Environment\ServerInterface
+ */
+ public function getServer()
+ {
+ return $this->server;
+ }
+
+ /**
+ * Method to set property server
+ *
+ * @param \Windwalker\Environment\ServerInterface $server
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setServer($server)
+ {
+ $this->server = $server;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/PhpHelper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/PhpHelper.php
new file mode 100644
index 00000000..18a31c9c
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/PhpHelper.php
@@ -0,0 +1,163 @@
+getServer();
+```
+
+## The Server Object
+
+### Detect Running Environment
+
+``` php
+$server->isWeb();
+$server->isCli();
+```
+
+Same as:
+
+``` php
+use Windwalker\Environment\PhpHelper;
+
+PhpHelper:isWeb();
+PhpHelper::isCli();
+```
+
+### Detect System OS
+
+Get server OS information. The `getOS()` return first 3 letters from `getUname()`. The Uname is same as `PHP_OS`.
+List of `PHP_OS` please see: https://gist.github.com/asika32764/90e49a82c124858c9e1a
+
+``` php
+$sever->getOS(); // WIN, UNI, LIN, DAR ... etc.
+$sever->getUname(); // PHP_OS
+
+$sever->isWin();
+$sever->isLinux();
+$sever->isUnix();
+```
+
+### Get System Path
+
+``` php
+$server->getWorkingDirectory();
+
+$server->getRoot();
+
+$server->getEntry();
+
+$server->getServerPublicRoot();
+
+$server->getRequestUri();
+```
+
+#### getWorkingDirectory()
+
+If in Web environment, this method return running script directory.
+
+If in CLI environment, this method return current terminal working dir(same as `pwd` command).
+
+#### getRoot(`[$full = true]`)
+
+Get running script root directory.
+
+Set first argument to `false`, will return relative path from DocumentRoot in Web,
+or return relative path from working dir in CLI.
+
+#### getEntry(`[$full = true]`)
+
+Get running script file name.
+
+Set first argument to `false`, will return relative path from DocumentRoot in Web,
+or return relative path from working dir in CLI.
+
+#### getServerPublicRoot()
+
+Return the Http server DocumentRoot, same as `$_SERVER['DOCUMENT_ROOT']`.
+
+#### getRequestUri(`[$withParams = true]`)
+
+Call this method will return the URI path as `$_SERVER['REQUEST_URI']` with Http queries.
+
+```
+/path/foo/?bar=baz
+```
+
+Set first argument to `false` will return request path without params, same as `$_SERVER['PHP_SELF']`.
+
+```
+/path/foo/
+```
+
+### Get Request Information
+
+``` php
+$server->getHost();
+$server->getScheme();
+$server->getPort();
+```
+
+## The PhpHelper
+
+PhpHelper provides some useful methods to know about our PHP status.
+
+### Check PHP Running Environment
+
+``` php
+PhpHelper::isWeb();
+PhpHelper::isCli();
+PhpHelper::isHHVM();
+PhpHelper::isPHP();
+PhpHelper::isEmbed();
+```
+
+### Get PHP Version
+
+If is PHP, return `PHP_VERSION`. If is HHVM, return `HHVM_VERSION`.
+
+``` php
+PhpHelper::getVersion()
+```
+
+### Set Debug Mode
+
+`setStrict()` will set `error_reporting()` to 32767.
+
+`setMuted()` will set `error_reporting()` to 0.
+
+``` php
+PhpHelper::setStrict();
+PhpHelper::setMuted();
+```
+
+### Check Extensions
+
+``` php
+PhpHelper::hasXdebug();
+PhpHelper::hasPcntl();
+PhpHelper::hasCurl();
+PhpHelper::hasMcrypt();
+```
+
+## WebEnvironment
+
+WebEnvironment maintains two objects, the Server and the WebClient.
+
+``` php
+use Windwalker\Environment\Web\WebEnvironment;
+
+$env = new WebEnvironment;
+
+$server = $env->getServer();
+$client = $env->getClient();
+```
+
+## WebClient
+
+WebClient is a client detector help us know information about user's browser.
+
+### Detect Browser
+
+``` php
+$browser = $client->getBrowser();
+
+// Check is IE
+$browser == WebClient::IE;
+```
+
+Available Browser Detection
+
+- IE
+- FIREFOX
+- CHROME
+- SAFARI
+- OPERA
+- ANDROID_TABLET
+
+### Detect Browser Version
+
+``` php
+$version = $client->getBrowserVersion();
+
+// Check version
+$version >= 11;
+```
+
+### Detect Browser Engine
+
+``` php
+$engine = $client->getEngine();
+
+// Check engine
+$engine == Client::WEBKIT
+```
+
+Available Engines
+
+- TRIDENT
+- WEBKIT
+- GECKO
+- PRESTO
+- KHTML
+- AMAYA
+
+### Detect User's OS or Device
+
+``` php
+$platform = $client->getPlatform();
+
+// Check platform
+$platform == Client::ANDROID
+```
+
+Available Platforms
+
+- WINDOWS
+- WINDOWS_PHONE
+- WINDOWS_CE
+- IPHONE
+- IPAD
+- IPOD
+- MAC
+- BLACKBERRY
+- ANDROID
+- LINUX
+
+### Other Detection
+
+``` php
+$client->isRobot();
+$client->isMobile();
+$client->getLanguages();
+$client->getEncodings();
+$client->isSSLConnection();
+$client->getUserAgent();
+```
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Server.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Server.php
new file mode 100644
index 00000000..0ff9c661
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Server.php
@@ -0,0 +1,285 @@
+os)
+ {
+ // Detect the native operating system type.
+ $this->os = strtoupper(substr($this->uname, 0, 3));
+ }
+
+ return $this->os;
+ }
+
+ /**
+ * isWin
+ *
+ * @return bool
+ */
+ public function isWin()
+ {
+ return $this->getOS() == 'WIN';
+ }
+
+ /**
+ * isUnix
+ *
+ * @see https://gist.github.com/asika32764/90e49a82c124858c9e1a
+ *
+ * @return bool
+ */
+ public function isUnix()
+ {
+ $unames = array(
+ 'CYG',
+ 'DAR',
+ 'FRE',
+ 'HP-',
+ 'IRI',
+ 'LIN',
+ 'NET',
+ 'OPE',
+ 'SUN',
+ 'UNI'
+ );
+
+ return in_array($this->getOS(), $unames);
+ }
+
+ /**
+ * isLinux
+ *
+ * @return bool
+ */
+ public function isLinux()
+ {
+ return $this->getOS() == 'LIN';
+ }
+
+ /**
+ * Method to set property os
+ *
+ * @param string $os
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setOS($os)
+ {
+ $this->os = $os;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property Uname
+ *
+ * @return string
+ */
+ public function getUname()
+ {
+ return $this->uname;
+ }
+
+ /**
+ * Method to set property uname
+ *
+ * @param string $uname
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setUname($uname)
+ {
+ $this->uname = $uname;
+
+ return $this;
+ }
+
+ /**
+ * getWorkingDirectory
+ *
+ * @return string
+ */
+ public function getWorkingDirectory()
+ {
+ return getcwd();
+ }
+
+ /**
+ * getRoot
+ *
+ * @param bool $full
+ *
+ * @return string
+ */
+ public function getRoot($full = true)
+ {
+ return dirname($this->getEntry($full));
+ }
+
+ /**
+ * getDocumentRoot
+ *
+ * @return string
+ */
+ public function getServerPublicRoot()
+ {
+ return $this->getGlobals('_SERVER', 'DOCUMENT_ROOT');
+ }
+
+ /**
+ * getEntry
+ *
+ * @param bool $full
+ *
+ * @return string
+ */
+ public function getEntry($full = true)
+ {
+ $key = $full ? 'SCRIPT_FILENAME' : 'SCRIPT_NAME';
+
+ $wdir = $this->getWorkingDirectory();
+
+ $file = $this->getGlobals('_SERVER', $key);
+
+ if (strpos($file, $wdir) === 0)
+ {
+ $file = substr($file, strlen($wdir));
+ }
+
+ $file = trim($file, '.' . DIRECTORY_SEPARATOR);
+
+ if ($full && $this->isCli())
+ {
+ $file = $wdir . DIRECTORY_SEPARATOR . $file;
+ }
+
+ return $file;
+ }
+
+ /**
+ * getRequestUri
+ *
+ * @param bool $withParams
+ *
+ * @return string
+ */
+ public function getRequestUri($withParams = true)
+ {
+ if ($withParams)
+ {
+ return $this->getGlobals('_SERVER', 'REQUEST_URI');
+ }
+
+ return $this->getGlobals('_SERVER', 'PHP_SELF');
+ }
+
+ /**
+ * getHost
+ *
+ * @return string
+ */
+ public function getHost()
+ {
+ return $this->getGlobals('_SERVER', 'HTTP_HOST');
+ }
+
+ /**
+ * getPort
+ *
+ * @return string
+ */
+ public function getPort()
+ {
+ return $this->getGlobals('_SERVER', 'SERVER_PORT');
+ }
+
+ /**
+ * getScheme
+ *
+ * @return string
+ */
+ public function getScheme()
+ {
+ return $this->getGlobals('_SERVER', 'REQUEST_SCHEME');
+ }
+
+ /**
+ * getGlobals
+ *
+ * @param string $type
+ * @param string $key
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ protected function getGlobals($type, $key, $default = null)
+ {
+ if (!isset($GLOBALS['_SERVER']))
+ {
+ $GLOBALS['_SERVER'] = $_SERVER;
+ }
+
+ if (isset($GLOBALS[$type][$key]))
+ {
+ return $GLOBALS[$type][$key];
+ }
+
+ return $default;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/ServerHelper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/ServerHelper.php
new file mode 100644
index 00000000..bc2af1df
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/ServerHelper.php
@@ -0,0 +1,81 @@
+isWin();
+ }
+
+ /**
+ * isLinux
+ *
+ * @return boolean
+ */
+ public static function isLinux()
+ {
+ return static::getServer()->isLinux();
+ }
+
+ /**
+ * isUnix
+ *
+ * @return boolean
+ */
+ public static function isUnix()
+ {
+ return static::getServer()->isUnix();
+ }
+
+ /**
+ * getServer
+ *
+ * @return Server
+ */
+ public static function getServer()
+ {
+ if (!static::$server)
+ {
+ static::$server = new Server;
+ }
+
+ return static::$server;
+ }
+
+ /**
+ * Method to set property server
+ *
+ * @param Server $server
+ *
+ * @return void
+ */
+ public static function setServer($server)
+ {
+ static::$server = $server;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/ServerInterface.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/ServerInterface.php
new file mode 100644
index 00000000..ef1e76d6
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/ServerInterface.php
@@ -0,0 +1,40 @@
+instance = new Server;
+
+ // Detect the native operating system type.
+ $this->os = strtoupper(substr(PHP_OS, 0, 3));
+
+ $this->isWin = $this->os == 'WIN';
+
+ $this->isMac = $this->os == 'MAC';
+
+ $this->isUnix = in_array($this->os, array('CYG', 'DAR', 'FRE', 'LIN', 'NET', 'OPE', 'MAC'));
+
+ $this->isLinux = $this->os == 'LIN';
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * getOSTestData
+ *
+ * @return array
+ */
+ public function getIsWinTestData()
+ {
+ return array(
+ array('CYGWIN_NT-5.1', false),
+ array('Darwin', false),
+ array('FreeBSD', false),
+ array('HP-UX', false),
+ array('IRIX64', false),
+ array('Linux', false),
+ array('NetBSD', false),
+ array('OpenBSD', false),
+ array('SunOS', false),
+ array('Unix', false),
+ array('WIN32', true),
+ array('WINNT', true),
+ array('Windows', true)
+ );
+ }
+
+ /**
+ * getOSTestData
+ *
+ * @return array
+ */
+ public function getIsUnixTestData()
+ {
+ return array(
+ array('CYGWIN_NT-5.1', true),
+ array('Darwin', true),
+ array('FreeBSD', true),
+ array('HP-UX', true),
+ array('IRIX64', true),
+ array('Linux', true),
+ array('NetBSD', true),
+ array('OpenBSD', true),
+ array('SunOS', true),
+ array('Unix', true),
+ array('WIN32', false),
+ array('WINNT', false),
+ array('Windows', false)
+ );
+ }
+
+ /**
+ * getOSTestData
+ *
+ * @return array
+ */
+ public function getIsLinuxTestData()
+ {
+ return array(
+ array('CYGWIN_NT-5.1', false),
+ array('Darwin', false),
+ array('FreeBSD', false),
+ array('HP-UX', false),
+ array('IRIX64', false),
+ array('Linux', true),
+ array('NetBSD', false),
+ array('OpenBSD', false),
+ array('SunOS', false),
+ array('Unix', false),
+ array('WIN32', false),
+ array('WINNT', false),
+ array('Windows', false)
+ );
+ }
+
+ /**
+ * Method to test getOS().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Application\Environment\Server::getOS
+ */
+ public function testGetOS()
+ {
+ $this->instance->setUname('Darwin');
+
+ $this->assertEquals('DAR', $this->instance->getOS());
+ }
+
+ /**
+ * Method to test isWin().
+ *
+ * @param string $os
+ * @param boolean $value
+ *
+ * @return void
+ *
+ * @dataProvider getIsWinTestData
+ *
+ * @covers Windwalker\Application\Environment\Server::isWin
+ */
+ public function testIsWin($os, $value)
+ {
+ $this->instance->setOS(null);
+ $this->instance->setUname($os);
+
+ $this->assertEquals($value, $this->instance->isWin());
+ }
+
+ /**
+ * Method to test isUnix().
+ *
+ * @param string $os
+ * @param boolean $value
+ *
+ * @return void
+ *
+ * @dataProvider getIsUnixTestData
+ *
+ * @covers Windwalker\Application\Environment\Server::isUnix
+ */
+ public function testIsUnix($os, $value)
+ {
+ $this->instance->setOS(null);
+ $this->instance->setUname($os);
+
+ $this->assertEquals($value, $this->instance->isUnix());
+ }
+
+ /**
+ * Method to test isLinux().
+ *
+ * @param string $os
+ * @param boolean $value
+ *
+ * @return void
+ *
+ * @dataProvider getIsLinuxTestData
+ *
+ * @covers Windwalker\Application\Environment\Server::isLinux
+ */
+ public function testIsLinux($os, $value)
+ {
+ $this->instance->setOS(null);
+ $this->instance->setUname($os);
+
+ $this->assertEquals($value, $this->instance->isLinux());
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Test/Stub/StubClient.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Test/Stub/StubClient.php
new file mode 100644
index 00000000..77674c38
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Test/Stub/StubClient.php
@@ -0,0 +1,168 @@
+$name;
+ }
+ else
+ {
+ throw new \Exception('Undefined or private property: ' . __CLASS__ . '::' . $name);
+ }
+ }
+
+ /**
+ * loadClientInformation()
+ *
+ * @param string $userAgent The user-agent string to parse.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ public function loadClientInformation($userAgent = null)
+ {
+ return parent::loadClientInformation($userAgent);
+ }
+
+ /**
+ * fetchConfigurationData()
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ public function fetchConfigurationData()
+ {
+ return parent::fetchConfigurationData();
+ }
+
+ /**
+ * loadSystemURIs()
+ *
+ * @param string $ua The user-agent string to parse.
+ *
+ * @return string
+ *
+ * @since 2.0
+ */
+ public function testHelperClient($ua)
+ {
+ $_SERVER['HTTP_USER_AGENT'] = $ua;
+
+ $this->detectClientInformation();
+
+ return $this->config->get('client');
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Test/WebClientTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Test/WebClientTest.php
new file mode 100644
index 00000000..388d91d0
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Test/WebClientTest.php
@@ -0,0 +1,357 @@
+inspector = new StubClient;
+ }
+
+ /**
+ * Tests the \Windwalker\Environment\Web\WebClient::__construct method.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ public function test__construct()
+ {
+ $this->markTestIncomplete();
+ }
+
+ /**
+ * Tests the \Windwalker\Environment\Web\WebClient::__get method.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ public function test__get()
+ {
+ $this->markTestIncomplete();
+ }
+
+ /**
+ * Tests the \Windwalker\Environment\Web\WebClient::detectBrowser method.
+ *
+ * @param string $platform The expected platform.
+ * @param boolean $mobile The expected mobile result.
+ * @param string $engine The expected engine.
+ * @param string $browser The expected browser.
+ * @param string $version The expected browser version.
+ * @param string $ua The input user agent.
+ *
+ * @return void
+ *
+ * @dataProvider getUserAgentData
+ * @since 2.0
+ */
+ public function testDetectBrowser($platform, $mobile, $engine, $browser, $version, $ua)
+ {
+ $this->inspector->detectBrowser($ua);
+
+ // Test the assertions.
+ $this->assertEquals($browser, $this->inspector->getBrowser(), 'Browser detection failed');
+ $this->assertEquals($version, $this->inspector->getBrowserVersion(), 'Version detection failed');
+ }
+
+ /**
+ * Tests the \Windwalker\Environment\Web\WebClient::detectEncoding method.
+ *
+ * @param string $ae The input accept encoding.
+ * @param array $e The expected array of encodings.
+ *
+ * @return void
+ *
+ * @dataProvider getEncodingData
+ * @since 2.0
+ */
+ public function testDetectEncoding($ae, $e)
+ {
+ $this->inspector->detectEncoding($ae);
+
+ // Test the assertions.
+ $this->assertEquals($this->inspector->getEncodings(), $e, 'Encoding detection failed');
+ }
+
+ /**
+ * Tests the \Windwalker\Environment\Web\WebClient::detectEngine method.
+ *
+ * @param string $p The expected platform.
+ * @param boolean $m The expected mobile result.
+ * @param string $e The expected engine.
+ * @param string $b The expected browser.
+ * @param string $v The expected browser version.
+ * @param string $ua The input user agent.
+ *
+ * @return void
+ *
+ * @dataProvider getUserAgentData
+ * @since 2.0
+ */
+ public function testDetectEngine($p, $m, $e, $b, $v, $ua)
+ {
+ $this->inspector->detectEngine($ua);
+
+ // Test the assertion.
+ $this->assertEquals($this->inspector->getEngine(), $e, 'Engine detection failed.');
+ }
+
+ /**
+ * Tests the \Windwalker\Environment\Web\WebClient::detectLanguage method.
+ *
+ * @param string $al The input accept language.
+ * @param array $l The expected array of languages.
+ *
+ * @return void
+ *
+ * @dataProvider getLanguageData
+ * @since 2.0
+ */
+ public function testDetectLanguage($al, $l)
+ {
+ $this->inspector->detectLanguage($al);
+
+ // Test the assertions.
+ $this->assertEquals($this->inspector->getLanguages(), $l, 'Language detection failed');
+ }
+
+ /**
+ * Tests the \Windwalker\Environment\Web\WebClient::detectPlatform method.
+ *
+ * @param string $p The expected platform.
+ * @param boolean $m The expected mobile result.
+ * @param string $e The expected engine.
+ * @param string $b The expected browser.
+ * @param string $v The expected browser version.
+ * @param string $ua The input user agent.
+ *
+ * @return void
+ *
+ * @dataProvider getUserAgentData
+ * @since 2.0
+ */
+ public function testDetectPlatform($p, $m, $e, $b, $v, $ua)
+ {
+ $this->inspector->detectPlatform($ua);
+
+ // Test the assertions.
+ $this->assertEquals($this->inspector->isMobile(), $m, 'Mobile detection failed.');
+ $this->assertEquals($this->inspector->getPlatform(), $p, 'Platform detection failed.');
+ }
+
+ /**
+ * Tests the \Windwalker\Environment\Web\WebClient::detectRobot method.
+ *
+ * @param string $userAgent The user agent
+ * @param boolean $expected The expected results of the function
+ *
+ * @return void
+ *
+ * @dataProvider detectRobotData
+ * @since 2.0
+ */
+ public function testDetectRobot($userAgent, $expected)
+ {
+ $this->inspector->detectRobot($userAgent);
+
+ // Test the assertions.
+ $this->assertEquals($this->inspector->isRobot(), $expected, 'Robot detection failed');
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Test/server.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Test/server.php
new file mode 100644
index 00000000..381b187d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Test/server.php
@@ -0,0 +1,26 @@
+getEntry();
+echo "\n";
+echo $server->getWorkingDirectory();
+
+echo "\n\n";
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Web/WebClient.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Web/WebClient.php
new file mode 100644
index 00000000..22d712db
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Web/WebClient.php
@@ -0,0 +1,635 @@
+userAgent = $_SERVER['HTTP_USER_AGENT'];
+ }
+ else
+ {
+ $this->userAgent = $userAgent;
+ }
+
+ // If no explicit acceptable encoding string was given attempt to use the implicit one from server environment.
+ if (empty($acceptEncoding) && isset($_SERVER['HTTP_ACCEPT_ENCODING']))
+ {
+ $this->acceptEncoding = $_SERVER['HTTP_ACCEPT_ENCODING'];
+ }
+ else
+ {
+ $this->acceptEncoding = $acceptEncoding;
+ }
+
+ // If no explicit acceptable languages string was given attempt to use the implicit one from server environment.
+ if (empty($acceptLanguage) && isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
+ {
+ $this->acceptLanguage = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
+ }
+ else
+ {
+ $this->acceptLanguage = $acceptLanguage;
+ }
+ }
+
+ /**
+ * Detects the client browser and version in a user agent string.
+ *
+ * @param string $userAgent The user-agent string to parse.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ protected function detectBrowser($userAgent)
+ {
+ $patternBrowser = '';
+
+ // Attempt to detect the browser type. Obviously we are only worried about major browsers.
+ if ((stripos($userAgent, 'MSIE') !== false) && (stripos($userAgent, 'Opera') === false))
+ {
+ $this->browser = self::IE;
+ $patternBrowser = 'MSIE';
+ }
+ elseif ((stripos($userAgent, 'Firefox') !== false) && (stripos($userAgent, 'like Firefox') === false))
+ {
+ $this->browser = self::FIREFOX;
+ $patternBrowser = 'Firefox';
+ }
+ elseif (stripos($userAgent, 'Chrome') !== false)
+ {
+ $this->browser = self::CHROME;
+ $patternBrowser = 'Chrome';
+ }
+ elseif (stripos($userAgent, 'Safari') !== false)
+ {
+ $this->browser = self::SAFARI;
+ $patternBrowser = 'Safari';
+ }
+ elseif (stripos($userAgent, 'Opera') !== false)
+ {
+ $this->browser = self::OPERA;
+ $patternBrowser = 'Opera';
+ }
+
+ // If we detected a known browser let's attempt to determine the version.
+ if ($this->browser)
+ {
+ // Build the REGEX pattern to match the browser version string within the user agent string.
+ $pattern = '#(?Version|' . $patternBrowser . ')[/ ]+(?[0-9.|a-zA-Z.]*)#';
+
+ // Attempt to find version strings in the user agent string.
+ $matches = array();
+
+ if (preg_match_all($pattern, $userAgent, $matches))
+ {
+ // Do we have both a Version and browser match?
+ if (count($matches['browser']) == 2)
+ {
+ // See whether Version or browser came first, and use the number accordingly.
+ if (strripos($userAgent, 'Version') < strripos($userAgent, $patternBrowser))
+ {
+ $this->browserVersion = $matches['version'][0];
+ }
+ else
+ {
+ $this->browserVersion = $matches['version'][1];
+ }
+ }
+ elseif (count($matches['browser']) > 2)
+ {
+ $key = array_search('Version', $matches['browser']);
+
+ if ($key)
+ {
+ $this->browserVersion = $matches['version'][$key];
+ }
+ }
+ else
+ // We only have a Version or a browser so use what we have.
+ {
+ $this->browserVersion = $matches['version'][0];
+ }
+ }
+ }
+
+ // Mark this detection routine as run.
+ $this->detection['browser'] = true;
+ }
+
+ /**
+ * Method to detect the accepted response encoding by the client.
+ *
+ * @param string $acceptEncoding The client accept encoding string to parse.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ protected function detectEncoding($acceptEncoding)
+ {
+ // Parse the accepted encodings.
+ $this->encodings = array_map('trim', (array) explode(',', $acceptEncoding));
+
+ // Mark this detection routine as run.
+ $this->detection['acceptEncoding'] = true;
+ }
+
+ /**
+ * Detects the client rendering engine in a user agent string.
+ *
+ * @param string $userAgent The user-agent string to parse.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ protected function detectEngine($userAgent)
+ {
+ if (stripos($userAgent, 'MSIE') !== false || stripos($userAgent, 'Trident') !== false)
+ {
+ // Attempt to detect the client engine -- starting with the most popular ... for now.
+ $this->engine = self::TRIDENT;
+ }
+ elseif (stripos($userAgent, 'AppleWebKit') !== false || stripos($userAgent, 'blackberry') !== false)
+ {
+ // Evidently blackberry uses WebKit and doesn't necessarily report it. Bad RIM.
+ $this->engine = self::WEBKIT;
+ }
+ elseif (stripos($userAgent, 'Gecko') !== false && stripos($userAgent, 'like Gecko') === false)
+ {
+ // We have to check for like Gecko because some other browsers spoof Gecko.
+ $this->engine = self::GECKO;
+ }
+ elseif (stripos($userAgent, 'Opera') !== false || stripos($userAgent, 'Presto') !== false)
+ {
+ // Sometimes Opera browsers don't say Presto.
+ $this->engine = self::PRESTO;
+ }
+ elseif (stripos($userAgent, 'KHTML') !== false)
+ {
+ // *sigh*
+ $this->engine = self::KHTML;
+ }
+ elseif (stripos($userAgent, 'Amaya') !== false)
+ {
+ // Lesser known engine but it finishes off the major list from Wikipedia :-)
+ $this->engine = self::AMAYA;
+ }
+
+ // Mark this detection routine as run.
+ $this->detection['engine'] = true;
+ }
+
+ /**
+ * Method to detect the accepted languages by the client.
+ *
+ * @param mixed $acceptLanguage The client accept language string to parse.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ protected function detectLanguage($acceptLanguage)
+ {
+ // Parse the accepted encodings.
+ $this->languages = array_map('trim', (array) explode(',', $acceptLanguage));
+
+ // Mark this detection routine as run.
+ $this->detection['acceptLanguage'] = true;
+ }
+
+ /**
+ * Detects the client platform in a user agent string.
+ *
+ * @param string $userAgent The user-agent string to parse.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ protected function detectPlatform($userAgent)
+ {
+ // Attempt to detect the client platform.
+ if (stripos($userAgent, 'Windows') !== false)
+ {
+ $this->platform = self::WINDOWS;
+
+ // Let's look at the specific mobile options in the Windows space.
+ if (stripos($userAgent, 'Windows Phone') !== false)
+ {
+ $this->mobile = true;
+ $this->platform = self::WINDOWS_PHONE;
+ }
+ elseif (stripos($userAgent, 'Windows CE') !== false)
+ {
+ $this->mobile = true;
+ $this->platform = self::WINDOWS_CE;
+ }
+ }
+ elseif (stripos($userAgent, 'iPhone') !== false)
+ {
+ // Interestingly 'iPhone' is present in all iOS devices so far including iPad and iPods.
+ $this->mobile = true;
+ $this->platform = self::IPHONE;
+
+ // Let's look at the specific mobile options in the iOS space.
+ if (stripos($userAgent, 'iPad') !== false)
+ {
+ $this->platform = self::IPAD;
+ }
+ elseif (stripos($userAgent, 'iPod') !== false)
+ {
+ $this->platform = self::IPOD;
+ }
+ }
+ elseif (stripos($userAgent, 'iPad') !== false)
+ {
+ // In case where iPhone is not mentioed in iPad user agent string
+ $this->mobile = true;
+ $this->platform = self::IPAD;
+ }
+ elseif (stripos($userAgent, 'iPod') !== false)
+ {
+ // In case where iPhone is not mentioed in iPod user agent string
+ $this->mobile = true;
+ $this->platform = self::IPOD;
+ }
+ elseif (preg_match('/macintosh|mac os x/i', $userAgent))
+ {
+ // This has to come after the iPhone check because mac strings are also present in iOS devices.
+ $this->platform = self::MAC;
+ }
+ elseif (stripos($userAgent, 'Blackberry') !== false)
+ {
+ $this->mobile = true;
+ $this->platform = self::BLACKBERRY;
+ }
+ elseif (stripos($userAgent, 'Android') !== false)
+ {
+ $this->mobile = true;
+ $this->platform = self::ANDROID;
+ /*
+ * Attempt to distinguish between Android phones and tablets
+ * There is no totally foolproof method but certain rules almost always hold
+ * Android 3.x is only used for tablets
+ * Some devices and browsers encourage users to change their UA string to include Tablet.
+ * Google encourages manufacturers to exclude the string Mobile from tablet device UA strings.
+ * In some modes Kindle Android devices include the string Mobile but they include the string Silk.
+ */
+ if (stripos($userAgent, 'Android 3') !== false || stripos($userAgent, 'Tablet') !== false
+ || stripos($userAgent, 'Mobile') === false || stripos($userAgent, 'Silk') !== false )
+ {
+ $this->platform = self::ANDROID_TABLET;
+ }
+ }
+ elseif (stripos($userAgent, 'Linux') !== false)
+ {
+ $this->platform = self::LINUX;
+ }
+
+ // Mark this detection routine as run.
+ $this->detection['platform'] = true;
+ }
+
+ /**
+ * Determines if the browser is a robot or not.
+ *
+ * @param string $userAgent The user-agent string to parse.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ protected function detectRobot($userAgent)
+ {
+ if (preg_match('/http|bot|robot|spider|crawler|curl|^$/i', $userAgent))
+ {
+ $this->robot = true;
+ }
+ else
+ {
+ $this->robot = false;
+ }
+
+ $this->detection['robot'] = true;
+ }
+
+ /**
+ * getPlatform
+ *
+ * @param bool $refresh
+ *
+ * @return int
+ */
+ public function getPlatform($refresh = false)
+ {
+ if (empty($this->detection['platform']) || $refresh)
+ {
+ $this->detectPlatform($this->userAgent);
+ }
+
+ return $this->platform;
+ }
+
+ /**
+ * getMobile
+ *
+ * @param bool $refresh
+ *
+ * @return boolean
+ */
+ public function isMobile($refresh = false)
+ {
+ if (empty($this->detection['platform']) || $refresh)
+ {
+ $this->detectPlatform($this->userAgent);
+ }
+
+ return $this->mobile;
+ }
+
+ /**
+ * getEngine
+ *
+ * @param bool $refresh
+ *
+ * @return int
+ */
+ public function getEngine($refresh = false)
+ {
+ if (empty($this->detection['engine']) || $refresh)
+ {
+ $this->detectEngine($this->userAgent);
+ }
+
+ return $this->engine;
+ }
+
+ /**
+ * getBrowser
+ *
+ * @param bool $refresh
+ *
+ * @return int
+ */
+ public function getBrowser($refresh = false)
+ {
+ if (empty($this->detection['browser']) || $refresh)
+ {
+ $this->detectBrowser($this->userAgent);
+ }
+
+ return $this->browser;
+ }
+
+ /**
+ * getBrowserVersion
+ *
+ * @param bool $refresh
+ *
+ * @return string
+ */
+ public function getBrowserVersion($refresh = false)
+ {
+ if (empty($this->detection['browser']) || $refresh)
+ {
+ $this->detectBrowser($this->userAgent);
+ }
+
+ return $this->browserVersion;
+ }
+
+ /**
+ * getLanguages
+ *
+ * @param bool $refresh
+ *
+ * @return array
+ */
+ public function getLanguages($refresh = false)
+ {
+ if (empty($this->detection['acceptLanguage']) || $refresh)
+ {
+ $this->detectLanguage($this->acceptLanguage);
+ }
+
+ return $this->languages;
+ }
+
+ /**
+ * getEncodings
+ *
+ * @param bool $refresh
+ *
+ * @return array
+ */
+ public function getEncodings($refresh = false)
+ {
+ if (empty($this->detection['acceptEncoding']) || $refresh)
+ {
+ $this->detectEncoding($this->acceptEncoding);
+ }
+
+ return $this->encodings;
+ }
+
+ /**
+ * getUserAgent
+ *
+ * @return string
+ */
+ public function getUserAgent()
+ {
+ return $this->userAgent;
+ }
+
+ /**
+ * setUserAgent
+ *
+ * @param string $userAgent
+ *
+ * @return WebClient Return self to support chaining.
+ */
+ public function setUserAgent($userAgent)
+ {
+ $this->userAgent = $userAgent;
+
+ return $this;
+ }
+
+ /**
+ * getRobot
+ *
+ * @param bool $refresh
+ *
+ * @return boolean
+ */
+ public function isRobot($refresh = false)
+ {
+ if (empty($this->detection['robot']) || $refresh)
+ {
+ $this->detectRobot($this->userAgent);
+ }
+
+ return $this->robot;
+ }
+
+ /**
+ * Determine if we are using a secure (SSL) connection.
+ *
+ * @return boolean True if using SSL, false if not.
+ *
+ * @since 2.0
+ */
+ public function isSSLConnection()
+ {
+ return (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off');
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Web/WebEnvironment.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Web/WebEnvironment.php
new file mode 100644
index 00000000..e9895808
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/Web/WebEnvironment.php
@@ -0,0 +1,64 @@
+client = $client ? : new WebClient;
+
+ parent::__construct($server);
+ }
+
+ /**
+ * Method to get property Client
+ *
+ * @return WebClient
+ */
+ public function getClient()
+ {
+ return $this->client;
+ }
+
+ /**
+ * Method to set property client
+ *
+ * @param WebClient $client
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setClient($client)
+ {
+ $this->client = $client;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/composer.json b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/composer.json
new file mode 100644
index 00000000..deec2f1b
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/composer.json
@@ -0,0 +1,25 @@
+{
+ "name": "windwalker/environment",
+ "type": "windwalker-package",
+ "description": "Windwalker Environment package",
+ "keywords": ["windwalker", "framework", "environment"],
+ "homepage": "https://github.com/ventoviro/windwalker-environment",
+ "license": "LGPL-2.0+",
+ "require": {
+ "php": ">=5.3.10"
+ },
+ "require-dev": {
+ "windwalker/test": "~2.0"
+ },
+ "minimum-stability": "beta",
+ "autoload": {
+ "psr-4": {
+ "Windwalker\\Environment\\": ""
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/phpunit.travis.xml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/phpunit.travis.xml
new file mode 100644
index 00000000..690ec926
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/environment/phpunit.travis.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/.gitignore b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/.gitignore
new file mode 100644
index 00000000..84718b5d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/.gitignore
@@ -0,0 +1,11 @@
+# Development system files #
+.*
+!/.gitignore
+!/.travis.yml
+
+# Composer #
+vendor/*
+composer.lock
+
+# Test #
+phpunit.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/.travis.yml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/.travis.yml
new file mode 100644
index 00000000..5420e5c4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/.travis.yml
@@ -0,0 +1,16 @@
+language: php
+
+sudo: false
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+
+before_script:
+ - composer update --dev
+
+script:
+ - phpunit --configuration phpunit.travis.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Comparator/FileComparatorInterface.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Comparator/FileComparatorInterface.php
new file mode 100644
index 00000000..24a5f7d6
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Comparator/FileComparatorInterface.php
@@ -0,0 +1,16 @@
+isFile();
+ };
+
+ return static::findByCallback($path, $callback, $recursive, $toArray);
+ }
+
+ /**
+ * folders
+ *
+ * @param string $path
+ * @param bool $recursive
+ * @param boolean $toArray
+ *
+ * @return \CallbackFilterIterator
+ */
+ public static function folders($path, $recursive = false, $toArray = false)
+ {
+ /**
+ * Files callback
+ *
+ * @param \SplFileInfo $current Current item's value
+ * @param string $key Current item's key
+ * @param \RecursiveDirectoryIterator $iterator Iterator being filtered
+ *
+ * @return boolean TRUE to accept the current item, FALSE otherwise
+ */
+ $callback = function ($current, $key, $iterator) use ($path, $recursive)
+ {
+ if ($recursive)
+ {
+ // Ignore self
+ if ($iterator->getRealPath() == Path::clean($path))
+ {
+ return false;
+ }
+
+ // If set to recursive, every returned folder name will include a dot (.),
+ // so we can't using isDot() to detect folder.
+ return $iterator->isDir() && ($iterator->getBasename() != '..');
+ }
+ else
+ {
+ return $iterator->isDir() && !$iterator->isDot();
+ }
+ };
+
+ return static::findByCallback($path, $callback, $recursive, $toArray);
+ }
+
+ /**
+ * items
+ *
+ * @param string $path
+ * @param bool $recursive
+ * @param boolean $toArray
+ *
+ * @return \CallbackFilterIterator
+ */
+ public static function items($path, $recursive = false, $toArray = false)
+ {
+ /**
+ * Files callback
+ *
+ * @param \SplFileInfo $current Current item's value
+ * @param string $key Current item's key
+ * @param \RecursiveDirectoryIterator $iterator Iterator being filtered
+ *
+ * @return boolean TRUE to accept the current item, FALSE otherwise
+ */
+ $callback = function ($current, $key, $iterator) use ($path, $recursive)
+ {
+ if ($recursive)
+ {
+ // Ignore self
+ if ($iterator->getRealPath() == Path::clean($path))
+ {
+ return false;
+ }
+
+ // If set to recursive, every returned folder name will include a dot (.),
+ // so we can't using isDot() to detect folder.
+ return ($iterator->getBasename() != '..');
+ }
+ else
+ {
+ return !$iterator->isDot();
+ }
+ };
+
+ return static::findByCallback($path, $callback, $recursive, $toArray);
+ }
+
+ /**
+ * Find one file and return.
+ *
+ * @param string $path The directory path.
+ * @param mixed $condition Finding condition, that can be a string, a regex or a callback function.
+ * Callback example:
+ *
+ * function($current, $key, $iterator)
+ * {
+ * return @preg_match('^Foo', $current->getFilename()) && ! $iterator->isDot();
+ * }
+ *
+ * @param boolean $recursive True to resursive.
+ *
+ * @return \SplFileInfo Finded file info object.
+ *
+ * @since 2.0
+ */
+ public static function findOne($path, $condition, $recursive = false)
+ {
+ $iterator = new \LimitIterator(static::find($path, $condition, $recursive), 0, 1);
+
+ $iterator->rewind();
+
+ return $iterator->current();
+ }
+
+ /**
+ * Find all files which matches condition.
+ *
+ * @param string $path The directory path.
+ * @param mixed $condition Finding condition, that can be a string, a regex or a callback function.
+ * Callback example:
+ *
+ * function($current, $key, $iterator)
+ * {
+ * return @preg_match('^Foo', $current->getFilename()) && ! $iterator->isDot();
+ * }
+ *
+ * @param boolean $recursive True to resursive.
+ * @param boolean $toArray True to convert iterator to array.
+ *
+ * @return \CallbackFilterIterator Found files or paths iterator.
+ *
+ * @since 2.0
+ */
+ public static function find($path, $condition, $recursive = false, $toArray = false)
+ {
+ // If conditions is string or array, we make it to regex.
+ if (!($condition instanceof \Closure) && !($condition instanceof FileComparatorInterface))
+ {
+ if (is_array($condition))
+ {
+ $condition = '/(' . implode('|', $condition) . ')/';
+ }
+ else
+ {
+ $condition = '/' . (string) $condition . '/';
+ }
+
+ /**
+ * Files callback
+ *
+ * @param \SplFileInfo $current Current item's value
+ * @param string $key Current item's key
+ * @param \RecursiveDirectoryIterator $iterator Iterator being filtered
+ *
+ * @return boolean TRUE to accept the current item, FALSE otherwise
+ */
+ $condition = function ($current, $key, $iterator) use ($condition)
+ {
+ return @preg_match($condition, $iterator->getFilename()) && !$iterator->isDot();
+ };
+ }
+ // If condition is compare object, wrap it with callback.
+ elseif ($condition instanceof FileComparatorInterface)
+ {
+ /**
+ * Files callback
+ *
+ * @param \SplFileInfo $current Current item's value
+ * @param string $key Current item's key
+ * @param \RecursiveDirectoryIterator $iterator Iterator being filtered
+ *
+ * @return boolean TRUE to accept the current item, FALSE otherwise
+ */
+ $condition = function ($current, $key, $iterator) use ($condition)
+ {
+ return $condition->compare($current, $key, $iterator);
+ };
+ }
+
+ return static::findByCallback($path, $condition, $recursive, $toArray);
+ }
+
+ /**
+ * Using a closure function to filter file.
+ *
+ * Reference: http://www.php.net/manual/en/class.callbackfilteriterator.php
+ *
+ * @param string $path The directory path.
+ * @param \Closure $callback A callback function to filter file.
+ * @param boolean $recursive True to recursive.
+ * @param boolean $toArray True to convert iterator to array.
+ *
+ * @return \CallbackFilterIterator Filtered file or path iteator.
+ *
+ * @since 2.0
+ */
+ public static function findByCallback($path, \Closure $callback, $recursive = false, $toArray = false)
+ {
+ $itarator = new \CallbackFilterIterator(static::createIterator($path, $recursive), $callback);
+
+ if ($toArray)
+ {
+ return static::iteratorToArray($itarator);
+ }
+
+ return $itarator;
+ }
+
+ /**
+ * Create file iterator of current dir.
+ *
+ * @param string $path The directory path.
+ * @param boolean $recursive True to recursive.
+ * @param integer $options FilesystemIterator Flags provides which will affect the behavior of some methods.
+ *
+ * @throws \InvalidArgumentException
+ * @return \FilesystemIterator|\RecursiveIteratorIterator File & dir iterator.
+ */
+ public static function createIterator($path, $recursive = false, $options = null)
+ {
+ $path = Path::clean($path);
+
+ if ($recursive)
+ {
+ $options = $options ? : (\FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO);
+ }
+ else
+ {
+ $options = $options ? : (\FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS);
+ }
+
+ try
+ {
+ $iterator = new RecursiveDirectoryIterator($path, $options);
+ }
+ catch (\UnexpectedValueException $exception)
+ {
+ throw new \InvalidArgumentException(sprintf('Dir: %s not found.', (string) $path), null, $exception);
+ }
+
+ // If rescurive set to true, use RecursiveIteratorIterator
+ return $recursive ? new \RecursiveIteratorIterator($iterator) : $iterator;
+ }
+
+ /**
+ * iteratorToArray
+ *
+ * @param \Traversable $iterator
+ *
+ * @return array
+ */
+ public static function iteratorToArray(\Traversable $iterator)
+ {
+ $array = array();
+
+ foreach ($iterator as $key => $file)
+ {
+ $array[] = (string) $file;
+ }
+
+ return $array;
+ }
+}
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Folder.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Folder.php
new file mode 100644
index 00000000..44eed54d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Folder.php
@@ -0,0 +1,475 @@
+getBasename();
+ break;
+
+ case ($pathType === static::PATH_RELATIVE):
+ $pathLength = strlen($path);
+ $name = $file->getRealPath();
+ $name = trim(substr($name, $pathLength), DIRECTORY_SEPARATOR);
+ break;
+
+ case ($pathType === static::PATH_ABSOLUTE):
+ default:
+ $name = $file->getPathname();
+ break;
+ }
+
+ $files[] = $name;
+ }
+
+ return $files;
+ }
+
+ /**
+ * items
+ *
+ * @param string $path
+ * @param boolean $recursive
+ * @param integer $pathType
+ *
+ * @return array
+ */
+ public static function items($path, $recursive = false, $pathType = self::PATH_ABSOLUTE)
+ {
+ $files = array();
+ $pathLength = strlen($path);
+
+ /** @var $file \SplFileInfo */
+ foreach (Filesystem::items($path, $recursive) as $file)
+ {
+ switch ($pathType)
+ {
+ case ($pathType === self::PATH_BASENAME):
+ $name = $file->getBasename();
+ break;
+
+ case ($pathType === static::PATH_RELATIVE):
+ $pathLength = strlen($path);
+ $name = $file->getRealPath();
+ $name = trim(substr($name, $pathLength), DIRECTORY_SEPARATOR);
+ break;
+
+ case ($pathType === static::PATH_ABSOLUTE):
+ default:
+ $name = $file->getPathname();
+ break;
+ }
+
+ $files[] = $name;
+ }
+
+ return $files;
+ }
+
+ /**
+ * folders
+ *
+ * @param string $path
+ * @param boolean $recursive
+ * @param integer $pathType
+ *
+ * @return array
+ */
+ public static function folders($path, $recursive = false, $pathType = self::PATH_ABSOLUTE)
+ {
+ $files = array();
+
+ /** @var $file \SplFileInfo */
+ foreach (Filesystem::folders($path, $recursive) as $file)
+ {
+ switch ($pathType)
+ {
+ case ($pathType === self::PATH_BASENAME):
+ $name = $file->getBasename();
+ break;
+
+ case ($pathType === static::PATH_RELATIVE):
+ $pathLength = strlen($path);
+ $name = $file->getRealPath();
+ $name = trim(substr($name, $pathLength), DIRECTORY_SEPARATOR);
+ break;
+
+ case ($pathType === static::PATH_ABSOLUTE):
+ default:
+ $name = $file->getPathname();
+ break;
+ }
+
+ $files[] = $name;
+ }
+
+ return $files;
+ }
+
+ /**
+ * Lists folder in format suitable for tree display.
+ *
+ * @param string $path The path of the folder to read.
+ * @param integer $maxLevel The maximum number of levels to recursively read, defaults to three.
+ * @param integer $level The current level, optional.
+ * @param integer $parent Unique identifier of the parent folder, if any.
+ *
+ * @return array Folders in the given folder.
+ *
+ * @since 2.0
+ */
+ public static function listFolderTree($path, $maxLevel = 3, $level = 0, $parent = 0)
+ {
+ $dirs = array();
+
+ static $index;
+ static $base;
+
+ if ($level == 0)
+ {
+ $index = 0;
+ $base = Path::clean($path);
+ }
+
+ if ($level < $maxLevel)
+ {
+ $folders = static::folders($path, false, false);
+
+ sort($folders);
+
+ // First path, index foldernames
+ foreach ($folders as $name)
+ {
+ $id = ++$index;
+ $fullName = Path::clean($path . '/' . $name);
+
+ $dirs[] = array(
+ 'id' => $id,
+ 'parent' => $parent,
+ 'name' => $name,
+ 'fullname' => $fullName,
+ 'relative' => trim(str_replace($base, '', $fullName), DIRECTORY_SEPARATOR)
+ );
+
+ $dirs2 = self::listFolderTree($fullName, $maxLevel, $level + 1, $id);
+
+ $dirs = array_merge($dirs, $dirs2);
+ }
+ }
+
+ return $dirs;
+ }
+
+ /**
+ * Makes path name safe to use.
+ *
+ * @param string $path The full path to sanitise.
+ *
+ * @return string The sanitised string.
+ *
+ * @since 2.0
+ */
+ public static function makeSafe($path)
+ {
+ $regex = array('#[^A-Za-z0-9_\\\/\(\)\[\]\{\}\#\$\^\+\.\'~`!@&=;,-]#');
+
+ return preg_replace($regex, '', $path);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Iterator/ArrayObject.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Iterator/ArrayObject.php
new file mode 100644
index 00000000..54d70618
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Iterator/ArrayObject.php
@@ -0,0 +1,479 @@
+setFlags($flags);
+ $this->storage = $input;
+ $this->setIteratorClass($iteratorClass);
+ $this->protectedProperties = array_keys(get_object_vars($this));
+ }
+
+ /**
+ * Returns whether the requested key exists
+ *
+ * @param mixed $key
+ *
+ * @throws \InvalidArgumentException
+ * @return boolean
+ */
+ public function __isset($key)
+ {
+ if ($this->flag == self::ARRAY_AS_PROPS)
+ {
+ return $this->offsetExists($key);
+ }
+
+ if (in_array($key, $this->protectedProperties))
+ {
+ throw new \InvalidArgumentException('$key is a protected property, use a different key');
+ }
+
+ return isset($this->$key);
+ }
+
+ /**
+ * Sets the value at the specified key to value
+ *
+ * @param mixed $key
+ * @param mixed $value
+ *
+ * @throws \InvalidArgumentException
+ * @return void|mixed
+ */
+ public function __set($key, $value)
+ {
+ if ($this->flag == self::ARRAY_AS_PROPS)
+ {
+ return $this->offsetSet($key, $value);
+ }
+
+ if (in_array($key, $this->protectedProperties))
+ {
+ throw new \InvalidArgumentException('$key is a protected property, use a different key');
+ }
+
+ $this->$key = $value;
+ }
+
+ /**
+ * Unsets the value at the specified key
+ *
+ * @param mixed $key
+ *
+ * @throws \InvalidArgumentException
+ * @return void|mixed
+ */
+ public function __unset($key)
+ {
+ if ($this->flag == self::ARRAY_AS_PROPS)
+ {
+ return $this->offsetUnset($key);
+ }
+
+ if (in_array($key, $this->protectedProperties))
+ {
+ throw new \InvalidArgumentException('$key is a protected property, use a different key');
+ }
+
+ unset($this->$key);
+ }
+
+ /**
+ * Returns the value at the specified key by reference
+ *
+ * @param mixed $key
+ *
+ * @throws \InvalidArgumentException
+ * @return mixed
+ */
+ public function &__get($key)
+ {
+ $ret = null;
+
+ if ($this->flag == self::ARRAY_AS_PROPS)
+ {
+ $ret =& $this->offsetGet($key);
+
+ return $ret;
+ }
+
+ if (in_array($key, $this->protectedProperties))
+ {
+ throw new \InvalidArgumentException('$key is a protected property, use a different key');
+ }
+
+ return $this->$key;
+ }
+
+ /**
+ * Appends the value
+ *
+ * @param mixed $value
+ *
+ * @return void
+ */
+ public function append($value)
+ {
+ $this->storage[] = $value;
+ }
+
+ /**
+ * Sort the entries by value
+ *
+ * @return void
+ */
+ public function asort()
+ {
+ asort($this->storage);
+ }
+
+ /**
+ * Get the number of public properties in the ArrayObject
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->storage);
+ }
+
+ /**
+ * Exchange the array for another one.
+ *
+ * @param array|ArrayObject $data
+ *
+ * @throws \InvalidArgumentException
+ * @return array
+ */
+ public function exchangeArray($data)
+ {
+ if (!is_array($data) && !is_object($data))
+ {
+ throw new \InvalidArgumentException('Passed variable is not an array or object, using empty array instead');
+ }
+
+ if (is_object($data) && ($data instanceof self || $data instanceof \ArrayObject))
+ {
+ $data = $data->getArrayCopy();
+ }
+
+ if (!is_array($data))
+ {
+ $data = (array) $data;
+ }
+
+ $storage = $this->storage;
+
+ $this->storage = $data;
+
+ return $storage;
+ }
+
+ /**
+ * Creates a copy of the ArrayObject.
+ *
+ * @return array
+ */
+ public function getArrayCopy()
+ {
+ return $this->storage;
+ }
+
+ /**
+ * Gets the behavior flags.
+ *
+ * @return int
+ */
+ public function getFlags()
+ {
+ return $this->flag;
+ }
+
+ /**
+ * Create a new iterator from an ArrayObject instance
+ *
+ * @return \Iterator
+ */
+ public function getIterator()
+ {
+ $class = $this->iteratorClass;
+
+ return new $class($this->storage);
+ }
+
+ /**
+ * Gets the iterator classname for the ArrayObject.
+ *
+ * @return string
+ */
+ public function getIteratorClass()
+ {
+ return $this->iteratorClass;
+ }
+
+ /**
+ * Sort the entries by key
+ *
+ * @return void
+ */
+ public function ksort()
+ {
+ ksort($this->storage);
+ }
+
+ /**
+ * Sort an array using a case insensitive "natural order" algorithm
+ *
+ * @return void
+ */
+ public function natcasesort()
+ {
+ natcasesort($this->storage);
+ }
+
+ /**
+ * Sort entries using a "natural order" algorithm
+ *
+ * @return void
+ */
+ public function natsort()
+ {
+ natsort($this->storage);
+ }
+
+ /**
+ * Returns whether the requested key exists
+ *
+ * @param mixed $key
+ *
+ * @return bool
+ */
+ public function offsetExists($key)
+ {
+ return isset($this->storage[$key]);
+ }
+
+ /**
+ * Returns the value at the specified key
+ *
+ * @param mixed $key
+ *
+ * @return mixed
+ */
+ public function &offsetGet($key)
+ {
+ $ret = null;
+
+ if (!$this->offsetExists($key))
+ {
+ return $ret;
+ }
+
+ $ret =& $this->storage[$key];
+
+ return $ret;
+ }
+
+ /**
+ * Sets the value at the specified key to value
+ *
+ * @param mixed $key
+ * @param mixed $value
+ *
+ * @return void
+ */
+ public function offsetSet($key, $value)
+ {
+ $this->storage[$key] = $value;
+ }
+
+ /**
+ * Unsets the value at the specified key
+ *
+ * @param mixed $key
+ *
+ * @return void
+ */
+ public function offsetUnset($key)
+ {
+ if ($this->offsetExists($key))
+ {
+ unset($this->storage[$key]);
+ }
+ }
+
+ /**
+ * Serialize an ArrayObject
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ return serialize(get_object_vars($this));
+ }
+
+ /**
+ * Sets the behavior flags
+ *
+ * @param int $flags
+ *
+ * @return void
+ */
+ public function setFlags($flags)
+ {
+ $this->flag = $flags;
+ }
+
+ /**
+ * Sets the iterator classname for the ArrayObject
+ *
+ * @param string $class
+ *
+ * @throws \InvalidArgumentException
+ * @return void
+ */
+ public function setIteratorClass($class)
+ {
+ if (class_exists($class))
+ {
+ $this->iteratorClass = $class;
+
+ return;
+ }
+
+ if (strpos($class, '\\') === 0)
+ {
+ $class = '\\' . $class;
+
+ if (class_exists($class))
+ {
+ $this->iteratorClass = $class;
+
+ return;
+ }
+ }
+
+ throw new \InvalidArgumentException('The iterator class does not exist');
+ }
+
+ /**
+ * Sort the entries with a user-defined comparison function and maintain key association
+ *
+ * @param callable $function
+ *
+ * @return void
+ */
+ public function uasort($function)
+ {
+ if (is_callable($function))
+ {
+ uasort($this->storage, $function);
+ }
+ }
+
+ /**
+ * Sort the entries by keys using a user-defined comparison function
+ *
+ * @param callable $function
+ *
+ * @return void
+ */
+ public function uksort($function)
+ {
+ if (is_callable($function))
+ {
+ uksort($this->storage, $function);
+ }
+ }
+
+ /**
+ * Unserialize an ArrayObject
+ *
+ * @param string $data
+ *
+ * @return void
+ */
+ public function unserialize($data)
+ {
+ $ar = unserialize($data);
+
+ $this->protectedProperties = array_keys(get_object_vars($this));
+
+ $this->setFlags($ar['flag']);
+ $this->exchangeArray($ar['storage']);
+ $this->setIteratorClass($ar['iteratorClass']);
+
+ foreach ($ar as $k => $v)
+ {
+ switch ($k)
+ {
+ case 'flag':
+ $this->setFlags($v);
+ break;
+ case 'storage':
+ $this->exchangeArray($v);
+ break;
+ case 'iteratorClass':
+ $this->setIteratorClass($v);
+ break;
+ case 'protectedProperties':
+ continue;
+ default:
+ $this->__set($k, $v);
+ }
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Iterator/CallbackFilterIterator.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Iterator/CallbackFilterIterator.php
new file mode 100644
index 00000000..abc2452e
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Iterator/CallbackFilterIterator.php
@@ -0,0 +1,61 @@
+callback = $callback;
+
+ parent::__construct($iterator);
+ }
+
+ /**
+ * accept
+ *
+ * @return bool|mixed
+ */
+ public function accept()
+ {
+ $inner = $this->getInnerIterator();
+
+ return call_user_func_array(
+ $this->callback,
+ array(
+ $inner->current(),
+ $inner->key(),
+ $inner
+ )
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Iterator/RecursiveDirectoryIterator.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Iterator/RecursiveDirectoryIterator.php
new file mode 100644
index 00000000..74e2ef81
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Iterator/RecursiveDirectoryIterator.php
@@ -0,0 +1,43 @@
+getPathname();
+
+ $endletters = DIRECTORY_SEPARATOR . '.';
+
+ if (substr($name, -2) == $endletters)
+ {
+ $name = substr($name, 0, -2);
+ }
+
+ $file = new \SplFileInfo($name);
+
+ return $file;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Path.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Path.php
new file mode 100644
index 00000000..2242d407
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Path.php
@@ -0,0 +1,298 @@
+getBasename() == $file);
+ };
+
+ $collection = new PathCollection($paths);
+
+ return $collection->findOne($filter);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Path/PathCollection.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Path/PathCollection.php
new file mode 100644
index 00000000..f1fedab9
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Path/PathCollection.php
@@ -0,0 +1,424 @@
+addPaths($paths);
+ }
+
+ /**
+ * Batch add paths to bag.
+ *
+ * @param mixed $paths Paths to add to path bag, string will be converted to PathLocator object.
+ *
+ * @return PathCollection Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function addPaths($paths)
+ {
+ $paths = is_array($paths) ? $paths : array($paths);
+
+ foreach ($paths as $key => $path)
+ {
+ $key = is_int($key) ? null : $key;
+
+ $this->addPath($path, $key);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add one path to bag.
+ *
+ * @param mixed $path The path your want to store in bag,
+ * have to be a string or PathLocator object.
+ * @param string $key Path key, useful when you want to remove a path.
+ *
+ * @throws \InvalidArgumentException
+ * @return PathCollection Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function addPath($path, $key = null)
+ {
+ // If path element is subclass of PathLocatorInterface, just put it in path bag.
+ // You can create any your Path locator class implements from PathLocatorInterface.
+ if ($path instanceof PathLocatorInterface)
+ {
+ // Nothing to do
+ }
+ // If this element is a path string, we create a PathLocator to wrap it.
+ elseif (is_string($path) || !$path)
+ {
+ $path = new PathLocator($path);
+ }
+ // If type of this element not match our interface, throw exception.
+ else
+ {
+ throw new \InvalidArgumentException('PathCollection need every path element instance of PathLocatorInterface.');
+ }
+
+ if ($key)
+ {
+ parent::offsetSet($key, $path);
+ }
+ else
+ {
+ parent::append($path);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Using key to remove a path from bag.
+ *
+ * @param string $key The key of path you want to remove.
+ *
+ * @return PathCollection Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function removePath($key)
+ {
+ parent::offsetUnset($key);
+
+ return $this;
+ }
+
+ /**
+ * Get all paths with key from bag.
+ *
+ * @return array An array includes all path objects.
+ *
+ * @since 2.0
+ */
+ public function getPaths()
+ {
+ return parent::getArrayCopy();
+ }
+
+ /**
+ * Using key to get a path.
+ *
+ * @param string $key The key of path you want to get.
+ * @param string $default If path not exists, return this default path.
+ * Default value can be PathLocator object string or null.
+ * String will auto wrapped by object, if is null, just return null.
+ *
+ * @return PathLocator The path which you want.
+ *
+ * @since 2.0
+ */
+ public function getPath($key, $default = null)
+ {
+ if (!parent::offsetExists($key))
+ {
+ if (!$default)
+ {
+ return $default;
+ }
+
+ if (!($default instanceof PathLocatorInterface))
+ {
+ $default = new PathLocator($default);
+ }
+
+ return $default;
+ }
+
+ return parent::offsetGet($key);
+ }
+
+ /**
+ * Append all paths' iterator into an OuterIterator.
+ *
+ * @param \Closure $callback Contains the logic of how to get iterator from path object.
+ *
+ * @return \AppendIterator Appended iterators.
+ *
+ * @since 2.0
+ */
+ protected function appendIterator(\Closure $callback = null)
+ {
+ $iterator = new \AppendIterator;
+
+ $paths = (array) parent::getArrayCopy();
+
+ $clousre = function ($path) use ($callback, $iterator)
+ {
+ $iterator->append($callback($path));
+ };
+
+ foreach ($this as $path)
+ {
+ if ($this->isSubdir($path))
+ {
+ continue;
+ }
+
+ $clousre($path);
+ }
+
+ return $iterator;
+ }
+
+ /**
+ * Get all files and folders as an iterator.
+ *
+ * @param boolean $recursive True to support recrusive.
+ *
+ * @return \AppendIterator An OutterIterator contains all paths' iterator.
+ *
+ * @since 2.0
+ */
+ public function getAllChildren($recursive = false)
+ {
+ return $this->appendIterator(
+ function ($path) use ($recursive)
+ {
+ return $path->getIterator($recursive);
+ }
+ );
+ }
+
+ /**
+ * Find one file from all paths.
+ *
+ * @param mixed $condition Finding condition, that can be a string, a regex or a callback function.
+ * Callback example:
+ *
+ * function($current, $key, $iterator)
+ * {
+ * return @preg_match('^Foo', $current->getFilename()) && ! $iterator->isDot();
+ * }
+ *
+ * @param boolean $recursive True to resursive.
+ *
+ * @return \SplFileInfo Finded file info object.
+ *
+ * @since 2.0
+ */
+ public function findOne($condition, $recursive = false)
+ {
+ $iterator = $this->appendIterator(
+ function ($path) use ($condition, $recursive)
+ {
+ return Filesystem::find((string) $path, $condition, $recursive);
+ }
+ );
+
+ $iterator->rewind();
+
+ return $iterator->current();
+ }
+
+ /**
+ * Find all files from paths.
+ *
+ * @param mixed $condition Finding condition, that can be a string, a regex or a callback function.
+ * Callback example:
+ *
+ * function($current, $key, $iterator)
+ * {
+ * return @preg_match('^Foo', $current->getFilename()) && ! $iterator->isDot();
+ * }
+ *
+ * @param boolean $recursive True to resursive.
+ *
+ * @return \AppendIterator Finded files or paths iterator.
+ *
+ * @since 2.0
+ */
+ public function find($condition, $recursive = false)
+ {
+ return $this->appendIterator(
+ function ($path) use ($condition, $recursive)
+ {
+ return Filesystem::find((string) $path, $condition, $recursive);
+ }
+ );
+ }
+
+ /**
+ * Get file iterator of all paths
+ *
+ * @param boolean $recursive True to resursive.
+ *
+ * @return \AppendIterator Iterator only include files.
+ */
+ public function getFiles($recursive = false)
+ {
+ return $this->appendIterator(
+ function ($path) use ($recursive)
+ {
+ return Filesystem::files((string) $path, $recursive);
+ }
+ );
+ }
+
+ /**
+ * Get folder iterator of all paths
+ *
+ * @param boolean $recursive True to resursive.
+ *
+ * @return \AppendIterator Iterator only include dirs.
+ */
+ public function getFolders($recursive = false)
+ {
+ return $this->appendIterator(
+ function ($path) use ($recursive)
+ {
+ return Filesystem::folders((string) $path, $recursive);
+ }
+ );
+ }
+
+ /**
+ * Set prefix to all paths.
+ *
+ * @param string $prefix The prefix path you want to prepend when path convert to string.
+ *
+ * @return PathCollection Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function setPrefix($prefix)
+ {
+ foreach ($this->storage as &$path)
+ {
+ $path->setPrefix((string) $prefix);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Append a new path to all paths.
+ *
+ * @param string $appended Path to append.
+ *
+ * @return PathCollection Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function appendAll($appended)
+ {
+ foreach ($this->storage as &$path)
+ {
+ $path->append($appended);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Prepend a new path to all paths.
+ *
+ * @param string $prepended Path to prepend.
+ *
+ * @return PathCollection Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function prependAll($prepended)
+ {
+ foreach ($this->storage as &$path)
+ {
+ $path->prepend($prepended);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Convert paths bag to array, and every path to string.
+ *
+ * @param bool $reindex
+ *
+ * @return array Raw paths.
+ *
+ * @since 2.0
+ */
+ public function toArray($reindex = false)
+ {
+ $array = array();
+
+ foreach ($this as $key => $path)
+ {
+ if ($reindex)
+ {
+ $array[] = (string) clone $path;
+ }
+ else
+ {
+ $array[$key] = (string) clone $path;
+ }
+ }
+
+ return $array;
+ }
+
+ /**
+ * Is this path a subdir of another path in bag?
+ *
+ * When running recursive scan dir, we have to avoid to re scan same dir.
+ *
+ * @param PathLocator $path The path to detect is subdir or not.
+ *
+ * @return boolean Is subdir or not.
+ *
+ * @since 2.0
+ */
+ public function isSubdir($path)
+ {
+ foreach ($this->storage as $member)
+ {
+ if ($member->isSubdirOf($path))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Path/PathLocator.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Path/PathLocator.php
new file mode 100644
index 00000000..3e457ee2
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Path/PathLocator.php
@@ -0,0 +1,512 @@
+paths = $this->normalize($path);
+ }
+
+ /**
+ * Replace with a new path.
+ *
+ * @param string $path Path to parse.
+ *
+ * @return static Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function redirect($path)
+ {
+ $this->paths = $this->normalize($path);
+
+ return $this;
+ }
+
+ /**
+ * Get file iterator of current dir.
+ *
+ * @param boolean $recursive True to resursive.
+ *
+ * @return \FilesystemIterator|\RecursiveIteratorIterator File & dir iterator.
+ */
+ public function getIterator($recursive = false)
+ {
+ // If we put this object into a foreach, return all files and folders to iterator.
+ return Filesystem::items((string) $this, $recursive);
+ }
+
+ /**
+ * Get folder iterator of current dir.
+ *
+ * @param boolean $recursive True to resursive.
+ *
+ * @return \CallbackFilterIterator Iterator only include dirs.
+ */
+ public function getFolders($recursive = false)
+ {
+ return Filesystem::folders((string) $this, $recursive);
+ }
+
+ /**
+ * Get file iterator of current dir
+ *
+ * @param boolean $recursive True to resursive.
+ *
+ * @return \CallbackFilterIterator Iterator only include files.
+ */
+ public function getFiles($recursive = false)
+ {
+ return Filesystem::files((string) $this, $recursive);
+ }
+
+ /**
+ * Find one file and return.
+ *
+ * @param mixed $condition Finding condition, that can be a string, a regex or a callback function.
+ * Callback example:
+ *
+ * function($current, $key, $iterator)
+ * {
+ * return @preg_match('^Foo', $current->getFilename()) && ! $iterator->isDot();
+ * }
+ *
+ * @param boolean $recursive True to resursive.
+ *
+ * @return \SplFileInfo Finded file info object.
+ *
+ * @since 2.0
+ */
+ public function findOne($condition, $recursive = false)
+ {
+ return Filesystem::findOne((string) $this, $condition, $recursive);
+ }
+
+ /**
+ * Find all files which matches condition.
+ *
+ * @param mixed $condition Finding condition, that can be a string, a regex or a callback function.
+ * Callback example:
+ *
+ * function($current, $key, $iterator)
+ * {
+ * return @preg_match('^Foo', $current->getFilename()) && ! $iterator->isDot();
+ * }
+ *
+ * @param boolean $recursive True to resursive.
+ *
+ * @return \CallbackFilterIterator Finded files or paths iterator.
+ *
+ * @since 2.0
+ */
+ public function find($condition, $recursive = false)
+ {
+ return Filesystem::find((string) $this, $condition, $recursive);
+ }
+
+ /**
+ * Using a closure function to filter file.
+ *
+ * @param \Closure $callback A callback function to filter file.
+ * @param boolean $recursive True to recursive.
+ *
+ * @return \CallbackFilterIterator Filtered file or path iteator.
+ *
+ * @see http://www.php.net/manual/en/class.callbackfilteriterator.php
+ * @since 2.0
+ */
+ public function findByCallback(\Closure $callback, $recursive = false)
+ {
+ return Filesystem::findByCallback((string) $this, $callback, $recursive);
+ }
+
+ /**
+ * Normalize path, remove not necessary elements.
+ *
+ * @param string $path A given path to normalize.
+ * @param bool $returnString Return string or array.
+ *
+ * @return string|array Normalized path.
+ *
+ * @since 2.0
+ */
+ protected function normalize($path, $returnString = false)
+ {
+ // Clean the Directory separator
+ $path = $this->clean($path);
+
+ // Extract to array
+ $path = $this->extract($path);
+
+ // Remove dots from path
+ $path = $this->removeDots($path);
+
+ // If set to return string, compact it.
+ if ($returnString == true)
+ {
+ $path = $this->compact($path);
+ }
+
+ return $path;
+ }
+
+ /**
+ * Clean path and remove dots.
+ *
+ * @param string $path A given path to parse.
+ *
+ * @return string Cleaned path.
+ *
+ * @since 2.0
+ */
+ protected function clean($path)
+ {
+ $path = rtrim($path, ' /\\');
+
+ $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
+
+ return $path;
+ }
+
+ /**
+ * Remove dots from path.
+ *
+ * @param string|array $path A given path to remove dots.
+ *
+ * @return string|array Cleaned path.
+ *
+ * @since 2.0
+ */
+ protected function removeDots($path)
+ {
+ $isBeginning = true;
+
+ // If not array, extract it.
+ $isArray = is_array($path);
+
+ $path = $isArray ? $path : $this->extract($path);
+
+ // Search for dot files
+ foreach ($path as $key => $row)
+ {
+ // Remove dot files
+ if ($row == '.')
+ {
+ unset($path[$key]);
+ }
+
+ // Remove dots and go parent dir
+ if ($row == '..' && !$isBeginning)
+ {
+ unset($path[$key]);
+ unset($path[$key - 1]);
+ }
+
+ // Do not get parent if dots in the beginning
+ if ($row != '..' && $isBeginning)
+ {
+ $isBeginning = false;
+ }
+ }
+
+ // Re index array
+ $path = array_values($path);
+
+ return $isArray ? $path : $this->compact($path);
+ }
+
+ /**
+ * Detect is current path a dir?
+ *
+ * @return boolean True if is a dir.
+ *
+ * @since 2.0
+ */
+ public function isDir()
+ {
+ return is_dir((string) $this);
+ }
+
+ /**
+ * Detect is current path a file?
+ *
+ * @return boolean True if is a file.
+ *
+ * @since 2.0
+ */
+ public function isFile()
+ {
+ return is_file((string) $this);
+ }
+
+ /**
+ * Detect is current path exists?
+ *
+ * @return boolean True if exists.
+ *
+ * @since 2.0
+ */
+ public function exists()
+ {
+ return file_exists((string) $this);
+ }
+
+ /**
+ * Set a prefix, when this object convert to string,
+ * prefix will auto add to the front of path.
+ *
+ * @param string $prefix Prefix string to set.
+ *
+ * @return static Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function setPrefix($prefix = '')
+ {
+ $this->prefix = $this->normalize($prefix, true);
+
+ return $this;
+ }
+
+ /**
+ * Get a child path of given name.
+ *
+ * @param string $name Child name.
+ *
+ * @return static Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function child($name)
+ {
+ $path = $this->normalize($name);
+
+ $this->append($path);
+
+ return $this;
+ }
+
+ /**
+ * Get a parent path of given condition.
+ *
+ * @param boolean $condition Parent condition.
+ *
+ * @return static Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function parent($condition = null)
+ {
+ // Up one level
+ if (is_null($condition))
+ {
+ array_pop($this->paths);
+ }
+ // Up mutiple level
+ elseif (is_int($condition))
+ {
+ $this->paths = array_slice($this->paths, 0, -$condition);
+ }
+ // Find a dir name and go to this level
+ elseif (is_string($condition))
+ {
+ $paths = $this->paths;
+
+ $paths = array_reverse($paths);
+
+ // Find parent
+ $n = 0;
+
+ foreach ($paths as $key => $name)
+ {
+ if ($key == 0)
+ {
+ // Ignore latest dir
+ continue;
+ }
+
+ // Is this dir match condition?
+ if ($name == $condition)
+ {
+ $n = $key;
+ break;
+ }
+ }
+
+ $this->paths = array_slice($this->paths, 0, -$n);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Append a new path before current path.
+ *
+ * @param string $path Path to append.
+ *
+ * @return static Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function append($path)
+ {
+ if (!is_array($path))
+ {
+ $path = $this->normalize($path);
+ }
+
+ $path = array_merge($this->paths, $path);
+
+ $this->paths = $this->removeDots($path);
+
+ return $this;
+ }
+
+ /**
+ * Append a new path before current path.
+ *
+ * @param string $path Path to append.
+ *
+ * @return static Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function prepend($path)
+ {
+ if (!is_array($path))
+ {
+ $path = $this->normalize($path);
+ }
+
+ $path = array_merge($path, $this->paths);
+
+ $this->paths = $this->removeDots($path);
+
+ return $this;
+ }
+
+ /**
+ * Is this path subdir of given path?
+ *
+ * @param string $parent Given path to detect.
+ *
+ * @return boolean Is subdir or not.
+ *
+ * @since 2.0
+ */
+ public function isSubdirOf($parent)
+ {
+ $self = (string) $this;
+
+ $parent = $this->normalize($parent, true);
+
+ // Path is self
+ if ($self == $parent)
+ {
+ return false;
+ }
+
+ // Path is parent
+ if (strpos($parent, $self) === 0)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Convert this object to string.
+ *
+ * @return string Path name.
+ *
+ * @since 2.0
+ */
+ public function __toString()
+ {
+ $path = $this->compact($this->paths);
+
+ if ($this->prefix)
+ {
+ $path = rtrim($this->prefix, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . trim($path, DIRECTORY_SEPARATOR);
+ }
+
+ $path = $this->removeDots($path);
+
+ return $path;
+ }
+
+ /**
+ * Explode path by DIRECTORY_SEPARATOR.
+ *
+ * @param string $path Path to extract.
+ *
+ * @return array Extracted path array.
+ *
+ * @since 2.0
+ */
+ protected function extract($path)
+ {
+ return explode(DIRECTORY_SEPARATOR, $path);
+ }
+
+ /**
+ * Implode path by DIRECTORY_SEPARATOR.
+ *
+ * @param string $path Path to compact.
+ *
+ * @return array Compacted path array.
+ *
+ * @since 2.0
+ */
+ protected function compact($path)
+ {
+ return implode(DIRECTORY_SEPARATOR, $path);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Path/PathLocatorInterface.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Path/PathLocatorInterface.php
new file mode 100644
index 00000000..627bff76
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Path/PathLocatorInterface.php
@@ -0,0 +1,13 @@
+child('plugins') // => /var/www/flower/plugins
+ ->child('system/flower/lib'); // => /var/www/flower/plugins/system/flower/lib
+```
+
+##### Parent
+
+``` php
+$path->parent() // => /var/www/flower/plugins/system/flower (Up one level)
+ ->parent(2) // => /var/www/flower/plugins (Up 2 levels)
+ ->parent('www'); // => /var/www (Find a parent and go this level)
+```
+
+##### Prefix
+
+Add a prefix of system path, we can change it, only when converting to string, the prefix will be added to path.
+
+``` php
+$path2 = new PathLocator('src/Sakura/Olive');
+
+echo $path->addPrefix($_SERVER['DOCUMENT_ROOT']); // => /var/www/src/Sakura/Olive
+```
+
+#### Filesystem Operation
+
+``` php
+echo $path->isDir(); // true or false
+echo $path->isFile(); // true or false
+echo $path->exists(); // true or false
+```
+
+##### Get file info
+
+This function has not prepared yet.
+
+``` php
+$path->getInfo(); // return SplFileInfo of current directory
+
+$path->getInfo('index.php'); // return SplFileInfo of this file
+```
+
+##### Scan dir
+
+Get Folders
+
+``` php
+$dirs = $path->getFolders([true to recrusive]);
+
+foreach($dirs as $dir)
+{
+ echo $dir . ' '; // print all dir's name
+}
+```
+
+Get Files
+
+``` php
+$files = $path->getFiles([true to recrusive]);
+
+foreach($files as $file)
+{
+ echo $file->getPathname() . ' '; // print all file's name
+}
+```
+
+##### Find files
+
+Find by string or regex
+
+``` php
+echo $path->find('config.json'); // Find one file and return fileinfo object
+
+echo $path->find(array('^config')); // Find one file by regex
+
+// Second argument set to TRUE for recursive
+foreach($path->findAll(array('^config_*.json', '!^..'), true) as $file)
+{
+ // Find all files as array, param 2 to recursive
+}
+```
+
+Find by callback
+
+``` php
+$callback = function($current, $key, $iterator)
+{
+ return return @preg_match('^Foo', $current->getFilename()) && ! $iterator->isDot();
+};
+
+foreach($path->findAll($callback, true) as $file)
+{
+ // ...
+}
+```
+
+Find by Comparator
+
+This comparator object may contain the filter logic, but not prepared yet.
+
+``` php
+$comparator = new FileComparator;
+
+foreach($path->findAll(FileComparatorInterface $comparator, true) as $file)
+{
+ // ...
+}
+```
+
+#### Strict Mode
+
+This function not prepared yet.
+
+``` php
+$dl2 = new \DirectoryLocator($_SERVER['DOCUMENT_ROOT'] . '/src', true);
+$dls->child('Campenont'); // throw PathNotExistsException();
+$dls->child('../www/index.php'); // throw PathNotDirException();
+```
+
+*
+
+## PathCollection object
+
+A collection of paths, we can put many paths to this object, and use it as array.
+
+And we can use this collection to iterate all sub dirs and files, also find files.
+
+The iterator will travel to every `PathLocator` in this collection object, and return an SplFileInfo for us.
+
+#### Create a new PathCollection
+
+##### Add with no key
+
+``` php
+$paths = new PathCollection(array(
+ new PathLocator('templates/' . $template . '/html/' . $option),
+ new PathLocator('Sakuras/' . $option . '/view/tmpl/'),
+ 'layouts/' . $option , // Auto convert to PathLocator
+));
+```
+
+##### Add with key name
+
+``` php
+$paths = new PathColleciotn(array(
+ 'Template' => new PathLocator('templates/' . $template . '/html/' . $option),
+ 'Sakura' => new PathLocator('Sakuras/' . $option . '/view/tmpl/'),
+ 'Layout' => new PathLocator('layouts/' . $option)
+));
+```
+
+#### Paths operations
+
+##### Add path
+
+``` php
+$paths->addPath(new PathLocator('Foo')); // No key name, will using number as key
+
+$paths->addPath(new PathLocator('Foo'), 'Foo'); // With key name
+```
+
+##### Add paths
+
+``` php
+$paths->addPaths(array(new PathLocator('Bar'))); // Add by array
+```
+
+##### Remove path
+
+``` php
+$paths->removePath('Foo'); // Remove by key name
+$paths->removePath(0); // Remove by number
+```
+
+##### Set prefix to all paths
+
+We can change this prefix, only when converting to string,
+the prefix will have been added to path.
+
+``` php
+// Prepend all path with a prefix path.
+
+$paths->setPrefix('/var/www/flower');
+```
+
+#### Iterator
+
+List all PathLocator
+
+``` php
+foreach($paths as $path)
+{
+ echo $path // print path string
+}
+```
+
+Return a raw array
+
+``` php
+foreach($paths->toArray() as $path)
+{
+ echo $path // print path string
+}
+```
+
+List all files and folders of all paths
+
+``` php
+foreach($paths->getAllChildren([true to recrusive]) as $file)
+{
+ echo $file // SplFileInfo
+}
+```
+
+List all files
+
+``` php
+foreach($paths->getFiles([true to recrusive]) as $file)
+{
+ echo $file->getFilename() // SplFileInfo
+}
+```
+
+List all folders
+
+``` php
+foreach($paths->getFolders([true to recrusive]) as $dir)
+{
+ echo $file->getPathname() // SplFileInfo
+}
+```
+
+#### Find Files and Folders
+
+Same as PathLocator, but return all paths' file & folders.
+
+``` php
+$paths->find('config.json');
+
+$paths->findAll('config_*.json');
+```
+
+-------
+
+### Using it as array or string
+
+``` php
+$cache = new PathLocator($_SERVER['DOCUMENT_ROOT'] . '/cache');
+$loader = new \Twig_Loader_Filesystem($paths);
+
+$twig = new \Twig_Environment($loader, array(
+ 'cache' => (string) $cache,
+));
+```
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/README.md b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/README.md
new file mode 100644
index 00000000..c72513e6
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/README.md
@@ -0,0 +1,362 @@
+# Windwalker Filesystem
+
+Windwalker Filesystem provides some easy interface to operate file and folders.
+
+## Installation via Composer
+
+Add this to the require block in your `composer.json`.
+
+``` json
+{
+ "require": {
+ "windwalker/filesystem": "~2.0"
+ }
+}
+```
+
+## File
+
+File is a abstract class provides methods to operate files.
+
+### Write & Delete files
+
+``` php
+use Windwalker\Filesystem\File;
+
+$file = '/path/to/file.txt';
+
+File::write($file, $content);
+
+File::delete($file);
+```
+
+### Move & Copy
+
+``` php
+$src = '/path/to/file.txt';
+$dest = '/path/of/new/file.txt';
+
+// Move
+File::move($src, $dest);
+
+// Force move if file exsits
+File::move($src, $dest, true);
+
+// Copy
+File::copy($src, $dest);
+
+// Force copy if file exists
+File::copy($src, $dest, true);
+```
+
+### Upload
+
+``` php
+File::upload($src, $dest);
+```
+
+It is basically the wrapper for the PHP `move_uploaded_file()` function, but also does checks availability
+and permissions on both source and destination path.
+
+### File Name
+
+Strip extension and get simple path:
+
+``` php
+$file = '/path/to/flower.txt';
+
+$name = File::stripExtension($file); // /path/to/flower
+```
+
+Get extension:
+
+``` php
+$file = '/path/to/flower.txt';
+
+File::getExtension($file); // txt
+```
+
+Get only file name.
+
+``` php
+$file = '/path/to/flower.txt';
+
+File::getFilename($file); // flower.txt
+```
+
+Make file name safe to store.
+
+``` php
+$path = /path!/to/flower sakura.
+
+File::makeSafe($path); // /path/to/flowersakura
+```
+
+## Folder
+
+Folder class help us operate folders and list files of a folder.
+
+### Folder Operation
+
+Move & Copy
+
+``` php
+use Windwalker\Filesystem\Folder;
+
+// Move folder
+Folder::move($src, $dest);
+
+// Force move if folder exists
+Folder::move($src, $dest, true);
+
+// Copy folder, will also copy all children
+Folder::copy($src, $dest);
+
+// Force copy if folder exists
+Folder::copy($src, $dest, true);
+```
+
+Create & Delete
+
+``` php
+Folder::create($path);
+
+Folder::delete($path);
+```
+
+### List Files
+
+#### List Folders
+
+``` php
+// List folders of a folder
+Folder::folders($dir);
+
+// List folders recursive
+Folder::folders($dir, true);
+
+// Path type: Get basename of every item
+Folder::folders($dir, true, Folder::PATH_BASENAME);
+```
+
+Available path type:
+
+- `Folder::PATH_ABSOLUTE` - Absolute full path.
+- `Folder::PATH_RELATIVE` - Relative path from folder you scan.
+- `Folder::PATH_BASENAME` - The folder or file name.
+
+#### List Files
+
+``` php
+// List files of a folder
+Folder::files($dir);
+
+// List files recursive
+Folder::files($dir, true);
+
+// Path type: Get basename of every item
+Folder::files($dir, true, Folder::PATH_BASENAME);
+```
+
+#### List Files & Folders
+
+``` php
+// List files & folders of a folder
+Folder::items($dir);
+
+// List files & folders recursive
+Folder::items($dir, true);
+
+// Path type: Get basename of every item
+Folder::items($dir, true, Folder::PATH_RELATIVE);
+```
+
+## Filesystem Class
+
+Filesystem class is a universal finder to find and operate folders & files.
+
+### Folder & File Operation
+
+Filesystem move & copy method will auto detect the path is a folder or file, if is folder, it will call `Folder::move()`,
+ if is file, it will call `File::move()`.
+
+``` php
+// we don't need to know $src is a folder or file, Filesystem will detect it.
+Filesystem::move($src, $dest);
+Filesystem::copy($src, $dest);
+Filesystem::delete($src, $dest);
+```
+
+## Path
+
+A simple helper to handler some path string.
+
+### Clean Path
+
+To strip additional / or \ in a path name.
+
+``` php
+$path = '/var/www\flower\sakura/olive';
+
+$path = Path::clean($path); // Will be: '/var/www/flower/sakura/olive'
+```
+
+### Permissions
+
+``` php
+// Get by number
+Path::getPermissions($path); // 755
+
+// Get by string
+Path::getPermissions($path, true); // dwrxwrx--x
+
+// Set permissions, if is file, set to 644, if is folder set to 755
+Path::setPermissions($path, '0644', '0755');
+
+// Check can change Permissions
+Path::canChmod($path); // Bool
+```
+
+
+
+### Finder
+
+Finder is the most powerful function of Filesystem, it provides an interface to let us use our logic to filter files.
+
+#### Simple Finder
+
+``` php
+// Argument 2 is recursive
+$folders = Filesystem::folders($path, true);
+$files = Filesystem::files($path, true);
+$items = Filesystem::items($path, true);
+```
+
+The simple finder are same as Folder, but it will not scan all files instantly, but returns an Iterator instead,
+ we can send this iterator to `foreach` and do some filter by `SplFileInfo` object.
+
+``` php
+foreach ($items as $item)
+{
+ if ($item->isDir() || $item->isDot())
+ {
+ continue;
+ }
+
+ // Do something
+}
+```
+
+If you really need array not an Iterator, use `Filesystem::iteratorToArray()`.
+
+``` php
+$folders = Filesystem::folder($path, true);
+
+// To array
+$folders = Filesystem::iteratorToArray($folders);
+```
+
+Or set argument 3 to `TRUE`.
+
+``` php
+$folders = Filesystem::folder($path, true, true);
+
+is_array($folders); // TRUE
+```
+
+### Advanced Finder
+
+Find by name.
+
+``` php
+$files = Filesystem::find($path, 'flower.php');
+```
+
+Multiple name.
+
+``` php
+$files = Filesystem::find($path, array('flower.php', 'sakura.php'));
+```
+
+Find by regex
+
+``` php
+$files = Filesystem::find($path, '^[a-zA-Z0-9]');
+```
+
+Only find first matched.
+
+``` php
+$file = Filesystem::findOne($path, array('flower.php', 'sakura.php'));
+```
+
+Find recursive
+
+``` php
+$files = Filesystem::find($path, array('flower.php', 'sakura.php'), true);
+```
+
+To array
+
+``` php
+$files = Filesystem::find($path, array('flower.php', 'sakura.php'), true, true);
+```
+
+### Callback Finder
+
+Inject our filter logic to find files.
+
+``` php
+/**
+ * Files callback
+ *
+ * @param \SplFileInfo $current Current item's value
+ * @param string $key Current item's key
+ * @param \RecursiveDirectoryIterator $iterator Iterator being filtered
+ *
+ * @return boolean TRUE to accept the current item, FALSE otherwise
+ */
+$closure = function($current, $key, $iterator)
+{
+ return Path::getPermissions($current->getPath()) >= 755;
+};
+
+$files = Filesystem::find($path, $closure, true);
+```
+
+Or create a `FileComparator` object.
+
+``` php
+use Windwalker\Filesystem\Comparator\FileComparatorInterface;
+
+class MyComparator implements FileComparatorInterface
+{
+ public function compare($current, $key, $iterator)
+ {
+ return Path::getPermissions($current->getPath()) >= 755;
+ }
+}
+
+$files = Filesystem::find($path, new MyComparator, true);
+```
+
+### Advanced Comparator
+
+We can create our own comparator like an finder object.
+
+``` php
+// This is just an example
+
+$comparator = new MyAdvancedComparator;
+
+$comparator->setTimeGreaterThan(new DataTime)
+ ->setExtension('ini|php')
+ ->setSize('< 2M')
+ ->setPermission('>= 644');
+
+$files = Filesystem::find($path, $comparator, true);
+```
+
+## PathLocator & PathCollection
+
+See [PathLocator Document](Path)
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/AbstractFilesystemTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/AbstractFilesystemTest.php
new file mode 100644
index 00000000..e4e1bf70
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/AbstractFilesystemTest.php
@@ -0,0 +1,96 @@
+assertEquals('Wu-la', $name);
+
+ $name = File::stripExtension(__DIR__ . '/Wu-la.la');
+
+ $this->assertEquals(__DIR__ . '/Wu-la', $name);
+ }
+
+ /**
+ * Method to test getExtension().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\File::getExtension
+ */
+ public function testGetExtension()
+ {
+ $ext = File::getExtension('Wu-la.la');
+
+ $this->assertEquals('la', $ext);
+ }
+
+ /**
+ * Method to test getFilename().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\File::getFilename
+ */
+ public function testGetFilename()
+ {
+ $name = File::getFilename(__DIR__ . '/Wu-la.la');
+
+ $this->assertEquals('Wu-la.la', $name);
+ }
+
+ /**
+ * Provides the data to test the makeSafe method.
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function dataTestMakeSafe()
+ {
+ return array(
+ array(
+ 'windwalker.',
+ array('#^\.#'),
+ 'windwalker',
+ 'There should be no fullstop on the end of a filename',
+ ),
+ array(
+ 'Test w1ndwa1ker_5-1.html',
+ array('#^\.#'),
+ 'Test w1ndwa1ker_5-1.html',
+ 'Alphanumeric symbols, dots, dashes, spaces and underscores should not be filtered',
+ ),
+ array(
+ 'Test w1ndwa1ker_5-1.html',
+ array('#^\.#', '/\s+/'),
+ 'Testw1ndwa1ker_5-1.html',
+ 'Using strip chars parameter here to strip all spaces',
+ ),
+ array(
+ 'windwalker.php!.',
+ array('#^\.#'),
+ 'windwalker.php',
+ 'Non-alphanumeric symbols should be filtered to avoid disguising file extensions',
+ ),
+ array(
+ 'windwalker.php.!',
+ array('#^\.#'),
+ 'windwalker.php',
+ 'Non-alphanumeric symbols should be filtered to avoid disguising file extensions',
+ ),
+ array(
+ '.gitignore',
+ array(),
+ '.gitignore',
+ 'Files starting with a fullstop should be allowed when strip chars parameter is empty',
+ ),
+ );
+ }
+
+ /**
+ * Method to test makeSafe().
+ *
+ * @param string $name The name of the file to test filtering of
+ * @param array $stripChars Whether to filter spaces out the name or not
+ * @param string $expected The expected safe file name
+ * @param string $message The message to show on failure of test
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\File::makeSafe
+ *
+ * @dataProvider dataTestMakeSafe
+ */
+ public function testMakeSafe($name, $stripChars, $expected, $message)
+ {
+ $this->assertEquals(File::makeSafe($name, $stripChars), $expected, $message);
+ }
+
+ /**
+ * Method to test copy().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\File::copy
+ */
+ public function testCopy()
+ {
+ File::copy(static::$dest . '/folder1/level2/file3', static::$dest . '/folder2/level2/file4');
+
+ $this->assertFileExists(static::$dest . '/folder2/level2/file4');
+
+ // Copy force
+ File::copy(static::$dest . '/folder1/level2/file3', static::$dest . '/folder2/level2/file4', true);
+
+ $this->assertFileExists(static::$dest . '/folder2/level2/file4');
+ }
+
+ /**
+ * Method to test delete().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\File::delete
+ */
+ public function testDelete()
+ {
+ File::delete(static::$dest . '/folder1/path1');
+
+ $this->assertFileNotExists(static::$dest . '/folder1/path1');
+
+ try
+ {
+ File::delete(static::$dest . '/folder1/path2');
+ }
+ catch (FilesystemException $e)
+ {
+ $this->assertInstanceOf('Windwalker\\Filesystem\\Exception\\FilesystemException', $e);
+ }
+ }
+
+ /**
+ * Method to test move().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\File::move
+ */
+ public function testMove()
+ {
+ File::move(static::$dest . '/folder1/path1', static::$dest . '/folder2/level3/path2');
+
+ $this->assertFileExists(static::$dest . '/folder2/level3/path2');
+
+ // Move force
+ File::move(static::$dest . '/folder1/level2/file3', static::$dest . '/folder2/level3/path2', true);
+
+ $this->assertFileExists(static::$dest . '/folder2/level3/path2');
+ }
+
+ /**
+ * Method to test write().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\File::write
+ */
+ public function testWrite()
+ {
+ File::write(static::$dest . '/folder3/level2/test.txt', 'tmpFile');
+
+ $this->assertStringEqualsFile(static::$dest . '/folder3/level2/test.txt', 'tmpFile');
+ }
+
+ /**
+ * Method to test upload().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\File::upload
+ */
+ public function testUpload()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/FilesystemTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/FilesystemTest.php
new file mode 100644
index 00000000..6c975e24
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/FilesystemTest.php
@@ -0,0 +1,319 @@
+assertTrue(is_dir(static::$dest));
+ $this->assertFileExists(__DIR__ . '/dest/folder1/level2/file3');
+ }
+
+ /**
+ * Method to test move().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Filesystem::move
+ */
+ public function testMove()
+ {
+ $dest2 = __DIR__ . '/dest2';
+
+ if (is_dir($dest2))
+ {
+ Filesystem::delete($dest2);
+ }
+
+ Filesystem::move(static::$dest, $dest2);
+
+ $this->assertTrue(is_dir($dest2));
+ $this->assertFileExists($dest2 . '/folder1/level2/file3');
+
+ Filesystem::delete($dest2);
+ }
+
+ /**
+ * Method to test delete().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Filesystem::delete
+ */
+ public function testDelete()
+ {
+ Filesystem::delete(static::$dest);
+
+ $this->assertFalse(is_dir(static::$dest));
+ $this->assertFileNotExists(static::$dest . '/folder1/level2/file3');
+ }
+
+ /**
+ * Method to test files().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Filesystem::files
+ */
+ public function testFiles()
+ {
+ $files = Filesystem::files(__DIR__ . '/dest/folder1/level2', true, true);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths(array(__DIR__ . '/dest/folder1/level2/file3')),
+ FilesystemTestHelper::cleanPaths($files)
+ );
+
+ // Recursive
+ $files = Filesystem::files(static::$dest, true, true);
+
+ $compare = FilesystemTestHelper::getFilesRecursive('dest');
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths($compare),
+ FilesystemTestHelper::cleanPaths($files)
+ );
+
+ // Iterator
+ $files = Filesystem::files(static::$dest, true);
+
+ $this->assertInstanceOf('CallbackFilterIterator', $files);
+
+ $files2 = Filesystem::iteratorToArray($files);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths($compare),
+ FilesystemTestHelper::cleanPaths($files2)
+ );
+
+ $files->rewind();
+
+ $this->assertInstanceOf('SplFileinfo', $files->current());
+ }
+
+ /**
+ * Method to test folders().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Filesystem::folders
+ */
+ public function testFolders()
+ {
+ $folders = Filesystem::folders(static::$dest . '/folder1', true, true);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths(array(static::$dest . '/folder1/level2')),
+ FilesystemTestHelper::cleanPaths($folders)
+ );
+
+ // Recursive
+ $folders = Filesystem::folders(static::$dest, true, true);
+
+ $compare = FilesystemTestHelper::getFoldersRecursive('dest');
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths($compare),
+ FilesystemTestHelper::cleanPaths($folders)
+ );
+
+ // Iterator
+ $folders = Filesystem::folders(static::$dest, true);
+
+ $this->assertInstanceOf('CallbackFilterIterator', $folders);
+
+ $folders2 = Filesystem::iteratorToArray($folders);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths($compare),
+ FilesystemTestHelper::cleanPaths($folders2)
+ );
+
+ $folders->rewind();
+
+ $this->assertInstanceOf('SplFileinfo', $folders->current());
+ }
+
+ /**
+ * Method to test items().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Filesystem::items
+ */
+ public function testItems()
+ {
+ $items = Filesystem::items(static::$dest . '/folder1/level2', true, true);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths(array(static::$dest . '/folder1/level2/file3')),
+ FilesystemTestHelper::cleanPaths($items)
+ );
+
+ // Recursive
+ $items = Filesystem::items(static::$dest, true, true);
+
+ $compare = FilesystemTestHelper::getItemsRecursive('dest');
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths($compare),
+ FilesystemTestHelper::cleanPaths($items)
+ );
+
+ // Iterator
+ $items = Filesystem::items(static::$dest, true);
+
+ $this->assertInstanceOf('CallbackFilterIterator', $items);
+
+ $items2 = Filesystem::iteratorToArray($items);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths($compare),
+ FilesystemTestHelper::cleanPaths($items2)
+ );
+
+ $items->rewind();
+
+ $this->assertInstanceOf('SplFileinfo', $items->current());
+ }
+
+ /**
+ * Method to test findOne().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Filesystem::findOne
+ */
+ public function testFindOne()
+ {
+ // String condition
+ $file = Filesystem::findOne(static::$dest, 'file', true);
+ $files = Filesystem::find(static::$dest, 'file', true, true);
+
+ $this->assertEquals(
+ Path::clean((string) $files[0]),
+ Path::clean((string) $file)
+ );
+ }
+
+ /**
+ * Method to test find().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Filesystem::find
+ */
+ public function testFind()
+ {
+ // String condition
+ $files = Filesystem::find(static::$dest, 'file', true, true);
+
+ $expect1 = array(
+ __DIR__ . '/dest/file2.txt',
+ __DIR__ . '/dest/folder1/level2/file3',
+ __DIR__ . '/dest/folder2/file2.html',
+ );
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths($expect1),
+ FilesystemTestHelper::cleanPaths($files)
+ );
+
+ // Array condition
+ $files = Filesystem::find(static::$dest, array('file', 'path'), true, true);
+
+ $expect2 = array(
+ __DIR__ . '/dest/file2.txt',
+ __DIR__ . '/dest/folder1/level2/file3',
+ __DIR__ . '/dest/folder1/path1',
+ __DIR__ . '/dest/folder2/file2.html',
+ );
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths($expect2),
+ FilesystemTestHelper::cleanPaths($files)
+ );
+
+ // Callable condition
+ $condition = function ($current, $key, $iterator)
+ {
+ return pathinfo($current->getBasename(), PATHINFO_EXTENSION) == 'html';
+ };
+
+ $files = Filesystem::find(static::$dest, $condition, true, true);
+
+ $expect3 = array(
+ __DIR__ . '/dest/folder2/file2.html',
+ );
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths($expect3),
+ FilesystemTestHelper::cleanPaths($files)
+ );
+ }
+
+ /**
+ * Method to test findByCallback().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Filesystem::findByCallback
+ */
+ public function testFindByCallback()
+ {
+ $condition = function ($current, $key, $iterator)
+ {
+ return pathinfo($current->getBasename(), PATHINFO_EXTENSION) == 'html';
+ };
+
+ $files = Filesystem::find(static::$dest, $condition, true, true);
+
+ $expect3 = array(
+ __DIR__ . '/dest/folder2/file2.html',
+ );
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths($expect3),
+ FilesystemTestHelper::cleanPaths($files)
+ );
+ }
+
+ /**
+ * Method to test createIterator().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Filesystem::createIterator
+ */
+ public function testCreateIterator()
+ {
+ $this->assertInstanceOf('Windwalker\\Filesystem\\Iterator\\RecursiveDirectoryIterator', Filesystem::createIterator(static::$dest));
+ $this->assertInstanceOf('RecursiveIteratorIterator', Filesystem::createIterator(static::$dest, true));
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/FilesystemTestHelper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/FilesystemTestHelper.php
new file mode 100644
index 00000000..1aa409ad
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/FilesystemTestHelper.php
@@ -0,0 +1,106 @@
+ $path)
+ {
+ $paths[$key] = Path::clean($path);
+ }
+
+ sort($paths);
+
+ return $paths;
+ }
+
+ /**
+ * getFilesRescurive
+ *
+ * @param string $folder
+ *
+ * @return array
+ */
+ public static function getFilesRecursive($folder = 'dest')
+ {
+ return array(
+ __DIR__ . '/' . $folder . '/file2.txt',
+ __DIR__ . '/' . $folder . '/folder1/level2/file3',
+ __DIR__ . '/' . $folder . '/folder1/path1',
+ __DIR__ . '/' . $folder . '/folder2/file2.html'
+ );
+ }
+
+ /**
+ * getFilesRescurive
+ *
+ * @param string $folder
+ *
+ * @return array
+ */
+ public static function getFoldersRecursive($folder = 'dest')
+ {
+ return array (
+ __DIR__ . '/' . $folder . '/folder1',
+ __DIR__ . '/' . $folder . '/folder1/level2',
+ __DIR__ . '/' . $folder . '/folder2',
+ );
+ }
+
+ /**
+ * getFilesRescurive
+ *
+ * @param string $folder
+ *
+ * @return array
+ */
+ public static function getItemsRecursive($folder = 'dest')
+ {
+ return array (
+ __DIR__ . '/' . $folder . '/file2.txt',
+ __DIR__ . '/' . $folder . '/folder1',
+ __DIR__ . '/' . $folder . '/folder1/level2',
+ __DIR__ . '/' . $folder . '/folder1/level2/file3',
+ __DIR__ . '/' . $folder . '/folder1/path1',
+ __DIR__ . '/' . $folder . '/folder2',
+ __DIR__ . '/' . $folder . '/folder2/file2.html',
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/FolderTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/FolderTest.php
new file mode 100644
index 00000000..96e30156
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/FolderTest.php
@@ -0,0 +1,258 @@
+assertTrue(is_dir(static::$dest));
+ $this->assertFileExists(static::$dest . '/folder1/level2/file3');
+ }
+
+ /**
+ * Method to test create().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Folder::create
+ */
+ public function testCreate()
+ {
+ Folder::create(static::$dest . '/flower');
+
+ $this->assertTrue(is_dir(static::$dest . '/flower'));
+
+ Folder::create(static::$dest . '/foo/bar');
+
+ $this->assertTrue(is_dir(static::$dest . '/foo/bar'));
+
+ Folder::create(static::$dest . '/yoo', 0775);
+
+ if (TestEnvironment::isWindows())
+ {
+ $this->assertEquals(777, Path::getPermissions(static::$dest . '/yoo'));
+ }
+ else
+ {
+ $this->assertEquals(775, Path::getPermissions(static::$dest . '/yoo'));
+ }
+ }
+
+ /**
+ * Method to test delete().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Folder::delete
+ */
+ public function testDelete()
+ {
+ Folder::create(static::$dest . '/flower');
+
+ Folder::delete(static::$dest . '/flower');
+
+ $this->assertFalse(is_dir(static::$dest . '/flower'));
+ }
+
+ /**
+ * Method to test move().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Folder::move
+ */
+ public function testMove()
+ {
+ $dest2 = __DIR__ . '/dest2';
+
+ if (is_dir($dest2))
+ {
+ Folder::delete($dest2);
+ }
+
+ Folder::move(static::$dest, $dest2);
+
+ $this->assertTrue(is_dir($dest2));
+ $this->assertFileExists($dest2 . '/folder1/level2/file3');
+
+ Folder::delete($dest2);
+ }
+
+ /**
+ * Method to test files().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Folder::files
+ */
+ public function testFiles()
+ {
+ $files = Folder::files(__DIR__ . '/dest/folder1/level2', true);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths(array(__DIR__ . '/dest/folder1/level2/file3')),
+ FilesystemTestHelper::cleanPaths($files)
+ );
+
+ // No full name
+ $files = Folder::files(__DIR__ . '/dest/folder1/level2', true, Folder::PATH_BASENAME);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths(array('file3')),
+ FilesystemTestHelper::cleanPaths($files)
+ );
+
+ $files = Folder::files(__DIR__ . '/dest/folder1', true, Folder::PATH_RELATIVE);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths(array('level2/file3', 'path1')),
+ FilesystemTestHelper::cleanPaths($files)
+ );
+
+ // Recursive
+ $files = Folder::files(static::$dest, true);
+
+ $compare = FilesystemTestHelper::getFilesRecursive('dest');
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths($compare),
+ FilesystemTestHelper::cleanPaths($files)
+ );
+ }
+
+ /**
+ * Method to test items().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Folder::items
+ */
+ public function testItems()
+ {
+ $items = Folder::items(static::$dest . '/folder1/level2', true);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths(array(static::$dest . '/folder1/level2/file3')),
+ FilesystemTestHelper::cleanPaths($items)
+ );
+
+ // No full name
+ $items = Folder::items(static::$dest . '/folder1/level2', true, Folder::PATH_BASENAME);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths(array('file3')),
+ FilesystemTestHelper::cleanPaths($items)
+ );
+
+ // Recursive
+ $items = Folder::items(static::$dest, true, Folder::PATH_ABSOLUTE);
+
+ $compare = FilesystemTestHelper::getItemsRecursive('dest');
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths($compare),
+ FilesystemTestHelper::cleanPaths($items)
+ );
+ }
+
+ /**
+ * Method to test folders().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Folder::folders
+ */
+ public function testFolders()
+ {
+ $folders = Folder::folders(static::$dest . '/folder1', true);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths(array(static::$dest . '/folder1/level2')),
+ FilesystemTestHelper::cleanPaths($folders)
+ );
+
+ // No full name
+ $folders = Folder::folders(static::$dest . '/folder1', true, Folder::PATH_BASENAME);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths(array('level2')),
+ FilesystemTestHelper::cleanPaths($folders)
+ );
+
+ $folders = Folder::folders(static::$dest, true, Folder::PATH_RELATIVE);
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths(array('folder1', 'folder1/level2', 'folder2')),
+ FilesystemTestHelper::cleanPaths($folders)
+ );
+
+ // Recursive
+ $folders = Folder::folders(static::$dest, true, Folder::PATH_ABSOLUTE);
+
+ $compare = FilesystemTestHelper::getFoldersRecursive('dest');
+
+ $this->assertEquals(
+ FilesystemTestHelper::cleanPaths($compare),
+ FilesystemTestHelper::cleanPaths($folders)
+ );
+ }
+
+ /**
+ * Method to test listFolderTree().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Folder::listFolderTree
+ */
+ public function testListFolderTree()
+ {
+ $tree = Folder::listFolderTree(static::$dest);
+
+ $this->assertEquals($tree[0]['relative'], 'folder1');
+ $this->assertEquals($tree[1]['parent'], 1);
+ $this->assertEquals($tree[1]['relative'], 'folder1' . DIRECTORY_SEPARATOR . 'level2');
+ $this->assertEquals($tree[2]['fullname'], Path::clean(static::$dest . '/folder2'));
+ }
+
+ /**
+ * Method to test makeSafe().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Folder::makeSafe
+ */
+ public function testMakeSafe()
+ {
+ $safe = Folder::makeSafe('fo_o/bar 2/yo-o.o/三杯雞 go:to:fly.ing');
+
+ $this->assertEquals('fo_o/bar2/yo-o.o/gotofly.ing', $safe);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/PathCollectionTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/PathCollectionTest.php
new file mode 100644
index 00000000..b93cf705
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/PathCollectionTest.php
@@ -0,0 +1,498 @@
+collection = new PathCollection();
+ }
+
+ /**
+ * Data provider for testClean() method.
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function getPathData()
+ {
+ return array(
+ // Input Path, Directory Separator, Expected Output
+ 'one path' => array(
+ '/var/www/foo/bar',
+ array(new PathLocator('/var/www/foo/bar'))
+ ),
+
+ 'paths with on key' => array(
+ array(
+ '/',
+ '/var/www/foo/bar',
+ '/var/www/windwalker/bar/foo'
+ ),
+ array(
+ new PathLocator('/'),
+ new PathLocator('/var/www/foo/bar'),
+ new PathLocator('/var/www/windwalker/bar/foo')
+ )
+ ),
+
+ 'paths with key' => array(
+ array(
+ 'root' => '/',
+ 'foo' => '/var/www/foo'
+ ),
+ array(
+ 'root' => new PathLocator('/'),
+ 'foo' => new PathLocator('/var/www/foo')
+ )
+ )
+ );
+ }
+
+ /**
+ * Data provider for testClean() method.
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function getIteratorData()
+ {
+ return array(
+ 'no rescurive' => array(
+ array(
+ __DIR__ . '/files/folder1',
+ __DIR__ . '/files/folder2'
+ ),
+
+ array(
+ Path::clean(__DIR__ . '/files/folder1'),
+ Path::clean(__DIR__ . '/files/folder2')
+ ),
+
+ false
+ ),
+ /*
+ 'rescurive' => array(
+ array(
+ __DIR__ . 'files'
+ ),
+
+ array(
+ Path::clean(__DIR__ . 'files/folder1'),
+ Path::clean(__DIR__ . 'files/folder1/file1'),
+ Path::clean(__DIR__ . 'files/folder2/file2.html'),
+ Path::clean(__DIR__ . 'files/file2.txt')
+ ),
+
+ true
+ )
+ */
+ );
+ }
+
+ /**
+ * name description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string nameReturn
+ *
+ * @since 2.0
+ */
+ public function getIteratorRecursiveData()
+ {
+ return array(
+ 'no rescurive' => array(
+ array(
+ __DIR__ . '/files/folder1',
+ __DIR__ . '/files/folder2',
+ __DIR__ . '/files/file2.txt',
+ ),
+
+ array(
+ Path::clean(__DIR__ . '/files/folder1'),
+ Path::clean(__DIR__ . '/files/folder2')
+ ),
+
+ false
+ ),
+
+ 'rescurive' => array(
+ array(
+ __DIR__ . '/files'
+ ),
+
+ array(
+ Path::clean(__DIR__ . '/files/folder1'),
+ Path::clean(__DIR__ . '/files/folder1/path1'),
+ Path::clean(__DIR__ . '/files/folder2/file2.html'),
+ Path::clean(__DIR__ . '/files/file2.txt')
+ ),
+
+ true
+ )
+ );
+ }
+
+ /**
+ * test__construct description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string test__constructReturn
+ *
+ * @since 2.0
+ */
+ public function test__construct()
+ {
+ $collections = new PathCollection('/var/www/foo/bar');
+
+ $paths = $collections->getPaths();
+
+ $this->assertEquals(array(new PathLocator('/var/www/foo/bar')), $paths);
+ }
+
+ /**
+ * testAddPaths description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string testAddPathsReturn
+ *
+ * @dataProvider getPathData
+ *
+ * @since 2.0
+ */
+ public function testAddPaths($paths, $expects)
+ {
+ $this->collection->addPaths($paths);
+
+ $paths = $this->collection->getPaths();
+
+ $this->assertEquals($paths, $expects);
+ }
+
+ /**
+ * addPath description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string addPathReturn
+ *
+ * @since 2.0
+ */
+ public function testAddPath()
+ {
+ $path = new PathLocator('/var/foo/bar');
+
+ $this->collection->addPath($path, 'bar');
+
+ $this->assertEquals($path, $this->collection->getPath('bar'));
+ }
+
+ /**
+ * removePath description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string removePathReturn
+ *
+ * @since 2.0
+ */
+ public function testRemovePath()
+ {
+ $path = new PathLocator('/var/foo/bar');
+
+ $this->collection->addPath($path, 'bar');
+
+ $this->collection->removePath('bar');
+
+ $path = $this->collection->getPath('bar');
+
+ $this->assertNull($path);
+ }
+
+ /**
+ * getPaths description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string getPathsReturn
+ *
+ * @dataProvider getPathData
+ *
+ * @since 2.0
+ */
+ public function testGetPaths($paths, $expects)
+ {
+ $this->setUp();
+
+ $this->collection->addPaths($paths);
+
+ $paths = $this->collection->getPaths();
+
+ $this->assertEquals($paths, $expects);
+ }
+
+ /**
+ * getPath description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string getPathReturn
+ *
+ * @since 2.0
+ */
+ public function testGetPath()
+ {
+ $path = new PathLocator('/var/foo/bar2');
+
+ $this->collection->addPath($path, 'bar2');
+
+ $this->assertEquals($path, $this->collection->getPath('bar2'));
+
+ $this->assertEquals(new PathLocator('/'), $this->collection->getPath('bar3', '/'));
+ }
+
+ /**
+ * getIterator description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string getIteratorReturn
+ *
+ * @dataProvider getIteratorData
+ *
+ * @since 2.0
+ */
+ public function testGetIterator($paths, $expects, $rescursive)
+ {
+ $this->setUp();
+
+ $this->collection->addPaths($paths);
+
+ $iterator = $this->collection;
+
+ $compare = array();
+
+ foreach($iterator as $file)
+ {
+ $compare[] = (string) $file;
+ }
+
+ $this->assertEquals($compare, $expects);
+ }
+
+ /**
+ * testDiresctoryIterator description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string testDiresctoryIteratorReturn
+ *
+ * @since 2.0
+ */
+ public function testGetDiresctoryIterator()
+ {
+ $this->markTestIncomplete();
+ }
+
+ /**
+ * setPrefix description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string setPrefixReturn
+ *
+ * @since 2.0
+ */
+ public function testSetPrefix()
+ {
+ $this->setUp();
+
+ $this->collection->addPath('windwalker/dir/foo/bar', 'foo');
+ $this->collection->addPath('windwalker/dir/yoo/hoo', 'yoo');
+
+ $this->collection->setPrefix('/var/www');
+
+ $expects = array(
+ Path::clean('/var/www/windwalker/dir/foo/bar'),
+ Path::clean('/var/www/windwalker/dir/yoo/hoo'),
+ );
+
+ $paths = array(
+ (string) $this->collection->getPath('foo'),
+ (string) $this->collection->getPath('yoo')
+ );
+
+ $this->assertEquals($paths, $expects);
+ }
+
+ /**
+ * find description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string findReturn
+ *
+ * @since 2.0
+ */
+ public function find()
+ {
+
+ }
+
+ /**
+ * findAll description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string findAllReturn
+ *
+ * @since 2.0
+ */
+ public function findAll()
+ {
+
+ }
+
+ /**
+ * toArray description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string toArrayReturn
+ *
+ * @since 2.0
+ */
+ public function toArray()
+ {
+
+ }
+
+ /**
+ * getFiles description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string getFilesReturn
+ *
+ * @since 2.0
+ */
+ public function getFiles($rescursive = false)
+ {
+
+ }
+
+ /**
+ * getFolders description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string getFoldersReturn
+ *
+ * @since 2.0
+ */
+ public function getFolders($rescursive)
+ {
+
+ }
+
+ /**
+ * appendAll description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string appendAllReturn
+ *
+ * @since 2.0
+ */
+ public function appendAll()
+ {
+
+ }
+
+ /**
+ * prependAll description
+ *
+ * @param string
+ * @param string
+ * @param string
+ *
+ * @return string prependAllReturn
+ *
+ * @since 2.0
+ */
+ public function prependAll()
+ {
+
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/PathTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/PathTest.php
new file mode 100644
index 00000000..7467c32b
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/PathTest.php
@@ -0,0 +1,141 @@
+ array('/var/www/foo/bar/baz', '/', '/var/www/foo/bar/baz'),
+ 'One backslash.' => array('/var/www/foo\\bar/baz', '/', '/var/www/foo/bar/baz'),
+ 'Two and one backslashes.' => array('/var/www\\\\foo\\bar/baz', '/', '/var/www/foo/bar/baz'),
+ 'Mixed backslashes and double forward slashes.' => array('/var\\/www//foo\\bar/baz', '/', '/var/www/foo/bar/baz'),
+ 'UNC path.' => array('\\\\www\\docroot', '\\', '\\\\www\\docroot'),
+ 'UNC path with forward slash.' => array('\\\\www/docroot', '\\', '\\\\www\\docroot'),
+ 'UNC path with UNIX directory separator.' => array('\\\\www/docroot', '/', '/www/docroot'),
+ );
+ }
+
+ /**
+ * Method to test canChmod().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Path::canChmod
+ * @TODO Implement testCanChmod().
+ */
+ public function testCanChmod()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setPermissions().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Path::setPermissions
+ * @TODO Implement testSetPermissions().
+ */
+ public function testSetPermissions()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getPermissions().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Path::getPermissions
+ * @TODO Implement testGetPermissions().
+ */
+ public function testGetPermissions()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test check().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Path::check
+ * @TODO Implement testCheck().
+ */
+ public function testCheck()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test clean().
+ *
+ * @param string $input
+ * @param string $ds
+ * @param string $expected
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Path::clean
+ *
+ * @dataProvider getCleanData
+ */
+ public function testClean($input, $ds, $expected)
+ {
+ $this->assertEquals(
+ $expected,
+ Path::clean($input, $ds)
+ );
+ }
+
+ /**
+ * Method to test find().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Filesystem\Path::find
+ * @TODO Implement testFind().
+ */
+ public function testFind()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/files/file2.txt b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/files/file2.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/files/folder1/level2/file3 b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/files/folder1/level2/file3
new file mode 100644
index 00000000..e69de29b
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/files/folder1/path1 b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/files/folder1/path1
new file mode 100644
index 00000000..e69de29b
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/files/folder2/file2.html b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/Test/files/folder2/file2.html
new file mode 100644
index 00000000..e69de29b
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/composer.json b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/composer.json
new file mode 100644
index 00000000..3fccbe8d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/composer.json
@@ -0,0 +1,25 @@
+{
+ "name": "windwalker/filesystem",
+ "type": "windwalker-package",
+ "description": "Windwalker Filesystem package",
+ "keywords": ["windwalker", "framework", "filesystem"],
+ "homepage": "https://github.com/ventoviro/windwalker-filesystem",
+ "license": "LGPL-2.0+",
+ "require": {
+ "php": ">=5.3.10"
+ },
+ "require-dev": {
+ "windwalker/test": "~2.0"
+ },
+ "minimum-stability": "beta",
+ "autoload": {
+ "psr-4": {
+ "Windwalker\\Filesystem\\": ""
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/phpunit.travis.xml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/phpunit.travis.xml
new file mode 100644
index 00000000..690ec926
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/filesystem/phpunit.travis.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/.gitignore b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/.gitignore
new file mode 100644
index 00000000..84718b5d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/.gitignore
@@ -0,0 +1,11 @@
+# Development system files #
+.*
+!/.gitignore
+!/.travis.yml
+
+# Composer #
+vendor/*
+composer.lock
+
+# Test #
+phpunit.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/.travis.yml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/.travis.yml
new file mode 100644
index 00000000..5420e5c4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/.travis.yml
@@ -0,0 +1,16 @@
+language: php
+
+sudo: false
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+
+before_script:
+ - composer update --dev
+
+script:
+ - phpunit --configuration phpunit.travis.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Enum/AbstractHtmlList.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Enum/AbstractHtmlList.php
new file mode 100644
index 00000000..e7419202
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Enum/AbstractHtmlList.php
@@ -0,0 +1,84 @@
+name, null, $attribs);
+
+ $this->setItems((array) $items);
+ }
+
+ /**
+ * Quick create for PHP 5.3
+ *
+ * @param array $attribs
+ *
+ * @return static
+ */
+ public static function create($attribs = array())
+ {
+ return new static($attribs);
+ }
+
+ /**
+ * addItem
+ *
+ * @param ListItem|string $item
+ * @param array $attribs
+ *
+ * @return static
+ */
+ public function addItem($item, $attribs = array())
+ {
+ if (!$item instanceof ListItem)
+ {
+ $item = new ListItem($item, $attribs);
+ }
+
+ $this->content[] = $item;
+
+ return $this;
+ }
+
+ /**
+ * setItems
+ *
+ * @param ListItem[] $items
+ *
+ * @return static
+ */
+ public function setItems(array $items)
+ {
+ $this->content = new HtmlElements;
+
+ foreach ($items as $item)
+ {
+ $this->addItem($item);
+ }
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Enum/DList.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Enum/DList.php
new file mode 100644
index 00000000..70a11b01
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Enum/DList.php
@@ -0,0 +1,104 @@
+addTitle($title, $titleAttribs)
+ ->addDesc($description, $descAttribs);
+
+ return $this;
+ }
+
+ /**
+ * addItem
+ *
+ * @param DListDescription|string $item
+ * @param array $attribs
+ *
+ * @return static
+ */
+ public function addDesc($item, $attribs = array())
+ {
+ if (!$item instanceof DListDescription)
+ {
+ $item = new DListDescription($item, $attribs);
+ }
+
+ $this->content[] = $item;
+
+ return $this;
+ }
+
+ /**
+ * addItem
+ *
+ * @param DListTitle|string $item
+ * @param array $attribs
+ *
+ * @return static
+ */
+ public function addTitle($item, $attribs = array())
+ {
+ if (!$item instanceof DListTitle)
+ {
+ $item = new DListTitle($item, $attribs);
+ }
+
+ $this->content[] = $item;
+
+ return $this;
+ }
+
+ /**
+ * addItem
+ *
+ * @param DListTitle|string $item
+ * @param array $attribs
+ *
+ * @return static
+ */
+ public function addItem($item, $attribs = array())
+ {
+ if ($item instanceof DListTitle)
+ {
+ $this->addTitle($item);
+ }
+ else
+ {
+ $this->addDesc($item, $attribs);
+ }
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Enum/DListDescription.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Enum/DListDescription.php
new file mode 100644
index 00000000..89d49e2f
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Enum/DListDescription.php
@@ -0,0 +1,30 @@
+name($name)
+ ->setAttribute('id', $name)
+ ->method($method)
+ ->action($action)
+ ->enctype($enctype);
+
+ foreach ($attribs as $key => $value)
+ {
+ $form->setAttribute($key, $value);
+ }
+
+ return $form->renderStart();
+ }
+
+ /**
+ * end
+ *
+ * @return string
+ */
+ public static function end()
+ {
+ return static::getToken() . '';
+ }
+
+ /**
+ * renderStart
+ *
+ * @return string
+ */
+ public function renderStart()
+ {
+ $html = $this->toString(true);
+
+ return substr($html, 0, -7);
+ }
+
+ /**
+ * renderEnd
+ *
+ * @return string
+ */
+ public function renderEnd()
+ {
+ return static::end();
+ }
+
+ /**
+ * getToken
+ *
+ * @return string
+ */
+ public static function getToken()
+ {
+ if (static::$tokenHandler)
+ {
+ return call_user_func(static::$tokenHandler);
+ }
+
+ return '';
+ }
+
+ /**
+ * acceptCharset
+ *
+ * @param string $value
+ *
+ * @return static
+ */
+ public function acceptCharset($value)
+ {
+ $this->attribs['accept-charset'] = $value;
+
+ return $this;
+ }
+
+ /**
+ * action
+ *
+ * @param string $value
+ *
+ * @return static
+ */
+ public function action($value)
+ {
+ $this->attribs['action'] = $value;
+
+ return $this;
+ }
+
+ /**
+ * autocomplete
+ *
+ * @param string $value
+ *
+ * @return static
+ */
+ public function autocomplete($value)
+ {
+ $this->attribs['autocomplete'] = $value;
+
+ return $this;
+ }
+
+ /**
+ * enctype
+ *
+ * @param string $value
+ *
+ * @return static
+ */
+ public function enctype($value)
+ {
+ $this->attribs['enctype'] = $value;
+
+ return $this;
+ }
+
+ /**
+ * method
+ *
+ * @param string $value
+ *
+ * @return static
+ */
+ public function method($value)
+ {
+ $this->attribs['method'] = $value;
+
+ return $this;
+ }
+
+ /**
+ * name
+ *
+ * @param string $value
+ *
+ * @return static
+ */
+ public function name($value)
+ {
+ $this->attribs['name'] = $value;
+
+ return $this;
+ }
+
+ /**
+ * novalidate
+ *
+ * @param string $value
+ *
+ * @return static
+ */
+ public function novalidate($value)
+ {
+ $value = (bool) $value;
+
+ $this->attribs['novalidate'] = $value ? 'novalidate' : null;
+
+ return $this;
+ }
+
+ /**
+ * target
+ *
+ * @param string $value
+ *
+ * @return static
+ */
+ public function target($value)
+ {
+ $this->attribs['target'] = $value;
+
+ return $this;
+ }
+
+ /**
+ * accept
+ *
+ * @param string $value
+ *
+ * @return static
+ */
+ public function accept($value)
+ {
+ $this->attribs['accept'] = $value;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property TokenHandler
+ *
+ * @return string
+ */
+ public static function getTokenHandler()
+ {
+ return static::$tokenHandler;
+ }
+
+ /**
+ * Method to set property tokenHandler
+ *
+ * @param string $tokenHandler
+ *
+ * @return static Return self to support chaining.
+ */
+ public static function setTokenHandler($tokenHandler)
+ {
+ if ($tokenHandler !== null && !is_callable($tokenHandler))
+ {
+ throw new \InvalidArgumentException('Tokan handler not callable.');
+ }
+
+ static::$tokenHandler = $tokenHandler;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Form/InputElement.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Form/InputElement.php
new file mode 100644
index 00000000..8d801e82
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Form/InputElement.php
@@ -0,0 +1,36 @@
+ array(), 'footer' => array());
+
+ /**
+ * Associative array of attributes for the table-tag
+ * @var array
+ */
+ protected $options;
+
+ /**
+ * Constructor for a Grid object
+ *
+ * @param array $options Associative array of attributes for the table-tag
+ *
+ * @since 2.1
+ */
+ public function __construct($options = array())
+ {
+ $this->setTableOptions($options, true);
+ }
+
+ /**
+ * create
+ *
+ * @param array $options
+ *
+ * @return static
+ */
+ public static function create($options = array())
+ {
+ return new static($options);
+ }
+
+ /**
+ * Magic function to render this object as a table.
+ *
+ * @return string
+ *
+ * @since 2.1
+ */
+ public function __toString()
+ {
+ try
+ {
+ return $this->toString();
+ }
+ catch (\Exception $e)
+ {
+ return (string) $e;
+ }
+ }
+
+ /**
+ * Method to set the attributes for a table-tag
+ *
+ * @param array $options Associative array of attributes for the table-tag
+ * @param bool $replace Replace possibly existing attributes
+ *
+ * @return static This object for chaining
+ *
+ * @since 2.1
+ */
+ public function setTableOptions($options = array(), $replace = false)
+ {
+ if ($replace)
+ {
+ $this->options = $options;
+ }
+ else
+ {
+ $this->options = array_merge($this->options, $options);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the Attributes of the current table
+ *
+ * @return array Associative array of attributes
+ *
+ * @since 2.1
+ */
+ public function getTableOptions()
+ {
+ return $this->options;
+ }
+
+ /**
+ * Add new column name to process
+ *
+ * @param string $name Internal column name
+ *
+ * @return static This object for chaining
+ *
+ * @since 2.1
+ */
+ public function addColumn($name)
+ {
+ $this->columns[] = $name;
+
+ return $this;
+ }
+
+ /**
+ * Returns the list of internal columns
+ *
+ * @return array List of internal columns
+ *
+ * @since 2.1
+ */
+ public function getColumns()
+ {
+ return $this->columns;
+ }
+
+ /**
+ * Delete column by name
+ *
+ * @param string $name Name of the column to be deleted
+ *
+ * @return static This object for chaining
+ *
+ * @since 2.1
+ */
+ public function deleteColumn($name)
+ {
+ $index = array_search($name, $this->columns);
+
+ if ($index !== false)
+ {
+ unset($this->columns[$index]);
+ $this->columns = array_values($this->columns);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Method to set a whole range of columns at once
+ * This can be used to re-order the columns, too
+ *
+ * @param array $columns List of internal column names
+ *
+ * @return static This object for chaining
+ *
+ * @since 2.1
+ */
+ public function setColumns($columns)
+ {
+ $this->columns = array_values($columns);
+
+ return $this;
+ }
+
+ /**
+ * Adds a row to the table and sets the currently
+ * active row to the new row
+ *
+ * @param array $options Associative array of attributes for the row
+ * @param int|bool $special 1 for a new row in the header, 2 for a new row in the footer
+ *
+ * @return static This object for chaining
+ *
+ * @since 2.1
+ */
+ public function addRow($options = array(), $special = self::ROW_NORMAL)
+ {
+ $this->rows[]['_row'] = $options;
+ $this->activeRow = count($this->rows) - 1;
+
+ if ($special)
+ {
+ if ($special === static::ROW_HEAD)
+ {
+ $this->specialRows['header'][] = $this->activeRow;
+ }
+ elseif ($special === static::ROW_FOOT)
+ {
+ $this->specialRows['footer'][] = $this->activeRow;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Method to get the attributes of the currently active row
+ *
+ * @return array Associative array of attributes
+ *
+ * @since 2.1
+ */
+ public function getRowOptions()
+ {
+ return $this->rows[$this->activeRow]['_row'];
+ }
+
+ /**
+ * Method to set the attributes of the currently active row
+ *
+ * @param array $options Associative array of attributes
+ *
+ * @return static This object for chaining
+ *
+ * @since 2.1
+ */
+ public function setRowOptions($options)
+ {
+ $this->rows[$this->activeRow]['_row'] = $options;
+
+ return $this;
+ }
+
+ /**
+ * Get the currently active row ID
+ *
+ * @return int ID of the currently active row
+ *
+ * @since 2.1
+ */
+ public function getActiveRow()
+ {
+ return $this->activeRow;
+ }
+
+ /**
+ * Set the currently active row
+ *
+ * @param int $id ID of the row to be set to current
+ *
+ * @return static This object for chaining
+ *
+ * @since 2.1
+ */
+ public function setActiveRow($id)
+ {
+ $this->activeRow = (int) $id;
+
+ return $this;
+ }
+
+ /**
+ * Set cell content for a specific column for the
+ * currently active row
+ *
+ * @param string $name Name of the column
+ * @param string $content Content for the cell
+ * @param array $option Associative array of attributes for the td-element
+ * @param bool $replace If false, the content is appended to the current content of the cell
+ *
+ * @return static This object for chaining
+ *
+ * @since 2.1
+ */
+ public function setRowCell($name, $content, $option = array(), $replace = true)
+ {
+ if ($replace || !isset($this->rows[$this->activeRow][$name]))
+ {
+ $cell = new \stdClass;
+ $cell->options = $option;
+ $cell->content = $content;
+ $this->rows[$this->activeRow][$name] = $cell;
+ }
+ else
+ {
+ $this->rows[$this->activeRow][$name]->content .= $content;
+ $this->rows[$this->activeRow][$name]->options = $option;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get all data for a row
+ *
+ * @param int|bool $id ID of the row to return
+ *
+ * @return array Array of columns of a table row
+ *
+ * @since 2.1
+ */
+ public function getRow($id = false)
+ {
+ if ($id === false)
+ {
+ $id = $this->activeRow;
+ }
+
+ if (isset($this->rows[(int) $id]))
+ {
+ return $this->rows[(int) $id];
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Get the IDs of all rows in the table
+ *
+ * @param int|bool $special false for the standard rows, 1 for the header rows, 2 for the footer rows
+ *
+ * @return array Array of IDs
+ *
+ * @since 2.1
+ */
+ public function getRows($special = false)
+ {
+ if ($special)
+ {
+ if ($special === 1)
+ {
+ return $this->specialRows['header'];
+ }
+ else
+ {
+ return $this->specialRows['footer'];
+ }
+ }
+
+ return array_diff(array_keys($this->rows), array_merge($this->specialRows['header'], $this->specialRows['footer']));
+ }
+
+ /**
+ * Delete a row from the object
+ *
+ * @param int $id ID of the row to be deleted
+ *
+ * @return static This object for chaining
+ *
+ * @since 2.1
+ */
+ public function deleteRow($id)
+ {
+ unset($this->rows[$id]);
+
+ if (in_array($id, $this->specialRows['header']))
+ {
+ unset($this->specialRows['header'][array_search($id, $this->specialRows['header'])]);
+ }
+
+ if (in_array($id, $this->specialRows['footer']))
+ {
+ unset($this->specialRows['footer'][array_search($id, $this->specialRows['footer'])]);
+ }
+
+ if ($this->activeRow == $id)
+ {
+ end($this->rows);
+ $this->activeRow = key($this->rows);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Render the HTML table
+ *
+ * @return string The rendered HTML table
+ *
+ * @since 2.1
+ */
+ public function toString()
+ {
+ $output = array();
+ $output[] = 'renderAttributes($this->getTableOptions()) . '>';
+
+ if (count($this->specialRows['header']))
+ {
+ $output[] = $this->renderArea($this->specialRows['header'], 'thead', 'th');
+ }
+
+ if (count($this->specialRows['footer']))
+ {
+ $output[] = $this->renderArea($this->specialRows['footer'], 'tfoot');
+ }
+
+ $ids = array_diff(array_keys($this->rows), array_merge($this->specialRows['header'], $this->specialRows['footer']));
+
+ if (count($ids))
+ {
+ $output[] = $this->renderArea($ids);
+ }
+
+ $output[] = '
';
+
+ return implode('', $output);
+ }
+
+ /**
+ * Render an area of the table
+ *
+ * @param array $ids IDs of the rows to render
+ * @param string $area Name of the area to render. Valid: tbody, tfoot, thead
+ * @param string $cell Name of the cell to render. Valid: td, th
+ *
+ * @return string The rendered table area
+ *
+ * @since 2.1
+ */
+ protected function renderArea($ids, $area = 'tbody', $cell = 'td')
+ {
+ $output = array();
+ $output[] = '<' . $area . ">\n";
+
+ foreach ($ids as $id)
+ {
+ $output[] = "\trenderAttributes($this->rows[$id]['_row']) . ">\n";
+
+ foreach ($this->getColumns() as $name)
+ {
+ if (isset($this->rows[$id][$name]))
+ {
+ $column = $this->rows[$id][$name];
+ $output[] = "\t\t<" . $cell . $this->renderAttributes($column->options) . '>' . $column->content . '' . $cell . ">\n";
+ }
+ }
+
+ $output[] = "\t \n";
+ }
+
+ $output[] = '' . $area . '>';
+
+ return implode('', $output);
+ }
+
+ /**
+ * Renders an HTML attribute from an associative array
+ *
+ * @param array $attributes Associative array of attributes
+ *
+ * @return string The HTML attribute string
+ *
+ * @since 2.1
+ */
+ protected function renderAttributes($attributes)
+ {
+ if (count((array) $attributes) == 0)
+ {
+ return '';
+ }
+
+ $return = array();
+
+ foreach ($attributes as $key => $option)
+ {
+ $return[] = $key . '="' . $option . '"';
+ }
+
+ return ' ' . implode(' ', $return);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Grid/KeyValueGrid.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Grid/KeyValueGrid.php
new file mode 100644
index 00000000..da4d272a
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Grid/KeyValueGrid.php
@@ -0,0 +1,172 @@
+setColumns(array(static::COL_KEY, static::COL_VALUE));
+ }
+
+ /**
+ * addHeader
+ *
+ * @param string $keyTitle
+ * @param string $valueTitle
+ * @param array $options
+ *
+ * @return static
+ */
+ public function addHeader($keyTitle = 'Key', $valueTitle = 'Value', $options = array())
+ {
+ $this->addRow((array) $this->getValue($options, static::ROW), static::ROW_HEAD)
+ ->setRowCell(static::COL_KEY, $keyTitle, (array) $this->getValue($options, static::COL_KEY))
+ ->setRowCell(static::COL_VALUE, $valueTitle, (array) $this->getValue($options, static::COL_VALUE));
+
+ return $this;
+ }
+
+ /**
+ * addItem
+ *
+ * @param string $key
+ * @param string $value
+ * @param array $options
+ *
+ * @return static
+ */
+ public function addItem($key, $value = null, $options = array())
+ {
+ if (is_array($value))
+ {
+ $value = print_r($value, 1);
+ }
+
+ $this->addRow((array) $this->getValue($options, static::ROW))
+ ->setRowCell(static::COL_KEY, $key, (array) $this->getValue($options, static::COL_KEY));
+
+ if ($value !== false)
+ {
+ $this->setRowCell(static::COL_VALUE, $value, (array) $this->getValue($options, static::COL_VALUE));
+ }
+
+ return $this;
+ }
+
+ /**
+ * addItems
+ *
+ * @param string $items
+ * @param array $options
+ *
+ * @return static
+ */
+ public function addItems($items = null, $options = array())
+ {
+ $this->configure($items, function(KeyValueGrid $grid, $key, $value) use ($options)
+ {
+ $grid->addItem($key, $value, $options);
+ });
+
+ return $this;
+ }
+
+ /**
+ * addTitle
+ *
+ * @param string $name
+ * @param array $options
+ *
+ * @return static
+ */
+ public function addTitle($name, $options = array())
+ {
+ $options[static::COL_KEY]['colspan'] = 2;
+
+ $this->addItem($name, false, $options);
+
+ return $this;
+ }
+
+ /**
+ * configureRows
+ *
+ * @param array $items
+ * @param callable $handler
+ *
+ * @return static
+ */
+ public function configure($items, $handler)
+ {
+ if (!is_callable($handler))
+ {
+ throw new \InvalidArgumentException(__METHOD__ . ' Handler should be callable.');
+ }
+
+ if (!$items instanceof \Traversable && !is_array($items))
+ {
+ throw new \InvalidArgumentException(__METHOD__ . ' items should be array or iterator.');
+ }
+
+ foreach ($items as $key => $item)
+ {
+ call_user_func($handler, $this, $key, $item);
+ }
+
+ return $this;
+ }
+
+ /**
+ * getValue
+ *
+ * @param array $options
+ * @param string $name
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ protected function getValue(array $options, $name, $default = null)
+ {
+ if (isset($options[$name]))
+ {
+ return $options[$name];
+ }
+
+ return $default;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Helper/HtmlHelper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Helper/HtmlHelper.php
new file mode 100644
index 00000000..c6aa02b7
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Helper/HtmlHelper.php
@@ -0,0 +1,134 @@
+ true,
+ 'output-xhtml' => true,
+ 'show-body-only' => true,
+ 'wrap' => false
+ );
+
+ return tidy_repair_string($html, $TidyConfig, 'utf8');
+ }
+ else
+ {
+ $arr_single_tags = array('meta', 'img', 'br', 'link', 'area');
+
+ // Put all opened tags into an array
+ preg_match_all("#<([a-z]+)( .*)?(?!/)>#iU", $html, $result);
+ $openedtags = $result[1];
+
+ // Put all closed tags into an array
+ preg_match_all("#([a-z]+)>#iU", $html, $result);
+
+ $closedtags = $result[1];
+ $len_opened = count($openedtags);
+
+ // All tags are closed
+ if (count($closedtags) == $len_opened)
+ {
+ return $html;
+ }
+
+ $openedtags = array_reverse($openedtags);
+
+ // Close tags
+ for ($i = 0; $i < $len_opened; $i++)
+ {
+ if (!in_array($openedtags[$i], $closedtags))
+ {
+ if (!in_array($openedtags[$i], $arr_single_tags))
+ {
+ $html .= "" . $openedtags[$i] . ">";
+ }
+ }
+ else
+ {
+ unset ($closedtags[array_search($openedtags[$i], $closedtags)]);
+ }
+ }
+
+ return $html;
+ }
+ }
+
+ /**
+ * Internal method to get a JavaScript object notation string from an array
+ *
+ * @param array $array The array to convert to JavaScript object notation
+ *
+ * @return string JavaScript object notation representation of the array
+ */
+ public static function getJSObject(array $array = array())
+ {
+ $elements = array();
+
+ foreach ($array as $k => $v)
+ {
+ // Don't encode either of these types
+ if (is_null($v) || is_resource($v))
+ {
+ continue;
+ }
+
+ // Safely encode as a Javascript string
+ $key = json_encode((string) $k);
+
+ if (is_bool($v))
+ {
+ $elements[] = $key . ': ' . ($v ? 'true' : 'false');
+ }
+ elseif (is_numeric($v))
+ {
+ $elements[] = $key . ': ' . ($v + 0);
+ }
+ elseif (is_string($v))
+ {
+ if (strpos($v, '\\') === 0)
+ {
+ // Items such as functions and JSON objects are prefixed with \, strip the prefix and don't encode them
+ $elements[] = $key . ': ' . substr($v, 1);
+ }
+ else
+ {
+ // The safest way to insert a string
+ $elements[] = $key . ': ' . json_encode((string) $v);
+ }
+ }
+ else
+ {
+ $elements[] = $key . ': ' . static::getJSObject(is_object($v) ? get_object_vars($v) : $v);
+ }
+ }
+
+ return '{' . implode(',', $elements) . '}';
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Media/AbstractMediaElement.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Media/AbstractMediaElement.php
new file mode 100644
index 00000000..104ce57f
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Media/AbstractMediaElement.php
@@ -0,0 +1,213 @@
+name, null, $attribs);
+
+ $this->content = new HtmlElements;
+ }
+
+ /**
+ * Quick create for PHP 5.3
+ *
+ * @param array $attribs
+ *
+ * @return static
+ */
+ public static function create($attribs = array())
+ {
+ return new static($attribs);
+ }
+
+ /**
+ * toString
+ *
+ * @param boolean $forcePair
+ *
+ * @return string
+ */
+ public function toString($forcePair = false)
+ {
+ $content = $this->content;
+
+ $content = $content . $this->hint;
+
+ return HtmlBuilder::create($this->name, $content, $this->attribs, $forcePair);
+ }
+
+ /**
+ * setMainSource
+ *
+ * @param string $src
+ *
+ * @return static
+ */
+ public function setMainSource($src)
+ {
+ $this->setAttribute('src', $src);
+
+ return $this;
+ }
+
+ /**
+ * addSource
+ *
+ * @param string $type
+ * @param string $src
+ * @param string $media
+ *
+ * @return $this
+ */
+ public function addSource($type, $src, $media = null)
+ {
+ $this->content[] = new HtmlElement('source', null, array(
+ 'src' => $src,
+ 'type' => $this->name . '/' . strtolower($type),
+ 'media' => $media
+ ));
+
+ return $this;
+ }
+
+ /**
+ * addOggSource
+ *
+ * @param string $src
+ * @param string $media
+ *
+ * @return static
+ */
+ public function addOggSource($src, $media = null)
+ {
+ return $this->addSource('ogg', $src, $media);
+ }
+
+ /**
+ * Method to get property Hint
+ *
+ * @return string
+ */
+ public function getNoSupportHint()
+ {
+ return $this->hint;
+ }
+
+ /**
+ * Method to set property hint
+ *
+ * @param string $hint
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setNoSupportHint($hint)
+ {
+ $this->hint = $hint;
+
+ return $this;
+ }
+
+ /**
+ * autoplay
+ *
+ * @param boolean $bool
+ *
+ * @return static
+ */
+ public function autoplay($bool)
+ {
+ $this->attribs['autoplay'] = (bool) $bool;
+
+ return $this;
+ }
+
+ /**
+ * controls
+ *
+ * @param boolean $bool
+ *
+ * @return static
+ */
+ public function controls($bool)
+ {
+ $this->attribs['controls'] = (bool) $bool;
+
+ return $this;
+ }
+
+ /**
+ * loop
+ *
+ * @param boolean $bool
+ *
+ * @return static
+ */
+ public function loop($bool)
+ {
+ $this->attribs['loop'] = (bool) $bool;
+
+ return $this;
+ }
+
+ /**
+ * muted
+ *
+ * @param boolean $bool
+ *
+ * @return static
+ */
+ public function muted($bool)
+ {
+ $this->attribs['muted'] = (bool) $bool;
+
+ return $this;
+ }
+
+ /**
+ * preload
+ *
+ * @param string $data
+ *
+ * @return static
+ */
+ public function preload($data)
+ {
+ $this->attribs['preload'] = $data;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Media/Audio.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Media/Audio.php
new file mode 100644
index 00000000..9c085676
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Media/Audio.php
@@ -0,0 +1,50 @@
+addSource('mpeg', $src, $media);
+ }
+
+ /**
+ * addWavSource
+ *
+ * @param string $src
+ * @param string $media
+ *
+ * @return static
+ */
+ public function addWavSource($src, $media = null)
+ {
+ return $this->addSource('wav', $src, $media);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Media/Video.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Media/Video.php
new file mode 100644
index 00000000..534bd31d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Media/Video.php
@@ -0,0 +1,92 @@
+addSource('mp4', $src, $media);
+ }
+
+ /**
+ * addWebMSource
+ *
+ * @param string $src
+ * @param string $media
+ *
+ * @return static
+ */
+ public function addWebMSource($src, $media = null)
+ {
+ return $this->addSource('webm', $src, $media);
+ }
+
+ /**
+ * poster
+ *
+ * @param string $data
+ *
+ * @return static
+ */
+ public function poster($data)
+ {
+ $this->attribs['poster'] = $data;
+
+ return $this;
+ }
+
+ /**
+ * height
+ *
+ * @param string $data
+ *
+ * @return static
+ */
+ public function height($data)
+ {
+ $this->attribs['height'] = $data;
+
+ return $this;
+ }
+
+ /**
+ * width
+ *
+ * @param string $data
+ *
+ * @return static
+ */
+ public function width($data)
+ {
+ $this->attribs['width'] = $data;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Option.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Option.php
new file mode 100644
index 00000000..7a98336d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Option.php
@@ -0,0 +1,73 @@
+value = $value;
+
+ $attribs['value'] = $value;
+
+ parent::__construct('option', $text, $attribs);
+ }
+
+ /**
+ * Method to get property Value
+ *
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Method to set property value
+ *
+ * @param string $value
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setValue($value)
+ {
+ $this->value = $value;
+
+ $this['value'] = $value;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/README.md b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/README.md
new file mode 100644
index 00000000..502bad68
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/README.md
@@ -0,0 +1,180 @@
+# Windwalker Html
+
+Windwalker Html is a tool set using to create html elements and help us handler html string.
+
+## Installation via Composer
+
+Add this to the require block in your `composer.json`.
+
+``` json
+{
+ "require": {
+ "windwalker/html": "~2.0"
+ }
+}
+```
+
+## Select List
+
+``` php
+use Windwalker\Html\Select\SelectList;
+use Windwalker\Html\Option;
+
+$select = new SelectList(
+ 'form[timezone]',
+ array(
+ new Option('Asia - Tokyo', 'Asia/Tokyo', array('class' => 'opt')),
+ new Option('Asia - Taipei', 'Asia/Taipei'),
+ new Option('Europe - Paris', 'Asia/Paris'),
+ new Option('UTC', 'UTC'),
+ ),
+ array('class' => 'input-select'),
+ 'UTC',
+ false
+);
+
+echo $select;
+```
+
+The result:
+
+``` html
+
+ Asia - Tokyo
+ Asia - Taipei
+ Europe - Paris
+ UTC
+
+```
+
+### Group Select
+
+Use two level array to make options grouped.
+
+``` php
+use Windwalker\Html\Select\CheckboxList;
+
+$select = new SelectList(
+ 'form[timezone]',
+ array(
+ 'Asia' => array(
+ new Option('Tokyo', 'Asia/Tokyo', array('class' => 'opt')),
+ new Option('Taipei', 'Asia/Taipei')
+ ),
+ 'Europe' => array(
+ new Option('Europe - Paris', 'Asia/Paris')
+ )
+ ,
+ new Option('UTC', 'UTC'),
+ ),
+ array('class' => 'input-select'),
+ 'UTC',
+ false
+);
+
+echo $select;
+```
+
+The result
+
+``` html
+
+
+ Tokyo
+ Taipei
+
+
+
+ Europe - Paris
+
+
+ UTC
+
+```
+
+## CheckboxList
+
+``` php
+$select = new CheckboxList(
+ 'form[timezone]',
+ array(
+ new Option('Asia - Tokyo', 'Asia/Tokyo', array('class' => 'opt')),
+ new Option('Asia - Taipei', 'Asia/Taipei'),
+ new Option('Europe - Paris', 'Asia/Paris'),
+ new Option('UTC', 'UTC'),
+ ),
+ array('class' => 'input-select'),
+ 'UTC',
+ false
+);
+
+echo $select;
+```
+
+The result
+
+``` html
+
+
+ Asia - Tokyo
+
+
+ Asia - Taipei
+
+
+ Europe - Paris
+
+
+ UTC
+
+```
+
+If you want to use `div` to wrap all inputs instead `span`, set tag name to object.
+
+``` php
+$select->setName('div');
+```
+
+## RadioList
+
+Same as Checkboxes, but the input type will be `type="radio"`
+
+## HtmlHelper
+
+### Repair Tags
+
+We can using `repair()` method to repair unpaired tags by `php tidy`, if tidy extension not exists, will using simple tag close function to fix it.
+
+``` php
+$html = 'foo';
+
+$html = \Windwalker\Html\Helper\HtmlHelper::repair($html);
+
+echo $html; //
foo
+```
+
+### Get JS Object
+
+This method convert a nested array or object to JSON format that you can inject it to JS code.
+
+``` php
+$option = array(
+ 'url' => 'http://foo.com',
+ 'foo' => array('bar', 'yoo')
+);
+
+echo $option = \Windwalker\Html\Helper\HtmlHelper::getJSOBject($option);
+```
+
+Result
+
+```
+{
+ "url" : "http://foo.com",
+ "foo" : ["bar", "yoo"]
+}
+```
+
+## More Builder
+
+We'll add more builder object after version 2.1.
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Select/AbstractInputList.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Select/AbstractInputList.php
new file mode 100644
index 00000000..60ea03f4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Select/AbstractInputList.php
@@ -0,0 +1,261 @@
+checked = $checked;
+
+ parent::__construct('span', (array) $options, $attribs);
+ }
+
+ /**
+ * prepareOptions
+ *
+ * @return void
+ */
+ protected function prepareOptions()
+ {
+ foreach ($this->content as $key => $option)
+ {
+ if (!($option instanceof Option))
+ {
+ throw new \InvalidArgumentException('List item should be an Windwalker\\Html\\Option object.');
+ }
+
+ if ($this->isChecked($option))
+ {
+ $option['checked'] = 'checked';
+ }
+
+ $attrs = $option->getAttributes();
+
+ $attrs['type'] = $this->type;
+ $attrs['name'] = $this->getAttribute('name');
+
+ $attrs['id'] = $option->getAttribute('id');
+ $attrs['id'] = $attrs['id'] ? : strtolower(trim(preg_replace('/[^A-Z0-9_\.-]/i', '-', $attrs['name'] ? : 'empty'), '-'));
+ $attrs['id'] .= '-' . strtolower(trim(preg_replace('/[^A-Z0-9_\.-]/i', '-', $option->getValue() ? : 'empty'), '-'));
+ $attrs['id'] = 'input-' . $attrs['id'];
+ $attrs['disabled'] = $this->disabled;
+ $attrs['readonly'] = $this->readonly;
+
+ // Do not affect source options
+ $option = clone $option;
+
+ $option->setAttributes($attrs);
+
+ $input = new HtmlElement('input', null, $attrs);
+
+ $option->setAttribute('disabled', null);
+ $option->setAttribute('readonly', null);
+
+ $label = $this->createLabel($option);
+
+ $this->content[$key] = new HtmlElements(array($input, $label));
+ }
+ }
+
+ /**
+ * isChecked
+ *
+ * @param Option $option
+ *
+ * @return bool
+ */
+ protected function isChecked(Option $option)
+ {
+ return $option->getValue() == $this->getChecked();
+ }
+
+ /**
+ * toString
+ *
+ * @param boolean $forcePair
+ *
+ * @return string
+ */
+ public function toString($forcePair = false)
+ {
+ if ($this->getAttribute('disabled'))
+ {
+ $this->disabled = true;
+ $this->setAttribute('disabled', null);
+ }
+
+ if ($this->getAttribute('readonly'))
+ {
+ $this->readonly = true;
+ $this->setAttribute('readonly', null);
+ }
+
+ $this->prepareOptions();
+
+ $attrs = $this->getAttributes();
+ $attrs['id'] = $this->getAttribute('id');
+ $attrs['class'] = $this->type . '-inputs ' . $this->getAttribute('class');
+
+ $attrs['name'] = null;
+ $attrs['onchange'] = null;
+ $attrs['size'] = null;
+
+ return HtmlBuilder::create($this->name, $this->content, $attrs, $forcePair);
+ }
+
+ /**
+ * createLabel
+ *
+ * @param Option $option
+ *
+ * @return Htmlelement
+ */
+ protected function createLabel($option)
+ {
+ $attrs = $option->getAttributes();
+
+ $attrs['id'] = $option->getAttribute('id') . '-label';
+ $attrs['for'] = $option->getAttribute('id');
+ $attrs['value'] = null;
+ $attrs['checked'] = null;
+ $attrs['type'] = null;
+ $attrs['name'] = null;
+
+ return new HtmlElement('label', $option->getContent(), $attrs);
+ }
+
+ /**
+ * Method to get property Checked
+ *
+ * @return mixed
+ */
+ public function getChecked()
+ {
+ return $this->checked;
+ }
+
+ /**
+ * Method to set property checked
+ *
+ * @param mixed $checked
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setChecked($checked)
+ {
+ $this->checked = $checked;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property Disabled
+ *
+ * @return boolean
+ */
+ public function getDisabled()
+ {
+ return $this->disabled;
+ }
+
+ /**
+ * Method to set property disabled
+ *
+ * @param boolean $disabled
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setDisabled($disabled)
+ {
+ $this->disabled = $disabled;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property Readonly
+ *
+ * @return boolean
+ */
+ public function getReadonly()
+ {
+ return $this->readonly;
+ }
+
+ /**
+ * Method to set property readonly
+ *
+ * @param boolean $readonly
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setReadonly($readonly)
+ {
+ $this->readonly = $readonly;
+
+ return $this;
+ }
+}
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Select/CheckboxList.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Select/CheckboxList.php
new file mode 100644
index 00000000..94afe046
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Select/CheckboxList.php
@@ -0,0 +1,56 @@
+content as $key => $option)
+ {
+ $option[0]->setAttribute('name', $option[0]->getAttribute('name') . '[]');
+ }
+ }
+
+ /**
+ * isChecked
+ *
+ * @param Option $option
+ *
+ * @return bool
+ */
+ protected function isChecked(Option $option)
+ {
+ return in_array($option->getValue(), (array) $this->getChecked());
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Select/RadioList.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Select/RadioList.php
new file mode 100644
index 00000000..7bef06a9
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Select/RadioList.php
@@ -0,0 +1,25 @@
+setSelected($selected);
+ $this->setMultiple($multiple);
+
+ parent::__construct('select', (array) $options, $attribs);
+ }
+
+ /**
+ * Quick create for PHP 5.3
+ *
+ * @param array $attribs
+ *
+ * @return static
+ */
+ public static function create($name, $attribs = array())
+ {
+ return new static($name, array(), $attribs);
+ }
+
+ /**
+ * toString
+ *
+ * @param bool $forcePair
+ *
+ * @return string
+ */
+ public function toString($forcePair = false)
+ {
+ $tmpContent = clone $this->getContent();
+ $tmpName = $this->getAttribute('name');
+
+ $this->prepareOptions();
+
+ if ($this->multiple)
+ {
+ $this->setAttribute('name', $this->getAttribute('name') . '[]');
+ }
+
+ $html = parent::toString($forcePair);
+
+ $this->setAttribute('name', $tmpName);
+ $this->setContent($tmpContent);
+
+ return $html;
+ }
+
+ /**
+ * prepareOptions
+ *
+ * @return void
+ */
+ protected function prepareOptions()
+ {
+ foreach ($this->content as $name => $option)
+ {
+ // Array means it is a group
+ if (is_array($option))
+ {
+ foreach ($option as &$opt)
+ {
+ if ($this->checkSelected($opt->getValue()))
+ {
+ $opt['selected'] = 'selected';
+ }
+ }
+
+ $this->content[$name] = new HtmlElement('optgroup', $option, array('label' => $name));
+ }
+ // Not array means it is an option
+ else
+ {
+ if ($this->checkSelected($option->getValue()))
+ {
+ $option['selected'] = 'selected';
+ }
+ }
+ }
+ }
+
+ /**
+ * checkSelected
+ *
+ * @param mixed $value
+ *
+ * @return bool
+ */
+ protected function checkSelected($value)
+ {
+ $value = (string) $value;
+
+ if ($this->multiple)
+ {
+ return in_array($value, (array) $this->getSelected());
+ }
+ else
+ {
+ return $value == (string) $this->getSelected();
+ }
+ }
+
+ /**
+ * Method to get property Selected
+ *
+ * @return mixed
+ */
+ public function getSelected()
+ {
+ return $this->selected;
+ }
+
+ /**
+ * Method to set property selected
+ *
+ * @param mixed $selected
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setSelected($selected)
+ {
+ $this->selected = $selected;
+
+ return $this;
+ }
+
+ /**
+ * __clone
+ *
+ * @return void
+ */
+ public function __clone()
+ {
+ $this->content = clone $this->content;
+ }
+
+ /**
+ * Method to get property Multiple
+ *
+ * @return boolean
+ */
+ public function getMultiple()
+ {
+ return $this->multiple;
+ }
+
+ /**
+ * Method to set property multiple
+ *
+ * @param boolean $multiple
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setMultiple($multiple)
+ {
+ $this->multiple = $multiple;
+
+ $this->setAttribute('multiple', $multiple ? 'true' : 'false');
+
+ return $this;
+ }
+
+ /**
+ * addOption
+ *
+ * @param Option $option
+ * @param string $group
+ *
+ * @return static
+ */
+ public function addOption(Option $option, $group = null)
+ {
+ if ($group)
+ {
+ $content = $this->content[$group];
+
+ array_push($content, $option);
+
+ $this->content[$group] = $content;
+ }
+ else
+ {
+ $this->content[] = $option;
+ }
+
+ return $this;
+ }
+}
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/AbstractInputListTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/AbstractInputListTest.php
new file mode 100644
index 00000000..572f876b
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/AbstractInputListTest.php
@@ -0,0 +1,77 @@
+markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getChecked().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Html\Select\AbstractInputList::getChecked
+ * @TODO Implement testGetChecked().
+ */
+ public function testGetChecked()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setChecked().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Html\Select\AbstractInputList::setChecked
+ * @TODO Implement testSetChecked().
+ */
+ public function testSetChecked()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/AudioTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/AudioTest.php
new file mode 100644
index 00000000..dfef433f
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/AudioTest.php
@@ -0,0 +1,77 @@
+ 'foo'))
+ ->addWavSource('foo.wav')
+ ->addOggSource('foo.ogg')
+ ->addMp3Source('foo.mp3', 'screen and (min-width:320px)')
+ ->autoplay(true)
+ ->controls(true)
+ ->loop(true)
+ ->muted(true)
+ ->preload(Audio::PRELOAD_METADATA);
+
+ $html = <<
+
+
+
+
+HTML;
+
+ $this->assertHtmlFormatEquals($html, $audio);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/CheckboxListTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/CheckboxListTest.php
new file mode 100644
index 00000000..792b5f85
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/CheckboxListTest.php
@@ -0,0 +1,103 @@
+ 'opt')),
+ new Option('Asia - Taipei', 'Asia/Taipei'),
+ new Option('Europe - Paris', 'Asia/Paris'),
+ new Option('UTC', 'UTC'),
+ ),
+ array('class' => 'input-select'),
+ 'UTC',
+ false
+ );
+
+ $expect = <<
+
+ Asia - Tokyo
+
+
+ Asia - Taipei
+
+
+ Europe - Paris
+
+
+ UTC
+
+HTML;
+
+ $this->assertHtmlFormatEquals($expect, $select);
+ }
+
+ /**
+ * testCreateList
+ *
+ * @return void
+ *
+ * Windwalker\Html\Select\SelectList::toString
+ */
+ public function testCreateListWithDisabled()
+ {
+ $select = new CheckboxList(
+ 'form[timezone]',
+ array(
+ new Option('Asia - Tokyo', 'Asia/Tokyo', array('class' => 'opt')),
+ new Option('Asia - Taipei', 'Asia/Taipei'),
+ new Option('Europe - Paris', 'Asia/Paris'),
+ new Option('UTC', 'UTC'),
+ ),
+ array('class' => 'input-select', 'disabled' => true, 'readonly' => true),
+ 'UTC',
+ false
+ );
+
+ $expect = <<
+
+ Asia - Tokyo
+
+
+ Asia - Taipei
+
+
+ Europe - Paris
+
+
+ UTC
+
+HTML;
+
+ $this->assertHtmlFormatEquals($expect, $select);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/DListTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/DListTest.php
new file mode 100644
index 00000000..13fa1baf
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/DListTest.php
@@ -0,0 +1,179 @@
+assertEquals(' ', (string) $list);
+
+ $list = new DList(null, array('id' => 'list', 'class' => 'nav'));
+
+ $this->assertEquals(' ', (string) $list);
+
+ $items = array(
+ new DListTitle('Spider Man'),
+ new DListDescription('Remember, with great power, comes great responsibility'),
+ new DListTitle('Forrest Gump'),
+ new DListDescription('Life was like a box of chocolates.'),
+ new DListTitle('Inception'),
+ new DListDescription('You mustn’t be afraid to dream a little bigger,darling.', array('class' => 'nav-item'))
+ );
+
+ $list = new DList($items);
+
+ $html = <<
+ Spider Man
+ Remember, with great power, comes great responsibility
+
+ Forrest Gump
+ Life was like a box of chocolates.
+
+ Inception
+ You mustn’t be afraid to dream a little bigger,darling.
+
+HTML;
+
+ $this->assertHtmlFormatEquals($html, (string) $list);
+ }
+
+ /**
+ * Method to test addItem().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Html\Enum\AbstractHtmlList::addItem
+ */
+ public function testAddItem()
+ {
+ $list = new DList;
+
+ $list->addTitle(new DListTitle('123'))
+ ->addDesc('ABC');
+
+ $html = <<
+ 123
+ ABC
+
+HTML;
+
+ $this->assertHtmlFormatEquals($html, $list);
+ }
+
+ /**
+ * testSetItems
+ *
+ * @return void
+ */
+ public function testSetItems()
+ {
+ $items = array(
+ new DListTitle('Spider Man'),
+ new DListDescription('Remember, with great power, comes great responsibility'),
+ new DListTitle('Forrest Gump'),
+ new DListDescription('Life was like a box of chocolates.'),
+ new DListTitle('Inception'),
+ new DListDescription('You mustn’t be afraid to dream a little bigger,darling.', array('class' => 'nav-item'))
+ );
+
+ $list = new DList;
+ $list->setItems($items);
+
+ $html = <<
+ Spider Man
+ Remember, with great power, comes great responsibility
+
+ Forrest Gump
+ Life was like a box of chocolates.
+
+ Inception
+ You mustn’t be afraid to dream a little bigger,darling.
+
+HTML;
+
+ $this->assertHtmlFormatEquals($html, (string) $list);
+ }
+
+ /**
+ * testAddDescription
+ *
+ * @return void
+ */
+ public function testAddDescription()
+ {
+ $list = new DList;
+
+ $list->addDescription('Spider Man', 'Remember, with great power, comes great responsibility')
+ ->addDescription('Forrest Gump', 'Life was like a box of chocolates.')
+ ->addDescription('Inception', 'You mustn’t be afraid to dream a little bigger,darling.', array(), array('class' => 'nav-item'));
+
+ $html = <<
+ Spider Man
+ Remember, with great power, comes great responsibility
+
+ Forrest Gump
+ Life was like a box of chocolates.
+
+ Inception
+ You mustn’t be afraid to dream a little bigger,darling.
+
+HTML;
+
+ $this->assertHtmlFormatEquals($html, (string) $list);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/FormWrapperTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/FormWrapperTest.php
new file mode 100644
index 00000000..b7a0003e
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/FormWrapperTest.php
@@ -0,0 +1,129 @@
+instance = new FormWrapper;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test create().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Html\Form\FormWrapper::create
+ */
+ public function testCreate()
+ {
+ $this->assertInstanceOf(get_class($this->instance), FormWrapper::create());
+
+ $form = FormWrapper::create('Foo', array('class' => 'foo'));
+
+ $this->assertDomFormatEquals('', $form);
+ }
+
+ /**
+ * Method to test start().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Html\Form\FormWrapper::start
+ */
+ public function testStart()
+ {
+ $this->assertEquals('', FormWrapper::end());
+
+ FormWrapper::setTokenHandler(function()
+ {
+ return new InputElement('hidden', 'token', 1);
+ });
+
+ $this->assertEquals(' ', FormWrapper::end());
+ }
+
+ /**
+ * Method to test renderStart().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Html\Form\FormWrapper::*
+ */
+ public function testRenderStart()
+ {
+ $form = new FormWrapper;
+
+ $form->accept('UTF-8')
+ ->acceptCharset('UTF-8')
+ ->action('foo.php')
+ ->autocomplete('off')
+ ->enctype(FormWrapper::ENCTYPE_URLENCODED)
+ ->method(FormWrapper::METHOD_POST)
+ ->name('test')
+ ->novalidate(true)
+ ->target('_blank');
+
+ $html = <<
+HTML;
+
+ $this->assertDomFormatEquals($html, $form->renderStart());
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/OListTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/OListTest.php
new file mode 100644
index 00000000..c9ea0f68
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/OListTest.php
@@ -0,0 +1,133 @@
+assertEquals(' ', (string) $list);
+
+ $list = new OList(null, array('id' => 'list', 'class' => 'nav'));
+
+ $this->assertEquals(' ', (string) $list);
+
+ $items = array(
+ new ListItem('Remember, with great power, comes great responsibility'),
+ new ListItem('Life was like a box of chocolates.'),
+ new ListItem('You mustn’t be afraid to dream a little bigger,darling.', array('class' => 'nav-item'))
+ );
+
+ $list = new OList($items);
+
+ $html = <<
+ Remember, with great power, comes great responsibility
+ Life was like a box of chocolates.
+ You mustn’t be afraid to dream a little bigger,darling.
+
+HTML;
+
+ $this->assertHtmlFormatEquals($html, (string) $list);
+ }
+
+ /**
+ * Method to test addItem().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Html\Enum\AbstractHtmlList::addItem
+ */
+ public function testAddItem()
+ {
+ $list = new OList;
+
+ $list->addItem(new ListItem('123'))
+ ->addItem('ABC');
+
+ $html = <<
+ 123
+ ABC
+
+HTML;
+
+ $this->assertHtmlFormatEquals($html, $list);
+ }
+
+ /**
+ * testSetItems
+ *
+ * @return void
+ */
+ public function testSetItems()
+ {
+ $items = array(
+ new ListItem('Remember, with great power, comes great responsibility'),
+ new ListItem('Life was like a box of chocolates.'),
+ new ListItem('You mustn’t be afraid to dream a little bigger,darling.', array('class' => 'nav-item'))
+ );
+
+ $list = new OList;
+ $list->setItems($items);
+
+ $html = <<
+ Remember, with great power, comes great responsibility
+ Life was like a box of chocolates.
+ You mustn’t be afraid to dream a little bigger,darling.
+
+HTML;
+
+ $this->assertHtmlFormatEquals($html, (string) $list);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/OptionTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/OptionTest.php
new file mode 100644
index 00000000..c1342802
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/OptionTest.php
@@ -0,0 +1,78 @@
+instance = new Option('flower', 'sakura', array('class' => 'item'));
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * testToString
+ *
+ * @return void
+ *
+ * @covers Windwalker\Html\Option::toString
+ *
+ */
+ public function testToString()
+ {
+ $this->assertEquals(
+ DomHelper::minify('flower '),
+ DomHelper::minify($this->instance)
+ );
+ }
+
+ /**
+ * Method to test getValue().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Html\Option::getValue
+ */
+ public function testGetAndSetValue()
+ {
+ $this->instance->setValue('sunflower');
+
+ $this->assertEquals('sunflower', $this->instance->getValue());
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/RadioListTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/RadioListTest.php
new file mode 100644
index 00000000..ce8c0aae
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/RadioListTest.php
@@ -0,0 +1,113 @@
+ 'opt')),
+ new Option('Asia - Taipei', 'Asia/Taipei'),
+ new Option('Europe - Paris', 'Asia/Paris'),
+ new Option('UTC', 'UTC'),
+ ),
+ array('class' => 'input-select'),
+ 'UTC',
+ false
+ );
+
+ $expect = <<
+
+ Asia - Tokyo
+
+
+ Asia - Taipei
+
+
+ Europe - Paris
+
+
+ UTC
+
+HTML;
+
+ $this->assertHtmlFormatEquals($expect, $select);
+ }
+
+ /**
+ * testCreateList
+ *
+ * @return void
+ *
+ * Windwalker\Html\Select\SelectList::toString
+ */
+ public function testCreateListWithDisabled()
+ {
+ $select = new RadioList(
+ 'form[timezone]',
+ array(
+ new Option('Asia - Tokyo', 'Asia/Tokyo', array('class' => 'opt')),
+ new Option('Asia - Taipei', 'Asia/Taipei'),
+ new Option('Europe - Paris', 'Asia/Paris'),
+ new Option('UTC', 'UTC'),
+ ),
+ array('class' => 'input-select', 'disabled' => true, 'readonly' => true),
+ 'UTC',
+ false
+ );
+
+ $expect = <<
+
+ Asia - Tokyo
+
+
+ Asia - Taipei
+
+
+ Europe - Paris
+
+
+ UTC
+
+HTML;
+
+ $this->assertHtmlFormatEquals($expect, $select);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/SelectListTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/SelectListTest.php
new file mode 100644
index 00000000..724745e5
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/SelectListTest.php
@@ -0,0 +1,193 @@
+instance = new SelectList;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * testCreateList
+ *
+ * @return void
+ *
+ * Windwalker\Html\Select\SelectList::toString
+ */
+ public function testCreateList()
+ {
+ $select = new SelectList(
+ 'form[timezone]',
+ array(
+ new Option('Asia - Tokyo', 'Asia/Tokyo', array('class' => 'opt')),
+ new Option('Asia - Taipei', 'Asia/Taipei'),
+ new Option('Europe - Paris', 'Asia/Paris'),
+ new Option('UTC', 'UTC'),
+ ),
+ array('class' => 'input-select'),
+ 'UTC',
+ false
+ );
+
+ $expect = <<
+ Asia - Tokyo
+ Asia - Taipei
+ Europe - Paris
+ UTC
+
+HTML;
+
+ $this->assertHtmlFormatEquals($expect, $select);
+
+ $expect = <<
+ Asia - Tokyo
+ Asia - Taipei
+ Europe - Paris
+ UTC
+ Europe - London
+
+HTML;
+
+ $select->addOption(new Option('Europe - London', 'Europe/London'));
+
+ $this->assertHtmlFormatEquals($expect, $select);
+ }
+
+ /**
+ * testCreateList
+ *
+ * @return void
+ *
+ * Windwalker\Html\Select\SelectList::toString
+ */
+ public function testCreateGroupList()
+ {
+ $select = new SelectList(
+ 'form[timezone]',
+ array(
+ 'Asia' => array(
+ new Option('Tokyo', 'Asia/Tokyo', array('class' => 'opt')),
+ new Option('Taipei', 'Asia/Taipei')
+ ),
+ 'Europe' => array(
+ new Option('Europe - Paris', 'Asia/Paris')
+ )
+ ,
+ new Option('UTC', 'UTC'),
+ ),
+ array('class' => 'input-select'),
+ 'UTC',
+ false
+ );
+
+ $expect = <<
+
+ Tokyo
+ Taipei
+
+
+
+ Europe - Paris
+
+
+ UTC
+
+HTML;
+
+ $this->assertHtmlFormatEquals($expect, $select);
+
+ $expect = <<
+
+ Tokyo
+ Taipei
+
+
+
+ Europe - Paris
+ Europe - London
+
+
+ UTC
+
+HTML;
+ $select->addOption(new Option('Europe - London', 'Europe/London'), 'Europe');
+
+ $this->assertHtmlFormatEquals($expect, $select);
+ }
+
+ /**
+ * Method to test getSelected().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Html\Select\SelectList::getSelected
+ * @TODO Implement testGetSelected().
+ */
+ public function testGetSelected()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setSelected().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Html\Select\SelectList::setSelected
+ * @TODO Implement testSetSelected().
+ */
+ public function testSetSelected()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/UListTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/UListTest.php
new file mode 100644
index 00000000..2e375776
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/UListTest.php
@@ -0,0 +1,133 @@
+assertEquals('', (string) $list);
+
+ $list = new UList(null, array('id' => 'list', 'class' => 'nav'));
+
+ $this->assertEquals('', (string) $list);
+
+ $items = array(
+ new ListItem('Remember, with great power, comes great responsibility'),
+ new ListItem('Life was like a box of chocolates.'),
+ new ListItem('You mustn’t be afraid to dream a little bigger,darling.', array('class' => 'nav-item'))
+ );
+
+ $list = new UList($items);
+
+ $html = <<
+ Remember, with great power, comes great responsibility
+ Life was like a box of chocolates.
+ You mustn’t be afraid to dream a little bigger,darling.
+
+HTML;
+
+ $this->assertHtmlFormatEquals($html, (string) $list);
+ }
+
+ /**
+ * Method to test addItem().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Html\Enum\AbstractHtmlList::addItem
+ */
+ public function testAddItem()
+ {
+ $list = new UList;
+
+ $list->addItem(new ListItem('123'))
+ ->addItem('ABC');
+
+ $html = <<
+ 123
+ ABC
+
+HTML;
+
+ $this->assertHtmlFormatEquals($html, $list);
+ }
+
+ /**
+ * testSetItems
+ *
+ * @return void
+ */
+ public function testSetItems()
+ {
+ $items = array(
+ new ListItem('Remember, with great power, comes great responsibility'),
+ new ListItem('Life was like a box of chocolates.'),
+ new ListItem('You mustn’t be afraid to dream a little bigger,darling.', array('class' => 'nav-item'))
+ );
+
+ $list = new UList;
+ $list->setItems($items);
+
+ $html = <<
+ Remember, with great power, comes great responsibility
+ Life was like a box of chocolates.
+ You mustn’t be afraid to dream a little bigger,darling.
+
+HTML;
+
+ $this->assertHtmlFormatEquals($html, (string) $list);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/VideoTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/VideoTest.php
new file mode 100644
index 00000000..600557f7
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/Test/VideoTest.php
@@ -0,0 +1,81 @@
+instance = new Video;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test toString().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Html\Media\Video::toString
+ */
+ public function testToString()
+ {
+ $video = Video::create(array('id' => 'foo'))
+ ->addMp4Source('foo.mp4')
+ ->addOggSource('foo.ogg')
+ ->addWebMSource('foo.webm', 'screen and (min-width:320px)')
+ ->autoplay(true)
+ ->controls(true)
+ ->loop(true)
+ ->muted(true)
+ ->poster('poster.png')
+ ->preload(Video::PRELOAD_AUTO)
+ ->height(1920)
+ ->width(1080);
+
+ $html = <<
+
+
+
+
+HTML;
+
+ $this->assertHtmlFormatEquals($html, $video);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/composer.json b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/composer.json
new file mode 100644
index 00000000..d0bf0960
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/composer.json
@@ -0,0 +1,28 @@
+{
+ "name": "windwalker/html",
+ "type": "windwalker-package",
+ "description": "Windwalker Html package",
+ "keywords": ["windwalker", "framework", "html"],
+ "homepage": "https://github.com/ventoviro/windwalker-html",
+ "license": "LGPL-2.0+",
+ "require": {
+ "php": ">=5.3.10",
+ "windwalker/dom": "~2.0"
+ },
+ "require-dev": {
+ "windwalker/test": "~2.0"
+ },
+ "suggest": {
+ },
+ "minimum-stability": "beta",
+ "autoload": {
+ "psr-4": {
+ "Windwalker\\Html\\": ""
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/phpunit.travis.xml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/phpunit.travis.xml
new file mode 100644
index 00000000..690ec926
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/html/phpunit.travis.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/index.html b/deployed/windwalker/libraries/windwalker/vendor/windwalker/index.html
new file mode 100644
index 00000000..2efb97f3
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/index.html
@@ -0,0 +1 @@
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/.gitignore b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/.gitignore
new file mode 100644
index 00000000..84718b5d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/.gitignore
@@ -0,0 +1,11 @@
+# Development system files #
+.*
+!/.gitignore
+!/.travis.yml
+
+# Composer #
+vendor/*
+composer.lock
+
+# Test #
+phpunit.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/.travis.yml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/.travis.yml
new file mode 100644
index 00000000..5420e5c4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/.travis.yml
@@ -0,0 +1,16 @@
+language: php
+
+sudo: false
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+
+before_script:
+ - composer update --dev
+
+script:
+ - phpunit --configuration phpunit.travis.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Color/ColorProcessor.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Color/ColorProcessor.php
new file mode 100644
index 00000000..d0991e52
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Color/ColorProcessor.php
@@ -0,0 +1,201 @@
+(.*?)<\/\\1>/s';
+
+ /**
+ * Regex used for removing color codes
+ *
+ * @var string
+ * @since 2.0
+ */
+ protected static $stripFilter = '/<[\/]?[a-z=;]+>/';
+
+ /**
+ * Array of ColorStyle objects
+ *
+ * @var array
+ * @since 2.0
+ */
+ protected $styles = array();
+
+ /**
+ * Class constructor
+ *
+ * @since 2.0
+ */
+ public function __construct()
+ {
+ $this->addPredefinedStyles();
+ }
+
+ /**
+ * Add a style.
+ *
+ * @param string $name The style name.
+ * @param ColorStyle $style The color style.
+ *
+ * @return ColorProcessor Instance of $this to allow chaining.
+ *
+ * @since 2.0
+ */
+ public function addStyle($name, ColorStyle $style)
+ {
+ $this->styles[$name] = $style;
+
+ return $this;
+ }
+
+ /**
+ * Strip color tags from a string.
+ *
+ * @param string $string The string.
+ *
+ * @return string
+ *
+ * @since 2.0
+ */
+ public static function stripColors($string)
+ {
+ return preg_replace(static::$stripFilter, '', $string);
+ }
+
+ /**
+ * Process a string.
+ *
+ * @param string $string The string to process.
+ *
+ * @return string
+ *
+ * @since 2.0
+ */
+ public function process($string)
+ {
+ preg_match_all($this->tagFilter, $string, $matches);
+
+ if (!$matches)
+ {
+ return $string;
+ }
+
+ foreach ($matches[0] as $i => $m)
+ {
+ if (array_key_exists($matches[1][$i], $this->styles))
+ {
+ $string = $this->replaceColors($string, $matches[1][$i], $matches[2][$i], $this->styles[$matches[1][$i]]);
+ }
+ // Custom format
+ elseif (strpos($matches[1][$i], '='))
+ {
+ $string = $this->replaceColors($string, $matches[1][$i], $matches[2][$i], ColorStyle::fromString($matches[1][$i]));
+ }
+ }
+
+ return $string;
+ }
+
+ /**
+ * Replace color tags in a string.
+ *
+ * @param string $text The original text.
+ * @param string $tag The matched tag.
+ * @param string $match The match.
+ * @param ColorStyle $style The color style to apply.
+ *
+ * @return mixed
+ *
+ * @since 2.0
+ */
+ protected function replaceColors($text, $tag, $match, Colorstyle $style)
+ {
+ $replace = $this->noColors
+ ? $match
+ : "\033[" . $style . "m" . $match . "\033[0m";
+
+ return str_replace('<' . $tag . '>' . $match . '' . $tag . '>', $replace, $text);
+ }
+
+ /**
+ * Adds predefined color styles to the ColorProcessor object
+ *
+ * @return static Instance of $this to allow chaining.
+ *
+ * @since 2.0
+ */
+ protected function addPredefinedStyles()
+ {
+ $this->addStyle(
+ 'info',
+ new ColorStyle('green', '', array('bold'))
+ );
+
+ $this->addStyle(
+ 'comment',
+ new ColorStyle('yellow', '', array('bold'))
+ );
+
+ $this->addStyle(
+ 'question',
+ new ColorStyle('black', 'cyan')
+ );
+
+ $this->addStyle(
+ 'error',
+ new ColorStyle('white', 'red')
+ );
+
+ return $this;
+ }
+
+ /**
+ * Method to get property NoColors
+ *
+ * @return boolean
+ */
+ public function getNoColors()
+ {
+ return $this->noColors;
+ }
+
+ /**
+ * Method to set property noColors
+ *
+ * @param boolean $noColors
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setNoColors($noColors)
+ {
+ $this->noColors = $noColors;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Color/ColorProcessorInterface.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Color/ColorProcessorInterface.php
new file mode 100644
index 00000000..0e972a21
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Color/ColorProcessorInterface.php
@@ -0,0 +1,49 @@
+ 0,
+ 'red' => 1,
+ 'green' => 2,
+ 'yellow' => 3,
+ 'blue' => 4,
+ 'magenta' => 5,
+ 'cyan' => 6,
+ 'white' => 7
+ );
+
+ /**
+ * Known styles
+ *
+ * @var array
+ * @since 2.0
+ */
+ private static $knownOptions = array(
+ 'bold' => 1,
+ 'underscore' => 4,
+ 'blink' => 5,
+ 'reverse' => 7,
+ );
+
+ /**
+ * Foreground base value
+ *
+ * @var integer
+ * @since 2.0
+ */
+ private static $fgBase = 30;
+
+ /**
+ * Background base value
+ *
+ * @var integer
+ * @since 2.0
+ */
+ private static $bgBase = 40;
+
+ /**
+ * Foreground color
+ *
+ * @var integer
+ * @since 2.0
+ */
+ private $fgColor = 0;
+
+ /**
+ * Background color
+ *
+ * @var integer
+ * @since 2.0
+ */
+ private $bgColor = 0;
+
+ /**
+ * Array of style options
+ *
+ * @var array
+ * @since 2.0
+ */
+ private $options = array();
+
+ /**
+ * Constructor
+ *
+ * @param string $fg Foreground color.
+ * @param string $bg Background color.
+ * @param array $options Style options.
+ *
+ * @since 2.0
+ * @throws \InvalidArgumentException
+ */
+ public function __construct($fg = '', $bg = '', $options = array())
+ {
+ if ($fg)
+ {
+ if (false == array_key_exists($fg, static::$knownColors))
+ {
+ throw new \InvalidArgumentException(
+ sprintf('Invalid foreground color "%1$s" [%2$s]',
+ $fg,
+ implode(', ', $this->getKnownColors())
+ )
+ );
+ }
+
+ $this->fgColor = static::$fgBase + static::$knownColors[$fg];
+ }
+
+ if ($bg)
+ {
+ if (false == array_key_exists($bg, static::$knownColors))
+ {
+ throw new \InvalidArgumentException(
+ sprintf('Invalid background color "%1$s" [%2$s]',
+ $bg,
+ implode(', ', $this->getKnownColors())
+ )
+ );
+ }
+
+ $this->bgColor = static::$bgBase + static::$knownColors[$bg];
+ }
+
+ foreach ($options as $option)
+ {
+ if (false == array_key_exists($option, static::$knownOptions))
+ {
+ throw new \InvalidArgumentException(
+ sprintf('Invalid option "%1$s" [%2$s]',
+ $option,
+ implode(', ', $this->getKnownOptions())
+ )
+ );
+ }
+
+ $this->options[] = $option;
+ }
+ }
+
+ /**
+ * Convert to a string.
+ *
+ * @return string
+ *
+ * @since 2.0
+ */
+ public function __toString()
+ {
+ return $this->getStyle();
+ }
+
+ /**
+ * Create a color style from a parameter string.
+ *
+ * Example: fg=red;bg=blue;options=bold,blink
+ *
+ * @param string $string The parameter string.
+ *
+ * @return ColorStyle Instance of $this to allow chaining.
+ *
+ * @since 2.0
+ * @throws \RuntimeException
+ */
+ public static function fromString($string)
+ {
+ $fg = '';
+ $bg = '';
+ $options = array();
+
+ $parts = explode(';', $string);
+
+ foreach ($parts as $part)
+ {
+ $subParts = explode('=', $part);
+
+ if (count($subParts) < 2)
+ {
+ continue;
+ }
+
+ switch ($subParts[0])
+ {
+ case 'fg':
+ $fg = $subParts[1];
+ break;
+
+ case 'bg':
+ $bg = $subParts[1];
+ break;
+
+ case 'options':
+ $options = explode(',', $subParts[1]);
+ break;
+
+ default:
+ throw new \RuntimeException('Invalid option');
+ break;
+ }
+ }
+
+ return new self($fg, $bg, $options);
+ }
+
+ /**
+ * Get the translated color code.
+ *
+ * @return string
+ *
+ * @since 2.0
+ */
+ public function getStyle()
+ {
+ $values = array();
+
+ if ($this->fgColor)
+ {
+ $values[] = $this->fgColor;
+ }
+
+ if ($this->bgColor)
+ {
+ $values[] = $this->bgColor;
+ }
+
+ foreach ($this->options as $option)
+ {
+ $values[] = static::$knownOptions[$option];
+ }
+
+ return implode(';', $values);
+ }
+
+ /**
+ * Get the known colors.
+ *
+ * @return string
+ *
+ * @since 2.0
+ */
+ public function getKnownColors()
+ {
+ return array_keys(static::$knownColors);
+ }
+
+ /**
+ * Get the known options.
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function getKnownOptions()
+ {
+ return array_keys(static::$knownOptions);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Color/NoColorProcessor.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Color/NoColorProcessor.php
new file mode 100644
index 00000000..4ca34f7b
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Color/NoColorProcessor.php
@@ -0,0 +1,25 @@
+input = $input ? : new CliInput;
+ $this->output = $output ? : new CliOutput;
+ }
+
+ /**
+ * Write a string to standard output
+ *
+ * @param string $text The text to display.
+ * @param boolean $nl True (default) to append a new line at the end of the output string.
+ *
+ * @return IO Instance of $this to allow chaining.
+ */
+ public function out($text = '', $nl = true)
+ {
+ $this->output->out($text, $nl);
+
+ return $this;
+ }
+
+ /**
+ * Get a value from standard input.
+ *
+ * @return string The input string from standard input.
+ */
+ public function in()
+ {
+ return $this->input->in();
+ }
+
+ /**
+ * Write a string to standard error output.
+ *
+ * @param string $text The text to display.
+ * @param boolean $nl True (default) to append a new line at the end of the output string.
+ *
+ * @since 2.0
+ * @return $this
+ */
+ public function err($text = '', $nl = true)
+ {
+ $this->output->err($text, $nl);
+
+ return $this;
+ }
+
+ /**
+ * Gets a value from the input data.
+ *
+ * @param string $name Name of the value to get.
+ * @param mixed $default Default value to return if variable does not exist.
+ *
+ * @return mixed The filtered input value.
+ *
+ * @since 2.0
+ */
+ public function getOption($name, $default = null)
+ {
+ return $this->input->get($name, $default);
+ }
+
+ /**
+ * Sets a value
+ *
+ * @param string $name Name of the value to set.
+ * @param mixed $value Value to assign to the input.
+ *
+ * @return IO
+ *
+ * @since 2.0
+ */
+ public function setOption($name, $value)
+ {
+ $this->input->set($name, $value);
+
+ return $this;
+ }
+
+ /**
+ * getArgument
+ *
+ * @param integer $offset
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public function getArgument($offset, $default = null)
+ {
+ return $this->input->getArgument($offset, $default);
+ }
+
+ /**
+ * setArgument
+ *
+ * @param integer $offset
+ * @param mixed $value
+ *
+ * @return IO
+ */
+ public function setArgument($offset, $value)
+ {
+ $this->input->setArgument($offset, $value);
+
+ return $this;
+ }
+
+ /**
+ * getInput
+ *
+ * @return CliInput|CliInputInterface
+ */
+ public function getInput()
+ {
+ return $this->input;
+ }
+
+ /**
+ * setInput
+ *
+ * @param CliInputInterface $input
+ *
+ * @return IO Return self to support chaining.
+ */
+ public function setInput(CliInputInterface $input)
+ {
+ $this->input = $input;
+
+ return $this;
+ }
+
+ /**
+ * getOutput
+ *
+ * @return CliOutputInterface|ColorfulOutputInterface
+ */
+ public function getOutput()
+ {
+ return $this->output;
+ }
+
+ /**
+ * setOutput
+ *
+ * @param CliOutputInterface $output
+ *
+ * @return IO Return self to support chaining.
+ */
+ public function setOutput(CliOutputInterface $output)
+ {
+ $this->output = $output;
+
+ return $this;
+ }
+
+ /**
+ * getExecuted
+ *
+ * @return mixed
+ */
+ public function getCalledScript()
+ {
+ return $this->input->getCalledScript();
+ }
+
+ /**
+ * getOptions
+ *
+ * @return string[]
+ */
+ public function getOptions()
+ {
+ return $this->input->all();
+ }
+
+ /**
+ * getArguments
+ *
+ * @return string[]
+ */
+ public function getArguments()
+ {
+ return $this->input->args;
+ }
+
+ /**
+ * Set value to property
+ *
+ * @param mixed $offset Property key.
+ * @param mixed $value Property value to set.
+ *
+ * @return void
+ */
+ public function offsetSet($offset, $value)
+ {
+ $this->input->getArgument($offset, $value);
+ }
+
+ /**
+ * Unset a property.
+ *
+ * @param mixed $offset Key to unset.
+ *
+ * @return void
+ */
+ public function offsetUnset($offset)
+ {
+ unset($this->input->args[$offset]);
+ }
+
+ /**
+ * Property is exist or not.
+ *
+ * @param mixed $offset Property key.
+ *
+ * @return boolean
+ */
+ public function offsetExists($offset)
+ {
+ return isset($this->input->args[$offset]);
+ }
+
+ /**
+ * Get a value of property.
+ *
+ * @param mixed $offset Property key.
+ *
+ * @return mixed The value of this property.
+ */
+ public function offsetGet($offset)
+ {
+ return $this->getArgument($offset);
+ }
+
+ /**
+ * Get the data store for iterate.
+ *
+ * @return \Traversable The data to be iterator.
+ */
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->input->args);
+ }
+
+ /**
+ * Serialize data.
+ *
+ * @return string Serialized data string.
+ */
+ public function serialize()
+ {
+ return serialize($this->input);
+ }
+
+ /**
+ * Unserialize the data.
+ *
+ * @param string $serialized THe serialized data string.
+ *
+ * @return IO Support chaining.
+ */
+ public function unserialize($serialized)
+ {
+ $this->input = unserialize($serialized);
+
+ return $this;
+ }
+
+ /**
+ * Count data.
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->input->args);
+ }
+
+ /**
+ * Serialize to json format.
+ *
+ * @return string Encoded json string.
+ */
+ public function jsonSerialize()
+ {
+ return array(
+ 'arguments' => $this->input->args,
+ 'options' => $this->input->all()
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/IOInterface.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/IOInterface.php
new file mode 100644
index 00000000..af44f92c
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/IOInterface.php
@@ -0,0 +1,108 @@
+parseArguments();
+ }
+
+ /**
+ * Method to serialize the input.
+ *
+ * @return string The serialized input.
+ *
+ * @since 2.0
+ */
+ public function serialize()
+ {
+ // Load all of the inputs.
+ $this->loadAllInputs();
+
+ // Remove $_ENV and $_SERVER from the inputs.
+ $inputs = $this->inputs;
+ unset($inputs['env']);
+ unset($inputs['server']);
+
+ // Serialize the executable, args, options, data, and inputs.
+ return serialize(array($this->calledScript, $this->args, $this->filter, $this->data, $inputs));
+ }
+
+ /**
+ * Gets a value from the input data.
+ *
+ * @param string $name Name of the value to get.
+ * @param mixed $default Default value to return if variable does not exist.
+ * @param string $filter Filter to apply to the value.
+ *
+ * @return mixed The filtered input value.
+ *
+ * @since 2.0
+ */
+ public function get($name, $default = null, $filter = 'string')
+ {
+ return parent::get($name, $default, $filter);
+ }
+
+ /**
+ * Gets an array of values from the request.
+ *
+ * @return mixed The filtered input data.
+ *
+ * @since 2.0
+ */
+ public function all()
+ {
+ return $this->getArray();
+ }
+
+ /**
+ * Method to unserialize the input.
+ *
+ * @param string $input The serialized input.
+ *
+ * @return Input The input object.
+ *
+ * @since 2.0
+ */
+ public function unserialize($input)
+ {
+ // Unserialize the executable, args, options, data, and inputs.
+ list($this->calledScript, $this->args, $this->filter, $this->data, $this->inputs) = unserialize($input);
+
+ $this->filter = $this->filter ? : new NullFilter;
+ }
+
+ /**
+ * getArgument
+ *
+ * @param integer $offset
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public function getArgument($offset, $default = null)
+ {
+ return isset($this->args[$offset]) ? $this->args[$offset] : $default;
+ }
+
+ /**
+ * setArgument
+ *
+ * @param integer $offset
+ * @param mixed $value
+ *
+ * @return CliInput
+ */
+ public function setArgument($offset, $value)
+ {
+ $this->args[$offset] = $value;
+
+ return $this;
+ }
+
+ /**
+ * Initialise the options and arguments
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ protected function parseArguments()
+ {
+ $argv = $_SERVER['argv'];
+
+ $this->calledScript = array_shift($argv);
+
+ $out = array();
+
+ for ($i = 0, $j = count($argv); $i < $j; $i++)
+ {
+ $arg = $argv[$i];
+
+ // --foo --bar=baz
+ if (substr($arg, 0, 2) === '--')
+ {
+ $eqPos = strpos($arg, '=');
+
+ // --foo
+ if ($eqPos === false)
+ {
+ $key = substr($arg, 2);
+
+ // --foo value
+ if ($i + 1 < $j && $argv[$i + 1][0] !== '-')
+ {
+ $value = $argv[$i + 1];
+ $i++;
+ }
+ else
+ {
+ $value = isset($out[$key]) ? $out[$key] : true;
+ }
+
+ $out[$key] = $value;
+ }
+
+ // --bar=baz
+ else
+ {
+ $key = substr($arg, 2, $eqPos - 2);
+ $value = substr($arg, $eqPos + 1);
+ $out[$key] = $value;
+ }
+ }
+
+ // -k=value -abc
+ else
+ {
+ if (substr($arg, 0, 1) === '-')
+ {
+ // -k=value
+ if (substr($arg, 2, 1) === '=')
+ {
+ $key = substr($arg, 1, 1);
+ $value = substr($arg, 3);
+ $out[$key] = $value;
+ }
+ // -abc
+ else
+ {
+ $chars = str_split(substr($arg, 1));
+
+ foreach ($chars as $char)
+ {
+ $key = $char;
+ $value = isset($out[$key]) ? $out[$key] : true;
+ $out[$key] = $value;
+ }
+
+ // -a a-value
+ if ((count($chars) === 1) && ($i + 1 < $j) && ($argv[$i + 1][0] !== '-'))
+ {
+ $out[$key] = $argv[$i + 1];
+ $i++;
+ }
+ }
+ }
+
+ // plain-arg
+ else
+ {
+ $this->args[] = $arg;
+ }
+ }
+ }
+
+ $this->data = $out;
+ }
+
+ /**
+ * Get a value from standard input.
+ *
+ * @return string The input string from standard input.
+ */
+ public function in()
+ {
+ return rtrim(fread($this->inputStream, 8192), "\n\r");
+ }
+
+ /**
+ * getInputStream
+ *
+ * @return resource
+ */
+ public function getInputStream()
+ {
+ return $this->inputStream;
+ }
+
+ /**
+ * setInputStream
+ *
+ * @param resource $inputStream
+ *
+ * @return CliInput Return self to support chaining.
+ */
+ public function setInputStream($inputStream)
+ {
+ $this->inputStream = $inputStream;
+
+ return $this;
+ }
+
+ /**
+ * getCalledScript
+ *
+ * @return string
+ */
+ public function getCalledScript()
+ {
+ return $this->calledScript;
+ }
+
+ /**
+ * setCalledScript
+ *
+ * @param string $calledScript
+ *
+ * @return CliInput Return self to support chaining.
+ */
+ public function setCalledScript($calledScript)
+ {
+ $this->calledScript = $calledScript;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Input/CliInputInterface.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Input/CliInputInterface.php
new file mode 100644
index 00000000..9c5867fa
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Input/CliInputInterface.php
@@ -0,0 +1,73 @@
+outputStream;
+ }
+
+ /**
+ * setOutStream
+ *
+ * @param resource $outStream
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setOutputStream($outStream)
+ {
+ $this->outputStream = $outStream;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property ErrorStream
+ *
+ * @return resource
+ */
+ public function getErrorStream()
+ {
+ return $this->errorStream;
+ }
+
+ /**
+ * Method to set property errorStream
+ *
+ * @param resource $errorStream
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setErrorStream($errorStream)
+ {
+ $this->errorStream = $errorStream;
+
+ return $this;
+ }
+}
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Output/CliOutput.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Output/CliOutput.php
new file mode 100644
index 00000000..17e8423b
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Output/CliOutput.php
@@ -0,0 +1,106 @@
+setProcessor(($processor instanceof ColorProcessorInterface) ? $processor : new ColorProcessor);
+ }
+
+ /**
+ * Write a string to standard output
+ *
+ * @param string $text The text to display.
+ * @param boolean $nl True (default) to append a new line at the end of the output string.
+ *
+ * @return CliOutput Instance of $this to allow chaining.
+ */
+ public function out($text = '', $nl = true)
+ {
+ fwrite($this->outputStream, $this->getProcessor()->process($text) . ($nl ? "\n" : null));
+
+ return $this;
+ }
+
+ /**
+ * Write a string to standard error output.
+ *
+ * @param string $text The text to display.
+ * @param boolean $nl True (default) to append a new line at the end of the output string.
+ *
+ * @since 2.0
+ * @return $this
+ */
+ public function err($text = '', $nl = true)
+ {
+ fwrite($this->errorStream, $this->processor->process($text) . ($nl ? "\n" : null));
+
+ return $this;
+ }
+
+ /**
+ * Set a processor
+ *
+ * @param ColorProcessorInterface $processor The output processor.
+ *
+ * @return CliOutput Instance of $this to allow chaining.
+ *
+ * @since 2.0
+ */
+ public function setProcessor(ColorProcessorInterface $processor)
+ {
+ $this->processor = $processor;
+
+ return $this;
+ }
+
+ /**
+ * Get a processor
+ *
+ * @return ColorProcessorInterface
+ *
+ * @since 2.0
+ * @throws \RuntimeException
+ */
+ public function getProcessor()
+ {
+ if ($this->processor)
+ {
+ return $this->processor;
+ }
+
+ throw new \RuntimeException('A ColorProcessorInterface object has not been set.');
+ }
+}
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Output/CliOutputInterface.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Output/CliOutputInterface.php
new file mode 100644
index 00000000..31d40e17
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/Output/CliOutputInterface.php
@@ -0,0 +1,37 @@
+outputStream, $text . ($nl ? "\n" : null));
+
+ return $this;
+ }
+
+ /**
+ * Write a string to standard error output.
+ *
+ * @param string $text The text to display.
+ * @param boolean $nl True (default) to append a new line at the end of the output string.
+ *
+ * @since 2.0
+ * @return $this
+ */
+ public function err($text = '', $nl = true)
+ {
+ fwrite($this->errorStream, $text . ($nl ? "\n" : null));
+
+ return $this;
+ }
+}
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/README.md b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/README.md
new file mode 100644
index 00000000..84b184f5
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Cli/README.md
@@ -0,0 +1,180 @@
+# CLI Input & Output
+
+## The CLI Input
+
+When we are writing command line program, mostly we will use `$_SERVER['argv']` to get command and options.
+
+If we type:
+
+``` bash
+php cli/console.php flower sakura -a -bc --olive -d=foo --bar baz
+```
+
+The `$_SERVER['argv']` will look like:
+
+```
+Array(
+ [0] => cli/console.php
+ [1] => flower
+ [3] => sakura
+ [4] => -a
+ [5] => -bc
+ [6] => --olive
+ [7] => -d=foo
+ [8] => --bar
+ [9] => baz
+)
+```
+
+It is hard to use, The `CliInput` object will parse this arguments and provides us an easy using interface to get arguments and options.
+
+``` php
+use Windwalker\IO\Cli\Input\CliInput;
+
+$input = new CliInput;
+
+$input->getCalledScript(); // cli/console.php
+
+// Get Arguments
+$input->getArgument(0); // flower
+
+$input->getArgument(3, 'default_value'); // Return default
+
+// Get Options
+$input->get('a'); // true
+$input->get('b'); // true
+$input->get('g'); // null
+$input->get('olive'); // true
+
+$input->get('d'); // 'foo'
+$input->get('bar'); // 'baz'
+
+$input->get('yoo', 'default'); // Return default
+```
+
+### Ask From STDIN
+
+``` php
+echo 'What is your name: ';
+$answer = $input->in(); // Terminal wil ask user question
+
+// Same as
+$answer = fread(STDIN);
+```
+
+## The CLI Output
+
+CliOutput help us write text to standard output
+
+``` php
+use Windwalker\IO\Cli\Output\CliOutput;
+
+$output = new CliOutput;
+
+// Write to STDOUT
+$output->out('It is the east, and Juliet is the sun.');
+
+// Write to STDERR
+$output->err('Whoop, there has something wrong.');
+```
+
+See php [IO-Streams](http://php.net/manual/en/features.commandline.io-streams.php)
+
+### Colorful Output
+
+It is possible to use colors on an ANSI enabled terminal.
+
+``` php
+// Green text
+$output->out('foo ');
+
+// Yellow text
+$output->out('foo ');
+
+// Black text on a cyan background
+$output->out('foo ');
+
+// White text on a red background
+$output->out('foo ');
+```
+
+You can also create your own styles.
+
+``` php
+use Windwalker\IO\Cli\Color\ColorStyle;
+use Windwalker\IO\Cli\Output\ColorfulOutputInterface;
+
+if ($output instanceof ColorfulOutputInterface)
+{
+ $style = new Colorstyle('yellow', 'red', array('bold', 'blink'));
+
+ $output->getProcessor()->addStyle('fire', $style);
+}
+
+$output->out('foo ');
+```
+
+Available foreground and background colors are:
+
+- black
+- red
+- green
+- yellow
+- blue
+- magenta
+- cyan
+- white
+
+And available options are:
+
+- bold
+- underscore
+- blink
+- reverse
+
+You can also set these colors and options inside the tagname:
+
+``` php
+// Green text
+$output->out('foo ');
+
+// Black text on a cyan background
+$output->out('foo ');
+
+// Bold text on a yellow background
+$output->out('foo ');
+```
+
+## The IO Object
+
+IO is an object integrate both Input and Output to provides an universal interface to handler I/O in command line programs.
+
+``` php
+use Windwalker\IO\Cli\IO;
+
+$io = new IO;
+
+// Or inject your object
+$io = new IO(new CliInput, new CliOutput);
+```
+
+The interface is totally same as Input and Output.
+
+``` php
+$io->in('Question: ');
+$io->out('Brevity is the soul of wit.');
+
+$io->getArgument(0);
+$io->getOption('foo');
+
+$io->getCalledScript();
+```
+
+### Array Access
+
+The benefit of IO object is that it can use array access to get arguments:
+
+``` php
+$arg1 = $io[0];
+$arg2 = $io[1] ? : 'baz';
+```
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Compat/JsonSerializable.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Compat/JsonSerializable.php
new file mode 100644
index 00000000..99d42d77
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Compat/JsonSerializable.php
@@ -0,0 +1,24 @@
+data = &$_COOKIE;
+ }
+
+ /**
+ * Sets a value
+ *
+ * @param string $name Name of the value to set.
+ * @param mixed $value Value to assign to the input.
+ * @param integer $expire The time the cookie expires. This is a Unix timestamp so is in number
+ * of seconds since the epoch. In other words, you'll most likely set this
+ * with the time() function plus the number of seconds before you want it
+ * to expire. Or you might use mktime(). time()+60*60*24*30 will set the
+ * cookie to expire in 30 days. If set to 0, or omitted, the cookie will
+ * expire at the end of the session (when the browser closes).
+ * @param string $path The path on the server in which the cookie will be available on. If set
+ * to '/', the cookie will be available within the entire domain. If set to
+ * '/foo/', the cookie will only be available within the /foo/ directory and
+ * all sub-directories such as /foo/bar/ of domain. The default value is the
+ * current directory that the cookie is being set in.
+ * @param string $domain The domain that the cookie is available to. To make the cookie available
+ * on all subdomains of example.com (including example.com itself) then you'd
+ * set it to '.example.com'. Although some browsers will accept cookies without
+ * the initial ., RFC 2109 requires it to be included. Setting the domain to
+ * 'www.example.com' or '.www.example.com' will make the cookie only available
+ * in the www subdomain.
+ * @param boolean $secure Indicates that the cookie should only be transmitted over a secure HTTPS
+ * connection from the client. When set to TRUE, the cookie will only be set
+ * if a secure connection exists. On the server-side, it's on the programmer
+ * to send this kind of cookie only on secure connection (e.g. with respect
+ * to $_SERVER["HTTPS"]).
+ * @param boolean $httpOnly When TRUE the cookie will be made accessible only through the HTTP protocol.
+ * This means that the cookie won't be accessible by scripting languages, such
+ * as JavaScript. This setting can effectively help to reduce identity theft
+ * through XSS attacks (although it is not supported by all browsers).
+ *
+ * @return void
+ *
+ * @link http://www.ietf.org/rfc/rfc2109.txt
+ * @see setcookie()
+ * @since 2.0
+ */
+ public function set($name, $value, $expire = 0, $path = '', $domain = '', $secure = false, $httpOnly = false)
+ {
+ setcookie($name, $value, $expire, $path, $domain, $secure, $httpOnly);
+
+ $this->data[$name] = $value;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/FilesInput.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/FilesInput.php
new file mode 100644
index 00000000..f12b7ad1
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/FilesInput.php
@@ -0,0 +1,112 @@
+data = &$_FILES;
+ }
+
+ /**
+ * Gets a value from the input data.
+ *
+ * @param string $name The name of the input property (usually the name of the files INPUT tag) to get.
+ * @param mixed $default The default value to return if the named property does not exist.
+ * @param string $filter The filter to apply to the value.
+ *
+ * @return mixed The filtered input value.
+ *
+ * @see JFilterInput::clean
+ * @since 2.0
+ */
+ public function get($name, $default = null, $filter = InputFilter::CMD)
+ {
+ if (isset($this->data[$name]))
+ {
+ $results = $this->decodeData(
+ array(
+ $this->data[$name]['name'],
+ $this->data[$name]['type'],
+ $this->data[$name]['tmp_name'],
+ $this->data[$name]['error'],
+ $this->data[$name]['size']
+ )
+ );
+
+ return $results;
+ }
+
+ return $default;
+ }
+
+ /**
+ * Method to decode a data array.
+ *
+ * @param array $data The data array to decode.
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ protected function decodeData(array $data)
+ {
+ $result = array();
+
+ if (is_array($data[0]))
+ {
+ foreach ($data[0] as $k => $v)
+ {
+ $result[$k] = $this->decodeData(array($data[0][$k], $data[1][$k], $data[2][$k], $data[3][$k], $data[4][$k]));
+ }
+
+ return $result;
+ }
+
+ return array('name' => $data[0], 'type' => $data[1], 'tmp_name' => $data[2], 'error' => $data[3], 'size' => $data[4]);
+ }
+
+ /**
+ * Sets a value.
+ *
+ * @param string $name The name of the input property to set.
+ * @param mixed $value The value to assign to the input property.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ public function set($name, $value)
+ {
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Filter/NullFilter.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Filter/NullFilter.php
new file mode 100644
index 00000000..88fdd8bb
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Filter/NullFilter.php
@@ -0,0 +1,30 @@
+data);
+ }
+ else
+ {
+ parse_str($raw, $this->data);
+ }
+
+ if (!is_array($this->data))
+ {
+ $this->data = array();
+ }
+ }
+ else
+ {
+ if ($reference)
+ {
+ $this->data = &$source;
+ }
+ else
+ {
+ $this->data = $source;
+ }
+ }
+ }
+
+ /**
+ * Gets the raw HTTP data string from the request.
+ *
+ * @return string The raw HTP data string from the request.
+ *
+ * @since 2.0
+ */
+ public static function getRawData()
+ {
+ return static::$raw;
+ }
+
+ /**
+ * setRawData
+ *
+ * @param string $data
+ *
+ * @return string
+ */
+ public static function setRawData($data)
+ {
+ static::$raw = $data;
+ }
+
+ /**
+ * loadRawFromRequest
+ *
+ * @return string
+ */
+ protected function loadRawFromRequest()
+ {
+ if (static::$raw)
+ {
+ return static::$raw;
+ }
+
+ static::$raw = file_get_contents('php://input');
+
+ // This is a workaround for where php://input has already been read.
+ // See note under php://input on http://php.net/manual/en/wrappers.php.php
+ if (empty($this->raw) && isset($GLOBALS['HTTP_RAW_POST_DATA']))
+ {
+ static::$raw = $GLOBALS['HTTP_RAW_POST_DATA'];
+ }
+
+ return static::$raw;
+ }
+
+ /**
+ * parseFormData
+ *
+ * @param string $input
+ * @param array &$data
+ *
+ * @link http://stackoverflow.com/questions/5483851/manually-parse-raw-http-data-with-php/5488449#5488449
+ *
+ * @return array
+ */
+ public static function parseFormData($input, array &$data)
+ {
+ // grab multipart boundary from content type header
+ preg_match('/boundary=(.*)$/', $_SERVER['CONTENT_TYPE'], $matches);
+
+ $boundary = $matches[1];
+
+ // split content by boundary and get rid of last -- element
+ $aBlocks = preg_split("/-+$boundary/", $input);
+
+ array_pop($aBlocks);
+
+ // loop data blocks
+ foreach ($aBlocks as $id => $block)
+ {
+ if (empty($block))
+ {
+ continue;
+ }
+
+ // you'll have to var_dump $block to understand this and maybe replace \n or \r with a visibile char
+
+ // parse uploaded files
+ if (strpos($block, 'application/octet-stream') !== false)
+ {
+ // match "name", then everything after "stream" (optional) except for prepending newlines
+ preg_match("/name=\"([^\"]*)\".*stream[\n|\r]+([^\n\r].*)?$/s", $block, $matches);
+ }
+ // parse all other fields
+ else
+ {
+ // match "name" and optional value in between newline sequences
+ preg_match('/name=\"([^\"]*)\"[\n|\r]+([^\n\r].*)?[\n|\r]$/s', $block, $matches);
+ }
+
+ if (isset($matches[1]) && isset($matches[2]))
+ {
+ $data[$matches[1]] = rtrim($matches[2], "\n\r");
+ }
+ }
+
+ return $data;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Input.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Input.php
new file mode 100644
index 00000000..cabd557b
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Input.php
@@ -0,0 +1,579 @@
+filter = $filter;
+ }
+ else
+ {
+ $this->filter = class_exists('Windwalker\\Filter\\InputFilter') ? new InputFilter : new NullFilter;
+ }
+
+ $this->prepareSource($source);
+ }
+
+ /**
+ * Prepare source.
+ *
+ * @param array $source Optional source data. If omitted, a copy of the server variable '_REQUEST' is used.
+ * @param boolean $reference If set to true, he source in first argument will be reference.
+ *
+ * @return void
+ */
+ public function prepareSource(&$source = null, $reference = false)
+ {
+ if (is_null($source))
+ {
+ $this->data = &$_REQUEST;
+ }
+ else
+ {
+ if ($reference)
+ {
+ $this->data = &$source;
+ }
+ else
+ {
+ $this->data = $source;
+ }
+ }
+ }
+
+ /**
+ * Magic method to get an input object
+ *
+ * @param mixed $name Name of the input object to retrieve.
+ *
+ * @return Input The request input object
+ *
+ * @since 2.0
+ */
+ public function __get($name)
+ {
+ if (isset($this->inputs[$name]))
+ {
+ return $this->inputs[$name];
+ }
+
+ $filter = ($this->filter instanceof NullFilter) ? null : $this->filter;
+
+ $className = __NAMESPACE__ . '\\' . ucfirst($name) . 'Input';
+
+ if (!class_exists($className))
+ {
+ $className = __NAMESPACE__ . '\\' . ucfirst($name);
+ }
+
+ if (class_exists($className))
+ {
+ $this->inputs[$name] = new $className(null, $filter);
+
+ return $this->inputs[$name];
+ }
+
+ $superGlobal = '_' . strtoupper($name);
+
+ if (isset($GLOBALS[$superGlobal]))
+ {
+ $this->inputs[$name] = new Input($GLOBALS[$superGlobal], $filter);
+
+ return $this->inputs[$name];
+ }
+
+ if (in_array(strtolower($name), array('put', 'patch', 'delete', 'link', 'unlink')))
+ {
+ $data = (strtolower($this->getMethod()) == strtolower($name)) ? null : array();
+
+ $this->inputs[$name] = new FormDataInput($data, $filter);
+
+ return $this->inputs[$name];
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the number of variables.
+ *
+ * @return integer The number of variables in the input.
+ *
+ * @since 2.0
+ * @see Countable::count()
+ */
+ public function count()
+ {
+ return count($this->data);
+ }
+
+ /**
+ * Gets a value from the input data.
+ *
+ * @param string $name Name of the value to get.
+ * @param mixed $default Default value to return if variable does not exist.
+ * @param string $filter Filter to apply to the value.
+ *
+ * @return mixed The filtered input value.
+ *
+ * @since 2.0
+ */
+ public function get($name, $default = null, $filter = 'cmd')
+ {
+ if (isset($this->data[$name]))
+ {
+ return $this->filter->clean($this->data[$name], $filter);
+ }
+
+ return $default;
+ }
+
+ /**
+ * Gets an array of values from the request.
+ *
+ * @param array $vars Associative array of keys and filter types to apply.
+ * If empty and datasource is null, all the input data will be returned
+ * but filtered using the default case in JFilterInput::clean.
+ * @param mixed $datasource Array to retrieve data from, or null
+ *
+ * @return mixed The filtered input data.
+ *
+ * @since 2.0
+ */
+ public function getArray(array $vars = array(), $datasource = null)
+ {
+ if (empty($vars) && is_null($datasource))
+ {
+ $vars = $this->data;
+ }
+
+ $results = array();
+
+ foreach ($vars as $k => $v)
+ {
+ if (is_array($v))
+ {
+ if (is_null($datasource))
+ {
+ if ($this instanceof FilesInput)
+ {
+ $results[$k] = $this->getArray($this->get($k, null, 'array'), $this->get($k, null, 'array'));
+ }
+ else
+ {
+ $results[$k] = $this->getArray($v, $this->get($k, null, 'array'));
+ }
+ }
+ else
+ {
+ $results[$k] = $this->getArray($v, $datasource[$k]);
+ }
+ }
+ else
+ {
+ if (is_null($datasource))
+ {
+ $results[$k] = $this->get($k, null, $v);
+ }
+ elseif (isset($datasource[$k]))
+ {
+ $results[$k] = $this->filter->clean($datasource[$k], $v);
+ }
+ else
+ {
+ $results[$k] = $this->filter->clean(null, $v);
+ }
+ }
+ }
+
+ return $results;
+ }
+
+ /**
+ * Sets a value
+ *
+ * @param string $name Name of the value to set.
+ * @param mixed $value Value to assign to the input.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ public function set($name, $value)
+ {
+ $this->data[$name] = $value;
+ }
+
+ /**
+ * Define a value. The value will only be set if there's no value for the name or if it is null.
+ *
+ * @param string $name Name of the value to define.
+ * @param mixed $value Value to assign to the input.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ public function def($name, $value)
+ {
+ if (isset($this->data[$name]))
+ {
+ return;
+ }
+
+ $this->data[$name] = $value;
+ }
+
+ /**
+ * Check if a value name exists.
+ *
+ * @param string $name Value name
+ *
+ * @return boolean
+ *
+ * @since 2.0
+ */
+ public function exists($name)
+ {
+ return isset($this->data[$name]);
+ }
+
+ /**
+ * extract
+ *
+ * @param string $name
+ *
+ * @return static
+ */
+ public function extract($name)
+ {
+ return new static($this->get($name, array(), 'raw'));
+ }
+
+ /**
+ * getByPath
+ *
+ * @param string $paths
+ * @param mixed $default
+ * @param string $filter
+ *
+ * @return array|null
+ */
+ public function getByPath($paths, $default = null, $filter = InputFilter::CMD)
+ {
+ if (empty($paths))
+ {
+ return null;
+ }
+
+ $args = is_array($paths) ? $paths : explode('.', $paths);
+
+ $dataTmp = $this->data;
+
+ foreach ($args as $arg)
+ {
+ if (is_object($dataTmp) && !empty($dataTmp->$arg))
+ {
+ $dataTmp = $dataTmp->$arg;
+ }
+ elseif (is_array($dataTmp) && !empty($dataTmp[$arg]))
+ {
+ $dataTmp = $dataTmp[$arg];
+ }
+ else
+ {
+ return $default;
+ }
+ }
+
+ return $this->filter->clean($dataTmp, $filter);
+ }
+
+ /**
+ * setByPath
+ *
+ * @param string $paths
+ * @param mixed $value
+ *
+ * @return bool
+ */
+ public function setByPath($paths, $value)
+ {
+ if (empty($paths))
+ {
+ return false;
+ }
+
+ $args = is_array($paths) ? $paths : explode('.', $paths);
+
+ $dataTmp = &$this->data;
+
+ foreach ($args as $arg)
+ {
+ if (is_object($dataTmp))
+ {
+ if (empty($dataTmp->$arg))
+ {
+ $dataTmp->$arg = array();
+ }
+
+ $dataTmp = &$dataTmp->$arg;
+ }
+ elseif (is_array($dataTmp))
+ {
+ if (empty($dataTmp[$arg]))
+ {
+ $dataTmp[$arg] = array();
+ }
+
+ $dataTmp = &$dataTmp[$arg];
+ }
+ else
+ {
+ $dataTmp = array();
+ }
+ }
+
+ $dataTmp = $value;
+
+ return true;
+ }
+
+ /**
+ * Magic method to get filtered input data.
+ *
+ * @param string $name Name of the filter type prefixed with 'get'.
+ * @param array $arguments [0] The name of the variable [1] The default value.
+ *
+ * @return mixed The filtered input value.
+ *
+ * @since 2.0
+ */
+ public function __call($name, $arguments)
+ {
+ if (substr($name, 0, 3) == 'get')
+ {
+ $filter = substr($name, 3);
+
+ $default = null;
+
+ if (isset($arguments[1]))
+ {
+ $default = $arguments[1];
+ }
+
+ return $this->get($arguments[0], $default, $filter);
+ }
+ }
+
+ /**
+ * Gets the request method.
+ *
+ * @return string The request method.
+ *
+ * @since 2.0
+ */
+ public function getMethod()
+ {
+ if (isset($_SERVER['REQUEST_METHOD']))
+ {
+ return strtoupper($_SERVER['REQUEST_METHOD']);
+ }
+
+ return null;
+ }
+
+ /**
+ * Method to serialize the input.
+ *
+ * @return string The serialized input.
+ *
+ * @since 2.0
+ */
+ public function serialize()
+ {
+ // Load all of the inputs.
+ $this->loadAllInputs();
+
+ // Remove $_ENV and $_SERVER from the inputs.
+ $inputs = $this->inputs;
+ unset($inputs['env']);
+ unset($inputs['server']);
+
+ // Serialize the options, data, and inputs.
+ return serialize(array($this->data, $inputs));
+ }
+
+ /**
+ * Method to unserialize the input.
+ *
+ * @param string $input The serialized input.
+ *
+ * @return Input The input object.
+ *
+ * @since 2.0
+ */
+ public function unserialize($input)
+ {
+ // Unserialize the data, and inputs.
+ list($this->data, $this->inputs) = unserialize($input);
+
+ $this->filter = class_exists('Windwalker\\Filter\\InputFilter') ? new InputFilter : new NullFilter;
+ }
+
+ /**
+ * Method to load all of the global inputs.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ public function loadAllInputs()
+ {
+ static $loaded = false;
+
+ if (!$loaded)
+ {
+ // Load up all the globals.
+ foreach ($GLOBALS as $global => $data)
+ {
+ // Check if the global starts with an underscore.
+ if (strpos($global, '_') === 0)
+ {
+ // Convert global name to input name.
+ $global = strtolower($global);
+ $global = substr($global, 1);
+
+ // Get the input.
+ $this->$global;
+ }
+ }
+
+ $method = $this->getMethod();
+
+ $this->$method;
+
+ $loaded = true;
+ }
+ }
+
+ /**
+ * getAllInputs
+ *
+ * @return Input[]
+ */
+ public function getAllInputs()
+ {
+ $this->loadAllInputs();
+
+ return $this->inputs;
+ }
+
+ /**
+ * dumpAllInputs
+ *
+ * @return array
+ */
+ public function dumpAllInputs()
+ {
+ $inputs = $this->getAllInputs();
+
+ $return = array();
+
+ foreach ($inputs as $key => $input)
+ {
+ $return[$key] = $input->getArray();
+ }
+
+ return $return;
+ }
+
+ /**
+ * Method to set property data
+ *
+ * @param array $data
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setData($data)
+ {
+ $this->data = $data;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/JsonInput.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/JsonInput.php
new file mode 100644
index 00000000..389544a8
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/JsonInput.php
@@ -0,0 +1,54 @@
+data = json_decode($raw, true);
+
+ if (!is_array($this->data))
+ {
+ $this->data = array();
+ }
+ }
+ else
+ {
+ if ($reference)
+ {
+ $this->data = &$source;
+ }
+ else
+ {
+ $this->data = $source;
+ }
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/README.md b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/README.md
new file mode 100644
index 00000000..0b5e2c97
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/README.md
@@ -0,0 +1,261 @@
+# Windwalker IO
+
+Windwalker IO package is an input & output handler to get request or send output to user terminal.
+
+This package is heavily based on Joomla Input but has modified a lot, please see original concept of [Joomla Wiki](http://docs.joomla.org/Retrieving_request_data_using_JInput).
+
+## Installation via Composer
+
+Add this to the require block in your `composer.json`.
+
+``` json
+{
+ "require": {
+ "windwalker/io": "~2.0"
+ }
+}
+```
+
+## Web Input
+
+Mostly, we will need to get request data from http, the `$_GET`, `$_POST` or `$_REQUEST` provides us these data.
+
+But it is very unsafe if we only use super global variables, the Input object can help us get values from these variables and clean every string.
+
+``` php
+use Windwalker\IO\Input;
+
+$input = new Input;
+
+$input->get('flower'); // Same as $_REQUEST['flower']
+
+$input->set('flower', 'sakura');
+```
+
+The second argument is default value if request params not exists
+
+``` php
+$input->get('flower', 'default');
+```
+
+### Filter
+
+Input use [Windwalker Filter](https://github.com/ventoviro/windwalker-filter) package to clean request string, the default filter type is `CMD`.
+We can use other filter type:
+
+``` php
+// mysite.com/?flower=to be, or not to be.
;
+
+$input->get('flower'); // tobeornottobe (Default cmd filter)
+
+$input->get('flower', 'default_value', InputFilter::STRING); // to be, or not to be
+
+$input->getString('flower'); // to be, or not to be (Same as above, using magic method)
+
+$input->getRaw('flower') // to be, or not to be.
+```
+
+More filter usage please see: [Windwalker Filter](https://github.com/ventoviro/windwalker-filter)
+
+### Get Array
+
+Input is able to get data as array.
+
+``` php
+// mysite.com/?flower[1]=sakura&flower[2]=olive;
+
+$input->get('flower', InputFilter::ARRAY); // Array( [1] => sakura [2] => olive)
+```
+
+Use `getArray()` method
+
+``` php
+// mysite.com/?flower=sakura&foo=bar&king=Richard
+
+// Get all request
+$input->getArray();
+
+// To retrieve values you want
+$array(
+ 'flower' => '',
+ 'king' => '',
+);
+
+$input->getArray($array); // Array( [flower] => sakura [king] => Richard)
+
+// Specify different filters for each of the inputs:
+$array(
+ 'flower' => InputFilter::CMD,
+ 'king' => InputFilter::STRING,
+);
+
+// Use nested array to get more complicated hierarchies of values
+
+$input->getArray(array(
+ 'windwalker' => array(
+ 'title' => InputFilter::STRING,
+ 'quantity' => InputFilter::INTEGER,
+ 'state' => 'integer' // Same as above
+ )
+));
+```
+
+### Get And Set Multi-Level
+
+If we want to get value of `foo[bar][baz]`, just use `setByPath()`:
+
+``` php
+$value = $input->getByPath('foo.bar.baz', 'default', InputFilter::STRING);
+
+$input->setByPath('foo.bar.baz', $data);
+```
+
+### Get Value From Other Methods
+
+We can get other methods as a new input object.
+
+``` php
+$post = $input->post;
+
+$value = $post->get('foo', 'bar');
+
+// Other inputs
+$get = $input->get;
+$put = $input->put;
+$delete = $input->delete;
+```
+
+## Get SUPER GLOBALS
+
+``` php
+$env = $input->env;
+$session = $input->session;
+$cookie = $input->cookie;
+$server = $input->server;
+
+$server->get('REMOTE_ADDR'); // Same as $_SERVER['REMOTE_ADDR'];
+```
+
+See: [SUPER GLOBALS](http://php.net/manual/en/language.variables.superglobals.php)
+
+### Get method of current request:
+
+``` php
+$method = $input->getMethod();
+```
+
+## Files Input
+
+The format that PHP returns file data in for arrays can at times be awkward, especially when dealing with arrays of files.
+FilesInput provides a convenient interface for making life a little easier, grouping the data by file.
+
+Suppose you have a form like:
+
+``` html
+
+```
+
+Normally, PHP would put these in an array called `$_FILES` that looked like:
+
+```
+Array
+(
+ [flower] => Array
+ (
+ [name] => Array
+ (
+ [test] => Array
+ (
+ [0] => youtube_icon.png
+ [1] => Younger_Son_2.jpg
+ )
+
+ )
+
+ [type] => Array
+ (
+ [test] => Array
+ (
+ [0] => image/png
+ [1] => image/jpeg
+ )
+
+ )
+
+ [tmp_name] => Array
+ (
+ [test] => Array
+ (
+ [0] => /tmp/phpXoIpSD
+ [1] => /tmp/phpWDE7ye
+ )
+
+ )
+
+ [error] => Array
+ (
+ [test] => Array
+ (
+ [0] => 0
+ [1] => 0
+ )
+
+ )
+
+ [size] => Array
+ (
+ [test] => Array
+ (
+ [0] => 34409
+ [1] => 99529
+ )
+
+ )
+
+ )
+
+)
+```
+
+FilesInput produces a result that is cleaner and easier to work with:
+
+``` php
+$files = $input->files->get('flower');
+```
+
+`$files` then becomes:
+
+```
+Array
+(
+ [test] => Array
+ (
+ [0] => Array
+ (
+ [name] => youtube_icon.png
+ [type] => image/png
+ [tmp_name] => /tmp/phpXoIpSD
+ [error] => 0
+ [size] => 34409
+ )
+
+ [1] => Array
+ (
+ [name] => Younger_Son_2.jpg
+ [type] => image/jpeg
+ [tmp_name] => /tmp/phpWDE7ye
+ [error] => 0
+ [size] => 99529
+ )
+
+ )
+)
+```
+
+## CLI Input & Output
+
+Please see [Cli README](Cli)
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/CliInputTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/CliInputTest.php
new file mode 100644
index 00000000..e73f3a3d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/CliInputTest.php
@@ -0,0 +1,486 @@
+instance = new CliInput;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test serialize().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Input\CliInput::serialize
+ * @TODO Implement testSerialize().
+ */
+ public function testSerialize()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test get().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Input\CliInput::get
+ * @TODO Implement testGet().
+ */
+ public function testGet()
+ {
+ $_SERVER['argv'] = array('/dev/null', '--foo=bar', '-ab', 'blah', '-g', 'flower sakura');
+
+ $this->instance = new CliInput;
+
+ $this->assertEquals(
+ 'bar',
+ $this->instance->get('foo'),
+ 'Line: ' . __LINE__ . '.'
+ );
+
+ $this->assertEquals(
+ true,
+ $this->instance->get('a'),
+ 'Line: ' . __LINE__ . '.'
+ );
+
+ $this->assertEquals(
+ true,
+ $this->instance->get('b'),
+ 'Line: ' . __LINE__ . '.'
+ );
+
+ $this->assertEquals(
+ array('blah'),
+ $this->instance->args,
+ 'Line: ' . __LINE__ . '.'
+ );
+
+ // Default filter
+ $this->assertEquals(
+ 'flower sakura',
+ $this->instance->get('g'),
+ 'Default filter should be string. Line: ' . __LINE__
+ );
+ }
+
+ /**
+ * Test the Windwalker\IO\Cli::get method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli::get
+ * @covers Windwalker\IO\Cli::parseArguments
+ * @since 2.0
+ */
+ public function testParseLongArguments()
+ {
+ $_SERVER['argv'] = array('/dev/null', '--ab', 'cd', '--ef', '--gh=bam');
+
+ $this->instance = new CliInput;
+
+ $this->assertThat(
+ $this->instance->get('ab'),
+ $this->identicalTo('cd'),
+ 'Line: ' . __LINE__ . '.'
+ );
+
+ $this->assertThat(
+ $this->instance->get('ef'),
+ $this->identicalTo('1'),
+ 'Line: ' . __LINE__ . '.'
+ );
+
+ $this->assertThat(
+ $this->instance->get('gh'),
+ $this->identicalTo('bam'),
+ 'Line: ' . __LINE__ . '.'
+ );
+
+ $this->assertEmpty(
+ $this->instance->args,
+ 'Line: ' . __LINE__ . '.'
+ );
+ }
+
+ /**
+ * Test the Windwalker\IO\Cli::get method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli::get
+ * @covers Windwalker\IO\Cli::parseArguments
+ * @since 2.0
+ */
+ public function testParseShortArguments()
+ {
+ $_SERVER['argv'] = array('/dev/null', '-ab', '-c', '-e', 'f', 'foobar', 'ghijk');
+
+ $this->instance = new CliInput;
+
+ $this->assertThat(
+ $this->instance->get('a'),
+ $this->identicalTo('1'),
+ 'Line: ' . __LINE__ . '.'
+ );
+
+ $this->assertThat(
+ $this->instance->get('b'),
+ $this->identicalTo('1'),
+ 'Line: ' . __LINE__ . '.'
+ );
+
+ $this->assertThat(
+ $this->instance->get('c'),
+ $this->identicalTo('1'),
+ 'Line: ' . __LINE__ . '.'
+ );
+
+ $this->assertThat(
+ $this->instance->get('e'),
+ $this->identicalTo('f'),
+ 'Line: ' . __LINE__ . '.'
+ );
+
+ $this->assertThat(
+ $this->instance->args,
+ $this->equalTo(array('foobar', 'ghijk')),
+ 'Line: ' . __LINE__ . '.'
+ );
+ }
+
+ /**
+ * Test the JInput::parseArguments method.
+ *
+ * @dataProvider provider_parseArguments
+ */
+ public function testParseArguments($inputArgv, $expectedData, $expectedArgs)
+ {
+ $_SERVER['argv'] = $inputArgv;
+
+ $this->instance = new CliInput;
+
+ $this->assertThat(
+ TestHelper::getValue($this->instance, 'data'),
+ $this->identicalTo($expectedData)
+ );
+
+ $this->assertThat(
+ $this->instance->args,
+ $this->identicalTo($expectedArgs)
+ );
+ }
+
+ /**
+ * Test inputs:
+ *
+ * php test.php --foo --bar=baz
+ * php test.php -abc
+ * php test.php arg1 arg2 arg3
+ * php test.php plain-arg --foo --bar=baz --funny="spam=eggs" --also-funny=spam=eggs \
+ * 'plain arg 2' -abc -k=value "plain arg 3" --s="original" --s='overwrite' --s
+ * php test.php --key value -abc not-c-value
+ * php test.php --key1 value1 -a --key2 -b b-value --c
+ *
+ * Note that this pattern is not supported: -abc c-value
+ */
+ public function provider_parseArguments()
+ {
+ return array(
+
+ // php test.php --foo --bar=baz
+ array(
+ array('test.php', '--foo', '--bar=baz'),
+ array(
+ 'foo' => true,
+ 'bar' => 'baz'
+ ),
+ array()
+ ),
+
+ // php test.php -abc
+ array(
+ array('test.php', '-abc'),
+ array(
+ 'a' => true,
+ 'b' => true,
+ 'c' => true
+ ),
+ array()
+ ),
+
+ // php test.php arg1 arg2 arg3
+ array(
+ array('test.php', 'arg1', 'arg2', 'arg3'),
+ array(),
+ array(
+ 'arg1',
+ 'arg2',
+ 'arg3'
+ )
+ ),
+
+ // php test.php plain-arg --foo --bar=baz --funny="spam=eggs" --also-funny=spam=eggs \
+ // 'plain arg 2' -abc -k=value "plain arg 3" --s="original" --s='overwrite' --s
+ array(
+ array('test.php', 'plain-arg', '--foo', '--bar=baz', '--funny=spam=eggs', '--also-funny=spam=eggs',
+ 'plain arg 2', '-abc', '-k=value', 'plain arg 3', '--s=original', '--s=overwrite', '--s'),
+ array(
+ 'foo' => true,
+ 'bar' => 'baz',
+ 'funny' => 'spam=eggs',
+ 'also-funny' => 'spam=eggs',
+ 'a' => true,
+ 'b' => true,
+ 'c' => true,
+ 'k' => 'value',
+ 's' => 'overwrite'
+ ),
+ array(
+ 'plain-arg',
+ 'plain arg 2',
+ 'plain arg 3'
+ )
+ ),
+
+ // php test.php --key value -abc not-c-value
+ array(
+ array('test.php', '--key', 'value', '-abc', 'not-c-value'),
+ array(
+ 'key' => 'value',
+ 'a' => true,
+ 'b' => true,
+ 'c' => true
+ ),
+ array(
+ 'not-c-value'
+ )
+ ),
+
+ // php test.php --key1 value1 -a --key2 -b b-value --c
+ array(
+ array('test.php', '--key1', 'value1', '-a', '--key2', '-b', 'b-value', '--c'),
+ array(
+ 'key1' => 'value1',
+ 'a' => true,
+ 'key2' => true,
+ 'b' => 'b-value',
+ 'c' => true
+ ),
+ array()
+ )
+ );
+ }
+
+ /**
+ * Test the Windwalker\IO\Cli::get method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli::get
+ * @since 2.0
+ */
+ public function testGetFromServer()
+ {
+ // Check the object type.
+ $this->assertInstanceOf(
+ 'Windwalker\\IO\\Input',
+ $this->instance->server,
+ 'Line: ' . __LINE__ . '.'
+ );
+
+ // Test the get method.
+ $this->assertThat(
+ $this->instance->server->get('PHP_SELF', null, InputFilter::STRING),
+ $this->identicalTo($_SERVER['PHP_SELF']),
+ 'Line: ' . __LINE__ . '.'
+ );
+ }
+
+ /**
+ * Method to test all().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Input\CliInput::all
+ */
+ public function testAll()
+ {
+ $_SERVER['argv'] = array('/dev/null', '-ab', '-c', '-e', 'f', 'foobar', 'ghijk');
+
+ $this->instance = new CliInput;
+
+ $this->assertEquals(array('a' => 1, 'b' => 1, 'c' => 1, 'e' => 'f'), $this->instance->all());
+ }
+
+ /**
+ * Method to test unserialize().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Input\CliInput::unserialize
+ * @TODO Implement testUnserialize().
+ */
+ public function testUnserialize()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getArgument().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Input\CliInput::getArgument
+ */
+ public function testGetArgument()
+ {
+ $_SERVER['argv'] = array('/dev/null', '-ab', '-c', '-e', 'f', 'foobar', 'ghijk');
+
+ $input = new CliInput;
+
+ $this->assertEquals('foobar', $input->getArgument(0));
+ $this->assertEquals('d', $input->getArgument(5, 'd'));
+ }
+
+ /**
+ * Method to test setArgument().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Input\CliInput::setArgument
+ */
+ public function testSetArgument()
+ {
+ $_SERVER['argv'] = array('/dev/null', '-ab', '-c', '-e', 'f', 'foobar', 'ghijk');
+
+ $input = new CliInput;
+
+ $input->setArgument(2, 'bar');
+
+ $this->assertEquals('bar', $input->getArgument(2));
+ }
+
+ /**
+ * Method to test in().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Input\CliInput::in
+ */
+ public function testIn()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getInputStream().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Input\CliInput::getInputStream
+ */
+ public function testGetInputStream()
+ {
+ $this->assertEquals(STDIN, $this->instance->getInputStream());
+ }
+
+ /**
+ * Method to test setInputStream().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Input\CliInput::setInputStream
+ * @TODO Implement testSetInputStream().
+ */
+ public function testSetInputStream()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getCalledScript().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Input\CliInput::getCalledScript
+ */
+ public function testGetCalledScript()
+ {
+ $_SERVER['argv'] = array('/dev/null', '-ab', '-c', '-e', 'f', 'foobar', 'ghijk');
+
+ $input = new CliInput;
+
+ $this->assertEquals('/dev/null', $input->getCalledScript());
+ }
+
+ /**
+ * Method to test setCalledScript().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Input\CliInput::setCalledScript
+ * @TODO Implement testSetCalledScript().
+ */
+ public function testSetCalledScript()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/CliOutputTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/CliOutputTest.php
new file mode 100644
index 00000000..3971591d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/CliOutputTest.php
@@ -0,0 +1,111 @@
+instance = new CliOutput;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test out().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Output\CliOutput::out
+ * @TODO Implement testOut().
+ */
+ public function testOut()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test err().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Output\CliOutput::err
+ * @TODO Implement testErr().
+ */
+ public function testErr()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setProcessor().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Output\CliOutput::setProcessor
+ * @TODO Implement testSetProcessor().
+ */
+ public function testSetProcessor()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getProcessor().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Output\CliOutput::getProcessor
+ * @TODO Implement testGetProcessor().
+ */
+ public function testGetProcessor()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/ColorProcessorTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/ColorProcessorTest.php
new file mode 100644
index 00000000..29809527
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/ColorProcessorTest.php
@@ -0,0 +1,154 @@
+instance = new ColorProcessor;
+
+ $this->winOs = TestEnvironment::isWindows();
+
+ if ($this->winOs)
+ {
+ $this->instance->setNoColors(true);
+ }
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test addStyle().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Color\ColorProcessor::addStyle
+ */
+ public function testAddStyle()
+ {
+ $style = new ColorStyle('red');
+ $this->instance->addStyle('foo', $style);
+
+ $check = ($this->winOs) ? 'foo' : '[31mfoo[0m';
+
+ $this->assertThat(
+ $this->instance->process('foo '),
+ $this->equalTo($check)
+ );
+ }
+
+ /**
+ * Method to test stripColors().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Color\ColorProcessor::stripColors
+ */
+ public function testStripColors()
+ {
+ $this->assertThat(
+ $this->instance->stripColors('foo '),
+ $this->equalTo('foo')
+ );
+ }
+
+ /**
+ * Method to test process().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Color\ColorProcessor::process
+ */
+ public function testProcess()
+ {
+ $check = ($this->winOs) ? 'foo' : '[31mfoo[0m';
+
+ $this->assertThat(
+ $this->instance->process('foo '),
+ $this->equalTo($check)
+ );
+ }
+
+ /**
+ * Tests the process method for replacing colors
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Color\ColorProcessor::process
+ * @since 2.0
+ */
+ public function testProcessNamed()
+ {
+ $style = new ColorStyle('red');
+ $this->instance->addStyle('foo', $style);
+
+ $check = ($this->winOs) ? 'foo' : '[31mfoo[0m';
+
+ $this->assertThat(
+ $this->instance->process('foo '),
+ $this->equalTo($check)
+ );
+ }
+
+ /**
+ * Tests the process method for replacing colors
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\Color\ColorProcessor::replaceColors
+ * @since 2.0
+ */
+ public function testProcessReplace()
+ {
+ $check = ($this->winOs) ? 'foo' : '[31mfoo[0m';
+
+ $this->assertThat(
+ $this->instance->process('foo '),
+ $this->equalTo($check)
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/ColorStyleTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/ColorStyleTest.php
new file mode 100644
index 00000000..d1c0a2c7
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/ColorStyleTest.php
@@ -0,0 +1,138 @@
+instance = new ColorStyle('red', 'white', array('blink'));
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Test the GetStyle method.
+ *
+ * @covers Windawlker\IO\Cli\Color\ColorStyle::getStyle
+ *
+ * @return void
+ */
+ public function testGetStyle()
+ {
+ $this->assertThat(
+ $this->instance->getStyle(),
+ $this->equalTo('31;47;5')
+ );
+ }
+
+ /**
+ * Test the ToString method.
+ *
+ * @return void
+ */
+ public function testToString()
+ {
+ $this->assertThat(
+ $this->instance->__toString(),
+ $this->equalTo('31;47;5')
+ );
+ }
+
+ /**
+ * Test the __construct method.
+ *
+ * @return void
+ */
+ public function fromString()
+ {
+ $style = new ColorStyle('white', 'red', array('blink', 'bold'));
+
+ $this->assertThat(
+ $this->instance->fromString('fg=white;bg=red;options=blink,bold'),
+ $this->equalTo($style)
+ );
+ }
+
+ /**
+ * Test the fromString method.
+ *
+ * @expectedException \RuntimeException
+ *
+ * @return void
+ */
+ public function testFromStringInvalid()
+ {
+ $this->instance->fromString('XXX;XX=YY');
+ }
+
+ /**
+ * Test the __construct method.
+ *
+ * @expectedException \InvalidArgumentException
+ *
+ * @return void
+ */
+ public function testConstructInvalid1()
+ {
+ new ColorStyle('INVALID');
+ }
+
+ /**
+ * Test the __construct method.
+ *
+ * @expectedException \InvalidArgumentException
+ *
+ * @return void
+ */
+ public function testConstructInvalid2()
+ {
+ new ColorStyle('', 'INVALID');
+ }
+
+ /**
+ * Test the __construct method.
+ *
+ * @expectedException \InvalidArgumentException
+ *
+ * @return void
+ */
+ public function testConstructInvalid3()
+ {
+ new ColorStyle('', '', array('INVALID'));
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/IOTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/IOTest.php
new file mode 100644
index 00000000..f6a8a058
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/Cli/IOTest.php
@@ -0,0 +1,415 @@
+instance = new IO;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test out().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::out
+ * @TODO Implement testOut().
+ */
+ public function testOut()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test in().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::in
+ * @TODO Implement testIn().
+ */
+ public function testIn()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test err().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::err
+ * @TODO Implement testErr().
+ */
+ public function testErr()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getOption().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::getOption
+ * @TODO Implement testGetOption().
+ */
+ public function testGetOption()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setOption().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::setOption
+ * @TODO Implement testSetOption().
+ */
+ public function testSetOption()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getArgument().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::getArgument
+ * @TODO Implement testGetArgument().
+ */
+ public function testGetArgument()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setArgument().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::setArgument
+ * @TODO Implement testSetArgument().
+ */
+ public function testSetArgument()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getInput().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::getInput
+ * @TODO Implement testGetInput().
+ */
+ public function testGetInput()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setInput().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::setInput
+ * @TODO Implement testSetInput().
+ */
+ public function testSetInput()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getOutput().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::getOutput
+ * @TODO Implement testGetOutput().
+ */
+ public function testGetOutput()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setOutput().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::setOutput
+ * @TODO Implement testSetOutput().
+ */
+ public function testSetOutput()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getCalledScript().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::getCalledScript
+ * @TODO Implement testGetCalledScript().
+ */
+ public function testGetCalledScript()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getOptions().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::getOptions
+ * @TODO Implement testGetOptions().
+ */
+ public function testGetOptions()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getArguments().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::getArguments
+ * @TODO Implement testGetArguments().
+ */
+ public function testGetArguments()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test offsetSet().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::offsetSet
+ * @TODO Implement testOffsetSet().
+ */
+ public function testOffsetSet()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test offsetUnset().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::offsetUnset
+ * @TODO Implement testOffsetUnset().
+ */
+ public function testOffsetUnset()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test offsetExists().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::offsetExists
+ * @TODO Implement testOffsetExists().
+ */
+ public function testOffsetExists()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test offsetGet().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::offsetGet
+ * @TODO Implement testOffsetGet().
+ */
+ public function testOffsetGet()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getIterator().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::getIterator
+ * @TODO Implement testGetIterator().
+ */
+ public function testGetIterator()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test serialize().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::serialize
+ * @TODO Implement testSerialize().
+ */
+ public function testSerialize()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test unserialize().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::unserialize
+ * @TODO Implement testUnserialize().
+ */
+ public function testUnserialize()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test count().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::count
+ * @TODO Implement testCount().
+ */
+ public function testCount()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test jsonSerialize().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cli\IO::jsonSerialize
+ * @TODO Implement testJsonSerialize().
+ */
+ public function testJsonSerialize()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/CookieTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/CookieTest.php
new file mode 100644
index 00000000..874a60ec
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/CookieTest.php
@@ -0,0 +1,109 @@
+instance = new Cookie;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Test the Windwalker\IO\Cookie::__construct method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cookie::__construct
+ * @since 2.0
+ */
+ public function test__construct()
+ {
+ // Default constructor call
+ $instance = new Cookie;
+
+ $this->assertEquals(
+ $_COOKIE,
+ TestHelper::getValue($instance, 'data')
+ );
+ }
+
+ /**
+ * Test the Windwalker\IO\Cookie::set method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Cookie::set
+ * @since 2.0
+ */
+ public function testSet()
+ {
+ $instance = new Cookie;
+ $instance->set('foo', 'bar');
+
+ $data = TestHelper::getValue($instance, 'data');
+
+ $this->assertArrayHasKey('foo', $data);
+ $this->assertContains('bar', $data);
+ }
+}
+
+// Stub for setcookie
+namespace Windwalker\IO;
+
+/**
+ * Stub.
+ *
+ * @param string $name Name
+ * @param string $value Value
+ * @param int $expire Expire
+ * @param string $path Path
+ * @param string $domain Domain
+ * @param bool $secure Secure
+ * @param bool $httpOnly HttpOnly
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+function setcookie($name, $value, $expire = 0, $path = '', $domain = '', $secure = false, $httpOnly = false)
+{
+ return true;
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/FilesInputTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/FilesInputTest.php
new file mode 100644
index 00000000..e46907ee
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/FilesInputTest.php
@@ -0,0 +1,203 @@
+instance = new FilesInput;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Test the Windwalker\Input\Files::__construct method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Files::__construct
+ * @since 2.0
+ */
+ public function test__construct()
+ {
+ $this->assertEquals(
+ $_FILES,
+ TestHelper::getValue($this->instance, 'data')
+ );
+ }
+
+ /**
+ * Test the Windwalker\Input\Files::get method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Files::get
+ * @since 2.0
+ */
+ public function testGet()
+ {
+ $this->assertEquals('foobar', $this->instance->get('myfile', 'foobar'));
+
+ $data = array(
+ 'myfile' => array(
+ 'name' => 'n',
+ 'type' => 'ty',
+ 'tmp_name' => 'tm',
+ 'error' => 'e',
+ 'size' => 's'
+ ),
+ 'myfile2' => array(
+ 'name' => 'nn',
+ 'type' => 'ttyy',
+ 'tmp_name' => 'ttmm',
+ 'error' => 'ee',
+ 'size' => 'ss'
+ )
+ );
+
+ TestHelper::setValue($this->instance, 'data', $data);
+
+ $expected = array(
+ 'name' => 'n',
+ 'type' => 'ty',
+ 'tmp_name' => 'tm',
+ 'error' => 'e',
+ 'size' => 's'
+ );
+
+ $this->assertEquals($expected, $this->instance->get('myfile'));
+
+ $data2 = array(
+ 'foo' => array(
+ 'name' => array(
+ 'myfile' => 'n',
+ 'myfile2' => 'nn'
+ ),
+ 'type' => array(
+ 'myfile' => 'ty',
+ 'myfile2' => 'ttyy'
+ ),
+ 'tmp_name' => array(
+ 'myfile' => 'tm',
+ 'myfile2' => 'ttmm'
+ ),
+ 'error' => array(
+ 'myfile' => 'e',
+ 'myfile2' => 'ee'
+ ),
+ 'size' => array(
+ 'myfile' => 's',
+ 'myfile2' => 'ss'
+ )
+ )
+ );
+
+ TestHelper::setValue($this->instance, 'data', $data2);
+
+ $this->assertEquals($data, $this->instance->get('foo'));
+
+ // We don't convert data structure for getByPath() now.
+ $this->assertEquals('n', $this->instance->getByPath('foo.name.myfile'));
+ }
+
+ /**
+ * Test the Windwalker\Input\Files::decodeData method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Files::decodeData
+ * @since 2.0
+ */
+ public function testDecodeData()
+ {
+ $data = array('n', 'ty', 'tm', 'e', 's');
+
+ $decoded = TestHelper::invoke($this->instance, 'decodeData', $data);
+
+ $expected = array(
+ 'name' => 'n',
+ 'type' => 'ty',
+ 'tmp_name' => 'tm',
+ 'error' => 'e',
+ 'size' => 's'
+ );
+
+ $this->assertEquals($expected, $decoded);
+
+ $dataArr = array('first', 'second');
+ $data = array($dataArr , $dataArr, $dataArr, $dataArr, $dataArr);
+
+ $decoded = TestHelper::invoke($this->instance, 'decodeData', $data);
+
+ $expectedFirst = array(
+ 'name' => 'first',
+ 'type' => 'first',
+ 'tmp_name' => 'first',
+ 'error' => 'first',
+ 'size' => 'first'
+ );
+
+ $expectedSecond = array(
+ 'name' => 'second',
+ 'type' => 'second',
+ 'tmp_name' => 'second',
+ 'error' => 'second',
+ 'size' => 'second'
+ );
+
+ $expected = array($expectedFirst, $expectedSecond);
+
+ $this->assertEquals($expected, $decoded);
+ }
+
+ /**
+ * Test the Windwalker\Input\Files::set method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Files::set
+ * @since 2.0
+ */
+ public function testSet()
+ {
+ $this->instance->set('foo', 'bar');
+
+ $this->assertEquals(null, $this->instance->get('foo'));
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/FormDataInputTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/FormDataInputTest.php
new file mode 100644
index 00000000..6206ef11
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/FormDataInputTest.php
@@ -0,0 +1,137 @@
+instance = new FormDataInput(array());
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Test the Windwalker\IO\Json::__construct method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Json::__construct
+ * @since 2.0
+ */
+ public function test__construct()
+ {
+ $this->assertInstanceOf(
+ 'Windwalker\Filter\InputFilter',
+ TestHelper::getValue($this->instance, 'filter')
+ );
+
+ $this->assertEmpty(
+ TestHelper::getValue($this->instance, 'data')
+ );
+
+ // Given Source & filter
+ $src = array('foo' => 'bar');
+ $input = new FormDataInput($src);
+
+ $this->assertEquals(
+ $src,
+ TestHelper::getValue($input, 'data')
+ );
+
+ // Src from GLOBAL
+ FormDataInput::setRawData(null);
+
+ $_SERVER['CONTENT_TYPE'] = 'multipart/form-data; boundary=----WebKitFormBoundary8zi5vcW6H9OgqKSj';
+
+ $GLOBALS['HTTP_RAW_POST_DATA'] = <<assertEquals(
+ array('flower' => 'SAKURA', 'tree' => 'Marabutan', 'fruit' => 'Apple'),
+ TestHelper::getValue($input, 'data')
+ );
+ }
+
+ /**
+ * Method to test getRawData().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\FormDataInput::getRawData
+ * @TODO Implement testGetRawData().
+ */
+ public function testGetRawData()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test parseFormData().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\FormDataInput::parseFormData
+ * @TODO Implement testParseFormData().
+ */
+ public function testParseFormData()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/InputTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/InputTest.php
new file mode 100644
index 00000000..d199da7c
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/InputTest.php
@@ -0,0 +1,582 @@
+instance = new Input;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Test the Windwalker\Input\Input::__construct method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::__construct
+ */
+ public function test__construct()
+ {
+ // Default constructor call
+ $instance = new Input;
+
+ $this->assertEquals(
+ $_REQUEST,
+ TestHelper::getValue($instance, 'data')
+ );
+
+ $this->assertInstanceOf(
+ 'Windwalker\Filter\InputFilter',
+ TestHelper::getValue($instance, 'filter')
+ );
+
+ // Given source & filter
+ $instance = new Input($_GET, new InputFilter);
+
+ $this->assertEquals(
+ $_GET,
+ TestHelper::getValue($instance, 'data')
+ );
+
+ $this->assertInstanceOf(
+ 'Windwalker\Filter\InputFilter',
+ TestHelper::getValue($instance, 'filter')
+ );
+ }
+
+ /**
+ * testPrepareSource
+ *
+ * @return void
+ */
+ public function testPrepareSource()
+ {
+ $_REQUEST['foo'] = 'bar';
+
+ $instance = new Input;
+
+ $instance->prepareSource($_REQUEST, true);
+
+ $this->assertSame($_REQUEST, TestHelper::getValue($instance, 'data'));
+
+ $instance->set('foo', 'baz');
+
+ $this->assertEquals('baz', $instance->get('foo'));
+ }
+
+ /**
+ * Method to test __get().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Input::__get
+ */
+ public function test__get()
+ {
+ $instance = $this->newInstance(array());
+
+ $this->assertAttributeEquals($_GET, 'data', $instance->get);
+
+ $inputs = TestHelper::getValue($instance, 'inputs');
+
+ // Previously cached input
+ $this->assertArrayHasKey('get', $inputs);
+
+ $this->assertTrue($inputs['get'] instanceof Input);
+
+ $this->assertAttributeEquals($_GET, 'data', $instance->get);
+
+ $cookies = $instance->cookie;
+ $this->assertInstanceOf('Windwalker\IO\Input', $cookies);
+ $this->assertInstanceOf('Windwalker\IO\Cookie', $cookies);
+
+ // If nothing is returned
+ $this->assertEquals(null, $instance->foobar);
+ }
+
+ /**
+ * Method to test count().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Input::count
+ */
+ public function testCount()
+ {
+ $input = $this->newInstance(array('foo' => 2, 'bar' => 3, 'gamma' => 4));
+
+ $this->assertEquals(3, $input->count());
+
+ $input = $this->newInstance();
+
+ $this->assertEquals(0, $input->count());
+ }
+
+
+ /**
+ * Test the Windwalker\Input\Input::get method with a normal value.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::get
+ * @since 2.0
+ */
+ public function testGetWithStandardValue()
+ {
+ $instance = $this->newInstance(array('foo' => 'bar'));
+
+ $this->assertEquals('bar', $instance->get('foo'));
+ }
+
+ /**
+ * Test the Windwalker\Input\Input::get method with empty string.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::get
+ * @since 2.0
+ */
+ public function testGetWithEmptyString()
+ {
+ $instance = $this->newInstance(array('foo' => ''));
+
+ $this->assertEquals('', $instance->get('foo'));
+
+ $this->assertInternalType('string', $instance->get('foo'));
+ }
+
+ /**
+ * Test the Windwalker\Input\Input::get method with integer 0.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::get
+ * @since 2.0
+ */
+ public function testGetWith0()
+ {
+ $instance = $this->newInstance(array('foo' => 0));
+
+ $this->assertEquals(0, $instance->getInt('foo'));
+
+ $this->assertInternalType('integer', $instance->getInt('foo'));
+ }
+
+ /**
+ * Test the Windwalker\Input\Input::get method with float 0.0.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::get
+ * @since 2.0
+ */
+ public function testGetWith0Point0()
+ {
+ $instance = $this->newInstance(array('foo' => 0.0));
+
+ $this->assertEquals(0.0, $instance->getFloat('foo'));
+
+ $this->assertInternalType('float', $instance->getFloat('foo'));
+ }
+
+ /**
+ * Test the Windwalker\Input\Input::get method with string "0".
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::get
+ * @since 2.0
+ */
+ public function testGetWithString0()
+ {
+ $instance = $this->newInstance(array('foo' => "0"));
+
+ $this->assertEquals("0", $instance->get('foo'));
+
+ $this->assertInternalType('string', $instance->get('foo'));
+ }
+
+ /**
+ * Test the Windwalker\Input\Input::get method with false.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::get
+ * @since 2.0
+ */
+ public function testGetWithFalse()
+ {
+ $instance = $this->newInstance(array('foo' => false));
+
+ $this->assertFalse($instance->getBoolean('foo'));
+
+ $this->assertInternalType('boolean', $instance->getBool('foo'));
+ }
+
+ /**
+ * Tests retrieving a default value..
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::get
+ * @since 2.0
+ */
+ public function testGetDefault()
+ {
+ $instance = $this->newInstance(array('foo' => 'bar'));
+
+ // Test the get method.
+ $this->assertEquals('default', $instance->get('default_value', 'default'));
+ }
+
+ /**
+ * Test the Windwalker\Input\Input::def method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::def
+ * @since 2.0
+ */
+ public function testDefNotReadWhenValueExists()
+ {
+ $instance = $this->newInstance(array('foo' => 'bar'));
+
+ $instance->def('foo', 'nope');
+
+ $this->assertEquals('bar', $instance->get('foo'));
+ }
+
+ /**
+ * Test the Windwalker\Input\Input::def method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::def
+ * @since 2.0
+ */
+ public function testDefRead()
+ {
+ $instance = $this->newInstance(array('foo' => 'bar'));
+
+ $instance->def('bar', 'nope');
+
+ $this->assertEquals('nope', $instance->get('bar'));
+ }
+
+ /**
+ * Test the Windwalker\Input\Input::set method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::set
+ * @since 2.0
+ */
+ public function testSet()
+ {
+ $instance = $this->newInstance(array('foo' => 'bar'));
+
+ $instance->set('foo', 'gamma');
+
+ $this->assertEquals('gamma', $instance->get('foo'));
+ }
+
+ /**
+ * Test the Windwalker\Input\Input::exists method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::exists
+ * @since __DEPLOY_VERSION__
+ */
+ public function testExists()
+ {
+ $instance = $this->newInstance(array('foo' => 'bar'));
+
+ $this->assertTrue($instance->exists('foo'));
+
+ $this->assertFalse($instance->exists('bar'));
+ }
+
+ /**
+ * Test the Windwalker\Input\Input::getArray method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::get
+ * @since 2.0
+ */
+ public function testGetArray()
+ {
+ $array = array(
+ 'var1' => 'value1',
+ 'var2' => 34,
+ 'var3' => array('test')
+ );
+
+ $input = $this->newInstance($array);
+
+ $this->assertEquals(
+ $array,
+ $input->getArray(
+ array('var1' => 'raw', 'var2' => 'raw', 'var3' => 'raw')
+ )
+ );
+
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Test the Windwalker\Input\Input::get method using a nested data set.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::get
+ * @since 2.0
+ */
+ public function testGetArrayNested()
+ {
+ $array = array(
+ 'var2' => 34,
+ 'var3' => array('var2' => 'test'),
+ 'var4' => array('var1' => array('var2' => 'test'))
+ );
+
+ $input = $this->newInstance($array);
+
+ $this->assertEquals(
+ array('var4' => array('var1' => array('var2' => 'test'))),
+ $input->getArray(
+ array(
+ 'var4' => array(
+ 'var1' => array('var2' => 'test')
+ )
+ )
+ )
+ );
+ }
+
+ /**
+ * testGetByPath
+ *
+ * @covers Windwalker\Input\Input::getByPath
+ *
+ * @return void
+ */
+ public function testGetByPath()
+ {
+ $array = array(
+ 'var2' => 34,
+ 'var3' => array('var2' => 'test123'),
+ 'var4' => array('var1' => array('var2' => 'test'))
+ );
+
+ $input = $this->newInstance($array);
+
+ $this->assertEquals('test', $input->getByPath('var4.var1.var2'));
+ $this->assertEquals('default', $input->getByPath('var2.foo.bar', 'default'));
+ $this->assertEquals('123', $input->getByPath('var3.var2', null, InputFilter::INTEGER));
+ }
+
+ /**
+ * testGetByPath
+ *
+ * @covers Windwalker\Input\Input::setByPath
+ *
+ * @return void
+ */
+ public function testSetByPath()
+ {
+ $array = array(
+ 'var2' => 34,
+ 'var3' => array('var2' => 'test123'),
+ 'var4' => array('var1' => array('var2' => 'test'))
+ );
+
+ $input = $this->newInstance($array);
+
+ $input->setByPath('var3.var2', '2567-flower');
+
+ $this->assertEquals('2567', $input->getByPath('var3.var2', null, InputFilter::INTEGER));
+ }
+
+ /**
+ * Test the Windwalker\Input\Input::getArray method without specified variables.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Input\Input::getArray
+ * @since 2.0
+ */
+ public function testGetArrayWithoutSpecifiedVariables()
+ {
+ $array = array(
+ 'var2' => 34,
+ 'var3' => array('var2' => 'test'),
+ 'var4' => array('var1' => array('var2' => 'test')),
+ 'var5' => array('foo' => array()),
+ 'var6' => array('bar' => null),
+ 'var7' => null
+ );
+
+ $input = $this->newInstance($array);
+
+ $this->assertEquals($input->getArray(), $array);
+ }
+
+ /**
+ * Method to test __call().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Input::__call
+ */
+ public function test__call()
+ {
+ $instance = $this->newInstance(array('foo' => 'bar'));
+
+ $this->assertEquals(
+ 'bar',
+ $instance->getRaw('foo')
+ );
+
+ $this->assertEquals(
+ 'two',
+ $instance->getRaw('one', 'two')
+ );
+
+ $this->assertNull(
+ $instance->setRaw('one', 'two')
+ );
+ }
+
+ /**
+ * Method to test getMethod().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Input::getMethod
+ */
+ public function testGetMethod()
+ {
+ $_SERVER['REQUEST_METHOD'] = 'custom';
+
+ $instance = $this->newInstance(array());
+
+ $this->assertEquals('CUSTOM', $instance->getMethod());
+ }
+
+ /**
+ * Method to test serialize().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Input::serialize
+ */
+ public function testSerialize()
+ {
+ $_SERVER['REQUEST_METHOD'] = 'custom';
+
+ $instance = $this->newInstance(array('foo' => 'bar123'));
+
+ $input = unserialize(serialize($instance));
+
+ $this->assertEquals('bar123', $input->get('foo'));
+ $this->assertEquals('123', $input->getInt('foo'));
+ }
+
+ /**
+ * Method to test unserialize().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Input::unserialize
+ * @TODO Implement testUnserialize().
+ */
+ public function testUnserialize()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test loadAllInputs().
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Input::loadAllInputs
+ */
+ public function testLoadAllInputs()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestSkipped(
+ 'A bug that the static $loaded variable has been set to true.....'
+ );
+
+ $instance = $this->newInstance(array());
+ TestHelper::setValue($instance, 'loaded', false);
+
+ $inputs = TestHelper::getValue($instance, 'inputs');
+ $this->assertCount(0, $inputs);
+
+ TestHelper::invoke($instance, 'loadAllInputs');
+
+ $inputs = TestHelper::getValue($instance, 'inputs');
+ $this->assertGreaterThan(0, count($inputs));
+ }
+
+ /**
+ * newInstance
+ *
+ * @param array $data
+ *
+ * @return Input
+ */
+ protected function newInstance($data = array())
+ {
+ return new Input($data);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/JsonInputTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/JsonInputTest.php
new file mode 100644
index 00000000..6b841fb3
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/Test/JsonInputTest.php
@@ -0,0 +1,108 @@
+instance = new JsonInput;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Test the Windwalker\IO\Json::__construct method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\Json::__construct
+ * @since 2.0
+ */
+ public function test__construct()
+ {
+ $this->assertInstanceOf(
+ 'Windwalker\Filter\InputFilter',
+ TestHelper::getValue($this->instance, 'filter')
+ );
+
+ $this->assertEmpty(
+ TestHelper::getValue($this->instance, 'data')
+ );
+
+ // Given Source & filter
+ $src = array('foo' => 'bar');
+ $json = new JsonInput($src);
+
+ $this->assertEquals(
+ $src,
+ TestHelper::getValue($json, 'data')
+ );
+
+ // Src from GLOBAL
+ JsonInput::setRawData(null);
+
+ $GLOBALS['HTTP_RAW_POST_DATA'] = '{"a":1,"b":2}';
+ $json = new JsonInput;
+
+ $this->assertEquals(
+ array('a' => 1, 'b' => 2),
+ TestHelper::getValue($json, 'data')
+ );
+ }
+
+ /**
+ * Test the Windwalker\IO\Json::getRaw method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\IO\JsonInput::getRawData()
+ * @since 2.0
+ */
+ public function testGetRawData()
+ {
+ $GLOBALS['HTTP_RAW_POST_DATA'] = '{"a":1,"b":2}';
+
+ $json = new JsonInput;
+
+ $this->assertEquals(
+ $GLOBALS['HTTP_RAW_POST_DATA'],
+ $json->getRawData()
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/composer.json b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/composer.json
new file mode 100644
index 00000000..310a05c1
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/composer.json
@@ -0,0 +1,29 @@
+{
+ "name": "windwalker/io",
+ "type": "windwalker-package",
+ "description": "Windwalker IO package",
+ "keywords": ["windwalker", "framework", "io"],
+ "homepage": "https://github.com/ventoviro/windwalker-io",
+ "license": "LGPL-2.0+",
+ "require": {
+ "php": ">=5.3.10"
+ },
+ "require-dev": {
+ "windwalker/test": "~2.0",
+ "windwalker/filter": "~2.0"
+ },
+ "suggest": {
+ "windwalker/filter": "Install 2.* if you require filter support."
+ },
+ "minimum-stability": "beta",
+ "autoload": {
+ "psr-4": {
+ "Windwalker\\IO\\": ""
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/phpunit.travis.xml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/phpunit.travis.xml
new file mode 100644
index 00000000..690ec926
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/phpunit.travis.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/phpunit.xml.dist b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/phpunit.xml.dist
new file mode 100644
index 00000000..94b6811c
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/io/phpunit.xml.dist
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/.gitignore b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/.gitignore
new file mode 100644
index 00000000..84718b5d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/.gitignore
@@ -0,0 +1,11 @@
+# Development system files #
+.*
+!/.gitignore
+!/.travis.yml
+
+# Composer #
+vendor/*
+composer.lock
+
+# Test #
+phpunit.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/.travis.yml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/.travis.yml
new file mode 100644
index 00000000..5420e5c4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/.travis.yml
@@ -0,0 +1,16 @@
+language: php
+
+sudo: false
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+
+before_script:
+ - composer update --dev
+
+script:
+ - phpunit --configuration phpunit.travis.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Compat/JsonSerializable.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Compat/JsonSerializable.php
new file mode 100644
index 00000000..99d42d77
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Compat/JsonSerializable.php
@@ -0,0 +1,24 @@
+ $value)
+ {
+ // If the value is an object then we need to put it in a local section.
+ if (is_array($value))
+ {
+ if (!RegistryHelper::isAssociativeArray($value))
+ {
+ continue;
+ }
+
+ // Add the section line.
+ $local[] = '';
+ $local[] = '[' . $key . ']';
+
+ // Add the properties for this section.
+ foreach ($value as $k => $v)
+ {
+ if (is_numeric($k))
+ {
+ continue;
+ }
+
+ $local[] = $k . '=' . static::getValueAsINI($v);
+ }
+ }
+ else
+ {
+ // Not in a section so add the property to the global array.
+ $global[] = $key . '=' . static::getValueAsINI($value);
+ }
+ }
+
+ return implode("\n", array_merge($global, $local));
+ }
+
+ /**
+ * Parse an INI formatted string and convert it into an object.
+ *
+ * @param string $data INI formatted string to convert.
+ * @param array $options An array of options used by the formatter, or a boolean setting to process sections.
+ *
+ * @return object Data object.
+ */
+ public static function stringToStruct($data, array $options = array())
+ {
+ $sections = (isset($options['processSections'])) ? $options['processSections'] : false;
+
+ // Check the memory cache for already processed strings.
+ $hash = md5($data . ':' . (int) $sections);
+
+ if (isset(self::$cache[$hash]))
+ {
+ return self::$cache[$hash];
+ }
+
+ // If no lines present just return the object.
+ if (empty($data))
+ {
+ return new \stdClass;
+ }
+
+ $obj = new \stdClass;
+ $section = false;
+ $lines = explode("\n", $data);
+
+ // Process the lines.
+ foreach ($lines as $line)
+ {
+ // Trim any unnecessary whitespace.
+ $line = trim($line);
+
+ // Ignore empty lines and comments.
+ if (empty($line) || ($line{0} == ';'))
+ {
+ continue;
+ }
+
+ if ($sections)
+ {
+ $length = strlen($line);
+
+ // If we are processing sections and the line is a section add the object and continue.
+ if (($line[0] == '[') && ($line[$length - 1] == ']'))
+ {
+ $section = substr($line, 1, $length - 2);
+ $obj->$section = new \stdClass;
+ continue;
+ }
+ }
+ elseif ($line{0} == '[')
+ {
+ continue;
+ }
+
+ // Check that an equal sign exists and is not the first character of the line.
+ if (!strpos($line, '='))
+ {
+ // Maybe throw exception?
+ continue;
+ }
+
+ // Get the key and value for the line.
+ list ($key, $value) = explode('=', $line, 2);
+
+ // If the value is quoted then we assume it is a string.
+ $length = strlen($value);
+
+ if ($length && ($value[0] == '"') && ($value[$length - 1] == '"'))
+ {
+ // Strip the quotes and Convert the new line characters.
+ $value = stripcslashes(substr($value, 1, ($length - 2)));
+ $value = str_replace('\n', "\n", $value);
+ }
+ else
+ {
+ // If the value is not quoted, we assume it is not a string.
+
+ // If the value is 'false' assume boolean false.
+ if ($value == 'false')
+ {
+ $value = false;
+ }
+ elseif ($value == 'true')
+ // If the value is 'true' assume boolean true.
+ {
+ $value = true;
+ }
+ elseif (is_numeric($value))
+ // If the value is numeric than it is either a float or int.
+ {
+ // If there is a period then we assume a float.
+ if (strpos($value, '.') !== false)
+ {
+ $value = (float) $value;
+ }
+ else
+ {
+ $value = (int) $value;
+ }
+ }
+ }
+
+ // If a section is set add the key/value to the section, otherwise top level.
+ if ($section)
+ {
+ $obj->$section->$key = $value;
+ }
+ else
+ {
+ $obj->$key = $value;
+ }
+ }
+
+ // Cache the string to save cpu cycles -- thus the world :)
+ self::$cache[$hash] = clone ($obj);
+
+ return $obj;
+ }
+
+ /**
+ * Method to get a value in an INI format.
+ *
+ * @param mixed $value The value to convert to INI format.
+ *
+ * @return string The value in INI format.
+ */
+ protected static function getValueAsINI($value)
+ {
+ $string = '';
+
+ switch (gettype($value))
+ {
+ case 'integer':
+ case 'double':
+ $string = $value;
+ break;
+
+ case 'boolean':
+ $string = $value ? 'true' : 'false';
+ break;
+
+ case 'string':
+ // Sanitize any CRLF characters..
+ $string = '"' . str_replace(array("\r\n", "\n"), '\\n', $value) . '"';
+ break;
+ }
+
+ return $string;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/JsonFormat.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/JsonFormat.php
new file mode 100644
index 00000000..a9992ac8
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/JsonFormat.php
@@ -0,0 +1,83 @@
+'))
+ {
+ $depth = $depth ? : 512;
+
+ return json_encode($struct, $option, $depth);
+ }
+
+ /*
+ if ($depth)
+ {
+ throw new \InvalidArgumentException('Depth in json_encode() only support higher than PHP 5.5');
+ }
+ */
+
+ return json_encode($struct, $option);
+ }
+
+ /**
+ * Parse a JSON formatted string and convert it into an object.
+ *
+ * @param string $data JSON formatted string to convert.
+ * @param array $options Options used by the formatter.
+ *
+ * @return object Data object.
+ */
+ public static function stringToStruct($data, array $options = array())
+ {
+ $assoc = RegistryHelper::getValue($options, 'assoc', false);
+ $depth = RegistryHelper::getValue($options, 'depth', 512);
+ $option = RegistryHelper::getValue($options, 'options', 0);
+
+ if (PHP_VERSION >= 5.4)
+ {
+ return json_decode(trim($data), $assoc, $depth, $option);
+ }
+ else
+ {
+ return json_decode(trim($data), $assoc, $depth);
+ }
+ }
+
+ /**
+ * prettyPrint
+ *
+ * @return bool|int
+ */
+ public static function prettyPrint()
+ {
+ return defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : false;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/PhpFormat.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/PhpFormat.php
new file mode 100644
index 00000000..c9e2e6d5
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/PhpFormat.php
@@ -0,0 +1,114 @@
+ $v)
+ {
+ if (is_scalar($v))
+ {
+ $vars .= sprintf("\t'%s' => '%s',\n", $k, addcslashes($v, '\\\''));
+ }
+ elseif (is_array($v) || is_object($v))
+ {
+ $vars .= sprintf("\t'%s' => %s,\n", $k, static::getArrayString((array) $v));
+ }
+ }
+
+ $str = "";
+ }
+
+ return $str;
+ }
+
+ /**
+ * Parse a PHP class formatted string and convert it into an object.
+ *
+ * @param string $data PHP Class formatted string to convert.
+ * @param array $options Options used by the formatter.
+ *
+ * @return object Data object.
+ */
+ public static function stringToStruct($data, array $options = array())
+ {
+ return $data;
+ }
+
+ /**
+ * Method to get an array as an exported string.
+ *
+ * @param array $a The array to get as a string.
+ *
+ * @return array
+ */
+ protected static function getArrayString($a, $level = 2)
+ {
+ $s = "array(\n";
+ $i = 0;
+
+ foreach ($a as $k => $v)
+ {
+ $s .= ($i) ? ",\n" : '';
+ $s .= str_repeat("\t", $level) . '"' . $k . '" => ';
+
+ if (is_array($v) || is_object($v))
+ {
+ $s .= static::getArrayString((array) $v, $level + 1);
+ }
+ else
+ {
+ $s .= '"' . addslashes($v) . '"';
+ }
+
+ $i++;
+ }
+
+ $s .= "\n" . str_repeat("\t", $level - 1) . ")";
+
+ return $s;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/XmlFormat.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/XmlFormat.php
new file mode 100644
index 00000000..ef9307b9
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/XmlFormat.php
@@ -0,0 +1,156 @@
+');
+
+ // Iterate over the object members.
+ static::getXmlChildren($root, $struct, $nodeName);
+
+ return $root->asXML();
+ }
+
+ /**
+ * Parse a XML formatted string and convert it into an object.
+ *
+ * @param string $data XML formatted string to convert.
+ * @param array $options Options used by the formatter.
+ *
+ * @return object Data object.
+ *
+ * @since 2.0
+ */
+ public static function stringToStruct($data, array $options = array())
+ {
+ $obj = new \stdClass;
+
+ // Parse the XML string.
+ $xml = simplexml_load_string($data);
+
+ foreach ($xml->children() as $node)
+ {
+ $obj->{$node['name']} = static::getValueFromNode($node);
+ }
+
+ return $obj;
+ }
+
+ /**
+ * Method to get a PHP native value for a SimpleXMLElement object. -- called recursively
+ *
+ * @param object $node SimpleXMLElement object for which to get the native value.
+ *
+ * @return mixed Native value of the SimpleXMLElement object.
+ */
+ protected static function getValueFromNode($node)
+ {
+ switch ($node['type'])
+ {
+ case 'integer':
+ $value = (string) $node;
+
+ return (int) $value;
+ break;
+
+ case 'string':
+ return (string) $node;
+ break;
+
+ case 'boolean':
+ $value = (string) $node;
+
+ return (bool) $value;
+ break;
+
+ case 'double':
+ $value = (string) $node;
+
+ return (float) $value;
+ break;
+
+ case 'array':
+ $value = array();
+
+ foreach ($node->children() as $child)
+ {
+ $value[(string) $child['name']] = static::getValueFromNode($child);
+ }
+
+ break;
+
+ default:
+ $value = new \stdClass;
+
+ foreach ($node->children() as $child)
+ {
+ $value->$child['name'] = static::getValueFromNode($child);
+ }
+
+ break;
+ }
+
+ return $value;
+ }
+
+ /**
+ * Method to build a level of the XML string -- called recursively
+ *
+ * @param \SimpleXMLElement $node SimpleXMLElement object to attach children.
+ * @param object $var Object that represents a node of the XML document.
+ * @param string $nodeName The name to use for node elements.
+ *
+ * @return void
+ */
+ protected static function getXmlChildren(\SimpleXMLElement $node, $var, $nodeName)
+ {
+ // Iterate over the object members.
+ foreach ((array) $var as $k => $v)
+ {
+ if (is_scalar($v))
+ {
+ $n = $node->addChild($nodeName, $v);
+ $n->addAttribute('name', $k);
+ $n->addAttribute('type', gettype($v));
+ }
+ else
+ {
+ $n = $node->addChild($nodeName);
+ $n->addAttribute('name', $k);
+ $n->addAttribute('type', gettype($v));
+
+ static::getXmlChildren($n, $v, $nodeName);
+ }
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/YamlFormat.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/YamlFormat.php
new file mode 100644
index 00000000..97229300
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/YamlFormat.php
@@ -0,0 +1,128 @@
+dump($array, $inline, $indent);
+ }
+
+ /**
+ * Parse a YAML formatted string and convert it into an object.
+ * We use the json_* methods to convert the parsed YAML array to an object.
+ *
+ * @param string $data YAML formatted string to convert.
+ * @param array $options Options used by the formatter.
+ *
+ * @return object Data object.
+ *
+ * @since 2.0
+ */
+ static public function stringToStruct($data, array $options = array())
+ {
+ $array = static::getParser()->parse(trim($data));
+
+ return json_decode(json_encode($array));
+ }
+
+ /**
+ * getParser
+ *
+ * @return \Symfony\Component\Yaml\Parser
+ */
+ public static function getParser()
+ {
+ if (!static::$parser)
+ {
+ static::$parser = new SymfonyYamlParser;
+ }
+
+ return static::$parser;
+ }
+
+ /**
+ * setParser
+ *
+ * @param \Symfony\Component\Yaml\Parser $parser
+ *
+ * @return YamlFormat Return self to support chaining.
+ */
+ public static function setParser($parser)
+ {
+ static::$parser = $parser;
+ }
+
+ /**
+ * getDumper
+ *
+ * @return \Symfony\Component\Yaml\Dumper
+ */
+ public static function getDumper()
+ {
+ if (!static::$dumper)
+ {
+ static::$dumper = new SymfonyYamlDumper;
+ }
+
+ return static::$dumper;
+ }
+
+ /**
+ * setDumper
+ *
+ * @param \Symfony\Component\Yaml\Dumper $dumper
+ *
+ * @return YamlFormat Return self to support chaining.
+ */
+ public static function setDumper($dumper)
+ {
+ static::$dumper = $dumper;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/YmlFormat.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/YmlFormat.php
new file mode 100644
index 00000000..01fded9e
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Format/YmlFormat.php
@@ -0,0 +1,18 @@
+set('foo', 'bar');
+
+// Get a value from the registry;
+$value = $registry->get('foo');
+
+```
+
+## Load config by Registry
+
+``` php
+use Windwalker\Registry\Registry;
+
+$registry = new Registry;
+
+// Load by string
+$registry->loadString('{"foo" : "bar"}');
+
+$registry->loadString(' ', 'xml');
+
+// Load by object or array
+$registry->load($object);
+
+// Load by file
+$registry->loadFile($root . '/config/config.json', 'json');
+```
+
+## Accessing a Registry by getter & setter
+
+### Get value
+
+``` php
+$registry->get('foo');
+
+// Get a non-exists value and return default
+$registry->get('foo', 'default');
+
+// OR
+
+$registry->get('foo') ?: 'default';
+```
+
+### Set value
+
+``` php
+// Set value
+$registry->set('bar', $value);
+
+// Sets a default value if not already assigned.
+$registry->def('bar', $default);
+```
+
+### Accessing children value by path
+
+``` php
+$json = '{
+ "parent" : {
+ "child" : "Foo"
+ }
+}';
+
+$registry = new Registry($json);
+
+$registry->get('parent.child'); // return 'Foo'
+
+$registry->set('parent.child', $value);
+```
+
+### Append & Prepend
+
+Support `push / pop / shift / unshift` methods.
+
+``` php
+$registry->set('foo.bar', array('fisrt', 'second'));
+
+$registry->push('foo.bar', 'third');
+
+$registry->get('foo.bar');
+// Result: Array(first, second, third)
+```
+
+### Use other separator
+
+``` php
+$registry->setSeparator('/');
+
+$data = $registry->get('foo/bar');
+```
+
+## Accessing a Registry as an Array
+
+The `Registry` class implements `ArrayAccess` so the properties of the registry can be accessed as an array. Consider the following examples:
+
+``` php
+// Set a value in the registry.
+$registry['foo'] = 'bar';
+
+// Get a value from the registry;
+$value = $registry['foo'];
+
+// Check if a key in the registry is set.
+if (isset($registry['foo']))
+{
+ echo 'Say bar.';
+}
+```
+
+## Merge Registry
+
+#### Using load* methods to merge two config files.
+
+``` php
+$json1 = '{
+ "field" : {
+ "keyA" : "valueA",
+ "keyB" : "valueB"
+ }
+}';
+
+$json2 = '{
+ "field" : {
+ "keyB" : "a new valueB"
+ }
+}';
+
+$registry->loadString($json1);
+$registry->loadString($json2);
+```
+
+Output
+
+```
+Array(
+ field => Array(
+ keyA => valueA
+ keyB => a new valueB
+ )
+)
+```
+
+#### Merge Another Registry
+
+``` php
+$object1 = '{
+ "foo" : "foo value",
+ "bar" : {
+ "bar1" : "bar value 1",
+ "bar2" : "bar value 2"
+ }
+}';
+
+$object2 = '{
+ "foo" : "foo value",
+ "bar" : {
+ "bar2" : "new bar value 2"
+ }
+}';
+
+$registry1 = new Registry(json_decode($object1));
+$registry2 = new Registry(json_decode($object2));
+
+$registry1->merge($registry2);
+```
+
+If you just want to merge first level, do not hope recursive:
+
+``` php
+$registry1->merge($registry2, false); // Set param 2 to false that Registry will only merge first level
+```
+
+Merge to a child node:
+
+``` php
+$registry->mergeTo('foo.bar', $anotherRegistry);
+```
+
+## Dump to file.
+
+``` php
+$registry->toString();
+
+$registry->toString('xml');
+
+$registry->toString('ini');
+```
+
+## Dump to one dimension
+
+``` php
+$array = array(
+ 'flower' => array(
+ 'sunflower' => 'light',
+ 'sakura' => 'samurai'
+ )
+);
+
+$registry = new Registry($array);
+
+// Make data to one dimension
+
+$flatted = $registry->flatten();
+
+print_r($flatted);
+```
+
+The result:
+
+```
+Array
+(
+ [flower.sunflower] => light
+ [flower.sakura] => samurai
+)
+```
+
+## Using YAML
+
+Add Symfony YAML component in `composer.json`
+
+``` json
+{
+ "require-dev": {
+ "symfony/yaml": "~2.0"
+ }
+}
+```
+
+Using `yaml` format
+
+``` php
+$registry->loadFile($yamlFile, 'yaml');
+
+$registry->loadString('foo: bar', 'yaml');
+
+// Convert to string
+$registry->toString('yaml');
+```
+
+## RegistryHelper
+
+``` php
+use Windwalker\Registry\RegistryHelper;
+
+RehistryHelper::loadFaile($file, $format); // File to array
+RehistryHelper::loadString($string, $format); // String to array
+RehistryHelper::toString($array, $format); // Array to string
+
+// Use format class
+$json = RehistryHelper::getFormatClass('json'); // Get JsonFormat
+$string = $json::structToString($array);
+```
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Registry.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Registry.php
new file mode 100644
index 00000000..d89efe62
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Registry.php
@@ -0,0 +1,801 @@
+bindData($this->data, $data);
+ }
+ elseif (!empty($data) && is_string($data))
+ {
+ $this->loadString($data, $format);
+ }
+ }
+
+ /**
+ * Magic function to clone the registry object.
+ *
+ * @return Registry
+ *
+ * @since 2.0
+ */
+ public function __clone()
+ {
+ $this->data = unserialize(serialize($this->data));
+ }
+
+ /**
+ * Magic function to render this object as a string using default args of toString method.
+ *
+ * @return string
+ *
+ * @since 2.0
+ */
+ public function __toString()
+ {
+ try
+ {
+ return $this->toString();
+ }
+ catch (\Exception $e)
+ {
+ return trigger_error((string) $e, E_USER_ERROR);
+ }
+ }
+
+ /**
+ * Implementation for the JsonSerializable interface.
+ * Allows us to pass Registry objects to json_encode.
+ *
+ * @return array
+ *
+ * @since 2.0
+ * @note The interface is only present in PHP 5.4 and up.
+ */
+ public function jsonSerialize()
+ {
+ return $this->data;
+ }
+
+ /**
+ * Sets a default value if not already assigned.
+ *
+ * @param string $path The name of the parameter.
+ * @param mixed $value An optional value for the parameter.
+ *
+ * @return static Return self to support chaining.
+ *
+ * @since 2.0
+ */
+ public function def($path, $value = '')
+ {
+ $value = $this->get($path, $value);
+ $this->set($path, $value);
+
+ return $this;
+ }
+
+ /**
+ * Check if a registry path exists.
+ *
+ * @param string $path Registry path (e.g. foo.content.showauthor)
+ *
+ * @return boolean
+ *
+ * @since 2.0
+ */
+ public function exists($path)
+ {
+ return !is_null($this->get($path));
+ }
+
+ /**
+ * Get a registry value.
+ *
+ * @param string $path Registry path (e.g. foo.content.showauthor)
+ * @param mixed $default Optional default value, returned if the internal value is null.
+ *
+ * @return mixed Value of entry or null
+ *
+ * @since 2.0
+ */
+ public function get($path, $default = null)
+ {
+ $result = RegistryHelper::getByPath($this->data, $path, $this->separator);
+
+ return !is_null($result) ? $result : $default;
+ }
+
+ /**
+ * Reset all data.
+ *
+ * @return static
+ */
+ public function reset()
+ {
+ $this->data = array();
+
+ return $this;
+ }
+
+ /**
+ * Clear all data.
+ *
+ * @return static
+ *
+ * @deprecated 3.0
+ */
+ public function clear()
+ {
+ return $this->reset();
+ }
+
+ /**
+ * Load a associative array of values into the default namespace
+ *
+ * @param array $array Associative array of value to load
+ *
+ * @return static Return this object to support chaining.
+ *
+ * @since 2.0
+ * @deprecated 3.0 Use load() instead.
+ */
+ public function loadArray($array)
+ {
+ $this->bindData($this->data, $array, false);
+
+ return $this;
+ }
+
+ /**
+ * Load the public variables of the object into the default namespace.
+ *
+ * @param object $object The object holding the publics to load
+ *
+ * @return static Return this object to support chaining.
+ *
+ * @since 2.0
+ * @deprecated 3.0 Use load() instead.
+ */
+ public function loadObject($object)
+ {
+ $this->bindData($this->data, $object, false);
+
+ return $this;
+ }
+
+ /**
+ * Load an array or object of values into the default namespace
+ *
+ * @param array|object $data The value to load into registry.
+ * @param boolean $raw Set to false that we will convert all object to array.
+ *
+ * @return static Return this object to support chaining.
+ */
+ public function load($data, $raw = false)
+ {
+ $this->bindData($this->data, $data, $raw);
+
+ return $this;
+ }
+
+ /**
+ * Load the contents of a file into the registry
+ *
+ * @param string $file Path to file to load
+ * @param string $format Format of the file [optional: defaults to JSON]
+ * @param array $options Options used by the formatter
+ *
+ * @return static Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function loadFile($file, $format = Format::JSON, $options = array())
+ {
+ $this->load(RegistryHelper::loadFile($file, $format, $options), false);
+
+ return $this;
+ }
+
+ /**
+ * Load a string into the registry
+ *
+ * @param string $data String to load into the registry
+ * @param string $format Format of the string
+ * @param array $options Options used by the formatter
+ *
+ * @return static Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function loadString($data, $format = Format::JSON, $options = array())
+ {
+ $this->load(RegistryHelper::loadString($data, $format, $options), false);
+
+ return $this;
+ }
+
+ /**
+ * Merge a structure data into this object.
+ *
+ * @param Registry|mixed $source Source structure data to merge.
+ * @param boolean $raw Set to false to convert all object to array.
+ *
+ * @return static Return this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function merge($source, $raw = false)
+ {
+ if ($source instanceof Registry)
+ {
+ $source = $source->getRaw();
+ }
+
+ $this->bindData($this->data, $source, $raw);
+
+ return $this;
+ }
+
+ /**
+ * Merge a structure data to a node.
+ *
+ * @param string $path The path to merge as root.
+ * @param Registry $source Source structure data to merge.
+ * @param boolean $raw Set to false to convert all object to array.
+ *
+ * @return static
+ */
+ public function mergeTo($path, $source, $raw = false)
+ {
+ $nodes = RegistryHelper::getPathNodes($path);
+
+ $data = array();
+
+ $tmp =& $data;
+
+ foreach ($nodes as $node)
+ {
+ $tmp[$node] = array();
+
+ $tmp =& $tmp[$node];
+ }
+
+ if ($source instanceof Registry)
+ {
+ $source = $source->getRaw();
+ }
+
+ $tmp = $source;
+
+ $this->bindData($this->data, $data, $raw);
+
+ return $this;
+ }
+
+ /**
+ * extract
+ *
+ * @param string $path
+ *
+ * @return static
+ */
+ public function extract($path)
+ {
+ return new static($this->get($path));
+ }
+
+ /**
+ * getRaw
+ *
+ * @return \stdClass
+ */
+ public function getRaw()
+ {
+ return $this->data;
+ }
+
+ /**
+ * Checks whether an offset exists in the iterator.
+ *
+ * @param mixed $offset The array offset.
+ *
+ * @return boolean True if the offset exists, false otherwise.
+ *
+ * @since 2.0
+ */
+ public function offsetExists($offset)
+ {
+ return (boolean) ($this->get($offset) !== null);
+ }
+
+ /**
+ * Gets an offset in the iterator.
+ *
+ * @param mixed $offset The array offset.
+ *
+ * @return mixed The array value if it exists, null otherwise.
+ *
+ * @since 2.0
+ */
+ public function offsetGet($offset)
+ {
+ return $this->get($offset);
+ }
+
+ /**
+ * Sets an offset in the iterator.
+ *
+ * @param mixed $offset The array offset.
+ * @param mixed $value The array value.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ public function offsetSet($offset, $value)
+ {
+ $this->set($offset, $value);
+ }
+
+ /**
+ * Unsets an offset in the iterator.
+ *
+ * @param mixed $offset The array offset.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ public function offsetUnset($offset)
+ {
+ $this->set($offset, null);
+ }
+
+ /**
+ * Set a registry value and convert object to array.
+ *
+ * @param string $path Registry Path (e.g. foo.content.showauthor)
+ * @param mixed $value Value of entry.
+ *
+ * @return static Return self to support chaining.
+ *
+ * @since 2.0
+ */
+ public function set($path, $value)
+ {
+ if (is_array($value) || is_object($value))
+ {
+ $value = RegistryHelper::toArray($value, true);
+ }
+
+ RegistryHelper::setByPath($this->data, $path, $value, $this->separator);
+
+ return $this;
+ }
+
+ /**
+ * Set a registry value.
+ *
+ * @param string $path Registry Path (e.g. foo.content.showauthor)
+ * @param mixed $value Value of entry.
+ *
+ * @return static Return self to support chaining.
+ *
+ * @since 2.1
+ */
+ public function setRaw($path, $value)
+ {
+ RegistryHelper::setByPath($this->data, $path, $value, $this->separator);
+
+ return $this;
+ }
+
+ /**
+ * Transforms a namespace to an array
+ *
+ * @return array An associative array holding the namespace data
+ *
+ * @since 2.0
+ */
+ public function toArray()
+ {
+ return (array) $this->asArray($this->data);
+ }
+
+ /**
+ * Transforms a namespace to an object
+ *
+ * @param string $class The class of object.
+ *
+ * @return object An an object holding the namespace data
+ *
+ * @since 2.0
+ */
+ public function toObject($class = 'stdClass')
+ {
+ return RegistryHelper::toObject($this->data, $class);
+ }
+
+ /**
+ * Get a namespace in a given string format
+ *
+ * @param string $format Format to return the string in
+ * @param mixed $options Parameters used by the formatter, see formatters for more info
+ *
+ * @return string Namespace in string format
+ *
+ * @since 2.0
+ */
+ public function toString($format = Format::JSON, $options = array())
+ {
+ return RegistryHelper::toString($this->data, $format, $options);
+ }
+
+ /**
+ * Method to recursively bind data to a parent object.
+ *
+ * @param array $parent The parent object on which to attach the data values.
+ * @param mixed $data An array or object of data to bind to the parent object.
+ * @param boolean $raw Set to false to convert all object to array.
+ *
+ * @return void
+ */
+ protected function bindData(&$parent, $data, $raw = false)
+ {
+ // Ensure the input data is an array.
+ if (!$raw)
+ {
+ $data = RegistryHelper::toArray($data, true);
+ }
+
+ foreach ($data as $key => $value)
+ {
+ if (in_array($value, $this->ignoreValues, true))
+ {
+ continue;
+ }
+
+ if (is_array($value))
+ {
+ if (!isset($parent[$key]))
+ {
+ $parent[$key] = array();
+ }
+
+ $this->bindData($parent[$key], $value);
+ }
+ else
+ {
+ $parent[$key] = $value;
+ }
+ }
+ }
+
+ /**
+ * Method to recursively convert an object of data to an array.
+ *
+ * @param mixed $data An object of data to return as an array.
+ *
+ * @return array Array representation of the input object.
+ *
+ * @since 2.0
+ */
+ protected function asArray($data)
+ {
+ $array = array();
+
+ if (is_object($data))
+ {
+ $data = get_object_vars($data);
+ }
+
+ foreach ($data as $k => $v)
+ {
+ if (is_object($v) || is_array($v))
+ {
+ $array[$k] = $this->asArray($v);
+ }
+ else
+ {
+ $array[$k] = $v;
+ }
+ }
+
+ return $array;
+ }
+
+ /**
+ * Dump to on dimension array.
+ *
+ * @param string $separator The key separator.
+ *
+ * @return string[] Dumped array.
+ */
+ public function flatten($separator = '.')
+ {
+ return RegistryHelper::flatten($this->data, $separator);
+ }
+
+ /**
+ * Method to get property Separator
+ *
+ * @return string
+ *
+ * @since 2.1
+ */
+ public function getSeparator()
+ {
+ return $this->separator;
+ }
+
+ /**
+ * Method to set property separator
+ *
+ * @param string $separator
+ *
+ * @return static Return self to support chaining.
+ *
+ * @since 2.1
+ */
+ public function setSeparator($separator)
+ {
+ $this->separator = $separator;
+
+ return $this;
+ }
+
+ /**
+ * Push value to a path in registry
+ *
+ * @param string $path Parent registry Path (e.g. windwalker.content.showauthor)
+ * @param mixed $value Value of entry, one or more elements.
+ *
+ * @return integer the new number of elements in the array.
+ *
+ * @since 2.1
+ */
+ public function push($path, $value)
+ {
+ $node = $this->get($path);
+
+ if (!$node)
+ {
+ $node = array();
+ }
+ elseif (is_object($node))
+ {
+ $node = get_object_vars($node);
+ }
+
+ if (!is_array($node))
+ {
+ throw new \UnexpectedValueException(sprintf('The value at path: %s should be object or array but is %s.', $path, gettype($node)));
+ }
+
+ $args = func_get_args();
+
+ if (count($args) <= 2)
+ {
+ $num = array_push($node, $value);
+ }
+ else
+ {
+ $args[0] = &$node;
+
+ $num = call_user_func_array('array_push', $args);
+ }
+
+ $this->set($path, $node);
+
+ return $num;
+ }
+
+ /**
+ * Prepend value to a path in registry.
+ *
+ * @param string $path Parent registry Path (e.g. windwalker.content.showauthor)
+ * @param mixed $value Value of entry, one or more elements.
+ *
+ * @return integer the new number of elements in the array.
+ *
+ * @since 2.1
+ */
+ public function unshift($path, $value)
+ {
+ $node = $this->get($path);
+
+ if (!$node)
+ {
+ $node = array();
+ }
+ elseif (is_object($node))
+ {
+ $node = get_object_vars($node);
+ }
+
+ if (!is_array($node))
+ {
+ throw new \UnexpectedValueException(sprintf('The value at path: %s should be object or array but is %s.', $path, gettype($node)));
+ }
+
+ $args = func_get_args();
+
+ if (count($args) <= 2)
+ {
+ $key = array_unshift($node, $value);
+ }
+ else
+ {
+ $args[0] = &$node;
+
+ $key = call_user_func_array('array_unshift', $args);
+ }
+
+ $this->set($path, $node);
+
+ return $key;
+ }
+
+ /**
+ * To remove first element from the path of this registry.
+ *
+ * @param string $path The registry path.
+ *
+ * @return mixed The shifted value, or null if array is empty.
+ */
+ public function shift($path)
+ {
+ $node = $this->get($path);
+
+ if (is_object($node))
+ {
+ $node = get_object_vars($node);
+ }
+
+ if (!is_array($node))
+ {
+ throw new \UnexpectedValueException(sprintf('The value at path: %s should be object or array but is %s.', $path, gettype($node)));
+ }
+
+ $value = array_shift($node);
+
+ $this->set($path, $node);
+
+ return $value;
+ }
+
+ /**
+ * To remove last element from the path of this registry.
+ *
+ * @param string $path The registry path.
+ *
+ * @return mixed The shifted value, or &null; if array is empty.
+ */
+ public function pop($path)
+ {
+ $node = $this->get($path);
+
+ if (is_object($node))
+ {
+ $node = get_object_vars($node);
+ }
+
+ if (!is_array($node))
+ {
+ throw new \UnexpectedValueException(sprintf('The value at path: %s should be object or array but is %s.', $path, gettype($node)));
+ }
+
+ $value = array_pop($node);
+
+ $this->set($path, $node);
+
+ return $value;
+ }
+
+ /**
+ * Gets this object represented as an RecursiveArrayIterator.
+ *
+ * This allows the data properties to be accessed via a foreach statement.
+ *
+ * You can wrap this iterator by RecursiveIteratorIterator that will support recursive foreach.
+ * Example: `foreach (new \RecursiveIteratorIterator($registry) as $value)`
+ *
+ * @return \RecursiveArrayIterator This object represented as an RecursiveArrayIterator.
+ *
+ * @see IteratorAggregate::getIterator()
+ * @since 2.1
+ */
+ public function getIterator()
+ {
+ return new \RecursiveArrayIterator($this->data);
+ }
+
+ /**
+ * Count elements of the data object
+ *
+ * @return integer The custom count as an integer.
+ *
+ * @link http://php.net/manual/en/countable.count.php
+ * @since 2.1
+ */
+ public function count()
+ {
+ return count($this->data);
+ }
+
+ /**
+ * Method to get property IgnoreValues
+ *
+ * @return array
+ */
+ public function getIgnoreValues()
+ {
+ return $this->ignoreValues;
+ }
+
+ /**
+ * Method to set property ignoreValues
+ *
+ * @param array $ignoreValues
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setIgnoreValues($ignoreValues)
+ {
+ $this->ignoreValues = (array) $ignoreValues;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/RegistryHelper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/RegistryHelper.php
new file mode 100644
index 00000000..e837639e
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/RegistryHelper.php
@@ -0,0 +1,432 @@
+ $v)
+ {
+ if ($k !== $v)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * getValue
+ *
+ * @param array $array
+ * @param string $name
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public static function getValue(array $array, $name, $default = null)
+ {
+ return isset($array[$name]) ? $array[$name] : $default;
+ }
+
+ /**
+ * Utility function to map an array to a stdClass object.
+ *
+ * @param array $array The array to map.
+ * @param string $class Name of the class to create
+ *
+ * @return object The object mapped from the given array
+ *
+ * @since 2.0
+ */
+ public static function toObject($array, $class = 'stdClass')
+ {
+ $object = new $class;
+
+ foreach ($array as $k => $v)
+ {
+ if (is_array($v))
+ {
+ $object->$k = static::toObject($v, $class);
+ }
+ else
+ {
+ $object->$k = $v;
+ }
+ }
+
+ return $object;
+ }
+
+ /**
+ * Get data from array or object by path.
+ *
+ * Example: `RegistryHelper::getByPath($array, 'foo.bar.yoo')` equals to $array['foo']['bar']['yoo'].
+ *
+ * @param mixed $data An array or object to get value.
+ * @param mixed $path The key path.
+ * @param string $separator Separator of paths.
+ *
+ * @return mixed Found value, null if not exists.
+ *
+ * @since 2.1
+ */
+ public static function getByPath(array $data, $path, $separator = '.')
+ {
+ $nodes = static::getPathNodes($path, $separator);
+
+ if (empty($nodes))
+ {
+ return null;
+ }
+
+ $dataTmp = $data;
+
+ foreach ($nodes as $arg)
+ {
+ if (is_object($dataTmp) && isset($dataTmp->$arg))
+ {
+ $dataTmp = $dataTmp->$arg;
+ }
+ elseif ($dataTmp instanceof \ArrayAccess && isset($dataTmp[$arg]))
+ {
+ $dataTmp = $dataTmp[$arg];
+ }
+ elseif (is_array($dataTmp) && isset($dataTmp[$arg]))
+ {
+ $dataTmp = $dataTmp[$arg];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ return $dataTmp;
+ }
+
+ /**
+ * setByPath
+ *
+ * @param mixed &$data
+ * @param string $path
+ * @param mixed $value
+ * @param string $separator
+ *
+ * @return boolean
+ *
+ * @since 2.1
+ */
+ public static function setByPath(array &$data, $path, $value, $separator = '.')
+ {
+ $nodes = static::getPathNodes($path, $separator);
+
+ if (empty($nodes))
+ {
+ return false;
+ }
+
+ $dataTmp = &$data;
+
+ foreach ($nodes as $node)
+ {
+ if (is_array($dataTmp))
+ {
+ if (empty($dataTmp[$node]))
+ {
+ $dataTmp[$node] = array();
+ }
+
+ $dataTmp = &$dataTmp[$node];
+ }
+ else
+ {
+ // If a node is value but path is not go to the end, we replace this value as a new store.
+ // Then next node can insert new value to this store.
+ $dataTmp = array();
+ }
+ }
+
+ // Now, path go to the end, means we get latest node, set value to this node.
+ $dataTmp = $value;
+
+ return true;
+ }
+
+ /**
+ * Explode the registry path into an array and remove empty
+ * nodes that occur as a result of a double dot. ex: windwalker..test
+ * Finally, re-key the array so they are sequential.
+ *
+ * @param string $path
+ * @param string $separator
+ *
+ * @return array
+ */
+ public static function getPathNodes($path, $separator = '.')
+ {
+ return array_values(array_filter(explode($separator, $path), 'strlen'));
+ }
+
+ /**
+ * Method to recursively convert data to one dimension array.
+ *
+ * @param array|object $array The array or object to convert.
+ * @param string $separator The key separator.
+ * @param string $prefix Last level key prefix.
+ *
+ * @return array
+ */
+ public static function flatten($array, $separator = '.', $prefix = '')
+ {
+ $return = array();
+
+ if ($array instanceof \Traversable)
+ {
+ $array = iterator_to_array($array);
+ }
+ elseif (is_object($array))
+ {
+ $array = get_object_vars($array);
+ }
+
+ foreach ($array as $k => $v)
+ {
+ $key = $prefix ? $prefix . $separator . $k : $k;
+
+ if (is_object($v) || is_array($v))
+ {
+ $return = array_merge($return, static::flatten($v, $separator, $key));
+ }
+ else
+ {
+ $return[$key] = $v;
+ }
+ }
+
+ return $return;
+ }
+
+ /**
+ * Utility function to convert all types to an array.
+ *
+ * @param mixed $data The data to convert.
+ * @param bool $recursive Recursive if data is nested.
+ *
+ * @return array The converted array.
+ */
+ public static function toArray($data, $recursive = false)
+ {
+ // Ensure the input data is an array.
+ if ($data instanceof \Traversable)
+ {
+ $data = iterator_to_array($data);
+ }
+ elseif (is_object($data))
+ {
+ $data = get_object_vars($data);
+ }
+ else
+ {
+ $data = (array) $data;
+ }
+
+ if ($recursive)
+ {
+ foreach ($data as &$value)
+ {
+ if (is_array($value) || is_object($value))
+ {
+ $value = static::toArray($value, $recursive);
+ }
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * dumpObjectValues
+ *
+ * @param mixed $object
+ *
+ * @return array
+ */
+ public static function dumpObjectValues($object)
+ {
+ $data = array();
+
+ static::$objectStorage = new \SplObjectStorage;
+
+ static::doDump($data, $object);
+
+ return $data;
+ }
+
+ /**
+ * doDump
+ *
+ * @param array $data
+ * @param mixed $object
+ *
+ * @return void
+ */
+ private static function doDump(&$data, $object)
+ {
+ if (is_object($object) && static::$objectStorage->contains($object))
+ {
+ $data = null;
+
+ return;
+ }
+
+ if (is_object($object))
+ {
+ static::$objectStorage->attach($object);
+ }
+
+ if (is_array($object) || $object instanceof \Traversable)
+ {
+ foreach ($object as $key => $value)
+ {
+ static::doDump($data[$key], $value);
+ }
+ }
+ elseif (is_object($object))
+ {
+ $ref = new \ReflectionObject($object);
+
+ $properties = $ref->getProperties();
+
+ foreach ($properties as $property)
+ {
+ $property->setAccessible(true);
+
+ $value = $property->getValue($object);
+
+ static::doDump($data[$property->getName()], $value);
+ }
+ }
+ else
+ {
+ $data = $object;
+ }
+ }
+}
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/IniFormatTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/IniFormatTest.php
new file mode 100644
index 00000000..4650ece8
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/IniFormatTest.php
@@ -0,0 +1,79 @@
+instance = new IniFormat;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test objectToString().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\IniFormat::structToString
+ * @TODO Implement testObjectToString().
+ */
+ public function testObjectToString()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test stringToObject().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\IniFormat::stringToStruct
+ * @TODO Implement testStringToObject().
+ */
+ public function testStringToObject()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/JsonFormatTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/JsonFormatTest.php
new file mode 100644
index 00000000..050a9184
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/JsonFormatTest.php
@@ -0,0 +1,79 @@
+instance = new JsonFormat;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test objectToString().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\JsonFormat::structToString
+ * @TODO Implement testObjectToString().
+ */
+ public function testObjectToString()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test stringToObject().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\JsonFormat::stringToStruct
+ * @TODO Implement testStringToObject().
+ */
+ public function testStringToObject()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/PhpFormatTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/PhpFormatTest.php
new file mode 100644
index 00000000..1b39c294
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/PhpFormatTest.php
@@ -0,0 +1,79 @@
+instance = new PhpFormat;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test objectToString().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\PhpFormat::structToString
+ * @TODO Implement testObjectToString().
+ */
+ public function testObjectToString()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test stringToObject().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\PhpFormat::stringToStruct
+ * @TODO Implement testStringToObject().
+ */
+ public function testStringToObject()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/XmlFormatTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/XmlFormatTest.php
new file mode 100644
index 00000000..6a442532
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/XmlFormatTest.php
@@ -0,0 +1,79 @@
+instance = new XmlFormat;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test objectToString().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\XmlFormat::structToString
+ * @TODO Implement testObjectToString().
+ */
+ public function testObjectToString()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test stringToObject().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\XmlFormat::stringToStruct
+ * @TODO Implement testStringToObject().
+ */
+ public function testStringToObject()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/YamlFormatTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/YamlFormatTest.php
new file mode 100644
index 00000000..65117f90
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Format/YamlFormatTest.php
@@ -0,0 +1,143 @@
+instance = new YamlFormat;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test objectToString().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\YamlFormat::structToString
+ * @TODO Implement testObjectToString().
+ */
+ public function testObjectToString()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test stringToObject().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\YamlFormat::stringToStruct
+ * @TODO Implement testStringToObject().
+ */
+ public function testStringToObject()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getParser().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\YamlFormat::getParser
+ * @TODO Implement testGetParser().
+ */
+ public function testGetParser()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setParser().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\YamlFormat::setParser
+ * @TODO Implement testSetParser().
+ */
+ public function testSetParser()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getDumper().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\YamlFormat::getDumper
+ * @TODO Implement testGetDumper().
+ */
+ public function testGetDumper()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setDumper().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Format\YamlFormat::setDumper
+ * @TODO Implement testSetDumper().
+ */
+ public function testSetDumper()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/RegistryHelperTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/RegistryHelperTest.php
new file mode 100644
index 00000000..45cd2c68
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/RegistryHelperTest.php
@@ -0,0 +1,294 @@
+assertFalse(RegistryHelper::isAssociativeArray(array('a', 'b')));
+
+ $this->assertTrue(RegistryHelper::isAssociativeArray(array(1, 2, 'a' => 'b', 'c', 'd')));
+ }
+
+ /**
+ * Method to test toObject().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\RegistryHelper::toObject
+ */
+ public function testToObject()
+ {
+ $data = RegistryHelper::toObject(array('foo' => 'bar'));
+
+ $this->assertInternalType('object', $data);
+
+ $this->assertEquals('bar', $data->foo);
+
+ $data = RegistryHelper::toObject(array('foo' => 'bar'), 'ArrayObject');
+
+ $this->assertInstanceOf('ArrayObject', $data);
+
+ $data = RegistryHelper::toObject(array('foo' => array('bar' => 'baz')));
+
+ $this->assertEquals('baz', $data->foo->bar);
+ }
+
+ /**
+ * Method to test getByPath().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\RegistryHelper::getByPath
+ */
+ public function testGetByPath()
+ {
+ $data = array(
+ 'flower' => 'sakura',
+ 'olive' => 'peace',
+ 'pos1' => array(
+ 'sunflower' => 'love'
+ ),
+ 'pos2' => array(
+ 'cornflower' => 'elegant'
+ ),
+ 'array' => array(
+ 'A',
+ 'B',
+ 'C'
+ )
+ );
+
+ $this->assertEquals('sakura', RegistryHelper::getByPath($data, 'flower'));
+ $this->assertEquals('love', RegistryHelper::getByPath($data, 'pos1.sunflower'));
+ $this->assertEquals('love', RegistryHelper::getByPath($data, 'pos1/sunflower', '/'));
+ $this->assertEquals($data['array'], RegistryHelper::getByPath($data, 'array'));
+ $this->assertNull(RegistryHelper::getByPath($data, 'not.exists'));
+ }
+
+ /**
+ * Method to test getByPath().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\RegistryHelper::getByPath
+ */
+ public function testGetByPathWithObject()
+ {
+ $data = array(
+ 'flower' => 'sakura',
+ 'olive' => 'peace',
+ 'pos1' => (object) array(
+ 'sunflower' => 'love'
+ ),
+ 'pos2' => new Registry(array(
+ 'cornflower' => 'elegant'
+ )),
+ 'array' => array(
+ 'A',
+ 'B',
+ 'C'
+ )
+ );
+
+ $this->assertEquals('sakura', RegistryHelper::getByPath($data, 'flower'));
+ $this->assertEquals('love', RegistryHelper::getByPath($data, 'pos1.sunflower'));
+ $this->assertEquals('elegant', RegistryHelper::getByPath($data, 'pos2.cornflower'));
+ $this->assertEquals(null, RegistryHelper::getByPath($data, 'pos2.data'));
+ }
+
+ /**
+ * Method to test setByPath().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\RegistryHelper::setByPath
+ */
+ public function testSetByPath()
+ {
+ $data = array();
+
+ // One level
+ $return = RegistryHelper::setByPath($data, 'flower', 'sakura');
+
+ $this->assertEquals('sakura', $data['flower']);
+ $this->assertTrue($return);
+
+ // Multi-level
+ RegistryHelper::setByPath($data, 'foo.bar', 'test');
+
+ $this->assertEquals('test', $data['foo']['bar']);
+
+ // Separator
+ RegistryHelper::setByPath($data, 'foo/bar', 'play', '/');
+
+ $this->assertEquals('play', $data['foo']['bar']);
+
+ // False
+ $return = RegistryHelper::setByPath($data, '', 'goo');
+
+ $this->assertFalse($return);
+
+ // Fix path
+ RegistryHelper::setByPath($data, 'double..separators', 'value');
+
+ $this->assertEquals('value', $data['double']['separators']);
+ }
+
+ /**
+ * Method to test getPathNodes().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\RegistryHelper::getPathNodes
+ */
+ public function testGetPathNodes()
+ {
+ $this->assertEquals(array('a', 'b', 'c'), RegistryHelper::getPathNodes('a..b.c'));
+ $this->assertEquals(array('a', 'b', 'c'), RegistryHelper::getPathNodes('a//b/c', '/'));
+ }
+
+ /**
+ * testFlatten
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\RegistryHelper::flatten
+ * @since 2.0
+ */
+ public function testFlatten()
+ {
+ $array = array(
+ 'flower' => 'sakura',
+ 'olive' => 'peace',
+ 'pos1' => array(
+ 'sunflower' => 'love'
+ ),
+ 'pos2' => array(
+ 'cornflower' => 'elegant'
+ )
+ );
+
+ $flatted = RegistryHelper::flatten($array);
+
+ $this->assertEquals($flatted['pos1.sunflower'], 'love');
+
+ $flatted = RegistryHelper::flatten($array, '/');
+
+ $this->assertEquals($flatted['pos1/sunflower'], 'love');
+ }
+
+ /**
+ * Data provider for object inputs
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestToArray()
+ {
+ return array(
+ 'string' => array(
+ 'foo',
+ false,
+ array('foo')
+ ),
+ 'array' => array(
+ array('foo'),
+ false,
+ array('foo')
+ ),
+ 'array_recursive' => array(
+ array('foo' => array(
+ (object) array('bar' => 'bar'),
+ (object) array('baz' => 'baz')
+ )),
+ true,
+ array('foo' => array(
+ array('bar' => 'bar'),
+ array('baz' => 'baz')
+ ))
+ ),
+ 'iterator' => array(
+ array('foo' => new \ArrayIterator(array('bar' => 'baz'))),
+ true,
+ array('foo' => array('bar' => 'baz'))
+ )
+ );
+ }
+
+ /**
+ * testToArray
+ *
+ * @param $input
+ * @param $recursive
+ * @param $expect
+ *
+ * @return void
+ *
+ * @dataProvider seedTestToArray
+ * @covers Windwalker\Utilities\ArrayHelper::toArray
+ */
+ public function testToArray($input, $recursive, $expect)
+ {
+ $this->assertEquals($expect, RegistryHelper::toArray($input, $recursive));
+ }
+
+ public function testDumpObjectValue()
+ {
+ $data = new StubDumpable(new StubDumpable);
+
+ $dumped = RegistryHelper::dumpObjectValues($data);
+
+ $this->assertEquals('foo', $dumped['foo']);
+ $this->assertEquals('bar', $dumped['bar']);
+ $this->assertNull($dumped['data']['self']);
+ $this->assertEquals(RegistryHelper::dumpObjectValues(new StubDumpable), $dumped['data']['new']);
+ $this->assertEquals(array('sakura', 'rose'), $dumped['data']['flower']);
+ $this->assertEquals(array('wind' => 'walker'), $dumped['iterator']);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/RegistryTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/RegistryTest.php
new file mode 100644
index 00000000..dd6dd0ec
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/RegistryTest.php
@@ -0,0 +1,680 @@
+instance = new Registry($this->getTestData());
+ }
+
+ /**
+ * getTestData
+ *
+ * @return array
+ */
+ protected function getTestData()
+ {
+ return array(
+ 'flower' => 'sakura',
+ 'olive' => 'peace',
+ 'pos1' => array(
+ 'sunflower' => 'love'
+ ),
+ 'pos2' => array(
+ 'cornflower' => 'elegant'
+ ),
+ 'array' => array(
+ 'A',
+ 'B',
+ 'C'
+ )
+ );
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test __clone().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::__clone
+ */
+ public function test__clone()
+ {
+ $registry1 = new Registry($this->getTestData());
+
+ $registry2 = clone $registry1;
+
+ $this->assertEquals($registry1, $registry2);
+ }
+
+ /**
+ * Method to test __toString().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::__toString
+ */
+ public function test__toString()
+ {
+ $this->assertJsonStringEqualsJsonString(json_encode($this->getTestData()), (string) $this->instance);
+ }
+
+ /**
+ * Method to test jsonSerialize().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::jsonSerialize
+ */
+ public function testJsonSerialize()
+ {
+ $this->assertJsonStringEqualsJsonString(json_encode($this->getTestData()), (string) $this->instance);
+ }
+
+ /**
+ * Method to test def().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::def
+ */
+ public function testDef()
+ {
+ $this->assertNull($this->instance->get('lily'));
+
+ $this->instance->def('lily', 'love');
+
+ $this->assertEquals('love', $this->instance->get('lily'));
+ }
+
+ /**
+ * Method to test exists().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::exists
+ */
+ public function testExists()
+ {
+ $this->assertFalse($this->instance->exists('rose'));
+ $this->assertTrue($this->instance->exists('flower'));
+ }
+
+ /**
+ * Method to test get().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::get
+ */
+ public function testGet()
+ {
+ $this->assertEquals($this->instance->get('flower', 'canna'), 'sakura');
+
+ $this->assertEquals($this->instance->get('not.exists', 'canna'), 'canna');
+
+ $this->assertNull($this->instance->get('not.exists'));
+
+ $this->assertEquals($this->instance->get('pos1.sunflower'), 'love');
+ }
+
+ /**
+ * Method to test loadArray().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::load
+ */
+ public function testLoadArray()
+ {
+ $registry = new Registry;
+
+ $registry->load($this->getTestData());
+
+ $this->assertEquals($registry->get('olive'), 'peace');
+
+ $this->assertEquals($registry->get('pos1.sunflower'), 'love');
+ }
+
+ /**
+ * Method to test loadObject().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::load
+ */
+ public function testLoadObject()
+ {
+ $registry = new Registry;
+
+ $registry->load((object) $this->getTestData());
+
+ $this->assertEquals($registry->get('olive'), 'peace');
+
+ $this->assertEquals($registry->get('pos1.sunflower'), 'love');
+ }
+
+ /**
+ * Method to test loadFile().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::loadFile
+ */
+ public function testLoadFile()
+ {
+ $registry = new Registry;
+
+ $this->assertEquals($registry->reset()->loadFile(__DIR__ . '/Stubs/flower.json', 'json')->get('flower'), 'sakura');
+ $this->assertEquals($registry->reset()->loadFile(__DIR__ . '/Stubs/flower.yml', 'yaml')->get('flower'), 'sakura');
+ $this->assertEquals($registry->reset()->loadFile(__DIR__ . '/Stubs/flower.ini', 'ini')->get('flower'), 'sakura');
+ $this->assertEquals($registry->reset()->loadFile(__DIR__ . '/Stubs/flower.xml', 'xml')->get('flower'), 'sakura');
+ $this->assertEquals($registry->reset()->loadFile(__DIR__ . '/Stubs/flower.php', 'php')->get('flower'), 'sakura');
+ }
+
+ /**
+ * Method to test loadString().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::loadString
+ */
+ public function testLoadString()
+ {
+ $registry = new Registry;
+
+ $this->assertEquals($registry->reset()->loadString(file_get_contents(__DIR__ . '/Stubs/flower.json'), 'json')->get('flower'), 'sakura');
+ $this->assertEquals($registry->reset()->loadString(file_get_contents(__DIR__ . '/Stubs/flower.yml'), 'yaml')->get('flower'), 'sakura');
+ $this->assertEquals($registry->reset()->loadString(file_get_contents(__DIR__ . '/Stubs/flower.ini'), 'ini')->get('flower'), 'sakura');
+ $this->assertEquals($registry->reset()->loadString(file_get_contents(__DIR__ . '/Stubs/flower.xml'), 'xml')->get('flower'), 'sakura');
+ }
+
+ /**
+ * Method to test merge().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::merge
+ */
+ public function testMerge()
+ {
+ // Test recursive merge
+ $object1 = '{
+ "foo" : "foo value",
+ "bar" : {
+ "bar1" : "bar value 1",
+ "bar2" : "bar value 2",
+ "bar3" : "bar value 3"
+ }
+ }';
+ $object2 = '{
+ "foo" : "foo value",
+ "bar" : {
+ "bar2" : "new bar value 2",
+ "bar3" : null
+ }
+ }';
+
+ $registry1 = new Registry(json_decode($object1));
+ $registry2 = new Registry(json_decode($object2));
+
+ $registry1->merge($registry2);
+
+ $this->assertEquals('new bar value 2', $registry1->get('bar.bar2'), 'Line: ' . __LINE__ . '. bar.bar2 should be override.');
+ $this->assertEquals('bar value 1', $registry1->get('bar.bar1'), 'Line: ' . __LINE__ . '. bar.bar1 should not be override.');
+ $this->assertSame('bar value 3', $registry1->get('bar.bar3'), 'Line: ' . __LINE__ . '. bar.bar3 should not be override.');
+
+ $registry = new Registry(array('flower' => 'rose', 'honor' => 'Osmanthus month'));
+
+ $registry->merge($this->instance);
+
+ $this->assertEquals($registry->get('flower'), 'sakura');
+ $this->assertEquals($registry->get('honor'), 'Osmanthus month');
+ }
+
+ /**
+ * Method to test merge().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::merge
+ */
+ public function testMergeWithIgnoreValues()
+ {
+ // Test recursive merge
+ $object1 = '{
+ "foo" : "foo value",
+ "bar" : {
+ "bar1" : "bar value 1",
+ "bar2" : "bar value 2",
+ "bar3" : "bar value 3"
+ }
+ }';
+ $object2 = '{
+ "foo" : "foo value",
+ "bar" : {
+ "bar2" : "new bar value 2",
+ "bar3" : ""
+ }
+ }';
+
+ $registry1 = new Registry(json_decode($object1));
+ $registry2 = new Registry(json_decode($object2));
+
+ $registry1->setIgnoreValues(array(null, ''));
+ $registry1->merge($registry2);
+
+ $this->assertEquals('new bar value 2', $registry1->get('bar.bar2'), 'Line: ' . __LINE__ . '. bar.bar2 should be override.');
+ $this->assertEquals('bar value 1', $registry1->get('bar.bar1'), 'Line: ' . __LINE__ . '. bar.bar1 should not be override.');
+ $this->assertSame('bar value 3', $registry1->get('bar.bar3'), 'Line: ' . __LINE__ . '. bar.bar3 should not be override.');
+
+ $registry = new Registry(array('flower' => 'rose', 'honor' => 'Osmanthus month'));
+
+ $registry->merge($this->instance);
+
+ $this->assertEquals($registry->get('flower'), 'sakura');
+ $this->assertEquals($registry->get('honor'), 'Osmanthus month');
+ }
+
+ /**
+ * testMergeTo
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::mergeTo
+ */
+ public function testMergeTo()
+ {
+ $registry = new Registry(array('sunflower' => 'shine', 'honor' => 'Osmanthus month'));
+
+ $this->instance->mergeTo('pos1', $registry);
+
+ $this->assertEquals($this->instance->get('pos1.sunflower'), 'shine');
+ $this->assertEquals($this->instance->get('pos1.honor'), 'Osmanthus month');
+
+ $this->instance->mergeTo('foo.bar', $registry);
+
+ $this->assertEquals($this->instance->get('foo.bar.sunflower'), 'shine');
+ $this->assertEquals($this->instance->get('foo.bar.honor'), 'Osmanthus month');
+ }
+
+ /**
+ * Method to test offsetExists().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::offsetExists
+ */
+ public function testOffsetExists()
+ {
+ $this->assertTrue(isset($this->instance['flower']));
+ $this->assertFalse(isset($this->instance['carbon']));
+ }
+
+ /**
+ * Method to test offsetGet().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::offsetGet
+ */
+ public function testOffsetGet()
+ {
+ $this->assertEquals($this->instance['flower'], 'sakura');
+ }
+
+ /**
+ * Method to test offsetSet().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::offsetSet
+ */
+ public function testOffsetSet()
+ {
+ $this->instance['bird'] = 'flying';
+
+ $this->assertEquals($this->instance['bird'], 'flying');
+ }
+
+ /**
+ * Method to test offsetUnset().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::offsetUnset
+ */
+ public function testOffsetUnset()
+ {
+ unset($this->instance['bird']);
+
+ $this->assertEquals($this->instance['bird'], null);
+ }
+
+ /**
+ * Method to test set().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::set
+ */
+ public function testSet()
+ {
+ $this->instance->set('tree.bird', 'sleeping');
+
+ $this->assertEquals($this->instance->get('tree.bird'), 'sleeping');
+ }
+
+ /**
+ * Method to test setRaw()
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::setRaw
+ */
+ public function testSetRaw()
+ {
+ $object = (object) array('foo' => 'bar');
+
+ $this->instance->setRaw('tree.bird', $object);
+
+ $this->assertEquals('bar', $this->instance->get('tree.bird.foo'));
+ $this->assertSame($object, $this->instance->get('tree.bird'));
+ }
+
+ /**
+ * Method to test toArray().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::toArray
+ */
+ public function testToArray()
+ {
+ $registry = new Registry($this->getTestData());
+
+ $this->assertEquals($registry->toArray(), $this->getTestData());
+ }
+
+ /**
+ * Method to test toObject().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::toObject
+ */
+ public function testToObject()
+ {
+ $registry = new Registry($this->getTestData());
+
+ $this->assertEquals($registry->toObject(), RegistryHelper::toObject($this->getTestData()));
+ }
+
+ /**
+ * Method to test toString().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::toString
+ */
+ public function testToString()
+ {
+ $registry = new Registry($this->getTestData());
+
+ $this->assertStringSafeEquals($this->loadFile(__DIR__ . '/Stubs/flower.ini'), $registry->toString('ini'));
+ $this->assertStringSafeEquals($this->loadFile(__DIR__ . '/Stubs/flower.json'), $registry->toString('json'));
+ $this->assertStringSafeEquals($this->loadFile(__DIR__ . '/Stubs/flower.yml'), $registry->toString('yml'));
+ $this->assertStringSafeEquals($this->loadFile(__DIR__ . '/Stubs/flower.xml'), $registry->toString('xml'));
+ $this->assertStringSafeEquals($this->loadFile(__DIR__ . '/Stubs/flower.php'), $registry->toString('php'));
+ }
+
+ /**
+ * Method to test flatten().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::flatten
+ */
+ public function testFlatten()
+ {
+ $flatted = $this->instance->flatten();
+
+ $this->assertEquals($flatted['pos1.sunflower'], 'love');
+
+ $flatted = $this->instance->flatten('/');
+
+ $this->assertEquals($flatted['pos1/sunflower'], 'love');
+ }
+
+ /**
+ * testAppend
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::push
+ */
+ public function testPush()
+ {
+ $registry = new Registry;
+
+ $registry->set('foo', array('var1', 'var2', 'var3'));
+
+ $registry->push('foo', 'var4');
+
+ $this->assertEquals('var4', $registry->get('foo.3'));
+
+ $registry->push('foo', 'var5', 'var6');
+
+ $this->assertEquals('var5', $registry->get('foo.4'));
+ $this->assertEquals('var6', $registry->get('foo.5'));
+
+ $registry->setRaw('foo2', (object) array('var1', 'var2', 'var3'));
+
+ $b = $registry->get('foo2');
+
+ $this->assertTrue(is_object($b));
+
+ $registry->push('foo2', 'var4');
+
+ $b = $registry->get('foo2');
+
+ $this->assertTrue(is_array($b));
+ }
+
+ /**
+ * testShift
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::shift
+ */
+ public function testShift()
+ {
+ $registry = new Registry;
+
+ $registry->set('foo.bar', array('var1', 'var2', 'var3'));
+
+ $this->assertEquals('var1', $registry->shift('foo.bar'));
+
+ $this->assertEquals('var2', $registry->get('foo.bar.0'));
+
+ $registry->setRaw('foo.bar2', (object) array('v1' => 'var1', 'v2' => 'var2', 'v3' => 'var3'));
+
+ $this->assertEquals('var1', $registry->shift('foo.bar2'));
+
+ $this->assertEquals('var2', $registry->get('foo.bar2.v2'));
+
+ $this->assertTrue(is_array($registry->get('foo.bar2')));
+ }
+
+ /**
+ * testPop
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::pop
+ */
+ public function testPop()
+ {
+ $registry = new Registry;
+
+ $registry->set('foo.bar', array('var1', 'var2', 'var3'));
+
+ $this->assertEquals('var3', $registry->pop('foo.bar'));
+
+ $this->assertNull($registry->get('foo.bar.2'));
+
+ $registry->setRaw('foo.bar2', (object) array('v1' => 'var1', 'v2' => 'var2', 'v3' => 'var3'));
+
+ $this->assertEquals('var3', $registry->pop('foo.bar2'));
+
+ $this->assertNull($registry->get('foo.bar2.v3'));
+
+ $this->assertTrue(is_array($registry->get('foo.bar2')));
+ }
+
+ /**
+ * testUnshift
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::unshift
+ */
+ public function testUnshift()
+ {
+ $registry = new Registry;
+
+ $registry->set('foo', array('var1', 'var2', 'var3'));
+
+ $registry->unshift('foo', 'var4');
+
+ $this->assertEquals('var4', $registry->get('foo.0'));
+
+ $registry->unshift('foo', 'var5', 'var6');
+
+ $this->assertEquals('var5', $registry->get('foo.0'));
+ $this->assertEquals('var6', $registry->get('foo.1'));
+
+ $registry->setRaw('foo2', (object) array('var1', 'var2', 'var3'));
+
+ $b = $registry->get('foo2');
+
+ $this->assertTrue(is_object($b));
+
+ $registry->unshift('foo2', 'var4');
+
+ $b = $registry->get('foo2');
+
+ $this->assertTrue(is_array($b));
+ }
+
+ /**
+ * testReset
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::reset
+ */
+ public function testReset()
+ {
+ $this->instance->reset();
+
+ $this->assertEquals(array(), $this->instance->getRaw());
+ }
+
+ /**
+ * testGetRaw
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::getRaw
+ */
+ public function testGetRaw()
+ {
+ $this->assertEquals($this->getTestData(), $this->instance->getRaw());
+ }
+
+ /**
+ * testGetIterator
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::getIterator
+ */
+ public function testGetIterator()
+ {
+ $this->assertInstanceOf('RecursiveArrayIterator', $this->instance->getIterator());
+
+ $this->assertEquals($this->getTestData(), iterator_to_array($this->instance));
+ $this->assertEquals(
+ iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveArrayIterator($this->getTestData()))),
+ iterator_to_array(new \RecursiveIteratorIterator($this->instance))
+ );
+ }
+
+ /**
+ * testCount
+ *
+ * @return void
+ *
+ * @covers Windwalker\Registry\Registry::count
+ */
+ public function testCount()
+ {
+ $this->assertEquals(5, count($this->instance));
+ }
+
+ /**
+ * loadFile
+ *
+ * @param string $file
+ *
+ * @return string
+ */
+ protected function loadFile($file)
+ {
+ $text = file_get_contents($file);
+
+ return $text;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/StubDumpable.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/StubDumpable.php
new file mode 100644
index 00000000..e62d6724
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/StubDumpable.php
@@ -0,0 +1,43 @@
+iterator = new \ArrayIterator(array('wind' => 'walker'));
+
+ $this->data = array(
+ 'self' => $this,
+ 'new' => $child,
+ 'flower' => array('sakura', 'rose')
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.ini b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.ini
new file mode 100644
index 00000000..c039c6d1
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.ini
@@ -0,0 +1,8 @@
+flower="sakura"
+olive="peace"
+
+[pos1]
+sunflower="love"
+
+[pos2]
+cornflower="elegant"
\ No newline at end of file
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.json b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.json
new file mode 100644
index 00000000..93280fba
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.json
@@ -0,0 +1 @@
+{"flower":"sakura","olive":"peace","pos1":{"sunflower":"love"},"pos2":{"cornflower":"elegant"},"array":["A","B","C"]}
\ No newline at end of file
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.php
new file mode 100644
index 00000000..f976e2c0
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.php
@@ -0,0 +1,17 @@
+ 'sakura',
+ 'olive' => 'peace',
+ 'pos1' => array(
+ "sunflower" => "love"
+ ),
+ 'pos2' => array(
+ "cornflower" => "elegant"
+ ),
+ 'array' => array(
+ "0" => "A",
+ "1" => "B",
+ "2" => "C"
+ ),
+);
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.xml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.xml
new file mode 100644
index 00000000..a1200d86
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.xml
@@ -0,0 +1,2 @@
+
+sakura peace love elegant A B C
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.yml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.yml
new file mode 100644
index 00000000..bceb0be4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/Test/Stubs/flower.yml
@@ -0,0 +1,10 @@
+flower: sakura
+olive: peace
+pos1:
+ sunflower: love
+pos2:
+ cornflower: elegant
+array:
+ - A
+ - B
+ - C
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/composer.json b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/composer.json
new file mode 100644
index 00000000..b2e0e530
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/composer.json
@@ -0,0 +1,29 @@
+{
+ "name": "windwalker/registry",
+ "type": "windwalker-package",
+ "description": "Windwalker Registry package",
+ "keywords": ["windwalker", "framework", "registry"],
+ "homepage": "https://github.com/ventoviro/windwalker-registry",
+ "license": "LGPL-2.0+",
+ "require": {
+ "php": ">=5.3.10"
+ },
+ "require-dev": {
+ "windwalker/test": "~2.0",
+ "symfony/yaml": "2.*"
+ },
+ "minimum-stability": "beta",
+ "suggest": {
+ "symfony/yaml": "Install 2.* if you require YAML support."
+ },
+ "autoload": {
+ "psr-4": {
+ "Windwalker\\Registry\\": ""
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/phpunit.travis.xml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/phpunit.travis.xml
new file mode 100644
index 00000000..690ec926
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/phpunit.travis.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/phpunit.xml.dist b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/phpunit.xml.dist
new file mode 100644
index 00000000..94b6811c
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/registry/phpunit.xml.dist
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/.gitignore b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/.gitignore
new file mode 100644
index 00000000..84718b5d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/.gitignore
@@ -0,0 +1,11 @@
+# Development system files #
+.*
+!/.gitignore
+!/.travis.yml
+
+# Composer #
+vendor/*
+composer.lock
+
+# Test #
+phpunit.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/.travis.yml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/.travis.yml
new file mode 100644
index 00000000..5420e5c4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/.travis.yml
@@ -0,0 +1,16 @@
+language: php
+
+sudo: false
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+
+before_script:
+ - composer update --dev
+
+script:
+ - phpunit --configuration phpunit.travis.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Compiler/BasicCompiler.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Compiler/BasicCompiler.php
new file mode 100644
index 00000000..66fe8afa
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Compiler/BasicCompiler.php
@@ -0,0 +1,138 @@
+{$requirements[$name]})";
+ }
+
+ return "(?P<{$name}>[^/]+)";
+ }
+
+ /**
+ * Adds a wildcard pattern to the regex.
+ *
+ * @param string $regex
+ *
+ * @return null
+ */
+ protected static function replaceWildcards($regex)
+ {
+ preg_match_all(chr(1) . '\(\\*([a-z][a-zA-Z0-9]*)\)' . chr(1), $regex, $matches, PREG_SET_ORDER);
+
+ foreach ($matches as $match)
+ {
+ $name = $match[1];
+
+ $regex = str_replace("(*{$name})", "(?P<{$name}>.*)", $regex);
+ }
+
+ return $regex;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Compiler/BasicGenerator.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Compiler/BasicGenerator.php
new file mode 100644
index 00000000..bcb27d2e
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Compiler/BasicGenerator.php
@@ -0,0 +1,129 @@
+ $segment)
+ {
+ if (empty($data[$segment]))
+ {
+ unset($segments[$k]);
+ }
+ }
+
+ $segments = $segments ? '/(' . implode(')/(', $segments) . ')' : '';
+
+ $route = str_replace($matches[0], $segments, $route);
+
+ return $route;
+ }
+
+ /**
+ * replaceSegments
+ *
+ * @param string $route
+ * @param array &$data
+ *
+ * @return mixed|string
+ */
+ protected static function replaceAllSegments($route, &$data)
+ {
+ preg_match_all(chr(1) . '\(([a-z][a-zA-Z0-9_]*)\)' . chr(1), $route, $matches, PREG_SET_ORDER);
+
+ foreach ($matches as $match)
+ {
+ if (isset($data[$match[1]]))
+ {
+ $route = str_replace($match[0], $data[$match[1]], $route);
+
+ unset($data[$match[1]]);
+ }
+ }
+
+ $queries = http_build_query($data);
+
+ if ($queries)
+ {
+ $route = rtrim($route, '/') . '?' . $queries;
+ }
+
+ return $route;
+ }
+
+ /**
+ * replaceWildCards
+ *
+ * @param string $route
+ * @param array &$data
+ *
+ * @return mixed
+ */
+ protected static function replaceWildCards($route, &$data)
+ {
+ preg_match_all(chr(1) . '\(\*([a-z][a-zA-Z0-9_]*)\)' . chr(1), $route, $matches, PREG_SET_ORDER);
+
+ if (!$matches)
+ {
+ return $route;
+ }
+
+ foreach ($matches as $match)
+ {
+ if (isset($data[$match[1]]))
+ {
+ $route = str_replace($match[0], implode('/', (array) $data[$match[1]]), $route);
+
+ unset($data[$match[1]]);
+ }
+ }
+
+ return $route;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Compiler/TrieCompiler.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Compiler/TrieCompiler.php
new file mode 100644
index 00000000..09fe91c4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Compiler/TrieCompiler.php
@@ -0,0 +1,112 @@
+.*)';
+ }
+ elseif ($segment[0] == '\\' && $segment[1] == '*')
+ {
+ // Match an escaped splat segment.
+ $regex[] = '\*' . preg_quote(substr($segment, 2));
+ }
+ elseif ($segment == ':')
+ {
+ // Match an unnamed variable without capture.
+ $regex[] = '[^/]*';
+ }
+ elseif ($segment[0] == ':')
+ {
+ // Match a named variable and capture the data.
+ $vars[] = $segment = substr($segment, 1);
+ $regex[] = static::requirementPattern($segment, $requirements);
+ }
+ elseif ($segment[0] == '\\' && $segment[1] == ':')
+ {
+ // Match a segment with an escaped variable character prefix.
+ $regex[] = preg_quote(substr($segment, 1));
+ }
+ else
+ {
+ // Match the standard segment.
+ $regex[] = preg_quote($segment);
+ }
+ }
+
+ static::$vars = $vars;
+
+ return chr(1) . '^' . implode('/', $regex) . '$' . chr(1);
+ }
+
+ /**
+ * requirementPattern
+ *
+ * @param string $name
+ * @param array $requirements
+ *
+ * @return string
+ */
+ protected static function requirementPattern($name, $requirements = array())
+ {
+ if (isset($requirements[$name]))
+ {
+ return "(?P<{$name}>{$requirements[$name]})";
+ }
+
+ return "(?P<{$name}>[^/]+)";
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Compiler/TrieGenerator.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Compiler/TrieGenerator.php
new file mode 100644
index 00000000..dc726d65
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Compiler/TrieGenerator.php
@@ -0,0 +1,84 @@
+getPattern(), $data);
+ }
+
+ /**
+ * Match routes.
+ *
+ * @param string $route
+ * @param string $method
+ * @param array $options
+ *
+ * @return Route|false
+ */
+ abstract public function match($route, $method = 'GET', $options = array());
+
+ /**
+ * Match routes.
+ *
+ * @param string $route
+ * @param Route $routeItem
+ *
+ * @return Route|false
+ */
+ public function matchRoute($route, Route $routeItem)
+ {
+ $regex = $routeItem->getRegex();
+
+ if (!$regex || $this->debug)
+ {
+ $regex = BasicCompiler::compile($routeItem->getPattern(), $routeItem->getRequirements());
+
+ $routeItem->setRegex($regex);
+ }
+
+ $route = RouteHelper::normalise($route);
+
+ if (preg_match($regex, $route, $matches))
+ {
+ $variables = RouteHelper::getVariables($matches);
+
+ $variables['_rawRoute'] = $route;
+ }
+ else
+ {
+ return false;
+ }
+
+ $routeItem->setVariables(array_merge($routeItem->getVariables(), $variables));
+
+ return $routeItem;
+ }
+
+ /**
+ * Set Routes
+ *
+ * @param Route[] $routes
+ *
+ * @return static
+ */
+ public function setRoutes(array $routes)
+ {
+ $this->routes = $routes;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property RouteMaps
+ *
+ * @return array
+ */
+ public function getRouteMaps()
+ {
+ return $this->routeMaps;
+ }
+
+ /**
+ * Method to set property routeMaps
+ *
+ * @param array $routeMaps
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setRouteMaps($routeMaps)
+ {
+ $this->routeMaps = $routeMaps;
+
+ return $this;
+ }
+
+ /**
+ * matchOptions
+ *
+ * @param Route $route
+ * @param string $method
+ * @param array $options
+ *
+ * @return bool
+ */
+ protected function matchOptions(Route $route, $method, $options)
+ {
+ $options = $route->prepareOptions($options);
+
+ // Match methods
+ $this->checkType('method', $method, 'string');
+
+ $allowMethods = $route->getAllowMethods();
+
+ if ($allowMethods && !in_array(strtoupper($method), $allowMethods))
+ {
+ return false;
+ }
+
+ // Match Host
+ $this->checkType('host', $options['host'], 'string');
+
+ $host = $route->getHost();
+
+ if ($host && $host != strtolower($options['host']))
+ {
+ return false;
+ }
+
+ // Match schemes
+ $this->checkType('scheme', $options['scheme'], 'string');
+
+ $scheme = $route->getScheme();
+
+ if ($scheme && $scheme != strtolower($options['scheme']))
+ {
+ return false;
+ }
+
+ $port = $route->getPort();
+
+ // Match port
+ if (!$route->getSSL() && $port && $port != $options['port'])
+ {
+ return false;
+ }
+
+ if ($route->getSSL() && $port && $port != $options['port'])
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * checkType
+ *
+ * @param string $name
+ * @param mixed $value
+ * @param string $type
+ * @param string $class
+ *
+ * @return boolean
+ */
+ protected function checkType($name, $value, $type = 'string', $class = null)
+ {
+ if ($value === null)
+ {
+ return true;
+ }
+
+ $type = strtolower($type);
+
+ $false = false;
+
+ if ($type == 'object')
+ {
+ if ($class && !is_subclass_of($value, $class))
+ {
+ $false = true;
+ }
+ elseif (!is_object($value))
+ {
+ $false = true;
+ }
+ }
+ elseif (gettype($value) != $type)
+ {
+ $false = true;
+ }
+
+ if (!$false)
+ {
+ return true;
+ }
+
+ if ($class)
+ {
+ throw new \InvalidArgumentException(sprintf('%s should be instance of of %s.', $name, $class));
+ }
+
+ throw new \InvalidArgumentException(sprintf('%s should be type of %s.', $name, $type));
+ }
+
+ /**
+ * buildRouteMaps
+ *
+ * @param bool $refresh
+ *
+ * @return static
+ */
+ protected function buildRouteMaps($refresh = false)
+ {
+ if ($this->routeMaps && !$this->debug && !$refresh)
+ {
+ return $this;
+ }
+
+ foreach ($this->routes as $key => $routeItem)
+ {
+ $this->routeMaps[$routeItem->getName()] = $key;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Method to get property Count
+ *
+ * @return int
+ */
+ public function getCount()
+ {
+ return $this->count;
+ }
+
+ /**
+ * Method to get property Debug
+ *
+ * @return boolean
+ */
+ public function getDebug()
+ {
+ return $this->debug;
+ }
+
+ /**
+ * Method to set property debug
+ *
+ * @param boolean $debug
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setDebug($debug)
+ {
+ $this->debug = $debug;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Matcher/BinaryMatcher.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Matcher/BinaryMatcher.php
new file mode 100644
index 00000000..4db43821
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Matcher/BinaryMatcher.php
@@ -0,0 +1,92 @@
+count = 0;
+
+ $this->buildRouteMaps();
+
+ $keys = array_keys($this->routeMaps);
+
+ $left = 0;
+ $right = count($this->routeMaps) - 1;
+
+ while ($left <= $right)
+ {
+ $middle = round(($left + $right) / 2);
+ $key = $keys[$middle];
+ $routeItem = $this->routes[$this->routeMaps[$key]];
+
+ $this->count++;
+
+ if ($this->matchOptions($routeItem, $method, $options) && $this->matchRoute($route, $routeItem))
+ {
+ return $routeItem;
+ }
+
+ if (strcmp($route, $key) < 0)
+ {
+ $right = $middle - 1;
+ }
+ else
+ {
+ $left = $middle + 1;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * buildRouteMaps
+ *
+ * @param bool $refresh
+ *
+ * @return static
+ */
+ protected function buildRouteMaps($refresh = false)
+ {
+ if ($this->routeMaps && !$this->debug && !$refresh)
+ {
+ return $this;
+ }
+
+ foreach ($this->routes as $key => $routeItem)
+ {
+ $this->routeMaps[$routeItem->getPattern()] = $key;
+ }
+
+ ksort($this->routeMaps);
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Matcher/MatcherInterface.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Matcher/MatcherInterface.php
new file mode 100644
index 00000000..a7ce50db
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Matcher/MatcherInterface.php
@@ -0,0 +1,49 @@
+count = 0;
+
+ foreach ($this->routes as $routeItem)
+ {
+ $this->count++;
+
+ if (!$this->matchOptions($routeItem, $method, $options))
+ {
+ continue;
+ }
+
+ if ($this->matchRoute($route, $routeItem))
+ {
+ return $routeItem;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Matcher/TrieMatcher.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Matcher/TrieMatcher.php
new file mode 100644
index 00000000..a515f72a
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Matcher/TrieMatcher.php
@@ -0,0 +1,255 @@
+method = $method;
+ $this->options = $options;
+ $this->count = 0;
+
+ // Init some data
+ $this->buildRouteMaps()
+ ->buildTree();
+
+ // Match
+ $segments = explode('/', RouteHelper::sanitize($route));
+
+ $routeItem = $this->matchSegment($segments, $this->tree);
+
+ if (!$routeItem)
+ {
+ return false;
+ }
+
+ $routeItem->setVariables(array_merge($routeItem->getVariables(), $this->vars));
+
+ return $routeItem;
+ }
+
+ /**
+ * matchSegment
+ *
+ * @param array $segments
+ * @param array $node
+ * @param int $level
+ *
+ * @return bool|Route
+ */
+ protected function matchSegment($segments, $node, $level = 1)
+ {
+ $segment = isset($segments[$level - 1]) ? $segments[$level - 1] : false;
+
+ if ($segment === false)
+ {
+ return false;
+ }
+
+ $segment = $segment ? : '/';
+
+ foreach ($node as $regex => $child)
+ {
+ $this->count++;
+
+ // Start with a '(' is a regex
+ if ($regex[0] == '(')
+ {
+ preg_match(chr(1) . $regex . chr(1), $segment, $match);
+
+ if (!$match)
+ {
+ continue;
+ }
+
+ RouteHelper::getVariables($match, $this->vars);
+ }
+ // Otherwise it is a static string
+ else
+ {
+ if ($regex != $segment)
+ {
+ continue;
+ }
+ }
+
+ $result = false;
+
+ // Has child, iterate it.
+ if ($child && is_array($child))
+ {
+ $child = $this->matchSegment($segments, $child, $level + 1);
+ }
+
+ // If is string, means we get a route index, using this index to find Route from maps.
+ if (is_string($child))
+ {
+ $child = $this->routes[$this->routeMaps[$child]];
+ }
+
+ // Match this Route
+ if ($child instanceof Route)
+ {
+ $result = $this->matchOptions($child, $this->method, $this->options);
+ }
+
+ // If match fail, continue find next element.
+ if (!$result)
+ {
+ continue;
+ }
+
+ return $child;
+ }
+
+ return false;
+ }
+
+ /**
+ * buildTree
+ *
+ * @param bool $refresh
+ *
+ * @return static
+ */
+ protected function buildTree($refresh = false)
+ {
+ if ($this->tree && $this->debug && $refresh)
+ {
+ return $this;
+ }
+
+ // Build Tree
+ foreach ($this->routes as $routeItem)
+ {
+ $pattern = $routeItem->getPattern();
+
+ // Compile this route
+ $regex = TrieCompiler::compile($pattern, $routeItem->getRequirements());
+
+ $regex = trim($regex, chr(1) . '^$');
+
+ // Make sure no other '/' is the path separator
+ $regex = str_replace('[^/]', '{:PLACEHOLDER:}', $regex);
+
+ // Split it
+ $regex = explode('/', $regex);
+
+ // Start build tree
+ $node = &$this->tree;
+
+ $length = count($regex);
+
+ foreach ((array) $regex as $k => $segment)
+ {
+ // Fallback the placeholder to /
+ $segment = str_replace('{:PLACEHOLDER:}', '[^/]', $segment);
+
+ $segment = $segment ? : '/';
+
+ if (!isset($node[$segment]))
+ {
+ $node[$segment] = array();
+ }
+
+ // If is last segment, set it as Route name,
+ // that we can search it later or cache this map.
+ if ($k + 1 == $length)
+ {
+ $node[$segment] = $routeItem->getName();
+ }
+
+ $node = &$node[$segment];
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * clear
+ *
+ * @return void
+ */
+ public function clear()
+ {
+ $this->tree = array();
+ }
+
+ /**
+ * Method to get property Tree
+ *
+ * @return array
+ */
+ public function getTree()
+ {
+ return $this->tree;
+ }
+
+ /**
+ * Method to set property tree
+ *
+ * @param array $tree
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setTree($tree)
+ {
+ $this->tree = $tree;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/README.md b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/README.md
new file mode 100644
index 00000000..be1f2423
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/README.md
@@ -0,0 +1,351 @@
+# Windwalker Router
+
+## Installation via Composer
+
+Add this to the require block in your `composer.json`.
+
+``` json
+{
+ "require": {
+ "windwalker/router": "~2.0"
+ }
+}
+```
+
+## Getting Started
+
+``` php
+use Windwalker\Router\Router;
+
+$router = new Router;
+```
+
+### Add Routes
+
+``` php
+use Windwalker\Route\Route;
+
+// Route with name
+$router->addRoute(new Route('sakura', 'flower/(id)/sakura', array('_controller' => 'SakuraController')));
+
+// Route without name
+$router->addRoute(new Route(null, 'flower/(id)/sakura', array('_controller' => 'SakuraController')));
+```
+
+### Match Route
+
+``` php
+$route = $router->match('flower/12/sakura');
+
+$variables = $route->getVariables(); // Array([_controller] => SakuraController)
+
+// Use variables
+$class = $variables['_controller'];
+
+$controller = new $class;
+```
+
+### Add More Options to Route
+
+Route interface: '($name, $pattern[, $variables = array()][, $allowMethods = array()][, $options = array()])'
+
+``` php
+$route = new Route(
+ 'name',
+ 'pattern/of/route/(id).(format)',
+
+ // Default Variables
+ array(
+ 'id' => 1,
+ 'alias' => 'foo-bar-baz',
+ 'format' => 'html'
+ ),
+
+ // Allow methods
+ array('GET', 'POST'),
+
+ // Options
+ array(
+ 'host' => 'windwalker.io',
+ 'scheme' => 'http', // Only http & https
+ 'port' => 80,
+ 'sslPort' => 443,
+ 'requirements' => array(
+ 'id' => '\d+'
+ ),
+ 'extra' => array(
+ '_ctrl' => 'Controller\Class\Name',
+ )
+ )
+);
+
+$router->addRoute($route);
+
+// match routes
+$route = $router->match(
+ 'pattern/of/route/25.html',
+ array(
+ 'host' => $uri->getHost(),
+ 'scheme' => $uri->getScheme(),
+ 'port' => $uri->getPort()
+ )
+);
+
+$variables = $route->getVariables();
+
+// Merge these matched variables back to http request
+$_REQUEST = array_merge($_REQUEST, $variables);
+
+// Extra is the optional variables but we won't want to merge into request
+$extra = $router->getExtra();
+
+print_r($variables);
+print_r($extra);
+```
+
+The printed result:
+
+```
+Array
+(
+ [id] => 25
+ [alias] => foo-bar-baz
+ [format] => html
+)
+
+Array(
+ [_ctrl] => Controller\Class\Name
+)
+```
+
+### Build Route
+
+`build()` is a method to generate route uri for view template.
+
+``` php
+$router->addRoute(new Route('sakura', 'flower/(id)/sakura', array('_controller' => 'SakuraController')));
+
+$uri = $router->build('sakura', array('id' => 30)); // flower/30/sakura
+
+echo 'Link ';
+```
+
+### Quick Mapping
+
+`addMap()` is a simple method to quick add route without complex options.
+
+``` php
+$router->addMap('flower/(id)/sakura', array('_controller' => 'SakuraController', 'id' => 1));
+
+$variables = $router->match('flower/30/sakura');
+```
+
+## Rules
+
+### Simple Params
+
+``` php
+new Route(null, 'flower/(id)-(alias)');
+```
+
+### Optional Params
+
+#### Single Optional Params
+
+``` php
+new Route(null, 'flower(/id)');
+```
+
+Matched route could be:
+
+```
+flower
+flower/25
+```
+
+#### Multiple Optional Params
+
+``` php
+new Route(null, 'flower(/year,month,day)');
+```
+
+Matched route could be:
+
+```
+flower
+flower/2014
+flower/2014/10
+flower/2014/10/12
+```
+
+The matched variables will be
+
+```
+Array
+(
+ [year] => 2014
+ [month] => 10
+ [day] => 12
+)
+```
+
+### Wildcards
+
+``` php
+// Match 'king/john/troilus/and/cressida'
+new Route(null, 'flower/(*tags)');
+```
+
+Matched:
+
+```
+Array
+(
+ [tags] => Array
+ (
+ [0] => john
+ [1] => troilus
+ [2] => and
+ [3] => cressida
+ )
+)
+```
+
+## Matchers
+
+Windwalker Router provides some matchers to use different way to match routes.
+
+### Sequential Matcher
+
+Sequential Matcher use the [Sequential Search Method](http://en.wikipedia.org/wiki/Linear_search) to find route.
+It is the slowest matcher but much more customizable. It is the default matcher of Windwalker Router.
+
+``` php
+use Windwalker\Router\Matcher\SequentialMatcher;
+
+$router = new Router(array(), new SequentialMatcher);
+```
+
+### Binary Matcher
+
+Binary Matcher use the [Binary Search Algorithm](http://en.wikipedia.org/wiki/Binary_search_algorithm) to find route.
+This matcher is faster than SequentialMatcher but it will break the ordering of your routes. Binary search will re-sort all routes by pattern characters.
+
+``` php
+use Windwalker\Router\Matcher\BinaryMatcher;
+
+$router = new Router(array(), new BinaryMatcher);
+```
+
+### Trie Matcher
+
+Trie Matcher use the [Trie](http://en.wikipedia.org/wiki/Trie) tree to search route.
+This matcher is the fastest method of Windwalker Router, but the limit is that it need to use an simpler route pattern
+which is not as flexible as the other two matchers.
+
+``` php
+use Windwalker\Router\Matcher\TrieMatcher;
+
+$router = new Router(array(), new TrieMatcher);
+```
+
+### Rules of TrieMatcher
+
+#### Simple Params
+
+only match when the uri segments all exists. If you want to use optional segments, you must add two or more patterns.
+
+```
+flower
+flower/:id
+flower/:id/:alias
+```
+
+#### Wildcards
+
+This pattern will convert segments after `flower/` this to an array which named `tags`:
+
+```
+flower/*tags
+```
+
+## Single Action Router
+
+Single action router is a simple router that extends Windwalker Router. It just return a string if matched.
+
+This is a single action controller example:
+
+``` php
+$router->addMap('flower/(id)/(alias)', 'FlowerController');
+
+$controller = $router->match('flower/25/sakura');
+
+$_REQUEST = array_merge($_REQUEST, $router->getVariables());
+
+echo (new $controller)->execute();
+```
+
+Or a controller with action name:
+
+``` php
+$router->addMap('flower/(id)/(alias)', 'FlowerController::indexAction');
+
+$matched = $router->match('flower/25/sakura');
+
+$_REQUEST = array_merge($_REQUEST, $router->getVariables());
+
+list($controller, $action) = explode('::', $matched);
+
+echo (new $controller)->$action();
+```
+
+## RestRouter
+
+RestRouter is a simple router extends to SingleActionRouter, it can add some suffix of different methods.
+
+``` php
+$router->addMap('flower/(id)/(alias)', 'Flower\\Controller\\');
+
+$controller = $router->match('flower/25/sakura', 'POST'); // Get Flower\\Controller\\Create
+
+(new $controller)->execute();
+```
+
+Default Suffix mapping is:
+
+```
+'GET' => 'Get',
+'POST' => 'Create',
+'PUT' => 'Update',
+'PATCH' => 'Update',
+'DELETE' => 'Delete',
+'HEAD' => 'Head',
+'OPTIONS' => 'Options'
+```
+
+You can override it:
+
+``` php
+$router->setHttpMethodSuffix('POST', 'SaveController');
+```
+
+## Exception
+
+If Router not matched anything, it throws `Windwalker\Router\Exception\RouteNotFoundException`.
+
+``` php
+try
+{
+ $route = $router->match('flower/25');
+}
+catch (RouteNotFoundException $e)
+{
+ Application::close('Page not found', 404);
+
+ exit();
+}
+catch (\Exception $e)
+{
+ // Do other actions...
+}
+```
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/RestRouter.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/RestRouter.php
new file mode 100644
index 00000000..9a26e2a8
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/RestRouter.php
@@ -0,0 +1,163 @@
+ controller suffix pairs for routing the request.
+ *
+ * @var array
+ */
+ protected $suffixMap = array(
+ 'GET' => 'Get',
+ 'POST' => 'Create',
+ 'PUT' => 'Update',
+ 'PATCH' => 'Update',
+ 'DELETE' => 'Delete',
+ 'HEAD' => 'Head',
+ 'OPTIONS' => 'Options'
+ );
+
+ /**
+ * Property customMethod.
+ *
+ * @var string
+ */
+ protected $customMethod = null;
+
+ /**
+ * A boolean allowing to pass _method as parameter in POST requests
+ *
+ * @var boolean
+ */
+ protected $allowCustomMethod = false;
+
+ /**
+ * Get the property to allow or not method in POST request
+ *
+ * @return boolean
+ */
+ public function isAllowCustomMethod()
+ {
+ return $this->allowCustomMethod;
+ }
+
+ /**
+ * Set a controller class suffix for a given HTTP method.
+ *
+ * @param string $method The HTTP method for which to set the class suffix.
+ * @param string $suffix The class suffix to use when fetching the controller name for a given request.
+ *
+ * @return static Returns itself to support chaining.
+ */
+ public function setHttpMethodSuffix($method, $suffix)
+ {
+ $this->suffixMap[strtoupper((string) $method)] = (string) $suffix;
+
+ return $this;
+ }
+
+ /**
+ * Set to allow or not method in POST request
+ *
+ * @param boolean $value A boolean to allow or not method in POST request
+ *
+ * @return static
+ */
+ public function allowCustomMethod($value)
+ {
+ $this->allowCustomMethod = $value;
+
+ return $this;
+ }
+
+ /**
+ * getCustomMethod
+ *
+ * @return string
+ */
+ public function getCustomMethod()
+ {
+ return $this->customMethod;
+ }
+
+ /**
+ * setCustomMethod
+ *
+ * @param string $customMethod
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setCustomMethod($customMethod)
+ {
+ $this->customMethod = strtoupper($customMethod);
+
+ return $this;
+ }
+
+ /**
+ * Get the controller class suffix string.
+ *
+ * @param string $method
+ *
+ * @return string
+ *
+ * @since 2.0
+ */
+ protected function fetchControllerSuffix($method = 'GET')
+ {
+ $method = strtoupper($method);
+
+ // Validate that we have a map to handle the given HTTP method.
+ if (!isset($this->suffixMap[$method]))
+ {
+ throw new \RuntimeException(sprintf('Unable to support the HTTP method `%s`.', $method), 404);
+ }
+
+ // Check if request method is POST
+ if ( $this->allowCustomMethod == true && strcmp(strtoupper($method), 'POST') === 0)
+ {
+ // Get the method from input
+ $postMethod = $this->getCustomMethod();
+
+ // Validate that we have a map to handle the given HTTP method from input
+ if ($postMethod && isset($this->suffixMap[strtoupper($postMethod)]))
+ {
+ return ucfirst($this->suffixMap[strtoupper($postMethod)]);
+ }
+ }
+
+ return ucfirst($this->suffixMap[$method]);
+ }
+
+ /**
+ * Parse the given route and return the name of a controller mapped to the given route.
+ *
+ * @param string $route The route string for which to find and execute a controller.
+ * @param string $method
+ * @param array $options
+ *
+ * @return string The controller name for the given route excluding prefix.
+ *
+ * @since 2.0
+ */
+ public function match($route, $method = 'GET', $options = array())
+ {
+ $name = parent::match($route, $method, $options);
+
+ // Append the HTTP method based suffix.
+ $name .= $this->fetchControllerSuffix($method);
+
+ return $name;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Route.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Route.php
new file mode 100644
index 00000000..a0795496
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Route.php
@@ -0,0 +1,548 @@
+name = $name;
+ $this->variables = $variables;
+
+ $this->setPattern($pattern);
+ $this->setOptions($options);
+ $this->setAllowMethods($allowMethods);
+ }
+
+ /**
+ * getPattern
+ *
+ * @return string
+ */
+ public function getPattern()
+ {
+ return $this->pattern;
+ }
+
+ /**
+ * setPattern
+ *
+ * @param string $pattern
+ *
+ * @return Route Return self to support chaining.
+ */
+ public function setPattern($pattern)
+ {
+ $this->pattern = RouteHelper::normalise($pattern);
+
+ return $this;
+ }
+
+ /**
+ * getRegex
+ *
+ * @return string
+ */
+ public function getRegex()
+ {
+ return $this->regex;
+ }
+
+ /**
+ * setRegex
+ *
+ * @param string $regex
+ *
+ * @return Route Return self to support chaining.
+ */
+ public function setRegex($regex)
+ {
+ $this->regex = $regex;
+
+ return $this;
+ }
+
+ /**
+ * getVars
+ *
+ * @return array
+ */
+ public function getVars()
+ {
+ return $this->vars;
+ }
+
+ /**
+ * setVars
+ *
+ * @param array $vars
+ *
+ * @return Route Return self to support chaining.
+ */
+ public function setVars($vars)
+ {
+ $this->vars = $vars;
+
+ return $this;
+ }
+
+ /**
+ * getMethod
+ *
+ * @return string
+ */
+ public function getAllowMethods()
+ {
+ return $this->allowMethods;
+ }
+
+ /**
+ * setMethod
+ *
+ * @param array|string $methods
+ *
+ * @return Route Return self to support chaining.
+ */
+ public function setAllowMethods($methods)
+ {
+ $methods = (array) $methods;
+
+ $methods = array_map('strtoupper', $methods);
+
+ $this->allowMethods = $methods;
+
+ return $this;
+ }
+
+ /**
+ * getVariables
+ *
+ * @return array
+ */
+ public function getVariables()
+ {
+ return $this->variables;
+ }
+
+ /**
+ * setVariables
+ *
+ * @param array $variables
+ *
+ * @return Route Return self to support chaining.
+ */
+ public function setVariables($variables)
+ {
+ $this->variables = $variables;
+
+ return $this;
+ }
+
+ /**
+ * getName
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * setName
+ *
+ * @param string $name
+ *
+ * @return Route Return self to support chaining.
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property Options
+ *
+ * @return array
+ */
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ /**
+ * Method to set property options
+ *
+ * @param array $options
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setOptions($options)
+ {
+ $options = $this->prepareOptions($options);
+
+ $this->setHost($options['host']);
+ $this->setScheme($options['scheme']);
+ $this->setPort($options['port']);
+ $this->setSslPort($options['sslPort']);
+ $this->setRequirements($options['requirements']);
+ $this->setExtra($options['extra']);
+
+ return $this;
+ }
+
+ /**
+ * prepareOptions
+ *
+ * @param array $options
+ *
+ * @return array
+ */
+ public function prepareOptions($options)
+ {
+ $defaultOptions = array(
+ 'requirements' => array(),
+ 'options' => array(),
+ 'host' => null,
+ 'scheme' => null,
+ 'port' => null,
+ 'sslPort' => null,
+ 'extra' => array()
+ );
+
+ return array_merge($defaultOptions, (array) $options);
+ }
+
+ /**
+ * Method to get property Options
+ *
+ * @param string $name
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public function getOption($name, $default = null)
+ {
+ if (array_key_exists($name, $this->options))
+ {
+ return $this->options[$name];
+ }
+
+ return $default;
+ }
+
+ /**
+ * Method to set property options
+ *
+ * @param string $name
+ * @param mixed $value
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setOption($name, $value)
+ {
+ $this->options[$name] = $value;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property SslPort
+ *
+ * @return int
+ */
+ public function getSslPort()
+ {
+ return $this->sslPort;
+ }
+
+ /**
+ * Method to set property sslPort
+ *
+ * @param int $sslPort
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setSslPort($sslPort)
+ {
+ $this->sslPort = (int) $sslPort;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property Port
+ *
+ * @return int
+ */
+ public function getPort()
+ {
+ return $this->port;
+ }
+
+ /**
+ * Method to set property port
+ *
+ * @param int $port
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setPort($port)
+ {
+ $this->port = (int) $port;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property Scheme
+ *
+ * @return string
+ */
+ public function getScheme()
+ {
+ return $this->scheme;
+ }
+
+ /**
+ * Method to set property scheme
+ *
+ * @param string $scheme
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setScheme($scheme)
+ {
+ $this->scheme = strtolower($scheme);
+
+ $this->ssl = ($this->scheme == 'https');
+
+ return $this;
+ }
+
+ /**
+ * Method to get property Host
+ *
+ * @return string
+ */
+ public function getHost()
+ {
+ return $this->host;
+ }
+
+ /**
+ * Method to set property host
+ *
+ * @param string $host
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setHost($host)
+ {
+ $this->host = strtolower($host);
+
+ return $this;
+ }
+
+ /**
+ * Method to get property Requirements
+ *
+ * @return array
+ */
+ public function getRequirements()
+ {
+ return $this->requirements;
+ }
+
+ /**
+ * Method to set property requirements
+ *
+ * @param array $requirements
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setRequirements($requirements)
+ {
+ $this->requirements = (array) $requirements;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property Ssl
+ *
+ * @return boolean
+ */
+ public function getSSL()
+ {
+ return $this->ssl;
+ }
+
+ /**
+ * Method to set property ssl
+ *
+ * @param boolean $ssl
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setSSL($ssl)
+ {
+ $this->ssl = $ssl;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property Extra
+ *
+ * @return array
+ */
+ public function getExtra()
+ {
+ return $this->extra;
+ }
+
+ /**
+ * Method to set property extra
+ *
+ * @param array $extra
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setExtra($extra)
+ {
+ $this->extra = (array) $extra;
+
+ return $this;
+ }
+
+ /**
+ * Retrieve an external iterator
+ *
+ * @return \Traversable An instance of an object implementing Iterator or Traversable
+ */
+ public function getIterator()
+ {
+ return new \ArrayIterator(get_object_vars($this));
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/RouteHelper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/RouteHelper.php
new file mode 100644
index 00000000..5da4300c
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/RouteHelper.php
@@ -0,0 +1,93 @@
+ $var)
+ {
+ if (is_numeric($i))
+ {
+ continue;
+ }
+
+ if (strpos($var, '/') !== false)
+ {
+ $var = explode('/', $var);
+ }
+
+ $vars[$i] = $var;
+ }
+
+ return $vars;
+ }
+
+ /**
+ * getEnvironment
+ *
+ * @return array
+ */
+ public static function getEnvironment()
+ {
+ return array(
+ 'host' => $_SERVER['HTTP_HOST'],
+ 'scheme' => $_SERVER['REQUEST_SCHEME'],
+ 'port' => $_SERVER['SERVER_PORT']
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Router.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Router.php
new file mode 100644
index 00000000..9fe742e4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Router.php
@@ -0,0 +1,270 @@
+addRoutes($routes);
+
+ $this->matcher = $matcher ? : new SequentialMatcher;
+ }
+
+ /**
+ * addMap
+ *
+ * @param string $pattern
+ * @param array $variables
+ *
+ * @return Route
+ */
+ public function addMap($pattern, $variables = array())
+ {
+ $route = new Route(null, $pattern, $variables);
+
+ $this->addRoute($route);
+
+ return $route;
+ }
+
+ /**
+ * addMaps
+ *
+ * @param array $maps
+ *
+ * @return $this
+ */
+ public function addMaps(array $maps)
+ {
+ foreach ($maps as $pattern => $variables)
+ {
+ $this->addMap($pattern, $variables);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add Route
+ *
+ * @param string|Route $name
+ * @param string $pattern
+ * @param array $variables
+ * @param array $method
+ * @param array $options
+ *
+ * @return static
+ */
+ public function addRoute($name, $pattern = null, $variables = array(), $method = array(), $options = array())
+ {
+ if ($name instanceof Route)
+ {
+ $route = $name;
+ }
+ else
+ {
+ if (!is_string($pattern))
+ {
+ throw new \InvalidArgumentException('Route pattern should be string');
+ }
+
+ $route = new Route($name, $pattern, $variables, $method, $options);
+ }
+
+ if ($name = $route->getName())
+ {
+ $this->routes[$name] = $route;
+ }
+ elseif (!$name || is_numeric($name))
+ {
+ $this->routes[] = $route;
+ }
+
+ return $this;
+ }
+
+ /**
+ * hasRoute
+ *
+ * @param string $name
+ *
+ * @return boolean
+ */
+ public function hasRoute($name)
+ {
+ return isset($this->routes[$name]);
+ }
+
+ /**
+ * getRoute
+ *
+ * @param string $name
+ *
+ * @return Route
+ */
+ public function getRoute($name)
+ {
+ if ($this->hasRoute($name))
+ {
+ return $this->routes[$name];
+ }
+
+ return null;
+ }
+
+ /**
+ * addRoutes
+ *
+ * @param array $routes
+ *
+ * @return Router
+ */
+ public function addRoutes(array $routes)
+ {
+ foreach ($routes as $route)
+ {
+ $this->addRoute($route);
+ }
+
+ return $this;
+ }
+
+ /**
+ * parseRoute
+ *
+ * @param string $route
+ * @param string $method
+ * @param array $options
+ *
+ * @return Route|boolean
+ */
+ public function match($route, $method = 'GET', $options = array())
+ {
+ // Trim the query string off.
+ $route = preg_replace('/([^?]*).*/u', '\1', $route);
+
+ // Sanitize and explode the route.
+ $route = parse_url($route, PHP_URL_PATH);
+
+ $matched = $this->matcher
+ ->setRoutes($this->routes)
+ ->match($route, $method, $options);
+
+ if ($matched === false)
+ {
+ throw new RouteNotFoundException(sprintf('Unable to handle request for route `%s`.', $route), 404);
+ }
+
+ return $matched;
+ }
+
+ /**
+ * buildRoute
+ *
+ * @param string $name
+ * @param array $queries
+ * @param bool $rootSlash
+ *
+ * @return string
+ */
+ public function build($name, $queries = array(), $rootSlash = false)
+ {
+ if (!array_key_exists($name, $this->routes))
+ {
+ throw new \OutOfRangeException('Route: ' . $name . ' not found.');
+ }
+
+ $route = $this->matcher->build($this->routes[$name], (array) $queries);
+
+ if ($rootSlash)
+ {
+ return RouteHelper::normalise($route);
+ }
+
+ return ltrim($route, '/');
+ }
+
+ /**
+ * Method to get property Matcher
+ *
+ * @return MatcherInterface
+ */
+ public function getMatcher()
+ {
+ return $this->matcher;
+ }
+
+ /**
+ * Method to set property matcher
+ *
+ * @param MatcherInterface $matcher
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setMatcher($matcher)
+ {
+ $this->matcher = $matcher;
+
+ return $this;
+ }
+
+ /**
+ * Method to get property Routes
+ *
+ * @return Route[]
+ */
+ public function getRoutes()
+ {
+ return $this->routes;
+ }
+
+ /**
+ * Method to set property routes
+ *
+ * @param Route[] $routes
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setRoutes($routes)
+ {
+ $this->routes = $routes;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/RouterInterface.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/RouterInterface.php
new file mode 100644
index 00000000..031e1206
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/RouterInterface.php
@@ -0,0 +1,27 @@
+addMaps($routes);
+
+ $this->matcher = $matcher ? : new SequentialMatcher;
+ }
+
+ /**
+ * addRoute
+ *
+ * @param string $pattern
+ * @param string $controller
+ *
+ * @throws \LogicException
+ * @throws \InvalidArgumentException
+ * @return static
+ */
+ public function addMap($pattern, $controller = null)
+ {
+ if (!is_string($controller))
+ {
+ throw new \InvalidArgumentException('Please give me controller name string. ' . ucfirst(gettype($controller)) . ' given.');
+ }
+
+ if ($pattern instanceof Route)
+ {
+ throw new \LogicException('Do not use Route object in ' . get_called_class());
+ }
+
+ return parent::addRoute(null, $pattern, array('_controller' => $controller));
+ }
+
+ /**
+ * parseRoute
+ *
+ * @param string $route
+ * @param string $method
+ * @param array $options
+ *
+ * @throws \UnexpectedValueException
+ * @return array|boolean
+ */
+ public function match($route, $method = 'GET', $options = array())
+ {
+ $matched = parent::match($route, $method, $options);
+
+ $vars = $matched->getVariables();
+
+ if (!array_key_exists('_controller', $vars))
+ {
+ throw new \UnexpectedValueException('Controller not found.', 500);
+ }
+
+ $controller = $vars['_controller'];
+
+ unset($vars['_controller']);
+
+ $this->setVariables($vars);
+
+ return $controller;
+ }
+
+ /**
+ * getRequests
+ *
+ * @return array
+ */
+ public function getVariables()
+ {
+ return $this->variables;
+ }
+
+ /**
+ * setRequests
+ *
+ * @param array $variables
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setVariables($variables)
+ {
+ $this->variables = $variables;
+
+ return $this;
+ }
+}
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Compiler/BasicCompilerTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Compiler/BasicCompilerTest.php
new file mode 100644
index 00000000..0f92f502
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Compiler/BasicCompilerTest.php
@@ -0,0 +1,138 @@
+\d+)',
+ '/flower/25',
+ array('id' => 25),
+ __LINE__
+ ),
+ array(
+ '/flower/caesar/(id)/(alias)',
+ '/flower/caesar/(?P\d+)/(?P[^/]+)',
+ '/flower/caesar/25/othello',
+ array('id' => 25, 'alias' => 'othello'),
+ __LINE__
+ ),
+ array(
+ '/flower/caesar/(id)-(alias)',
+ '/flower/caesar/(?P\d+)-(?P[^/]+)',
+ '/flower/caesar/25-othello',
+ array('id' => 25, 'alias' => 'othello'),
+ __LINE__
+ ),
+ array(
+ '/flower(/id)',
+ '/flower(/(?P\d+))?',
+ '/flower/33',
+ array('id' => 33),
+ __LINE__
+ ),
+ array(
+ '/flower(/id)',
+ '/flower(/(?P\d+))?',
+ '/flower',
+ array(),
+ __LINE__
+ ),
+ array(
+ '/flower/caesar(/id,alias)',
+ '/flower/caesar(/(?P\d+)(/(?P[^/]+))?)?',
+ '/flower/caesar/25/othello',
+ array('id' => 25, 'alias' => 'othello'),
+ __LINE__
+ ),
+ array(
+ '/flower/caesar(/id,alias)',
+ '/flower/caesar(/(?P\d+)(/(?P[^/]+))?)?',
+ '/flower/caesar/25',
+ array('id' => 25),
+ __LINE__
+ ),
+ array(
+ '/flower/caesar(/id,alias)',
+ '/flower/caesar(/(?P\d+)(/(?P[^/]+))?)?',
+ '/flower/caesar',
+ array(),
+ __LINE__
+ ),
+ array(
+ '/king(/foo,bar,baz,yoo)',
+ '/king(/(?P[^/]+)(/(?P[^/]+)(/(?P[^/]+)(/(?P[^/]+))?)?)?)?',
+ '/king/john/troilus/and/cressida',
+ array('foo' => 'john', 'bar' => 'troilus', 'baz' => 'and', 'yoo' => 'cressida'),
+ __LINE__
+ ),
+ array(
+ '/king/(*tags)',
+ '/king/(?P.*)',
+ '/king/john/troilus/and/cressida',
+ array('tags' => array('john', 'troilus', 'and', 'cressida')),
+ __LINE__
+ ),
+ array(
+ '/king/(*tags)/and/(alias)',
+ '/king/(?P.*)/and/(?P[^/]+)',
+ '/king/john/troilus/and/cressida',
+ array('tags' => array('john', 'troilus'), 'alias' => 'cressida'),
+ __LINE__
+ ),
+ );
+ }
+
+ /**
+ * Method to test compile().
+ *
+ * @param string $pattern
+ * @param string $expected
+ * @param int $line
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Compiler\BasicCompiler::compile
+ *
+ * @dataProvider regexList
+ */
+ public function testCompile($pattern, $expected, $route, $expectedMatches, $line)
+ {
+ $regex = BasicCompiler::compile($pattern, array('id' => '\d+'));
+
+ $this->assertEquals(chr(1) . '^' . $expected . '$' . chr(1), $regex, 'Fail at: ' . $line);
+
+ preg_match($regex, $route, $matches);
+
+ $this->assertNotEmpty($matches);
+
+ $vars = RouteHelper::getVariables($matches);
+
+ $this->assertEquals($expectedMatches, $vars);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Compiler/BasicGeneratorTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Compiler/BasicGeneratorTest.php
new file mode 100644
index 00000000..074d82d3
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Compiler/BasicGeneratorTest.php
@@ -0,0 +1,104 @@
+ 25),
+ 'flower/25',
+ __LINE__
+ ),
+ array(
+ 'flower/(id)/(alias)',
+ array('id' => 25, 'alias' => 'sakura'),
+ 'flower/25/sakura',
+ __LINE__
+ ),
+ array(
+ 'flower/(id)/(alias)',
+ array('alias' => 'sakura'),
+ 'flower/(id)/sakura',
+ __LINE__
+ ),
+ array(
+ 'flower/(id)-(alias)',
+ array('id' => 25, 'alias' => 'sakura'),
+ 'flower/25-sakura',
+ __LINE__
+ ),
+ array(
+ 'flower(/id)',
+ array('id' => 25, 'alias' => 'sakura'),
+ 'flower/25?alias=sakura',
+ __LINE__
+ ),
+ array(
+ 'flower(/id)',
+ array('alias' => 'sakura'),
+ 'flower?alias=sakura',
+ __LINE__
+ ),
+ array(
+ 'flower(/id,alias)',
+ array('id' => 25, 'alias' => 'sakura'),
+ 'flower/25/sakura',
+ __LINE__
+ ),
+ array(
+ 'flower(/foo,bar,baz)',
+ array('foo' => 2014, 'bar' => 9, 'baz' => 27),
+ 'flower/2014/9/27',
+ __LINE__
+ ),
+ array(
+ 'flower/(*tags)',
+ array('id' => 25, 'tags' => array('sakura', 'rose', 'olive')),
+ 'flower/sakura/rose/olive?id=25',
+ __LINE__
+ ),
+ array(
+ 'flower/(*tags)/(alias)',
+ array('id' => 25, 'alias' => 'wind', 'tags' => array('sakura', 'rose', 'olive')),
+ 'flower/sakura/rose/olive/wind?id=25',
+ __LINE__
+ ),
+ );
+ }
+
+ /**
+ * Method to test generate().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Compiler\BasicGenerator::generate
+ *
+ * @dataProvider regexList
+ */
+ public function testGenerate($pattern, $data, $expected, $line)
+ {
+ $this->assertEquals($expected, BasicGenerator::generate($pattern, $data), 'Fail at: ' . $line);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Compiler/TrieCompilerTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Compiler/TrieCompilerTest.php
new file mode 100644
index 00000000..299be734
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Compiler/TrieCompilerTest.php
@@ -0,0 +1,94 @@
+\d+)',
+ '/flower/5',
+ array('id' => 5),
+ __LINE__
+ ),
+ array(
+ '/flower/caesar/:id/:alias',
+ '/flower/caesar/(?P\d+)/(?P[^/]+)',
+ '/flower/caesar/25/othello',
+ array('id' => 25, 'alias' => 'othello'),
+ __LINE__
+ ),
+ array(
+ '/king/john/*tags',
+ '/king/john/(?P.*)',
+ '/king/john/troilus/and/cressida',
+ array('tags' => array('troilus', 'and', 'cressida')),
+ __LINE__
+ ),
+ array(
+ '/king/*tags/:alias',
+ '/king/(?P.*)/(?P[^/]+)',
+ '/king/john/troilus/and/cressida',
+ array('tags' => array('john', 'troilus', 'and'), 'alias' => 'cressida'),
+ __LINE__
+ ),
+ array(
+ '/king/*tags/and/:alias',
+ '/king/(?P.*)/and/(?P[^/]+)',
+ '/king/john/troilus/and/cressida',
+ array('tags' => array('john', 'troilus'), 'alias' => 'cressida'),
+ __LINE__
+ ),
+ );
+ }
+
+ /**
+ * Method to test compile().
+ *
+ * @param string $pattern
+ * @param string $expected
+ * @param int $line
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Compiler\BasicCompiler::compile
+ *
+ * @dataProvider regexList
+ */
+ public function testCompile($pattern, $expected, $route, $expectedMatches, $line)
+ {
+ $regex = TrieCompiler::compile($pattern, array('id' => '\d+'));
+
+ $this->assertEquals(chr(1) . '^' . $expected . '$' . chr(1), $regex, 'Fail at: ' . $line);
+
+ preg_match($regex, $route, $matches);
+
+ $vars = RouteHelper::getVariables($matches);
+
+ $this->assertNotEmpty($matches);
+
+ $this->assertEquals($expectedMatches, $vars);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Compiler/TrieGeneratorTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Compiler/TrieGeneratorTest.php
new file mode 100644
index 00000000..6f97d0c1
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Compiler/TrieGeneratorTest.php
@@ -0,0 +1,74 @@
+ 25),
+ '/flower/25',
+ __LINE__
+ ),
+ array(
+ '/flower/:id/:alias',
+ array('id' => 25, 'alias' => 'sakura'),
+ '/flower/25/sakura',
+ __LINE__
+ ),
+ array(
+ '/flower/:id/:alias',
+ array('alias' => 'sakura'),
+ '/flower/null/sakura',
+ __LINE__
+ ),
+ array(
+ '/flower/*tags',
+ array('id' => 25, 'tags' => array('sakura', 'rose', 'olive')),
+ '/flower/sakura/rose/olive/?id=25',
+ __LINE__
+ ),
+ array(
+ '/flower/*tags/:alias',
+ array('id' => 25, 'alias' => 'wind', 'tags' => array('sakura', 'rose', 'olive')),
+ '/flower/sakura/rose/olive/wind/?id=25',
+ __LINE__
+ ),
+ );
+ }
+
+ /**
+ * Method to test generate().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Compiler\BasicGenerator::generate
+ *
+ * @dataProvider regexList
+ */
+ public function testGenerate($pattern, $data, $expected, $line)
+ {
+ $this->assertEquals($expected, TrieGenerator::generate($pattern, $data), 'Fail at: ' . $line);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Matcher/BinaryMatcherTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Matcher/BinaryMatcherTest.php
new file mode 100644
index 00000000..f624a2ec
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Matcher/BinaryMatcherTest.php
@@ -0,0 +1,77 @@
+instance = new BinaryMatcher;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test match().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Matcher\BinaryMatcher::match
+ */
+ public function testMatch()
+ {
+ $routes = file_get_contents(__DIR__ . '/../fixtures/routes.txt');
+
+ $routes = explode("\n", trim($routes));
+
+ $routes = array_map(
+ function ($route)
+ {
+ return new Route($route, $route, array('_return' => $route));
+ },
+ $routes
+ );
+
+ $matched = $this->instance->setRoutes($routes)
+ ->match('/corge/quux/qux');
+
+ $this->assertEquals('/corge/quux/qux', $matched->getName());
+
+ $this->instance->getCount();
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Matcher/SequentialMatcherTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Matcher/SequentialMatcherTest.php
new file mode 100644
index 00000000..11fbed83
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Matcher/SequentialMatcherTest.php
@@ -0,0 +1,235 @@
+instance = new SequentialMatcher;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * metchCases
+ *
+ * @return array
+ */
+ public function matchCases()
+ {
+ return array(
+ // @ Same route, but different server params
+
+ // Port 80 with default route
+ array(
+ 'http://windwalker.com/flower/5',
+ 'flower/(id)',
+ 'GET',
+ true,
+ __LINE__
+ ),
+ // Port 443(default) with SSL
+ array(
+ 'https://windwalker.com/flower/5',
+ 'flower/(id)',
+ 'GET',
+ false,
+ __LINE__
+ ),
+ // Port 137 with SSL
+ array(
+ 'https://windwalker.com:137/flower/5',
+ 'flower/(id)',
+ 'GET',
+ false,
+ __LINE__
+ ),
+ // POST method
+ array(
+ 'http://windwalker.com/flower/5',
+ 'flower/(id)',
+ 'POST',
+ false,
+ __LINE__
+ ),
+ // PUT method
+ array(
+ 'http://windwalker.com/flower/5',
+ 'flower/(id)',
+ 'PUT',
+ true,
+ __LINE__
+ ),
+ // Different host
+ array(
+ 'http://johnnywalker.com/flower/5',
+ 'flower/(id)',
+ 'GET',
+ false,
+ __LINE__
+ ),
+ // @ Match different routes
+
+ // Root
+ array(
+ 'http://windwalker.com/',
+ '/',
+ 'GET',
+ true,
+ __LINE__
+ ),
+
+ // Optional id
+ array(
+ 'http://windwalker.com/flower/5',
+ 'flower(/id)',
+ 'GET',
+ true,
+ __LINE__
+ ),
+ array(
+ 'http://windwalker.com/flower',
+ 'flower(/id)',
+ 'GET',
+ true,
+ __LINE__
+ ),
+ // Optional Multiple
+ array(
+ 'http://windwalker.com/flower/5/sakura',
+ 'flower(/id,alias)',
+ 'GET',
+ true,
+ __LINE__
+ ),
+ array(
+ 'http://windwalker.com/flower/5',
+ 'flower(/id,alias)',
+ 'GET',
+ true,
+ __LINE__
+ ),
+ array(
+ 'http://windwalker.com/flower',
+ 'flower(/id,alias)',
+ 'GET',
+ true,
+ __LINE__
+ ),
+ // Wildcards
+ array(
+ 'http://windwalker.com/flower/foo/bar/baz',
+ 'flower/(*tags)',
+ 'GET',
+ true,
+ __LINE__
+ ),
+ array(
+ 'http://windwalker.com/flower',
+ 'flower/(*tags)',
+ 'GET',
+ false,
+ __LINE__
+ ),
+ );
+ }
+
+ /**
+ * Method to test match().
+ *
+ * @param string $url
+ * @param string $pattern
+ * @param string $method
+ * @param boolean $expected
+ * @param integer $line
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Route::match
+ *
+ * @dataProvider matchCases
+ */
+ public function testMatch($url, $pattern, $method, $expected, $line)
+ {
+ $uri = new Uri($url);
+
+ $host = $uri->getHost();
+ $scheme = $uri->getScheme();
+ $port = $uri->getPort() ? : 80;
+
+ $config = array(
+ 'name' => 'flower',
+ 'pattern' => $pattern,
+ 'variables' => array(
+ '_controller' => 'FlowerController',
+ 'id' => 1
+ ),
+ 'method' => array('GET', 'PUT'),
+ 'host' => 'windwalker.com',
+ 'scheme' => 'http',
+ 'port' => 80,
+ 'sslPort' => 443,
+ 'requirements' => array(
+ 'id' => '\d+'
+ )
+ );
+
+ $route = new \Windwalker\Router\Route(
+ $config['name'],
+ $config['pattern'],
+ $config['variables'],
+ $config['method'],
+ $config
+ );
+
+ $result = $this->instance
+ ->setRoutes(array($route))
+ ->match(
+ $uri->getPath(),
+ $method,
+ array(
+ 'host' => $host,
+ 'scheme' => $scheme,
+ 'port' => $port
+ )
+ );
+
+ $this->assertEquals($expected, !empty($result), 'Match fail, case on line: ' . $line);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Matcher/TrieMatcherTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Matcher/TrieMatcherTest.php
new file mode 100644
index 00000000..161ed0ee
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/Matcher/TrieMatcherTest.php
@@ -0,0 +1,243 @@
+markTestSkipped('Not prepare');
+
+ $this->instance = new TrieMatcher;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * metchCases
+ *
+ * @return array
+ */
+ public function matchCases()
+ {
+ return array(
+ // @ Same route, but different server params
+
+ // Port 80 with default route
+ array(
+ 'http://windwalker.com/flower/5',
+ 'flower/:id',
+ 'GET',
+ true,
+ __LINE__
+ ),
+ // Port 443(default) with SSL
+ array(
+ 'https://windwalker.com/flower/5',
+ 'flower/:id',
+ 'GET',
+ false,
+ __LINE__
+ ),
+ // Port 137 with SSL
+ array(
+ 'https://windwalker.com:137/flower/5',
+ 'flower/:id',
+ 'GET',
+ false,
+ __LINE__
+ ),
+ // POST method
+ array(
+ 'http://windwalker.com/flower/5',
+ 'flower/:id',
+ 'POST',
+ false,
+ __LINE__
+ ),
+ // PUT method
+ array(
+ 'http://windwalker.com/flower/5',
+ 'flower/:id',
+ 'PUT',
+ true,
+ __LINE__
+ ),
+ // Different host
+ array(
+ 'http://johnnywalker.com/flower/5',
+ 'flower/:id',
+ 'GET',
+ false,
+ __LINE__
+ ),
+ // @ Match different routes
+
+ // Root
+ array(
+ 'http://windwalker.com/',
+ '/',
+ 'GET',
+ true,
+ __LINE__
+ ),
+
+ // Basic rules
+ array(
+ 'http://windwalker.com/flower/5',
+ 'flower/:id/item/:alias',
+ 'GET',
+ false,
+ __LINE__
+ ),
+
+ // Wildcards
+ array(
+ 'http://windwalker.com/flower/foo/bar/baz',
+ 'flower/*tags',
+ 'GET',
+ true,
+ __LINE__
+ ),
+ array(
+ 'http://windwalker.com/flower',
+ 'flower/*tags',
+ 'GET',
+ false,
+ __LINE__
+ ),
+ );
+ }
+
+ /**
+ * Method to test match().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Route::match
+ */
+ public function testMatch()
+ {
+ $routes = file_get_contents(__DIR__ . '/../fixtures/trie.txt');
+
+ $routes = explode("\n", trim($routes));
+
+ $routes = array_map(
+ function ($route)
+ {
+ $route = trim($route, '/');
+
+ return new Route($route, $route, array('_return' => $route));
+ },
+ $routes
+ );
+
+ $matched = $this->instance->setRoutes($routes)
+ ->match('/corge/quux/qux');
+
+ $this->assertFalse(!$matched);
+
+ $this->assertEquals('corge/quux/:qux', $matched->getName());
+
+ $this->instance->getCount();
+ }
+
+ /**
+ * Method to test match().
+ *
+ * @param string $url
+ * @param string $pattern
+ * @param string $method
+ * @param boolean $expected
+ * @param integer $line
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Route::match
+ *
+ * @dataProvider matchCases
+ */
+ public function testMatchRules($url, $pattern, $method, $expected, $line)
+ {
+ $uri = new Uri($url);
+
+ $host = $uri->getHost();
+ $scheme = $uri->getScheme();
+ $port = $uri->getPort() ? : 80;
+
+ $config = array(
+ 'name' => 'flower',
+ 'pattern' => $pattern,
+ 'variables' => array(
+ '_controller' => 'FlowerController',
+ 'id' => 1
+ ),
+ 'method' => array('GET', 'PUT'),
+ 'host' => 'windwalker.com',
+ 'scheme' => 'http',
+ 'port' => 80,
+ 'sslPort' => 443,
+ 'requirements' => array(
+ 'id' => '\d+'
+ )
+ );
+
+ $route = new \Windwalker\Router\Route(
+ $config['name'],
+ $config['pattern'],
+ $config['variables'],
+ $config['method'],
+ $config
+ );
+
+ $result = $this->instance
+ ->setRoutes(array($route))
+ ->match(
+ $uri->getPath(),
+ $method,
+ array(
+ 'host' => $host,
+ 'scheme' => $scheme,
+ 'port' => $port
+ )
+ );
+
+ $this->assertEquals($expected, !empty($result), 'Match fail, case on line: ' . $line);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/RestRouterTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/RestRouterTest.php
new file mode 100644
index 00000000..677ba96f
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/RestRouterTest.php
@@ -0,0 +1,165 @@
+instance = new RestRouter;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test isAllowCustomMethod().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\RestRouter::isAllowCustomMethod
+ */
+ public function testIsAllowCustomMethod()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setHttpMethodSuffix().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\RestRouter::setHttpMethodSuffix
+ * @TODO Implement testSetHttpMethodSuffix().
+ */
+ public function testSetHttpMethodSuffix()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test allowCustomMethod().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\RestRouter::allowCustomMethod
+ * @TODO Implement testAllowCustomMethod().
+ */
+ public function testAllowCustomMethod()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getCustomMethod().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\RestRouter::getCustomMethod
+ * @TODO Implement testGetCustomMethod().
+ */
+ public function testGetCustomMethod()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setCustomMethod().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\RestRouter::setCustomMethod
+ * @TODO Implement testSetCustomMethod().
+ */
+ public function testSetCustomMethod()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test match().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\RestRouter::match
+ */
+ public function testMatch()
+ {
+ $routes = array(
+ 'flower/(id)/(alias)' => 'Flower\\Controller\\',
+ 'foo/bar(/id,sakura)' => 'Sakura\\Controller\\'
+ );
+
+ $this->instance->addMaps($routes);
+
+ $result = $this->instance->match('flower/5/foo');
+ $vars = $this->instance->getVariables();
+
+ $this->assertEquals('Flower\\Controller\\Get', $result);
+ $this->assertEquals('foo', $vars['alias']);
+
+ $result = $this->instance->match('foo/bar/5/baz', 'POST');
+ $vars = $this->instance->getVariables();
+
+ $this->assertEquals('Sakura\\Controller\\Create', $result);
+ $this->assertEquals('baz', $vars['sakura']);
+
+ $this->instance
+ ->allowCustomMethod(true)
+ ->setCustomMethod('PUT');
+
+ $result = $this->instance->match('foo/bar/5/baz', 'POST');
+ $vars = $this->instance->getVariables();
+
+ $this->assertEquals('Sakura\\Controller\\Update', $result);
+ $this->assertEquals('baz', $vars['sakura']);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/RouteHelperTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/RouteHelperTest.php
new file mode 100644
index 00000000..0a577b8d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/RouteHelperTest.php
@@ -0,0 +1,69 @@
+assertEquals('/foo/bar/baz', RouteHelper::sanitize('/foo/bar/baz'));
+ $this->assertEquals('/foo/bar/baz', RouteHelper::sanitize('http://flower.com/foo/bar/baz/?olive=peace'));
+ }
+
+ /**
+ * Method to test normalise()
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\RouteHelper::normalise
+ */
+ public function testNormalise()
+ {
+ $this->assertEquals('/foo/bar/baz', RouteHelper::sanitize('foo/bar/baz/'));
+ }
+
+ /**
+ * testGetVariables
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\RouteHelper::getVariables
+ */
+ public function testGetVariables()
+ {
+ $array = array(
+ 0 => 5,
+ 'id' => 5,
+ 1 => 'foo',
+ 'bar' => 'foo'
+ );
+
+ $this->assertEquals(array('id' => 5, 'bar' => 'foo'), RouteHelper::getVariables($array));
+
+ $vars = array(
+ 'flower' => 'sakura'
+ );
+
+ $this->assertEquals(array('flower' => 'sakura', 'id' => 5, 'bar' => 'foo'), RouteHelper::getVariables($array, $vars));
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/RouterTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/RouterTest.php
new file mode 100644
index 00000000..eb910e77
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/RouterTest.php
@@ -0,0 +1,270 @@
+instance = new Router;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test addMap().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Router::addMap
+ */
+ public function testAddMap()
+ {
+ $this->instance->addMap('flower/(id)/(alias)', array('_controller' => 'FlowerController'));
+
+ $routes = $this->instance->getRoutes();
+
+ $this->assertInstanceOf('Windwalker\Router\Route', $routes[0]);
+ $this->assertEquals('/flower/(id)/(alias)', $routes[0]->getPattern());
+ }
+
+ /**
+ * Method to test addMaps().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Router::addMaps
+ */
+ public function testAddMaps()
+ {
+ $routes = array(
+ 'flower/(id)/(alias)' => array('_controller' => 'FlowerController'),
+ 'flower/(id)/sakura' => array('_controller' => 'SakuraController'),
+ );
+
+ $this->instance->addMaps($routes);
+
+ $routes = $this->instance->getRoutes();
+
+ $this->assertInstanceOf('Windwalker\Router\Route', $routes[0]);
+ $this->assertInstanceOf('Windwalker\Router\Route', $routes[1]);
+ }
+
+ /**
+ * Method to test addRoute().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Router::addRoute
+ */
+ public function testAddRoute()
+ {
+ $this->instance->addRoute(new Route(null, 'flower/(id)/(alias)', array('_controller' => 'FlowerController')));
+
+ $routes = $this->instance->getRoutes();
+
+ $this->assertInstanceOf('Windwalker\Router\Route', $routes[0]);
+
+ $result = $this->instance->match('flower/5/foo');
+
+ $this->assertInstanceOf('Windwalker\Router\Route', $result);
+
+ $result = $result->getVariables();
+
+ $this->assertEquals('FlowerController', $result['_controller']);
+ $this->assertEquals('foo', $result['alias']);
+
+ $this->instance->addRoute(new Route('sakura', 'flower/(id)/sakura', array('_controller' => 'SakuraController')));
+
+ $routes = $this->instance->getRoutes();
+
+ $this->assertInstanceOf('Windwalker\Router\Route', $routes['sakura']);
+
+ $this->instance->addRoute('foo', 'foo/bar/baz', array('_ctrl' => 'yoo'));
+
+ $routes = $this->instance->getRoutes();
+
+ $this->assertInstanceOf('Windwalker\Router\Route', $routes['foo']);
+ }
+
+ /**
+ * Method to test addRoutes().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Router::addRoutes
+ */
+ public function testAddRoutes()
+ {
+ $routes = array(
+ new Route(null, 'flower/(id)/(alias)', array('_controller' => 'FlowerController')),
+ new Route('sakura', 'flower/(id)/sakura', array('_controller' => 'SakuraController')),
+ );
+
+ $this->instance->addRoutes($routes);
+
+ $routes = $this->instance->getRoutes();
+
+ $this->assertInstanceOf('Windwalker\Router\Route', $routes[0]);
+ $this->assertInstanceOf('Windwalker\Router\Route', $routes['sakura']);
+ }
+
+ /**
+ * testHasAndGetRoute
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Router::hasRoutes
+ * @covers Windwalker\Router\Router::getRoutes
+ */
+ public function testHasAndGetRoute()
+ {
+ $this->instance->addRoute($route = new Route('foo', '/foo'));
+
+ $this->assertFalse($this->instance->hasRoute('bar'));
+ $this->assertTrue($this->instance->hasRoute('foo'));
+
+ $this->assertNull($this->instance->getRoute('bar'));
+ $this->assertSame($route, $this->instance->getRoute('foo'));
+ }
+
+ /**
+ * Method to test match().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Router::match
+ */
+ public function testMatch()
+ {
+ $routes = array(
+ new Route(null, 'flower/(id)/(alias)', array('_controller' => 'FlowerController')),
+ new Route('sakura', 'foo/bar(/id,sakura)', array('_controller' => 'SakuraController')),
+ );
+
+ $this->instance->addRoutes($routes);
+
+ $result = $this->instance->match('flower/5/foo');
+
+ $this->assertInstanceOf('Windwalker\Router\Route', $result);
+
+ $result = $result->getVariables();
+
+ $this->assertEquals('FlowerController', $result['_controller']);
+ $this->assertEquals('foo', $result['alias']);
+
+ $result = $this->instance->match('foo/bar/5/baz');
+
+ $this->assertInstanceOf('Windwalker\Router\Route', $result);
+
+ $result = $result->getVariables();
+
+ $this->assertEquals('SakuraController', $result['_controller']);
+ $this->assertEquals('baz', $result['sakura']);
+ }
+
+ /**
+ * Method to test build().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Router::build
+ */
+ public function testBuild()
+ {
+ $routes = array(
+ new Route('flower', 'flower/(id)/(alias)', array('_controller' => 'FlowerController')),
+ new Route('sakura', 'foo/bar(/id,sakura)', array('_controller' => 'SakuraController')),
+ );
+
+ $this->instance->addRoutes($routes);
+
+ $this->assertEquals('flower/25/sakura', $this->instance->build('flower', array('id' => 25, 'alias' => 'sakura')));
+ $this->assertEquals('/flower/25/sakura', $this->instance->build('flower', array('id' => 25, 'alias' => 'sakura'), true));
+ }
+
+ /**
+ * Method to test getMethod().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Router::getMethod
+ */
+ public function testGetMethod()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setMethod().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Router::setMethod
+ * @TODO Implement testSetMethod().
+ */
+ public function testSetMethod()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getMatcher().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\Router::getMatcher
+ */
+ public function testGetAndSetMatcher()
+ {
+ $this->assertInstanceOf('Windwalker\Router\Matcher\MatcherInterface', $this->instance->getMatcher());
+
+ $matcher = new TrieMatcher;
+
+ $this->instance->setMatcher($matcher);
+
+ $this->assertSame($matcher, $this->instance->getMatcher());
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/SingleActionRouterTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/SingleActionRouterTest.php
new file mode 100644
index 00000000..a9cd970e
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/SingleActionRouterTest.php
@@ -0,0 +1,125 @@
+instance = new SingleActionRouter;
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ *
+ * @return void
+ */
+ protected function tearDown()
+ {
+ }
+
+ /**
+ * Method to test addMap().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\SingleActionRouter::addMap
+ */
+ public function testAddMap()
+ {
+ $this->instance->addMap('flower/(id)/(alias)', 'FlowerController');
+
+ $routes = $this->instance->getRoutes();
+
+ $this->assertInstanceOf('Windwalker\Router\Route', $routes[0]);
+ $this->assertEquals('/flower/(id)/(alias)', $routes[0]->getPattern());
+ }
+
+ /**
+ * Method to test match().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\SingleActionRouter::match
+ */
+ public function testMatch()
+ {
+ $routes = array(
+ 'flower/(id)/(alias)' => 'FlowerController',
+ 'foo/bar(/id,sakura)' => 'SakuraController'
+ );
+
+ $this->instance->addMaps($routes);
+
+ $result = $this->instance->match('flower/5/foo');
+ $vars = $this->instance->getVariables();
+
+ $this->assertEquals('FlowerController', $result);
+ $this->assertEquals('foo', $vars['alias']);
+
+ $result = $this->instance->match('foo/bar/5/baz');
+ $vars = $this->instance->getVariables();
+
+ $this->assertEquals('SakuraController', $result);
+ $this->assertEquals('baz', $vars['sakura']);
+ }
+
+ /**
+ * Method to test getRequests().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\SingleActionRouter::getVariables
+ * @TODO Implement testGetVariables().
+ */
+ public function testGetVariables()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setRequests().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Router\SingleActionRouter::setVariables
+ * @TODO Implement testSetVariables().
+ */
+ public function testSetVariables()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/benchmark.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/benchmark.php
new file mode 100644
index 00000000..8478c558
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/benchmark.php
@@ -0,0 +1,126 @@
+ $route));
+ },
+ $routes
+);
+
+$count = count($routes);
+
+$seq = new \Windwalker\Router\Matcher\SequentialMatcher;
+
+$seq->setRoutes($routeItems)->setDebug(false);
+
+$trie = new \Windwalker\Router\Matcher\TrieMatcher;
+
+$trie->setRoutes($routeItems)->setDebug(false);
+
+$bin = new \Windwalker\Router\Matcher\BinaryMatcher;
+
+$bin->setRoutes($routeItems)->setDebug(false);
+
+$bench = new \Windwalker\Profiler\Benchmark;
+
+$avg = array();
+
+$bench->addTask(
+ 'Sequential',
+ function() use ($seq, $routes, $count, &$avg)
+ {
+ static $i = 0;
+
+ if ($i + 1 > $count)
+ {
+ $i = 0;
+ }
+
+ $r = $seq->match($routes[$i]);
+
+ if ($r->getName() == trim($routes[$i], '/'))
+ {
+ echo '.';
+ $avg['seq'] += $seq->getCount();
+ }
+
+ $i++;
+ }
+);
+
+$bench->addTask(
+ 'Binary',
+ function() use ($bin, $routes, $count, &$avg)
+ {
+ static $i = 0;
+
+ if ($i + 1 > $count)
+ {
+ $i = 0;
+ }
+
+ $r = $bin->match($routes[$i]);
+
+ if ($r->getName() == trim($routes[$i], '/'))
+ {
+ echo '.';
+ $avg['bin'] += $bin->getCount();
+ }
+
+ $i++;
+ }
+);
+
+$bench->addTask(
+ 'Trie',
+ function() use ($trie, $routes, $count, &$avg)
+ {
+ static $i = 0;
+
+ $trie->setTree(unserialize(file_get_contents(__DIR__ . '/fixtures/cache.trie')));
+
+ if ($i + 1 > $count)
+ {
+ $i = 0;
+ }
+
+ $r = $trie->match($routes[$i]);
+
+ if ($r->getName() == trim($routes[$i], '/'))
+ {
+ echo '.';
+ $avg['trie'] += $trie->getCount();
+ }
+
+ $i++;
+ }
+);
+
+$bench->execute(1000);
+echo "\n";
+
+echo $avg['seq'] / 1000 . "\n";
+echo $avg['bin'] / 1000 . "\n";
+echo $avg['trie'] / 1000 . "\n";
+
+echo $bench->render();
+echo "\n";
+
+// file_put_contents(__DIR__ . '/cache.trie', serialize($trie->getTree()));
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/fixtures/cache.trie b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/fixtures/cache.trie
new file mode 100644
index 00000000..a72ae0fe
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/fixtures/cache.trie
@@ -0,0 +1 @@
+a:8:{s:3:"foo";a:7:{s:3:"bar";a:6:{s:3:"baz";s:11:"foo/bar/baz";s:3:"qux";s:11:"foo/bar/qux";s:4:"quux";s:12:"foo/bar/quux";s:5:"corge";s:13:"foo/bar/corge";s:6:"grault";s:14:"foo/bar/grault";s:6:"garply";s:14:"foo/bar/garply";}s:3:"baz";a:6:{s:3:"bar";s:11:"foo/baz/bar";s:3:"qux";s:11:"foo/baz/qux";s:4:"quux";s:12:"foo/baz/quux";s:5:"corge";s:13:"foo/baz/corge";s:6:"grault";s:14:"foo/baz/grault";s:6:"garply";s:14:"foo/baz/garply";}s:3:"qux";a:6:{s:3:"bar";s:11:"foo/qux/bar";s:3:"baz";s:11:"foo/qux/baz";s:4:"quux";s:12:"foo/qux/quux";s:5:"corge";s:13:"foo/qux/corge";s:6:"grault";s:14:"foo/qux/grault";s:6:"garply";s:14:"foo/qux/garply";}s:4:"quux";a:6:{s:3:"bar";s:12:"foo/quux/bar";s:3:"baz";s:12:"foo/quux/baz";s:3:"qux";s:12:"foo/quux/qux";s:5:"corge";s:14:"foo/quux/corge";s:6:"grault";s:15:"foo/quux/grault";s:6:"garply";s:15:"foo/quux/garply";}s:5:"corge";a:6:{s:3:"bar";s:13:"foo/corge/bar";s:3:"baz";s:13:"foo/corge/baz";s:3:"qux";s:13:"foo/corge/qux";s:4:"quux";s:14:"foo/corge/quux";s:6:"grault";s:16:"foo/corge/grault";s:6:"garply";s:16:"foo/corge/garply";}s:6:"grault";a:6:{s:3:"bar";s:14:"foo/grault/bar";s:3:"baz";s:14:"foo/grault/baz";s:3:"qux";s:14:"foo/grault/qux";s:4:"quux";s:15:"foo/grault/quux";s:5:"corge";s:16:"foo/grault/corge";s:6:"garply";s:17:"foo/grault/garply";}s:6:"garply";a:6:{s:3:"bar";s:14:"foo/garply/bar";s:3:"baz";s:14:"foo/garply/baz";s:3:"qux";s:14:"foo/garply/qux";s:4:"quux";s:15:"foo/garply/quux";s:5:"corge";s:16:"foo/garply/corge";s:6:"grault";s:17:"foo/garply/grault";}}s:3:"bar";a:7:{s:3:"foo";a:6:{s:3:"baz";s:11:"bar/foo/baz";s:3:"qux";s:11:"bar/foo/qux";s:4:"quux";s:12:"bar/foo/quux";s:5:"corge";s:13:"bar/foo/corge";s:6:"grault";s:14:"bar/foo/grault";s:6:"garply";s:14:"bar/foo/garply";}s:3:"baz";a:6:{s:3:"foo";s:11:"bar/baz/foo";s:3:"qux";s:11:"bar/baz/qux";s:4:"quux";s:12:"bar/baz/quux";s:5:"corge";s:13:"bar/baz/corge";s:6:"grault";s:14:"bar/baz/grault";s:6:"garply";s:14:"bar/baz/garply";}s:3:"qux";a:6:{s:3:"foo";s:11:"bar/qux/foo";s:3:"baz";s:11:"bar/qux/baz";s:4:"quux";s:12:"bar/qux/quux";s:5:"corge";s:13:"bar/qux/corge";s:6:"grault";s:14:"bar/qux/grault";s:6:"garply";s:14:"bar/qux/garply";}s:4:"quux";a:6:{s:3:"foo";s:12:"bar/quux/foo";s:3:"baz";s:12:"bar/quux/baz";s:3:"qux";s:12:"bar/quux/qux";s:5:"corge";s:14:"bar/quux/corge";s:6:"grault";s:15:"bar/quux/grault";s:6:"garply";s:15:"bar/quux/garply";}s:5:"corge";a:6:{s:3:"foo";s:13:"bar/corge/foo";s:3:"baz";s:13:"bar/corge/baz";s:3:"qux";s:13:"bar/corge/qux";s:4:"quux";s:14:"bar/corge/quux";s:6:"grault";s:16:"bar/corge/grault";s:6:"garply";s:16:"bar/corge/garply";}s:6:"grault";a:6:{s:3:"foo";s:14:"bar/grault/foo";s:3:"baz";s:14:"bar/grault/baz";s:3:"qux";s:14:"bar/grault/qux";s:4:"quux";s:15:"bar/grault/quux";s:5:"corge";s:16:"bar/grault/corge";s:6:"garply";s:17:"bar/grault/garply";}s:6:"garply";a:6:{s:3:"foo";s:14:"bar/garply/foo";s:3:"baz";s:14:"bar/garply/baz";s:3:"qux";s:14:"bar/garply/qux";s:4:"quux";s:15:"bar/garply/quux";s:5:"corge";s:16:"bar/garply/corge";s:6:"grault";s:17:"bar/garply/grault";}}s:3:"baz";a:7:{s:3:"foo";a:6:{s:3:"bar";s:11:"baz/foo/bar";s:3:"qux";s:11:"baz/foo/qux";s:4:"quux";s:12:"baz/foo/quux";s:5:"corge";s:13:"baz/foo/corge";s:6:"grault";s:14:"baz/foo/grault";s:6:"garply";s:14:"baz/foo/garply";}s:3:"bar";a:6:{s:3:"foo";s:11:"baz/bar/foo";s:3:"qux";s:11:"baz/bar/qux";s:4:"quux";s:12:"baz/bar/quux";s:5:"corge";s:13:"baz/bar/corge";s:6:"grault";s:14:"baz/bar/grault";s:6:"garply";s:14:"baz/bar/garply";}s:3:"qux";a:6:{s:3:"foo";s:11:"baz/qux/foo";s:3:"bar";s:11:"baz/qux/bar";s:4:"quux";s:12:"baz/qux/quux";s:5:"corge";s:13:"baz/qux/corge";s:6:"grault";s:14:"baz/qux/grault";s:6:"garply";s:14:"baz/qux/garply";}s:4:"quux";a:6:{s:3:"foo";s:12:"baz/quux/foo";s:3:"bar";s:12:"baz/quux/bar";s:3:"qux";s:12:"baz/quux/qux";s:5:"corge";s:14:"baz/quux/corge";s:6:"grault";s:15:"baz/quux/grault";s:6:"garply";s:15:"baz/quux/garply";}s:5:"corge";a:6:{s:3:"foo";s:13:"baz/corge/foo";s:3:"bar";s:13:"baz/corge/bar";s:3:"qux";s:13:"baz/corge/qux";s:4:"quux";s:14:"baz/corge/quux";s:6:"grault";s:16:"baz/corge/grault";s:6:"garply";s:16:"baz/corge/garply";}s:6:"grault";a:6:{s:3:"foo";s:14:"baz/grault/foo";s:3:"bar";s:14:"baz/grault/bar";s:3:"qux";s:14:"baz/grault/qux";s:4:"quux";s:15:"baz/grault/quux";s:5:"corge";s:16:"baz/grault/corge";s:6:"garply";s:17:"baz/grault/garply";}s:6:"garply";a:6:{s:3:"foo";s:14:"baz/garply/foo";s:3:"bar";s:14:"baz/garply/bar";s:3:"qux";s:14:"baz/garply/qux";s:4:"quux";s:15:"baz/garply/quux";s:5:"corge";s:16:"baz/garply/corge";s:6:"grault";s:17:"baz/garply/grault";}}s:3:"qux";a:7:{s:3:"foo";a:6:{s:3:"bar";s:11:"qux/foo/bar";s:3:"baz";s:11:"qux/foo/baz";s:4:"quux";s:12:"qux/foo/quux";s:5:"corge";s:13:"qux/foo/corge";s:6:"grault";s:14:"qux/foo/grault";s:6:"garply";s:14:"qux/foo/garply";}s:3:"bar";a:6:{s:3:"foo";s:11:"qux/bar/foo";s:3:"baz";s:11:"qux/bar/baz";s:4:"quux";s:12:"qux/bar/quux";s:5:"corge";s:13:"qux/bar/corge";s:6:"grault";s:14:"qux/bar/grault";s:6:"garply";s:14:"qux/bar/garply";}s:3:"baz";a:6:{s:3:"foo";s:11:"qux/baz/foo";s:3:"bar";s:11:"qux/baz/bar";s:4:"quux";s:12:"qux/baz/quux";s:5:"corge";s:13:"qux/baz/corge";s:6:"grault";s:14:"qux/baz/grault";s:6:"garply";s:14:"qux/baz/garply";}s:4:"quux";a:6:{s:3:"foo";s:12:"qux/quux/foo";s:3:"bar";s:12:"qux/quux/bar";s:3:"baz";s:12:"qux/quux/baz";s:5:"corge";s:14:"qux/quux/corge";s:6:"grault";s:15:"qux/quux/grault";s:6:"garply";s:15:"qux/quux/garply";}s:5:"corge";a:6:{s:3:"foo";s:13:"qux/corge/foo";s:3:"bar";s:13:"qux/corge/bar";s:3:"baz";s:13:"qux/corge/baz";s:4:"quux";s:14:"qux/corge/quux";s:6:"grault";s:16:"qux/corge/grault";s:6:"garply";s:16:"qux/corge/garply";}s:6:"grault";a:6:{s:3:"foo";s:14:"qux/grault/foo";s:3:"bar";s:14:"qux/grault/bar";s:3:"baz";s:14:"qux/grault/baz";s:4:"quux";s:15:"qux/grault/quux";s:5:"corge";s:16:"qux/grault/corge";s:6:"garply";s:17:"qux/grault/garply";}s:6:"garply";a:6:{s:3:"foo";s:14:"qux/garply/foo";s:3:"bar";s:14:"qux/garply/bar";s:3:"baz";s:14:"qux/garply/baz";s:4:"quux";s:15:"qux/garply/quux";s:5:"corge";s:16:"qux/garply/corge";s:6:"grault";s:17:"qux/garply/grault";}}s:4:"quux";a:7:{s:3:"foo";a:6:{s:3:"bar";s:12:"quux/foo/bar";s:3:"baz";s:12:"quux/foo/baz";s:3:"qux";s:12:"quux/foo/qux";s:5:"corge";s:14:"quux/foo/corge";s:6:"grault";s:15:"quux/foo/grault";s:6:"garply";s:15:"quux/foo/garply";}s:3:"bar";a:6:{s:3:"foo";s:12:"quux/bar/foo";s:3:"baz";s:12:"quux/bar/baz";s:3:"qux";s:12:"quux/bar/qux";s:5:"corge";s:14:"quux/bar/corge";s:6:"grault";s:15:"quux/bar/grault";s:6:"garply";s:15:"quux/bar/garply";}s:3:"baz";a:6:{s:3:"foo";s:12:"quux/baz/foo";s:3:"bar";s:12:"quux/baz/bar";s:3:"qux";s:12:"quux/baz/qux";s:5:"corge";s:14:"quux/baz/corge";s:6:"grault";s:15:"quux/baz/grault";s:6:"garply";s:15:"quux/baz/garply";}s:3:"qux";a:6:{s:3:"foo";s:12:"quux/qux/foo";s:3:"bar";s:12:"quux/qux/bar";s:3:"baz";s:12:"quux/qux/baz";s:5:"corge";s:14:"quux/qux/corge";s:6:"grault";s:15:"quux/qux/grault";s:6:"garply";s:15:"quux/qux/garply";}s:5:"corge";a:6:{s:3:"foo";s:14:"quux/corge/foo";s:3:"bar";s:14:"quux/corge/bar";s:3:"baz";s:14:"quux/corge/baz";s:3:"qux";s:14:"quux/corge/qux";s:6:"grault";s:17:"quux/corge/grault";s:6:"garply";s:17:"quux/corge/garply";}s:6:"grault";a:6:{s:3:"foo";s:15:"quux/grault/foo";s:3:"bar";s:15:"quux/grault/bar";s:3:"baz";s:15:"quux/grault/baz";s:3:"qux";s:15:"quux/grault/qux";s:5:"corge";s:17:"quux/grault/corge";s:6:"garply";s:18:"quux/grault/garply";}s:6:"garply";a:6:{s:3:"foo";s:15:"quux/garply/foo";s:3:"bar";s:15:"quux/garply/bar";s:3:"baz";s:15:"quux/garply/baz";s:3:"qux";s:15:"quux/garply/qux";s:5:"corge";s:17:"quux/garply/corge";s:6:"grault";s:18:"quux/garply/grault";}}s:5:"corge";a:7:{s:3:"foo";a:6:{s:3:"bar";s:13:"corge/foo/bar";s:3:"baz";s:13:"corge/foo/baz";s:3:"qux";s:13:"corge/foo/qux";s:4:"quux";s:14:"corge/foo/quux";s:6:"grault";s:16:"corge/foo/grault";s:6:"garply";s:16:"corge/foo/garply";}s:3:"bar";a:6:{s:3:"foo";s:13:"corge/bar/foo";s:3:"baz";s:13:"corge/bar/baz";s:3:"qux";s:13:"corge/bar/qux";s:4:"quux";s:14:"corge/bar/quux";s:6:"grault";s:16:"corge/bar/grault";s:6:"garply";s:16:"corge/bar/garply";}s:3:"baz";a:6:{s:3:"foo";s:13:"corge/baz/foo";s:3:"bar";s:13:"corge/baz/bar";s:3:"qux";s:13:"corge/baz/qux";s:4:"quux";s:14:"corge/baz/quux";s:6:"grault";s:16:"corge/baz/grault";s:6:"garply";s:16:"corge/baz/garply";}s:3:"qux";a:6:{s:3:"foo";s:13:"corge/qux/foo";s:3:"bar";s:13:"corge/qux/bar";s:3:"baz";s:13:"corge/qux/baz";s:4:"quux";s:14:"corge/qux/quux";s:6:"grault";s:16:"corge/qux/grault";s:6:"garply";s:16:"corge/qux/garply";}s:4:"quux";a:6:{s:3:"foo";s:14:"corge/quux/foo";s:3:"bar";s:14:"corge/quux/bar";s:3:"baz";s:14:"corge/quux/baz";s:3:"qux";s:14:"corge/quux/qux";s:6:"grault";s:17:"corge/quux/grault";s:6:"garply";s:17:"corge/quux/garply";}s:6:"grault";a:6:{s:3:"foo";s:16:"corge/grault/foo";s:3:"bar";s:16:"corge/grault/bar";s:3:"baz";s:16:"corge/grault/baz";s:3:"qux";s:16:"corge/grault/qux";s:4:"quux";s:17:"corge/grault/quux";s:6:"garply";s:19:"corge/grault/garply";}s:6:"garply";a:6:{s:3:"foo";s:16:"corge/garply/foo";s:3:"bar";s:16:"corge/garply/bar";s:3:"baz";s:16:"corge/garply/baz";s:3:"qux";s:16:"corge/garply/qux";s:4:"quux";s:17:"corge/garply/quux";s:6:"grault";s:19:"corge/garply/grault";}}s:6:"grault";a:7:{s:3:"foo";a:6:{s:3:"bar";s:14:"grault/foo/bar";s:3:"baz";s:14:"grault/foo/baz";s:3:"qux";s:14:"grault/foo/qux";s:4:"quux";s:15:"grault/foo/quux";s:5:"corge";s:16:"grault/foo/corge";s:6:"garply";s:17:"grault/foo/garply";}s:3:"bar";a:6:{s:3:"foo";s:14:"grault/bar/foo";s:3:"baz";s:14:"grault/bar/baz";s:3:"qux";s:14:"grault/bar/qux";s:4:"quux";s:15:"grault/bar/quux";s:5:"corge";s:16:"grault/bar/corge";s:6:"garply";s:17:"grault/bar/garply";}s:3:"baz";a:6:{s:3:"foo";s:14:"grault/baz/foo";s:3:"bar";s:14:"grault/baz/bar";s:3:"qux";s:14:"grault/baz/qux";s:4:"quux";s:15:"grault/baz/quux";s:5:"corge";s:16:"grault/baz/corge";s:6:"garply";s:17:"grault/baz/garply";}s:3:"qux";a:6:{s:3:"foo";s:14:"grault/qux/foo";s:3:"bar";s:14:"grault/qux/bar";s:3:"baz";s:14:"grault/qux/baz";s:4:"quux";s:15:"grault/qux/quux";s:5:"corge";s:16:"grault/qux/corge";s:6:"garply";s:17:"grault/qux/garply";}s:4:"quux";a:6:{s:3:"foo";s:15:"grault/quux/foo";s:3:"bar";s:15:"grault/quux/bar";s:3:"baz";s:15:"grault/quux/baz";s:3:"qux";s:15:"grault/quux/qux";s:5:"corge";s:17:"grault/quux/corge";s:6:"garply";s:18:"grault/quux/garply";}s:5:"corge";a:6:{s:3:"foo";s:16:"grault/corge/foo";s:3:"bar";s:16:"grault/corge/bar";s:3:"baz";s:16:"grault/corge/baz";s:3:"qux";s:16:"grault/corge/qux";s:4:"quux";s:17:"grault/corge/quux";s:6:"garply";s:19:"grault/corge/garply";}s:6:"garply";a:6:{s:3:"foo";s:17:"grault/garply/foo";s:3:"bar";s:17:"grault/garply/bar";s:3:"baz";s:17:"grault/garply/baz";s:3:"qux";s:17:"grault/garply/qux";s:4:"quux";s:18:"grault/garply/quux";s:5:"corge";s:19:"grault/garply/corge";}}s:6:"garply";a:7:{s:3:"foo";a:6:{s:3:"bar";s:14:"garply/foo/bar";s:3:"baz";s:14:"garply/foo/baz";s:3:"qux";s:14:"garply/foo/qux";s:4:"quux";s:15:"garply/foo/quux";s:5:"corge";s:16:"garply/foo/corge";s:6:"grault";s:17:"garply/foo/grault";}s:3:"bar";a:6:{s:3:"foo";s:14:"garply/bar/foo";s:3:"baz";s:14:"garply/bar/baz";s:3:"qux";s:14:"garply/bar/qux";s:4:"quux";s:15:"garply/bar/quux";s:5:"corge";s:16:"garply/bar/corge";s:6:"grault";s:17:"garply/bar/grault";}s:3:"baz";a:6:{s:3:"foo";s:14:"garply/baz/foo";s:3:"bar";s:14:"garply/baz/bar";s:3:"qux";s:14:"garply/baz/qux";s:4:"quux";s:15:"garply/baz/quux";s:5:"corge";s:16:"garply/baz/corge";s:6:"grault";s:17:"garply/baz/grault";}s:3:"qux";a:6:{s:3:"foo";s:14:"garply/qux/foo";s:3:"bar";s:14:"garply/qux/bar";s:3:"baz";s:14:"garply/qux/baz";s:4:"quux";s:15:"garply/qux/quux";s:5:"corge";s:16:"garply/qux/corge";s:6:"grault";s:17:"garply/qux/grault";}s:4:"quux";a:6:{s:3:"foo";s:15:"garply/quux/foo";s:3:"bar";s:15:"garply/quux/bar";s:3:"baz";s:15:"garply/quux/baz";s:3:"qux";s:15:"garply/quux/qux";s:5:"corge";s:17:"garply/quux/corge";s:6:"grault";s:18:"garply/quux/grault";}s:5:"corge";a:6:{s:3:"foo";s:16:"garply/corge/foo";s:3:"bar";s:16:"garply/corge/bar";s:3:"baz";s:16:"garply/corge/baz";s:3:"qux";s:16:"garply/corge/qux";s:4:"quux";s:17:"garply/corge/quux";s:6:"grault";s:19:"garply/corge/grault";}s:6:"grault";a:6:{s:3:"foo";s:17:"garply/grault/foo";s:3:"bar";s:17:"garply/grault/bar";s:3:"baz";s:17:"garply/grault/baz";s:3:"qux";s:17:"garply/grault/qux";s:4:"quux";s:18:"garply/grault/quux";s:5:"corge";s:19:"garply/grault/corge";}}}
\ No newline at end of file
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/fixtures/routes.txt b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/fixtures/routes.txt
new file mode 100644
index 00000000..ff960253
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/fixtures/routes.txt
@@ -0,0 +1,336 @@
+/foo/bar/baz
+/foo/bar/qux
+/foo/bar/quux
+/foo/bar/corge
+/foo/bar/grault
+/foo/bar/garply
+/foo/baz/bar
+/foo/baz/qux
+/foo/baz/quux
+/foo/baz/corge
+/foo/baz/grault
+/foo/baz/garply
+/foo/qux/bar
+/foo/qux/baz
+/foo/qux/quux
+/foo/qux/corge
+/foo/qux/grault
+/foo/qux/garply
+/foo/quux/bar
+/foo/quux/baz
+/foo/quux/qux
+/foo/quux/corge
+/foo/quux/grault
+/foo/quux/garply
+/foo/corge/bar
+/foo/corge/baz
+/foo/corge/qux
+/foo/corge/quux
+/foo/corge/grault
+/foo/corge/garply
+/foo/grault/bar
+/foo/grault/baz
+/foo/grault/qux
+/foo/grault/quux
+/foo/grault/corge
+/foo/grault/garply
+/foo/garply/bar
+/foo/garply/baz
+/foo/garply/qux
+/foo/garply/quux
+/foo/garply/corge
+/foo/garply/grault
+/bar/foo/baz
+/bar/foo/qux
+/bar/foo/quux
+/bar/foo/corge
+/bar/foo/grault
+/bar/foo/garply
+/bar/baz/foo
+/bar/baz/qux
+/bar/baz/quux
+/bar/baz/corge
+/bar/baz/grault
+/bar/baz/garply
+/bar/qux/foo
+/bar/qux/baz
+/bar/qux/quux
+/bar/qux/corge
+/bar/qux/grault
+/bar/qux/garply
+/bar/quux/foo
+/bar/quux/baz
+/bar/quux/qux
+/bar/quux/corge
+/bar/quux/grault
+/bar/quux/garply
+/bar/corge/foo
+/bar/corge/baz
+/bar/corge/qux
+/bar/corge/quux
+/bar/corge/grault
+/bar/corge/garply
+/bar/grault/foo
+/bar/grault/baz
+/bar/grault/qux
+/bar/grault/quux
+/bar/grault/corge
+/bar/grault/garply
+/bar/garply/foo
+/bar/garply/baz
+/bar/garply/qux
+/bar/garply/quux
+/bar/garply/corge
+/bar/garply/grault
+/baz/foo/bar
+/baz/foo/qux
+/baz/foo/quux
+/baz/foo/corge
+/baz/foo/grault
+/baz/foo/garply
+/baz/bar/foo
+/baz/bar/qux
+/baz/bar/quux
+/baz/bar/corge
+/baz/bar/grault
+/baz/bar/garply
+/baz/qux/foo
+/baz/qux/bar
+/baz/qux/quux
+/baz/qux/corge
+/baz/qux/grault
+/baz/qux/garply
+/baz/quux/foo
+/baz/quux/bar
+/baz/quux/qux
+/baz/quux/corge
+/baz/quux/grault
+/baz/quux/garply
+/baz/corge/foo
+/baz/corge/bar
+/baz/corge/qux
+/baz/corge/quux
+/baz/corge/grault
+/baz/corge/garply
+/baz/grault/foo
+/baz/grault/bar
+/baz/grault/qux
+/baz/grault/quux
+/baz/grault/corge
+/baz/grault/garply
+/baz/garply/foo
+/baz/garply/bar
+/baz/garply/qux
+/baz/garply/quux
+/baz/garply/corge
+/baz/garply/grault
+/qux/foo/bar
+/qux/foo/baz
+/qux/foo/quux
+/qux/foo/corge
+/qux/foo/grault
+/qux/foo/garply
+/qux/bar/foo
+/qux/bar/baz
+/qux/bar/quux
+/qux/bar/corge
+/qux/bar/grault
+/qux/bar/garply
+/qux/baz/foo
+/qux/baz/bar
+/qux/baz/quux
+/qux/baz/corge
+/qux/baz/grault
+/qux/baz/garply
+/qux/quux/foo
+/qux/quux/bar
+/qux/quux/baz
+/qux/quux/corge
+/qux/quux/grault
+/qux/quux/garply
+/qux/corge/foo
+/qux/corge/bar
+/qux/corge/baz
+/qux/corge/quux
+/qux/corge/grault
+/qux/corge/garply
+/qux/grault/foo
+/qux/grault/bar
+/qux/grault/baz
+/qux/grault/quux
+/qux/grault/corge
+/qux/grault/garply
+/qux/garply/foo
+/qux/garply/bar
+/qux/garply/baz
+/qux/garply/quux
+/qux/garply/corge
+/qux/garply/grault
+/quux/foo/bar
+/quux/foo/baz
+/quux/foo/qux
+/quux/foo/corge
+/quux/foo/grault
+/quux/foo/garply
+/quux/bar/foo
+/quux/bar/baz
+/quux/bar/qux
+/quux/bar/corge
+/quux/bar/grault
+/quux/bar/garply
+/quux/baz/foo
+/quux/baz/bar
+/quux/baz/qux
+/quux/baz/corge
+/quux/baz/grault
+/quux/baz/garply
+/quux/qux/foo
+/quux/qux/bar
+/quux/qux/baz
+/quux/qux/corge
+/quux/qux/grault
+/quux/qux/garply
+/quux/corge/foo
+/quux/corge/bar
+/quux/corge/baz
+/quux/corge/qux
+/quux/corge/grault
+/quux/corge/garply
+/quux/grault/foo
+/quux/grault/bar
+/quux/grault/baz
+/quux/grault/qux
+/quux/grault/corge
+/quux/grault/garply
+/quux/garply/foo
+/quux/garply/bar
+/quux/garply/baz
+/quux/garply/qux
+/quux/garply/corge
+/quux/garply/grault
+/corge/foo/bar
+/corge/foo/baz
+/corge/foo/qux
+/corge/foo/quux
+/corge/foo/grault
+/corge/foo/garply
+/corge/bar/foo
+/corge/bar/baz
+/corge/bar/qux
+/corge/bar/quux
+/corge/bar/grault
+/corge/bar/garply
+/corge/baz/foo
+/corge/baz/bar
+/corge/baz/qux
+/corge/baz/quux
+/corge/baz/grault
+/corge/baz/garply
+/corge/qux/foo
+/corge/qux/bar
+/corge/qux/baz
+/corge/qux/quux
+/corge/qux/grault
+/corge/qux/garply
+/corge/quux/foo
+/corge/quux/bar
+/corge/quux/baz
+/corge/quux/qux
+/corge/quux/grault
+/corge/quux/garply
+/corge/grault/foo
+/corge/grault/bar
+/corge/grault/baz
+/corge/grault/qux
+/corge/grault/quux
+/corge/grault/garply
+/corge/garply/foo
+/corge/garply/bar
+/corge/garply/baz
+/corge/garply/qux
+/corge/garply/quux
+/corge/garply/grault
+/grault/foo/bar
+/grault/foo/baz
+/grault/foo/qux
+/grault/foo/quux
+/grault/foo/corge
+/grault/foo/garply
+/grault/bar/foo
+/grault/bar/baz
+/grault/bar/qux
+/grault/bar/quux
+/grault/bar/corge
+/grault/bar/garply
+/grault/baz/foo
+/grault/baz/bar
+/grault/baz/qux
+/grault/baz/quux
+/grault/baz/corge
+/grault/baz/garply
+/grault/qux/foo
+/grault/qux/bar
+/grault/qux/baz
+/grault/qux/quux
+/grault/qux/corge
+/grault/qux/garply
+/grault/quux/foo
+/grault/quux/bar
+/grault/quux/baz
+/grault/quux/qux
+/grault/quux/corge
+/grault/quux/garply
+/grault/corge/foo
+/grault/corge/bar
+/grault/corge/baz
+/grault/corge/qux
+/grault/corge/quux
+/grault/corge/garply
+/grault/garply/foo
+/grault/garply/bar
+/grault/garply/baz
+/grault/garply/qux
+/grault/garply/quux
+/grault/garply/corge
+/garply/foo/bar
+/garply/foo/baz
+/garply/foo/qux
+/garply/foo/quux
+/garply/foo/corge
+/garply/foo/grault
+/garply/bar/foo
+/garply/bar/baz
+/garply/bar/qux
+/garply/bar/quux
+/garply/bar/corge
+/garply/bar/grault
+/garply/baz/foo
+/garply/baz/bar
+/garply/baz/qux
+/garply/baz/quux
+/garply/baz/corge
+/garply/baz/grault
+/garply/qux/foo
+/garply/qux/bar
+/garply/qux/baz
+/garply/qux/quux
+/garply/qux/corge
+/garply/qux/grault
+/garply/quux/foo
+/garply/quux/bar
+/garply/quux/baz
+/garply/quux/qux
+/garply/quux/corge
+/garply/quux/grault
+/garply/corge/foo
+/garply/corge/bar
+/garply/corge/baz
+/garply/corge/qux
+/garply/corge/quux
+/garply/corge/grault
+/garply/grault/foo
+/garply/grault/bar
+/garply/grault/baz
+/garply/grault/qux
+/garply/grault/quux
+/garply/grault/corge
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/fixtures/trie.txt b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/fixtures/trie.txt
new file mode 100644
index 00000000..60906790
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/Test/fixtures/trie.txt
@@ -0,0 +1,336 @@
+/foo/bar/baz
+/foo/bar/:qux
+/foo/bar/quux
+/foo/bar/*corge
+/foo/bar/grault
+/foo/bar/garply
+/foo/baz/bar
+/foo/baz/:qux
+/foo/baz/quux
+/foo/baz/*corge
+/foo/baz/grault
+/foo/baz/garply
+/foo/:qux/bar
+/foo/:qux/baz
+/foo/:qux/quux
+/foo/:qux/*corge
+/foo/:qux/grault
+/foo/:qux/garply
+/foo/quux/bar
+/foo/quux/baz
+/foo/quux/:qux
+/foo/quux/*corge
+/foo/quux/grault
+/foo/quux/garply
+/foo/*corge/bar
+/foo/*corge/baz
+/foo/*corge/:qux
+/foo/*corge/quux
+/foo/*corge/grault
+/foo/*corge/garply
+/foo/grault/bar
+/foo/grault/baz
+/foo/grault/:qux
+/foo/grault/quux
+/foo/grault/*corge
+/foo/grault/garply
+/foo/garply/bar
+/foo/garply/baz
+/foo/garply/:qux
+/foo/garply/quux
+/foo/garply/*corge
+/foo/garply/grault
+/bar/foo/baz
+/bar/foo/:qux
+/bar/foo/quux
+/bar/foo/*corge
+/bar/foo/grault
+/bar/foo/garply
+/bar/baz/foo
+/bar/baz/:qux
+/bar/baz/quux
+/bar/baz/*corge
+/bar/baz/grault
+/bar/baz/garply
+/bar/:qux/foo
+/bar/:qux/baz
+/bar/:qux/quux
+/bar/:qux/*corge
+/bar/:qux/grault
+/bar/:qux/garply
+/bar/quux/foo
+/bar/quux/baz
+/bar/quux/:qux
+/bar/quux/*corge
+/bar/quux/grault
+/bar/quux/garply
+/bar/*corge/foo
+/bar/*corge/baz
+/bar/*corge/:qux
+/bar/*corge/quux
+/bar/*corge/grault
+/bar/*corge/garply
+/bar/grault/foo
+/bar/grault/baz
+/bar/grault/:qux
+/bar/grault/quux
+/bar/grault/*corge
+/bar/grault/garply
+/bar/garply/foo
+/bar/garply/baz
+/bar/garply/:qux
+/bar/garply/quux
+/bar/garply/*corge
+/bar/garply/grault
+/baz/foo/bar
+/baz/foo/:qux
+/baz/foo/quux
+/baz/foo/*corge
+/baz/foo/grault
+/baz/foo/garply
+/baz/bar/foo
+/baz/bar/:qux
+/baz/bar/quux
+/baz/bar/*corge
+/baz/bar/grault
+/baz/bar/garply
+/baz/:qux/foo
+/baz/:qux/bar
+/baz/:qux/quux
+/baz/:qux/*corge
+/baz/:qux/grault
+/baz/:qux/garply
+/baz/quux/foo
+/baz/quux/bar
+/baz/quux/:qux
+/baz/quux/*corge
+/baz/quux/grault
+/baz/quux/garply
+/baz/*corge/foo
+/baz/*corge/bar
+/baz/*corge/:qux
+/baz/*corge/quux
+/baz/*corge/grault
+/baz/*corge/garply
+/baz/grault/foo
+/baz/grault/bar
+/baz/grault/:qux
+/baz/grault/quux
+/baz/grault/*corge
+/baz/grault/garply
+/baz/garply/foo
+/baz/garply/bar
+/baz/garply/:qux
+/baz/garply/quux
+/baz/garply/*corge
+/baz/garply/grault
+/qux/foo/bar
+/qux/foo/baz
+/qux/foo/quux
+/qux/foo/*corge
+/qux/foo/grault
+/qux/foo/garply
+/qux/bar/foo
+/qux/bar/baz
+/qux/bar/quux
+/qux/bar/*corge
+/qux/bar/grault
+/qux/bar/garply
+/qux/baz/foo
+/qux/baz/bar
+/qux/baz/quux
+/qux/baz/*corge
+/qux/baz/grault
+/qux/baz/garply
+/qux/quux/foo
+/qux/quux/bar
+/qux/quux/baz
+/qux/quux/*corge
+/qux/quux/grault
+/qux/quux/garply
+/qux/*corge/foo
+/qux/*corge/bar
+/qux/*corge/baz
+/qux/*corge/quux
+/qux/*corge/grault
+/qux/*corge/garply
+/qux/grault/foo
+/qux/grault/bar
+/qux/grault/baz
+/qux/grault/quux
+/qux/grault/*corge
+/qux/grault/garply
+/qux/garply/foo
+/qux/garply/bar
+/qux/garply/baz
+/qux/garply/quux
+/qux/garply/*corge
+/qux/garply/grault
+/quux/foo/bar
+/quux/foo/baz
+/quux/foo/:qux
+/quux/foo/*corge
+/quux/foo/grault
+/quux/foo/garply
+/quux/bar/foo
+/quux/bar/baz
+/quux/bar/:qux
+/quux/bar/*corge
+/quux/bar/grault
+/quux/bar/garply
+/quux/baz/foo
+/quux/baz/bar
+/quux/baz/:qux
+/quux/baz/*corge
+/quux/baz/grault
+/quux/baz/garply
+/quux/:qux/foo
+/quux/:qux/bar
+/quux/:qux/baz
+/quux/:qux/*corge
+/quux/:qux/grault
+/quux/:qux/garply
+/quux/*corge/foo
+/quux/*corge/bar
+/quux/*corge/baz
+/quux/*corge/:qux
+/quux/*corge/grault
+/quux/*corge/garply
+/quux/grault/foo
+/quux/grault/bar
+/quux/grault/baz
+/quux/grault/:qux
+/quux/grault/*corge
+/quux/grault/garply
+/quux/garply/foo
+/quux/garply/bar
+/quux/garply/baz
+/quux/garply/:qux
+/quux/garply/*corge
+/quux/garply/grault
+/corge/foo/bar
+/corge/foo/baz
+/corge/foo/:qux
+/corge/foo/quux
+/corge/foo/grault
+/corge/foo/garply
+/corge/bar/foo
+/corge/bar/baz
+/corge/bar/:qux
+/corge/bar/quux
+/corge/bar/grault
+/corge/bar/garply
+/corge/baz/foo
+/corge/baz/bar
+/corge/baz/:qux
+/corge/baz/quux
+/corge/baz/grault
+/corge/baz/garply
+/corge/:qux/foo
+/corge/:qux/bar
+/corge/:qux/baz
+/corge/:qux/quux
+/corge/:qux/grault
+/corge/:qux/garply
+/corge/quux/foo
+/corge/quux/bar
+/corge/quux/baz
+/corge/quux/:qux
+/corge/quux/grault
+/corge/quux/garply
+/corge/grault/foo
+/corge/grault/bar
+/corge/grault/baz
+/corge/grault/:qux
+/corge/grault/quux
+/corge/grault/garply
+/corge/garply/foo
+/corge/garply/bar
+/corge/garply/baz
+/corge/garply/:qux
+/corge/garply/quux
+/corge/garply/grault
+/grault/foo/bar
+/grault/foo/baz
+/grault/foo/:qux
+/grault/foo/quux
+/grault/foo/*corge
+/grault/foo/garply
+/grault/bar/foo
+/grault/bar/baz
+/grault/bar/:qux
+/grault/bar/quux
+/grault/bar/*corge
+/grault/bar/garply
+/grault/baz/foo
+/grault/baz/bar
+/grault/baz/:qux
+/grault/baz/quux
+/grault/baz/*corge
+/grault/baz/garply
+/grault/:qux/foo
+/grault/:qux/bar
+/grault/:qux/baz
+/grault/:qux/quux
+/grault/:qux/*corge
+/grault/:qux/garply
+/grault/quux/foo
+/grault/quux/bar
+/grault/quux/baz
+/grault/quux/:qux
+/grault/quux/*corge
+/grault/quux/garply
+/grault/*corge/foo
+/grault/*corge/bar
+/grault/*corge/baz
+/grault/*corge/:qux
+/grault/*corge/quux
+/grault/*corge/garply
+/grault/garply/foo
+/grault/garply/bar
+/grault/garply/baz
+/grault/garply/:qux
+/grault/garply/quux
+/grault/garply/*corge
+/garply/foo/bar
+/garply/foo/baz
+/garply/foo/:qux
+/garply/foo/quux
+/garply/foo/*corge
+/garply/foo/grault
+/garply/bar/foo
+/garply/bar/baz
+/garply/bar/:qux
+/garply/bar/quux
+/garply/bar/*corge
+/garply/bar/grault
+/garply/baz/foo
+/garply/baz/bar
+/garply/baz/:qux
+/garply/baz/quux
+/garply/baz/*corge
+/garply/baz/grault
+/garply/:qux/foo
+/garply/:qux/bar
+/garply/:qux/baz
+/garply/:qux/quux
+/garply/:qux/*corge
+/garply/:qux/grault
+/garply/quux/foo
+/garply/quux/bar
+/garply/quux/baz
+/garply/quux/:qux
+/garply/quux/*corge
+/garply/quux/grault
+/garply/*corge/foo
+/garply/*corge/bar
+/garply/*corge/baz
+/garply/*corge/:qux
+/garply/*corge/quux
+/garply/*corge/grault
+/garply/grault/foo
+/garply/grault/bar
+/garply/grault/baz
+/garply/grault/:qux
+/garply/grault/quux
+/garply/grault/*corge
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/composer.json b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/composer.json
new file mode 100644
index 00000000..c779cc52
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/composer.json
@@ -0,0 +1,26 @@
+{
+ "name": "windwalker/router",
+ "type": "windwalker-package",
+ "description": "Windwalker Router package",
+ "keywords": ["windwalker", "framework", "router"],
+ "homepage": "https://github.com/ventoviro/windwalker-router",
+ "license": "LGPL-2.0+",
+ "require": {
+ "php": ">=5.3.10"
+ },
+ "require-dev": {
+ "windwalker/test": "~2.0",
+ "windwalker/uri": "~2.0"
+ },
+ "minimum-stability": "beta",
+ "autoload": {
+ "psr-4": {
+ "Windwalker\\Router\\": ""
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ }
+}
\ No newline at end of file
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/phpunit.travis.xml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/phpunit.travis.xml
new file mode 100644
index 00000000..690ec926
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/router/phpunit.travis.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/.gitignore b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/.gitignore
new file mode 100644
index 00000000..84718b5d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/.gitignore
@@ -0,0 +1,11 @@
+# Development system files #
+.*
+!/.gitignore
+!/.travis.yml
+
+# Composer #
+vendor/*
+composer.lock
+
+# Test #
+phpunit.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/.travis.yml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/.travis.yml
new file mode 100644
index 00000000..5420e5c4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/.travis.yml
@@ -0,0 +1,16 @@
+language: php
+
+sudo: false
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+
+before_script:
+ - composer update --dev
+
+script:
+ - phpunit --configuration phpunit.travis.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/README.md b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/README.md
new file mode 100644
index 00000000..f521fd52
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/README.md
@@ -0,0 +1,219 @@
+# Windwalker String
+
+Windwalker String package provides UTF-8 string operation, it is a Joomla String fork but added more functions.
+
+## Installation via Composer
+
+Add this to the require block in your `composer.json`.
+
+``` json
+{
+ "require": {
+ "windwalker/string": "~2.0"
+ }
+}
+```
+
+## Simple Template Engine
+
+Simple variable replace.
+
+``` php
+use Windwalker\String\SimpleTemplate;
+
+$string = 'Hello my name is: {{ name }}~~~!!!';
+
+SimpleTemplate::render($string, array('name' => 'Simon')); // Hello my name is Simon~~~!!!
+```
+
+Multi-level variable.
+
+``` php
+$string = 'Hello my name is: {{ user.name }} and ID is: {{ user.id }}~~~!!!';
+
+$array = array(
+ 'user' => array(
+ 'name' => 'Simon',
+ 'id' => 123
+ )
+);
+
+SimpleTemplate::render($string, $array); // Hello my name is Simon and ID is: 123~~~!!!
+```
+
+Custom Tags:
+
+
+``` php
+$string = 'Hello my name is: {$ name $}~~~!!!';
+
+SimpleTemplate::render($string, array('name' => 'Simon'), array('{$', '$}'); // Hello my name is Simon~~~!!!
+```
+
+## Utf8String
+
+Utf8String is a wrap of `phputf8` library:
+
+``` php
+use Windwalker\String\Utf8String;
+
+$string = '這是一個最美的小情歌';
+
+Utf8String::substr($string, 0, 5); // '這是一個最'
+Utf8String::strlen($string); // 10
+
+// More methods
+Utf8String::is_ascii($string);
+
+Utf8String::strpos($str, $search, $offset = false);
+
+Utf8String::strrpos($str, $search, $offset = 0);
+
+Utf8String::strtolower($string);
+
+Utf8String::strtoupper($string);
+
+Utf8String::str_ireplace($search, $replace, $str, $count = null);
+
+Utf8String::str_split($str, $split_len = 1);
+
+Utf8String::strcasecmp($str1, $str2, $locale = false);
+
+Utf8String::strcmp($str1, $str2, $locale = false);
+
+Utf8String::strcspn($str, $mask, $start = null, $length = null);
+
+Utf8String::stristr($str, $search);
+
+Utf8String::strrev($string);
+
+Utf8String::strspn($str, $mask, $start = null, $length = null);
+
+Utf8String::substr_replace($str, $repl, $start, $length = null);
+
+Utf8String::ltrim($str, $charlist = null);
+
+Utf8String::rtrim($str, $charlist = null);
+
+Utf8String::trim($str, $charlist = null);
+
+Utf8String::ucfirst($str, $delimiter = null, $newDelimiter = null);
+
+Utf8String::ucwords($string);
+
+Utf8String::transcode($source, $from_encoding, $to_encoding); // Equals to iconv())
+
+Utf8String::valid($string);
+
+Utf8String::compliant($string);
+
+Utf8String::unicode_to_utf8($string);
+
+Utf8String::unicode_to_utf16($string);
+```
+
+## StringHelper
+
+### Empty String Determine
+
+isEmpty()
+
+``` php
+use Windwalker\String\StringHelper;
+
+StringHelper::isEmpty(''); // true
+StringHelper::isEmpty(0); // false
+StringHelper::isEmpty(array()); // true
+StringHelper::isEmpty(null); // true
+```
+
+isZero()
+
+``` php
+StringHelper::isZero(0); // true
+StringHelper::isZero('0'); // true
+StringHelper::isZero(''); // false
+StringHelper::isZero(null); // false
+```
+
+### Quote
+
+An useful method to quate a string.
+
+``` php
+// Default quote is `"`
+StringHelper::quote('foo'); // "foo"
+
+// Custom quotes
+StringHelper::quote('foo', array('{{', '}}')); // {{foo}}
+
+// Backquote
+StringHelper::backquote('foo'); // `foo`
+```
+
+### More Methods
+
+increment()
+
+``` php
+StringHelper::increment('Title'); // Title (2)
+StringHelper::increment('Title', StringHelper::INCREMENT_STYLE_DASH); // Title-2
+```
+
+at()
+
+``` php
+StringHelper::at('歡迎光臨', 2); // 光
+```
+
+collapseWhitespace()
+
+``` php
+StringHelper::collapseWhitespace('Welcome to Windwalker'); // 'Welcome to Windwalker'
+```
+
+endsWith()
+
+``` php
+StringHelper::endsWith('歡迎光臨', '光臨' [, $caseSensive = true]); // true
+```
+
+startsWith()
+
+``` php
+StringHelper::startsWith('歡迎光臨', '歡迎' [, $caseSensive = true]); // true
+```
+
+``` php
+// Default callback is array_push
+StringHelper::explode('.', 'foo.bar', 3); // array('foo', 'bar', null);
+
+// Shift null
+StringHelper::explode('.', 'foo.bar', 3, 'array_shift'); // array(null, 'foo', 'bar');
+
+// Limit
+StringHelper::explode('.', 'foo.bar.yoo', 2); // array('foo', 'bar.yoo');
+
+// Useful to use list()
+
+list($foo, $bar, $yoo) = StringHelper::explode('.', 'foo.bar', 3);
+```
+
+## StringInflector
+
+``` php
+use Windwalker\String\StringInflector;
+
+$inflector = StringInflector::getInstance();
+$string = 'category';
+
+if ($inflector->isSingular($string))
+{
+ $string = $inflector->toPular(); // categories
+}
+
+if ($inflector->isPlural($string))
+{
+ $string = $inflector->toSingular(); // category
+}
+```
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/SimpleTemplate.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/SimpleTemplate.php
new file mode 100644
index 00000000..bf273b64
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/SimpleTemplate.php
@@ -0,0 +1,59 @@
+ array(
+ '#-(\d+)$#',
+ '-%d'
+ ),
+ self::INCREMENT_STYLE_DEFAULT => array(
+ array('#\((\d+)\)$#', '#\(\d+\)$#'),
+ array(' (%d)', '(%d)'),
+ ),
+ );
+
+ /**
+ * isEmptyString
+ *
+ * @param string $string
+ *
+ * @return boolean
+ */
+ public static function isEmpty($string)
+ {
+ if (is_array($string) || is_object($string))
+ {
+ return empty($string);
+ }
+
+ $string = (string) $string;
+
+ return !(boolean) strlen($string);
+ }
+
+ /**
+ * isZero
+ *
+ * @param string $string
+ *
+ * @return boolean
+ */
+ public static function isZero($string)
+ {
+ return $string === '0' || $string === 0;
+ }
+
+ /**
+ * Quote a string.
+ *
+ * @param string $string The string to quote.
+ * @param array $quote The quote symbol.
+ *
+ * @return string Quoted string.
+ */
+ public static function quote($string, $quote = array('"', '"'))
+ {
+ $quote = (array) $quote;
+
+ if (empty($quote[1]))
+ {
+ $quote[1] = $quote[0];
+ }
+
+ return $quote[0] . $string . $quote[1];
+ }
+
+ /**
+ * Back quote a string.
+ *
+ * @param string $string The string to quote.
+ *
+ * @return string Quoted string.
+ */
+ public static function backquote($string)
+ {
+ return static::quote($string, '`');
+ }
+
+ /**
+ * Parse variable and replace it. This method is a simple template engine.
+ *
+ * Example: The {{ foo.bar.yoo }} will be replace to value of `$data['foo']['bar']['yoo']`
+ *
+ * @param string $string The template to replace.
+ * @param array $data The data to find.
+ * @param array $tags The variable tags.
+ *
+ * @return string Replaced template.
+ *
+ * @deprecated 3.0 Use SimpleTemplate::render() instead.
+ */
+ public static function parseVariable($string, $data = array(), $tags = array('{{', '}}'))
+ {
+ return SimpleTemplate::render($string, $data, $tags);
+ }
+
+ /**
+ * Increments a trailing number in a string.
+ *
+ * Used to easily create distinct labels when copying objects. The method has the following styles:
+ *
+ * default: "Label" becomes "Label (2)"
+ * dash: "Label" becomes "Label-2"
+ *
+ * @param string $string The source string.
+ * @param string $style The the style (default|dash).
+ * @param integer $n If supplied, this number is used for the copy, otherwise it is the 'next' number.
+ *
+ * @return string The incremented string.
+ *
+ * @since 2.0
+ */
+ public static function increment($string, $style = self::INCREMENT_STYLE_DEFAULT, $n = 0)
+ {
+ $styleSpec = isset(self::$incrementStyles[$style]) ? self::$incrementStyles[$style] : self::$incrementStyles['default'];
+
+ // Regular expression search and replace patterns.
+ if (is_array($styleSpec[0]))
+ {
+ $rxSearch = $styleSpec[0][0];
+ $rxReplace = $styleSpec[0][1];
+ }
+ else
+ {
+ $rxSearch = $rxReplace = $styleSpec[0];
+ }
+
+ // New and old (existing) sprintf formats.
+ if (is_array($styleSpec[1]))
+ {
+ $newFormat = $styleSpec[1][0];
+ $oldFormat = $styleSpec[1][1];
+ }
+ else
+ {
+ $newFormat = $oldFormat = $styleSpec[1];
+ }
+
+ // Check if we are incrementing an existing pattern, or appending a new one.
+ if (preg_match($rxSearch, $string, $matches))
+ {
+ $n = empty($n) ? ($matches[1] + 1) : $n;
+ $string = preg_replace($rxReplace, sprintf($oldFormat, $n), $string);
+ }
+ else
+ {
+ $n = empty($n) ? 2 : $n;
+ $string .= sprintf($newFormat, $n);
+ }
+
+ return $string;
+ }
+
+ /**
+ * at
+ *
+ * @param string $string
+ * @param int $num
+ *
+ * @return string
+ */
+ public static function at($string, $num)
+ {
+ $num = (int) $num;
+
+ if (Utf8String::strlen($string) < $num)
+ {
+ return null;
+ }
+
+ return Utf8String::substr($string, $num, 1);
+ }
+
+ /**
+ * remove spaces
+ *
+ * See: http://stackoverflow.com/questions/3760816/remove-new-lines-from-string
+ * And: http://stackoverflow.com/questions/9558110/php-remove-line-break-or-cr-lf-with-no-success
+ *
+ * @param string $string
+ *
+ * @return string
+ */
+ public static function collapseWhitespace($string)
+ {
+ $string = preg_replace('/\s\s+/', ' ', $string);
+
+ return trim(preg_replace('/\s+/', ' ', $string));
+ }
+
+ /**
+ * endsWith
+ *
+ * @param string $string
+ * @param string $target
+ * @param boolean $caseSensitive
+ *
+ * @return boolean
+ */
+ public static function endsWith($string, $target, $caseSensitive = true)
+ {
+ $stringLength = Utf8String::strlen($string);
+ $targetLength = Utf8String::strlen($target);
+
+ if ($stringLength < $targetLength)
+ {
+ return false;
+ }
+
+ if (!$caseSensitive)
+ {
+ $string = strtolower($string);
+ $target = strtolower($target);
+ }
+
+ $end = Utf8String::substr($string, -$targetLength);
+
+ return $end === $target;
+ }
+
+ /**
+ * startsWith
+ *
+ * @param string $string
+ * @param string $target
+ * @param boolean $caseSensitive
+ *
+ * @return boolean
+ */
+ public static function startsWith($string, $target, $caseSensitive = true)
+ {
+ if (!$caseSensitive)
+ {
+ $string = strtolower($string);
+ $target = strtolower($target);
+ }
+
+ return strpos($string, $target) === 0;
+ }
+
+ /**
+ * Explode a string and force elements number.
+ *
+ * @param string $separator
+ * @param string $data
+ * @param int $number
+ * @param string $callback
+ *
+ * @return array
+ */
+ public static function explode($separator, $data, $number = null, $callback = 'array_push')
+ {
+ if ($number)
+ {
+ $array = explode($separator, $data, $number);
+ }
+ else
+ {
+ $array = explode($separator, $data);
+ }
+
+ if (count($array) < $number)
+ {
+ foreach (range(1, $number - count($array)) as $i)
+ {
+ $callback($array, null);
+ }
+ }
+
+ return $array;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/StringInflector.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/StringInflector.php
new file mode 100644
index 00000000..c4361c20
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/StringInflector.php
@@ -0,0 +1,464 @@
+ array(
+ '/(matr)ices$/i' => '\1ix',
+ '/(vert|ind)ices$/i' => '\1ex',
+ '/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$/i' => '\1us',
+ '/([ftw]ax)es/i' => '\1',
+ '/(cris|ax|test)es$/i' => '\1is',
+ '/(shoe|slave)s$/i' => '\1',
+ '/(o)es$/i' => '\1',
+ '/([^aeiouy]|qu)ies$/i' => '\1y',
+ '/$1ses$/i' => '\s',
+ '/ses$/i' => '\s',
+ '/eaus$/' => 'eau',
+ '/^(.*us)$/' => '\\1',
+ '/s$/i' => '',
+ ),
+ 'plural' => array(
+ '/([m|l])ouse$/i' => '\1ice',
+ '/(matr|vert|ind)(ix|ex)$/i' => '\1ices',
+ '/(x|ch|ss|sh)$/i' => '\1es',
+ '/([^aeiouy]|qu)y$/i' => '\1ies',
+ '/([^aeiouy]|qu)ies$/i' => '\1y',
+ '/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
+ '/sis$/i' => 'ses',
+ '/([ti])um$/i' => '\1a',
+ '/(buffal|tomat)o$/i' => '\1\2oes',
+ '/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us$/i' => '\1i',
+ '/us$/i' => 'uses',
+ '/(ax|cris|test)is$/i' => '\1es',
+ '/s$/i' => 's',
+ '/$/' => 's',
+ ),
+ 'countable' => array(
+ 'id',
+ 'hits',
+ 'clicks',
+ ),
+ );
+
+ /**
+ * Cached inflections.
+ *
+ * The array is in the form [singular => plural]
+ *
+ * @var array
+ * @since 2.0
+ */
+ protected $cache = array();
+
+ /**
+ * Protected constructor.
+ *
+ * @since 2.0
+ */
+ public function __construct()
+ {
+ // Pre=populate the irregual singular/plural.
+ $this->addWord('deer')
+ ->addWord('moose')
+ ->addWord('sheep')
+ ->addWord('bison')
+ ->addWord('salmon')
+ ->addWord('pike')
+ ->addWord('trout')
+ ->addWord('fish')
+ ->addWord('swine')
+
+ ->addWord('alias', 'aliases')
+ ->addWord('bus', 'buses')
+ ->addWord('foot', 'feet')
+ ->addWord('goose', 'geese')
+ ->addWord('hive', 'hives')
+ ->addWord('louse', 'lice')
+ ->addWord('man', 'men')
+ ->addWord('mouse', 'mice')
+ ->addWord('ox', 'oxen')
+ ->addWord('quiz', 'quizes')
+ ->addWord('status', 'statuses')
+ ->addWord('tooth', 'teeth')
+ ->addWord('woman', 'women');
+ }
+
+ /**
+ * Adds inflection regex rules to the inflector.
+ *
+ * @param mixed $data A string or an array of strings or regex rules to add.
+ * @param string $ruleType The rule type: singular | plural | countable
+ *
+ * @return void
+ *
+ * @since 2.0
+ * @throws \InvalidArgumentException
+ */
+ private function addRule($data, $ruleType)
+ {
+ if (is_string($data))
+ {
+ $data = array($data);
+ }
+ elseif (!is_array($data))
+ {
+ // Do not translate.
+ throw new \InvalidArgumentException('Invalid inflector rule data.');
+ }
+
+ foreach ($data as $rule)
+ {
+ // Ensure a string is pushed.
+ array_push($this->rules[$ruleType], (string) $rule);
+ }
+ }
+
+ /**
+ * Gets an inflected word from the cache where the singular form is supplied.
+ *
+ * @param string $singular A singular form of a word.
+ *
+ * @return mixed The cached inflection or false if none found.
+ *
+ * @since 2.0
+ */
+ private function getCachedPlural($singular)
+ {
+ $singular = Utf8String::strtolower($singular);
+
+ // Check if the word is in cache.
+ if (isset($this->cache[$singular]))
+ {
+ return $this->cache[$singular];
+ }
+
+ return false;
+ }
+
+ /**
+ * Gets an inflected word from the cache where the plural form is supplied.
+ *
+ * @param string $plural A plural form of a word.
+ *
+ * @return mixed The cached inflection or false if none found.
+ *
+ * @since 2.0
+ */
+ private function getCachedSingular($plural)
+ {
+ $plural = Utf8String::strtolower($plural);
+
+ return array_search($plural, $this->cache);
+ }
+
+ /**
+ * Execute a regex from rules.
+ *
+ * The 'plural' rule type expects a singular word.
+ * The 'singular' rule type expects a plural word.
+ *
+ * @param string $word The string input.
+ * @param string $ruleType String (eg, singular|plural)
+ *
+ * @return mixed An inflected string, or false if no rule could be applied.
+ *
+ * @since 2.0
+ */
+ private function matchRegexRule($word, $ruleType)
+ {
+ // Cycle through the regex rules.
+ foreach ($this->rules[$ruleType] as $regex => $replacement)
+ {
+ $matches = 0;
+ $matchedWord = preg_replace($regex, $replacement, $word, -1, $matches);
+
+ if ($matches > 0)
+ {
+ return $matchedWord;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Sets an inflected word in the cache.
+ *
+ * @param string $singular The singular form of the word.
+ * @param string $plural The plural form of the word. If omitted, it is assumed the singular and plural are identical.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ private function setCache($singular, $plural = null)
+ {
+ $singular = Utf8String::strtolower($singular);
+
+ if ($plural === null)
+ {
+ $plural = $singular;
+ }
+ else
+ {
+ $plural = Utf8String::strtolower($plural);
+ }
+
+ $this->cache[$singular] = $plural;
+ }
+
+ /**
+ * Adds a countable word.
+ *
+ * @param mixed $data A string or an array of strings to add.
+ *
+ * @return static Returns this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function addCountableRule($data)
+ {
+ $this->addRule($data, 'countable');
+
+ return $this;
+ }
+
+ /**
+ * Adds a specific singular-plural pair for a word.
+ *
+ * @param string $singular The singular form of the word.
+ * @param string $plural The plural form of the word. If omitted, it is assumed the singular and plural are identical.
+ *
+ * @return static Returns this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function addWord($singular, $plural =null)
+ {
+ $this->setCache($singular, $plural);
+
+ return $this;
+ }
+
+ /**
+ * Adds a pluralisation rule.
+ *
+ * @param mixed $data A string or an array of regex rules to add.
+ *
+ * @return static Returns this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function addPluraliseRule($data)
+ {
+ $this->addRule($data, 'plural');
+
+ return $this;
+ }
+
+ /**
+ * Adds a singularisation rule.
+ *
+ * @param mixed $data A string or an array of regex rules to add.
+ *
+ * @return static Returns this object to support chaining.
+ *
+ * @since 2.0
+ */
+ public function addSingulariseRule($data)
+ {
+ $this->addRule($data, 'singular');
+
+ return $this;
+ }
+
+ /**
+ * Gets an instance of the JStringInflector singleton.
+ *
+ * @param boolean $new If true (default is false), returns a new instance regardless if one exists.
+ * This argument is mainly used for testing.
+ *
+ * @return static
+ *
+ * @since 2.0
+ */
+ public static function getInstance($new = false)
+ {
+ if ($new)
+ {
+ return new static;
+ }
+ elseif (!is_object(static::$instance))
+ {
+ static::$instance = new static;
+ }
+
+ return static::$instance;
+ }
+
+ /**
+ * Checks if a word is countable.
+ *
+ * @param string $word The string input.
+ *
+ * @return boolean True if word is countable, false otherwise.
+ *
+ * @since 2.0
+ */
+ public function isCountable($word)
+ {
+ return (boolean) in_array($word, $this->rules['countable']);
+ }
+
+ /**
+ * Checks if a word is in a plural form.
+ *
+ * @param string $word The string input.
+ *
+ * @return boolean True if word is plural, false if not.
+ *
+ * @since 2.0
+ */
+ public function isPlural($word)
+ {
+ // Try the cache for an known inflection.
+ $inflection = $this->getCachedSingular($word);
+
+ if ($inflection !== false)
+ {
+ return true;
+ }
+
+ // Compute the inflection to cache the values, and compare.
+ return $this->toPlural($this->toSingular($word)) == $word;
+ }
+
+ /**
+ * Checks if a word is in a singular form.
+ *
+ * @param string $word The string input.
+ *
+ * @return boolean True if word is singular, false if not.
+ *
+ * @since 2.0
+ */
+ public function isSingular($word)
+ {
+ // Try the cache for an known inflection.
+ $inflection = $this->getCachedPlural($word);
+
+ if ($inflection !== false)
+ {
+ return true;
+ }
+
+ // Compute the inflection to cache the values, and compare.
+ return $this->toSingular($this->toPlural($word)) == $word;
+ }
+
+ /**
+ * Converts a word into its plural form.
+ *
+ * @param string $word The singular word to pluralise.
+ *
+ * @return mixed An inflected string, or false if no rule could be applied.
+ *
+ * @since 2.0
+ */
+ public function toPlural($word)
+ {
+ // Try to get the cached plural form from the singular.
+ $cache = $this->getCachedPlural($word);
+
+ if ($cache !== false)
+ {
+ return $cache;
+ }
+
+ // Check if the word is a known singular.
+ if ($this->getCachedSingular($word))
+ {
+ return false;
+ }
+
+ // Compute the inflection.
+ $inflected = $this->matchRegexRule($word, 'plural');
+
+ if ($inflected !== false)
+ {
+ $this->setCache($word, $inflected);
+
+ return $inflected;
+ }
+
+ return false;
+ }
+
+ /**
+ * Converts a word into its singular form.
+ *
+ * @param string $word The plural word to singularise.
+ *
+ * @return mixed An inflected string, or false if no rule could be applied.
+ *
+ * @since 2.0
+ */
+ public function toSingular($word)
+ {
+ // Try to get the cached singular form from the plural.
+ $cache = $this->getCachedSingular($word);
+
+ if ($cache !== false)
+ {
+ return $cache;
+ }
+
+ // Check if the word is a known plural.
+ if ($this->getCachedPlural($word))
+ {
+ return false;
+ }
+
+ // Compute the inflection.
+ $inflected = $this->matchRegexRule($word, 'singular');
+
+ if ($inflected !== false)
+ {
+ $this->setCache($inflected, $word);
+
+ return $inflected;
+ }
+
+ return false;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/StringNormalise.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/StringNormalise.php
new file mode 100644
index 00000000..082d3e9c
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/StringNormalise.php
@@ -0,0 +1,208 @@
+StringInflector = StringInflector::getInstance(true);
+ }
+
+ /**
+ * Method to test StringInflector::addRule().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::addRule
+ * @since 2.0
+ */
+ public function testAddRule()
+ {
+ // Case 1
+ TestHelper::invoke($this->StringInflector, 'addRule', '/foo/', 'singular');
+
+ $rules = TestHelper::getValue($this->StringInflector, 'rules');
+
+ $this->assertContains(
+ '/foo/',
+ $rules['singular'],
+ 'Checks if the singular rule was added correctly.'
+ );
+
+ // Case 2
+ TestHelper::invoke($this->StringInflector, 'addRule', '/bar/', 'plural');
+
+ $rules = TestHelper::getValue($this->StringInflector, 'rules');
+
+ $this->assertContains(
+ '/bar/',
+ $rules['plural'],
+ 'Checks if the plural rule was added correctly.'
+ );
+
+ // Case 3
+ TestHelper::invoke($this->StringInflector, 'addRule', array('/goo/', '/car/'), 'singular');
+
+ $rules = TestHelper::getValue($this->StringInflector, 'rules');
+
+ $this->assertContains(
+ '/goo/',
+ $rules['singular'],
+ 'Checks if an array of rules was added correctly (1).'
+ );
+
+ $this->assertContains(
+ '/car/',
+ $rules['singular'],
+ 'Checks if an array of rules was added correctly (2).'
+ );
+ }
+
+ /**
+ * Method to test StringInflector::addRule().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::addRule
+ * @expectedException InvalidArgumentException
+ * @since 2.0
+ */
+ public function testAddRuleException()
+ {
+ TestHelper::invoke($this->StringInflector, 'addRule', new \stdClass, 'singular');
+ }
+
+ /**
+ * Method to test StringInflector::getCachedPlural().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::getCachedPlural
+ * @since 2.0
+ */
+ public function testGetCachedPlural()
+ {
+ // Reset the cache.
+ TestHelper::setValue($this->StringInflector, 'cache', array('foo' => 'bar'));
+
+ $this->assertFalse(
+ TestHelper::invoke($this->StringInflector, 'getCachedPlural', 'bar'),
+ 'Checks for an uncached plural.'
+ );
+
+ $this->assertEquals(
+ 'bar',
+ TestHelper::invoke($this->StringInflector, 'getCachedPlural', 'foo'),
+ 'Checks for a cached plural word.'
+ );
+ }
+
+ /**
+ * Method to test StringInflector::getCachedSingular().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::getCachedSingular
+ * @since 2.0
+ */
+ public function testGetCachedSingular()
+ {
+ // Reset the cache.
+ TestHelper::setValue($this->StringInflector, 'cache', array('foo' => 'bar'));
+
+ $this->assertFalse(
+ TestHelper::invoke($this->StringInflector, 'getCachedSingular', 'foo'),
+ 'Checks for an uncached singular.'
+ );
+
+ $this->assertThat(
+ TestHelper::invoke($this->StringInflector, 'getCachedSingular', 'bar'),
+ $this->equalTo('foo'),
+ 'Checks for a cached singular word.'
+ );
+ }
+
+ /**
+ * Method to test StringInflector::matchRegexRule().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::matchRegexRule
+ * @since 2.0
+ */
+ public function testMatchRegexRule()
+ {
+ $this->assertThat(
+ TestHelper::invoke($this->StringInflector, 'matchRegexRule', 'xyz', 'plural'),
+ $this->equalTo('xyzs'),
+ 'Checks pluralising against the basic regex.'
+ );
+
+ $this->assertThat(
+ TestHelper::invoke($this->StringInflector, 'matchRegexRule', 'xyzs', 'singular'),
+ $this->equalTo('xyz'),
+ 'Checks singularising against the basic regex.'
+ );
+
+ $this->assertFalse(
+ TestHelper::invoke($this->StringInflector, 'matchRegexRule', 'xyz', 'singular'),
+ 'Checks singularising against an unmatched regex.'
+ );
+ }
+
+ /**
+ * Method to test StringInflector::setCache().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::setCache
+ * @since 2.0
+ */
+ public function testSetCache()
+ {
+ TestHelper::invoke($this->StringInflector, 'setCache', 'foo', 'bar');
+
+ $cache = TestHelper::getValue($this->StringInflector, 'cache');
+
+ $this->assertThat(
+ $cache['foo'],
+ $this->equalTo('bar'),
+ 'Checks the cache was set.'
+ );
+
+ TestHelper::invoke($this->StringInflector, 'setCache', 'foo', 'car');
+
+ $cache = TestHelper::getValue($this->StringInflector, 'cache');
+
+ $this->assertThat(
+ $cache['foo'],
+ $this->equalTo('car'),
+ 'Checks an existing value in the cache was reset.'
+ );
+ }
+
+ /**
+ * Method to test StringInflector::addCountableRule().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::addCountableRule
+ * @since 2.0
+ */
+ public function testAddCountableRule()
+ {
+ // Add string.
+ $this->StringInflector->addCountableRule('foo');
+
+ $rules = TestHelper::getValue($this->StringInflector, 'rules');
+
+ $this->assertContains(
+ 'foo',
+ $rules['countable'],
+ 'Checks a countable rule was added.'
+ );
+
+ // Add array.
+ $this->StringInflector->addCountableRule(array('goo', 'car'));
+
+ $rules = TestHelper::getValue($this->StringInflector, 'rules');
+
+ $this->assertContains(
+ 'car',
+ $rules['countable'],
+ 'Checks a countable rule was added by array.'
+ );
+ }
+
+ /**
+ * Method to test StringInflector::addWord().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::addWord
+ * @since 2.0
+ */
+ public function testAddWord()
+ {
+ $this->assertEquals(
+ $this->StringInflector,
+ $this->StringInflector->addWord('foo')
+ );
+
+ $cache = TestHelper::getValue($this->StringInflector, 'cache');
+
+ $this->assertArrayHasKey('foo', $cache);
+
+ $this->assertEquals(
+ 'foo',
+ $cache['foo']
+ );
+
+ $this->assertEquals(
+ $this->StringInflector,
+ $this->StringInflector->addWord('bar', 'foo')
+ );
+
+ $cache = TestHelper::getValue($this->StringInflector, 'cache');
+
+ $this->assertArrayHasKey('bar', $cache);
+
+ $this->assertEquals(
+ 'foo',
+ $cache['bar']
+ );
+ }
+
+ /**
+ * Method to test StringInflector::addPluraliseRule().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::addPluraliseRule
+ * @since 2.0
+ */
+ public function testAddPluraliseRule()
+ {
+ $chain = $this->StringInflector->addPluraliseRule(array('/foo/', '/bar/'));
+
+ $this->assertThat(
+ $chain,
+ $this->identicalTo($this->StringInflector),
+ 'Checks chaining.'
+ );
+
+ $rules = TestHelper::getValue($this->StringInflector, 'rules');
+
+ $this->assertCOntains(
+ '/bar/',
+ $rules['plural'],
+ 'Checks a pluralisation rule was added.'
+ );
+ }
+
+ /**
+ * Method to test StringInflector::addSingulariseRule().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::addSingulariseRule
+ * @since 2.0
+ */
+ public function testAddSingulariseRule()
+ {
+ $chain = $this->StringInflector->addSingulariseRule(array('/foo/', '/bar/'));
+
+ $this->assertThat(
+ $chain,
+ $this->identicalTo($this->StringInflector),
+ 'Checks chaining.'
+ );
+
+ $rules = TestHelper::getValue($this->StringInflector, 'rules');
+
+ $this->assertContains(
+ '/bar/',
+ $rules['singular'],
+ 'Checks a singularisation rule was added.'
+ );
+ }
+
+ /**
+ * Method to test StringInflector::getInstance().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::getInstance
+ * @since 2.0
+ */
+ public function testGetInstance()
+ {
+ $this->assertInstanceOf(
+ 'Windwalker\\String\\StringInflector',
+ StringInflector::getInstance(),
+ 'Check getInstance returns the right class.'
+ );
+
+ // Inject an instance an test.
+ TestHelper::setValue($this->StringInflector, 'instance', new \stdClass);
+
+ $this->assertThat(
+ StringInflector::getInstance(),
+ $this->equalTo(new \stdClass),
+ 'Checks singleton instance is returned.'
+ );
+
+ $this->assertInstanceOf(
+ 'Windwalker\\String\\StringInflector',
+ StringInflector::getInstance(true),
+ 'Check getInstance a fresh object with true argument even though the instance is set to something else.'
+ );
+ }
+
+ /**
+ * Method to test StringInflector::isCountable().
+ *
+ * @param string $input A string.
+ * @param boolean $expected The expected result of the function call.
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::isCountable
+ * @dataProvider seedIsCountable
+ * @since 2.0
+ */
+ public function testIsCountable($input, $expected)
+ {
+ $this->assertThat(
+ $this->StringInflector->isCountable($input),
+ $this->equalTo($expected)
+ );
+ }
+
+ /**
+ * Method to test StringInflector::isPlural().
+ *
+ * @param string $singular The singular form of a word.
+ * @param string $plural The plural form of a word.
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::isPlural
+ * @dataProvider seedSinglePlural
+ * @since 2.0
+ */
+ public function testIsPlural($singular, $plural)
+ {
+ $this->assertTrue(
+ $this->StringInflector->isPlural($plural),
+ 'Checks the plural is a plural.'
+ );
+
+ if ($singular != $plural)
+ {
+ $this->assertFalse(
+ $this->StringInflector->isPlural($singular),
+ 'Checks the singular is not plural.'
+ );
+ }
+ }
+
+ /**
+ * Method to test StringInflector::isSingular().
+ *
+ * @param string $singular The singular form of a word.
+ * @param string $plural The plural form of a word.
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::isSingular
+ * @dataProvider seedSinglePlural
+ * @since 2.0
+ */
+ public function testIsSingular($singular, $plural)
+ {
+ $this->assertTrue(
+ $this->StringInflector->isSingular($singular),
+ 'Checks the singular is a singular.'
+ );
+
+ if ($singular != $plural)
+ {
+ $this->assertFalse(
+ $this->StringInflector->isSingular($plural),
+ 'Checks the plural is not singular.'
+ );
+ }
+ }
+
+ /**
+ * Method to test StringInflector::toPlural().
+ *
+ * @param string $singular The singular form of a word.
+ * @param string $plural The plural form of a word.
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::toPlural
+ * @dataProvider seedSinglePlural
+ * @since 2.0
+ */
+ public function testToPlural($singular, $plural)
+ {
+ $this->assertThat(
+ $this->StringInflector->toPlural($singular),
+ $this->equalTo($plural)
+ );
+ }
+
+ /**
+ * Method to test StringInflector::toPlural().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::toPlural
+ * @since 2.0
+ */
+ public function testToPluralAlreadyPlural()
+ {
+ $this->assertFalse($this->StringInflector->toPlural('buses'));
+ }
+
+ /**
+ * Method to test StringInflector::toPlural().
+ *
+ * @param string $singular The singular form of a word.
+ * @param string $plural The plural form of a word.
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::toSingular
+ * @dataProvider seedSinglePlural
+ * @since 2.0
+ */
+ public function testToSingular($singular, $plural)
+ {
+ $this->assertThat(
+ $this->StringInflector->toSingular($plural),
+ $this->equalTo($singular)
+ );
+ }
+
+ /**
+ * Method to test StringInflector::toPlural().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringInflector::toSingular
+ * @since 2.0
+ */
+ public function testToSingularRetFalse()
+ {
+ // Assertion for already singular
+ $this->assertFalse($this->StringInflector->toSingular('bus'));
+
+ $this->assertFalse($this->StringInflector->toSingular('foo'));
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/Test/NormaliseTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/Test/NormaliseTest.php
new file mode 100644
index 00000000..ca61b770
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/Test/NormaliseTest.php
@@ -0,0 +1,314 @@
+assertEquals($expected, StringNormalise::fromCamelcase($input));
+ }
+
+ /**
+ * Method to test StringNormalise::fromCamelCase(string, true).
+ *
+ * @param string $input The input value for the method.
+ * @param string $expected The expected value from the method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringNormalise::fromCamelcase
+ * @dataProvider seedTestFromCamelCase
+ * @since 2.0
+ */
+ public function testFromCamelCase_grouped($input, $expected)
+ {
+ $this->assertEquals($expected, StringNormalise::fromCamelcase($input, true));
+ }
+
+ /**
+ * Method to test StringNormalise::toCamelCase().
+ *
+ * @param string $expected The expected value from the method.
+ * @param string $input The input value for the method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringNormalise::toCamelcase
+ * @dataProvider seedTestToCamelCase
+ * @since 2.0
+ */
+ public function testToCamelCase($expected, $input)
+ {
+ $this->assertEquals($expected, StringNormalise::toCamelcase($input));
+ }
+
+ /**
+ * Method to test StringNormalise::toDashSeparated().
+ *
+ * @param string $expected The expected value from the method.
+ * @param string $input The input value for the method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringNormalise::toDashSeparated
+ * @dataProvider seedTestToDashSeparated
+ * @since 2.0
+ */
+ public function testToDashSeparated($expected, $input)
+ {
+ $this->assertEquals($expected, StringNormalise::toDashSeparated($input));
+ }
+
+ /**
+ * Method to test StringNormalise::toSpaceSeparated().
+ *
+ * @param string $expected The expected value from the method.
+ * @param string $input The input value for the method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringNormalise::toSpaceSeparated
+ * @dataProvider seedTestToSpaceSeparated
+ * @since 2.0
+ */
+ public function testToSpaceSeparated($expected, $input)
+ {
+ $this->assertEquals($expected, StringNormalise::toSpaceSeparated($input));
+ }
+
+ /**
+ * Method to test StringNormalise::toUnderscoreSeparated().
+ *
+ * @param string $expected The expected value from the method.
+ * @param string $input The input value for the method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringNormalise::toUnderscoreSeparated
+ * @dataProvider seedTestToUnderscoreSeparated
+ * @since 2.0
+ */
+ public function testToUnderscoreSeparated($expected, $input)
+ {
+ $this->assertEquals($expected, StringNormalise::toUnderscoreSeparated($input));
+ }
+
+ /**
+ * Method to test StringNormalise::toVariable().
+ *
+ * @param string $expected The expected value from the method.
+ * @param string $input The input value for the method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringNormalise::toVariable
+ * @dataProvider seedTestToVariable
+ * @since 2.0
+ */
+ public function testToVariable($expected, $input)
+ {
+ $this->assertEquals($expected, StringNormalise::toVariable($input));
+ }
+
+ /**
+ * Method to test StringNormalise::toKey().
+ *
+ * @param string $expected The expected value from the method.
+ * @param string $input The input value for the method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringNormalise::toKey
+ * @dataProvider seedTestToKey
+ * @since 2.0
+ */
+ public function testToKey($expected, $input)
+ {
+ $this->assertEquals($expected, StringNormalise::toKey($input));
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/Test/StringHelperTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/Test/StringHelperTest.php
new file mode 100644
index 00000000..43ce91d9
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/Test/StringHelperTest.php
@@ -0,0 +1,195 @@
+assertTrue(StringHelper::isEmpty(''));
+ $this->assertFalse(StringHelper::isEmpty(0));
+ $this->assertFalse(StringHelper::isEmpty(' '));
+ $this->assertTrue(StringHelper::isEmpty(null));
+ $this->assertFalse(StringHelper::isEmpty(true));
+ $this->assertTrue(StringHelper::isEmpty(false));
+ }
+
+ /**
+ * Method to test isZero().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringHelper::isZero
+ */
+ public function testIsZero()
+ {
+ $this->assertTrue(StringHelper::isZero(0));
+ $this->assertTrue(StringHelper::isZero('0'));
+ $this->assertFalse(StringHelper::isZero(''));
+ $this->assertFalse(StringHelper::isZero(null));
+ $this->assertFalse(StringHelper::isZero(true));
+ $this->assertFalse(StringHelper::isZero(false));
+ }
+
+ /**
+ * Method to test quote().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringHelper::quote
+ */
+ public function testQuote()
+ {
+ $this->assertEquals('"foo"', StringHelper::quote('foo'));
+ $this->assertEquals('"foo"', StringHelper::quote('foo', '"'));
+ $this->assertEquals('"foo"', StringHelper::quote('foo', array('"', '"')));
+ $this->assertEquals('[foo]', StringHelper::quote('foo', array('[', ']')));
+ }
+
+ /**
+ * Method to test backquote().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringHelper::backquote
+ */
+ public function testBackquote()
+ {
+ $this->assertEquals('`foo`', StringHelper::backquote('foo'));
+ }
+
+ /**
+ * Method to test parseVariable().
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringHelper::parseVariable
+ */
+ public function testParseVariable()
+ {
+ $data['foo']['bar']['baz'] = 'Flower';
+
+ $this->assertEquals('This is Flower', StringHelper::parseVariable('This is {{ foo.bar.baz }}', $data));
+ $this->assertEquals('This is ', StringHelper::parseVariable('This is {{ foo.yoo }}', $data));
+ $this->assertEquals('This is Flower', StringHelper::parseVariable('This is [ foo.bar.baz ]', $data, array('[', ']')));
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestIncrement()
+ {
+ return array(
+ // Note: string, style, number, expected
+ 'First default increment' => array('title', null, 0, 'title (2)'),
+ 'Second default increment' => array('title(2)', null, 0, 'title(3)'),
+ 'First dash increment' => array('title', 'dash', 0, 'title-2'),
+ 'Second dash increment' => array('title-2', 'dash', 0, 'title-3'),
+ 'Set default increment' => array('title', null, 4, 'title (4)'),
+ 'Unknown style fallback to default' => array('title', 'foo', 0, 'title (2)'),
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string String to increment.
+ * @param string $style Default of Dash.
+ * @param string $number Number to increment.
+ * @param string $expected Expected value.
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\StringHelper::increment
+ * @dataProvider seedTestIncrement
+ * @since 2.0
+ */
+ public function testIncrement($string, $style, $number, $expected)
+ {
+ $this->assertEquals(
+ $expected,
+ StringHelper::increment($string, $style, $number)
+ );
+ }
+
+ /**
+ * testAt
+ *
+ * @return void
+ */
+ public function testAt()
+ {
+ $string = 'Foo Bar';
+
+ $this->assertEquals('F', StringHelper::at($string, 0));
+ $this->assertEquals('o', StringHelper::at($string, 1));
+ $this->assertNull(StringHelper::at($string, 10));
+ }
+
+ /**
+ * testEndsWith
+ *
+ * @return void
+ */
+ public function testEndsWith()
+ {
+ $string = 'Foo';
+
+ $this->assertTrue(StringHelper::endsWith($string, 'oo'));
+ $this->assertFalse(StringHelper::endsWith($string, 'Oo'));
+ $this->assertTrue(StringHelper::endsWith($string, 'Oo', false));
+ $this->assertFalse(StringHelper::endsWith($string, 'ooooo'));
+ $this->assertFalse(StringHelper::endsWith($string, 'uv'));
+ }
+
+ /**
+ * testStartsWith
+ *
+ * @return void
+ */
+ public function testStartsWith()
+ {
+ $string = 'Foo';
+
+ $this->assertTrue(StringHelper::startsWith($string, 'Fo'));
+ $this->assertFalse(StringHelper::startsWith($string, 'fo'));
+ $this->assertTrue(StringHelper::startsWith($string, 'fo', false));
+ $this->assertFalse(StringHelper::startsWith($string, 'ooooo'));
+ $this->assertFalse(StringHelper::startsWith($string, 'uv'));
+ }
+
+ /**
+ * testCollapseWhitespace
+ *
+ * @return void
+ */
+ public function testCollapseWhitespace()
+ {
+ $this->assertEquals('foo bar', StringHelper::collapseWhitespace(' foo bar '));
+ $this->assertEquals('foo bar', StringHelper::collapseWhitespace(" foo \n \r bar \n "));
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/Test/Utf8StringTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/Test/Utf8StringTest.php
new file mode 100644
index 00000000..8dabb903
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/Test/Utf8StringTest.php
@@ -0,0 +1,1075 @@
+ string ', '<>', false, false, 8),
+ array('Би шил {123} идэй {456} чадна', '}{', null, false, 7),
+ array('Би шил {123} идэй {456} чадна', '}{', 13, 10, 5)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestStristr()
+ {
+ return array(
+ array('haystack', 'needle', false),
+ array('before match, after match', 'match', 'match, after match'),
+ array('Би шил идэй чадна', 'шил', 'шил идэй чадна')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestStrrev()
+ {
+ return array(
+ array('abc def', 'fed cba'),
+ array('Би шил', 'лиш иБ')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestStrspn()
+ {
+ return array(
+ array('A321 Main Street', '0123456789', 1, 2, 2),
+ array('321 Main Street', '0123456789', null, 2, 2),
+ array('A321 Main Street', '0123456789', null, 10, 0),
+ array('321 Main Street', '0123456789', null, null, 3),
+ array('Main Street 321', '0123456789', null, -3, 0),
+ array('321 Main Street', '0123456789', null, -13, 2),
+ array('321 Main Street', '0123456789', null, -12, 3),
+ array('A321 Main Street', '0123456789', 0, null, 0),
+ array('A321 Main Street', '0123456789', 1, 10, 3),
+ array('A321 Main Street', '0123456789', 1, null, 3),
+ array('Би шил идэй чадна', 'Би', null, null, 2),
+ array('чадна Би шил идэй чадна', 'Би', null, null, 0)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestSubstr_replace()
+ {
+ return array(
+ array('321 Broadway Avenue', '321 Main Street', 'Broadway Avenue', 4, null),
+ array('321 Broadway Street', '321 Main Street', 'Broadway', 4, 4),
+ array('чадна 我能吞', 'чадна Би шил идэй чадна', '我能吞', 6, null),
+ array('чадна 我能吞 шил идэй чадна', 'чадна Би шил идэй чадна', '我能吞', 6, 2)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestLtrim()
+ {
+ return array(
+ array(' abc def', null, 'abc def'),
+ array(' abc def', '', ' abc def'),
+ array(' Би шил', null, 'Би шил'),
+ array("\t\n\r\x0BБи шил", null, 'Би шил'),
+ array("\x0B\t\n\rБи шил", "\t\n\x0B", "\rБи шил"),
+ array("\x09Би шил\x0A", "\x09\x0A", "Би шил\x0A"),
+ array('1234abc', '0123456789', 'abc')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestRtrim()
+ {
+ return array(
+ array('abc def ', null, 'abc def'),
+ array('abc def ', '', 'abc def '),
+ array('Би шил ', null, 'Би шил'),
+ array("Би шил\t\n\r\x0B", null, 'Би шил'),
+ array("Би шил\r\x0B\t\n", "\t\n\x0B", "Би шил\r"),
+ array("\x09Би шил\x0A", "\x09\x0A", "\x09Би шил"),
+ array('1234abc', 'abc', '01234')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestTrim()
+ {
+ return array(
+ array(' abc def ', null, 'abc def'),
+ array(' abc def ', '', ' abc def '),
+ array(' Би шил ', null, 'Би шил'),
+ array("\t\n\r\x0BБи шил\t\n\r\x0B", null, 'Би шил'),
+ array("\x0B\t\n\rБи шил\r\x0B\t\n", "\t\n\x0B", "\rБи шил\r"),
+ array("\x09Би шил\x0A", "\x09\x0A", "Би шил"),
+ array('1234abc56789', '0123456789', 'abc')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestUcfirst()
+ {
+ return array(
+ array('george', null, null, 'George'),
+ array('мога', null, null, 'Мога'),
+ array('ψυχοφθόρα', null, null, 'Ψυχοφθόρα'),
+ array('dr jekill and mister hyde', ' ', null, 'Dr Jekill And Mister Hyde'),
+ array('dr jekill and mister hyde', ' ', '_', 'Dr_Jekill_And_Mister_Hyde'),
+ array('dr jekill and mister hyde', ' ', '', 'DrJekillAndMisterHyde'),
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestUcwords()
+ {
+ return array(
+ array('george washington', 'George Washington'),
+ array("george\r\nwashington", "George\r\nWashington"),
+ array('мога', 'Мога'),
+ array('αβγ δεζ', 'Αβγ Δεζ'),
+ array('åbc öde', 'Åbc Öde')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestTranscode()
+ {
+ return array(
+ array('Åbc Öde €2.0', 'UTF-8', 'ISO-8859-1', "\xc5bc \xd6de EUR2.0"),
+ array(array('Åbc Öde €2.0'), 'UTF-8', 'ISO-8859-1', null),
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestValid()
+ {
+ return array(
+ array("\xCF\xB0", true),
+ array("\xFBa", false),
+ array("\xFDa", false),
+ array("foo\xF7bar", false),
+ array('george Мога Ž Ψυχοφθόρα ฉันกินกระจกได้ 我能吞下玻璃而不伤身体 ', true),
+ array("\xFF ABC", false),
+ array("0xfffd ABC", true),
+ array('', true)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestUnicodeToUtf8()
+ {
+ return array(
+ array("\u0422\u0435\u0441\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u044b", "Тест системы"),
+ array("\u00dcberpr\u00fcfung der Systemumstellung", "Überprüfung der Systemumstellung")
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestUnicodeToUtf16()
+ {
+ return array(
+ array("\u0422\u0435\u0441\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u044b", "Тест системы"),
+ array("\u00dcberpr\u00fcfung der Systemumstellung", "Überprüfung der Systemumstellung")
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param boolean $expected @todo
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\Utf8String::is_ascii
+ * @dataProvider seedTestIs_ascii
+ * @since 2.0
+ */
+ public function testIs_ascii($string, $expected)
+ {
+ $this->assertEquals(
+ $expected,
+ Utf8String::is_ascii($string)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $expect @todo
+ * @param string $haystack @todo
+ * @param string $needle @todo
+ * @param integer $offset @todo
+ *
+ * @return void
+ *
+ * @covers Windwalker\String\Utf8String::strpos
+ * @dataProvider seedTestStrpos
+ * @since 2.0
+ */
+ public function testStrpos($expect, $haystack, $needle, $offset = 0)
+ {
+ $actual = Utf8String::strpos($haystack, $needle, $offset);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $expect @todo
+ * @param string $haystack @todo
+ * @param string $needle @todo
+ * @param integer $offset @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::strrpos
+ * @dataProvider seedTestGetStrrpos
+ * @since 2.0
+ */
+ public function testStrrpos($expect, $haystack, $needle, $offset = 0)
+ {
+ $actual = Utf8String::strrpos($haystack, $needle, $offset);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $expect @todo
+ * @param string $string @todo
+ * @param string $start @todo
+ * @param bool|int $length @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::substr
+ * @dataProvider seedTestSubstr
+ * @since 2.0
+ */
+ public function testSubstr($expect, $string, $start, $length = false)
+ {
+ $actual = Utf8String::substr($string, $start, $length);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::strtolower
+ * @dataProvider seedTestStrtolower
+ * @since 2.0
+ */
+ public function testStrtolower($string, $expect)
+ {
+ $actual = Utf8String::strtolower($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::strtoupper
+ * @dataProvider seedTestStrtoupper
+ * @since 2.0
+ */
+ public function testStrtoupper($string, $expect)
+ {
+ $actual = Utf8String::strtoupper($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::strlen
+ * @dataProvider seedTestStrlen
+ * @since 2.0
+ */
+ public function testStrlen($string, $expect)
+ {
+ $actual = Utf8String::strlen($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $search @todo
+ * @param string $replace @todo
+ * @param string $subject @todo
+ * @param integer $count @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::str_ireplace
+ * @dataProvider seedTestStr_ireplace
+ * @since 2.0
+ */
+ public function testStr_ireplace($search, $replace, $subject, $count, $expect)
+ {
+ $actual = Utf8String::str_ireplace($search, $replace, $subject, $count);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $split_length @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::str_split
+ * @dataProvider seedTestStr_split
+ * @since 2.0
+ */
+ public function testStr_split($string, $split_length, $expect)
+ {
+ $actual = Utf8String::str_split($string, $split_length);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string1 @todo
+ * @param string $string2 @todo
+ * @param string $locale @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::strcasecmp
+ * @dataProvider seedTestStrcasecmp
+ * @since 2.0
+ */
+ public function testStrcasecmp($string1, $string2, $locale, $expect)
+ {
+ // Convert the $locale param to a string if it is an array
+ if (is_array($locale))
+ {
+ $locale = "'" . implode("', '", $locale) . "'";
+ }
+
+ if (substr(php_uname(), 0, 6) == 'Darwin' && $locale != false)
+ {
+ $this->markTestSkipped('Darwin bug prevents foreign conversion from working properly');
+ }
+ elseif ($locale != false && !setlocale(LC_COLLATE, $locale))
+ {
+ $this->markTestSkipped("Locale {$locale} is not available.");
+ }
+ else
+ {
+ $actual = Utf8String::strcasecmp($string1, $string2, $locale);
+
+ if ($actual != 0)
+ {
+ $actual = $actual / abs($actual);
+ }
+
+ $this->assertEquals($expect, $actual);
+ }
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string1 @todo
+ * @param string $string2 @todo
+ * @param string $locale @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::strcmp
+ * @dataProvider seedTestStrcmp
+ * @since 2.0
+ */
+ public function testStrcmp($string1, $string2, $locale, $expect)
+ {
+ // Convert the $locale param to a string if it is an array
+ if (is_array($locale))
+ {
+ $locale = "'" . implode("', '", $locale) . "'";
+ }
+
+ if (substr(php_uname(), 0, 6) == 'Darwin' && $locale != false)
+ {
+ $this->markTestSkipped('Darwin bug prevents foreign conversion from working properly');
+ }
+ elseif ($locale != false && !setlocale(LC_COLLATE, $locale))
+ {
+ // If the locale is not available, we can't have to transcode the string and can't reliably compare it.
+ $this->markTestSkipped("Locale {$locale} is not available.");
+ }
+ else
+ {
+ $actual = Utf8String::strcmp($string1, $string2, $locale);
+
+ if ($actual != 0)
+ {
+ $actual = $actual / abs($actual);
+ }
+
+ $this->assertEquals($expect, $actual);
+ }
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $haystack @todo
+ * @param string $needles @todo
+ * @param integer $start @todo
+ * @param integer $len @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::strcspn
+ * @dataProvider seedTestStrcspn
+ * @since 2.0
+ */
+ public function testStrcspn($haystack, $needles, $start, $len, $expect)
+ {
+ $actual = Utf8String::strcspn($haystack, $needles, $start, $len);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $haystack @todo
+ * @param string $needle @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::stristr
+ * @dataProvider seedTestStristr
+ * @since 2.0
+ */
+ public function testStristr($haystack, $needle, $expect)
+ {
+ $actual = Utf8String::stristr($haystack, $needle);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::strrev
+ * @dataProvider seedTestStrrev
+ * @since 2.0
+ */
+ public function testStrrev($string, $expect)
+ {
+ $actual = Utf8String::strrev($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $subject @todo
+ * @param string $mask @todo
+ * @param integer $start @todo
+ * @param integer $length @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::strspn
+ * @dataProvider seedTestStrspn
+ * @since 2.0
+ */
+ public function testStrspn($subject, $mask, $start, $length, $expect)
+ {
+ $actual = Utf8String::strspn($subject, $mask, $start, $length);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $expect @todo
+ * @param string $string @todo
+ * @param string $replacement @todo
+ * @param integer $start @todo
+ * @param integer $length @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::substr_replace
+ * @dataProvider seedTestSubstr_replace
+ * @since 2.0
+ */
+ public function testSubstr_replace($expect, $string, $replacement, $start, $length)
+ {
+ $actual = Utf8String::substr_replace($string, $replacement, $start, $length);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $charlist @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::ltrim
+ * @dataProvider seedTestLtrim
+ * @since 2.0
+ */
+ public function testLtrim($string, $charlist, $expect)
+ {
+ if ($charlist === null)
+ {
+ $actual = Utf8String::ltrim($string);
+ }
+ else
+ {
+ $actual = Utf8String::ltrim($string, $charlist);
+ }
+
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $charlist @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::rtrim
+ * @dataProvider seedTestRtrim
+ * @since 2.0
+ */
+ public function testRtrim($string, $charlist, $expect)
+ {
+ if ($charlist === null)
+ {
+ $actual = Utf8String::rtrim($string);
+ }
+ else
+ {
+ $actual = Utf8String::rtrim($string, $charlist);
+ }
+
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $charlist @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::trim
+ * @dataProvider seedTestTrim
+ * @since 2.0
+ */
+ public function testTrim($string, $charlist, $expect)
+ {
+ if ($charlist === null)
+ {
+ $actual = Utf8String::trim($string);
+ }
+ else
+ {
+ $actual = Utf8String::trim($string, $charlist);
+ }
+
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $delimiter @todo
+ * @param string $newDelimiter @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::ucfirst
+ * @dataProvider seedTestUcfirst
+ * @since 2.0
+ */
+ public function testUcfirst($string, $delimiter, $newDelimiter, $expect)
+ {
+ $actual = Utf8String::ucfirst($string, $delimiter, $newDelimiter);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::ucwords
+ * @dataProvider seedTestUcwords
+ * @since 2.0
+ */
+ public function testUcwords($string, $expect)
+ {
+ $actual = Utf8String::ucwords($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $source @todo
+ * @param string $from_encoding @todo
+ * @param string $to_encoding @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::transcode
+ * @dataProvider seedTestTranscode
+ * @since 2.0
+ */
+ public function testTranscode($source, $from_encoding, $to_encoding, $expect)
+ {
+ $actual = Utf8String::transcode($source, $from_encoding, $to_encoding);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::valid
+ * @dataProvider seedTestValid
+ * @since 2.0
+ */
+ public function testValid($string, $expect)
+ {
+ $actual = Utf8String::valid($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::unicode_to_utf8
+ * @dataProvider seedTestUnicodeToUtf8
+ * @since 2.0
+ */
+ public function testUnicodeToUtf8($string, $expect)
+ {
+ $actual = Utf8String::unicode_to_utf8($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::unicode_to_utf16
+ * @dataProvider seedTestUnicodeToUtf16
+ * @since 2.0
+ */
+ public function testUnicodeToUtf16($string, $expect)
+ {
+ $actual = Utf8String::unicode_to_utf16($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Windwalker\String\Utf8String::compliant
+ * @dataProvider seedTestValid
+ * @since 2.0
+ */
+ public function testCompliant($string, $expect)
+ {
+ $actual = Utf8String::compliant($string);
+ $this->assertEquals($expect, $actual);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/Utf8String.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/Utf8String.php
new file mode 100644
index 00000000..8dc4199d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/Utf8String.php
@@ -0,0 +1,802 @@
+='))
+{
+ @ini_set('default_charset', 'UTF-8');
+}
+else
+{
+ // Check if mbstring extension is loaded and attempt to load it if not present except for windows
+ if (extension_loaded('mbstring'))
+ {
+ @ini_set('mbstring.internal_encoding', 'UTF-8');
+ @ini_set('mbstring.http_input', 'UTF-8');
+ @ini_set('mbstring.http_output', 'UTF-8');
+ }
+ // Same for iconv
+ if (function_exists('iconv'))
+ {
+ iconv_set_encoding('internal_encoding', 'UTF-8');
+ iconv_set_encoding('input_encoding', 'UTF-8');
+ iconv_set_encoding('output_encoding', 'UTF-8');
+ }
+}
+
+/**
+ * Include the utf8 package
+ */
+if (!defined('UTF8'))
+{
+ require_once __DIR__ . '/phputf8/utf8.php';
+}
+
+if (!function_exists('utf8_strcasecmp'))
+{
+ require_once __DIR__ . '/phputf8/strcasecmp.php';
+}
+
+/**
+ * String handling class for utf-8 data
+ * Wraps the phputf8 library
+ * All functions assume the validity of utf-8 strings.
+ *
+ * This class is based on Joomla String package
+ *
+ * @since 2.0
+ */
+abstract class Utf8String
+{
+ /**
+ * Tests whether a string contains only 7bit ASCII bytes.
+ * You might use this to conditionally check whether a string
+ * needs handling as UTF-8 or not, potentially offering performance
+ * benefits by using the native PHP equivalent if it's just ASCII e.g.;
+ *
+ * ``` php
+ * if (String::is_ascii($someString))
+ * {
+ * // It's just ASCII - use the native PHP version
+ * $someString = strtolower($someString);
+ * }
+ * else
+ * {
+ * $someString = String::strtolower($someString);
+ * }
+ * ```
+ *
+ * @param string $str The string to test.
+ *
+ * @return boolean True if the string is all ASCII
+ *
+ * @since 2.0
+ */
+ public static function is_ascii($str)
+ {
+ // Search for any bytes which are outside the ASCII range...
+ return (preg_match('/(?:[^\x00-\x7F])/', $str) !== 1);
+ }
+
+ /**
+ * UTF-8 aware alternative to strpos.
+ *
+ * Find position of first occurrence of a string.
+ *
+ * @param string $str String being examined
+ * @param string $search String being searched for
+ * @param integer $offset Optional, specifies the position from which the search should be performed
+ *
+ * @return mixed Number of characters before the first match or FALSE on failure
+ *
+ * @see http://www.php.net/strpos
+ * @since 2.0
+ */
+ public static function strpos($str, $search, $offset = false)
+ {
+ if ($offset === false)
+ {
+ return utf8_strpos($str, $search);
+ }
+
+ return utf8_strpos($str, $search, $offset);
+ }
+
+ /**
+ * UTF-8 aware alternative to strrpos
+ * Finds position of last occurrence of a string
+ *
+ * @param string $str String being examined.
+ * @param string $search String being searched for.
+ * @param integer $offset Offset from the left of the string.
+ *
+ * @return mixed Number of characters before the last match or false on failure
+ *
+ * @see http://www.php.net/strrpos
+ * @since 2.0
+ */
+ public static function strrpos($str, $search, $offset = 0)
+ {
+ return utf8_strrpos($str, $search, $offset);
+ }
+
+ /**
+ * UTF-8 aware alternative to substr
+ * Return part of a string given character offset (and optionally length)
+ *
+ * @param string $str String being processed
+ * @param integer $offset Number of UTF-8 characters offset (from left)
+ * @param integer $length Optional length in UTF-8 characters from offset
+ *
+ * @return mixed string or FALSE if failure
+ *
+ * @see http://www.php.net/substr
+ * @since 2.0
+ */
+ public static function substr($str, $offset, $length = false)
+ {
+ if ($length === false)
+ {
+ return utf8_substr($str, $offset);
+ }
+
+ return utf8_substr($str, $offset, $length);
+ }
+
+ /**
+ * UTF-8 aware alternative to strtlower
+ *
+ * Make a string lowercase
+ * Note: The concept of a characters "case" only exists is some alphabets
+ * such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does
+ * not exist in the Chinese alphabet, for example. See Unicode Standard
+ * Annex #21: Case Mappings
+ *
+ * @param string $str String being processed
+ *
+ * @return mixed Either string in lowercase or FALSE is UTF-8 invalid
+ *
+ * @see http://www.php.net/strtolower
+ * @since 2.0
+ */
+ public static function strtolower($str)
+ {
+ return utf8_strtolower($str);
+ }
+
+ /**
+ * UTF-8 aware alternative to strtoupper
+ * Make a string uppercase
+ * Note: The concept of a characters "case" only exists is some alphabets
+ * such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does
+ * not exist in the Chinese alphabet, for example. See Unicode Standard
+ * Annex #21: Case Mappings
+ *
+ * @param string $str String being processed
+ *
+ * @return mixed Either string in uppercase or FALSE is UTF-8 invalid
+ *
+ * @see http://www.php.net/strtoupper
+ * @since 2.0
+ */
+ public static function strtoupper($str)
+ {
+ return utf8_strtoupper($str);
+ }
+
+ /**
+ * UTF-8 aware alternative to strlen.
+ *
+ * Returns the number of characters in the string (NOT THE NUMBER OF BYTES),
+ *
+ * @param string $str UTF-8 string.
+ *
+ * @return integer Number of UTF-8 characters in string.
+ *
+ * @see http://www.php.net/strlen
+ * @since 2.0
+ */
+ public static function strlen($str)
+ {
+ return utf8_strlen($str);
+ }
+
+ /**
+ * UTF-8 aware alternative to str_ireplace
+ * Case-insensitive version of str_replace
+ *
+ * @param string $search String to search
+ * @param string $replace Existing string to replace
+ * @param string $str New string to replace with
+ * @param integer $count Optional count value to be passed by reference
+ *
+ * @return string UTF-8 String
+ *
+ * @see http://www.php.net/str_ireplace
+ * @since 2.0
+ */
+ public static function str_ireplace($search, $replace, $str, $count = null)
+ {
+ if (!function_exists('utf8_ireplace'))
+ {
+ require_once __DIR__ . '/phputf8/str_ireplace.php';
+ }
+
+ if ($count === null)
+ {
+ return utf8_ireplace($search, $replace, $str);
+ }
+
+ return utf8_ireplace($search, $replace, $str, $count);
+ }
+
+ /**
+ * UTF-8 aware alternative to str_split
+ * Convert a string to an array
+ *
+ * @param string $str UTF-8 encoded string to process
+ * @param integer $split_len Number to characters to split string by
+ *
+ * @return array
+ *
+ * @see http://www.php.net/str_split
+ * @since 2.0
+ */
+ public static function str_split($str, $split_len = 1)
+ {
+ if (!function_exists('utf8_str_split'))
+ {
+ require_once __DIR__ . '/phputf8/str_split.php';
+ }
+
+ return utf8_str_split($str, $split_len);
+ }
+
+ /**
+ * UTF-8/LOCALE aware alternative to strcasecmp
+ * A case insensitive string comparison
+ *
+ * @param string $str1 string 1 to compare
+ * @param string $str2 string 2 to compare
+ * @param mixed $locale The locale used by strcoll or false to use classical comparison
+ *
+ * @return integer < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.
+ *
+ * @see http://www.php.net/strcasecmp
+ * @see http://www.php.net/strcoll
+ * @see http://www.php.net/setlocale
+ * @since 2.0
+ */
+ public static function strcasecmp($str1, $str2, $locale = false)
+ {
+ if ($locale)
+ {
+ // Get current locale
+ $locale0 = setlocale(LC_COLLATE, 0);
+
+ if (!$locale = setlocale(LC_COLLATE, $locale))
+ {
+ $locale = $locale0;
+ }
+
+ // See if we have successfully set locale to UTF-8
+ if (!stristr($locale, 'UTF-8') && stristr($locale, '_') && preg_match('~\.(\d+)$~', $locale, $m))
+ {
+ $encoding = 'CP' . $m[1];
+ }
+ elseif (stristr($locale, 'UTF-8') || stristr($locale, 'utf8'))
+ {
+ $encoding = 'UTF-8';
+ }
+ else
+ {
+ $encoding = 'nonrecodable';
+ }
+
+ // If we successfully set encoding it to utf-8 or encoding is sth weird don't recode
+ if ($encoding == 'UTF-8' || $encoding == 'nonrecodable')
+ {
+ return strcoll(utf8_strtolower($str1), utf8_strtolower($str2));
+ }
+
+ return strcoll(
+ self::transcode(utf8_strtolower($str1), 'UTF-8', $encoding),
+ self::transcode(utf8_strtolower($str2), 'UTF-8', $encoding)
+ );
+ }
+
+ return utf8_strcasecmp($str1, $str2);
+ }
+
+ /**
+ * UTF-8/LOCALE aware alternative to strcmp
+ * A case sensitive string comparison
+ *
+ * @param string $str1 string 1 to compare
+ * @param string $str2 string 2 to compare
+ * @param mixed $locale The locale used by strcoll or false to use classical comparison
+ *
+ * @return integer < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.
+ *
+ * @see http://www.php.net/strcmp
+ * @see http://www.php.net/strcoll
+ * @see http://www.php.net/setlocale
+ * @since 2.0
+ */
+ public static function strcmp($str1, $str2, $locale = false)
+ {
+ if ($locale)
+ {
+ // Get current locale
+ $locale0 = setlocale(LC_COLLATE, 0);
+
+ if (!$locale = setlocale(LC_COLLATE, $locale))
+ {
+ $locale = $locale0;
+ }
+
+ // See if we have successfully set locale to UTF-8
+ if (!stristr($locale, 'UTF-8') && stristr($locale, '_') && preg_match('~\.(\d+)$~', $locale, $m))
+ {
+ $encoding = 'CP' . $m[1];
+ }
+ elseif (stristr($locale, 'UTF-8') || stristr($locale, 'utf8'))
+ {
+ $encoding = 'UTF-8';
+ }
+ else
+ {
+ $encoding = 'nonrecodable';
+ }
+
+ // If we successfully set encoding it to utf-8 or encoding is sth weird don't recode
+ if ($encoding == 'UTF-8' || $encoding == 'nonrecodable')
+ {
+ return strcoll($str1, $str2);
+ }
+
+ return strcoll(static::transcode($str1, 'UTF-8', $encoding), static::transcode($str2, 'UTF-8', $encoding));
+ }
+
+ return strcmp($str1, $str2);
+ }
+
+ /**
+ * UTF-8 aware alternative to strcspn
+ * Find length of initial segment not matching mask
+ *
+ * @param string $str The string to process
+ * @param string $mask The mask
+ * @param integer $start Optional starting character position (in characters)
+ * @param integer $length Optional length
+ *
+ * @return integer The length of the initial segment of str1 which does not contain any of the characters in str2
+ *
+ * @see http://www.php.net/strcspn
+ * @since 2.0
+ */
+ public static function strcspn($str, $mask, $start = null, $length = null)
+ {
+ if (!function_exists('utf8_strcspn'))
+ {
+ require_once __DIR__ . '/phputf8/strcspn.php';
+ }
+
+ if ($start === null && $length === null)
+ {
+ return utf8_strcspn($str, $mask);
+ }
+
+ if ($length === null)
+ {
+ return utf8_strcspn($str, $mask, $start);
+ }
+
+ return utf8_strcspn($str, $mask, $start, $length);
+ }
+
+ /**
+ * UTF-8 aware alternative to stristr
+ * Returns all of haystack from the first occurrence of needle to the end.
+ * needle and haystack are examined in a case-insensitive manner
+ * Find first occurrence of a string using case insensitive comparison
+ *
+ * @param string $str The haystack
+ * @param string $search The needle
+ *
+ * @return string the sub string
+ *
+ * @see http://www.php.net/stristr
+ * @since 2.0
+ */
+ public static function stristr($str, $search)
+ {
+ if (!function_exists('utf8_stristr'))
+ {
+ require_once __DIR__ . '/phputf8/stristr.php';
+ }
+
+ return utf8_stristr($str, $search);
+ }
+
+ /**
+ * UTF-8 aware alternative to strrev
+ * Reverse a string
+ *
+ * @param string $str String to be reversed
+ *
+ * @return string The string in reverse character order
+ *
+ * @see http://www.php.net/strrev
+ * @since 2.0
+ */
+ public static function strrev($str)
+ {
+ if (!function_exists('utf8_strrev'))
+ {
+ require_once __DIR__ . '/phputf8/strrev.php';
+ }
+
+ return utf8_strrev($str);
+ }
+
+ /**
+ * UTF-8 aware alternative to strspn
+ * Find length of initial segment matching mask
+ *
+ * @param string $str The haystack
+ * @param string $mask The mask
+ * @param integer $start Start optional
+ * @param integer $length Length optional
+ *
+ * @return integer
+ *
+ * @see http://www.php.net/strspn
+ * @since 2.0
+ */
+ public static function strspn($str, $mask, $start = null, $length = null)
+ {
+ if (!function_exists('utf8_strspn'))
+ {
+ require_once __DIR__ . '/phputf8/strspn.php';
+ }
+
+ if ($start === null && $length === null)
+ {
+ return utf8_strspn($str, $mask);
+ }
+
+ if ($length === null)
+ {
+ return utf8_strspn($str, $mask, $start);
+ }
+
+ return utf8_strspn($str, $mask, $start, $length);
+ }
+
+ /**
+ * UTF-8 aware substr_replace
+ * Replace text within a portion of a string
+ *
+ * @param string $str The haystack
+ * @param string $repl The replacement string
+ * @param integer $start Start
+ * @param integer $length Length (optional)
+ *
+ * @return string
+ *
+ * @see http://www.php.net/substr_replace
+ * @since 2.0
+ */
+ public static function substr_replace($str, $repl, $start, $length = null)
+ {
+ // Loaded by library loader
+ if ($length === null)
+ {
+ return utf8_substr_replace($str, $repl, $start);
+ }
+
+ return utf8_substr_replace($str, $repl, $start, $length);
+ }
+
+ /**
+ * UTF-8 aware replacement for ltrim()
+ *
+ * Strip whitespace (or other characters) from the beginning of a string
+ * You only need to use this if you are supplying the charlist
+ * optional arg and it contains UTF-8 characters. Otherwise ltrim will
+ * work normally on a UTF-8 string
+ *
+ * @param string $str The string to be trimmed
+ * @param string $charlist The optional charlist of additional characters to trim
+ *
+ * @return string The trimmed string
+ *
+ * @see http://www.php.net/ltrim
+ * @since 2.0
+ */
+ public static function ltrim($str, $charlist = null)
+ {
+ if (empty($charlist) && $charlist !== null)
+ {
+ return $str;
+ }
+
+ if (!function_exists('utf8_ltrim'))
+ {
+ require_once __DIR__ . '/phputf8/trim.php';
+ }
+
+ if ($charlist === null)
+ {
+ return utf8_ltrim($str);
+ }
+
+ return utf8_ltrim($str, $charlist);
+ }
+
+ /**
+ * UTF-8 aware replacement for rtrim()
+ * Strip whitespace (or other characters) from the end of a string
+ * You only need to use this if you are supplying the charlist
+ * optional arg and it contains UTF-8 characters. Otherwise rtrim will
+ * work normally on a UTF-8 string
+ *
+ * @param string $str The string to be trimmed
+ * @param string $charlist The optional charlist of additional characters to trim
+ *
+ * @return string The trimmed string
+ *
+ * @see http://www.php.net/rtrim
+ * @since 2.0
+ */
+ public static function rtrim($str, $charlist = null)
+ {
+ if (empty($charlist) && $charlist !== null)
+ {
+ return $str;
+ }
+
+ if (!function_exists('utf8_rtrim'))
+ {
+ require_once __DIR__ . '/phputf8/trim.php';
+ }
+
+ if ($charlist === null)
+ {
+ return utf8_rtrim($str);
+ }
+
+ return utf8_rtrim($str, $charlist);
+ }
+
+ /**
+ * UTF-8 aware replacement for trim()
+ * Strip whitespace (or other characters) from the beginning and end of a string
+ * Note: you only need to use this if you are supplying the charlist
+ * optional arg and it contains UTF-8 characters. Otherwise trim will
+ * work normally on a UTF-8 string
+ *
+ * @param string $str The string to be trimmed
+ * @param string $charlist The optional charlist of additional characters to trim
+ *
+ * @return string The trimmed string
+ *
+ * @see http://www.php.net/trim
+ * @since 2.0
+ */
+ public static function trim($str, $charlist = null)
+ {
+ if (empty($charlist) && $charlist !== null)
+ {
+ return $str;
+ }
+
+ if (!function_exists('utf8_trim'))
+ {
+ require_once __DIR__ . '/phputf8/trim.php';
+ }
+
+ if ($charlist === null)
+ {
+ return utf8_trim($str);
+ }
+
+ return utf8_trim($str, $charlist);
+ }
+
+ /**
+ * UTF-8 aware alternative to ucfirst
+ * Make a string's first character uppercase or all words' first character uppercase
+ *
+ * @param string $str String to be processed
+ * @param string $delimiter The words delimiter (null means do not split the string)
+ * @param string $newDelimiter The new words delimiter (null means equal to $delimiter)
+ *
+ * @return string If $delimiter is null, return the string with first character as upper case (if applicable)
+ * else consider the string of words separated by the delimiter, apply the ucfirst to each words
+ * and return the string with the new delimiter
+ *
+ * @see http://www.php.net/ucfirst
+ * @since 2.0
+ */
+ public static function ucfirst($str, $delimiter = null, $newDelimiter = null)
+ {
+ if (!function_exists('utf8_ucfirst'))
+ {
+ require_once __DIR__ . '/phputf8/ucfirst.php';
+ }
+
+ if ($delimiter === null)
+ {
+ return utf8_ucfirst($str);
+ }
+
+ if ($newDelimiter === null)
+ {
+ $newDelimiter = $delimiter;
+ }
+
+ return implode($newDelimiter, array_map('utf8_ucfirst', explode($delimiter, $str)));
+ }
+
+ /**
+ * UTF-8 aware alternative to ucwords
+ * Uppercase the first character of each word in a string
+ *
+ * @param string $str String to be processed
+ *
+ * @return string String with first char of each word uppercase
+ *
+ * @see http://www.php.net/ucwords
+ * @since 2.0
+ */
+ public static function ucwords($str)
+ {
+ if (!function_exists('utf8_ucwords'))
+ {
+ require_once __DIR__ . '/phputf8/ucwords.php';
+ }
+
+ return utf8_ucwords($str);
+ }
+
+ /**
+ * Transcode a string.
+ *
+ * @param string $source The string to transcode.
+ * @param string $from_encoding The source encoding.
+ * @param string $to_encoding The target encoding.
+ *
+ * @return mixed The transcoded string, or null if the source was not a string.
+ *
+ * @link https://bugs.php.net/bug.php?id=48147
+ *
+ * @since 2.0
+ */
+ public static function transcode($source, $from_encoding, $to_encoding)
+ {
+ if (is_string($source))
+ {
+ $function = function_exists('mb_iconv') ? 'mb_iconv' : 'iconv';
+
+ switch (ICONV_IMPL)
+ {
+ case 'glibc':
+ return @$function($from_encoding, $to_encoding . '//TRANSLIT,IGNORE', $source);
+
+ case 'libiconv':
+ default:
+ return $function($from_encoding, $to_encoding . '//IGNORE//TRANSLIT', $source);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Tests a string as to whether it's valid UTF-8 and supported by the Unicode standard.
+ *
+ * Note: this function has been modified to simple return true or false.
+ *
+ * @param string $str UTF-8 encoded string.
+ *
+ * @return boolean true if valid
+ *
+ * @author
+ * @see http://hsivonen.iki.fi/php-utf8/
+ * @see compliant
+ * @since 2.0
+ */
+ public static function valid($str)
+ {
+ require_once __DIR__ . '/phputf8/utils/validation.php';
+
+ return utf8_is_valid($str);
+ }
+
+ /**
+ * Tests whether a string complies as UTF-8. This will be much
+ * faster than utf8_is_valid but will pass five and six octet
+ * UTF-8 sequences, which are not supported by Unicode and
+ * so cannot be displayed correctly in a browser. In other words
+ * it is not as strict as utf8_is_valid but it's faster. If you use
+ * it to validate user input, you place yourself at the risk that
+ * attackers will be able to inject 5 and 6 byte sequences (which
+ * may or may not be a significant risk, depending on what you are
+ * are doing)
+ *
+ * @param string $str UTF-8 string to check
+ *
+ * @return boolean TRUE if string is valid UTF-8
+ *
+ * @see valid
+ * @see http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php#54805
+ * @since 2.0
+ */
+ public static function compliant($str)
+ {
+ require_once __DIR__ . '/phputf8/utils/validation.php';
+
+ return utf8_compliant($str);
+ }
+
+ /**
+ * Converts Unicode sequences to UTF-8 string
+ *
+ * @param string $str Unicode string to convert
+ *
+ * @return string UTF-8 string
+ *
+ * @since 2.0
+ */
+ public static function unicode_to_utf8($str)
+ {
+ if (extension_loaded('mbstring'))
+ {
+ return preg_replace_callback(
+ '/\\\\u([0-9a-fA-F]{4})/',
+ function ($match)
+ {
+ return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UCS-2BE');
+ },
+ $str
+ );
+ }
+
+ return $str;
+ }
+
+ /**
+ * Converts Unicode sequences to UTF-16 string
+ *
+ * @param string $str Unicode string to convert
+ *
+ * @return string UTF-16 string
+ *
+ * @since 2.0
+ */
+ public static function unicode_to_utf16($str)
+ {
+ if (extension_loaded('mbstring'))
+ {
+ return preg_replace_callback(
+ '/\\\\u([0-9a-fA-F]{4})/',
+ function ($match)
+ {
+ return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UTF-16BE');
+ },
+ $str
+ );
+ }
+
+ return $str;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/composer.json b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/composer.json
new file mode 100644
index 00000000..8a493285
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/composer.json
@@ -0,0 +1,29 @@
+{
+ "name": "windwalker/string",
+ "type": "windwalker-package",
+ "description": "Windwalker String package",
+ "keywords": ["windwalker", "framework", "string"],
+ "homepage": "https://github.com/ventoviro/windwalker-string",
+ "license": "LGPL-2.0+",
+ "require": {
+ "php": ">=5.3.10"
+ },
+ "require-dev": {
+ "windwalker/test": "~2.0",
+ "windwalker/utilities": "~2.0"
+ },
+ "suggest": {
+ "windwalker/utilities": "Install 2.* if you want to use StringHelper::parseVariable() tmpl engine."
+ },
+ "minimum-stability": "beta",
+ "autoload": {
+ "psr-4": {
+ "Windwalker\\String\\": ""
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phpunit.travis.xml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phpunit.travis.xml
new file mode 100644
index 00000000..690ec926
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phpunit.travis.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phpunit.xml.dist b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phpunit.xml.dist
new file mode 100644
index 00000000..94b6811c
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phpunit.xml.dist
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/LICENSE b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/LICENSE
new file mode 100644
index 00000000..28f18896
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/LICENSE
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ , 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/README b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/README
new file mode 100644
index 00000000..6c309054
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/README
@@ -0,0 +1,82 @@
+++PHP UTF-8++
+
+Version 0.5
+
+++DOCUMENTATION++
+
+Documentation in progress in ./docs dir
+
+http://www.phpwact.org/php/i18n/charsets
+http://www.phpwact.org/php/i18n/utf-8
+
+Important Note: DO NOT use these functions without understanding WHY
+you are using them. In particular, do not blindly replace all use of PHP's
+string functions which functions found here - most of the time you will
+not need to, and you will be introducing a significant performance
+overhead to your application. You can get a good idea of when to use what
+from reading: http://www.phpwact.org/php/i18n/utf-8
+
+Important Note: For sake of performance most of the functions here are
+not "defensive" (e.g. there is not extensive parameter checking, well
+formed UTF-8 is assumed). This is particularily relevant when is comes to
+catching badly formed UTF-8 - you should screen input on the "outer
+perimeter" with help from functions in the utf8_validation.php and
+utf8_bad.php files.
+
+Important Note: this library treats ALL ASCII characters as valid, including ASCII control characters. But if you use some ASCII control characters in XML, it will render the XML ill-formed. Don't be a bozo: http://hsivonen.iki.fi/producing-xml/#controlchar
+
+++BUGS / SUPPORT / FEATURE REQUESTS ++
+
+Please report bugs to:
+http://sourceforge.net/tracker/?group_id=142846&atid=753842
+- if you are able, please submit a failing unit test
+(http://www.lastcraft.com/simple_test.php) with your bug report.
+
+For feature requests / faster implementation of functions found here,
+please drop them in via the RFE tracker: http://sourceforge.net/tracker/?group_id=142846&atid=753845
+Particularily interested in faster implementations!
+
+For general support / help, use:
+http://sourceforge.net/tracker/?group_id=142846&atid=753843
+
+In the VERY WORST case, you can email me: hfuecks gmail com - I tend to be slow to respond though so be warned.
+
+Important Note: when reporting bugs, please provide the following
+information;
+
+PHP version, whether the iconv extension is loaded (in PHP5 it's
+there by default), whether the mbstring extension is loaded. The
+following PHP script can be used to determine this information;
+
+";
+if ( extension_loaded('mbstring') ) {
+ print "mbstring available ";
+} else {
+ print "mbstring not available ";
+}
+if ( extension_loaded('iconv') ) {
+ print "iconv available ";
+} else {
+ print "iconv not available ";
+}
+?>
+
+++LICENSING++
+
+Parts of the code in this library come from other places, under different
+licenses.
+The authors involved have been contacted (see below). Attribution for
+which code came from elsewhere can be found in the source code itself.
+
++Andreas Gohr / Chris Smith - Dokuwiki
+There is a fair degree of collaboration / exchange of ideas and code
+beteen Dokuwiki's UTF-8 library;
+http://dev.splitbrain.org/view/darcs/dokuwiki/inc/utf8.php
+and phputf8. Although Dokuwiki is released under GPL, its UTF-8
+library is released under LGPL, hence no conflict with phputf8
+
++Henri Sivonen (http://hsivonen.iki.fi/php-utf8/ /
+http://hsivonen.iki.fi/php-utf8/) has also given permission for his
+code to be released under the terms of the LGPL. He ported a Unicode / UTF-8
+converter from the Mozilla codebase to PHP, which is re-used in phputf8
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/mbstring/core.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/mbstring/core.php
new file mode 100644
index 00000000..6e55eb29
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/mbstring/core.php
@@ -0,0 +1,135 @@
+
+* @link http://www.php.net/manual/en/function.strlen.php
+* @link http://www.php.net/manual/en/function.utf8-decode.php
+* @param string UTF-8 string
+* @return int number of UTF-8 characters in string
+* @package utf8
+*/
+function utf8_strlen($str){
+ return strlen(utf8_decode($str));
+}
+
+
+//--------------------------------------------------------------------
+/**
+* UTF-8 aware alternative to strpos
+* Find position of first occurrence of a string
+* Note: This will get alot slower if offset is used
+* Note: requires utf8_strlen amd utf8_substr to be loaded
+* @param string haystack
+* @param string needle (you should validate this with utf8_is_valid)
+* @param integer offset in characters (from left)
+* @return mixed integer position or FALSE on failure
+* @see http://www.php.net/strpos
+* @see utf8_strlen
+* @see utf8_substr
+* @package utf8
+*/
+function utf8_strpos($str, $needle, $offset = NULL) {
+
+ if ( is_null($offset) ) {
+
+ $ar = explode($needle, $str, 2);
+ if ( count($ar) > 1 ) {
+ return utf8_strlen($ar[0]);
+ }
+ return FALSE;
+
+ } else {
+
+ if ( !is_int($offset) ) {
+ trigger_error('utf8_strpos: Offset must be an integer',E_USER_ERROR);
+ return FALSE;
+ }
+
+ $str = utf8_substr($str, $offset);
+
+ if ( FALSE !== ( $pos = utf8_strpos($str, $needle) ) ) {
+ return $pos + $offset;
+ }
+
+ return FALSE;
+ }
+
+}
+
+//--------------------------------------------------------------------
+/**
+* UTF-8 aware alternative to strrpos
+* Find position of last occurrence of a char in a string
+* Note: This will get alot slower if offset is used
+* Note: requires utf8_substr and utf8_strlen to be loaded
+* @param string haystack
+* @param string needle (you should validate this with utf8_is_valid)
+* @param integer (optional) offset (from left)
+* @return mixed integer position or FALSE on failure
+* @see http://www.php.net/strrpos
+* @see utf8_substr
+* @see utf8_strlen
+* @package utf8
+*/
+function utf8_strrpos($str, $needle, $offset = NULL) {
+
+ if ( is_null($offset) ) {
+
+ $ar = explode($needle, $str);
+
+ if ( count($ar) > 1 ) {
+ // Pop off the end of the string where the last match was made
+ array_pop($ar);
+ $str = join($needle,$ar);
+ return utf8_strlen($str);
+ }
+ return FALSE;
+
+ } else {
+
+ if ( !is_int($offset) ) {
+ trigger_error('utf8_strrpos expects parameter 3 to be long',E_USER_WARNING);
+ return FALSE;
+ }
+
+ $str = utf8_substr($str, $offset);
+
+ if ( FALSE !== ( $pos = utf8_strrpos($str, $needle) ) ) {
+ return $pos + $offset;
+ }
+
+ return FALSE;
+ }
+
+}
+
+//--------------------------------------------------------------------
+/**
+* UTF-8 aware alternative to substr
+* Return part of a string given character offset (and optionally length)
+*
+* Note arguments: comparied to substr - if offset or length are
+* not integers, this version will not complain but rather massages them
+* into an integer.
+*
+* Note on returned values: substr documentation states false can be
+* returned in some cases (e.g. offset > string length)
+* mb_substr never returns false, it will return an empty string instead.
+* This adopts the mb_substr approach
+*
+* Note on implementation: PCRE only supports repetitions of less than
+* 65536, in order to accept up to MAXINT values for offset and length,
+* we'll repeat a group of 65535 characters when needed.
+*
+* Note on implementation: calculating the number of characters in the
+* string is a relatively expensive operation, so we only carry it out when
+* necessary. It isn't necessary for +ve offsets and no specified length
+*
+* @author Chris Smith
+* @param string
+* @param integer number of UTF-8 characters offset (from left)
+* @param integer (optional) length in UTF-8 characters from offset
+* @return mixed string or FALSE if failure
+* @package utf8
+*/
+function utf8_substr($str, $offset, $length = NULL) {
+
+ // generates E_NOTICE
+ // for PHP4 objects, but not PHP5 objects
+ $str = (string)$str;
+ $offset = (int)$offset;
+ if (!is_null($length)) $length = (int)$length;
+
+ // handle trivial cases
+ if ($length === 0) return '';
+ if ($offset < 0 && $length < 0 && $length < $offset)
+ return '';
+
+ // normalise negative offsets (we could use a tail
+ // anchored pattern, but they are horribly slow!)
+ if ($offset < 0) {
+
+ // see notes
+ $strlen = strlen(utf8_decode($str));
+ $offset = $strlen + $offset;
+ if ($offset < 0) $offset = 0;
+
+ }
+
+ $Op = '';
+ $Lp = '';
+
+ // establish a pattern for offset, a
+ // non-captured group equal in length to offset
+ if ($offset > 0) {
+
+ $Ox = (int)($offset/65535);
+ $Oy = $offset%65535;
+
+ if ($Ox) {
+ $Op = '(?:.{65535}){'.$Ox.'}';
+ }
+
+ $Op = '^(?:'.$Op.'.{'.$Oy.'})';
+
+ } else {
+
+ // offset == 0; just anchor the pattern
+ $Op = '^';
+
+ }
+
+ // establish a pattern for length
+ if (is_null($length)) {
+
+ // the rest of the string
+ $Lp = '(.*)$';
+
+ } else {
+
+ if (!isset($strlen)) {
+ // see notes
+ $strlen = strlen(utf8_decode($str));
+ }
+
+ // another trivial case
+ if ($offset > $strlen) return '';
+
+ if ($length > 0) {
+
+ // reduce any length that would
+ // go passed the end of the string
+ $length = min($strlen-$offset, $length);
+
+ $Lx = (int)( $length / 65535 );
+ $Ly = $length % 65535;
+
+ // negative length requires a captured group
+ // of length characters
+ if ($Lx) $Lp = '(?:.{65535}){'.$Lx.'}';
+ $Lp = '('.$Lp.'.{'.$Ly.'})';
+
+ } else if ($length < 0) {
+
+ if ( $length < ($offset - $strlen) ) {
+ return '';
+ }
+
+ $Lx = (int)((-$length)/65535);
+ $Ly = (-$length)%65535;
+
+ // negative length requires ... capture everything
+ // except a group of -length characters
+ // anchored at the tail-end of the string
+ if ($Lx) $Lp = '(?:.{65535}){'.$Lx.'}';
+ $Lp = '(.*)(?:'.$Lp.'.{'.$Ly.'})$';
+
+ }
+
+ }
+
+ if (!preg_match( '#'.$Op.$Lp.'#us',$str, $match )) {
+ return '';
+ }
+
+ return $match[1];
+
+}
+
+//---------------------------------------------------------------
+/**
+* UTF-8 aware alternative to strtolower
+* Make a string lowercase
+* Note: The concept of a characters "case" only exists is some alphabets
+* such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does
+* not exist in the Chinese alphabet, for example. See Unicode Standard
+* Annex #21: Case Mappings
+* Note: requires utf8_to_unicode and utf8_from_unicode
+* @author Andreas Gohr
+* @param string
+* @return mixed either string in lowercase or FALSE is UTF-8 invalid
+* @see http://www.php.net/strtolower
+* @see utf8_to_unicode
+* @see utf8_from_unicode
+* @see http://www.unicode.org/reports/tr21/tr21-5.html
+* @see http://dev.splitbrain.org/view/darcs/dokuwiki/inc/utf8.php
+* @package utf8
+*/
+function utf8_strtolower($string){
+
+ static $UTF8_UPPER_TO_LOWER = NULL;
+
+ if ( is_null($UTF8_UPPER_TO_LOWER) ) {
+ $UTF8_UPPER_TO_LOWER = array(
+ 0x0041=>0x0061, 0x03A6=>0x03C6, 0x0162=>0x0163, 0x00C5=>0x00E5, 0x0042=>0x0062,
+ 0x0139=>0x013A, 0x00C1=>0x00E1, 0x0141=>0x0142, 0x038E=>0x03CD, 0x0100=>0x0101,
+ 0x0490=>0x0491, 0x0394=>0x03B4, 0x015A=>0x015B, 0x0044=>0x0064, 0x0393=>0x03B3,
+ 0x00D4=>0x00F4, 0x042A=>0x044A, 0x0419=>0x0439, 0x0112=>0x0113, 0x041C=>0x043C,
+ 0x015E=>0x015F, 0x0143=>0x0144, 0x00CE=>0x00EE, 0x040E=>0x045E, 0x042F=>0x044F,
+ 0x039A=>0x03BA, 0x0154=>0x0155, 0x0049=>0x0069, 0x0053=>0x0073, 0x1E1E=>0x1E1F,
+ 0x0134=>0x0135, 0x0427=>0x0447, 0x03A0=>0x03C0, 0x0418=>0x0438, 0x00D3=>0x00F3,
+ 0x0420=>0x0440, 0x0404=>0x0454, 0x0415=>0x0435, 0x0429=>0x0449, 0x014A=>0x014B,
+ 0x0411=>0x0431, 0x0409=>0x0459, 0x1E02=>0x1E03, 0x00D6=>0x00F6, 0x00D9=>0x00F9,
+ 0x004E=>0x006E, 0x0401=>0x0451, 0x03A4=>0x03C4, 0x0423=>0x0443, 0x015C=>0x015D,
+ 0x0403=>0x0453, 0x03A8=>0x03C8, 0x0158=>0x0159, 0x0047=>0x0067, 0x00C4=>0x00E4,
+ 0x0386=>0x03AC, 0x0389=>0x03AE, 0x0166=>0x0167, 0x039E=>0x03BE, 0x0164=>0x0165,
+ 0x0116=>0x0117, 0x0108=>0x0109, 0x0056=>0x0076, 0x00DE=>0x00FE, 0x0156=>0x0157,
+ 0x00DA=>0x00FA, 0x1E60=>0x1E61, 0x1E82=>0x1E83, 0x00C2=>0x00E2, 0x0118=>0x0119,
+ 0x0145=>0x0146, 0x0050=>0x0070, 0x0150=>0x0151, 0x042E=>0x044E, 0x0128=>0x0129,
+ 0x03A7=>0x03C7, 0x013D=>0x013E, 0x0422=>0x0442, 0x005A=>0x007A, 0x0428=>0x0448,
+ 0x03A1=>0x03C1, 0x1E80=>0x1E81, 0x016C=>0x016D, 0x00D5=>0x00F5, 0x0055=>0x0075,
+ 0x0176=>0x0177, 0x00DC=>0x00FC, 0x1E56=>0x1E57, 0x03A3=>0x03C3, 0x041A=>0x043A,
+ 0x004D=>0x006D, 0x016A=>0x016B, 0x0170=>0x0171, 0x0424=>0x0444, 0x00CC=>0x00EC,
+ 0x0168=>0x0169, 0x039F=>0x03BF, 0x004B=>0x006B, 0x00D2=>0x00F2, 0x00C0=>0x00E0,
+ 0x0414=>0x0434, 0x03A9=>0x03C9, 0x1E6A=>0x1E6B, 0x00C3=>0x00E3, 0x042D=>0x044D,
+ 0x0416=>0x0436, 0x01A0=>0x01A1, 0x010C=>0x010D, 0x011C=>0x011D, 0x00D0=>0x00F0,
+ 0x013B=>0x013C, 0x040F=>0x045F, 0x040A=>0x045A, 0x00C8=>0x00E8, 0x03A5=>0x03C5,
+ 0x0046=>0x0066, 0x00DD=>0x00FD, 0x0043=>0x0063, 0x021A=>0x021B, 0x00CA=>0x00EA,
+ 0x0399=>0x03B9, 0x0179=>0x017A, 0x00CF=>0x00EF, 0x01AF=>0x01B0, 0x0045=>0x0065,
+ 0x039B=>0x03BB, 0x0398=>0x03B8, 0x039C=>0x03BC, 0x040C=>0x045C, 0x041F=>0x043F,
+ 0x042C=>0x044C, 0x00DE=>0x00FE, 0x00D0=>0x00F0, 0x1EF2=>0x1EF3, 0x0048=>0x0068,
+ 0x00CB=>0x00EB, 0x0110=>0x0111, 0x0413=>0x0433, 0x012E=>0x012F, 0x00C6=>0x00E6,
+ 0x0058=>0x0078, 0x0160=>0x0161, 0x016E=>0x016F, 0x0391=>0x03B1, 0x0407=>0x0457,
+ 0x0172=>0x0173, 0x0178=>0x00FF, 0x004F=>0x006F, 0x041B=>0x043B, 0x0395=>0x03B5,
+ 0x0425=>0x0445, 0x0120=>0x0121, 0x017D=>0x017E, 0x017B=>0x017C, 0x0396=>0x03B6,
+ 0x0392=>0x03B2, 0x0388=>0x03AD, 0x1E84=>0x1E85, 0x0174=>0x0175, 0x0051=>0x0071,
+ 0x0417=>0x0437, 0x1E0A=>0x1E0B, 0x0147=>0x0148, 0x0104=>0x0105, 0x0408=>0x0458,
+ 0x014C=>0x014D, 0x00CD=>0x00ED, 0x0059=>0x0079, 0x010A=>0x010B, 0x038F=>0x03CE,
+ 0x0052=>0x0072, 0x0410=>0x0430, 0x0405=>0x0455, 0x0402=>0x0452, 0x0126=>0x0127,
+ 0x0136=>0x0137, 0x012A=>0x012B, 0x038A=>0x03AF, 0x042B=>0x044B, 0x004C=>0x006C,
+ 0x0397=>0x03B7, 0x0124=>0x0125, 0x0218=>0x0219, 0x00DB=>0x00FB, 0x011E=>0x011F,
+ 0x041E=>0x043E, 0x1E40=>0x1E41, 0x039D=>0x03BD, 0x0106=>0x0107, 0x03AB=>0x03CB,
+ 0x0426=>0x0446, 0x00DE=>0x00FE, 0x00C7=>0x00E7, 0x03AA=>0x03CA, 0x0421=>0x0441,
+ 0x0412=>0x0432, 0x010E=>0x010F, 0x00D8=>0x00F8, 0x0057=>0x0077, 0x011A=>0x011B,
+ 0x0054=>0x0074, 0x004A=>0x006A, 0x040B=>0x045B, 0x0406=>0x0456, 0x0102=>0x0103,
+ 0x039B=>0x03BB, 0x00D1=>0x00F1, 0x041D=>0x043D, 0x038C=>0x03CC, 0x00C9=>0x00E9,
+ 0x00D0=>0x00F0, 0x0407=>0x0457, 0x0122=>0x0123,
+ );
+ }
+
+ $uni = utf8_to_unicode($string);
+
+ if ( !$uni ) {
+ return FALSE;
+ }
+
+ $cnt = count($uni);
+ for ($i=0; $i < $cnt; $i++){
+ if ( isset($UTF8_UPPER_TO_LOWER[$uni[$i]]) ) {
+ $uni[$i] = $UTF8_UPPER_TO_LOWER[$uni[$i]];
+ }
+ }
+
+ return utf8_from_unicode($uni);
+}
+
+//---------------------------------------------------------------
+/**
+* UTF-8 aware alternative to strtoupper
+* Make a string uppercase
+* Note: The concept of a characters "case" only exists is some alphabets
+* such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does
+* not exist in the Chinese alphabet, for example. See Unicode Standard
+* Annex #21: Case Mappings
+* Note: requires utf8_to_unicode and utf8_from_unicode
+* @author Andreas Gohr
+* @param string
+* @return mixed either string in lowercase or FALSE is UTF-8 invalid
+* @see http://www.php.net/strtoupper
+* @see utf8_to_unicode
+* @see utf8_from_unicode
+* @see http://www.unicode.org/reports/tr21/tr21-5.html
+* @see http://dev.splitbrain.org/view/darcs/dokuwiki/inc/utf8.php
+* @package utf8
+*/
+function utf8_strtoupper($string){
+
+ static $UTF8_LOWER_TO_UPPER = NULL;
+
+ if ( is_null($UTF8_LOWER_TO_UPPER) ) {
+ $UTF8_LOWER_TO_UPPER = array(
+ 0x0061=>0x0041, 0x03C6=>0x03A6, 0x0163=>0x0162, 0x00E5=>0x00C5, 0x0062=>0x0042,
+ 0x013A=>0x0139, 0x00E1=>0x00C1, 0x0142=>0x0141, 0x03CD=>0x038E, 0x0101=>0x0100,
+ 0x0491=>0x0490, 0x03B4=>0x0394, 0x015B=>0x015A, 0x0064=>0x0044, 0x03B3=>0x0393,
+ 0x00F4=>0x00D4, 0x044A=>0x042A, 0x0439=>0x0419, 0x0113=>0x0112, 0x043C=>0x041C,
+ 0x015F=>0x015E, 0x0144=>0x0143, 0x00EE=>0x00CE, 0x045E=>0x040E, 0x044F=>0x042F,
+ 0x03BA=>0x039A, 0x0155=>0x0154, 0x0069=>0x0049, 0x0073=>0x0053, 0x1E1F=>0x1E1E,
+ 0x0135=>0x0134, 0x0447=>0x0427, 0x03C0=>0x03A0, 0x0438=>0x0418, 0x00F3=>0x00D3,
+ 0x0440=>0x0420, 0x0454=>0x0404, 0x0435=>0x0415, 0x0449=>0x0429, 0x014B=>0x014A,
+ 0x0431=>0x0411, 0x0459=>0x0409, 0x1E03=>0x1E02, 0x00F6=>0x00D6, 0x00F9=>0x00D9,
+ 0x006E=>0x004E, 0x0451=>0x0401, 0x03C4=>0x03A4, 0x0443=>0x0423, 0x015D=>0x015C,
+ 0x0453=>0x0403, 0x03C8=>0x03A8, 0x0159=>0x0158, 0x0067=>0x0047, 0x00E4=>0x00C4,
+ 0x03AC=>0x0386, 0x03AE=>0x0389, 0x0167=>0x0166, 0x03BE=>0x039E, 0x0165=>0x0164,
+ 0x0117=>0x0116, 0x0109=>0x0108, 0x0076=>0x0056, 0x00FE=>0x00DE, 0x0157=>0x0156,
+ 0x00FA=>0x00DA, 0x1E61=>0x1E60, 0x1E83=>0x1E82, 0x00E2=>0x00C2, 0x0119=>0x0118,
+ 0x0146=>0x0145, 0x0070=>0x0050, 0x0151=>0x0150, 0x044E=>0x042E, 0x0129=>0x0128,
+ 0x03C7=>0x03A7, 0x013E=>0x013D, 0x0442=>0x0422, 0x007A=>0x005A, 0x0448=>0x0428,
+ 0x03C1=>0x03A1, 0x1E81=>0x1E80, 0x016D=>0x016C, 0x00F5=>0x00D5, 0x0075=>0x0055,
+ 0x0177=>0x0176, 0x00FC=>0x00DC, 0x1E57=>0x1E56, 0x03C3=>0x03A3, 0x043A=>0x041A,
+ 0x006D=>0x004D, 0x016B=>0x016A, 0x0171=>0x0170, 0x0444=>0x0424, 0x00EC=>0x00CC,
+ 0x0169=>0x0168, 0x03BF=>0x039F, 0x006B=>0x004B, 0x00F2=>0x00D2, 0x00E0=>0x00C0,
+ 0x0434=>0x0414, 0x03C9=>0x03A9, 0x1E6B=>0x1E6A, 0x00E3=>0x00C3, 0x044D=>0x042D,
+ 0x0436=>0x0416, 0x01A1=>0x01A0, 0x010D=>0x010C, 0x011D=>0x011C, 0x00F0=>0x00D0,
+ 0x013C=>0x013B, 0x045F=>0x040F, 0x045A=>0x040A, 0x00E8=>0x00C8, 0x03C5=>0x03A5,
+ 0x0066=>0x0046, 0x00FD=>0x00DD, 0x0063=>0x0043, 0x021B=>0x021A, 0x00EA=>0x00CA,
+ 0x03B9=>0x0399, 0x017A=>0x0179, 0x00EF=>0x00CF, 0x01B0=>0x01AF, 0x0065=>0x0045,
+ 0x03BB=>0x039B, 0x03B8=>0x0398, 0x03BC=>0x039C, 0x045C=>0x040C, 0x043F=>0x041F,
+ 0x044C=>0x042C, 0x00FE=>0x00DE, 0x00F0=>0x00D0, 0x1EF3=>0x1EF2, 0x0068=>0x0048,
+ 0x00EB=>0x00CB, 0x0111=>0x0110, 0x0433=>0x0413, 0x012F=>0x012E, 0x00E6=>0x00C6,
+ 0x0078=>0x0058, 0x0161=>0x0160, 0x016F=>0x016E, 0x03B1=>0x0391, 0x0457=>0x0407,
+ 0x0173=>0x0172, 0x00FF=>0x0178, 0x006F=>0x004F, 0x043B=>0x041B, 0x03B5=>0x0395,
+ 0x0445=>0x0425, 0x0121=>0x0120, 0x017E=>0x017D, 0x017C=>0x017B, 0x03B6=>0x0396,
+ 0x03B2=>0x0392, 0x03AD=>0x0388, 0x1E85=>0x1E84, 0x0175=>0x0174, 0x0071=>0x0051,
+ 0x0437=>0x0417, 0x1E0B=>0x1E0A, 0x0148=>0x0147, 0x0105=>0x0104, 0x0458=>0x0408,
+ 0x014D=>0x014C, 0x00ED=>0x00CD, 0x0079=>0x0059, 0x010B=>0x010A, 0x03CE=>0x038F,
+ 0x0072=>0x0052, 0x0430=>0x0410, 0x0455=>0x0405, 0x0452=>0x0402, 0x0127=>0x0126,
+ 0x0137=>0x0136, 0x012B=>0x012A, 0x03AF=>0x038A, 0x044B=>0x042B, 0x006C=>0x004C,
+ 0x03B7=>0x0397, 0x0125=>0x0124, 0x0219=>0x0218, 0x00FB=>0x00DB, 0x011F=>0x011E,
+ 0x043E=>0x041E, 0x1E41=>0x1E40, 0x03BD=>0x039D, 0x0107=>0x0106, 0x03CB=>0x03AB,
+ 0x0446=>0x0426, 0x00FE=>0x00DE, 0x00E7=>0x00C7, 0x03CA=>0x03AA, 0x0441=>0x0421,
+ 0x0432=>0x0412, 0x010F=>0x010E, 0x00F8=>0x00D8, 0x0077=>0x0057, 0x011B=>0x011A,
+ 0x0074=>0x0054, 0x006A=>0x004A, 0x045B=>0x040B, 0x0456=>0x0406, 0x0103=>0x0102,
+ 0x03BB=>0x039B, 0x00F1=>0x00D1, 0x043D=>0x041D, 0x03CC=>0x038C, 0x00E9=>0x00C9,
+ 0x00F0=>0x00D0, 0x0457=>0x0407, 0x0123=>0x0122,
+ );
+ }
+
+ $uni = utf8_to_unicode($string);
+
+ if ( !$uni ) {
+ return FALSE;
+ }
+
+ $cnt = count($uni);
+ for ($i=0; $i < $cnt; $i++){
+ if( isset($UTF8_LOWER_TO_UPPER[$uni[$i]]) ) {
+ $uni[$i] = $UTF8_LOWER_TO_UPPER[$uni[$i]];
+ }
+ }
+
+ return utf8_from_unicode($uni);
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/ord.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/ord.php
new file mode 100644
index 00000000..ea458fb5
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/ord.php
@@ -0,0 +1,93 @@
+= 0 && $ord0 <= 127 ) {
+ return $ord0;
+ }
+
+ if ( !isset($chr{1}) ) {
+ trigger_error('Short sequence - at least 2 bytes expected, only 1 seen');
+ return FALSE;
+ }
+
+ $ord1 = ord($chr{1});
+ if ( $ord0 >= 192 && $ord0 <= 223 ) {
+ return ( $ord0 - 192 ) * 64
+ + ( $ord1 - 128 );
+ }
+
+ if ( !isset($chr{2}) ) {
+ trigger_error('Short sequence - at least 3 bytes expected, only 2 seen');
+ return FALSE;
+ }
+ $ord2 = ord($chr{2});
+ if ( $ord0 >= 224 && $ord0 <= 239 ) {
+ return ($ord0-224)*4096
+ + ($ord1-128)*64
+ + ($ord2-128);
+ }
+
+ if ( !isset($chr{3}) ) {
+ trigger_error('Short sequence - at least 4 bytes expected, only 3 seen');
+ return FALSE;
+ }
+ $ord3 = ord($chr{3});
+ if ($ord0>=240 && $ord0<=247) {
+ return ($ord0-240)*262144
+ + ($ord1-128)*4096
+ + ($ord2-128)*64
+ + ($ord3-128);
+
+ }
+
+ if ( !isset($chr{4}) ) {
+ trigger_error('Short sequence - at least 5 bytes expected, only 4 seen');
+ return FALSE;
+ }
+ $ord4 = ord($chr{4});
+ if ($ord0>=248 && $ord0<=251) {
+ return ($ord0-248)*16777216
+ + ($ord1-128)*262144
+ + ($ord2-128)*4096
+ + ($ord3-128)*64
+ + ($ord4-128);
+ }
+
+ if ( !isset($chr{5}) ) {
+ trigger_error('Short sequence - at least 6 bytes expected, only 5 seen');
+ return FALSE;
+ }
+ if ($ord0>=252 && $ord0<=253) {
+ return ($ord0-252) * 1073741824
+ + ($ord1-128)*16777216
+ + ($ord2-128)*262144
+ + ($ord3-128)*4096
+ + ($ord4-128)*64
+ + (ord($chr{5})-128);
+ }
+
+ if ( $ord0 >= 254 && $ord0 <= 255 ) {
+ trigger_error('Invalid UTF-8 with surrogate ordinal '.$ord0);
+ return FALSE;
+ }
+
+}
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/str_ireplace.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/str_ireplace.php
new file mode 100644
index 00000000..41d26134
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/str_ireplace.php
@@ -0,0 +1,80 @@
+
+* @param string $input
+* @param int $length
+* @param string $padStr
+* @param int $type ( same constants as str_pad )
+* @return string
+* @see http://www.php.net/str_pad
+* @see utf8_substr
+* @package utf8
+*/
+function utf8_str_pad($input, $length, $padStr = ' ', $type = STR_PAD_RIGHT) {
+
+ $inputLen = utf8_strlen($input);
+ if ($length <= $inputLen) {
+ return $input;
+ }
+
+ $padStrLen = utf8_strlen($padStr);
+ $padLen = $length - $inputLen;
+
+ if ($type == STR_PAD_RIGHT) {
+ $repeatTimes = ceil($padLen / $padStrLen);
+ return utf8_substr($input . str_repeat($padStr, $repeatTimes), 0, $length);
+ }
+
+ if ($type == STR_PAD_LEFT) {
+ $repeatTimes = ceil($padLen / $padStrLen);
+ return utf8_substr(str_repeat($padStr, $repeatTimes), 0, floor($padLen)) . $input;
+ }
+
+ if ($type == STR_PAD_BOTH) {
+
+ $padLen/= 2;
+ $padAmountLeft = floor($padLen);
+ $padAmountRight = ceil($padLen);
+ $repeatTimesLeft = ceil($padAmountLeft / $padStrLen);
+ $repeatTimesRight = ceil($padAmountRight / $padStrLen);
+
+ $paddingLeft = utf8_substr(str_repeat($padStr, $repeatTimesLeft), 0, $padAmountLeft);
+ $paddingRight = utf8_substr(str_repeat($padStr, $repeatTimesRight), 0, $padAmountLeft);
+ return $paddingLeft . $input . $paddingRight;
+ }
+
+ trigger_error('utf8_str_pad: Unknown padding type (' . $type . ')',E_USER_ERROR);
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/str_split.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/str_split.php
new file mode 100644
index 00000000..b2021fa0
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/str_split.php
@@ -0,0 +1,35 @@
+
+* @see http://www.php.net/ltrim
+* @see http://dev.splitbrain.org/view/darcs/dokuwiki/inc/utf8.php
+* @return string
+* @package utf8
+*/
+function utf8_ltrim( $str, $charlist = FALSE ) {
+ if($charlist === FALSE) return ltrim($str);
+
+ //quote charlist for use in a characterclass
+ $charlist = preg_replace('!([\\\\\\-\\]\\[/^])!','\\\${1}',$charlist);
+
+ return preg_replace('/^['.$charlist.']+/u','',$str);
+}
+
+//---------------------------------------------------------------
+/**
+* UTF-8 aware replacement for rtrim()
+* Note: you only need to use this if you are supplying the charlist
+* optional arg and it contains UTF-8 characters. Otherwise rtrim will
+* work normally on a UTF-8 string
+* @author Andreas Gohr
+* @see http://www.php.net/rtrim
+* @see http://dev.splitbrain.org/view/darcs/dokuwiki/inc/utf8.php
+* @return string
+* @package utf8
+*/
+function utf8_rtrim( $str, $charlist = FALSE ) {
+ if($charlist === FALSE) return rtrim($str);
+
+ //quote charlist for use in a characterclass
+ $charlist = preg_replace('!([\\\\\\-\\]\\[/^])!','\\\${1}',$charlist);
+
+ return preg_replace('/['.$charlist.']+$/u','',$str);
+}
+
+//---------------------------------------------------------------
+/**
+* UTF-8 aware replacement for trim()
+* Note: you only need to use this if you are supplying the charlist
+* optional arg and it contains UTF-8 characters. Otherwise trim will
+* work normally on a UTF-8 string
+* @author Andreas Gohr
+* @see http://www.php.net/trim
+* @see http://dev.splitbrain.org/view/darcs/dokuwiki/inc/utf8.php
+* @return string
+* @package utf8
+*/
+function utf8_trim( $str, $charlist = FALSE ) {
+ if($charlist === FALSE) return trim($str);
+ return utf8_ltrim(utf8_rtrim($str, $charlist), $charlist);
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/ucfirst.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/ucfirst.php
new file mode 100644
index 00000000..f9163545
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/ucfirst.php
@@ -0,0 +1,34 @@
+
+* if ( utf8_is_ascii($someString) ) {
+* // It's just ASCII - use the native PHP version
+* $someString = strtolower($someString);
+* } else {
+* $someString = utf8_strtolower($someString);
+* }
+*
+*
+* @param string
+* @return boolean TRUE if it's all ASCII
+* @package utf8
+* @see utf8_is_ascii_ctrl
+*/
+function utf8_is_ascii($str) {
+ // Search for any bytes which are outside the ASCII range...
+ return (preg_match('/(?:[^\x00-\x7F])/',$str) !== 1);
+}
+
+//--------------------------------------------------------------------
+/**
+* Tests whether a string contains only 7bit ASCII bytes with device
+* control codes omitted. The device control codes can be found on the
+* second table here: http://www.w3schools.com/tags/ref_ascii.asp
+*
+* @param string
+* @return boolean TRUE if it's all ASCII without device control codes
+* @package utf8
+* @see utf8_is_ascii
+*/
+function utf8_is_ascii_ctrl($str) {
+ if ( strlen($str) > 0 ) {
+ // Search for any bytes which are outside the ASCII range,
+ // or are device control codes
+ return (preg_match('/[^\x09\x0A\x0D\x20-\x7E]/',$str) !== 1);
+ }
+ return FALSE;
+}
+
+//--------------------------------------------------------------------
+/**
+* Strip out all non-7bit ASCII bytes
+* If you need to transmit a string to system which you know can only
+* support 7bit ASCII, you could use this function.
+* @param string
+* @return string with non ASCII bytes removed
+* @package utf8
+* @see utf8_strip_non_ascii_ctrl
+*/
+function utf8_strip_non_ascii($str) {
+ ob_start();
+ while ( preg_match(
+ '/^([\x00-\x7F]+)|([^\x00-\x7F]+)/S',
+ $str, $matches) ) {
+ if ( !isset($matches[2]) ) {
+ echo $matches[0];
+ }
+ $str = substr($str, strlen($matches[0]));
+ }
+ $result = ob_get_contents();
+ ob_end_clean();
+ return $result;
+}
+
+//--------------------------------------------------------------------
+/**
+* Strip out device control codes in the ASCII range
+* which are not permitted in XML. Note that this leaves
+* multi-byte characters untouched - it only removes device
+* control codes
+* @see http://hsivonen.iki.fi/producing-xml/#controlchar
+* @param string
+* @return string control codes removed
+*/
+function utf8_strip_ascii_ctrl($str) {
+ ob_start();
+ while ( preg_match(
+ '/^([^\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+)|([\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+)/S',
+ $str, $matches) ) {
+ if ( !isset($matches[2]) ) {
+ echo $matches[0];
+ }
+ $str = substr($str, strlen($matches[0]));
+ }
+ $result = ob_get_contents();
+ ob_end_clean();
+ return $result;
+}
+
+//--------------------------------------------------------------------
+/**
+* Strip out all non 7bit ASCII bytes and ASCII device control codes.
+* For a list of ASCII device control codes see the 2nd table here:
+* http://www.w3schools.com/tags/ref_ascii.asp
+*
+* @param string
+* @return boolean TRUE if it's all ASCII
+* @package utf8
+*/
+function utf8_strip_non_ascii_ctrl($str) {
+ ob_start();
+ while ( preg_match(
+ '/^([\x09\x0A\x0D\x20-\x7E]+)|([^\x09\x0A\x0D\x20-\x7E]+)/S',
+ $str, $matches) ) {
+ if ( !isset($matches[2]) ) {
+ echo $matches[0];
+ }
+ $str = substr($str, strlen($matches[0]));
+ }
+ $result = ob_get_contents();
+ ob_end_clean();
+ return $result;
+}
+
+//---------------------------------------------------------------
+/**
+* Replace accented UTF-8 characters by unaccented ASCII-7 "equivalents".
+* The purpose of this function is to replace characters commonly found in Latin
+* alphabets with something more or less equivalent from the ASCII range. This can
+* be useful for converting a UTF-8 to something ready for a filename, for example.
+* Following the use of this function, you would probably also pass the string
+* through utf8_strip_non_ascii to clean out any other non-ASCII chars
+* Use the optional parameter to just deaccent lower ($case = -1) or upper ($case = 1)
+* letters. Default is to deaccent both cases ($case = 0)
+*
+* For a more complete implementation of transliteration, see the utf8_to_ascii package
+* available from the phputf8 project downloads:
+* http://prdownloads.sourceforge.net/phputf8
+*
+* @param string UTF-8 string
+* @param int (optional) -1 lowercase only, +1 uppercase only, 1 both cases
+* @param string UTF-8 with accented characters replaced by ASCII chars
+* @return string accented chars replaced with ascii equivalents
+* @author Andreas Gohr
+* @package utf8
+*/
+function utf8_accents_to_ascii( $str, $case=0 ){
+
+ static $UTF8_LOWER_ACCENTS = NULL;
+ static $UTF8_UPPER_ACCENTS = NULL;
+
+ if($case <= 0){
+
+ if ( is_null($UTF8_LOWER_ACCENTS) ) {
+ $UTF8_LOWER_ACCENTS = array(
+ 'à' => 'a', 'ô' => 'o', 'ď' => 'd', 'ḟ' => 'f', 'ë' => 'e', 'š' => 's', 'ơ' => 'o',
+ 'ß' => 'ss', 'ă' => 'a', 'ř' => 'r', 'ț' => 't', 'ň' => 'n', 'ā' => 'a', 'ķ' => 'k',
+ 'ŝ' => 's', 'ỳ' => 'y', 'ņ' => 'n', 'ĺ' => 'l', 'ħ' => 'h', 'ṗ' => 'p', 'ó' => 'o',
+ 'ú' => 'u', 'ě' => 'e', 'é' => 'e', 'ç' => 'c', 'ẁ' => 'w', 'ċ' => 'c', 'õ' => 'o',
+ 'ṡ' => 's', 'ø' => 'o', 'ģ' => 'g', 'ŧ' => 't', 'ș' => 's', 'ė' => 'e', 'ĉ' => 'c',
+ 'ś' => 's', 'î' => 'i', 'ű' => 'u', 'ć' => 'c', 'ę' => 'e', 'ŵ' => 'w', 'ṫ' => 't',
+ 'ū' => 'u', 'č' => 'c', 'ö' => 'oe', 'è' => 'e', 'ŷ' => 'y', 'ą' => 'a', 'ł' => 'l',
+ 'ų' => 'u', 'ů' => 'u', 'ş' => 's', 'ğ' => 'g', 'ļ' => 'l', 'ƒ' => 'f', 'ž' => 'z',
+ 'ẃ' => 'w', 'ḃ' => 'b', 'å' => 'a', 'ì' => 'i', 'ï' => 'i', 'ḋ' => 'd', 'ť' => 't',
+ 'ŗ' => 'r', 'ä' => 'ae', 'í' => 'i', 'ŕ' => 'r', 'ê' => 'e', 'ü' => 'ue', 'ò' => 'o',
+ 'ē' => 'e', 'ñ' => 'n', 'ń' => 'n', 'ĥ' => 'h', 'ĝ' => 'g', 'đ' => 'd', 'ĵ' => 'j',
+ 'ÿ' => 'y', 'ũ' => 'u', 'ŭ' => 'u', 'ư' => 'u', 'ţ' => 't', 'ý' => 'y', 'ő' => 'o',
+ 'â' => 'a', 'ľ' => 'l', 'ẅ' => 'w', 'ż' => 'z', 'ī' => 'i', 'ã' => 'a', 'ġ' => 'g',
+ 'ṁ' => 'm', 'ō' => 'o', 'ĩ' => 'i', 'ù' => 'u', 'į' => 'i', 'ź' => 'z', 'á' => 'a',
+ 'û' => 'u', 'þ' => 'th', 'ð' => 'dh', 'æ' => 'ae', 'µ' => 'u', 'ĕ' => 'e',
+ );
+ }
+
+ $str = str_replace(
+ array_keys($UTF8_LOWER_ACCENTS),
+ array_values($UTF8_LOWER_ACCENTS),
+ $str
+ );
+ }
+
+ if($case >= 0){
+ if ( is_null($UTF8_UPPER_ACCENTS) ) {
+ $UTF8_UPPER_ACCENTS = array(
+ 'À' => 'A', 'Ô' => 'O', 'Ď' => 'D', 'Ḟ' => 'F', 'Ë' => 'E', 'Š' => 'S', 'Ơ' => 'O',
+ 'Ă' => 'A', 'Ř' => 'R', 'Ț' => 'T', 'Ň' => 'N', 'Ā' => 'A', 'Ķ' => 'K',
+ 'Ŝ' => 'S', 'Ỳ' => 'Y', 'Ņ' => 'N', 'Ĺ' => 'L', 'Ħ' => 'H', 'Ṗ' => 'P', 'Ó' => 'O',
+ 'Ú' => 'U', 'Ě' => 'E', 'É' => 'E', 'Ç' => 'C', 'Ẁ' => 'W', 'Ċ' => 'C', 'Õ' => 'O',
+ 'Ṡ' => 'S', 'Ø' => 'O', 'Ģ' => 'G', 'Ŧ' => 'T', 'Ș' => 'S', 'Ė' => 'E', 'Ĉ' => 'C',
+ 'Ś' => 'S', 'Î' => 'I', 'Ű' => 'U', 'Ć' => 'C', 'Ę' => 'E', 'Ŵ' => 'W', 'Ṫ' => 'T',
+ 'Ū' => 'U', 'Č' => 'C', 'Ö' => 'Oe', 'È' => 'E', 'Ŷ' => 'Y', 'Ą' => 'A', 'Ł' => 'L',
+ 'Ų' => 'U', 'Ů' => 'U', 'Ş' => 'S', 'Ğ' => 'G', 'Ļ' => 'L', 'Ƒ' => 'F', 'Ž' => 'Z',
+ 'Ẃ' => 'W', 'Ḃ' => 'B', 'Å' => 'A', 'Ì' => 'I', 'Ï' => 'I', 'Ḋ' => 'D', 'Ť' => 'T',
+ 'Ŗ' => 'R', 'Ä' => 'Ae', 'Í' => 'I', 'Ŕ' => 'R', 'Ê' => 'E', 'Ü' => 'Ue', 'Ò' => 'O',
+ 'Ē' => 'E', 'Ñ' => 'N', 'Ń' => 'N', 'Ĥ' => 'H', 'Ĝ' => 'G', 'Đ' => 'D', 'Ĵ' => 'J',
+ 'Ÿ' => 'Y', 'Ũ' => 'U', 'Ŭ' => 'U', 'Ư' => 'U', 'Ţ' => 'T', 'Ý' => 'Y', 'Ő' => 'O',
+ 'Â' => 'A', 'Ľ' => 'L', 'Ẅ' => 'W', 'Ż' => 'Z', 'Ī' => 'I', 'Ã' => 'A', 'Ġ' => 'G',
+ 'Ṁ' => 'M', 'Ō' => 'O', 'Ĩ' => 'I', 'Ù' => 'U', 'Į' => 'I', 'Ź' => 'Z', 'Á' => 'A',
+ 'Û' => 'U', 'Þ' => 'Th', 'Ð' => 'Dh', 'Æ' => 'Ae', 'Ĕ' => 'E',
+ );
+ }
+ $str = str_replace(
+ array_keys($UTF8_UPPER_ACCENTS),
+ array_values($UTF8_UPPER_ACCENTS),
+ $str
+ );
+ }
+
+ return $str;
+
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/bad.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/bad.php
new file mode 100644
index 00000000..1ebb49c9
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/bad.php
@@ -0,0 +1,397 @@
+ 0 ) {
+ return $badList;
+ }
+ return FALSE;
+}
+
+//--------------------------------------------------------------------
+/**
+* Strips out any bad bytes from a UTF-8 string and returns the rest
+* PCRE Pattern to locate bad bytes in a UTF-8 string
+* Comes from W3 FAQ: Multilingual Forms
+* Note: modified to include full ASCII range including control chars
+* @see http://www.w3.org/International/questions/qa-forms-utf-8
+* @param string
+* @return string
+* @package utf8
+*/
+function utf8_bad_strip($str) {
+ $UTF8_BAD =
+ '([\x00-\x7F]'. # ASCII (including control chars)
+ '|[\xC2-\xDF][\x80-\xBF]'. # non-overlong 2-byte
+ '|\xE0[\xA0-\xBF][\x80-\xBF]'. # excluding overlongs
+ '|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}'. # straight 3-byte
+ '|\xED[\x80-\x9F][\x80-\xBF]'. # excluding surrogates
+ '|\xF0[\x90-\xBF][\x80-\xBF]{2}'. # planes 1-3
+ '|[\xF1-\xF3][\x80-\xBF]{3}'. # planes 4-15
+ '|\xF4[\x80-\x8F][\x80-\xBF]{2}'. # plane 16
+ '|(.{1}))'; # invalid byte
+ ob_start();
+ while (preg_match('/'.$UTF8_BAD.'/S', $str, $matches)) {
+ if ( !isset($matches[2])) {
+ echo $matches[0];
+ }
+ $str = substr($str,strlen($matches[0]));
+ }
+ $result = ob_get_contents();
+ ob_end_clean();
+ return $result;
+}
+
+//--------------------------------------------------------------------
+/**
+* Replace bad bytes with an alternative character - ASCII character
+* recommended is replacement char
+* PCRE Pattern to locate bad bytes in a UTF-8 string
+* Comes from W3 FAQ: Multilingual Forms
+* Note: modified to include full ASCII range including control chars
+* @see http://www.w3.org/International/questions/qa-forms-utf-8
+* @param string to search
+* @param string to replace bad bytes with (defaults to '?') - use ASCII
+* @return string
+* @package utf8
+*/
+function utf8_bad_replace($str, $replace = '?') {
+ $UTF8_BAD =
+ '([\x00-\x7F]'. # ASCII (including control chars)
+ '|[\xC2-\xDF][\x80-\xBF]'. # non-overlong 2-byte
+ '|\xE0[\xA0-\xBF][\x80-\xBF]'. # excluding overlongs
+ '|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}'. # straight 3-byte
+ '|\xED[\x80-\x9F][\x80-\xBF]'. # excluding surrogates
+ '|\xF0[\x90-\xBF][\x80-\xBF]{2}'. # planes 1-3
+ '|[\xF1-\xF3][\x80-\xBF]{3}'. # planes 4-15
+ '|\xF4[\x80-\x8F][\x80-\xBF]{2}'. # plane 16
+ '|(.{1}))'; # invalid byte
+ ob_start();
+ while (preg_match('/'.$UTF8_BAD.'/S', $str, $matches)) {
+ if ( !isset($matches[2])) {
+ echo $matches[0];
+ } else {
+ echo $replace;
+ }
+ $str = substr($str,strlen($matches[0]));
+ }
+ $result = ob_get_contents();
+ ob_end_clean();
+ return $result;
+}
+
+//--------------------------------------------------------------------
+/**
+* Return code from utf8_bad_identify() when a five octet sequence is detected.
+* Note: 5 octets sequences are valid UTF-8 but are not supported by Unicode so
+* do not represent a useful character
+* @see utf8_bad_identify
+* @package utf8
+*/
+define('UTF8_BAD_5OCTET',1);
+
+/**
+* Return code from utf8_bad_identify() when a six octet sequence is detected.
+* Note: 6 octets sequences are valid UTF-8 but are not supported by Unicode so
+* do not represent a useful character
+* @see utf8_bad_identify
+* @package utf8
+*/
+define('UTF8_BAD_6OCTET',2);
+
+/**
+* Return code from utf8_bad_identify().
+* Invalid octet for use as start of multi-byte UTF-8 sequence
+* @see utf8_bad_identify
+* @package utf8
+*/
+define('UTF8_BAD_SEQID',3);
+
+/**
+* Return code from utf8_bad_identify().
+* From Unicode 3.1, non-shortest form is illegal
+* @see utf8_bad_identify
+* @package utf8
+*/
+define('UTF8_BAD_NONSHORT',4);
+
+/**
+* Return code from utf8_bad_identify().
+* From Unicode 3.2, surrogate characters are illegal
+* @see utf8_bad_identify
+* @package utf8
+*/
+define('UTF8_BAD_SURROGATE',5);
+
+/**
+* Return code from utf8_bad_identify().
+* Codepoints outside the Unicode range are illegal
+* @see utf8_bad_identify
+* @package utf8
+*/
+define('UTF8_BAD_UNIOUTRANGE',6);
+
+/**
+* Return code from utf8_bad_identify().
+* Incomplete multi-octet sequence
+* Note: this is kind of a "catch-all"
+* @see utf8_bad_identify
+* @package utf8
+*/
+define('UTF8_BAD_SEQINCOMPLETE',7);
+
+//--------------------------------------------------------------------
+/**
+* Reports on the type of bad byte found in a UTF-8 string. Returns a
+* status code on the first bad byte found
+* @author
+* @param string UTF-8 encoded string
+* @return mixed integer constant describing problem or FALSE if valid UTF-8
+* @see utf8_bad_explain
+* @see http://hsivonen.iki.fi/php-utf8/
+* @package utf8
+*/
+function utf8_bad_identify($str, &$i) {
+
+ $mState = 0; // cached expected number of octets after the current octet
+ // until the beginning of the next UTF8 character sequence
+ $mUcs4 = 0; // cached Unicode character
+ $mBytes = 1; // cached expected number of octets in the current sequence
+
+ $len = strlen($str);
+
+ for($i = 0; $i < $len; $i++) {
+
+ $in = ord($str{$i});
+
+ if ( $mState == 0) {
+
+ // When mState is zero we expect either a US-ASCII character or a
+ // multi-octet sequence.
+ if (0 == (0x80 & ($in))) {
+ // US-ASCII, pass straight through.
+ $mBytes = 1;
+
+ } else if (0xC0 == (0xE0 & ($in))) {
+ // First octet of 2 octet sequence
+ $mUcs4 = ($in);
+ $mUcs4 = ($mUcs4 & 0x1F) << 6;
+ $mState = 1;
+ $mBytes = 2;
+
+ } else if (0xE0 == (0xF0 & ($in))) {
+ // First octet of 3 octet sequence
+ $mUcs4 = ($in);
+ $mUcs4 = ($mUcs4 & 0x0F) << 12;
+ $mState = 2;
+ $mBytes = 3;
+
+ } else if (0xF0 == (0xF8 & ($in))) {
+ // First octet of 4 octet sequence
+ $mUcs4 = ($in);
+ $mUcs4 = ($mUcs4 & 0x07) << 18;
+ $mState = 3;
+ $mBytes = 4;
+
+ } else if (0xF8 == (0xFC & ($in))) {
+
+ /* First octet of 5 octet sequence.
+ *
+ * This is illegal because the encoded codepoint must be either
+ * (a) not the shortest form or
+ * (b) outside the Unicode range of 0-0x10FFFF.
+ */
+
+ return UTF8_BAD_5OCTET;
+
+ } else if (0xFC == (0xFE & ($in))) {
+
+ // First octet of 6 octet sequence, see comments for 5 octet sequence.
+ return UTF8_BAD_6OCTET;
+
+ } else {
+ // Current octet is neither in the US-ASCII range nor a legal first
+ // octet of a multi-octet sequence.
+ return UTF8_BAD_SEQID;
+
+ }
+
+ } else {
+
+ // When mState is non-zero, we expect a continuation of the multi-octet
+ // sequence
+ if (0x80 == (0xC0 & ($in))) {
+
+ // Legal continuation.
+ $shift = ($mState - 1) * 6;
+ $tmp = $in;
+ $tmp = ($tmp & 0x0000003F) << $shift;
+ $mUcs4 |= $tmp;
+
+ /**
+ * End of the multi-octet sequence. mUcs4 now contains the final
+ * Unicode codepoint to be output
+ */
+ if (0 == --$mState) {
+
+ // From Unicode 3.1, non-shortest form is illegal
+ if (((2 == $mBytes) && ($mUcs4 < 0x0080)) ||
+ ((3 == $mBytes) && ($mUcs4 < 0x0800)) ||
+ ((4 == $mBytes) && ($mUcs4 < 0x10000)) ) {
+ return UTF8_BAD_NONSHORT;
+
+ // From Unicode 3.2, surrogate characters are illegal
+ } else if (($mUcs4 & 0xFFFFF800) == 0xD800) {
+ return UTF8_BAD_SURROGATE;
+
+ // Codepoints outside the Unicode range are illegal
+ } else if ($mUcs4 > 0x10FFFF) {
+ return UTF8_BAD_UNIOUTRANGE;
+ }
+
+ //initialize UTF8 cache
+ $mState = 0;
+ $mUcs4 = 0;
+ $mBytes = 1;
+ }
+
+ } else {
+ // ((0xC0 & (*in) != 0x80) && (mState != 0))
+ // Incomplete multi-octet sequence.
+ $i--;
+ return UTF8_BAD_SEQINCOMPLETE;
+ }
+ }
+ }
+
+ if ( $mState != 0 ) {
+ // Incomplete multi-octet sequence.
+ $i--;
+ return UTF8_BAD_SEQINCOMPLETE;
+ }
+
+ // No bad octets found
+ $i = NULL;
+ return FALSE;
+}
+
+//--------------------------------------------------------------------
+/**
+* Takes a return code from utf8_bad_identify() are returns a message
+* (in English) explaining what the problem is.
+* @param int return code from utf8_bad_identify
+* @return mixed string message or FALSE if return code unknown
+* @see utf8_bad_identify
+* @package utf8
+*/
+function utf8_bad_explain($code) {
+
+ switch ($code) {
+
+ case UTF8_BAD_5OCTET:
+ return 'Five octet sequences are valid UTF-8 but are not supported by Unicode';
+ break;
+
+ case UTF8_BAD_6OCTET:
+ return 'Six octet sequences are valid UTF-8 but are not supported by Unicode';
+ break;
+
+ case UTF8_BAD_SEQID:
+ return 'Invalid octet for use as start of multi-byte UTF-8 sequence';
+ break;
+
+ case UTF8_BAD_NONSHORT:
+ return 'From Unicode 3.1, non-shortest form is illegal';
+ break;
+
+ case UTF8_BAD_SURROGATE:
+ return 'From Unicode 3.2, surrogate characters are illegal';
+ break;
+
+ case UTF8_BAD_UNIOUTRANGE:
+ return 'Codepoints outside the Unicode range are illegal';
+ break;
+
+ case UTF8_BAD_SEQINCOMPLETE:
+ return 'Incomplete multi-octet sequence';
+ break;
+
+ }
+
+ trigger_error('Unknown error code: '.$code,E_USER_WARNING);
+ return FALSE;
+
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/patterns.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/patterns.php
new file mode 100644
index 00000000..69abd0e1
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/patterns.php
@@ -0,0 +1,63 @@
+
+* @param string string to locate index in
+* @param int (n times)
+* @return mixed - int if only one input int, array if more
+* @return boolean TRUE if it's all ASCII
+* @package utf8
+*/
+function utf8_byte_position() {
+
+ $args = func_get_args();
+ $str =& array_shift($args);
+ if (!is_string($str)) return false;
+
+ $result = array();
+
+ // trivial byte index, character offset pair
+ $prev = array(0,0);
+
+ // use a short piece of str to estimate bytes per character
+ // $i (& $j) -> byte indexes into $str
+ $i = utf8_locate_next_chr($str, 300);
+
+ // $c -> character offset into $str
+ $c = strlen(utf8_decode(substr($str,0,$i)));
+
+ // deal with arguments from lowest to highest
+ sort($args);
+
+ foreach ($args as $offset) {
+ // sanity checks FIXME
+
+ // 0 is an easy check
+ if ($offset == 0) { $result[] = 0; continue; }
+
+ // ensure no endless looping
+ $safety_valve = 50;
+
+ do {
+
+ if ( ($c - $prev[1]) == 0 ) {
+ // Hack: gone past end of string
+ $error = 0;
+ $i = strlen($str);
+ break;
+ }
+
+ $j = $i + (int)(($offset-$c) * ($i - $prev[0]) / ($c - $prev[1]));
+
+ // correct to utf8 character boundary
+ $j = utf8_locate_next_chr($str, $j);
+
+ // save the index, offset for use next iteration
+ $prev = array($i,$c);
+
+ if ($j > $i) {
+ // determine new character offset
+ $c += strlen(utf8_decode(substr($str,$i,$j-$i)));
+ } else {
+ // ditto
+ $c -= strlen(utf8_decode(substr($str,$j,$i-$j)));
+ }
+
+ $error = abs($c-$offset);
+
+ // ready for next time around
+ $i = $j;
+
+ // from 7 it is faster to iterate over the string
+ } while ( ($error > 7) && --$safety_valve) ;
+
+ if ($error && $error <= 7) {
+
+ if ($c < $offset) {
+ // move up
+ while ($error--) { $i = utf8_locate_next_chr($str,++$i); }
+ } else {
+ // move down
+ while ($error--) { $i = utf8_locate_current_chr($str,--$i); }
+ }
+
+ // ready for next arg
+ $c = $offset;
+ }
+ $result[] = $i;
+ }
+
+ if ( count($result) == 1 ) {
+ return $result[0];
+ }
+
+ return $result;
+}
+
+//--------------------------------------------------------------------
+/**
+* Given a string and any byte index, returns the byte index
+* of the start of the current UTF-8 character, relative to supplied
+* position. If the current character begins at the same place as the
+* supplied byte index, that byte index will be returned. Otherwise
+* this function will step backwards, looking for the index where
+* curent UTF-8 character begins
+* @author Chris Smith
+* @param string
+* @param int byte index in the string
+* @return int byte index of start of next UTF-8 character
+* @package utf8
+*/
+function utf8_locate_current_chr( &$str, $idx ) {
+
+ if ($idx <= 0) return 0;
+
+ $limit = strlen($str);
+ if ($idx >= $limit) return $limit;
+
+ // Binary value for any byte after the first in a multi-byte UTF-8 character
+ // will be like 10xxxxxx so & 0xC0 can be used to detect this kind
+ // of byte - assuming well formed UTF-8
+ while ($idx && ((ord($str[$idx]) & 0xC0) == 0x80)) $idx--;
+
+ return $idx;
+}
+
+//--------------------------------------------------------------------
+/**
+* Given a string and any byte index, returns the byte index
+* of the start of the next UTF-8 character, relative to supplied
+* position. If the next character begins at the same place as the
+* supplied byte index, that byte index will be returned.
+* @author Chris Smith
+* @param string
+* @param int byte index in the string
+* @return int byte index of start of next UTF-8 character
+* @package utf8
+*/
+function utf8_locate_next_chr( &$str, $idx ) {
+
+ if ($idx <= 0) return 0;
+
+ $limit = strlen($str);
+ if ($idx >= $limit) return $limit;
+
+ // Binary value for any byte after the first in a multi-byte UTF-8 character
+ // will be like 10xxxxxx so & 0xC0 can be used to detect this kind
+ // of byte - assuming well formed UTF-8
+ while (($idx < $limit) && ((ord($str[$idx]) & 0xC0) == 0x80)) $idx++;
+
+ return $idx;
+}
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/specials.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/specials.php
new file mode 100644
index 00000000..66e52a35
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/specials.php
@@ -0,0 +1,124 @@
+
+* @param string $string The UTF8 string to strip of special chars
+* @param string (optional) $repl Replace special with this string
+* @return string with common non-alphanumeric characters removed
+* @see utf8_specials_pattern
+*/
+function utf8_strip_specials($string, $repl=''){
+ return preg_replace(utf8_specials_pattern(), $repl, $string);
+}
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/unicode.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/unicode.php
new file mode 100644
index 00000000..76f60ef4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/unicode.php
@@ -0,0 +1,257 @@
+ 0xFFFF. Occurrances of the BOM are ignored. Surrogates
+* are not allowed.
+* Returns false if the input string isn't a valid UTF-8 octet sequence
+* and raises a PHP error at level E_USER_WARNING
+* Note: this function has been modified slightly in this library to
+* trigger errors on encountering bad bytes
+* @author
+* @param string UTF-8 encoded string
+* @return mixed array of unicode code points or FALSE if UTF-8 invalid
+* @see utf8_from_unicode
+* @see http://hsivonen.iki.fi/php-utf8/
+* @package utf8
+*/
+function utf8_to_unicode($str) {
+ $mState = 0; // cached expected number of octets after the current octet
+ // until the beginning of the next UTF8 character sequence
+ $mUcs4 = 0; // cached Unicode character
+ $mBytes = 1; // cached expected number of octets in the current sequence
+
+ $out = array();
+
+ $len = strlen($str);
+
+ for($i = 0; $i < $len; $i++) {
+
+ $in = ord($str{$i});
+
+ if ( $mState == 0) {
+
+ // When mState is zero we expect either a US-ASCII character or a
+ // multi-octet sequence.
+ if (0 == (0x80 & ($in))) {
+ // US-ASCII, pass straight through.
+ $out[] = $in;
+ $mBytes = 1;
+
+ } else if (0xC0 == (0xE0 & ($in))) {
+ // First octet of 2 octet sequence
+ $mUcs4 = ($in);
+ $mUcs4 = ($mUcs4 & 0x1F) << 6;
+ $mState = 1;
+ $mBytes = 2;
+
+ } else if (0xE0 == (0xF0 & ($in))) {
+ // First octet of 3 octet sequence
+ $mUcs4 = ($in);
+ $mUcs4 = ($mUcs4 & 0x0F) << 12;
+ $mState = 2;
+ $mBytes = 3;
+
+ } else if (0xF0 == (0xF8 & ($in))) {
+ // First octet of 4 octet sequence
+ $mUcs4 = ($in);
+ $mUcs4 = ($mUcs4 & 0x07) << 18;
+ $mState = 3;
+ $mBytes = 4;
+
+ } else if (0xF8 == (0xFC & ($in))) {
+ /* First octet of 5 octet sequence.
+ *
+ * This is illegal because the encoded codepoint must be either
+ * (a) not the shortest form or
+ * (b) outside the Unicode range of 0-0x10FFFF.
+ * Rather than trying to resynchronize, we will carry on until the end
+ * of the sequence and let the later error handling code catch it.
+ */
+ $mUcs4 = ($in);
+ $mUcs4 = ($mUcs4 & 0x03) << 24;
+ $mState = 4;
+ $mBytes = 5;
+
+ } else if (0xFC == (0xFE & ($in))) {
+ // First octet of 6 octet sequence, see comments for 5 octet sequence.
+ $mUcs4 = ($in);
+ $mUcs4 = ($mUcs4 & 1) << 30;
+ $mState = 5;
+ $mBytes = 6;
+
+ } else {
+ /* Current octet is neither in the US-ASCII range nor a legal first
+ * octet of a multi-octet sequence.
+ */
+ trigger_error(
+ 'utf8_to_unicode: Illegal sequence identifier '.
+ 'in UTF-8 at byte '.$i,
+ E_USER_WARNING
+ );
+ return FALSE;
+
+ }
+
+ } else {
+
+ // When mState is non-zero, we expect a continuation of the multi-octet
+ // sequence
+ if (0x80 == (0xC0 & ($in))) {
+
+ // Legal continuation.
+ $shift = ($mState - 1) * 6;
+ $tmp = $in;
+ $tmp = ($tmp & 0x0000003F) << $shift;
+ $mUcs4 |= $tmp;
+
+ /**
+ * End of the multi-octet sequence. mUcs4 now contains the final
+ * Unicode codepoint to be output
+ */
+ if (0 == --$mState) {
+
+ /*
+ * Check for illegal sequences and codepoints.
+ */
+ // From Unicode 3.1, non-shortest form is illegal
+ if (((2 == $mBytes) && ($mUcs4 < 0x0080)) ||
+ ((3 == $mBytes) && ($mUcs4 < 0x0800)) ||
+ ((4 == $mBytes) && ($mUcs4 < 0x10000)) ||
+ (4 < $mBytes) ||
+ // From Unicode 3.2, surrogate characters are illegal
+ (($mUcs4 & 0xFFFFF800) == 0xD800) ||
+ // Codepoints outside the Unicode range are illegal
+ ($mUcs4 > 0x10FFFF)) {
+
+ trigger_error(
+ 'utf8_to_unicode: Illegal sequence or codepoint '.
+ 'in UTF-8 at byte '.$i,
+ E_USER_WARNING
+ );
+
+ return FALSE;
+
+ }
+
+ if (0xFEFF != $mUcs4) {
+ // BOM is legal but we don't want to output it
+ $out[] = $mUcs4;
+ }
+
+ //initialize UTF8 cache
+ $mState = 0;
+ $mUcs4 = 0;
+ $mBytes = 1;
+ }
+
+ } else {
+ /**
+ *((0xC0 & (*in) != 0x80) && (mState != 0))
+ * Incomplete multi-octet sequence.
+ */
+ trigger_error(
+ 'utf8_to_unicode: Incomplete multi-octet '.
+ ' sequence in UTF-8 at byte '.$i,
+ E_USER_WARNING
+ );
+
+ return FALSE;
+ }
+ }
+ }
+ return $out;
+}
+
+//--------------------------------------------------------------------
+/**
+* Takes an array of ints representing the Unicode characters and returns
+* a UTF-8 string. Astral planes are supported ie. the ints in the
+* input can be > 0xFFFF. Occurrances of the BOM are ignored. Surrogates
+* are not allowed.
+* Returns false if the input array contains ints that represent
+* surrogates or are outside the Unicode range
+* and raises a PHP error at level E_USER_WARNING
+* Note: this function has been modified slightly in this library to use
+* output buffering to concatenate the UTF-8 string (faster) as well as
+* reference the array by it's keys
+* @param array of unicode code points representing a string
+* @return mixed UTF-8 string or FALSE if array contains invalid code points
+* @author
+* @see utf8_to_unicode
+* @see http://hsivonen.iki.fi/php-utf8/
+* @package utf8
+*/
+function utf8_from_unicode($arr) {
+ ob_start();
+
+ foreach (array_keys($arr) as $k) {
+
+ # ASCII range (including control chars)
+ if ( ($arr[$k] >= 0) && ($arr[$k] <= 0x007f) ) {
+
+ echo chr($arr[$k]);
+
+ # 2 byte sequence
+ } else if ($arr[$k] <= 0x07ff) {
+
+ echo chr(0xc0 | ($arr[$k] >> 6));
+ echo chr(0x80 | ($arr[$k] & 0x003f));
+
+ # Byte order mark (skip)
+ } else if($arr[$k] == 0xFEFF) {
+
+ // nop -- zap the BOM
+
+ # Test for illegal surrogates
+ } else if ($arr[$k] >= 0xD800 && $arr[$k] <= 0xDFFF) {
+
+ // found a surrogate
+ trigger_error(
+ 'utf8_from_unicode: Illegal surrogate '.
+ 'at index: '.$k.', value: '.$arr[$k],
+ E_USER_WARNING
+ );
+
+ return FALSE;
+
+ # 3 byte sequence
+ } else if ($arr[$k] <= 0xffff) {
+
+ echo chr(0xe0 | ($arr[$k] >> 12));
+ echo chr(0x80 | (($arr[$k] >> 6) & 0x003f));
+ echo chr(0x80 | ($arr[$k] & 0x003f));
+
+ # 4 byte sequence
+ } else if ($arr[$k] <= 0x10ffff) {
+
+ echo chr(0xf0 | ($arr[$k] >> 18));
+ echo chr(0x80 | (($arr[$k] >> 12) & 0x3f));
+ echo chr(0x80 | (($arr[$k] >> 6) & 0x3f));
+ echo chr(0x80 | ($arr[$k] & 0x3f));
+
+ } else {
+
+ trigger_error(
+ 'utf8_from_unicode: Codepoint out of Unicode range '.
+ 'at index: '.$k.', value: '.$arr[$k],
+ E_USER_WARNING
+ );
+
+ // out of range
+ return FALSE;
+ }
+ }
+
+ $result = ob_get_contents();
+ ob_end_clean();
+ return $result;
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/validation.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/validation.php
new file mode 100644
index 00000000..bc1acae8
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/string/phputf8/utils/validation.php
@@ -0,0 +1,173 @@
+
+* @param string UTF-8 encoded string
+* @return boolean true if valid
+* @see http://hsivonen.iki.fi/php-utf8/
+* @see utf8_compliant
+* @package utf8
+*/
+function utf8_is_valid($str) {
+
+ $mState = 0; // cached expected number of octets after the current octet
+ // until the beginning of the next UTF8 character sequence
+ $mUcs4 = 0; // cached Unicode character
+ $mBytes = 1; // cached expected number of octets in the current sequence
+
+ $len = strlen($str);
+
+ for($i = 0; $i < $len; $i++) {
+
+ $in = ord($str{$i});
+
+ if ( $mState == 0) {
+
+ // When mState is zero we expect either a US-ASCII character or a
+ // multi-octet sequence.
+ if (0 == (0x80 & ($in))) {
+ // US-ASCII, pass straight through.
+ $mBytes = 1;
+
+ } else if (0xC0 == (0xE0 & ($in))) {
+ // First octet of 2 octet sequence
+ $mUcs4 = ($in);
+ $mUcs4 = ($mUcs4 & 0x1F) << 6;
+ $mState = 1;
+ $mBytes = 2;
+
+ } else if (0xE0 == (0xF0 & ($in))) {
+ // First octet of 3 octet sequence
+ $mUcs4 = ($in);
+ $mUcs4 = ($mUcs4 & 0x0F) << 12;
+ $mState = 2;
+ $mBytes = 3;
+
+ } else if (0xF0 == (0xF8 & ($in))) {
+ // First octet of 4 octet sequence
+ $mUcs4 = ($in);
+ $mUcs4 = ($mUcs4 & 0x07) << 18;
+ $mState = 3;
+ $mBytes = 4;
+
+ } else if (0xF8 == (0xFC & ($in))) {
+ /* First octet of 5 octet sequence.
+ *
+ * This is illegal because the encoded codepoint must be either
+ * (a) not the shortest form or
+ * (b) outside the Unicode range of 0-0x10FFFF.
+ * Rather than trying to resynchronize, we will carry on until the end
+ * of the sequence and let the later error handling code catch it.
+ */
+ $mUcs4 = ($in);
+ $mUcs4 = ($mUcs4 & 0x03) << 24;
+ $mState = 4;
+ $mBytes = 5;
+
+ } else if (0xFC == (0xFE & ($in))) {
+ // First octet of 6 octet sequence, see comments for 5 octet sequence.
+ $mUcs4 = ($in);
+ $mUcs4 = ($mUcs4 & 1) << 30;
+ $mState = 5;
+ $mBytes = 6;
+
+ } else {
+ /* Current octet is neither in the US-ASCII range nor a legal first
+ * octet of a multi-octet sequence.
+ */
+ return FALSE;
+
+ }
+
+ } else {
+
+ // When mState is non-zero, we expect a continuation of the multi-octet
+ // sequence
+ if (0x80 == (0xC0 & ($in))) {
+
+ // Legal continuation.
+ $shift = ($mState - 1) * 6;
+ $tmp = $in;
+ $tmp = ($tmp & 0x0000003F) << $shift;
+ $mUcs4 |= $tmp;
+
+ /**
+ * End of the multi-octet sequence. mUcs4 now contains the final
+ * Unicode codepoint to be output
+ */
+ if (0 == --$mState) {
+
+ /*
+ * Check for illegal sequences and codepoints.
+ */
+ // From Unicode 3.1, non-shortest form is illegal
+ if (((2 == $mBytes) && ($mUcs4 < 0x0080)) ||
+ ((3 == $mBytes) && ($mUcs4 < 0x0800)) ||
+ ((4 == $mBytes) && ($mUcs4 < 0x10000)) ||
+ (4 < $mBytes) ||
+ // From Unicode 3.2, surrogate characters are illegal
+ (($mUcs4 & 0xFFFFF800) == 0xD800) ||
+ // Codepoints outside the Unicode range are illegal
+ ($mUcs4 > 0x10FFFF)) {
+
+ return FALSE;
+
+ }
+
+ //initialize UTF8 cache
+ $mState = 0;
+ $mUcs4 = 0;
+ $mBytes = 1;
+ }
+
+ } else {
+ /**
+ *((0xC0 & (*in) != 0x80) && (mState != 0))
+ * Incomplete multi-octet sequence.
+ */
+
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+//--------------------------------------------------------------------
+/**
+* Tests whether a string complies as UTF-8. This will be much
+* faster than utf8_is_valid but will pass five and six octet
+* UTF-8 sequences, which are not supported by Unicode and
+* so cannot be displayed correctly in a browser. In other words
+* it is not as strict as utf8_is_valid but it's faster. If you use
+* is to validate user input, you place yourself at the risk that
+* attackers will be able to inject 5 and 6 byte sequences (which
+* may or may not be a significant risk, depending on what you are
+* are doing)
+* @see utf8_is_valid
+* @see http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php#54805
+* @param string UTF-8 string to check
+* @return boolean TRUE if string is valid UTF-8
+* @package utf8
+*/
+function utf8_compliant($str) {
+ if ( strlen($str) == 0 ) {
+ return TRUE;
+ }
+ // If even just the first character can be matched, when the /u
+ // modifier is used, then it's valid UTF-8. If the UTF-8 is somehow
+ // invalid, nothing at all will match, even if the string contains
+ // some valid sequences
+ return (preg_match('/^.{1}/us',$str,$ar) == 1);
+}
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/.gitignore b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/.gitignore
new file mode 100644
index 00000000..84718b5d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/.gitignore
@@ -0,0 +1,11 @@
+# Development system files #
+.*
+!/.gitignore
+!/.travis.yml
+
+# Composer #
+vendor/*
+composer.lock
+
+# Test #
+phpunit.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/.travis.yml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/.travis.yml
new file mode 100644
index 00000000..5420e5c4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/.travis.yml
@@ -0,0 +1,16 @@
+language: php
+
+sudo: false
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+
+before_script:
+ - composer update --dev
+
+script:
+ - phpunit --configuration phpunit.travis.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/Helper/DomHelper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/Helper/DomHelper.php
new file mode 100644
index 00000000..b8719f42
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/Helper/DomHelper.php
@@ -0,0 +1,54 @@
+[^\S ]+/s',
+
+ // Strip whitespaces before tags, except space
+ '/[^\S ]+\',
+ '<',
+ '\\1'
+ );
+
+ $buffer = preg_replace($search, $replace, $buffer);
+
+ $buffer = str_replace(array(' <', '> '), array('<', '>'), $buffer);
+
+ return trim($buffer);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/Helper/TestDomHelper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/Helper/TestDomHelper.php
new file mode 100644
index 00000000..3c3241b7
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/Helper/TestDomHelper.php
@@ -0,0 +1,52 @@
+[^\S ]+/s',
+
+ // Strip whitespaces before tags, except space
+ '/[^\S ]+\',
+ '<',
+ '\\1'
+ );
+
+ $buffer = preg_replace($search, $replace, $buffer);
+
+ $buffer = str_replace(array(' <', '> '), array('<', '>'), $buffer);
+
+ return trim($buffer);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/Helper/TestStringHelper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/Helper/TestStringHelper.php
new file mode 100644
index 00000000..c8104163
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/Helper/TestStringHelper.php
@@ -0,0 +1,66 @@
+markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test assignMockReturns().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Test\TestHelper::assignMockReturns
+ * @TODO Implement testAssignMockReturns().
+ */
+ public function testAssignMockReturns()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test getValue().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Test\TestHelper::getValue
+ * @TODO Implement testGetValue().
+ */
+ public function testGetValue()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test invoke().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Test\TestHelper::invoke
+ * @TODO Implement testInvoke().
+ */
+ public function testInvoke()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+
+ /**
+ * Method to test setValue().
+ *
+ * @return void
+ *
+ * @covers Windwalker\Test\TestHelper::setValue
+ * @TODO Implement testSetValue().
+ */
+ public function testSetValue()
+ {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet.'
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/TestCase/AbstractBaseTestCase.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/TestCase/AbstractBaseTestCase.php
new file mode 100644
index 00000000..9514911d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/TestCase/AbstractBaseTestCase.php
@@ -0,0 +1,113 @@
+assertEquals(
+ TestStringHelper::clean($expected),
+ TestStringHelper::clean($actual),
+ $message,
+ $delta,
+ $maxDepth,
+ $canonicalize,
+ $ignoreCase
+ );
+ }
+
+ /**
+ * assertStringDataEquals
+ *
+ * @param string $expected
+ * @param string $actual
+ * @param string $message
+ * @param int $delta
+ * @param int $maxDepth
+ * @param bool $canonicalize
+ * @param bool $ignoreCase
+ *
+ * @return void
+ */
+ public function assertStringSafeEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false)
+ {
+ $this->assertEquals(
+ trim(TestStringHelper::removeCRLF($expected)),
+ trim(TestStringHelper::removeCRLF($actual)),
+ $message,
+ $delta,
+ $maxDepth,
+ $canonicalize,
+ $ignoreCase
+ );
+ }
+
+ /**
+ * assertExpectedException
+ *
+ * @param callable $closure
+ * @param string $class
+ * @param string $msg
+ * @param int $code
+ * @param string $message
+ *
+ * @return void
+ */
+ public function assertExpectedException($closure, $class = 'Exception', $msg = null, $code = null, $message = '')
+ {
+ if (is_object($class))
+ {
+ $class = get_class($class);
+ }
+
+ try
+ {
+ $closure();
+ }
+ catch (\Exception $e)
+ {
+ $this->assertInstanceOf($class, $e, $message);
+
+ if ($msg)
+ {
+ $this->assertStringStartsWith($msg, $e->getMessage(), $message);
+ }
+
+ if ($code)
+ {
+ $this->assertEquals($code, $e->getCode(), $message);
+ }
+
+ return;
+ }
+
+ $this->fail('No exception caught.');
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/TestCase/DomTestCase.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/TestCase/DomTestCase.php
new file mode 100644
index 00000000..f33d521e
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/TestCase/DomTestCase.php
@@ -0,0 +1,77 @@
+assertEquals(
+ static::minify($expected),
+ static::minify($actual),
+ $message,
+ $delta,
+ $maxDepth,
+ $canonicalize,
+ $ignoreCase
+ );
+ }
+
+ /**
+ * A simple method to minify Dom and Html.
+ *
+ * Code from: http://stackoverflow.com/questions/6225351/how-to-minify-php-page-html-output
+ *
+ * @param string $buffer
+ *
+ * @return mixed
+ */
+ public static function minify($buffer)
+ {
+ $search = array(
+ // Strip whitespaces after tags, except space
+ '/\>[^\S ]+/s',
+
+ // Strip whitespaces before tags, except space
+ '/[^\S ]+\',
+ '<',
+ '\\1'
+ );
+
+ $buffer = preg_replace($search, $replace, $buffer);
+
+ return $buffer;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/TestEnvironment.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/TestEnvironment.php
new file mode 100644
index 00000000..8c9f7695
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/TestEnvironment.php
@@ -0,0 +1,30 @@
+ $method)
+ {
+ if (is_array($method))
+ {
+ $methodName = $index;
+ $callback = $method;
+ }
+ else
+ {
+ $methodName = $method;
+ $callback = array(get_called_class(), 'mock' . $method);
+ }
+
+ $mockObject->expects($test->any())
+ ->method($methodName)
+ ->will($test->returnCallback($callback));
+ }
+ }
+
+ /**
+ * Assigns mock values to methods.
+ *
+ * @param \PHPUnit_Framework_MockObject_MockObject $mockObject The mock object.
+ * @param \PHPUnit_Framework_TestCase $test The test.
+ * @param array $array An associative array of methods to mock with return values:
+ * string (method name) => mixed (return value)
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ public static function assignMockReturns(\PHPUnit_Framework_MockObject_MockObject $mockObject, \PHPUnit_Framework_TestCase $test, $array)
+ {
+ foreach ($array as $method => $return)
+ {
+ $mockObject->expects($test->any())
+ ->method($method)
+ ->will($test->returnValue($return));
+ }
+ }
+
+ /**
+ * Helper method that gets a protected or private property in a class by relfection.
+ *
+ * @param object $object The object from which to return the property value.
+ * @param string $propertyName The name of the property to return.
+ *
+ * @return mixed The value of the property.
+ *
+ * @since 2.0
+ * @throws \InvalidArgumentException if property not available.
+ */
+ public static function getValue($object, $propertyName)
+ {
+ $refl = new \ReflectionClass($object);
+
+ // First check if the property is easily accessible.
+ if ($refl->hasProperty($propertyName))
+ {
+ $property = $refl->getProperty($propertyName);
+ $property->setAccessible(true);
+
+ return $property->getValue($object);
+ }
+
+ // Hrm, maybe dealing with a private property in the parent class.
+ if (get_parent_class($object))
+ {
+ $property = new \ReflectionProperty(get_parent_class($object), $propertyName);
+ $property->setAccessible(true);
+
+ return $property->getValue($object);
+ }
+
+ throw new \InvalidArgumentException(sprintf('Invalid property [%s] for class [%s]', $propertyName, get_class($object)));
+ }
+
+ /**
+ * Helper method that invokes a protected or private method in a class by reflection.
+ *
+ * Example usage:
+ *
+ * $this->asserTrue(TestCase::invoke('methodName', $this->object, 123));
+ *
+ * @param object $object The object on which to invoke the method.
+ * @param string $methodName The name of the method to invoke.
+ *
+ * @return mixed
+ *
+ * @since 2.0
+ */
+ public static function invoke($object, $methodName)
+ {
+ // Get the full argument list for the method.
+ $args = func_get_args();
+
+ // Remove the method name from the argument list.
+ array_shift($args);
+ array_shift($args);
+
+ $method = new \ReflectionMethod($object, $methodName);
+ $method->setAccessible(true);
+
+ $result = $method->invokeArgs(is_object($object) ? $object : null, $args);
+
+ return $result;
+ }
+
+ /**
+ * Helper method that sets a protected or private property in a class by relfection.
+ *
+ * @param object $object The object for which to set the property.
+ * @param string $propertyName The name of the property to set.
+ * @param mixed $value The value to set for the property.
+ *
+ * @return void
+ *
+ * @since 2.0
+ */
+ public static function setValue($object, $propertyName, $value)
+ {
+ $refl = new \ReflectionClass($object);
+
+ // First check if the property is easily accessible.
+ if ($refl->hasProperty($propertyName))
+ {
+ $property = $refl->getProperty($propertyName);
+ $property->setAccessible(true);
+
+ $property->setValue($object, $value);
+ }
+ elseif (get_parent_class($object))
+ // Hrm, maybe dealing with a private property in the parent class.
+ {
+ $property = new \ReflectionProperty(get_parent_class($object), $propertyName);
+ $property->setAccessible(true);
+
+ $property->setValue($object, $value);
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/composer.json b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/composer.json
new file mode 100644
index 00000000..4a83bf88
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/composer.json
@@ -0,0 +1,25 @@
+{
+ "name": "windwalker/test",
+ "type": "windwalker-package",
+ "description": "Windwalker Test package",
+ "keywords": ["windwalker", "framework", "test"],
+ "homepage": "https://github.com/ventoviro/windwalker-test",
+ "license": "LGPL-2.0+",
+ "require": {
+ "php": ">=5.3.10",
+ "windwalker/environment": "~2.0"
+ },
+ "require-dev": {
+ },
+ "minimum-stability": "beta",
+ "autoload": {
+ "psr-4": {
+ "Windwalker\\Test\\": ""
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/phpunit.travis.xml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/phpunit.travis.xml
new file mode 100644
index 00000000..690ec926
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/phpunit.travis.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/phpunit.xml.dist b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/phpunit.xml.dist
new file mode 100644
index 00000000..94b6811c
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/test/phpunit.xml.dist
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/.gitignore b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/.gitignore
new file mode 100644
index 00000000..84718b5d
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/.gitignore
@@ -0,0 +1,11 @@
+# Development system files #
+.*
+!/.gitignore
+!/.travis.yml
+
+# Composer #
+vendor/*
+composer.lock
+
+# Test #
+phpunit.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/.travis.yml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/.travis.yml
new file mode 100644
index 00000000..5420e5c4
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/.travis.yml
@@ -0,0 +1,16 @@
+language: php
+
+sudo: false
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+
+before_script:
+ - composer update --dev
+
+script:
+ - phpunit --configuration phpunit.travis.xml
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/ArrayHelper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/ArrayHelper.php
new file mode 100644
index 00000000..94d50805
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/ArrayHelper.php
@@ -0,0 +1,1139 @@
+ $v)
+ {
+ if (is_array($v))
+ {
+ $obj->$k = static::toObject($v, $class);
+ }
+ else
+ {
+ $obj->$k = $v;
+ }
+ }
+
+ return $obj;
+ }
+
+ /**
+ * Utility function to convert all types to an array.
+ *
+ * @param mixed $data The data to convert.
+ * @param bool $recursive Recursive if data is nested.
+ *
+ * @return array The converted array.
+ */
+ public static function toArray($data, $recursive = false)
+ {
+ // Ensure the input data is an array.
+ if ($data instanceof \Traversable)
+ {
+ $data = iterator_to_array($data);
+ }
+ elseif (is_object($data))
+ {
+ $data = get_object_vars($data);
+ }
+ else
+ {
+ $data = (array) $data;
+ }
+
+ if ($recursive)
+ {
+ foreach ($data as &$value)
+ {
+ if (is_array($value) || is_object($value))
+ {
+ $value = static::toArray($value, $recursive);
+ }
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * Utility function to map an array to a string.
+ *
+ * @param array $array The array to map.
+ * @param string $inner_glue The glue (optional, defaults to '=') between the key and the value.
+ * @param string $outer_glue The glue (optional, defaults to ' ') between array elements.
+ * @param boolean $keepOuterKey True if final key should be kept.
+ *
+ * @return string The string mapped from the given array
+ *
+ * @since 2.0
+ */
+ public static function toString(array $array, $inner_glue = '=', $outer_glue = ' ', $keepOuterKey = false)
+ {
+ $output = array();
+
+ foreach ($array as $key => $item)
+ {
+ if (is_array($item))
+ {
+ if ($keepOuterKey)
+ {
+ $output[] = $key;
+ }
+
+ // This is value is an array, go and do it again!
+ $output[] = self::toString($item, $inner_glue, $outer_glue, $keepOuterKey);
+ }
+ else
+ {
+ $output[] = $key . $inner_glue . '"' . $item . '"';
+ }
+ }
+
+ return implode($outer_glue, $output);
+ }
+
+ /**
+ * Utility function to map an object to an array
+ *
+ * @param object $source The source object
+ * @param boolean $recurse True to recurse through multi-level objects
+ * @param string $regex An optional regular expression to match on field names
+ *
+ * @return array The array mapped from the given object
+ *
+ * @since 2.0
+ */
+ public static function fromObject($source, $recurse = true, $regex = null)
+ {
+ if (is_object($source))
+ {
+ return static::arrayFromObject($source, $recurse, $regex);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Utility function to map an object or array to an array
+ *
+ * @param mixed $item The source object or array
+ * @param boolean $recurse True to recurse through multi-level objects
+ * @param string $regex An optional regular expression to match on field names
+ *
+ * @return array The array mapped from the given object
+ *
+ * @since 2.0
+ */
+ private static function arrayFromObject($item, $recurse, $regex)
+ {
+ if (is_object($item))
+ {
+ $result = array();
+
+ foreach (get_object_vars($item) as $k => $v)
+ {
+ if (!$regex || preg_match($regex, $k))
+ {
+ if ($recurse)
+ {
+ $result[$k] = self::arrayFromObject($v, $recurse, $regex);
+ }
+ else
+ {
+ $result[$k] = $v;
+ }
+ }
+ }
+ }
+ elseif (is_array($item))
+ {
+ $result = array();
+
+ foreach ($item as $k => $v)
+ {
+ $result[$k] = self::arrayFromObject($v, $recurse, $regex);
+ }
+ }
+ else
+ {
+ $result = $item;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Extracts a column from an array of arrays or objects
+ *
+ * @param array $array The source array
+ * @param string $index The index of the column or name of object property
+ *
+ * @return array Column of values from the source array
+ *
+ * @since 2.0
+ */
+ public static function getColumn(array $array, $index)
+ {
+ $result = array();
+
+ foreach ($array as $item)
+ {
+ if (is_array($item) && isset($item[$index]))
+ {
+ $result[] = $item[$index];
+ }
+ elseif (is_object($item) && isset($item->$index))
+ {
+ $result[] = $item->$index;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Utility function to return a value from a named array or a specified default
+ *
+ * @param array $source A named array or object.
+ * @param string $name The key to search for
+ * @param mixed $default The default value to give if no key found
+ * @param string $type Return type for the variable (INT, FLOAT, STRING, WORD, BOOLEAN, ARRAY)
+ *
+ * @return mixed The value from the source array
+ *
+ * @since 2.0
+ */
+ public static function getValue($source, $name, $default = null, $type = '')
+ {
+ if (!is_array($source) && !is_object($source))
+ {
+ throw new \InvalidArgumentException('The object must be an array or a object that implements ArrayAccess');
+ }
+
+ $result = null;
+
+ if (is_array($source) && isset($source[$name]))
+ {
+ $result = $source[$name];
+ }
+ elseif (is_object($source) && isset($source->$name))
+ {
+ $result = $source->$name;
+ }
+
+ // Handle the default case
+ if (is_null($result))
+ {
+ $result = $default;
+ }
+
+ // Handle the type constraint
+ switch (strtoupper($type))
+ {
+ case 'INT':
+ case 'INTEGER':
+ // Only use the first integer value
+ @preg_match('/-?[0-9]+/', $result, $matches);
+ $result = @(int) $matches[0];
+ break;
+
+ case 'FLOAT':
+ case 'DOUBLE':
+ // Only use the first floating point value
+ @preg_match('/-?[0-9]+(\.[0-9]+)?/', $result, $matches);
+ $result = @(float) $matches[0];
+ break;
+
+ case 'BOOL':
+ case 'BOOLEAN':
+ $result = (bool) $result;
+ break;
+
+ case 'ARRAY':
+ if (!is_array($result))
+ {
+ $result = array($result);
+ }
+ break;
+
+ case 'STRING':
+ $result = (string) $result;
+ break;
+
+ case 'WORD':
+ $result = (string) preg_replace('#\W#', '', $result);
+ break;
+
+ case 'NONE':
+ default:
+ // No casting necessary
+ break;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Set a value into array or object.
+ *
+ * @param mixed &$array An array to set value.
+ * @param string $key Array key to store this value.
+ * @param mixed $value Value which to set into array or object.
+ *
+ * @return mixed Result array or object.
+ */
+ public static function setValue(&$array, $key, $value)
+ {
+ if (is_array($array))
+ {
+ $array[$key] = $value;
+ }
+ elseif (is_object($array))
+ {
+ $array->$key = $value;
+ }
+
+ return $array;
+ }
+
+ /**
+ * Takes an associative array of arrays and inverts the array keys to values using the array values as keys.
+ *
+ * Example:
+ * $input = array(
+ * 'New' => array('1000', '1500', '1750'),
+ * 'Used' => array('3000', '4000', '5000', '6000')
+ * );
+ * $output = ArrayHelper::invert($input);
+ *
+ * Output would be equal to:
+ * $output = array(
+ * '1000' => 'New',
+ * '1500' => 'New',
+ * '1750' => 'New',
+ * '3000' => 'Used',
+ * '4000' => 'Used',
+ * '5000' => 'Used',
+ * '6000' => 'Used'
+ * );
+ *
+ * @param array $array The source array.
+ *
+ * @return array The inverted array.
+ *
+ * @since 2.0
+ */
+ public static function invert(array $array)
+ {
+ $return = array();
+
+ foreach ($array as $base => $values)
+ {
+ if (!is_array($values))
+ {
+ continue;
+ }
+
+ foreach ($values as $key)
+ {
+ // If the key isn't scalar then ignore it.
+ if (is_scalar($key))
+ {
+ $return[$key] = $base;
+ }
+ }
+ }
+
+ return $return;
+ }
+
+ /**
+ * Method to determine if an array is an associative array.
+ *
+ * @param array $array An array to test.
+ *
+ * @return boolean True if the array is an associative array.
+ *
+ * @since 2.0
+ */
+ public static function isAssociative($array)
+ {
+ if (is_array($array))
+ {
+ foreach (array_keys($array) as $k => $v)
+ {
+ if ($k !== $v)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Pivots an array to create a reverse lookup of an array of scalars, arrays or objects.
+ *
+ * @param array $source The source array.
+ * @param string $key Where the elements of the source array are objects or arrays, the key to pivot on.
+ *
+ * @return array An array of arrays pivoted either on the value of the keys, or an individual key of an object or array.
+ *
+ * @since 2.0
+ */
+ public static function pivot(array $source, $key = null)
+ {
+ $result = array();
+ $counter = array();
+
+ foreach ($source as $index => $value)
+ {
+ // Determine the name of the pivot key, and its value.
+ if (is_array($value))
+ {
+ // If the key does not exist, ignore it.
+ if (!isset($value[$key]))
+ {
+ continue;
+ }
+
+ $resultKey = $value[$key];
+ $resultValue = $source[$index];
+ }
+ elseif (is_object($value))
+ {
+ // If the key does not exist, ignore it.
+ if (!isset($value->$key))
+ {
+ continue;
+ }
+
+ $resultKey = $value->$key;
+ $resultValue = $source[$index];
+ }
+ else
+ {
+ // Just a scalar value.
+ $resultKey = $value;
+ $resultValue = $index;
+ }
+
+ // The counter tracks how many times a key has been used.
+ if (empty($counter[$resultKey]))
+ {
+ // The first time around we just assign the value to the key.
+ $result[$resultKey] = $resultValue;
+ $counter[$resultKey] = 1;
+ }
+ elseif ($counter[$resultKey] == 1)
+ {
+ // If there is a second time, we convert the value into an array.
+ $result[$resultKey] = array(
+ $result[$resultKey],
+ $resultValue,
+ );
+ $counter[$resultKey]++;
+ }
+ else
+ {
+ // After the second time, no need to track any more. Just append to the existing array.
+ $result[$resultKey][] = $resultValue;
+ }
+ }
+
+ unset($counter);
+
+ return $result;
+ }
+
+ /**
+ * Pivot Array, separate by key. Same as AKHelperArray::pivot().
+ * From:
+ * [value] => Array
+ * (
+ * [0] => aaa
+ * [1] => bbb
+ * )
+ * [text] => Array
+ * (
+ * [0] => aaa
+ * [1] => bbb
+ * )
+ * To:
+ * [0] => Array
+ * (
+ * [value] => aaa
+ * [text] => aaa
+ * )
+ * [1] => Array
+ * (
+ * [value] => bbb
+ * [text] => bbb
+ * )
+ *
+ * @param array $array An array with two level.
+ *
+ * @return array An pivoted array.
+ */
+ public static function pivotByKey($array)
+ {
+ $array = (array) $array;
+ $new = array();
+ $keys = array_keys($array);
+
+ foreach ($keys as $k => $val)
+ {
+ foreach ((array) $array[$val] as $k2 => $v2)
+ {
+ $new[$k2][$val] = $v2;
+ }
+ }
+
+ return $new;
+ }
+
+ /**
+ * Utility function to sort an array of objects on a given field
+ *
+ * @param array $a An array of objects
+ * @param mixed $k The key (string) or a array of key to sort on
+ * @param mixed $direction Direction (integer) or an array of direction to sort in [1 = Ascending] [-1 = Descending]
+ * @param mixed $caseSensitive Boolean or array of booleans to let sort occur case sensitive or insensitive
+ * @param mixed $locale Boolean or array of booleans to let sort occur using the locale language or not
+ *
+ * @return array The sorted array of objects
+ *
+ * @since 2.0
+ */
+ public static function sortObjects(array $a, $k, $direction = 1, $caseSensitive = true, $locale = false)
+ {
+ if (!is_array($locale) || !is_array($locale[0]))
+ {
+ $locale = array($locale);
+ }
+
+ $sortCase = (array) $caseSensitive;
+ $sortDirection = (array) $direction;
+ $key = (array) $k;
+ $sortLocale = $locale;
+
+ usort(
+ $a, function($a, $b) use($sortCase, $sortDirection, $key, $sortLocale)
+ {
+ for ($i = 0, $count = count($key); $i < $count; $i++)
+ {
+ if (isset($sortDirection[$i]))
+ {
+ $direction = $sortDirection[$i];
+ }
+
+ if (isset($sortCase[$i]))
+ {
+ $caseSensitive = $sortCase[$i];
+ }
+
+ if (isset($sortLocale[$i]))
+ {
+ $locale = $sortLocale[$i];
+ }
+
+ $va = $a->{$key[$i]};
+ $vb = $b->{$key[$i]};
+
+ if ((is_bool($va) || is_numeric($va)) && (is_bool($vb) || is_numeric($vb)))
+ {
+ $cmp = $va - $vb;
+ }
+ elseif ($caseSensitive)
+ {
+ $cmp = Utf8String::strcmp($va, $vb, $locale);
+ }
+ else
+ {
+ $cmp = Utf8String::strcasecmp($va, $vb, $locale);
+ }
+
+ if ($cmp > 0)
+ {
+ return $direction;
+ }
+
+ if ($cmp < 0)
+ {
+ return -$direction;
+ }
+ }
+
+ return 0;
+ }
+ );
+
+ return $a;
+ }
+
+ /**
+ * Multidimensional array safe unique test
+ *
+ * @param array $array The array to make unique.
+ *
+ * @return array
+ *
+ * @see http://php.net/manual/en/function.array-unique.php
+ * @since 2.0
+ */
+ public static function arrayUnique(array $array)
+ {
+ $array = array_map('serialize', $array);
+ $array = array_unique($array);
+ $array = array_map('unserialize', $array);
+
+ return $array;
+ }
+
+ /**
+ * An improved array_search that allows for partial matching
+ * of strings values in associative arrays.
+ *
+ * @param string $needle The text to search for within the array.
+ * @param array $haystack Associative array to search in to find $needle.
+ * @param boolean $caseSensitive True to search case sensitive, false otherwise.
+ *
+ * @return mixed Returns the matching array $key if found, otherwise false.
+ *
+ * @since 2.0
+ */
+ public static function arraySearch($needle, array $haystack, $caseSensitive = true)
+ {
+ foreach ($haystack as $key => $value)
+ {
+ $searchFunc = ($caseSensitive) ? 'strpos' : 'stripos';
+
+ if ($searchFunc($value, $needle) === 0)
+ {
+ return $key;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * array_merge_recursive does indeed merge arrays, but it converts values with duplicate
+ * keys to arrays rather than overwriting the value in the first array with the duplicate
+ * value in the second array, as array_merge does. I.e., with array_merge_recursive,
+ * this happens (documented behavior):
+ *
+ * array_merge_recursive(array('key' => 'org value'), array('key' => 'new value'));
+ * => array('key' => array('org value', 'new value'));
+ *
+ * array_merge_recursive_distinct does not change the datatypes of the values in the arrays.
+ * Matching keys' values in the second array overwrite those in the first array, as is the
+ * case with array_merge, i.e.:
+ *
+ * array_merge_recursive_distinct(array('key' => 'org value'), array('key' => 'new value'));
+ * => array('key' => array('new value'));
+ *
+ * Parameters are passed by reference, though only for performance reasons. They're not
+ * altered by this function.
+ *
+ * @param array &$array1 Array to be merge.
+ * @param array &$array2 Array to be merge.
+ * @param boolean $recursive Recursive merge, default is true.
+ *
+ * @return array Merged array.
+ *
+ * @since 2.0
+ *
+ * @author Daniel
+ * @author Gabriel Sobrinho
+ */
+ public static function merge(array &$array1, array &$array2, $recursive = true)
+ {
+ $merged = $array1;
+
+ foreach ($array2 as $key => &$value)
+ {
+ if ($recursive && is_array($value) && isset($merged[$key]) && is_array($merged[$key]))
+ {
+ $merged[$key] = static::merge($merged [$key], $value);
+ }
+ else
+ {
+ $merged[$key] = $value;
+ }
+ }
+
+ return $merged;
+ }
+
+ /**
+ * Get data from array or object by path.
+ *
+ * Example: `ArrayHelper::getByPath($array, 'foo.bar.yoo')` equals to $array['foo']['bar']['yoo'].
+ *
+ * @param mixed $data An array or object to get value.
+ * @param mixed $path The key path.
+ * @param string $separator Separator of paths.
+ *
+ * @return mixed Found value, null if not exists.
+ *
+ * @since 2.0
+ */
+ public static function getByPath($data, $path, $separator = '.')
+ {
+ $nodes = array_values(array_filter(explode($separator, $path), 'strlen'));
+
+ if (empty($nodes))
+ {
+ return null;
+ }
+
+ $dataTmp = $data;
+
+ foreach ($nodes as $arg)
+ {
+ if (is_object($dataTmp) && isset($dataTmp->$arg))
+ {
+ $dataTmp = $dataTmp->$arg;
+ }
+ elseif ($dataTmp instanceof \ArrayAccess && isset($dataTmp[$arg]))
+ {
+ $dataTmp = $dataTmp[$arg];
+ }
+ elseif (is_array($dataTmp) && isset($dataTmp[$arg]))
+ {
+ $dataTmp = $dataTmp[$arg];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ return $dataTmp;
+ }
+
+ /**
+ * setByPath
+ *
+ * @param mixed &$data
+ * @param string $path
+ * @param mixed $value
+ * @param string $separator
+ * @param string $storeType
+ *
+ * @return boolean
+ *
+ * @since 2.0
+ */
+ public static function setByPath(&$data, $path, $value, $separator = '.', $storeType = 'array')
+ {
+ $nodes = array_values(array_filter(explode($separator, $path), 'strlen'));
+
+ if (empty($nodes))
+ {
+ return false;
+ }
+
+ /**
+ * A closure as inner function to create data store.
+ *
+ * @param string $type
+ *
+ * @return array
+ *
+ * @throws \InvalidArgumentException
+ */
+ $createStore = function($type)
+ {
+ if (strtolower($type) == 'array')
+ {
+ return array();
+ }
+
+ if (class_exists($type))
+ {
+ return new $type;
+ }
+
+ throw new \InvalidArgumentException(sprintf('Type or class: %s not exists', $type));
+ };
+
+ $dataTmp = &$data;
+
+ foreach ($nodes as $node)
+ {
+ if (is_object($dataTmp))
+ {
+ if (empty($dataTmp->$node))
+ {
+ $dataTmp->$node = $createStore($storeType);
+ }
+
+ $dataTmp = &$dataTmp->$node;
+ }
+ elseif (is_array($dataTmp))
+ {
+ if (empty($dataTmp[$node]))
+ {
+ $dataTmp[$node] = $createStore($storeType);
+ }
+
+ $dataTmp = &$dataTmp[$node];
+ }
+ else
+ {
+ // If a node is value but path is not go to the end, we replace this value as a new store.
+ // Then next node can insert new value to this store.
+ $dataTmp = &$createStore($storeType);
+ }
+ }
+
+ // Now, path go to the end, means we get latest node, set value to this node.
+ $dataTmp = $value;
+
+ return true;
+ }
+
+ /**
+ * Recursive dump variables and limit by level.
+ *
+ * @param mixed $data The variable you want to dump.
+ * @param int $level The level number to limit recursive loop.
+ *
+ * @return string Dumped data.
+ *
+ * @since 2.0
+ */
+ public static function dump($data, $level = 5)
+ {
+ static $innerLevel = 1;
+
+ static $tabLevel = 1;
+
+ $self = __FUNCTION__;
+
+ $type = gettype($data);
+ $tabs = str_repeat(' ', $tabLevel);
+ $quoteTabes = str_repeat(' ', $tabLevel - 1);
+ $output = '';
+ $elements = array();
+
+ $recursiveType = array('object', 'array');
+
+ // Recursive
+ if (in_array($type, $recursiveType))
+ {
+ // If type is object, try to get properties by Reflection.
+ if ($type == 'object')
+ {
+ $output = get_class($data) . ' ' . ucfirst($type);
+ $ref = new \ReflectionObject($data);
+ $properties = $ref->getProperties();
+
+ foreach ($properties as $property)
+ {
+ $property->setAccessible(true);
+
+ $pType = $property->getName();
+
+ if ($property->isProtected())
+ {
+ $pType .= ":protected";
+ }
+ elseif ($property->isPrivate())
+ {
+ $pType .= ":" . $property->class . ":private";
+ }
+
+ if ($property->isStatic())
+ {
+ $pType .= ":static";
+ }
+
+ $elements[$pType] = $property->getValue($data);
+ }
+ }
+ // If type is array, just retun it's value.
+ elseif ($type == 'array')
+ {
+ $output = ucfirst($type);
+ $elements = $data;
+ }
+
+ // Start dumping data
+ if ($level == 0 || $innerLevel < $level)
+ {
+ // Start recursive print
+ $output .= "\n{$quoteTabes}(";
+
+ foreach ($elements as $key => $element)
+ {
+ $output .= "\n{$tabs}[{$key}] => ";
+
+ // Increment level
+ $tabLevel = $tabLevel + 2;
+ $innerLevel++;
+
+ $output .= in_array(gettype($element), $recursiveType) ? static::$self($element, $level) : $element;
+
+ // Decrement level
+ $tabLevel = $tabLevel - 2;
+ $innerLevel--;
+ }
+
+ $output .= "\n{$quoteTabes})\n";
+ }
+ else
+ {
+ $output .= "\n{$quoteTabes}*MAX LEVEL*\n";
+ }
+ }
+ else
+ {
+ $output = $data;
+ }
+
+ return $output;
+ }
+
+ /**
+ * Method to recursively convert data to one dimension array.
+ *
+ * @param array|object $array The array or object to convert.
+ * @param string $separator The key separator.
+ * @param string $prefix Last level key prefix.
+ *
+ * @return array
+ */
+ public static function flatten($array, $separator = '.', $prefix = '')
+ {
+ $return = array();
+
+ if ($array instanceof \Traversable)
+ {
+ $array = iterator_to_array($array);
+ }
+ elseif (is_object($array))
+ {
+ $array = get_object_vars($array);
+ }
+
+ foreach ($array as $k => $v)
+ {
+ $key = $prefix ? $prefix . $separator . $k : $k;
+
+ if (is_object($v) || is_array($v))
+ {
+ $return = array_merge($return, static::flatten($v, $separator, $key));
+ }
+ else
+ {
+ $return[$key] = $v;
+ }
+ }
+
+ return $return;
+ }
+
+ /**
+ * Query a two-dimensional array values to get second level array.
+ *
+ * @param array $array An array to query.
+ * @param mixed $queries Query strings, may contain Comparison Operators: '>', '>=', '<', '<='.
+ * Example:
+ * array(
+ * 'id' => 6, // Get all elements where id=6
+ * '>published' => 0 // Get all elements where published>0
+ * );
+ * @param boolean $strict Use strict to compare equals.
+ * @param boolean $keepKey Keep origin array keys.
+ *
+ * @return array An new two-dimensional array queried.
+ *
+ * @since 2.0
+ */
+ public static function query($array, $queries = array(), $strict = false, $keepKey = false)
+ {
+ $results = array();
+ $queries = (array) $queries;
+
+ // Visit Array
+ foreach ((array) $array as $k => $v)
+ {
+ $data = (array) $v;
+
+ // Visit Query Rules
+ foreach ($queries as $key => $val)
+ {
+ /*
+ * Key: is query key
+ * Val: is query value
+ * Data: is array element
+ */
+ $value = null;
+
+ if (substr($key, -2) == '>=')
+ {
+ if (static::getByPath($data, trim(substr($key, 0, -2))) >= $val)
+ {
+ $value = $v;
+ }
+ }
+ elseif (substr($key, -2) == '<=')
+ {
+ if (static::getByPath($data, trim(substr($key, 0, -2))) <= $val)
+ {
+ $value = $v;
+ }
+ }
+ elseif (substr($key, -1) == '>')
+ {
+ if (static::getByPath($data, trim(substr($key, 0, -1))) > $val)
+ {
+ $value = $v;
+ }
+ }
+ elseif (substr($key, -1) == '<')
+ {
+ if (static::getByPath($data, trim(substr($key, 0, -1))) < $val)
+ {
+ $value = $v;
+ }
+ }
+ else
+ {
+ if ($strict)
+ {
+ if (static::getByPath($data, $key) === $val)
+ {
+ $value = $v;
+ }
+ }
+ else
+ {
+ // Workaround for PHP 5.4 object compare bug, see: https://bugs.php.net/bug.php?id=62976
+ $compare1 = is_object(static::getByPath($data, $key)) ? get_object_vars(static::getByPath($data, $key)) : static::getByPath($data, $key);
+ $compare2 = is_object($val) ? get_object_vars($val) : $val;
+
+ if ($compare1 == $compare2)
+ {
+ $value = $v;
+ }
+ }
+ }
+
+ // Set Query results
+ if ($value)
+ {
+ if ($keepKey)
+ {
+ $results[$k] = $value;
+ }
+ else
+ {
+ $results[] = $value;
+ }
+ }
+ }
+ }
+
+ return $results;
+ }
+
+ /**
+ * Convert an Array or Object keys to new name by an array index.
+ *
+ * @param mixed $origin Array or Object to convert.
+ * @param mixed $map Array or Object index for convert.
+ *
+ * @return mixed Mapped array or object.
+ */
+ public static function mapKey($origin, $map = array())
+ {
+ $result = is_array($origin) ? array() : new \stdClass;
+
+ foreach ((array) $origin as $key => $val)
+ {
+ $newKey = self::getValue($map, $key);
+
+ if ($newKey)
+ {
+ self::setValue($result, $newKey, $val);
+ }
+ else
+ {
+ self::setValue($result, $key, $val);
+ }
+ }
+
+ return $result;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Classes/MultiSingletonTrait.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Classes/MultiSingletonTrait.php
new file mode 100644
index 00000000..d75dc36b
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Classes/MultiSingletonTrait.php
@@ -0,0 +1,66 @@
+setFlags($flags);
+ $this->storage = $input;
+ $this->setIteratorClass($iteratorClass);
+ $this->protectedProperties = array_keys(get_object_vars($this));
+ }
+
+ /**
+ * Returns whether the requested key exists
+ *
+ * @param mixed $key
+ *
+ * @throws \InvalidArgumentException
+ * @return boolean
+ */
+ public function __isset($key)
+ {
+ if ($this->flag == self::ARRAY_AS_PROPS)
+ {
+ return $this->offsetExists($key);
+ }
+
+ if (in_array($key, $this->protectedProperties))
+ {
+ throw new \InvalidArgumentException('$key is a protected property, use a different key');
+ }
+
+ return isset($this->$key);
+ }
+
+ /**
+ * Sets the value at the specified key to value
+ *
+ * @param mixed $key
+ * @param mixed $value
+ *
+ * @throws \InvalidArgumentException
+ * @return void|mixed
+ */
+ public function __set($key, $value)
+ {
+ if ($this->flag == self::ARRAY_AS_PROPS)
+ {
+ $this->offsetSet($key, $value);
+
+ return;
+ }
+
+ if (in_array($key, $this->protectedProperties))
+ {
+ throw new \InvalidArgumentException('$key is a protected property, use a different key');
+ }
+
+ $this->$key = $value;
+ }
+
+ /**
+ * Unsets the value at the specified key
+ *
+ * @param mixed $key
+ *
+ * @throws \InvalidArgumentException
+ * @return void|mixed
+ */
+ public function __unset($key)
+ {
+ if ($this->flag == self::ARRAY_AS_PROPS)
+ {
+ $this->offsetUnset($key);
+
+ return;
+ }
+
+ if (in_array($key, $this->protectedProperties))
+ {
+ throw new \InvalidArgumentException('$key is a protected property, use a different key');
+ }
+
+ unset($this->$key);
+ }
+
+ /**
+ * Returns the value at the specified key by reference
+ *
+ * @param mixed $key
+ *
+ * @throws \InvalidArgumentException
+ * @return mixed
+ */
+ public function &__get($key)
+ {
+ $ret = null;
+
+ if ($this->flag == self::ARRAY_AS_PROPS)
+ {
+ $ret =& $this->offsetGet($key);
+
+ return $ret;
+ }
+
+ if (in_array($key, $this->protectedProperties))
+ {
+ throw new \InvalidArgumentException('$key is a protected property, use a different key');
+ }
+
+ return $this->$key;
+ }
+
+ /**
+ * Appends the value
+ *
+ * @param mixed $value
+ *
+ * @return void
+ */
+ public function append($value)
+ {
+ $this->storage[] = $value;
+ }
+
+ /**
+ * Sort the entries by value
+ *
+ * @return void
+ */
+ public function asort()
+ {
+ asort($this->storage);
+ }
+
+ /**
+ * Get the number of public properties in the ArrayObject
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->storage);
+ }
+
+ /**
+ * Exchange the array for another one.
+ *
+ * @param array|ArrayObject $data
+ *
+ * @throws \InvalidArgumentException
+ * @return array
+ */
+ public function exchangeArray($data)
+ {
+ if (!is_array($data) && !is_object($data))
+ {
+ throw new \InvalidArgumentException('Passed variable is not an array or object, using empty array instead');
+ }
+
+ if (is_object($data) && ($data instanceof self || $data instanceof \ArrayObject))
+ {
+ $data = $data->getArrayCopy();
+ }
+
+ if (!is_array($data))
+ {
+ $data = (array) $data;
+ }
+
+ $storage = $this->storage;
+
+ $this->storage = $data;
+
+ return $storage;
+ }
+
+ /**
+ * Creates a copy of the ArrayObject.
+ *
+ * @return array
+ */
+ public function getArrayCopy()
+ {
+ return $this->storage;
+ }
+
+ /**
+ * Gets the behavior flags.
+ *
+ * @return int
+ */
+ public function getFlags()
+ {
+ return $this->flag;
+ }
+
+ /**
+ * Create a new iterator from an ArrayObject instance
+ *
+ * @return \Iterator
+ */
+ public function getIterator()
+ {
+ $class = $this->iteratorClass;
+
+ return new $class($this->storage);
+ }
+
+ /**
+ * Gets the iterator classname for the ArrayObject.
+ *
+ * @return string
+ */
+ public function getIteratorClass()
+ {
+ return $this->iteratorClass;
+ }
+
+ /**
+ * Sort the entries by key
+ *
+ * @return void
+ */
+ public function ksort()
+ {
+ ksort($this->storage);
+ }
+
+ /**
+ * Sort an array using a case insensitive "natural order" algorithm
+ *
+ * @return void
+ */
+ public function natcasesort()
+ {
+ natcasesort($this->storage);
+ }
+
+ /**
+ * Sort entries using a "natural order" algorithm
+ *
+ * @return void
+ */
+ public function natsort()
+ {
+ natsort($this->storage);
+ }
+
+ /**
+ * Returns whether the requested key exists
+ *
+ * @param mixed $key
+ *
+ * @return bool
+ */
+ public function offsetExists($key)
+ {
+ return isset($this->storage[$key]);
+ }
+
+ /**
+ * Returns the value at the specified key
+ *
+ * @param mixed $key
+ *
+ * @return mixed
+ */
+ public function &offsetGet($key)
+ {
+ $ret = null;
+
+ if (!$this->offsetExists($key))
+ {
+ return $ret;
+ }
+
+ $ret =& $this->storage[$key];
+
+ return $ret;
+ }
+
+ /**
+ * Sets the value at the specified key to value
+ *
+ * @param mixed $key
+ * @param mixed $value
+ *
+ * @return void
+ */
+ public function offsetSet($key, $value)
+ {
+ $this->storage[$key] = $value;
+ }
+
+ /**
+ * Unsets the value at the specified key
+ *
+ * @param mixed $key
+ *
+ * @return void
+ */
+ public function offsetUnset($key)
+ {
+ if ($this->offsetExists($key))
+ {
+ unset($this->storage[$key]);
+ }
+ }
+
+ /**
+ * Serialize an ArrayObject
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ return serialize(get_object_vars($this));
+ }
+
+ /**
+ * Sets the behavior flags
+ *
+ * @param int $flags
+ *
+ * @return void
+ */
+ public function setFlags($flags)
+ {
+ $this->flag = $flags;
+ }
+
+ /**
+ * Sets the iterator classname for the ArrayObject
+ *
+ * @param string $class
+ *
+ * @throws \InvalidArgumentException
+ * @return void
+ */
+ public function setIteratorClass($class)
+ {
+ if (class_exists($class))
+ {
+ $this->iteratorClass = $class;
+
+ return;
+ }
+
+ if (strpos($class, '\\') === 0)
+ {
+ $class = '\\' . $class;
+
+ if (class_exists($class))
+ {
+ $this->iteratorClass = $class;
+
+ return;
+ }
+ }
+
+ throw new \InvalidArgumentException('The iterator class does not exist');
+ }
+
+ /**
+ * Sort the entries with a user-defined comparison function and maintain key association
+ *
+ * @param callable $function
+ *
+ * @return void
+ */
+ public function uasort($function)
+ {
+ if (is_callable($function))
+ {
+ uasort($this->storage, $function);
+ }
+ }
+
+ /**
+ * Sort the entries by keys using a user-defined comparison function
+ *
+ * @param callable $function
+ *
+ * @return void
+ */
+ public function uksort($function)
+ {
+ if (is_callable($function))
+ {
+ uksort($this->storage, $function);
+ }
+ }
+
+ /**
+ * Unserialize an ArrayObject
+ *
+ * @param string $data
+ *
+ * @return void
+ */
+ public function unserialize($data)
+ {
+ $ar = unserialize($data);
+
+ $this->protectedProperties = array_keys(get_object_vars($this));
+
+ $this->setFlags($ar['flag']);
+ $this->exchangeArray($ar['storage']);
+ $this->setIteratorClass($ar['iteratorClass']);
+
+ foreach ($ar as $k => $v)
+ {
+ switch ($k)
+ {
+ case 'flag':
+ $this->setFlags($v);
+ break;
+ case 'storage':
+ $this->exchangeArray($v);
+ break;
+ case 'iteratorClass':
+ $this->setIteratorClass($v);
+ break;
+ case 'protectedProperties':
+ continue;
+ default:
+ $this->__set($k, $v);
+ }
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Iterator/DualIterator.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Iterator/DualIterator.php
new file mode 100644
index 00000000..2a45c9ff
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Iterator/DualIterator.php
@@ -0,0 +1,265 @@
+lhs = $lhs;
+ $this->rhs = $rhs;
+ $this->flags = $flags;
+ }
+
+ /**
+ * Get lhs.
+ *
+ * @return \Iterator Left Hand Side Iterator
+ */
+ public function getLHS()
+ {
+ return $this->lhs;
+ }
+
+ /**
+ * Get rhs.
+ *
+ * @return \Iterator Right Hand Side Iterator
+ */
+ public function getRHS()
+ {
+ return $this->rhs;
+ }
+
+ /**
+ * Set flags.
+ *
+ * @param int $flags new flags
+ *
+ * @return void
+ */
+ public function setFlags($flags)
+ {
+ $this->flags = $flags;
+ }
+
+ /**
+ * Get flag.
+ *
+ * @return int Current flags
+ */
+ public function getFlags()
+ {
+ return $this->flags;
+ }
+
+ /**
+ * Rewind both inner iterators
+ *
+ * @return void
+ */
+ public function rewind()
+ {
+ $this->lhs->rewind();
+ $this->rhs->rewind();
+ }
+
+ /**
+ * Is valid.
+ *
+ * @return boolean whether both inner iterators are valid
+ */
+ public function valid()
+ {
+ return $this->lhs->valid() && $this->rhs->valid();
+ }
+
+ /**
+ * Get current item.
+ *
+ * @return mixed current value depending on CURRENT_* flags
+ */
+ public function current()
+ {
+ switch ($this->flags & 0x0F)
+ {
+ default:
+ case self::CURRENT_ARRAY:
+ return array($this->lhs->current(), $this->rhs->current());
+ case self::CURRENT_LHS:
+ return $this->lhs->current();
+ case self::CURRENT_RHS:
+ return $this->rhs->current();
+ case self::CURRENT_0:
+ return null;
+ }
+ }
+
+ /**
+ * Get current key.
+ *
+ * @return mixed current value depending on KEY_* flags
+ */
+ public function key()
+ {
+ switch ($this->flags & 0xF0)
+ {
+ default:
+ case self::CURRENT_ARRAY:
+ return array($this->lhs->key(), $this->rhs->key());
+ case self::CURRENT_LHS:
+ return $this->lhs->key();
+ case self::CURRENT_RHS:
+ return $this->rhs->key();
+ case self::CURRENT_0:
+ return null;
+ }
+ }
+
+ /**
+ * Move both inner iterators forward
+ *
+ * @return void
+ */
+ public function next()
+ {
+ $this->lhs->next();
+ $this->rhs->next();
+ }
+
+ /**
+ * Are Identical.
+ *
+ * @return boolean Whether both inner iterators are valid and have identical
+ * current and key values or both are non valid.
+ */
+ public function areIdentical()
+ {
+ return $this->valid()
+ ? $this->lhs->current() === $this->rhs->current()
+ && $this->lhs->key() === $this->rhs->key()
+ : $this->lhs->valid() == $this->rhs->valid();
+ }
+
+ /**
+ * Are equal.
+ *
+ * @return boolean whether both inner iterators are valid and have equal current
+ * and key values or both are non valid.
+ */
+ public function areEqual()
+ {
+ return $this->valid()
+ ? $this->lhs->current() == $this->rhs->current()
+ && $this->lhs->key() == $this->rhs->key()
+ : $this->lhs->valid() == $this->rhs->valid();
+ }
+
+ /**
+ * Compare two iterators.
+ *
+ * @param \Iterator $lhs Left Hand Side Iterator
+ * @param \Iterator $rhs Right Hand Side Iterator
+ * @param boolean $identical Whether to use areEqual() or areIdentical()
+ *
+ * @return boolean whether both iterators are equal/identical
+ *
+ * @note If one implements RecursiveIterator the other must do as well.
+ * And if both do then a recursive comparison is being used.
+ */
+ public static function compareIterators(\Iterator $lhs, \Iterator $rhs, $identical = false)
+ {
+ if ($lhs instanceof \RecursiveIterator)
+ {
+ if ($rhs instanceof \RecursiveIterator)
+ {
+ $it = new RecursiveDualIterator($lhs, $rhs, self::CURRENT_0 | self::KEY_0);
+ $it = new RecursiveCompareDualIterator($it);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ $it = new DualIterator($lhs, $rhs, self::CURRENT_0 | self::KEY_0);
+ }
+
+ if ($identical)
+ {
+ foreach ($it as $n)
+ {
+ if (!$it->areIdentical())
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ foreach ($it as $n)
+ {
+ if (!$it->areEqual())
+ {
+ return false;
+ }
+ }
+ }
+
+ return $identical ? $it->areIdentical() : $it->areEqual();
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Iterator/RecursiveCompareDualIterator.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Iterator/RecursiveCompareDualIterator.php
new file mode 100644
index 00000000..d2ea3d7b
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Iterator/RecursiveCompareDualIterator.php
@@ -0,0 +1,84 @@
+equal = true;
+
+ parent::rewind();
+ }
+
+ /**
+ * Calculate $equal
+ *
+ * @see $equal
+ *
+ * @return void
+ */
+ public function endChildren()
+ {
+ $this->equal &= !$this->getInnerIterator()->getLHS()->valid()
+ && !$this->getInnerIterator()->getRHS()->valid();
+ }
+
+ /**
+ * Are Identical.
+ *
+ * @return boolean Whether both inner iterators are valid and have identical
+ * current and key values or both are non valid.
+ */
+ public function areIdentical()
+ {
+ return $this->equal && $this->getInnerIterator()->areIdentical();
+ }
+
+ /**
+ * Are equal.
+ *
+ * @return boolean Whether both inner iterators are valid and have equal current
+ * and key values or both are non valid.
+ */
+ public function areEqual()
+ {
+ return $this->equal && $this->getInnerIterator()->areEqual();
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Iterator/RecursiveDualIterator.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Iterator/RecursiveDualIterator.php
new file mode 100644
index 00000000..dcd376bf
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Iterator/RecursiveDualIterator.php
@@ -0,0 +1,84 @@
+equal = true;
+
+ parent::rewind();
+ }
+
+ /**
+ * Calculate $equal
+ *
+ * @see $equal
+ *
+ * @return void
+ */
+ public function endChildren()
+ {
+ $this->equal &= !$this->getInnerIterator()->getLHS()->valid()
+ && !$this->getInnerIterator()->getRHS()->valid();
+ }
+
+ /**
+ * Are Identical
+ *
+ * @return boolean Whether both inner iterators are valid and have identical
+ * current and key values or both are non valid.
+ */
+ public function areIdentical()
+ {
+ return $this->equal && $this->getInnerIterator()->areIdentical();
+ }
+
+ /**
+ * Are equal.
+ *
+ * @return boolean Whether both inner iterators are valid and have equal current
+ * and key values or both are non valid.
+ */
+ public function areEqual()
+ {
+ return $this->equal && $this->getInnerIterator()->areEqual();
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Queue/Priority.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Queue/Priority.php
new file mode 100644
index 00000000..9238bcb6
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Queue/Priority.php
@@ -0,0 +1,59 @@
+insert($item, $priority);
+ }
+
+ return $queueObject;
+ }
+
+ /**
+ * createPriorityQueueObject
+ *
+ * @return \SplPriorityQueue
+ *
+ * @deprecated 3.0 Use \Windwalker\Utilities\Queue\PriorityQueue instead.
+ */
+ public static function createPriorityQueueObject()
+ {
+ return new \SplPriorityQueue;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Queue/PriorityQueue.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Queue/PriorityQueue.php
new file mode 100644
index 00000000..98644ab2
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Queue/PriorityQueue.php
@@ -0,0 +1,232 @@
+merge($array);
+ }
+ else
+ {
+ $this->bind($array, $priority);
+ }
+ }
+
+ /**
+ * bind
+ *
+ * @param array $array
+ * @param int $priority
+ *
+ * @return void
+ */
+ public function bind($array = array(), $priority = Priority::NORMAL)
+ {
+ if (is_object($array))
+ {
+ $array = get_object_vars($array);
+ }
+
+ $array = (array) $array;
+
+ foreach ($array as $item)
+ {
+ $this->insert($item, $priority);
+ }
+ }
+
+ /**
+ * Insert a value with a given priority
+ *
+ * Utilizes {@var $serial} to ensure that values of equal priority are
+ * emitted in the same order in which they are inserted.
+ *
+ * @param mixed $datum
+ * @param mixed $priority
+ *
+ * @return void
+ */
+ public function insert($datum, $priority)
+ {
+ if (!is_array($priority))
+ {
+ $priority = array($priority, $this->serial--);
+ }
+ else
+ {
+ $priority[] = $this->serial--;
+ }
+
+ parent::insert($datum, $priority);
+ }
+
+ /**
+ * Serialize to an array
+ *
+ * Array will be priority => data pairs
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $array = array();
+
+ foreach (clone $this as $item)
+ {
+ $array[] = $item;
+ }
+
+ return $array;
+ }
+
+ /**
+ * Serialize
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ $clone = clone $this;
+
+ $clone->setExtractFlags(self::EXTR_BOTH);
+
+ $data = array();
+
+ foreach ($clone as $item)
+ {
+ $data[] = $item;
+ }
+
+ return serialize($data);
+ }
+
+ /**
+ * Deserialize
+ *
+ * @param string $data
+ *
+ * @return void
+ */
+ public function unserialize($data)
+ {
+ foreach (unserialize($data) as $item)
+ {
+ $this->insert($item['data'], $item['priority']);
+ }
+ }
+
+ /**
+ * merge
+ *
+ * @return static;
+ */
+ public function merge()
+ {
+ $args = func_get_args();
+
+ foreach ($args as $arg)
+ {
+ if (!($arg instanceof \SplPriorityQueue))
+ {
+ throw new \InvalidArgumentException('Only \SplPriorityQueue can merge.');
+ }
+
+ $queue = clone $arg;
+
+ $queue->setExtractFlags(self::EXTR_BOTH);
+
+ foreach ($queue as $item)
+ {
+ $this->insert($item['data'], $item['priority']);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * compare
+ *
+ * @param mixed $priority1
+ * @param mixed $priority2
+ *
+ * @return int
+ */
+ public function compare($priority1, $priority2)
+ {
+ $p1Count = count($priority1);
+ $p2Count = count($priority2);
+
+ $count = min($p1Count, $p2Count);
+
+ foreach (range(1, $count) as $i)
+ {
+ $k = $i - 1;
+
+ if ($priority1[$k] == $priority2[$k])
+ {
+ continue;
+ }
+ elseif ($priority1[$k] > $priority2[$k])
+ {
+ return 1;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Method to get property Serial
+ *
+ * @return int
+ */
+ public function getSerial()
+ {
+ return $this->serial;
+ }
+
+ /**
+ * Method to set property serial
+ *
+ * @param int $serial
+ *
+ * @return static Return self to support chaining.
+ */
+ public function setSerial($serial)
+ {
+ $this->serial = $serial;
+
+ return $this;
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/README.md b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/README.md
new file mode 100644
index 00000000..2c72a83f
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/README.md
@@ -0,0 +1,398 @@
+# Windwalker Utilities
+
+## Installation via Composer
+
+Add this to the require block in your `composer.json`.
+
+``` json
+{
+ "require": {
+ "windwalker/utilities": "~2.0"
+ }
+}
+```
+
+## Using ArrayHelper
+
+### toInteger
+
+```php
+use Windwalker\Utilities\ArrayHelper;
+
+$input = array(
+ "width" => "100",
+ "height" => "200xxx",
+ "length" => "10.3"
+);
+$result = ArrayHelper::toInteger($input);
+var_dump($result);
+```
+Result:
+```
+array(3) {
+ 'width' =>
+ int(100)
+ 'height' =>
+ int(200)
+ 'length' =>
+ int(10)
+}
+```
+
+### toObject
+
+```php
+use Windwalker\Utilities\ArrayHelper;
+
+class Book {
+ public $name;
+ public $author;
+ public $genre;
+ public $rating;
+}
+class Author {
+ public $name;
+ public $born;
+}
+$input = array(
+ "name" => "The Hitchhiker's Guide to the Galaxy",
+ "author" => array(
+ "name" => "Douglas Adams",
+ "born" => 1952,
+ "died" => 2001),
+ "genre" => "comic science fiction",
+ "rating" => 10
+);
+$book = ArrayHelper::toObject($input, 'Book');
+var_dump($book);
+```
+Result:
+```
+class Book#1 (4) {
+ public $name =>
+ string(36) "The Hitchhiker's Guide to the Galaxy"
+ public $author =>
+ class Book#2 (6) {
+ public $name =>
+ string(13) "Douglas Adams"
+ public $author =>
+ NULL
+ public $genre =>
+ NULL
+ public $rating =>
+ NULL
+ public $born =>
+ int(1952)
+ public $died =>
+ int(2001)
+ }
+ public $genre =>
+ string(21) "comic science fiction"
+ public $rating =>
+ int(10)
+}
+```
+
+### toString
+
+```php
+use Windwalker\Utilities\ArrayHelper;
+
+$input = array(
+ "fruit" => "apple",
+ "pi" => 3.14
+);
+echo ArrayHelper::toString($input);
+```
+Result:
+```
+fruit="apple" pi="3.14"
+```
+
+### fromObject
+
+```php
+use Windwalker\Utilities\ArrayHelper;
+
+class Book {
+ public $name;
+ public $author;
+ public $genre;
+ public $rating;
+}
+class Author {
+ public $name;
+ public $born;
+}
+
+$book = new Book();
+$book->name = "Harry Potter and the Philosopher's Stone";
+$book->author = new Author();
+$book->author->name = "J.K. Rowling";
+$book->author->born = 1965;
+$book->genre = "fantasy";
+$book->rating = 10;
+
+$array = ArrayHelper::fromObject($book);
+var_dump($array);
+```
+Result:
+```
+array(4) {
+ 'name' =>
+ string(40) "Harry Potter and the Philosopher's Stone"
+ 'author' =>
+ array(2) {
+ 'name' =>
+ string(12) "J.K. Rowling"
+ 'born' =>
+ int(1965)
+ }
+ 'genre' =>
+ string(7) "fantasy"
+ 'rating' =>
+ int(10)
+}
+```
+
+### getColumn
+
+```php
+use Windwalker\Utilities\ArrayHelper;
+
+$rows = array(
+ array("name" => "John", "age" => 20),
+ array("name" => "Alex", "age" => 35),
+ array("name" => "Sarah", "age" => 27)
+);
+$names = ArrayHelper::getColumn($rows, 'name');
+var_dump($names);
+```
+Result:
+```
+array(3) {
+ [0] =>
+ string(4) "John"
+ [1] =>
+ string(4) "Alex"
+ [2] =>
+ string(5) "Sarah"
+}
+```
+
+### getValue
+```php
+use Windwalker\Utilities\ArrayHelper;
+
+$city = array(
+ "name" => "Oslo",
+ "country" => "Norway"
+);
+
+// Prints 'Oslo'
+echo ArrayHelper::getValue($city, 'name');
+
+// Prints 'unknown mayor' (no 'mayor' key is found in the array)
+echo ArrayHelper::getValue($city, 'mayor', 'unknown mayor');
+```
+
+### invert
+
+```php
+use Windwalker\Utilities\ArrayHelper;
+
+$input = array(
+ 'New' => array('1000', '1500', '1750'),
+ 'Used' => array('3000', '4000', '5000', '6000')
+);
+$output = ArrayHelper::invert($input);
+var_dump($output);
+```
+Result:
+```
+array(7) {
+ [1000] =>
+ string(3) "New"
+ [1500] =>
+ string(3) "New"
+ [1750] =>
+ string(3) "New"
+ [3000] =>
+ string(4) "Used"
+ [4000] =>
+ string(4) "Used"
+ [5000] =>
+ string(4) "Used"
+ [6000] =>
+ string(4) "Used"
+}
+```
+
+
+### isAssociative
+
+```php
+use Windwalker\Utilities\ArrayHelper;
+
+$user = array("id" => 46, "name" => "John");
+echo ArrayHelper::isAssociative($user) ? 'true' : 'false'; // true
+
+$letters = array("a", "b", "c");
+echo ArrayHelper::isAssociative($letters) ? 'true' : 'false'; // false
+```
+
+### pivot
+
+```php
+use Windwalker\Utilities\ArrayHelper;
+
+$movies = array(
+ array('year' => 1972, 'title' => 'The Godfather'),
+ array('year' => 2000, 'title' => 'Gladiator'),
+ array('year' => 2000, 'title' => 'Memento'),
+ array('year' => 1964, 'title' => 'Dr. Strangelove')
+);
+$pivoted = ArrayHelper::pivot($movies, 'year');
+var_dump($pivoted);
+```
+Result:
+```
+array(3) {
+ [1972] =>
+ array(2) {
+ 'year' =>
+ int(1972)
+ 'title' =>
+ string(13) "The Godfather"
+ }
+ [2000] =>
+ array(2) {
+ [0] =>
+ array(2) {
+ 'year' =>
+ int(2000)
+ 'title' =>
+ string(9) "Gladiator"
+ }
+ [1] =>
+ array(2) {
+ 'year' =>
+ int(2000)
+ 'title' =>
+ string(7) "Memento"
+ }
+ }
+ [1964] =>
+ array(2) {
+ 'year' =>
+ int(1964)
+ 'title' =>
+ string(15) "Dr. Strangelove"
+ }
+}
+```
+
+### sortObjects
+
+```php
+use Windwalker\Utilities\ArrayHelper;
+
+$members = array(
+ (object) array('first_name' => 'Carl', 'last_name' => 'Hopkins'),
+ (object) array('first_name' => 'Lisa', 'last_name' => 'Smith'),
+ (object) array('first_name' => 'Julia', 'last_name' => 'Adams')
+);
+$sorted = ArrayHelper::sortObjects($members, 'last_name', 1);
+var_dump($sorted);
+```
+Result:
+```
+array(3) {
+ [0] =>
+ class stdClass#3 (2) {
+ public $first_name =>
+ string(5) "Julia"
+ public $last_name =>
+ string(5) "Adams"
+ }
+ [1] =>
+ class stdClass#1 (2) {
+ public $first_name =>
+ string(4) "Carl"
+ public $last_name =>
+ string(7) "Hopkins"
+ }
+ [2] =>
+ class stdClass#2 (2) {
+ public $first_name =>
+ string(4) "Lisa"
+ public $last_name =>
+ string(5) "Smith"
+ }
+}
+```
+
+### arrayUnique
+```php
+use Windwalker\Utilities\ArrayHelper;
+
+$names = array(
+ array("first_name" => "John", "last_name" => "Adams"),
+ array("first_name" => "John", "last_name" => "Adams"),
+ array("first_name" => "John", "last_name" => "Smith"),
+ array("first_name" => "Sam", "last_name" => "Smith")
+);
+$unique = ArrayHelper::arrayUnique($names);
+var_dump($unique);
+```
+Result:
+```
+array(3) {
+ [0] =>
+ array(2) {
+ 'first_name' =>
+ string(4) "John"
+ 'last_name' =>
+ string(5) "Adams"
+ }
+ [2] =>
+ array(2) {
+ 'first_name' =>
+ string(4) "John"
+ 'last_name' =>
+ string(5) "Smith"
+ }
+ [3] =>
+ array(2) {
+ 'first_name' =>
+ string(3) "Sam"
+ 'last_name' =>
+ string(5) "Smith"
+ }
+}
+```
+
+### flatten
+
+``` php
+use Windwalker\Utilities\ArrayHelper;
+
+$array = array(
+ 'flower' => array(
+ 'sakura' => 'samurai',
+ 'olive' => 'peace'
+ )
+);
+
+// Make nested data flatten and separate by dot (".")
+
+$flatted1 = ArrayHelper::flatten($array);
+
+echo $flatted1['flower.sakura']; // 'samuari'
+
+// Custom separator
+
+$flatted2 = ArrayHelper::flatten($array, '/');
+
+echo $flatted2['flower/olive']; // 'peace'
+```
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Reflection/ReflectionHelper.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Reflection/ReflectionHelper.php
new file mode 100644
index 00000000..6dffd48c
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Reflection/ReflectionHelper.php
@@ -0,0 +1,150 @@
+getFileName();
+ }
+
+ /**
+ * getPackageNamespace
+ *
+ * @param string|object $class
+ * @param int $backwards
+ *
+ * @return string
+ */
+ public static function getNamespaceBackwards($class, $backwards = 3)
+ {
+ if (!is_string($class))
+ {
+ $class = get_class($class);
+ }
+
+ $class = explode('\\', $class);
+
+ foreach (range(1, $backwards) as $i)
+ {
+ array_pop($class);
+ }
+
+ return implode('\\', $class);
+ }
+
+ /**
+ * Call static magic method.
+ *
+ * @param string $name The method name.
+ * @param array $args The arguments of this methods.
+ *
+ * @return mixed Return value from reflection class.
+ */
+ public static function __callStatic($name, $args)
+ {
+ $class = array_shift($args);
+
+ $ref = static::getReflection($class);
+
+ return call_user_func_array(array($ref, $name), $args);
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Test/ArrayHelperTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Test/ArrayHelperTest.php
new file mode 100644
index 00000000..f5bf77af
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Test/ArrayHelperTest.php
@@ -0,0 +1,2139 @@
+ array(
+ // Input
+ array(
+ array(1, 2, 3, array(4)),
+ array(2, 2, 3, array(4)),
+ array(3, 2, 3, array(4)),
+ array(2, 2, 3, array(4)),
+ array(3, 2, 3, array(4)),
+ ),
+ // Expected
+ array(
+ array(1, 2, 3, array(4)),
+ array(2, 2, 3, array(4)),
+ array(3, 2, 3, array(4)),
+ ),
+ )
+ );
+ }
+
+ /**
+ * Data provider for from object inputs
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestFromObject()
+ {
+ // Define a common array.
+ $common = array('integer' => 12, 'float' => 1.29999, 'string' => 'A Test String');
+
+ return array(
+ 'Invalid input' => array(
+ // Array The array being input
+ null,
+ // Boolean Recurse through multiple dimensions
+ null,
+ // String Regex to select only some attributes
+ null,
+ // String The expected return value
+ null,
+ // Boolean Use function defaults (true) or full argument list
+ true
+ ),
+ 'To single dimension array' => array(
+ (object) $common,
+ null,
+ null,
+ $common,
+ true
+ ),
+ 'Object with nested arrays and object.' => array(
+ (object) array(
+ 'foo' => $common,
+ 'bar' => (object) array(
+ 'goo' => $common,
+ ),
+ ),
+ null,
+ null,
+ array(
+ 'foo' => $common,
+ 'bar' => array(
+ 'goo' => $common,
+ ),
+ ),
+ true
+ ),
+ 'To single dimension array with recursion' => array(
+ (object) $common,
+ true,
+ null,
+ $common,
+ false
+ ),
+ 'To single dimension array using regex on keys' => array(
+ (object) $common,
+ true,
+ // Only get the 'integer' and 'float' keys.
+ '/^(integer|float)/',
+ array(
+ 'integer' => 12, 'float' => 1.29999
+ ),
+ false
+ ),
+ 'Nested objects to single dimension array' => array(
+ (object) array(
+ 'first' => (object) $common,
+ 'second' => (object) $common,
+ 'third' => (object) $common,
+ ),
+ null,
+ null,
+ array(
+ 'first' => (object) $common,
+ 'second' => (object) $common,
+ 'third' => (object) $common,
+ ),
+ false
+ ),
+ 'Nested objects into multiple dimension array' => array(
+ (object) array(
+ 'first' => (object) $common,
+ 'second' => (object) $common,
+ 'third' => (object) $common,
+ ),
+ null,
+ null,
+ array(
+ 'first' => $common,
+ 'second' => $common,
+ 'third' => $common,
+ ),
+ true
+ ),
+ 'Nested objects into multiple dimension array 2' => array(
+ (object) array(
+ 'first' => (object) $common,
+ 'second' => (object) $common,
+ 'third' => (object) $common,
+ ),
+ true,
+ null,
+ array(
+ 'first' => $common,
+ 'second' => $common,
+ 'third' => $common,
+ ),
+ true
+ ),
+ 'Nested objects into multiple dimension array 3' => array(
+ (object) array(
+ 'first' => (object) $common,
+ 'second' => (object) $common,
+ 'third' => (object) $common,
+ ),
+ false,
+ null,
+ array(
+ 'first' => (object) $common,
+ 'second' => (object) $common,
+ 'third' => (object) $common,
+ ),
+ false
+ ),
+ 'multiple 4' => array(
+ (object) array(
+ 'first' => 'Me',
+ 'second' => (object) $common,
+ 'third' => (object) $common,
+ ),
+ false,
+ null,
+ array(
+ 'first' => 'Me',
+ 'second' => (object) $common,
+ 'third' => (object) $common,
+ ),
+ false
+ ),
+ 'Nested objects into multiple dimension array of int and string' => array(
+ (object) array(
+ 'first' => (object) $common,
+ 'second' => (object) $common,
+ 'third' => (object) $common,
+ ),
+ true,
+ '/(first|second|integer|string)/',
+ array(
+ 'first' => array(
+ 'integer' => 12, 'string' => 'A Test String'
+ ), 'second' => array(
+ 'integer' => 12, 'string' => 'A Test String'
+ ),
+ ),
+ false
+ ),
+ 'multiple 6' => array(
+ (object) array(
+ 'first' => array(
+ 'integer' => 12,
+ 'float' => 1.29999,
+ 'string' => 'A Test String',
+ 'third' => (object) $common,
+ ),
+ 'second' => $common,
+ ),
+ null,
+ null,
+ array(
+ 'first' => array(
+ 'integer' => 12,
+ 'float' => 1.29999,
+ 'string' => 'A Test String',
+ 'third' => $common,
+ ),
+ 'second' => $common,
+ ),
+ true
+ ),
+ );
+ }
+
+ /**
+ * Data provider for get column
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestGetColumn()
+ {
+ return array(
+ 'generic array' => array(
+ array(
+ array(
+ 1, 2, 3, 4, 5
+ ), array(
+ 6, 7, 8, 9, 10
+ ), array(
+ 11, 12, 13, 14, 15
+ ), array(
+ 16, 17, 18, 19, 20
+ )
+ ),
+ 2,
+ array(
+ 3, 8, 13, 18
+ ),
+ 'Should get column #2'
+ ),
+ 'associative array' => array(
+ array(
+ array(
+ 'one' => 1, 'two' => 2, 'three' => 3, 'four' => 4, 'five' => 5
+ ),
+ array(
+ 'one' => 6, 'two' => 7, 'three' => 8, 'four' => 9, 'five' => 10
+ ),
+ array(
+ 'one' => 11, 'two' => 12, 'three' => 13, 'four' => 14, 'five' => 15
+ ),
+ array(
+ 'one' => 16, 'two' => 17, 'three' => 18, 'four' => 19, 'five' => 20
+ )
+ ),
+ 'four',
+ array(
+ 4, 9, 14, 19
+ ),
+ 'Should get column \'four\''
+ ),
+ 'object array' => array(
+ array(
+ (object) array(
+ 'one' => 1, 'two' => 2, 'three' => 3, 'four' => 4, 'five' => 5
+ ),
+ (object) array(
+ 'one' => 6, 'two' => 7, 'three' => 8, 'four' => 9, 'five' => 10
+ ),
+ (object) array(
+ 'one' => 11, 'two' => 12, 'three' => 13, 'four' => 14, 'five' => 15
+ ),
+ (object) array(
+ 'one' => 16, 'two' => 17, 'three' => 18, 'four' => 19, 'five' => 20
+ )
+ ),
+ 'four',
+ array(
+ 4, 9, 14, 19
+ ),
+ 'Should get column \'four\''
+ ),
+ );
+ }
+
+ /**
+ * Data provider for get value
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestGetValue()
+ {
+ $input = array(
+ 'one' => 1,
+ 'two' => 2,
+ 'three' => 3,
+ 'four' => 4,
+ 'five' => 5,
+ 'six' => 6,
+ 'seven' => 7,
+ 'eight' => 8,
+ 'nine' => 'It\'s nine',
+ 'ten' => 10,
+ 'eleven' => 11,
+ 'twelve' => 12,
+ 'thirteen' => 13,
+ 'fourteen' => 14,
+ 'fifteen' => 15,
+ 'sixteen' => 16,
+ 'seventeen' => 17,
+ 'eightteen' => 'eighteen ninety-five',
+ 'nineteen' => 19,
+ 'twenty' => 20
+ );
+
+ return array(
+ 'defaults' => array(
+ $input, 'five', null, null, 5, 'Should get 5', true
+ ),
+ 'get non-value' => array(
+ $input, 'fiveio', 198, null, 198, 'Should get the default value', false
+ ),
+ 'get int 5' => array(
+ $input, 'five', 198, 'int', (int) 5, 'Should get an int', false
+ ),
+ 'get float six' => array(
+ $input, 'six', 198, 'float', (float) 6, 'Should get a float', false
+ ),
+ 'get get boolean seven' => array(
+ $input, 'seven', 198, 'bool', (bool) 7, 'Should get a boolean', false
+ ),
+ 'get array eight' => array(
+ $input, 'eight', 198, 'array', array(
+ 8
+ ), 'Should get an array', false
+ ),
+ 'get string nine' => array(
+ $input, 'nine', 198, 'string', 'It\'s nine', 'Should get string', false
+ ),
+ 'get word' => array(
+ $input, 'eightteen', 198, 'word', 'eighteenninetyfive', 'Should get it as a single word', false
+ ),
+ );
+ }
+
+ /**
+ * Data provider for invert
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestInvert()
+ {
+ return array(
+ 'Case 1' => array(
+ // Input
+ array(
+ 'New' => array('1000', '1500', '1750'),
+ 'Used' => array('3000', '4000', '5000', '6000')
+ ),
+ // Expected
+ array(
+ '1000' => 'New',
+ '1500' => 'New',
+ '1750' => 'New',
+ '3000' => 'Used',
+ '4000' => 'Used',
+ '5000' => 'Used',
+ '6000' => 'Used'
+ )
+ ),
+ 'Case 2' => array(
+ // Input
+ array(
+ 'New' => array(1000, 1500, 1750),
+ 'Used' => array(2750, 3000, 4000, 5000, 6000),
+ 'Refurbished' => array(2000, 2500),
+ 'Unspecified' => array()
+ ),
+ // Expected
+ array(
+ '1000' => 'New',
+ '1500' => 'New',
+ '1750' => 'New',
+ '2750' => 'Used',
+ '3000' => 'Used',
+ '4000' => 'Used',
+ '5000' => 'Used',
+ '6000' => 'Used',
+ '2000' => 'Refurbished',
+ '2500' => 'Refurbished'
+ )
+ ),
+ 'Case 3' => array(
+ // Input
+ array(
+ 'New' => array(1000, 1500, 1750),
+ 'valueNotAnArray' => 2750,
+ 'withNonScalarValue' => array(2000, array(1000 , 3000))
+ ),
+ // Expected
+ array(
+ '1000' => 'New',
+ '1500' => 'New',
+ '1750' => 'New',
+ '2000' => 'withNonScalarValue'
+ )
+ )
+ );
+ }
+
+ /**
+ * Data provider for testPivot
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestPivot()
+ {
+ return array(
+ 'A scalar array' => array(
+ // Source
+ array(
+ 1 => 'a',
+ 2 => 'b',
+ 3 => 'b',
+ 4 => 'c',
+ 5 => 'a',
+ 6 => 'a',
+ ),
+ // Key
+ null,
+ // Expected
+ array(
+ 'a' => array(
+ 1, 5, 6
+ ),
+ 'b' => array(
+ 2, 3
+ ),
+ 'c' => 4,
+ )
+ ),
+ 'An array of associative arrays' => array(
+ // Source
+ array(
+ 1 => array('id' => 41, 'title' => 'boo'),
+ 2 => array('id' => 42, 'title' => 'boo'),
+ 3 => array('title' => 'boo'),
+ 4 => array('id' => 42, 'title' => 'boo'),
+ 5 => array('id' => 43, 'title' => 'boo'),
+ ),
+ // Key
+ 'id',
+ // Expected
+ array(
+ 41 => array('id' => 41, 'title' => 'boo'),
+ 42 => array(
+ array('id' => 42, 'title' => 'boo'),
+ array('id' => 42, 'title' => 'boo'),
+ ),
+ 43 => array('id' => 43, 'title' => 'boo'),
+ )
+ ),
+ 'An array of objects' => array(
+ // Source
+ array(
+ 1 => (object) array('id' => 41, 'title' => 'boo'),
+ 2 => (object) array('id' => 42, 'title' => 'boo'),
+ 3 => (object) array('title' => 'boo'),
+ 4 => (object) array('id' => 42, 'title' => 'boo'),
+ 5 => (object) array('id' => 43, 'title' => 'boo'),
+ ),
+ // Key
+ 'id',
+ // Expected
+ array(
+ 41 => (object) array('id' => 41, 'title' => 'boo'),
+ 42 => array(
+ (object) array('id' => 42, 'title' => 'boo'),
+ (object) array('id' => 42, 'title' => 'boo'),
+ ),
+ 43 => (object) array('id' => 43, 'title' => 'boo'),
+ )
+ ),
+ );
+ }
+
+ /**
+ * seedTestPivotByKey
+ *
+ * @return array
+ */
+ public function seedTestPivotByKey()
+ {
+ return array(
+ array(
+ // data
+ array(
+ 'Jones' => array(123, 223),
+ 'Arthur' => array('Lancelot', 'Jessica')
+ ),
+ // expected
+ array(
+ array('Jones' => 123, 'Arthur' => 'Lancelot'),
+ array('Jones' => 223, 'Arthur' => 'Jessica'),
+ ),
+ ),
+ );
+ }
+
+ /**
+ * Data provider for sorting objects
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestSortObject()
+ {
+ $input1 = array(
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ (object) array(
+ 'integer' => 15, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 35, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 1, 'float' => 1.29999, 'string' => 'N Test String'
+ ),
+ (object) array(
+ 'integer' => 5, 'float' => 1.29999, 'string' => 'T Test String'
+ ),
+ (object) array(
+ 'integer' => 22, 'float' => 1.29999, 'string' => 'E Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'G Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'L Test String'
+ ),
+ );
+ $input2 = array(
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ (object) array(
+ 'integer' => 15, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 35, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 1, 'float' => 1.29999, 'string' => 'N Test String'
+ ),
+ (object) array(
+ 'integer' => 5, 'float' => 1.29999, 'string' => 't Test String'
+ ),
+ (object) array(
+ 'integer' => 22, 'float' => 1.29999, 'string' => 'E Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'g Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'L Test String'
+ ),
+ );
+
+ if (substr(php_uname(), 0, 6) != 'Darwin')
+ {
+ $input3 = array(
+ (object) array(
+ 'string' => 'A Test String', 'integer' => 1,
+ ),
+ (object) array(
+ 'string' => 'é Test String', 'integer' => 2,
+ ),
+ (object) array(
+ 'string' => 'è Test String', 'integer' => 3,
+ ),
+ (object) array(
+ 'string' => 'É Test String', 'integer' => 4,
+ ),
+ (object) array(
+ 'string' => 'È Test String', 'integer' => 5,
+ ),
+ (object) array(
+ 'string' => 'Œ Test String', 'integer' => 6,
+ ),
+ (object) array(
+ 'string' => 'œ Test String', 'integer' => 7,
+ ),
+ (object) array(
+ 'string' => 'L Test String', 'integer' => 8,
+ ),
+ (object) array(
+ 'string' => 'P Test String', 'integer' => 9,
+ ),
+ (object) array(
+ 'string' => 'p Test String', 'integer' => 10,
+ ),
+ );
+ }
+ else
+ {
+ $input3 = array();
+ }
+
+ return array(
+ 'by int defaults' => array(
+ $input1,
+ 'integer',
+ null,
+ false,
+ false,
+ array(
+ (object) array(
+ 'integer' => 1, 'float' => 1.29999, 'string' => 'N Test String'
+ ),
+ (object) array(
+ 'integer' => 5, 'float' => 1.29999, 'string' => 'T Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'G Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'L Test String'
+ ),
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ (object) array(
+ 'integer' => 15, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 22, 'float' => 1.29999, 'string' => 'E Test String'
+ ),
+ (object) array(
+ 'integer' => 35, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ ),
+ 'Should be sorted by the integer field in ascending order',
+ true
+ ),
+ 'by int ascending' => array(
+ $input1,
+ 'integer',
+ 1,
+ false,
+ false,
+ array(
+ (object) array(
+ 'integer' => 1, 'float' => 1.29999, 'string' => 'N Test String'
+ ),
+ (object) array(
+ 'integer' => 5, 'float' => 1.29999, 'string' => 'T Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'G Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'L Test String'
+ ),
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ (object) array(
+ 'integer' => 15, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 22, 'float' => 1.29999, 'string' => 'E Test String'
+ ),
+ (object) array(
+ 'integer' => 35, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ ),
+ 'Should be sorted by the integer field in ascending order full argument list',
+ false
+ ),
+ 'by int descending' => array(
+ $input1,
+ 'integer',
+ -1,
+ false,
+ false,
+ array(
+ (object) array(
+ 'integer' => 35, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 22, 'float' => 1.29999, 'string' => 'E Test String'
+ ),
+ (object) array(
+ 'integer' => 15, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'G Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'L Test String'
+ ),
+ (object) array(
+ 'integer' => 5, 'float' => 1.29999, 'string' => 'T Test String'
+ ),
+ (object) array(
+ 'integer' => 1, 'float' => 1.29999, 'string' => 'N Test String'
+ ),
+ ),
+ 'Should be sorted by the integer field in descending order',
+ false
+ ),
+ 'by string ascending' => array(
+ $input1,
+ 'string',
+ 1,
+ false,
+ false,
+ array(
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ (object) array(
+ 'integer' => 35, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 15, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 22, 'float' => 1.29999, 'string' => 'E Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'G Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'L Test String'
+ ),
+ (object) array(
+ 'integer' => 1, 'float' => 1.29999, 'string' => 'N Test String'
+ ),
+ (object) array(
+ 'integer' => 5, 'float' => 1.29999, 'string' => 'T Test String'
+ ),
+ ),
+ 'Should be sorted by the string field in ascending order full argument list',
+ false,
+ array(1, 2)
+ ),
+ 'by string descending' => array(
+ $input1,
+ 'string',
+ -1,
+ false,
+ false,
+ array(
+ (object) array(
+ 'integer' => 5, 'float' => 1.29999, 'string' => 'T Test String'
+ ),
+ (object) array(
+ 'integer' => 1, 'float' => 1.29999, 'string' => 'N Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'L Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'G Test String'
+ ),
+ (object) array(
+ 'integer' => 22, 'float' => 1.29999, 'string' => 'E Test String'
+ ),
+ (object) array(
+ 'integer' => 15, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 35, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ ),
+ 'Should be sorted by the string field in descending order',
+ false,
+ array(5, 6)
+ ),
+ 'by casesensitive string ascending' => array(
+ $input2,
+ 'string',
+ 1,
+ true,
+ false,
+ array(
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ (object) array(
+ 'integer' => 35, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 15, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 22, 'float' => 1.29999, 'string' => 'E Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'L Test String'
+ ),
+ (object) array(
+ 'integer' => 1, 'float' => 1.29999, 'string' => 'N Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'g Test String'
+ ),
+ (object) array(
+ 'integer' => 5, 'float' => 1.29999, 'string' => 't Test String'
+ ),
+ ),
+ 'Should be sorted by the string field in ascending order with casesensitive comparisons',
+ false,
+ array(1, 2)
+ ),
+ 'by casesensitive string descending' => array(
+ $input2,
+ 'string',
+ -1,
+ true,
+ false,
+ array(
+ (object) array(
+ 'integer' => 5, 'float' => 1.29999, 'string' => 't Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'g Test String'
+ ),
+ (object) array(
+ 'integer' => 1, 'float' => 1.29999, 'string' => 'N Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'L Test String'
+ ),
+ (object) array(
+ 'integer' => 22, 'float' => 1.29999, 'string' => 'E Test String'
+ ),
+ (object) array(
+ 'integer' => 35, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 15, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ ),
+ 'Should be sorted by the string field in descending order with casesensitive comparisons',
+ false,
+ array(5, 6)
+ ),
+ 'by casesensitive string,integer ascending' => array(
+ $input2,
+ array(
+ 'string', 'integer'
+ ),
+ 1,
+ true,
+ false,
+ array(
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ (object) array(
+ 'integer' => 15, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 35, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 22, 'float' => 1.29999, 'string' => 'E Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'L Test String'
+ ),
+ (object) array(
+ 'integer' => 1, 'float' => 1.29999, 'string' => 'N Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'g Test String'
+ ),
+ (object) array(
+ 'integer' => 5, 'float' => 1.29999, 'string' => 't Test String'
+ ),
+ ),
+ 'Should be sorted by the string,integer field in descending order with casesensitive comparisons',
+ false
+ ),
+ 'by casesensitive string,integer descending' => array(
+ $input2,
+ array(
+ 'string', 'integer'
+ ),
+ -1,
+ true,
+ false,
+ array(
+ (object) array(
+ 'integer' => 5, 'float' => 1.29999, 'string' => 't Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'g Test String'
+ ),
+ (object) array(
+ 'integer' => 1, 'float' => 1.29999, 'string' => 'N Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'L Test String'
+ ),
+ (object) array(
+ 'integer' => 22, 'float' => 1.29999, 'string' => 'E Test String'
+ ),
+ (object) array(
+ 'integer' => 35, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 15, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ ),
+ 'Should be sorted by the string,integer field in descending order with casesensitive comparisons',
+ false
+ ),
+ 'by casesensitive string,integer ascending,descending' => array(
+ $input2,
+ array(
+ 'string', 'integer'
+ ),
+ array(
+ 1, -1
+ ),
+ true,
+ false,
+ array(
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ (object) array(
+ 'integer' => 35, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 15, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 22, 'float' => 1.29999, 'string' => 'E Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'L Test String'
+ ),
+ (object) array(
+ 'integer' => 1, 'float' => 1.29999, 'string' => 'N Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'g Test String'
+ ),
+ (object) array(
+ 'integer' => 5, 'float' => 1.29999, 'string' => 't Test String'
+ ),
+ ),
+ 'Should be sorted by the string,integer field in ascending,descending order with casesensitive comparisons',
+ false
+ ),
+ 'by casesensitive string,integer descending,ascending' => array(
+ $input2,
+ array(
+ 'string', 'integer'
+ ),
+ array(
+ -1, 1
+ ),
+ true,
+ false,
+ array(
+ (object) array(
+ 'integer' => 5, 'float' => 1.29999, 'string' => 't Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'g Test String'
+ ),
+ (object) array(
+ 'integer' => 1, 'float' => 1.29999, 'string' => 'N Test String'
+ ),
+ (object) array(
+ 'integer' => 6, 'float' => 1.29999, 'string' => 'L Test String'
+ ),
+ (object) array(
+ 'integer' => 22, 'float' => 1.29999, 'string' => 'E Test String'
+ ),
+ (object) array(
+ 'integer' => 15, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 35, 'float' => 1.29999, 'string' => 'C Test String'
+ ),
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ ),
+ 'Should be sorted by the string,integer field in descending,ascending order with casesensitive comparisons',
+ false
+ ),
+ 'by casesensitive string ascending' => array(
+ $input3,
+ 'string',
+ 1,
+ true,
+ array(
+ 'fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'
+ ),
+ array(
+ (object) array(
+ 'string' => 'A Test String', 'integer' => 1,
+ ),
+ (object) array(
+ 'string' => 'é Test String', 'integer' => 2,
+ ),
+ (object) array(
+ 'string' => 'É Test String', 'integer' => 4,
+ ),
+ (object) array(
+ 'string' => 'è Test String', 'integer' => 3,
+ ),
+ (object) array(
+ 'string' => 'È Test String', 'integer' => 5,
+ ),
+ (object) array(
+ 'string' => 'L Test String', 'integer' => 8,
+ ),
+ (object) array(
+ 'string' => 'œ Test String', 'integer' => 7,
+ ),
+ (object) array(
+ 'string' => 'Œ Test String', 'integer' => 6,
+ ),
+ (object) array(
+ 'string' => 'p Test String', 'integer' => 10,
+ ),
+ (object) array(
+ 'string' => 'P Test String', 'integer' => 9,
+ ),
+ ),
+ 'Should be sorted by the string field in ascending order with casesensitive comparisons and fr_FR locale',
+ false
+ ),
+ 'by caseinsensitive string, integer ascending' => array(
+ $input3,
+ array(
+ 'string', 'integer'
+ ),
+ 1,
+ false,
+ array(
+ 'fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'
+ ),
+ array(
+ (object) array(
+ 'string' => 'A Test String', 'integer' => 1,
+ ),
+ (object) array(
+ 'string' => 'é Test String', 'integer' => 2,
+ ),
+ (object) array(
+ 'string' => 'É Test String', 'integer' => 4,
+ ),
+ (object) array(
+ 'string' => 'è Test String', 'integer' => 3,
+ ),
+ (object) array(
+ 'string' => 'È Test String', 'integer' => 5,
+ ),
+ (object) array(
+ 'string' => 'L Test String', 'integer' => 8,
+ ),
+ (object) array(
+ 'string' => 'Œ Test String', 'integer' => 6,
+ ),
+ (object) array(
+ 'string' => 'œ Test String', 'integer' => 7,
+ ),
+ (object) array(
+ 'string' => 'P Test String', 'integer' => 9,
+ ),
+ (object) array(
+ 'string' => 'p Test String', 'integer' => 10,
+ ),
+ ),
+ 'Should be sorted by the string,integer field in ascending order with caseinsensitive comparisons and fr_FR locale',
+ false
+ ),
+ );
+ }
+
+ /**
+ * Data provider for numeric inputs
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestToInteger()
+ {
+ return array(
+ 'floating with single argument' => array(
+ array(
+ 0.9, 3.2, 4.9999999, 7.5
+ ), null, array(
+ 0, 3, 4, 7
+ ), 'Should truncate numbers in array'
+ ),
+ 'floating with default array' => array(
+ array(
+ 0.9, 3.2, 4.9999999, 7.5
+ ), array(
+ 1, 2, 3
+ ), array(
+ 0, 3, 4, 7
+ ), 'Supplied default should not be used'
+ ),
+ 'non-array with single argument' => array(
+ 12, null, array(), 'Should replace non-array input with empty array'
+ ),
+ 'non-array with default array' => array(
+ 12, array(
+ 1.5, 2.6, 3
+ ), array(
+ 1, 2, 3
+ ), 'Should replace non-array input with array of truncated numbers'
+ ),
+ 'non-array with default single' => array(
+ 12, 3.5, array(
+ 3
+ ), 'Should replace non-array with single-element array of truncated number'
+ ),
+ );
+ }
+
+ /**
+ * Data provider for object inputs
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestToObject()
+ {
+ return array(
+ 'single object' => array(
+ array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ null,
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'Should turn array into single object'
+ ),
+ 'multiple objects' => array(
+ array(
+ 'first' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'second' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'third' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ ),
+ null,
+ (object) array(
+ 'first' => (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'second' => (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'third' => (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ ),
+ 'Should turn multiple dimension array into nested objects'
+ ),
+ 'single object with class' => array(
+ array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'stdClass',
+ (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'Should turn array into single object'
+ ),
+ 'multiple objects with class' => array(
+ array(
+ 'first' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'second' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'third' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ ),
+ 'stdClass',
+ (object) array(
+ 'first' => (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'second' => (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'third' => (object) array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ ),
+ 'Should turn multiple dimension array into nested objects'
+ ),
+ );
+ }
+
+ /**
+ * Data provider for string inputs
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestToString()
+ {
+ return array(
+ 'single dimension 1' => array(
+ array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ null,
+ null,
+ false,
+ 'integer="12" float="1.29999" string="A Test String"',
+ 'Should turn array into single string with defaults',
+ true
+ ),
+ 'single dimension 2' => array(
+ array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ " = ",
+ null,
+ true,
+ 'integer = "12"float = "1.29999"string = "A Test String"',
+ 'Should turn array into single string with " = " and no spaces',
+ false
+ ),
+ 'single dimension 3' => array(
+ array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ ' = ',
+ ' then ',
+ true,
+ 'integer = "12" then float = "1.29999" then string = "A Test String"',
+ 'Should turn array into single string with " = " and then between elements',
+ false
+ ),
+ 'multiple dimensions 1' => array(
+ array(
+ 'first' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'second' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'third' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ ),
+ null,
+ null,
+ false,
+ 'integer="12" float="1.29999" string="A Test String" ' . 'integer="12" float="1.29999" string="A Test String" '
+ . 'integer="12" float="1.29999" string="A Test String"',
+ 'Should turn multiple dimension array into single string',
+ true
+ ),
+ 'multiple dimensions 2' => array(
+ array(
+ 'first' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'second' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'third' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ ),
+ ' = ',
+ null,
+ false,
+ 'integer = "12"float = "1.29999"string = "A Test String"' . 'integer = "12"float = "1.29999"string = "A Test String"'
+ . 'integer = "12"float = "1.29999"string = "A Test String"',
+ 'Should turn multiple dimension array into single string with " = " and no spaces',
+ false
+ ),
+ 'multiple dimensions 3' => array(
+ array(
+ 'first' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'second' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'third' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ ),
+ ' = ',
+ ' ',
+ false,
+ 'integer = "12" float = "1.29999" string = "A Test String" ' . 'integer = "12" float = "1.29999" string = "A Test String" '
+ . 'integer = "12" float = "1.29999" string = "A Test String"',
+ 'Should turn multiple dimension array into single string with " = " and a space',
+ false
+ ),
+ 'multiple dimensions 4' => array(
+ array(
+ 'first' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'second' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ 'third' => array(
+ 'integer' => 12, 'float' => 1.29999, 'string' => 'A Test String'
+ ),
+ ),
+ ' = ',
+ null,
+ true,
+ 'firstinteger = "12"float = "1.29999"string = "A Test String"' . 'secondinteger = "12"float = "1.29999"string = "A Test String"'
+ . 'thirdinteger = "12"float = "1.29999"string = "A Test String"',
+ 'Should turn multiple dimension array into single string with " = " and no spaces with outer key',
+ false
+ ),
+ );
+ }
+
+ /**
+ * Data provider for object inputs
+ *
+ * @return array
+ *
+ * @since 2.0
+ */
+ public function seedTestToArray()
+ {
+ return array(
+ 'string' => array(
+ 'foo',
+ false,
+ array('foo')
+ ),
+ 'array' => array(
+ array('foo'),
+ false,
+ array('foo')
+ ),
+ 'array_recursive' => array(
+ array('foo' => array(
+ (object) array('bar' => 'bar'),
+ (object) array('baz' => 'baz')
+ )),
+ true,
+ array('foo' => array(
+ array('bar' => 'bar'),
+ array('baz' => 'baz')
+ ))
+ ),
+ 'iterator' => array(
+ array('foo' => new \ArrayIterator(array('bar' => 'baz'))),
+ true,
+ array('foo' => array('bar' => 'baz'))
+ )
+ );
+ }
+
+ /**
+ * Tests the ArrayHelper::arrayUnique method.
+ *
+ * @param array $input The array being input.
+ * @param string $expected The expected return value.
+ *
+ * @return void
+ *
+ * @dataProvider seedTestArrayUnique
+ * @covers Windwalker\Utilities\ArrayHelper::arrayUnique
+ * @since 2.0
+ */
+ public function testArrayUnique($input, $expected)
+ {
+ $this->assertThat(
+ ArrayHelper::arrayUnique($input),
+ $this->equalTo($expected)
+ );
+ }
+
+ /**
+ * Tests conversion of object to string.
+ *
+ * @param array $input The array being input
+ * @param boolean $recurse Recurse through multiple dimensions?
+ * @param string $regex Regex to select only some attributes
+ * @param string $expect The expected return value
+ * @param boolean $defaults Use function defaults (true) or full argument list
+ *
+ * @return void
+ *
+ * @dataProvider seedTestFromObject
+ * @covers Windwalker\Utilities\ArrayHelper::fromObject
+ * @covers Windwalker\Utilities\ArrayHelper::arrayFromObject
+ * @since 2.0
+ */
+ public function testFromObject($input, $recurse, $regex, $expect, $defaults)
+ {
+ if ($defaults)
+ {
+ $output = ArrayHelper::fromObject($input);
+ }
+ else
+ {
+ $output = ArrayHelper::fromObject($input, $recurse, $regex);
+ }
+
+ $this->assertEquals($expect, $output);
+ }
+
+ /**
+ * Test pulling data from a single column (by index or association).
+ *
+ * @param array $input Input array
+ * @param mixed $index Column to pull, either by association or number
+ * @param array $expect The expected results
+ * @param string $message The failure message
+ *
+ * @return void
+ *
+ * @dataProvider seedTestGetColumn
+ * @covers Windwalker\Utilities\ArrayHelper::getColumn
+ * @since 2.0
+ */
+ public function testGetColumn($input, $index, $expect, $message)
+ {
+ $this->assertEquals($expect, ArrayHelper::getColumn($input, $index), $message);
+ }
+
+ /**
+ * Test get value from an array.
+ *
+ * @param array $input Input array
+ * @param mixed $index Element to pull, either by association or number
+ * @param mixed $default The defualt value, if element not present
+ * @param string $type The type of value returned
+ * @param array $expect The expected results
+ * @param string $message The failure message
+ * @param bool $defaults Use the defaults (true) or full argument list
+ *
+ * @return void
+ *
+ * @dataProvider seedTestGetValue
+ * @covers Windwalker\Utilities\ArrayHelper::getValue
+ * @since 2.0
+ */
+ public function testGetValue($input, $index, $default, $type, $expect, $message, $defaults)
+ {
+ if ($defaults)
+ {
+ $output = ArrayHelper::getValue($input, $index);
+ }
+ else
+ {
+ $output = ArrayHelper::getValue($input, $index, $default, $type);
+ }
+
+ $this->assertEquals($expect, $output, $message);
+ }
+
+ /**
+ * Method to test setValue
+ *
+ * @covers \Windwalker\Utilities\ArrayHelper::setValue
+ *
+ * @return void
+ */
+ public function testSetValue()
+ {
+ $data = array(
+ 'Archer' => 'Unlimited Blade World',
+ 'Saber' => 'Excalibur',
+ 'Lancer' => 'Gáe Bulg',
+ 'Rider' => 'Breaker Gorgon',
+ );
+ $data2 = (object) $data;
+
+ $newData = ArrayHelper::setValue($data, 'Saber', 'Avalon');
+
+ $this->assertEquals('Avalon', $data['Saber']);
+ $this->assertEquals('Avalon', $newData['Saber']);
+
+ $newData = ArrayHelper::setValue($data, 'Archer', 'Unlimited Blade Works');
+
+ $this->assertEquals('Unlimited Blade Works', $data['Archer']);
+ $this->assertEquals('Unlimited Blade Works', $newData['Archer']);
+
+ $newData = ArrayHelper::setValue($data, 'Berserker', 'Gold Hand');
+
+ $this->assertEquals('Gold Hand', $data['Berserker']);
+ $this->assertEquals('Gold Hand', $newData['Berserker']);
+
+ $newData2 = ArrayHelper::setValue($data2, 'Saber', 'Avalon');
+
+ $this->assertEquals('Avalon', $data2->Saber);
+ $this->assertEquals('Avalon', $newData2->Saber);
+
+ $newData2 = ArrayHelper::setValue($data2, 'Archer', 'Unlimited Blade Works');
+
+ $this->assertEquals('Unlimited Blade Works', $data2->Archer);
+ $this->assertEquals('Unlimited Blade Works', $newData2->Archer);
+
+ $newData2 = ArrayHelper::setValue($data2, 'Berserker', 'Gold Hand');
+
+ $this->assertEquals('Gold Hand', $data2->Berserker);
+ $this->assertEquals('Gold Hand', $newData2->Berserker);
+ }
+
+ /**
+ * Tests the ArrayHelper::invert method.
+ *
+ * @param array $input The array being input.
+ * @param string $expected The expected return value.
+ *
+ * @return void
+ *
+ * @dataProvider seedTestInvert
+ * @since 2.0
+ */
+ public function testInvert($input, $expected)
+ {
+ $this->assertThat(
+ ArrayHelper::invert($input),
+ $this->equalTo($expected)
+ );
+ }
+
+ /**
+ * Test the ArrayHelper::isAssociate method.
+ *
+ * @return void
+ *
+ * @since 2.0
+ * @sovers ArrayHelper::isAssociative
+ */
+ public function testIsAssociative()
+ {
+ $this->assertThat(
+ ArrayHelper::isAssociative(
+ array(
+ 1, 2, 3
+ )
+ ),
+ $this->isFalse(),
+ 'Line: ' . __LINE__ . ' This array should not be associative.'
+ );
+
+ $this->assertThat(
+ ArrayHelper::isAssociative(
+ array(
+ 'a' => 1, 'b' => 2, 'c' => 3
+ )
+ ),
+ $this->isTrue(),
+ 'Line: ' . __LINE__ . ' This array should be associative.'
+ );
+
+ $this->assertThat(
+ ArrayHelper::isAssociative(
+ array(
+ 'a' => 1, 2, 'c' => 3
+ )
+ ),
+ $this->isTrue(),
+ 'Line: ' . __LINE__ . ' This array should be associative.'
+ );
+ }
+
+ /**
+ * Tests the ArrayHelper::pivot method.
+ *
+ * @param array $source The source array.
+ * @param string $key Where the elements of the source array are objects or arrays, the key to pivot on.
+ * @param array $expected The expected result.
+ *
+ * @return void
+ *
+ * @dataProvider seedTestPivot
+ * @covers Windwalker\Utilities\ArrayHelper::pivot
+ * @since 2.0
+ */
+ public function testPivot($source, $key, $expected)
+ {
+ $this->assertThat(
+ ArrayHelper::pivot($source, $key),
+ $this->equalTo($expected)
+ );
+ }
+
+ /**
+ * Method to test pivotByKey().
+ *
+ * @param array $data
+ * @param array $expected
+ *
+ * @return void
+ *
+ * @dataProvider seedTestPivotByKey
+ * @covers \Windwalker\Helper\ArrayHelper::pivotByKey
+ */
+ public function testPivotByKey($data, $expected)
+ {
+ $this->assertEquals($expected, ArrayHelper::pivotByKey($data));
+ }
+
+ /**
+ * Test sorting an array of objects.
+ *
+ * @param array $input Input array of objects
+ * @param mixed $key Key to sort on
+ * @param mixed $direction Ascending (1) or Descending(-1)
+ * @param string $casesensitive @todo
+ * @param string $locale @todo
+ * @param array $expect The expected results
+ * @param string $message The failure message
+ * @param boolean $defaults Use the defaults (true) or full argument list
+ *
+ * @return void
+ *
+ * @dataProvider seedTestSortObject
+ * @covers Windwalker\Utilities\ArrayHelper::sortObjects
+ * @since 2.0
+ */
+ public function testSortObjects($input, $key, $direction, $casesensitive, $locale, $expect, $message, $defaults, $swappable_keys = array())
+ {
+ // Convert the $locale param to a string if it is an array
+ if (is_array($locale))
+ {
+ $locale = "'" . implode("', '", $locale) . "'";
+ }
+
+ if (empty($input))
+ {
+ $this->markTestSkipped('Skip for MAC until PHP sort bug is fixed');
+
+ return;
+ }
+ elseif ($locale != false && !setlocale(LC_COLLATE, $locale))
+ {
+ // If the locale is not available, we can't have to transcode the string and can't reliably compare it.
+ $this->markTestSkipped("Locale {$locale} is not available.");
+
+ return;
+ }
+
+ if ($defaults)
+ {
+ $output = ArrayHelper::sortObjects($input, $key);
+ }
+ else
+ {
+ $output = ArrayHelper::sortObjects($input, $key, $direction, $casesensitive, $locale);
+ }
+
+ // The ordering of elements that compare equal according to
+ // $key is undefined (implementation dependent).
+ if ($expect != $output && $swappable_keys) {
+ list($k1, $k2) = $swappable_keys;
+ $e1 = $output[$k1];
+ $e2 = $output[$k2];
+ $output[$k1] = $e2;
+ $output[$k2] = $e1;
+ }
+
+ $this->assertEquals($expect, $output, $message);
+ }
+
+ /**
+ * Test convert an array to all integers.
+ *
+ * @param string $input The array being input
+ * @param string $default The default value
+ * @param string $expect The expected return value
+ * @param string $message The failure message
+ *
+ * @return void
+ *
+ * @dataProvider seedTestToInteger
+ * @covers Windwalker\Utilities\ArrayHelper::toInteger
+ * @since 2.0
+ */
+ public function testToInteger($input, $default, $expect, $message)
+ {
+ $result = ArrayHelper::toInteger($input, $default);
+ $this->assertEquals(
+ $expect,
+ $result,
+ $message
+ );
+ }
+
+ /**
+ * Test convert array to object.
+ *
+ * @param string $input The array being input
+ * @param string $className The class name to build
+ * @param string $expect The expected return value
+ * @param string $message The failure message
+ *
+ * @return void
+ *
+ * @dataProvider seedTestToObject
+ * @covers Windwalker\Utilities\ArrayHelper::toObject
+ * @since 2.0
+ */
+ public function testToObject($input, $className, $expect, $message)
+ {
+ $this->assertEquals(
+ $expect,
+ ArrayHelper::toObject($input),
+ $message
+ );
+ }
+
+ /**
+ * testToArray
+ *
+ * @param $input
+ * @param $recursive
+ * @param $expect
+ *
+ * @return void
+ *
+ * @dataProvider seedTestToArray
+ * @covers Windwalker\Utilities\ArrayHelper::toArray
+ */
+ public function testToArray($input, $recursive, $expect)
+ {
+ $this->assertEquals($expect, ArrayHelper::toArray($input, $recursive));
+ }
+
+ /**
+ * Tests converting array to string.
+ *
+ * @param array $input The array being input
+ * @param string $inner The inner glue
+ * @param string $outer The outer glue
+ * @param boolean $keepKey Keep the outer key
+ * @param string $expect The expected return value
+ * @param string $message The failure message
+ * @param boolean $defaults Use function defaults (true) or full argument list
+ *
+ * @return void
+ *
+ * @dataProvider seedTestToString
+ * @covers Windwalker\Utilities\ArrayHelper::toString
+ * @since 2.0
+ */
+ public function testToString($input, $inner, $outer, $keepKey, $expect, $message, $defaults)
+ {
+ if ($defaults)
+ {
+ $output = ArrayHelper::toString($input);
+ }
+ else
+ {
+ $output = ArrayHelper::toString($input, $inner, $outer, $keepKey);
+ }
+
+ $this->assertEquals($expect, $output, $message);
+ }
+
+ /**
+ * Tests the arraySearch method.
+ *
+ * @return void
+ *
+ * @covers Windwalker\Utilities\ArrayHelper::arraySearch
+ * @since 2.0
+ */
+ public function testArraySearch()
+ {
+ $array = array(
+ 'name' => 'Foo',
+ 'email' => 'foobar@example.com'
+ );
+
+ // Search case sensitive.
+ $this->assertEquals('name', ArrayHelper::arraySearch('Foo', $array));
+
+ // Search case insenitive.
+ $this->assertEquals('email', ArrayHelper::arraySearch('FOOBAR', $array, false));
+
+ // Search non existent value.
+ $this->assertEquals(false, ArrayHelper::arraySearch('barfoo', $array));
+ }
+
+ /**
+ * testFlatten
+ *
+ * @return void
+ *
+ * @covers Windwalker\Utilities\ArrayHelper::flatten
+ * @since 2.0
+ */
+ public function testFlatten()
+ {
+ $array = array(
+ 'flower' => 'sakura',
+ 'olive' => 'peace',
+ 'pos1' => array(
+ 'sunflower' => 'love'
+ ),
+ 'pos2' => array(
+ 'cornflower' => 'elegant'
+ )
+ );
+
+ $flatted = ArrayHelper::flatten($array);
+
+ $this->assertEquals($flatted['pos1.sunflower'], 'love');
+
+ $flatted = ArrayHelper::flatten($array, '/');
+
+ $this->assertEquals($flatted['pos1/sunflower'], 'love');
+ }
+
+ /**
+ * Method to test query()
+ *
+ * @covers \Windwalker\Utilities\ArrayHelper::query
+ *
+ * @return void
+ */
+ public function testQuery()
+ {
+ $data = array(
+ array(
+ 'id' => 1,
+ 'title' => 'Julius Caesar',
+ 'data' => (object) array('foo' => 'bar'),
+ ),
+ array(
+ 'id' => 2,
+ 'title' => 'Macbeth',
+ 'data' => array(),
+ ),
+ array(
+ 'id' => 3,
+ 'title' => 'Othello',
+ 'data' => 123,
+ ),
+ array(
+ 'id' => 4,
+ 'title' => 'Hamlet',
+ 'data' => true,
+ ),
+ );
+
+ // Test id equals
+ $this->assertEquals(array($data[1]), ArrayHelper::query($data, array('id' => 2)));
+
+ // Test strict equals
+ $this->assertEquals(array($data[0], $data[2], $data[3]), ArrayHelper::query($data, array('data' => true), false));
+ $this->assertEquals(array($data[3]), ArrayHelper::query($data, array('data' => true), true));
+
+ // Test id GT
+ $this->assertEquals(array($data[1], $data[2], $data[3]), ArrayHelper::query($data, array('id >' => 1)));
+
+ // Test id GTE
+ $this->assertEquals(array($data[1], $data[2], $data[3]), ArrayHelper::query($data, array('id >=' => 2)));
+
+ // Test id LT
+ $this->assertEquals(array($data[0], $data[1]), ArrayHelper::query($data, array('id <' => 3)));
+
+ // Test id LTE
+ $this->assertEquals(array($data[0], $data[1]), ArrayHelper::query($data, array('id <=' => 2)));
+
+ // Test array equals
+ $this->assertEquals(array($data[1]), ArrayHelper::query($data, array('data' => array())));
+
+ // Test object equals
+ $object = new \stdClass;
+ $object->foo = 'bar';
+ $this->assertEquals(array($data[0], $data[3]), ArrayHelper::query($data, array('data' => $object)));
+
+ // Test object strict equals
+ $this->assertEquals(array($data[0]), ArrayHelper::query($data, array('data' => $data[0]['data']), true));
+
+ // Test Keep Key
+ $this->assertEquals(array(1 => $data[1], 2 => $data[2], 3 => $data[3]), ArrayHelper::query($data, array('id >=' => 2), false, true));
+ }
+
+ /**
+ * Method to test mapKey
+ *
+ * @covers \Windwalker\Utilities\ArrayHelper::mapKey
+ *
+ * @return void
+ */
+ public function testMapKey()
+ {
+ $data = array(
+ 'top' => 'Captain America',
+ 'middle' => 'Iron Man',
+ 'bottom' => 'Thor',
+ );
+ $data2 = (object) $data;
+
+ $map = array(
+ 'middle' => 'bottom',
+ 'bottom' => 'middle',
+ );
+
+ $expected = array(
+ 'top' => 'Captain America',
+ 'middle' => 'Thor',
+ 'bottom' => 'Iron Man',
+ );
+ $expected2 = (object) $expected;
+
+ $result = ArrayHelper::mapKey($data, $map);
+ $this->assertEquals($expected, $result);
+
+ $result2 = ArrayHelper::mapKey($data2, $map);
+ $this->assertEquals($expected2, $result2);
+ }
+
+ /**
+ * Method to test merge
+ *
+ * @covers \Windwalker\Utilities\ArrayHelper::merge
+ *
+ * @return void
+ */
+ public function testMerge()
+ {
+ $data1 = array(
+ 'green' => 'Hulk',
+ 'red' => 'empty',
+ 'human' => array(
+ 'dark' => 'empty',
+ 'black' => array(
+ 'male' => 'empty',
+ 'female' => 'empty',
+ 'no-gender' => 'empty',
+ ),
+ )
+ );
+ $data2 = array(
+ 'ai' => 'Jarvis',
+ 'agent' => 'Phil Coulson',
+ 'red' => array(
+ 'left' => 'Pepper',
+ 'right' => 'Iron Man',
+ ),
+ 'human' => array(
+ 'dark' => 'Nick Fury',
+ 'black' => array(
+ 'female' => 'Black Widow',
+ 'male' => 'Loki',
+ ),
+ )
+ );
+
+ $expected = array(
+ 'ai' => 'Jarvis',
+ 'agent' => 'Phil Coulson',
+ 'green' => 'Hulk',
+ 'red' => array(
+ 'left' => 'Pepper',
+ 'right' => 'Iron Man',
+ ),
+ 'human' => array(
+ 'dark' => 'Nick Fury',
+ 'black' => array(
+ 'male' => 'Loki',
+ 'female' => 'Black Widow',
+ 'no-gender' => 'empty',
+ ),
+ ),
+ );
+
+ $expected2 = array(
+ 'ai' => 'Jarvis',
+ 'agent' => 'Phil Coulson',
+ 'green' => 'Hulk',
+ 'red' => array(
+ 'left' => 'Pepper',
+ 'right' => 'Iron Man',
+ ),
+ 'human' => array(
+ 'dark' => 'Nick Fury',
+ 'black' => array(
+ 'male' => 'Loki',
+ 'female' => 'Black Widow',
+ ),
+ ),
+ );
+
+ $this->assertEquals($expected, ArrayHelper::merge($data1, $data2));
+ $this->assertEquals($expected2, ArrayHelper::merge($data1, $data2, false));
+ }
+
+ /**
+ * testGetByPath
+ *
+ * @return void
+ *
+ * @covers \Windwalker\Utilities\ArrayHelper::getByPath
+ */
+ public function testGetByPath()
+ {
+ $data = array(
+ 'flower' => 'sakura',
+ 'olive' => 'peace',
+ 'pos1' => array(
+ 'sunflower' => 'love'
+ ),
+ 'pos2' => array(
+ 'cornflower' => 'elegant'
+ ),
+ 'array' => array(
+ 'A',
+ 'B',
+ 'C'
+ )
+ );
+
+ $this->assertEquals('sakura', ArrayHelper::getByPath($data, 'flower'));
+ $this->assertEquals('love', ArrayHelper::getByPath($data, 'pos1.sunflower'));
+ $this->assertEquals('love', ArrayHelper::getByPath($data, 'pos1/sunflower', '/'));
+ $this->assertEquals($data['array'], ArrayHelper::getByPath($data, 'array'));
+ $this->assertNull(ArrayHelper::getByPath($data, 'not.exists'));
+ }
+
+ /**
+ * testSetByPath
+ *
+ * @return void
+ *
+ * @covers \Windwalker\Utilities\ArrayHelper::setByPath
+ */
+ public function testSetByPath()
+ {
+ $data = array();
+
+ // One level
+ $return = ArrayHelper::setByPath($data, 'flower', 'sakura');
+
+ $this->assertEquals('sakura', $data['flower']);
+ $this->assertTrue($return);
+
+ // Multi-level
+ ArrayHelper::setByPath($data, 'foo.bar', 'test');
+
+ $this->assertEquals('test', $data['foo']['bar']);
+
+ // Separator
+ ArrayHelper::setByPath($data, 'foo/bar', 'play', '/');
+
+ $this->assertEquals('play', $data['foo']['bar']);
+
+ // Type
+ ArrayHelper::setByPath($data, 'cloud/fly', 'bird', '/', 'stdClass');
+
+ $this->assertEquals('bird', $data['cloud']->fly);
+
+ // False
+ $return = ArrayHelper::setByPath($data, '', 'goo');
+
+ $this->assertFalse($return);
+
+ // Fix path
+ ArrayHelper::setByPath($data, 'double..separators', 'value');
+
+ $this->assertEquals('value', $data['double']['separators']);
+
+ $this->assertExpectedException(function()
+ {
+ ArrayHelper::setByPath($data, 'a.b', 'c', '.', 'Non\Exists\Class');
+ }, new \InvalidArgumentException, 'Type or class: Non\Exists\Class not exists');
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Test/functionsTest.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Test/functionsTest.php
new file mode 100644
index 00000000..a29eb61e
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Test/functionsTest.php
@@ -0,0 +1,32 @@
+assertEquals(
+ new \stdClass,
+ $object
+ );
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Test/index.html b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Test/index.html
new file mode 100644
index 00000000..2efb97f3
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/Test/index.html
@@ -0,0 +1 @@
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/composer.json b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/composer.json
new file mode 100644
index 00000000..8e768d8f
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/composer.json
@@ -0,0 +1,29 @@
+{
+ "name": "windwalker/utilities",
+ "type": "windwalker-package",
+ "description": "Windwalker Utilities package",
+ "keywords": ["windwalker", "framework", "utilities"],
+ "homepage": "https://github.com/ventoviro/windwalker-utilities",
+ "license": "LGPL-2.0+",
+ "require": {
+ "php": ">=5.3.10",
+ "windwalker/string": "~2.0"
+ },
+ "require-dev": {
+ "windwalker/test": "~2.0"
+ },
+ "minimum-stability": "beta",
+ "autoload": {
+ "psr-4": {
+ "Windwalker\\Utilities\\": ""
+ },
+ "files": [
+ "functions.php"
+ ]
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/functions.php b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/functions.php
new file mode 100644
index 00000000..d2ee23f1
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/functions.php
@@ -0,0 +1,92 @@
+bar().
+ * See: http://php.net/manual/en/migration54.new-features.php
+ *
+ * @param mixed $object The object to return.
+ *
+ * @since 2.0
+ *
+ * @return mixed
+ */
+ function with($object)
+ {
+ return $object;
+ }
+}
+
+if (!function_exists('show'))
+{
+ /**
+ * Dump Array or Object as tree node. If send multiple params in this method, this function will batch print it.
+ *
+ * @param mixed $data Array or Object to dump.
+ *
+ * @since 2.0
+ *
+ * @return void
+ */
+ function show($data)
+ {
+ $args = func_get_args();
+
+ $last = array_pop($args);
+
+ if (is_int($last))
+ {
+ $level = $last;
+ }
+ else
+ {
+ $level = 5;
+
+ $args[] = $last;
+ }
+
+ echo "\n\n";
+
+ if (PHP_SAPI != 'cli')
+ {
+ echo '';
+ }
+
+ // Dump Multiple values
+ if (count($args) > 1)
+ {
+ $prints = array();
+
+ $i = 1;
+
+ foreach ($args as $arg)
+ {
+ $prints[] = "[Value " . $i . "]\n" . \Windwalker\Utilities\ArrayHelper::dump($arg, $level);
+ $i++;
+ }
+
+ echo implode("\n\n", $prints);
+ }
+ else
+ {
+ // Dump one value.
+ echo \Windwalker\Utilities\ArrayHelper::dump($data, $level);
+ }
+
+ if (PHP_SAPI != 'cli')
+ {
+ echo ' ';
+ }
+ }
+}
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/phpunit.travis.xml b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/phpunit.travis.xml
new file mode 100644
index 00000000..690ec926
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/phpunit.travis.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/phpunit.xml.dist b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/phpunit.xml.dist
new file mode 100644
index 00000000..94b6811c
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/vendor/windwalker/utilities/phpunit.xml.dist
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ Test
+
+
+
diff --git a/deployed/windwalker/libraries/windwalker/windwalker.xml b/deployed/windwalker/libraries/windwalker/windwalker.xml
new file mode 100644
index 00000000..0b2ccf5b
--- /dev/null
+++ b/deployed/windwalker/libraries/windwalker/windwalker.xml
@@ -0,0 +1,46 @@
+
+
+ windwalker
+ windwalker
+ 2012-11-23
+ Copyright (C) 2008 - 2016 LYRASOFT. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ Asika
+ asika32764@gmail.com
+ http://lyrasoft.net
+ 2.1.18
+ 2.1.18
+ LIB_WINDWALKER_XML_DESC
+
+
+ bin
+ bundles
+ language
+ resource
+ src
+ vendor
+ composer.json
+ composer.lock
+ config.dist.json
+ index.html
+ windwalker.xml
+
+
+
+ css
+ js
+ index.html
+
+
+
+ zh-TW/zh-TW.lib_windwalker.ini
+ zh-TW/zh-TW.lib_windwalker.sys.ini
+
+ en-GB/en-GB.lib_windwalker.ini
+ en-GB/en-GB.lib_windwalker.sys.ini
+
+
+
+ https://raw.githubusercontent.com/ventoviro/windwalker-joomla-rad/staging/update.xml
+
+
diff --git a/deployed/windwalker/media/windwalker/css/index.html b/deployed/windwalker/media/windwalker/css/index.html
new file mode 100644
index 00000000..2efb97f3
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/css/index.html
@@ -0,0 +1 @@
+
diff --git a/deployed/windwalker/media/windwalker/css/jquery-ui/index.html b/deployed/windwalker/media/windwalker/css/jquery-ui/index.html
new file mode 100644
index 00000000..2efb97f3
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/css/jquery-ui/index.html
@@ -0,0 +1 @@
+
diff --git a/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/index.html b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/index.html
new file mode 100644
index 00000000..3af63015
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 00000000..5b5dab2a
Binary files /dev/null and b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644
index 00000000..ac8b229a
Binary files /dev/null and b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_flat_75_ffffff_40x100.png differ
diff --git a/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644
index 00000000..ad3d6346
Binary files /dev/null and b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png differ
diff --git a/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644
index 00000000..42ccba26
Binary files /dev/null and b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644
index 00000000..5a46b47c
Binary files /dev/null and b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_75_dadada_1x400.png differ
diff --git a/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644
index 00000000..86c2baa6
Binary files /dev/null and b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png differ
diff --git a/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644
index 00000000..4443fdc1
Binary files /dev/null and b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644
index 00000000..7c9fa6c6
Binary files /dev/null and b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ
diff --git a/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-icons_222222_256x240.png b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-icons_222222_256x240.png
new file mode 100644
index 00000000..b273ff11
Binary files /dev/null and b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/images/ui-icons_222222_256x240.png differ
diff --git a/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/index.html b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/index.html
new file mode 100644
index 00000000..3af63015
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/jquery-ui-1.8.24.custom.css b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/jquery-ui-1.8.24.custom.css
new file mode 100644
index 00000000..cd166a6b
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/css/jquery-ui/smoothness/jquery-ui-1.8.24.custom.css
@@ -0,0 +1,563 @@
+/*!
+ * jQuery UI CSS Framework 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
+.ui-helper-clearfix:after { clear: both; }
+.ui-helper-clearfix { zoom: 1; }
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
+
+
+/*!
+ * jQuery UI CSS Framework 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ *
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+ */
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
+.ui-widget .ui-widget { font-size: 1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
+.ui-widget-content a { color: #222222; }
+.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
+.ui-widget-header a { color: #222222; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
+.ui-widget :active { outline: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
+.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
+.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
+.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*!
+ * jQuery UI Resizable 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizable#theming
+ */
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*!
+ * jQuery UI Selectable 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectable#theming
+ */
+.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
+/*!
+ * jQuery UI Accordion 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion#theming
+ */
+/* IE/Win - Fix animation bug - #4615 */
+.ui-accordion { width: 100%; }
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
+.ui-accordion .ui-accordion-li-fix { display: inline; }
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
+.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
+.ui-accordion .ui-accordion-content-active { display: block; }
+/*!
+ * jQuery UI Autocomplete 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete#theming
+ */
+.ui-autocomplete { position: absolute; cursor: default; }
+
+/* workarounds */
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
+
+/*
+ * jQuery UI Menu 1.8.24
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Menu#theming
+ */
+.ui-menu {
+ list-style:none;
+ padding: 2px;
+ margin: 0;
+ display:block;
+ float: left;
+}
+.ui-menu .ui-menu {
+ margin-top: -3px;
+}
+.ui-menu .ui-menu-item {
+ margin:0;
+ padding: 0;
+ zoom: 1;
+ float: left;
+ clear: left;
+ width: 100%;
+}
+.ui-menu .ui-menu-item a {
+ text-decoration:none;
+ display:block;
+ padding:.2em .4em;
+ line-height:1.5;
+ zoom:1;
+}
+.ui-menu .ui-menu-item a.ui-state-hover,
+.ui-menu .ui-menu-item a.ui-state-active {
+ font-weight: normal;
+ margin: -1px;
+}
+/*!
+ * jQuery UI Button 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button#theming
+ */
+.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
+.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
+button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
+.ui-button-icons-only { width: 3.4em; }
+button.ui-button-icons-only { width: 3.7em; }
+
+/*button text element */
+.ui-button .ui-button-text { display: block; line-height: 1.4; }
+.ui-button-text-only .ui-button-text { padding: .4em 1em; }
+.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
+.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
+.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
+.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
+/* no icon support for input elements, provide padding by default */
+input.ui-button { padding: .4em 1em; }
+
+/*button icon element(s) */
+.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
+.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
+.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
+.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+
+/*button sets*/
+.ui-buttonset { margin-right: 7px; }
+.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
+
+/* workarounds */
+button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
+/*!
+ * jQuery UI Dialog 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog#theming
+ */
+.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
+.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
+.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
+/*!
+ * jQuery UI Slider 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider#theming
+ */
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }/*!
+ * jQuery UI Tabs 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs#theming
+ */
+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
+/*!
+ * jQuery UI Datepicker 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker#theming
+ */
+.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+ position: absolute; /*must have*/
+ z-index: -1; /*must have*/
+ filter: mask(); /*must have*/
+ top: -4px; /*must have*/
+ left: -4px; /*must have*/
+ width: 200px; /*must have*/
+ height: 200px; /*must have*/
+}/*!
+ * jQuery UI Progressbar 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar#theming
+ */
+.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/css/windwalker-admin.css b/deployed/windwalker/media/windwalker/css/windwalker-admin.css
new file mode 100644
index 00000000..78924c05
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/css/windwalker-admin.css
@@ -0,0 +1,57 @@
+/**
+ * Windwalker CSS
+ *
+ * Copyright 2014 Asikart.com
+ * License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE
+ *
+ * Author: Asika
+ */
+
+/* Search tools */
+.js-stools .search-field.btn-wrapper
+{
+ margin: 0;
+}
+
+.search-field #search_field
+{
+ margin: 0;
+ margin-right: 5px;
+}
+
+/* FORM */
+.control-group .star {
+ color: red;
+}
+
+#editor-xtd-buttons {
+ float: none;
+}
+
+.wf_editor_toggle,
+.mceEditor {
+ float: left;
+ width: 100%;
+}
+
+/* MODAL */
+.admin div.modal,
+.admin div.modal-body,
+.windwalker div.modal,
+.windwalker div.modal-body{
+ overflow: visible;
+}
+
+.cursor-pointer {
+ cursor: pointer;
+}
+
+/* TABLE LIST */
+.quick-edit-hover:hover {
+ background-color: yellow ;
+}
+
+.quick-edit-selected {
+ border: 1px solid blue !important;
+}
+
diff --git a/deployed/windwalker/media/windwalker/css/windwalker.css b/deployed/windwalker/media/windwalker/css/windwalker.css
new file mode 100644
index 00000000..53d062b8
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/css/windwalker.css
@@ -0,0 +1,35 @@
+/**
+ * Windwalker CSS
+ *
+ * Copyright 2013 Asikart.com
+ * License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+ *
+ * Generator: AKHelper
+ * Author: Asika
+ */
+
+
+/* FORM */
+.control-group .star {
+ color: red;
+}
+
+#editor-xtd-buttons {
+ float: none;
+}
+
+.wf_editor_toggle,
+.mceEditor {
+ float: left;
+ width: 100%;
+}
+
+
+/* TABLE LIST */
+.quick-edit-hover:hover {
+ background-color: yellow ;
+}
+
+.quick-edit-selected {
+ border: 1px solid blue !important;
+}
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/index.html b/deployed/windwalker/media/windwalker/index.html
new file mode 100644
index 00000000..2efb97f3
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/index.html
@@ -0,0 +1 @@
+
diff --git a/deployed/windwalker/media/windwalker/js/core/backbone.js b/deployed/windwalker/media/windwalker/js/core/backbone.js
new file mode 100644
index 00000000..53ff983a
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/core/backbone.js
@@ -0,0 +1,1893 @@
+// Backbone.js 1.2.2
+
+// (c) 2010-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Backbone may be freely distributed under the MIT license.
+// For all details and documentation:
+// http://backbonejs.org
+
+(function(factory) {
+
+ // Establish the root object, `window` (`self`) in the browser, or `global` on the server.
+ // We use `self` instead of `window` for `WebWorker` support.
+ var root = (typeof self == 'object' && self.self == self && self) ||
+ (typeof global == 'object' && global.global == global && global);
+
+ // Set up Backbone appropriately for the environment. Start with AMD.
+ if (typeof define === 'function' && define.amd) {
+ define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
+ // Export global even in AMD case in case this script is loaded with
+ // others that may still expect a global Backbone.
+ root.Backbone = factory(root, exports, _, $);
+ });
+
+ // Next for Node.js or CommonJS. jQuery may not be needed as a module.
+ } else if (typeof exports !== 'undefined') {
+ var _ = require('underscore'), $;
+ try { $ = require('jquery'); } catch(e) {}
+ factory(root, exports, _, $);
+
+ // Finally, as a browser global.
+ } else {
+ root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
+ }
+
+}(function(root, Backbone, _, $) {
+
+ // Initial Setup
+ // -------------
+
+ // Save the previous value of the `Backbone` variable, so that it can be
+ // restored later on, if `noConflict` is used.
+ var previousBackbone = root.Backbone;
+
+ // Create a local reference to a common array method we'll want to use later.
+ var slice = Array.prototype.slice;
+
+ // Current version of the library. Keep in sync with `package.json`.
+ Backbone.VERSION = '1.2.2';
+
+ // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
+ // the `$` variable.
+ Backbone.$ = $;
+
+ // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
+ // to its previous owner. Returns a reference to this Backbone object.
+ Backbone.noConflict = function() {
+ root.Backbone = previousBackbone;
+ return this;
+ };
+
+ // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
+ // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and
+ // set a `X-Http-Method-Override` header.
+ Backbone.emulateHTTP = false;
+
+ // Turn on `emulateJSON` to support legacy servers that can't deal with direct
+ // `application/json` requests ... this will encode the body as
+ // `application/x-www-form-urlencoded` instead and will send the model in a
+ // form param named `model`.
+ Backbone.emulateJSON = false;
+
+ // Proxy Backbone class methods to Underscore functions, wrapping the model's
+ // `attributes` object or collection's `models` array behind the scenes.
+ //
+ // collection.filter(function(model) { return model.get('age') > 10 });
+ // collection.each(this.addView);
+ //
+ // `Function#apply` can be slow so we use the method's arg count, if we know it.
+ var addMethod = function(length, method, attribute) {
+ switch (length) {
+ case 1: return function() {
+ return _[method](this[attribute]);
+ };
+ case 2: return function(value) {
+ return _[method](this[attribute], value);
+ };
+ case 3: return function(iteratee, context) {
+ return _[method](this[attribute], cb(iteratee, this), context);
+ };
+ case 4: return function(iteratee, defaultVal, context) {
+ return _[method](this[attribute], cb(iteratee, this), defaultVal, context);
+ };
+ default: return function() {
+ var args = slice.call(arguments);
+ args.unshift(this[attribute]);
+ return _[method].apply(_, args);
+ };
+ }
+ };
+ var addUnderscoreMethods = function(Class, methods, attribute) {
+ _.each(methods, function(length, method) {
+ if (_[method]) Class.prototype[method] = addMethod(length, method, attribute);
+ });
+ };
+
+ // Support `collection.sortBy('attr')` and `collection.findWhere({id: 1})`.
+ var cb = function(iteratee, instance) {
+ if (_.isFunction(iteratee)) return iteratee;
+ if (_.isObject(iteratee) && !instance._isModel(iteratee)) return modelMatcher(iteratee);
+ if (_.isString(iteratee)) return function(model) { return model.get(iteratee); };
+ return iteratee;
+ };
+ var modelMatcher = function(attrs) {
+ var matcher = _.matches(attrs);
+ return function(model) {
+ return matcher(model.attributes);
+ };
+ };
+
+ // Backbone.Events
+ // ---------------
+
+ // A module that can be mixed in to *any object* in order to provide it with
+ // a custom event channel. You may bind a callback to an event with `on` or
+ // remove with `off`; `trigger`-ing an event fires all callbacks in
+ // succession.
+ //
+ // var object = {};
+ // _.extend(object, Backbone.Events);
+ // object.on('expand', function(){ alert('expanded'); });
+ // object.trigger('expand');
+ //
+ var Events = Backbone.Events = {};
+
+ // Regular expression used to split event strings.
+ var eventSplitter = /\s+/;
+
+ // Iterates over the standard `event, callback` (as well as the fancy multiple
+ // space-separated events `"change blur", callback` and jQuery-style event
+ // maps `{event: callback}`).
+ var eventsApi = function(iteratee, events, name, callback, opts) {
+ var i = 0, names;
+ if (name && typeof name === 'object') {
+ // Handle event maps.
+ if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback;
+ for (names = _.keys(name); i < names.length ; i++) {
+ events = eventsApi(iteratee, events, names[i], name[names[i]], opts);
+ }
+ } else if (name && eventSplitter.test(name)) {
+ // Handle space separated event names by delegating them individually.
+ for (names = name.split(eventSplitter); i < names.length; i++) {
+ events = iteratee(events, names[i], callback, opts);
+ }
+ } else {
+ // Finally, standard events.
+ events = iteratee(events, name, callback, opts);
+ }
+ return events;
+ };
+
+ // Bind an event to a `callback` function. Passing `"all"` will bind
+ // the callback to all events fired.
+ Events.on = function(name, callback, context) {
+ return internalOn(this, name, callback, context);
+ };
+
+ // Guard the `listening` argument from the public API.
+ var internalOn = function(obj, name, callback, context, listening) {
+ obj._events = eventsApi(onApi, obj._events || {}, name, callback, {
+ context: context,
+ ctx: obj,
+ listening: listening
+ });
+
+ if (listening) {
+ var listeners = obj._listeners || (obj._listeners = {});
+ listeners[listening.id] = listening;
+ }
+
+ return obj;
+ };
+
+ // Inversion-of-control versions of `on`. Tell *this* object to listen to
+ // an event in another object... keeping track of what it's listening to
+ // for easier unbinding later.
+ Events.listenTo = function(obj, name, callback) {
+ if (!obj) return this;
+ var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
+ var listeningTo = this._listeningTo || (this._listeningTo = {});
+ var listening = listeningTo[id];
+
+ // This object is not listening to any other events on `obj` yet.
+ // Setup the necessary references to track the listening callbacks.
+ if (!listening) {
+ var thisId = this._listenId || (this._listenId = _.uniqueId('l'));
+ listening = listeningTo[id] = {obj: obj, objId: id, id: thisId, listeningTo: listeningTo, count: 0};
+ }
+
+ // Bind callbacks on obj, and keep track of them on listening.
+ internalOn(obj, name, callback, this, listening);
+ return this;
+ };
+
+ // The reducing API that adds a callback to the `events` object.
+ var onApi = function(events, name, callback, options) {
+ if (callback) {
+ var handlers = events[name] || (events[name] = []);
+ var context = options.context, ctx = options.ctx, listening = options.listening;
+ if (listening) listening.count++;
+
+ handlers.push({ callback: callback, context: context, ctx: context || ctx, listening: listening });
+ }
+ return events;
+ };
+
+ // Remove one or many callbacks. If `context` is null, removes all
+ // callbacks with that function. If `callback` is null, removes all
+ // callbacks for the event. If `name` is null, removes all bound
+ // callbacks for all events.
+ Events.off = function(name, callback, context) {
+ if (!this._events) return this;
+ this._events = eventsApi(offApi, this._events, name, callback, {
+ context: context,
+ listeners: this._listeners
+ });
+ return this;
+ };
+
+ // Tell this object to stop listening to either specific events ... or
+ // to every object it's currently listening to.
+ Events.stopListening = function(obj, name, callback) {
+ var listeningTo = this._listeningTo;
+ if (!listeningTo) return this;
+
+ var ids = obj ? [obj._listenId] : _.keys(listeningTo);
+
+ for (var i = 0; i < ids.length; i++) {
+ var listening = listeningTo[ids[i]];
+
+ // If listening doesn't exist, this object is not currently
+ // listening to obj. Break out early.
+ if (!listening) break;
+
+ listening.obj.off(name, callback, this);
+ }
+ if (_.isEmpty(listeningTo)) this._listeningTo = void 0;
+
+ return this;
+ };
+
+ // The reducing API that removes a callback from the `events` object.
+ var offApi = function(events, name, callback, options) {
+ if (!events) return;
+
+ var i = 0, listening;
+ var context = options.context, listeners = options.listeners;
+
+ // Delete all events listeners and "drop" events.
+ if (!name && !callback && !context) {
+ var ids = _.keys(listeners);
+ for (; i < ids.length; i++) {
+ listening = listeners[ids[i]];
+ delete listeners[listening.id];
+ delete listening.listeningTo[listening.objId];
+ }
+ return;
+ }
+
+ var names = name ? [name] : _.keys(events);
+ for (; i < names.length; i++) {
+ name = names[i];
+ var handlers = events[name];
+
+ // Bail out if there are no events stored.
+ if (!handlers) break;
+
+ // Replace events if there are any remaining. Otherwise, clean up.
+ var remaining = [];
+ for (var j = 0; j < handlers.length; j++) {
+ var handler = handlers[j];
+ if (
+ callback && callback !== handler.callback &&
+ callback !== handler.callback._callback ||
+ context && context !== handler.context
+ ) {
+ remaining.push(handler);
+ } else {
+ listening = handler.listening;
+ if (listening && --listening.count === 0) {
+ delete listeners[listening.id];
+ delete listening.listeningTo[listening.objId];
+ }
+ }
+ }
+
+ // Update tail event if the list has any events. Otherwise, clean up.
+ if (remaining.length) {
+ events[name] = remaining;
+ } else {
+ delete events[name];
+ }
+ }
+ if (_.size(events)) return events;
+ };
+
+ // Bind an event to only be triggered a single time. After the first time
+ // the callback is invoked, its listener will be removed. If multiple events
+ // are passed in using the space-separated syntax, the handler will fire
+ // once for each event, not once for a combination of all events.
+ Events.once = function(name, callback, context) {
+ // Map the event into a `{event: once}` object.
+ var events = eventsApi(onceMap, {}, name, callback, _.bind(this.off, this));
+ return this.on(events, void 0, context);
+ };
+
+ // Inversion-of-control versions of `once`.
+ Events.listenToOnce = function(obj, name, callback) {
+ // Map the event into a `{event: once}` object.
+ var events = eventsApi(onceMap, {}, name, callback, _.bind(this.stopListening, this, obj));
+ return this.listenTo(obj, events);
+ };
+
+ // Reduces the event callbacks into a map of `{event: onceWrapper}`.
+ // `offer` unbinds the `onceWrapper` after it has been called.
+ var onceMap = function(map, name, callback, offer) {
+ if (callback) {
+ var once = map[name] = _.once(function() {
+ offer(name, once);
+ callback.apply(this, arguments);
+ });
+ once._callback = callback;
+ }
+ return map;
+ };
+
+ // Trigger one or many events, firing all bound callbacks. Callbacks are
+ // passed the same arguments as `trigger` is, apart from the event name
+ // (unless you're listening on `"all"`, which will cause your callback to
+ // receive the true name of the event as the first argument).
+ Events.trigger = function(name) {
+ if (!this._events) return this;
+
+ var length = Math.max(0, arguments.length - 1);
+ var args = Array(length);
+ for (var i = 0; i < length; i++) args[i] = arguments[i + 1];
+
+ eventsApi(triggerApi, this._events, name, void 0, args);
+ return this;
+ };
+
+ // Handles triggering the appropriate event callbacks.
+ var triggerApi = function(objEvents, name, cb, args) {
+ if (objEvents) {
+ var events = objEvents[name];
+ var allEvents = objEvents.all;
+ if (events && allEvents) allEvents = allEvents.slice();
+ if (events) triggerEvents(events, args);
+ if (allEvents) triggerEvents(allEvents, [name].concat(args));
+ }
+ return objEvents;
+ };
+
+ // A difficult-to-believe, but optimized internal dispatch function for
+ // triggering events. Tries to keep the usual cases speedy (most internal
+ // Backbone events have 3 arguments).
+ var triggerEvents = function(events, args) {
+ var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
+ switch (args.length) {
+ case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
+ case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
+ case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
+ case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
+ default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
+ }
+ };
+
+ // Aliases for backwards compatibility.
+ Events.bind = Events.on;
+ Events.unbind = Events.off;
+
+ // Allow the `Backbone` object to serve as a global event bus, for folks who
+ // want global "pubsub" in a convenient place.
+ _.extend(Backbone, Events);
+
+ // Backbone.Model
+ // --------------
+
+ // Backbone **Models** are the basic data object in the framework --
+ // frequently representing a row in a table in a database on your server.
+ // A discrete chunk of data and a bunch of useful, related methods for
+ // performing computations and transformations on that data.
+
+ // Create a new model with the specified attributes. A client id (`cid`)
+ // is automatically generated and assigned for you.
+ var Model = Backbone.Model = function(attributes, options) {
+ var attrs = attributes || {};
+ options || (options = {});
+ this.cid = _.uniqueId(this.cidPrefix);
+ this.attributes = {};
+ if (options.collection) this.collection = options.collection;
+ if (options.parse) attrs = this.parse(attrs, options) || {};
+ attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
+ this.set(attrs, options);
+ this.changed = {};
+ this.initialize.apply(this, arguments);
+ };
+
+ // Attach all inheritable methods to the Model prototype.
+ _.extend(Model.prototype, Events, {
+
+ // A hash of attributes whose current and previous value differ.
+ changed: null,
+
+ // The value returned during the last failed validation.
+ validationError: null,
+
+ // The default name for the JSON `id` attribute is `"id"`. MongoDB and
+ // CouchDB users may want to set this to `"_id"`.
+ idAttribute: 'id',
+
+ // The prefix is used to create the client id which is used to identify models locally.
+ // You may want to override this if you're experiencing name clashes with model ids.
+ cidPrefix: 'c',
+
+ // Initialize is an empty function by default. Override it with your own
+ // initialization logic.
+ initialize: function(){},
+
+ // Return a copy of the model's `attributes` object.
+ toJSON: function(options) {
+ return _.clone(this.attributes);
+ },
+
+ // Proxy `Backbone.sync` by default -- but override this if you need
+ // custom syncing semantics for *this* particular model.
+ sync: function() {
+ return Backbone.sync.apply(this, arguments);
+ },
+
+ // Get the value of an attribute.
+ get: function(attr) {
+ return this.attributes[attr];
+ },
+
+ // Get the HTML-escaped value of an attribute.
+ escape: function(attr) {
+ return _.escape(this.get(attr));
+ },
+
+ // Returns `true` if the attribute contains a value that is not null
+ // or undefined.
+ has: function(attr) {
+ return this.get(attr) != null;
+ },
+
+ // Special-cased proxy to underscore's `_.matches` method.
+ matches: function(attrs) {
+ return !!_.iteratee(attrs, this)(this.attributes);
+ },
+
+ // Set a hash of model attributes on the object, firing `"change"`. This is
+ // the core primitive operation of a model, updating the data and notifying
+ // anyone who needs to know about the change in state. The heart of the beast.
+ set: function(key, val, options) {
+ if (key == null) return this;
+
+ // Handle both `"key", value` and `{key: value}` -style arguments.
+ var attrs;
+ if (typeof key === 'object') {
+ attrs = key;
+ options = val;
+ } else {
+ (attrs = {})[key] = val;
+ }
+
+ options || (options = {});
+
+ // Run validation.
+ if (!this._validate(attrs, options)) return false;
+
+ // Extract attributes and options.
+ var unset = options.unset;
+ var silent = options.silent;
+ var changes = [];
+ var changing = this._changing;
+ this._changing = true;
+
+ if (!changing) {
+ this._previousAttributes = _.clone(this.attributes);
+ this.changed = {};
+ }
+
+ var current = this.attributes;
+ var changed = this.changed;
+ var prev = this._previousAttributes;
+
+ // For each `set` attribute, update or delete the current value.
+ for (var attr in attrs) {
+ val = attrs[attr];
+ if (!_.isEqual(current[attr], val)) changes.push(attr);
+ if (!_.isEqual(prev[attr], val)) {
+ changed[attr] = val;
+ } else {
+ delete changed[attr];
+ }
+ unset ? delete current[attr] : current[attr] = val;
+ }
+
+ // Update the `id`.
+ this.id = this.get(this.idAttribute);
+
+ // Trigger all relevant attribute changes.
+ if (!silent) {
+ if (changes.length) this._pending = options;
+ for (var i = 0; i < changes.length; i++) {
+ this.trigger('change:' + changes[i], this, current[changes[i]], options);
+ }
+ }
+
+ // You might be wondering why there's a `while` loop here. Changes can
+ // be recursively nested within `"change"` events.
+ if (changing) return this;
+ if (!silent) {
+ while (this._pending) {
+ options = this._pending;
+ this._pending = false;
+ this.trigger('change', this, options);
+ }
+ }
+ this._pending = false;
+ this._changing = false;
+ return this;
+ },
+
+ // Remove an attribute from the model, firing `"change"`. `unset` is a noop
+ // if the attribute doesn't exist.
+ unset: function(attr, options) {
+ return this.set(attr, void 0, _.extend({}, options, {unset: true}));
+ },
+
+ // Clear all attributes on the model, firing `"change"`.
+ clear: function(options) {
+ var attrs = {};
+ for (var key in this.attributes) attrs[key] = void 0;
+ return this.set(attrs, _.extend({}, options, {unset: true}));
+ },
+
+ // Determine if the model has changed since the last `"change"` event.
+ // If you specify an attribute name, determine if that attribute has changed.
+ hasChanged: function(attr) {
+ if (attr == null) return !_.isEmpty(this.changed);
+ return _.has(this.changed, attr);
+ },
+
+ // Return an object containing all the attributes that have changed, or
+ // false if there are no changed attributes. Useful for determining what
+ // parts of a view need to be updated and/or what attributes need to be
+ // persisted to the server. Unset attributes will be set to undefined.
+ // You can also pass an attributes object to diff against the model,
+ // determining if there *would be* a change.
+ changedAttributes: function(diff) {
+ if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
+ var old = this._changing ? this._previousAttributes : this.attributes;
+ var changed = {};
+ for (var attr in diff) {
+ var val = diff[attr];
+ if (_.isEqual(old[attr], val)) continue;
+ changed[attr] = val;
+ }
+ return _.size(changed) ? changed : false;
+ },
+
+ // Get the previous value of an attribute, recorded at the time the last
+ // `"change"` event was fired.
+ previous: function(attr) {
+ if (attr == null || !this._previousAttributes) return null;
+ return this._previousAttributes[attr];
+ },
+
+ // Get all of the attributes of the model at the time of the previous
+ // `"change"` event.
+ previousAttributes: function() {
+ return _.clone(this._previousAttributes);
+ },
+
+ // Fetch the model from the server, merging the response with the model's
+ // local attributes. Any changed attributes will trigger a "change" event.
+ fetch: function(options) {
+ options = _.extend({parse: true}, options);
+ var model = this;
+ var success = options.success;
+ options.success = function(resp) {
+ var serverAttrs = options.parse ? model.parse(resp, options) : resp;
+ if (!model.set(serverAttrs, options)) return false;
+ if (success) success.call(options.context, model, resp, options);
+ model.trigger('sync', model, resp, options);
+ };
+ wrapError(this, options);
+ return this.sync('read', this, options);
+ },
+
+ // Set a hash of model attributes, and sync the model to the server.
+ // If the server returns an attributes hash that differs, the model's
+ // state will be `set` again.
+ save: function(key, val, options) {
+ // Handle both `"key", value` and `{key: value}` -style arguments.
+ var attrs;
+ if (key == null || typeof key === 'object') {
+ attrs = key;
+ options = val;
+ } else {
+ (attrs = {})[key] = val;
+ }
+
+ options = _.extend({validate: true, parse: true}, options);
+ var wait = options.wait;
+
+ // If we're not waiting and attributes exist, save acts as
+ // `set(attr).save(null, opts)` with validation. Otherwise, check if
+ // the model will be valid when the attributes, if any, are set.
+ if (attrs && !wait) {
+ if (!this.set(attrs, options)) return false;
+ } else {
+ if (!this._validate(attrs, options)) return false;
+ }
+
+ // After a successful server-side save, the client is (optionally)
+ // updated with the server-side state.
+ var model = this;
+ var success = options.success;
+ var attributes = this.attributes;
+ options.success = function(resp) {
+ // Ensure attributes are restored during synchronous saves.
+ model.attributes = attributes;
+ var serverAttrs = options.parse ? model.parse(resp, options) : resp;
+ if (wait) serverAttrs = _.extend({}, attrs, serverAttrs);
+ if (serverAttrs && !model.set(serverAttrs, options)) return false;
+ if (success) success.call(options.context, model, resp, options);
+ model.trigger('sync', model, resp, options);
+ };
+ wrapError(this, options);
+
+ // Set temporary attributes if `{wait: true}` to properly find new ids.
+ if (attrs && wait) this.attributes = _.extend({}, attributes, attrs);
+
+ var method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
+ if (method === 'patch' && !options.attrs) options.attrs = attrs;
+ var xhr = this.sync(method, this, options);
+
+ // Restore attributes.
+ this.attributes = attributes;
+
+ return xhr;
+ },
+
+ // Destroy this model on the server if it was already persisted.
+ // Optimistically removes the model from its collection, if it has one.
+ // If `wait: true` is passed, waits for the server to respond before removal.
+ destroy: function(options) {
+ options = options ? _.clone(options) : {};
+ var model = this;
+ var success = options.success;
+ var wait = options.wait;
+
+ var destroy = function() {
+ model.stopListening();
+ model.trigger('destroy', model, model.collection, options);
+ };
+
+ options.success = function(resp) {
+ if (wait) destroy();
+ if (success) success.call(options.context, model, resp, options);
+ if (!model.isNew()) model.trigger('sync', model, resp, options);
+ };
+
+ var xhr = false;
+ if (this.isNew()) {
+ _.defer(options.success);
+ } else {
+ wrapError(this, options);
+ xhr = this.sync('delete', this, options);
+ }
+ if (!wait) destroy();
+ return xhr;
+ },
+
+ // Default URL for the model's representation on the server -- if you're
+ // using Backbone's restful methods, override this to change the endpoint
+ // that will be called.
+ url: function() {
+ var base =
+ _.result(this, 'urlRoot') ||
+ _.result(this.collection, 'url') ||
+ urlError();
+ if (this.isNew()) return base;
+ var id = this.get(this.idAttribute);
+ return base.replace(/[^\/]$/, '$&/') + encodeURIComponent(id);
+ },
+
+ // **parse** converts a response into the hash of attributes to be `set` on
+ // the model. The default implementation is just to pass the response along.
+ parse: function(resp, options) {
+ return resp;
+ },
+
+ // Create a new model with identical attributes to this one.
+ clone: function() {
+ return new this.constructor(this.attributes);
+ },
+
+ // A model is new if it has never been saved to the server, and lacks an id.
+ isNew: function() {
+ return !this.has(this.idAttribute);
+ },
+
+ // Check if the model is currently in a valid state.
+ isValid: function(options) {
+ return this._validate({}, _.defaults({validate: true}, options));
+ },
+
+ // Run validation against the next complete set of model attributes,
+ // returning `true` if all is well. Otherwise, fire an `"invalid"` event.
+ _validate: function(attrs, options) {
+ if (!options.validate || !this.validate) return true;
+ attrs = _.extend({}, this.attributes, attrs);
+ var error = this.validationError = this.validate(attrs, options) || null;
+ if (!error) return true;
+ this.trigger('invalid', this, error, _.extend(options, {validationError: error}));
+ return false;
+ }
+
+ });
+
+ // Underscore methods that we want to implement on the Model, mapped to the
+ // number of arguments they take.
+ var modelMethods = { keys: 1, values: 1, pairs: 1, invert: 1, pick: 0,
+ omit: 0, chain: 1, isEmpty: 1 };
+
+ // Mix in each Underscore method as a proxy to `Model#attributes`.
+ addUnderscoreMethods(Model, modelMethods, 'attributes');
+
+ // Backbone.Collection
+ // -------------------
+
+ // If models tend to represent a single row of data, a Backbone Collection is
+ // more analogous to a table full of data ... or a small slice or page of that
+ // table, or a collection of rows that belong together for a particular reason
+ // -- all of the messages in this particular folder, all of the documents
+ // belonging to this particular author, and so on. Collections maintain
+ // indexes of their models, both in order, and for lookup by `id`.
+
+ // Create a new **Collection**, perhaps to contain a specific type of `model`.
+ // If a `comparator` is specified, the Collection will maintain
+ // its models in sort order, as they're added and removed.
+ var Collection = Backbone.Collection = function(models, options) {
+ options || (options = {});
+ if (options.model) this.model = options.model;
+ if (options.comparator !== void 0) this.comparator = options.comparator;
+ this._reset();
+ this.initialize.apply(this, arguments);
+ if (models) this.reset(models, _.extend({silent: true}, options));
+ };
+
+ // Default options for `Collection#set`.
+ var setOptions = {add: true, remove: true, merge: true};
+ var addOptions = {add: true, remove: false};
+
+ // Splices `insert` into `array` at index `at`.
+ var splice = function(array, insert, at) {
+ var tail = Array(array.length - at);
+ var length = insert.length;
+ for (var i = 0; i < tail.length; i++) tail[i] = array[i + at];
+ for (i = 0; i < length; i++) array[i + at] = insert[i];
+ for (i = 0; i < tail.length; i++) array[i + length + at] = tail[i];
+ };
+
+ // Define the Collection's inheritable methods.
+ _.extend(Collection.prototype, Events, {
+
+ // The default model for a collection is just a **Backbone.Model**.
+ // This should be overridden in most cases.
+ model: Model,
+
+ // Initialize is an empty function by default. Override it with your own
+ // initialization logic.
+ initialize: function(){},
+
+ // The JSON representation of a Collection is an array of the
+ // models' attributes.
+ toJSON: function(options) {
+ return this.map(function(model) { return model.toJSON(options); });
+ },
+
+ // Proxy `Backbone.sync` by default.
+ sync: function() {
+ return Backbone.sync.apply(this, arguments);
+ },
+
+ // Add a model, or list of models to the set. `models` may be Backbone
+ // Models or raw JavaScript objects to be converted to Models, or any
+ // combination of the two.
+ add: function(models, options) {
+ return this.set(models, _.extend({merge: false}, options, addOptions));
+ },
+
+ // Remove a model, or a list of models from the set.
+ remove: function(models, options) {
+ options = _.extend({}, options);
+ var singular = !_.isArray(models);
+ models = singular ? [models] : _.clone(models);
+ var removed = this._removeModels(models, options);
+ if (!options.silent && removed) this.trigger('update', this, options);
+ return singular ? removed[0] : removed;
+ },
+
+ // Update a collection by `set`-ing a new list of models, adding new ones,
+ // removing models that are no longer present, and merging models that
+ // already exist in the collection, as necessary. Similar to **Model#set**,
+ // the core operation for updating the data contained by the collection.
+ set: function(models, options) {
+ if (models == null) return;
+
+ options = _.defaults({}, options, setOptions);
+ if (options.parse && !this._isModel(models)) models = this.parse(models, options);
+
+ var singular = !_.isArray(models);
+ models = singular ? [models] : models.slice();
+
+ var at = options.at;
+ if (at != null) at = +at;
+ if (at < 0) at += this.length + 1;
+
+ var set = [];
+ var toAdd = [];
+ var toRemove = [];
+ var modelMap = {};
+
+ var add = options.add;
+ var merge = options.merge;
+ var remove = options.remove;
+
+ var sort = false;
+ var sortable = this.comparator && (at == null) && options.sort !== false;
+ var sortAttr = _.isString(this.comparator) ? this.comparator : null;
+
+ // Turn bare objects into model references, and prevent invalid models
+ // from being added.
+ var model;
+ for (var i = 0; i < models.length; i++) {
+ model = models[i];
+
+ // If a duplicate is found, prevent it from being added and
+ // optionally merge it into the existing model.
+ var existing = this.get(model);
+ if (existing) {
+ if (merge && model !== existing) {
+ var attrs = this._isModel(model) ? model.attributes : model;
+ if (options.parse) attrs = existing.parse(attrs, options);
+ existing.set(attrs, options);
+ if (sortable && !sort) sort = existing.hasChanged(sortAttr);
+ }
+ if (!modelMap[existing.cid]) {
+ modelMap[existing.cid] = true;
+ set.push(existing);
+ }
+ models[i] = existing;
+
+ // If this is a new, valid model, push it to the `toAdd` list.
+ } else if (add) {
+ model = models[i] = this._prepareModel(model, options);
+ if (model) {
+ toAdd.push(model);
+ this._addReference(model, options);
+ modelMap[model.cid] = true;
+ set.push(model);
+ }
+ }
+ }
+
+ // Remove stale models.
+ if (remove) {
+ for (i = 0; i < this.length; i++) {
+ model = this.models[i];
+ if (!modelMap[model.cid]) toRemove.push(model);
+ }
+ if (toRemove.length) this._removeModels(toRemove, options);
+ }
+
+ // See if sorting is needed, update `length` and splice in new models.
+ var orderChanged = false;
+ var replace = !sortable && add && remove;
+ if (set.length && replace) {
+ orderChanged = this.length != set.length || _.some(this.models, function(model, index) {
+ return model !== set[index];
+ });
+ this.models.length = 0;
+ splice(this.models, set, 0);
+ this.length = this.models.length;
+ } else if (toAdd.length) {
+ if (sortable) sort = true;
+ splice(this.models, toAdd, at == null ? this.length : at);
+ this.length = this.models.length;
+ }
+
+ // Silently sort the collection if appropriate.
+ if (sort) this.sort({silent: true});
+
+ // Unless silenced, it's time to fire all appropriate add/sort events.
+ if (!options.silent) {
+ for (i = 0; i < toAdd.length; i++) {
+ if (at != null) options.index = at + i;
+ model = toAdd[i];
+ model.trigger('add', model, this, options);
+ }
+ if (sort || orderChanged) this.trigger('sort', this, options);
+ if (toAdd.length || toRemove.length) this.trigger('update', this, options);
+ }
+
+ // Return the added (or merged) model (or models).
+ return singular ? models[0] : models;
+ },
+
+ // When you have more items than you want to add or remove individually,
+ // you can reset the entire set with a new list of models, without firing
+ // any granular `add` or `remove` events. Fires `reset` when finished.
+ // Useful for bulk operations and optimizations.
+ reset: function(models, options) {
+ options = options ? _.clone(options) : {};
+ for (var i = 0; i < this.models.length; i++) {
+ this._removeReference(this.models[i], options);
+ }
+ options.previousModels = this.models;
+ this._reset();
+ models = this.add(models, _.extend({silent: true}, options));
+ if (!options.silent) this.trigger('reset', this, options);
+ return models;
+ },
+
+ // Add a model to the end of the collection.
+ push: function(model, options) {
+ return this.add(model, _.extend({at: this.length}, options));
+ },
+
+ // Remove a model from the end of the collection.
+ pop: function(options) {
+ var model = this.at(this.length - 1);
+ return this.remove(model, options);
+ },
+
+ // Add a model to the beginning of the collection.
+ unshift: function(model, options) {
+ return this.add(model, _.extend({at: 0}, options));
+ },
+
+ // Remove a model from the beginning of the collection.
+ shift: function(options) {
+ var model = this.at(0);
+ return this.remove(model, options);
+ },
+
+ // Slice out a sub-array of models from the collection.
+ slice: function() {
+ return slice.apply(this.models, arguments);
+ },
+
+ // Get a model from the set by id.
+ get: function(obj) {
+ if (obj == null) return void 0;
+ var id = this.modelId(this._isModel(obj) ? obj.attributes : obj);
+ return this._byId[obj] || this._byId[id] || this._byId[obj.cid];
+ },
+
+ // Get the model at the given index.
+ at: function(index) {
+ if (index < 0) index += this.length;
+ return this.models[index];
+ },
+
+ // Return models with matching attributes. Useful for simple cases of
+ // `filter`.
+ where: function(attrs, first) {
+ return this[first ? 'find' : 'filter'](attrs);
+ },
+
+ // Return the first model with matching attributes. Useful for simple cases
+ // of `find`.
+ findWhere: function(attrs) {
+ return this.where(attrs, true);
+ },
+
+ // Force the collection to re-sort itself. You don't need to call this under
+ // normal circumstances, as the set will maintain sort order as each item
+ // is added.
+ sort: function(options) {
+ var comparator = this.comparator;
+ if (!comparator) throw new Error('Cannot sort a set without a comparator');
+ options || (options = {});
+
+ var length = comparator.length;
+ if (_.isFunction(comparator)) comparator = _.bind(comparator, this);
+
+ // Run sort based on type of `comparator`.
+ if (length === 1 || _.isString(comparator)) {
+ this.models = this.sortBy(comparator);
+ } else {
+ this.models.sort(comparator);
+ }
+ if (!options.silent) this.trigger('sort', this, options);
+ return this;
+ },
+
+ // Pluck an attribute from each model in the collection.
+ pluck: function(attr) {
+ return _.invoke(this.models, 'get', attr);
+ },
+
+ // Fetch the default set of models for this collection, resetting the
+ // collection when they arrive. If `reset: true` is passed, the response
+ // data will be passed through the `reset` method instead of `set`.
+ fetch: function(options) {
+ options = _.extend({parse: true}, options);
+ var success = options.success;
+ var collection = this;
+ options.success = function(resp) {
+ var method = options.reset ? 'reset' : 'set';
+ collection[method](resp, options);
+ if (success) success.call(options.context, collection, resp, options);
+ collection.trigger('sync', collection, resp, options);
+ };
+ wrapError(this, options);
+ return this.sync('read', this, options);
+ },
+
+ // Create a new instance of a model in this collection. Add the model to the
+ // collection immediately, unless `wait: true` is passed, in which case we
+ // wait for the server to agree.
+ create: function(model, options) {
+ options = options ? _.clone(options) : {};
+ var wait = options.wait;
+ model = this._prepareModel(model, options);
+ if (!model) return false;
+ if (!wait) this.add(model, options);
+ var collection = this;
+ var success = options.success;
+ options.success = function(model, resp, callbackOpts) {
+ if (wait) collection.add(model, callbackOpts);
+ if (success) success.call(callbackOpts.context, model, resp, callbackOpts);
+ };
+ model.save(null, options);
+ return model;
+ },
+
+ // **parse** converts a response into a list of models to be added to the
+ // collection. The default implementation is just to pass it through.
+ parse: function(resp, options) {
+ return resp;
+ },
+
+ // Create a new collection with an identical list of models as this one.
+ clone: function() {
+ return new this.constructor(this.models, {
+ model: this.model,
+ comparator: this.comparator
+ });
+ },
+
+ // Define how to uniquely identify models in the collection.
+ modelId: function (attrs) {
+ return attrs[this.model.prototype.idAttribute || 'id'];
+ },
+
+ // Private method to reset all internal state. Called when the collection
+ // is first initialized or reset.
+ _reset: function() {
+ this.length = 0;
+ this.models = [];
+ this._byId = {};
+ },
+
+ // Prepare a hash of attributes (or other model) to be added to this
+ // collection.
+ _prepareModel: function(attrs, options) {
+ if (this._isModel(attrs)) {
+ if (!attrs.collection) attrs.collection = this;
+ return attrs;
+ }
+ options = options ? _.clone(options) : {};
+ options.collection = this;
+ var model = new this.model(attrs, options);
+ if (!model.validationError) return model;
+ this.trigger('invalid', this, model.validationError, options);
+ return false;
+ },
+
+ // Internal method called by both remove and set.
+ _removeModels: function(models, options) {
+ var removed = [];
+ for (var i = 0; i < models.length; i++) {
+ var model = this.get(models[i]);
+ if (!model) continue;
+
+ var index = this.indexOf(model);
+ this.models.splice(index, 1);
+ this.length--;
+
+ if (!options.silent) {
+ options.index = index;
+ model.trigger('remove', model, this, options);
+ }
+
+ removed.push(model);
+ this._removeReference(model, options);
+ }
+ return removed.length ? removed : false;
+ },
+
+ // Method for checking whether an object should be considered a model for
+ // the purposes of adding to the collection.
+ _isModel: function (model) {
+ return model instanceof Model;
+ },
+
+ // Internal method to create a model's ties to a collection.
+ _addReference: function(model, options) {
+ this._byId[model.cid] = model;
+ var id = this.modelId(model.attributes);
+ if (id != null) this._byId[id] = model;
+ model.on('all', this._onModelEvent, this);
+ },
+
+ // Internal method to sever a model's ties to a collection.
+ _removeReference: function(model, options) {
+ delete this._byId[model.cid];
+ var id = this.modelId(model.attributes);
+ if (id != null) delete this._byId[id];
+ if (this === model.collection) delete model.collection;
+ model.off('all', this._onModelEvent, this);
+ },
+
+ // Internal method called every time a model in the set fires an event.
+ // Sets need to update their indexes when models change ids. All other
+ // events simply proxy through. "add" and "remove" events that originate
+ // in other collections are ignored.
+ _onModelEvent: function(event, model, collection, options) {
+ if ((event === 'add' || event === 'remove') && collection !== this) return;
+ if (event === 'destroy') this.remove(model, options);
+ if (event === 'change') {
+ var prevId = this.modelId(model.previousAttributes());
+ var id = this.modelId(model.attributes);
+ if (prevId !== id) {
+ if (prevId != null) delete this._byId[prevId];
+ if (id != null) this._byId[id] = model;
+ }
+ }
+ this.trigger.apply(this, arguments);
+ }
+
+ });
+
+ // Underscore methods that we want to implement on the Collection.
+ // 90% of the core usefulness of Backbone Collections is actually implemented
+ // right here:
+ var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 4,
+ foldl: 4, inject: 4, reduceRight: 4, foldr: 4, find: 3, detect: 3, filter: 3,
+ select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 3, includes: 3,
+ contains: 3, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3,
+ head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3,
+ without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3,
+ isEmpty: 1, chain: 1, sample: 3, partition: 3, groupBy: 3, countBy: 3,
+ sortBy: 3, indexBy: 3};
+
+ // Mix in each Underscore method as a proxy to `Collection#models`.
+ addUnderscoreMethods(Collection, collectionMethods, 'models');
+
+ // Backbone.View
+ // -------------
+
+ // Backbone Views are almost more convention than they are actual code. A View
+ // is simply a JavaScript object that represents a logical chunk of UI in the
+ // DOM. This might be a single item, an entire list, a sidebar or panel, or
+ // even the surrounding frame which wraps your whole app. Defining a chunk of
+ // UI as a **View** allows you to define your DOM events declaratively, without
+ // having to worry about render order ... and makes it easy for the view to
+ // react to specific changes in the state of your models.
+
+ // Creating a Backbone.View creates its initial element outside of the DOM,
+ // if an existing element is not provided...
+ var View = Backbone.View = function(options) {
+ this.cid = _.uniqueId('view');
+ _.extend(this, _.pick(options, viewOptions));
+ this._ensureElement();
+ this.initialize.apply(this, arguments);
+ };
+
+ // Cached regex to split keys for `delegate`.
+ var delegateEventSplitter = /^(\S+)\s*(.*)$/;
+
+ // List of view options to be set as properties.
+ var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];
+
+ // Set up all inheritable **Backbone.View** properties and methods.
+ _.extend(View.prototype, Events, {
+
+ // The default `tagName` of a View's element is `"div"`.
+ tagName: 'div',
+
+ // jQuery delegate for element lookup, scoped to DOM elements within the
+ // current view. This should be preferred to global lookups where possible.
+ $: function(selector) {
+ return this.$el.find(selector);
+ },
+
+ // Initialize is an empty function by default. Override it with your own
+ // initialization logic.
+ initialize: function(){},
+
+ // **render** is the core function that your view should override, in order
+ // to populate its element (`this.el`), with the appropriate HTML. The
+ // convention is for **render** to always return `this`.
+ render: function() {
+ return this;
+ },
+
+ // Remove this view by taking the element out of the DOM, and removing any
+ // applicable Backbone.Events listeners.
+ remove: function() {
+ this._removeElement();
+ this.stopListening();
+ return this;
+ },
+
+ // Remove this view's element from the document and all event listeners
+ // attached to it. Exposed for subclasses using an alternative DOM
+ // manipulation API.
+ _removeElement: function() {
+ this.$el.remove();
+ },
+
+ // Change the view's element (`this.el` property) and re-delegate the
+ // view's events on the new element.
+ setElement: function(element) {
+ this.undelegateEvents();
+ this._setElement(element);
+ this.delegateEvents();
+ return this;
+ },
+
+ // Creates the `this.el` and `this.$el` references for this view using the
+ // given `el`. `el` can be a CSS selector or an HTML string, a jQuery
+ // context or an element. Subclasses can override this to utilize an
+ // alternative DOM manipulation API and are only required to set the
+ // `this.el` property.
+ _setElement: function(el) {
+ this.$el = el instanceof Backbone.$ ? el : Backbone.$(el);
+ this.el = this.$el[0];
+ },
+
+ // Set callbacks, where `this.events` is a hash of
+ //
+ // *{"event selector": "callback"}*
+ //
+ // {
+ // 'mousedown .title': 'edit',
+ // 'click .button': 'save',
+ // 'click .open': function(e) { ... }
+ // }
+ //
+ // pairs. Callbacks will be bound to the view, with `this` set properly.
+ // Uses event delegation for efficiency.
+ // Omitting the selector binds the event to `this.el`.
+ delegateEvents: function(events) {
+ events || (events = _.result(this, 'events'));
+ if (!events) return this;
+ this.undelegateEvents();
+ for (var key in events) {
+ var method = events[key];
+ if (!_.isFunction(method)) method = this[method];
+ if (!method) continue;
+ var match = key.match(delegateEventSplitter);
+ this.delegate(match[1], match[2], _.bind(method, this));
+ }
+ return this;
+ },
+
+ // Add a single event listener to the view's element (or a child element
+ // using `selector`). This only works for delegate-able events: not `focus`,
+ // `blur`, and not `change`, `submit`, and `reset` in Internet Explorer.
+ delegate: function(eventName, selector, listener) {
+ this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener);
+ return this;
+ },
+
+ // Clears all callbacks previously bound to the view by `delegateEvents`.
+ // You usually don't need to use this, but may wish to if you have multiple
+ // Backbone views attached to the same DOM element.
+ undelegateEvents: function() {
+ if (this.$el) this.$el.off('.delegateEvents' + this.cid);
+ return this;
+ },
+
+ // A finer-grained `undelegateEvents` for removing a single delegated event.
+ // `selector` and `listener` are both optional.
+ undelegate: function(eventName, selector, listener) {
+ this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener);
+ return this;
+ },
+
+ // Produces a DOM element to be assigned to your view. Exposed for
+ // subclasses using an alternative DOM manipulation API.
+ _createElement: function(tagName) {
+ return document.createElement(tagName);
+ },
+
+ // Ensure that the View has a DOM element to render into.
+ // If `this.el` is a string, pass it through `$()`, take the first
+ // matching element, and re-assign it to `el`. Otherwise, create
+ // an element from the `id`, `className` and `tagName` properties.
+ _ensureElement: function() {
+ if (!this.el) {
+ var attrs = _.extend({}, _.result(this, 'attributes'));
+ if (this.id) attrs.id = _.result(this, 'id');
+ if (this.className) attrs['class'] = _.result(this, 'className');
+ this.setElement(this._createElement(_.result(this, 'tagName')));
+ this._setAttributes(attrs);
+ } else {
+ this.setElement(_.result(this, 'el'));
+ }
+ },
+
+ // Set attributes from a hash on this view's element. Exposed for
+ // subclasses using an alternative DOM manipulation API.
+ _setAttributes: function(attributes) {
+ this.$el.attr(attributes);
+ }
+
+ });
+
+ // Backbone.sync
+ // -------------
+
+ // Override this function to change the manner in which Backbone persists
+ // models to the server. You will be passed the type of request, and the
+ // model in question. By default, makes a RESTful Ajax request
+ // to the model's `url()`. Some possible customizations could be:
+ //
+ // * Use `setTimeout` to batch rapid-fire updates into a single request.
+ // * Send up the models as XML instead of JSON.
+ // * Persist models via WebSockets instead of Ajax.
+ //
+ // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests
+ // as `POST`, with a `_method` parameter containing the true HTTP method,
+ // as well as all requests with the body as `application/x-www-form-urlencoded`
+ // instead of `application/json` with the model in a param named `model`.
+ // Useful when interfacing with server-side languages like **PHP** that make
+ // it difficult to read the body of `PUT` requests.
+ Backbone.sync = function(method, model, options) {
+ var type = methodMap[method];
+
+ // Default options, unless specified.
+ _.defaults(options || (options = {}), {
+ emulateHTTP: Backbone.emulateHTTP,
+ emulateJSON: Backbone.emulateJSON
+ });
+
+ // Default JSON-request options.
+ var params = {type: type, dataType: 'json'};
+
+ // Ensure that we have a URL.
+ if (!options.url) {
+ params.url = _.result(model, 'url') || urlError();
+ }
+
+ // Ensure that we have the appropriate request data.
+ if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
+ params.contentType = 'application/json';
+ params.data = JSON.stringify(options.attrs || model.toJSON(options));
+ }
+
+ // For older servers, emulate JSON by encoding the request into an HTML-form.
+ if (options.emulateJSON) {
+ params.contentType = 'application/x-www-form-urlencoded';
+ params.data = params.data ? {model: params.data} : {};
+ }
+
+ // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
+ // And an `X-HTTP-Method-Override` header.
+ if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
+ params.type = 'POST';
+ if (options.emulateJSON) params.data._method = type;
+ var beforeSend = options.beforeSend;
+ options.beforeSend = function(xhr) {
+ xhr.setRequestHeader('X-HTTP-Method-Override', type);
+ if (beforeSend) return beforeSend.apply(this, arguments);
+ };
+ }
+
+ // Don't process data on a non-GET request.
+ if (params.type !== 'GET' && !options.emulateJSON) {
+ params.processData = false;
+ }
+
+ // Pass along `textStatus` and `errorThrown` from jQuery.
+ var error = options.error;
+ options.error = function(xhr, textStatus, errorThrown) {
+ options.textStatus = textStatus;
+ options.errorThrown = errorThrown;
+ if (error) error.call(options.context, xhr, textStatus, errorThrown);
+ };
+
+ // Make the request, allowing the user to override any Ajax options.
+ var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
+ model.trigger('request', model, xhr, options);
+ return xhr;
+ };
+
+ // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
+ var methodMap = {
+ 'create': 'POST',
+ 'update': 'PUT',
+ 'patch': 'PATCH',
+ "sendDelete": 'DELETE',
+ 'read': 'GET'
+ };
+
+ // Set the default implementation of `Backbone.ajax` to proxy through to `$`.
+ // Override this if you'd like to use a different library.
+ Backbone.ajax = function() {
+ return Backbone.$.ajax.apply(Backbone.$, arguments);
+ };
+
+ // Backbone.Router
+ // ---------------
+
+ // Routers map faux-URLs to actions, and fire events when routes are
+ // matched. Creating a new one sets its `routes` hash, if not set statically.
+ var Router = Backbone.Router = function(options) {
+ options || (options = {});
+ if (options.routes) this.routes = options.routes;
+ this._bindRoutes();
+ this.initialize.apply(this, arguments);
+ };
+
+ // Cached regular expressions for matching named param parts and splatted
+ // parts of route strings.
+ var optionalParam = /\((.*?)\)/g;
+ var namedParam = /(\(\?)?:\w+/g;
+ var splatParam = /\*\w+/g;
+ var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
+
+ // Set up all inheritable **Backbone.Router** properties and methods.
+ _.extend(Router.prototype, Events, {
+
+ // Initialize is an empty function by default. Override it with your own
+ // initialization logic.
+ initialize: function(){},
+
+ // Manually bind a single named route to a callback. For example:
+ //
+ // this.route('search/:query/p:num', 'search', function(query, num) {
+ // ...
+ // });
+ //
+ route: function(route, name, callback) {
+ if (!_.isRegExp(route)) route = this._routeToRegExp(route);
+ if (_.isFunction(name)) {
+ callback = name;
+ name = '';
+ }
+ if (!callback) callback = this[name];
+ var router = this;
+ Backbone.history.route(route, function(fragment) {
+ var args = router._extractParameters(route, fragment);
+ if (router.execute(callback, args, name) !== false) {
+ router.trigger.apply(router, ['route:' + name].concat(args));
+ router.trigger('route', name, args);
+ Backbone.history.trigger('route', router, name, args);
+ }
+ });
+ return this;
+ },
+
+ // Execute a route handler with the provided parameters. This is an
+ // excellent place to do pre-route setup or post-route cleanup.
+ execute: function(callback, args, name) {
+ if (callback) callback.apply(this, args);
+ },
+
+ // Simple proxy to `Backbone.history` to save a fragment into the history.
+ navigate: function(fragment, options) {
+ Backbone.history.navigate(fragment, options);
+ return this;
+ },
+
+ // Bind all defined routes to `Backbone.history`. We have to reverse the
+ // order of the routes here to support behavior where the most general
+ // routes can be defined at the bottom of the route map.
+ _bindRoutes: function() {
+ if (!this.routes) return;
+ this.routes = _.result(this, 'routes');
+ var route, routes = _.keys(this.routes);
+ while ((route = routes.pop()) != null) {
+ this.route(route, this.routes[route]);
+ }
+ },
+
+ // Convert a route string into a regular expression, suitable for matching
+ // against the current location hash.
+ _routeToRegExp: function(route) {
+ route = route.replace(escapeRegExp, '\\$&')
+ .replace(optionalParam, '(?:$1)?')
+ .replace(namedParam, function(match, optional) {
+ return optional ? match : '([^/?]+)';
+ })
+ .replace(splatParam, '([^?]*?)');
+ return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
+ },
+
+ // Given a route, and a URL fragment that it matches, return the array of
+ // extracted decoded parameters. Empty or unmatched parameters will be
+ // treated as `null` to normalize cross-browser behavior.
+ _extractParameters: function(route, fragment) {
+ var params = route.exec(fragment).slice(1);
+ return _.map(params, function(param, i) {
+ // Don't decode the search params.
+ if (i === params.length - 1) return param || null;
+ return param ? decodeURIComponent(param) : null;
+ });
+ }
+
+ });
+
+ // Backbone.History
+ // ----------------
+
+ // Handles cross-browser history management, based on either
+ // [pushState](http://diveintohtml5.info/history.html) and real URLs, or
+ // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange)
+ // and URL fragments. If the browser supports neither (old IE, natch),
+ // falls back to polling.
+ var History = Backbone.History = function() {
+ this.handlers = [];
+ this.checkUrl = _.bind(this.checkUrl, this);
+
+ // Ensure that `History` can be used outside of the browser.
+ if (typeof window !== 'undefined') {
+ this.location = window.location;
+ this.history = window.history;
+ }
+ };
+
+ // Cached regex for stripping a leading hash/slash and trailing space.
+ var routeStripper = /^[#\/]|\s+$/g;
+
+ // Cached regex for stripping leading and trailing slashes.
+ var rootStripper = /^\/+|\/+$/g;
+
+ // Cached regex for stripping urls of hash.
+ var pathStripper = /#.*$/;
+
+ // Has the history handling already been started?
+ History.started = false;
+
+ // Set up all inheritable **Backbone.History** properties and methods.
+ _.extend(History.prototype, Events, {
+
+ // The default interval to poll for hash changes, if necessary, is
+ // twenty times a second.
+ interval: 50,
+
+ // Are we at the app root?
+ atRoot: function() {
+ var path = this.location.pathname.replace(/[^\/]$/, '$&/');
+ return path === this.root && !this.getSearch();
+ },
+
+ // Does the pathname match the root?
+ matchRoot: function() {
+ var path = this.decodeFragment(this.location.pathname);
+ var root = path.slice(0, this.root.length - 1) + '/';
+ return root === this.root;
+ },
+
+ // Unicode characters in `location.pathname` are percent encoded so they're
+ // decoded for comparison. `%25` should not be decoded since it may be part
+ // of an encoded parameter.
+ decodeFragment: function(fragment) {
+ return decodeURI(fragment.replace(/%25/g, '%2525'));
+ },
+
+ // In IE6, the hash fragment and search params are incorrect if the
+ // fragment contains `?`.
+ getSearch: function() {
+ var match = this.location.href.replace(/#.*/, '').match(/\?.+/);
+ return match ? match[0] : '';
+ },
+
+ // Gets the true hash value. Cannot use location.hash directly due to bug
+ // in Firefox where location.hash will always be decoded.
+ getHash: function(window) {
+ var match = (window || this).location.href.match(/#(.*)$/);
+ return match ? match[1] : '';
+ },
+
+ // Get the pathname and search params, without the root.
+ getPath: function() {
+ var path = this.decodeFragment(
+ this.location.pathname + this.getSearch()
+ ).slice(this.root.length - 1);
+ return path.charAt(0) === '/' ? path.slice(1) : path;
+ },
+
+ // Get the cross-browser normalized URL fragment from the path or hash.
+ getFragment: function(fragment) {
+ if (fragment == null) {
+ if (this._usePushState || !this._wantsHashChange) {
+ fragment = this.getPath();
+ } else {
+ fragment = this.getHash();
+ }
+ }
+ return fragment.replace(routeStripper, '');
+ },
+
+ // Start the hash change handling, returning `true` if the current URL matches
+ // an existing route, and `false` otherwise.
+ start: function(options) {
+ if (History.started) throw new Error('Backbone.history has already been started');
+ History.started = true;
+
+ // Figure out the initial configuration. Do we need an iframe?
+ // Is pushState desired ... is it available?
+ this.options = _.extend({root: '/'}, this.options, options);
+ this.root = this.options.root;
+ this._wantsHashChange = this.options.hashChange !== false;
+ this._hasHashChange = 'onhashchange' in window && (document.documentMode === void 0 || document.documentMode > 7);
+ this._useHashChange = this._wantsHashChange && this._hasHashChange;
+ this._wantsPushState = !!this.options.pushState;
+ this._hasPushState = !!(this.history && this.history.pushState);
+ this._usePushState = this._wantsPushState && this._hasPushState;
+ this.fragment = this.getFragment();
+
+ // Normalize root to always include a leading and trailing slash.
+ this.root = ('/' + this.root + '/').replace(rootStripper, '/');
+
+ // Transition from hashChange to pushState or vice versa if both are
+ // requested.
+ if (this._wantsHashChange && this._wantsPushState) {
+
+ // If we've started off with a route from a `pushState`-enabled
+ // browser, but we're currently in a browser that doesn't support it...
+ if (!this._hasPushState && !this.atRoot()) {
+ var root = this.root.slice(0, -1) || '/';
+ this.location.replace(root + '#' + this.getPath());
+ // Return immediately as browser will do redirect to new url
+ return true;
+
+ // Or if we've started out with a hash-based route, but we're currently
+ // in a browser where it could be `pushState`-based instead...
+ } else if (this._hasPushState && this.atRoot()) {
+ this.navigate(this.getHash(), {replace: true});
+ }
+
+ }
+
+ // Proxy an iframe to handle location events if the browser doesn't
+ // support the `hashchange` event, HTML5 history, or the user wants
+ // `hashChange` but not `pushState`.
+ if (!this._hasHashChange && this._wantsHashChange && !this._usePushState) {
+ this.iframe = document.createElement('iframe');
+ this.iframe.src = 'javascript:0';
+ this.iframe.style.display = 'none';
+ this.iframe.tabIndex = -1;
+ var body = document.body;
+ // Using `appendChild` will throw on IE < 9 if the document is not ready.
+ var iWindow = body.insertBefore(this.iframe, body.firstChild).contentWindow;
+ iWindow.document.open();
+ iWindow.document.close();
+ iWindow.location.hash = '#' + this.fragment;
+ }
+
+ // Add a cross-platform `addEventListener` shim for older browsers.
+ var addEventListener = window.addEventListener || function (eventName, listener) {
+ return attachEvent('on' + eventName, listener);
+ };
+
+ // Depending on whether we're using pushState or hashes, and whether
+ // 'onhashchange' is supported, determine how we check the URL state.
+ if (this._usePushState) {
+ addEventListener('popstate', this.checkUrl, false);
+ } else if (this._useHashChange && !this.iframe) {
+ addEventListener('hashchange', this.checkUrl, false);
+ } else if (this._wantsHashChange) {
+ this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
+ }
+
+ if (!this.options.silent) return this.loadUrl();
+ },
+
+ // Disable Backbone.history, perhaps temporarily. Not useful in a real app,
+ // but possibly useful for unit testing Routers.
+ stop: function() {
+ // Add a cross-platform `removeEventListener` shim for older browsers.
+ var removeEventListener = window.removeEventListener || function (eventName, listener) {
+ return detachEvent('on' + eventName, listener);
+ };
+
+ // Remove window listeners.
+ if (this._usePushState) {
+ removeEventListener('popstate', this.checkUrl, false);
+ } else if (this._useHashChange && !this.iframe) {
+ removeEventListener('hashchange', this.checkUrl, false);
+ }
+
+ // Clean up the iframe if necessary.
+ if (this.iframe) {
+ document.body.removeChild(this.iframe);
+ this.iframe = null;
+ }
+
+ // Some environments will throw when clearing an undefined interval.
+ if (this._checkUrlInterval) clearInterval(this._checkUrlInterval);
+ History.started = false;
+ },
+
+ // Add a route to be tested when the fragment changes. Routes added later
+ // may override previous routes.
+ route: function(route, callback) {
+ this.handlers.unshift({route: route, callback: callback});
+ },
+
+ // Checks the current URL to see if it has changed, and if it has,
+ // calls `loadUrl`, normalizing across the hidden iframe.
+ checkUrl: function(e) {
+ var current = this.getFragment();
+
+ // If the user pressed the back button, the iframe's hash will have
+ // changed and we should use that for comparison.
+ if (current === this.fragment && this.iframe) {
+ current = this.getHash(this.iframe.contentWindow);
+ }
+
+ if (current === this.fragment) return false;
+ if (this.iframe) this.navigate(current);
+ this.loadUrl();
+ },
+
+ // Attempt to load the current URL fragment. If a route succeeds with a
+ // match, returns `true`. If no defined routes matches the fragment,
+ // returns `false`.
+ loadUrl: function(fragment) {
+ // If the root doesn't match, no routes can match either.
+ if (!this.matchRoot()) return false;
+ fragment = this.fragment = this.getFragment(fragment);
+ return _.some(this.handlers, function(handler) {
+ if (handler.route.test(fragment)) {
+ handler.callback(fragment);
+ return true;
+ }
+ });
+ },
+
+ // Save a fragment into the hash history, or replace the URL state if the
+ // 'replace' option is passed. You are responsible for properly URL-encoding
+ // the fragment in advance.
+ //
+ // The options object can contain `trigger: true` if you wish to have the
+ // route callback be fired (not usually desirable), or `replace: true`, if
+ // you wish to modify the current URL without adding an entry to the history.
+ navigate: function(fragment, options) {
+ if (!History.started) return false;
+ if (!options || options === true) options = {trigger: !!options};
+
+ // Normalize the fragment.
+ fragment = this.getFragment(fragment || '');
+
+ // Don't include a trailing slash on the root.
+ var root = this.root;
+ if (fragment === '' || fragment.charAt(0) === '?') {
+ root = root.slice(0, -1) || '/';
+ }
+ var url = root + fragment;
+
+ // Strip the hash and decode for matching.
+ fragment = this.decodeFragment(fragment.replace(pathStripper, ''));
+
+ if (this.fragment === fragment) return;
+ this.fragment = fragment;
+
+ // If pushState is available, we use it to set the fragment as a real URL.
+ if (this._usePushState) {
+ this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url);
+
+ // If hash changes haven't been explicitly disabled, update the hash
+ // fragment to store history.
+ } else if (this._wantsHashChange) {
+ this._updateHash(this.location, fragment, options.replace);
+ if (this.iframe && (fragment !== this.getHash(this.iframe.contentWindow))) {
+ var iWindow = this.iframe.contentWindow;
+
+ // Opening and closing the iframe tricks IE7 and earlier to push a
+ // history entry on hash-tag change. When replace is true, we don't
+ // want this.
+ if (!options.replace) {
+ iWindow.document.open();
+ iWindow.document.close();
+ }
+
+ this._updateHash(iWindow.location, fragment, options.replace);
+ }
+
+ // If you've told us that you explicitly don't want fallback hashchange-
+ // based history, then `navigate` becomes a page refresh.
+ } else {
+ return this.location.assign(url);
+ }
+ if (options.trigger) return this.loadUrl(fragment);
+ },
+
+ // Update the hash location, either replacing the current entry, or adding
+ // a new one to the browser history.
+ _updateHash: function(location, fragment, replace) {
+ if (replace) {
+ var href = location.href.replace(/(javascript:|#).*$/, '');
+ location.replace(href + '#' + fragment);
+ } else {
+ // Some browsers require that `hash` contains a leading #.
+ location.hash = '#' + fragment;
+ }
+ }
+
+ });
+
+ // Create the default Backbone.history.
+ Backbone.history = new History;
+
+ // Helpers
+ // -------
+
+ // Helper function to correctly set up the prototype chain for subclasses.
+ // Similar to `goog.inherits`, but uses a hash of prototype properties and
+ // class properties to be extended.
+ var extend = function(protoProps, staticProps) {
+ var parent = this;
+ var child;
+
+ // The constructor function for the new subclass is either defined by you
+ // (the "constructor" property in your `extend` definition), or defaulted
+ // by us to simply call the parent constructor.
+ if (protoProps && _.has(protoProps, 'constructor')) {
+ child = protoProps.constructor;
+ } else {
+ child = function(){ return parent.apply(this, arguments); };
+ }
+
+ // Add static properties to the constructor function, if supplied.
+ _.extend(child, parent, staticProps);
+
+ // Set the prototype chain to inherit from `parent`, without calling
+ // `parent` constructor function.
+ var Surrogate = function(){ this.constructor = child; };
+ Surrogate.prototype = parent.prototype;
+ child.prototype = new Surrogate;
+
+ // Add prototype properties (instance properties) to the subclass,
+ // if supplied.
+ if (protoProps) _.extend(child.prototype, protoProps);
+
+ // Set a convenience property in case the parent's prototype is needed
+ // later.
+ child.__super__ = parent.prototype;
+
+ return child;
+ };
+
+ // Set up inheritance for the model, collection, router, view and history.
+ Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;
+
+ // Throw an error when a URL is needed, and none is supplied.
+ var urlError = function() {
+ throw new Error('A "url" property or function must be specified');
+ };
+
+ // Wrap an optional error callback with a fallback error event.
+ var wrapError = function(model, options) {
+ var error = options.error;
+ options.error = function(resp) {
+ if (error) error.call(options.context, model, resp, options);
+ model.trigger('error', model, resp, options);
+ };
+ };
+
+ return Backbone;
+
+}));
diff --git a/deployed/windwalker/media/windwalker/js/core/backbone.min.js b/deployed/windwalker/media/windwalker/js/core/backbone.min.js
new file mode 100644
index 00000000..0d9da68d
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/core/backbone.min.js
@@ -0,0 +1 @@
+(function(factory){var root=(typeof self=='object'&&self.self==self&&self)||(typeof global=='object'&&global.global==global&&global);if(typeof define==='function'&&define.amd){define(['underscore','jquery','exports'],function(_,$,exports){root.Backbone=factory(root,exports,_,$)})}else if(typeof exports!=='undefined'){var _=require('underscore'),$;try{$=require('jquery')}catch(e){};factory(root,exports,_,$)}else root.Backbone=factory(root,{},root._,(root.jQuery||root.Zepto||root.ender||root.$))}(function(root,Backbone,_,$){var previousBackbone=root.Backbone,slice=Array.prototype.slice;Backbone.VERSION='1.2.2';Backbone.$=$;Backbone.noConflict=function(){root.Backbone=previousBackbone;return this};Backbone.emulateHTTP=false;Backbone.emulateJSON=false;var addMethod=function(length,method,attribute){switch(length){case 1:return function(){return _[method](this[attribute])};case 2:return function(value){return _[method](this[attribute],value)};case 3:return function(iteratee,context){return _[method](this[attribute],cb(iteratee,this),context)};case 4:return function(iteratee,defaultVal,context){return _[method](this[attribute],cb(iteratee,this),defaultVal,context)};default:return function(){var args=slice.call(arguments);args.unshift(this[attribute]);return _[method].apply(_,args)}}},addUnderscoreMethods=function(Class,methods,attribute){_.each(methods,function(length,method){if(_[method])Class.prototype[method]=addMethod(length,method,attribute)})},cb=function(iteratee,instance){if(_.isFunction(iteratee))return iteratee;if(_.isObject(iteratee)&&!instance._isModel(iteratee))return modelMatcher(iteratee);if(_.isString(iteratee))return function(model){return model.get(iteratee)};return iteratee},modelMatcher=function(attrs){var matcher=_.matches(attrs);return function(model){return matcher(model.attributes)}},Events=Backbone.Events={},eventSplitter=/\s+/,eventsApi=function(iteratee,events,name,callback,opts){var i=0,names;if(name&&typeof name==='object'){if(callback!==void(0)&&'context'in opts&&opts.context===void(0))opts.context=callback;for(names=_.keys(name);i7);this._useHashChange=this._wantsHashChange&&this._hasHashChange;this._wantsPushState=!!this.options.pushState;this._hasPushState=!!(this.history&&this.history.pushState);this._usePushState=this._wantsPushState&&this._hasPushState;this.fragment=this.getFragment();this.root=('/'+this.root+'/').replace(rootStripper,'/');if(this._wantsHashChange&&this._wantsPushState)if(!this._hasPushState&&!this.atRoot()){var root=this.root.slice(0,-1)||'/';this.location.replace(root+'#'+this.getPath());return true}else if(this._hasPushState&&this.atRoot())this.navigate(this.getHash(),{replace:true});if(!this._hasHashChange&&this._wantsHashChange&&!this._usePushState){this.iframe=document.createElement('iframe');this.iframe.src='javascript:0';this.iframe.style.display='none';this.iframe.tabIndex=-1;var body=document.body,iWindow=body.insertBefore(this.iframe,body.firstChild).contentWindow;iWindow.document.open();iWindow.document.close();iWindow.location.hash='#'+this.fragment};var addEventListener=window.addEventListener||function(eventName,listener){return attachEvent('on'+eventName,listener)};if(this._usePushState){addEventListener('popstate',this.checkUrl,false)}else if(this._useHashChange&&!this.iframe){addEventListener('hashchange',this.checkUrl,false)}else if(this._wantsHashChange)this._checkUrlInterval=setInterval(this.checkUrl,this.interval);if(!this.options.silent)return this.loadUrl()},stop:function(){var removeEventListener=window.removeEventListener||function(eventName,listener){return detachEvent('on'+eventName,listener)};if(this._usePushState){removeEventListener('popstate',this.checkUrl,false)}else if(this._useHashChange&&!this.iframe)removeEventListener('hashchange',this.checkUrl,false);if(this.iframe){document.body.removeChild(this.iframe);this.iframe=null};if(this._checkUrlInterval)clearInterval(this._checkUrlInterval);History.started=false},route:function(route,callback){this.handlers.unshift({route:route,callback:callback})},checkUrl:function(e){var current=this.getFragment();if(current===this.fragment&&this.iframe)current=this.getHash(this.iframe.contentWindow);if(current===this.fragment)return false;if(this.iframe)this.navigate(current);this.loadUrl()},loadUrl:function(fragment){if(!this.matchRoot())return false;fragment=this.fragment=this.getFragment(fragment);return _.some(this.handlers,function(handler){if(handler.route.test(fragment)){handler.callback(fragment);return true}})},navigate:function(fragment,options){if(!History.started)return false;if(!options||options===true)options={trigger:!!options};fragment=this.getFragment(fragment||'');var root=this.root;if(fragment===''||fragment.charAt(0)==='?')root=root.slice(0,-1)||'/';var url=root+fragment;fragment=this.decodeFragment(fragment.replace(pathStripper,''));if(this.fragment===fragment)return;this.fragment=fragment;if(this._usePushState){this.history[options.replace?'replaceState':'pushState']({},document.title,url)}else if(this._wantsHashChange){this._updateHash(this.location,fragment,options.replace);if(this.iframe&&(fragment!==this.getHash(this.iframe.contentWindow))){var iWindow=this.iframe.contentWindow;if(!options.replace){iWindow.document.open();iWindow.document.close()};this._updateHash(iWindow.location,fragment,options.replace)}}else return this.location.assign(url);if(options.trigger)return this.loadUrl(fragment)},_updateHash:function(location,fragment,replace){if(replace){var href=location.href.replace(/(javascript:|#).*$/,'');location.replace(href+'#'+fragment)}else location.hash='#'+fragment}});Backbone.history=new History();var extend=function(protoProps,staticProps){var parent=this,child;if(protoProps&&_.has(protoProps,'constructor')){child=protoProps.constructor}else child=function(){return parent.apply(this,arguments)};_.extend(child,parent,staticProps);var Surrogate=function(){this.constructor=child};Surrogate.prototype=parent.prototype;child.prototype=new Surrogate();if(protoProps)_.extend(child.prototype,protoProps);child.__super__=parent.prototype;return child};Model.extend=Collection.extend=Router.extend=View.extend=History.extend=extend;var urlError=function(){throw new Error('A "url" property or function must be specified')},wrapError=function(model,options){var error=options.error;options.error=function(resp){if(error)error.call(options.context,model,resp,options);model.trigger('error',model,resp,options)}};return Backbone}))
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/core/index.html b/deployed/windwalker/media/windwalker/js/core/index.html
new file mode 100644
index 00000000..2efb97f3
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/core/index.html
@@ -0,0 +1 @@
+
diff --git a/deployed/windwalker/media/windwalker/js/core/sweetalert2.min.js b/deployed/windwalker/media/windwalker/js/core/sweetalert2.min.js
new file mode 100644
index 00000000..57e4d8a9
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/core/sweetalert2.min.js
@@ -0,0 +1 @@
+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.swal=e():t.swal=e()}(this,function(){return function(t){function e(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,e),r.l=!0,r.exports}var n={};return e.m=t,e.c=n,e.d=function(t,n,o){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:o})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=8)}([function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o="swal-button";e.CLASS_NAMES={MODAL:"swal-modal",OVERLAY:"swal-overlay",SHOW_MODAL:"swal-overlay--show-modal",MODAL_TITLE:"swal-title",MODAL_TEXT:"swal-text",ICON:"swal-icon",ICON_CUSTOM:"swal-icon--custom",CONTENT:"swal-content",FOOTER:"swal-footer",BUTTON_CONTAINER:"swal-button-container",BUTTON:o,CONFIRM_BUTTON:o+"--confirm",CANCEL_BUTTON:o+"--cancel",DANGER_BUTTON:o+"--danger",BUTTON_LOADING:o+"--loading",BUTTON_LOADER:o+"__loader"},e.default=e.CLASS_NAMES},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getNode=function(t){var e="."+t;return document.querySelector(e)},e.stringToNode=function(t){var e=document.createElement("div");return e.innerHTML=t.trim(),e.firstChild},e.insertAfter=function(t,e){var n=e.nextSibling;e.parentNode.insertBefore(t,n)},e.removeNode=function(t){t.parentElement.removeChild(t)},e.throwErr=function(t){throw t=t.replace(/ +(?= )/g,""),"SweetAlert: "+(t=t.trim())},e.isPlainObject=function(t){if("[object Object]"!==Object.prototype.toString.call(t))return!1;var e=Object.getPrototypeOf(t);return null===e||e===Object.prototype},e.ordinalSuffixOf=function(t){var e=t%10,n=t%100;return 1===e&&11!==n?t+"st":2===e&&12!==n?t+"nd":3===e&&13!==n?t+"rd":t+"th"}},function(t,e,n){"use strict";function o(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),o(n(25));var r=n(26);e.overlayMarkup=r.default,o(n(27)),o(n(28)),o(n(29));var i=n(0),a=i.default.MODAL_TITLE,s=i.default.MODAL_TEXT,c=i.default.ICON,l=i.default.FOOTER;e.iconMarkup='\n
',e.titleMarkup='\n
\n',e.textMarkup='\n
',e.footerMarkup='\n
\n'},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1);e.CONFIRM_KEY="confirm",e.CANCEL_KEY="cancel";var r={visible:!0,text:null,value:null,className:"",closeModal:!0},i=Object.assign({},r,{visible:!1,text:"Cancel",value:null}),a=Object.assign({},r,{text:"OK",value:!0});e.defaultButtonList={cancel:i,confirm:a};var s=function(t){switch(t){case e.CONFIRM_KEY:return a;case e.CANCEL_KEY:return i;default:var n=t.charAt(0).toUpperCase()+t.slice(1);return Object.assign({},r,{text:n,value:t})}},c=function(t,e){var n=s(t);return!0===e?Object.assign({},n,{visible:!0}):"string"==typeof e?Object.assign({},n,{visible:!0,text:e}):o.isPlainObject(e)?Object.assign({visible:!0},n,e):Object.assign({},n,{visible:!1})},l=function(t){for(var e={},n=0,o=Object.keys(t);n=0&&w.splice(e,1)}function s(t){var e=document.createElement("style");return t.attrs.type="text/css",l(e,t.attrs),i(t,e),e}function c(t){var e=document.createElement("link");return t.attrs.type="text/css",t.attrs.rel="stylesheet",l(e,t.attrs),i(t,e),e}function l(t,e){Object.keys(e).forEach(function(n){t.setAttribute(n,e[n])})}function u(t,e){var n,o,r,i;if(e.transform&&t.css){if(!(i=e.transform(t.css)))return function(){};t.css=i}if(e.singleton){var l=h++;n=g||(g=s(e)),o=f.bind(null,n,l,!1),r=f.bind(null,n,l,!0)}else t.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=c(e),o=p.bind(null,n,e),r=function(){a(n),n.href&&URL.revokeObjectURL(n.href)}):(n=s(e),o=d.bind(null,n),r=function(){a(n)});return o(t),function(e){if(e){if(e.css===t.css&&e.media===t.media&&e.sourceMap===t.sourceMap)return;o(t=e)}else r()}}function f(t,e,n,o){var r=n?"":o.css;if(t.styleSheet)t.styleSheet.cssText=x(e,r);else{var i=document.createTextNode(r),a=t.childNodes;a[e]&&t.removeChild(a[e]),a.length?t.insertBefore(i,a[e]):t.appendChild(i)}}function d(t,e){var n=e.css,o=e.media;if(o&&t.setAttribute("media",o),t.styleSheet)t.styleSheet.cssText=n;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(n))}}function p(t,e,n){var o=n.css,r=n.sourceMap,i=void 0===e.convertToAbsoluteUrls&&r;(e.convertToAbsoluteUrls||i)&&(o=y(o)),r&&(o+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(r))))+" */");var a=new Blob([o],{type:"text/css"}),s=t.href;t.href=URL.createObjectURL(a),s&&URL.revokeObjectURL(s)}var m={},b=function(t){var e;return function(){return void 0===e&&(e=t.apply(this,arguments)),e}}(function(){return window&&document&&document.all&&!window.atob}),v=function(t){var e={};return function(n){return void 0===e[n]&&(e[n]=t.call(this,n)),e[n]}}(function(t){return document.querySelector(t)}),g=null,h=0,w=[],y=n(15);t.exports=function(t,e){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");e=e||{},e.attrs="object"==typeof e.attrs?e.attrs:{},e.singleton||(e.singleton=b()),e.insertInto||(e.insertInto="head"),e.insertAt||(e.insertAt="bottom");var n=r(t,e);return o(n,e),function(t){for(var i=[],a=0;athis.length)&&-1!==this.indexOf(t,e)}),Array.prototype.includes||Object.defineProperty(Array.prototype,"includes",{value:function(t,e){if(null==this)throw new TypeError('"this" is null or not defined');var n=Object(this),o=n.length>>>0;if(0===o)return!1;for(var r=0|e,i=Math.max(r>=0?r:o-Math.abs(r),0);i=0&&(t._idleTimeoutId=setTimeout(function(){t._onTimeout&&t._onTimeout()},e))},n(19),e.setImmediate=setImmediate,e.clearImmediate=clearImmediate},function(t,e,n){(function(t,e){!function(t,n){"use strict";function o(t){"function"!=typeof t&&(t=new Function(""+t));for(var e=new Array(arguments.length-1),n=0;n1)for(var n=1;n',e.default=e.modalMarkup},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.OVERLAY,i='\n
';e.default=i},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.ICON;e.errorIconMarkup=function(){var t=r+"--error",e=t+"__line";return'\n \n \n \n
\n '},e.warningIconMarkup=function(){var t=r+"--warning";return'\n \n \n \n '},e.successIconMarkup=function(){var t=r+"--success";return'\n \n \n\n
\n
\n '}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.CONTENT;e.contentMarkup='\n \n\n
\n'},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.BUTTON_CONTAINER,i=o.default.BUTTON,a=o.default.BUTTON_LOADER;e.buttonMarkup='\n \n'},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(4),r=n(2),i=n(0),a=i.default.ICON,s=i.default.ICON_CUSTOM,c=["error","warning","success","info"],l={error:r.errorIconMarkup(),warning:r.warningIconMarkup(),success:r.successIconMarkup()},u=function(t,e){var n=a+"--"+t;e.classList.add(n);var o=l[t];o&&(e.innerHTML=o)},f=function(t,e){e.classList.add(s);var n=document.createElement("img");n.src=t,e.appendChild(n)},d=function(t){if(t){var e=o.injectElIntoModal(r.iconMarkup);c.includes(t)?u(t,e):f(t,e)}};e.default=d},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(2),r=n(4),i=function(t){navigator.userAgent.includes("AppleWebKit")&&(t.style.display="none",t.offsetHeight,t.style.display="")};e.initTitle=function(t){if(t){var e=r.injectElIntoModal(o.titleMarkup);e.textContent=t,i(e)}},e.initText=function(t){if(t){var e=document.createDocumentFragment();t.split("\n").forEach(function(t,n,o){e.appendChild(document.createTextNode(t)),n0}).forEach(function(t){b.classList.add(t)})}n&&t===c.CONFIRM_KEY&&b.classList.add(s),b.textContent=r;var g={};return g[t]=i,f.setActionValue(g),f.setActionOptionsFor(t,{closeModal:p}),b.addEventListener("click",function(){return u.onAction(t)}),m},p=function(t,e){var n=r.injectElIntoModal(l.footerMarkup);for(var o in t){var i=t[o],a=d(o,i,e);i.visible&&n.appendChild(a)}0===n.children.length&&n.remove()};e.default=p},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(3),r=n(4),i=n(2),a=n(5),s=n(6),c=n(0),l=c.default.CONTENT,u=function(t){t.addEventListener("input",function(t){var e=t.target,n=e.value;a.setActionValue(n)}),t.addEventListener("keyup",function(t){if("Enter"===t.key)return s.onAction(o.CONFIRM_KEY)}),setTimeout(function(){t.focus(),a.setActionValue("")},0)},f=function(t,e,n){var o=document.createElement(e),r=l+"__"+e;o.classList.add(r);for(var i in n){var a=n[i];o[i]=a}"input"===e&&u(o),t.appendChild(o)},d=function(t){if(t){var e=r.injectElIntoModal(i.contentMarkup),n=t.element,o=t.attributes;"string"==typeof n?f(e,n,o):e.appendChild(n)}};e.default=d},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(2),i=function(){var t=o.stringToNode(r.overlayMarkup);document.body.appendChild(t)};e.default=i},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(5),r=n(6),i=n(1),a=n(3),s=n(0),c=s.default.MODAL,l=s.default.BUTTON,u=s.default.OVERLAY,f=function(t){t.preventDefault(),v()},d=function(t){t.preventDefault(),g()},p=function(t){if(o.default.isOpen)switch(t.key){case"Escape":return r.onAction(a.CANCEL_KEY)}},m=function(t){if(o.default.isOpen)switch(t.key){case"Tab":return f(t)}},b=function(t){if(o.default.isOpen)return"Tab"===t.key&&t.shiftKey?d(t):void 0},v=function(){var t=i.getNode(l);t&&(t.tabIndex=0,t.focus())},g=function(){var t=i.getNode(c),e=t.querySelectorAll("."+l),n=e.length-1,o=e[n];o&&o.focus()},h=function(t){t[t.length-1].addEventListener("keydown",m)},w=function(t){t[0].addEventListener("keydown",b)},y=function(){var t=i.getNode(c),e=t.querySelectorAll("."+l);e.length&&(h(e),w(e))},x=function(t){if(i.getNode(u)===t.target)return r.onAction(a.CANCEL_KEY)},_=function(t){var e=i.getNode(u);e.removeEventListener("click",x),t&&e.addEventListener("click",x)},k=function(t){o.default.timer&&clearTimeout(o.default.timer),t&&(o.default.timer=window.setTimeout(function(){return r.onAction(a.CANCEL_KEY)},t))},O=function(t){t.closeOnEsc?document.addEventListener("keyup",p):document.removeEventListener("keyup",p),t.dangerMode?v():g(),y(),_(t.closeOnClickOutside),k(t.timer)};e.default=O},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(3),i=n(37),a=n(38),s={title:null,text:null,icon:null,buttons:r.defaultButtonList,content:null,className:null,closeOnClickOutside:!0,closeOnEsc:!0,dangerMode:!1,timer:null},c=Object.assign({},s);e.setDefaults=function(t){c=Object.assign({},s,t)};var l=function(t){var e=t&&t.button,n=t&&t.buttons;return void 0!==e&&void 0!==n&&o.throwErr("Cannot set both 'button' and 'buttons' options!"),void 0!==e?{confirm:e}:n},u=function(t){return o.ordinalSuffixOf(t+1)},f=function(t,e){o.throwErr(u(e)+" argument ('"+t+"') is invalid")},d=function(t,e){var n=t+1,r=e[n];o.isPlainObject(r)||void 0===r||o.throwErr("Expected "+u(n)+" argument ('"+r+"') to be a plain object")},p=function(t,e){var n=t+1,r=e[n];void 0!==r&&o.throwErr("Unexpected "+u(n)+" argument ("+r+")")},m=function(t,e,n,r){var i=typeof e,a="string"===i,s=e instanceof Element;if(a){if(0===n)return{text:e};if(1===n)return{text:e,title:r[0]};if(2===n)return d(n,r),{icon:e};f(e,n)}else{if(s&&0===n)return d(n,r),{content:e};if(o.isPlainObject(e))return p(n,r),e;f(e,n)}};e.getOpts=function(){for(var t=[],e=0;e= 0 && length <= MAX_ARRAY_INDEX;
+ };
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles raw objects in addition to array-likes. Treats all
+ // sparse array-likes as if they were dense.
+ _.each = _.forEach = function(obj, iteratee, context) {
+ iteratee = optimizeCb(iteratee, context);
+ var i, length;
+ if (isArrayLike(obj)) {
+ for (i = 0, length = obj.length; i < length; i++) {
+ iteratee(obj[i], i, obj);
+ }
+ } else {
+ var keys = _.keys(obj);
+ for (i = 0, length = keys.length; i < length; i++) {
+ iteratee(obj[keys[i]], keys[i], obj);
+ }
+ }
+ return obj;
+ };
+
+ // Return the results of applying the iteratee to each element.
+ _.map = _.collect = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ results = Array(length);
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ results[index] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Create a reducing function iterating left or right.
+ function createReduce(dir) {
+ // Optimized iterator function as using arguments.length
+ // in the main function will deoptimize the, see #1991.
+ function iterator(obj, iteratee, memo, keys, index, length) {
+ for (; index >= 0 && index < length; index += dir) {
+ var currentKey = keys ? keys[index] : index;
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
+ }
+ return memo;
+ }
+
+ return function(obj, iteratee, memo, context) {
+ iteratee = optimizeCb(iteratee, context, 4);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ index = dir > 0 ? 0 : length - 1;
+ // Determine the initial value if none is provided.
+ if (arguments.length < 3) {
+ memo = obj[keys ? keys[index] : index];
+ index += dir;
+ }
+ return iterator(obj, iteratee, memo, keys, index, length);
+ };
+ }
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`.
+ _.reduce = _.foldl = _.inject = createReduce(1);
+
+ // The right-associative version of reduce, also known as `foldr`.
+ _.reduceRight = _.foldr = createReduce(-1);
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, predicate, context) {
+ var key;
+ if (isArrayLike(obj)) {
+ key = _.findIndex(obj, predicate, context);
+ } else {
+ key = _.findKey(obj, predicate, context);
+ }
+ if (key !== void 0 && key !== -1) return obj[key];
+ };
+
+ // Return all the elements that pass a truth test.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, predicate, context) {
+ var results = [];
+ predicate = cb(predicate, context);
+ _.each(obj, function(value, index, list) {
+ if (predicate(value, index, list)) results.push(value);
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, predicate, context) {
+ return _.filter(obj, _.negate(cb(predicate)), context);
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (!predicate(obj[currentKey], currentKey, obj)) return false;
+ }
+ return true;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Aliased as `any`.
+ _.some = _.any = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (predicate(obj[currentKey], currentKey, obj)) return true;
+ }
+ return false;
+ };
+
+ // Determine if the array or object contains a given item (using `===`).
+ // Aliased as `includes` and `include`.
+ _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ if (typeof fromIndex != 'number' || guard) fromIndex = 0;
+ return _.indexOf(obj, item, fromIndex) >= 0;
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ var isFunc = _.isFunction(method);
+ return _.map(obj, function(value) {
+ var func = isFunc ? method : value[method];
+ return func == null ? func : func.apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, _.property(key));
+ };
+
+ // Convenience version of a common use case of `filter`: selecting only objects
+ // containing specific `key:value` pairs.
+ _.where = function(obj, attrs) {
+ return _.filter(obj, _.matcher(attrs));
+ };
+
+ // Convenience version of a common use case of `find`: getting the first object
+ // containing specific `key:value` pairs.
+ _.findWhere = function(obj, attrs) {
+ return _.find(obj, _.matcher(attrs));
+ };
+
+ // Return the maximum element (or element-based computation).
+ _.max = function(obj, iteratee, context) {
+ var result = -Infinity, lastComputed = -Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value > result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iteratee, context) {
+ var result = Infinity, lastComputed = Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value < result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed < lastComputed || computed === Infinity && result === Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Shuffle a collection, using the modern version of the
+ // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
+ _.shuffle = function(obj) {
+ var set = isArrayLike(obj) ? obj : _.values(obj);
+ var length = set.length;
+ var shuffled = Array(length);
+ for (var index = 0, rand; index < length; index++) {
+ rand = _.random(0, index);
+ if (rand !== index) shuffled[index] = shuffled[rand];
+ shuffled[rand] = set[index];
+ }
+ return shuffled;
+ };
+
+ // Sample **n** random values from a collection.
+ // If **n** is not specified, returns a single random element.
+ // The internal `guard` argument allows it to work with `map`.
+ _.sample = function(obj, n, guard) {
+ if (n == null || guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ return obj[_.random(obj.length - 1)];
+ }
+ return _.shuffle(obj).slice(0, Math.max(0, n));
+ };
+
+ // Sort the object's values by a criterion produced by an iteratee.
+ _.sortBy = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value: value,
+ index: index,
+ criteria: iteratee(value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria;
+ var b = right.criteria;
+ if (a !== b) {
+ if (a > b || a === void 0) return 1;
+ if (a < b || b === void 0) return -1;
+ }
+ return left.index - right.index;
+ }), 'value');
+ };
+
+ // An internal function used for aggregate "group by" operations.
+ var group = function(behavior) {
+ return function(obj, iteratee, context) {
+ var result = {};
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index) {
+ var key = iteratee(value, index, obj);
+ behavior(result, value, key);
+ });
+ return result;
+ };
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key].push(value); else result[key] = [value];
+ });
+
+ // Indexes the object's values by a criterion, similar to `groupBy`, but for
+ // when you know that your index values will be unique.
+ _.indexBy = group(function(result, value, key) {
+ result[key] = value;
+ });
+
+ // Counts instances of an object that group by a certain criterion. Pass
+ // either a string attribute to count by, or a function that returns the
+ // criterion.
+ _.countBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key]++; else result[key] = 1;
+ });
+
+ // Safely create a real, live array from anything iterable.
+ _.toArray = function(obj) {
+ if (!obj) return [];
+ if (_.isArray(obj)) return slice.call(obj);
+ if (isArrayLike(obj)) return _.map(obj, _.identity);
+ return _.values(obj);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ if (obj == null) return 0;
+ return isArrayLike(obj) ? obj.length : _.keys(obj).length;
+ };
+
+ // Split a collection into two arrays: one whose elements all satisfy the given
+ // predicate, and one whose elements all do not satisfy the predicate.
+ _.partition = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var pass = [], fail = [];
+ _.each(obj, function(value, key, obj) {
+ (predicate(value, key, obj) ? pass : fail).push(value);
+ });
+ return [pass, fail];
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head` and `take`. The **guard** check
+ // allows it to work with `_.map`.
+ _.first = _.head = _.take = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[0];
+ return _.initial(array, array.length - n);
+ };
+
+ // Returns everything but the last entry of the array. Especially useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array.
+ _.last = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[array.length - 1];
+ return _.rest(array, Math.max(0, array.length - n));
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
+ // Especially useful on the arguments object. Passing an **n** will return
+ // the rest N values in the array.
+ _.rest = _.tail = _.drop = function(array, n, guard) {
+ return slice.call(array, n == null || guard ? 1 : n);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, _.identity);
+ };
+
+ // Internal implementation of a recursive `flatten` function.
+ var flatten = function(input, shallow, strict, startIndex) {
+ var output = [], idx = 0;
+ for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
+ var value = input[i];
+ if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
+ //flatten current level of array or arguments object
+ if (!shallow) value = flatten(value, shallow, strict);
+ var j = 0, len = value.length;
+ output.length += len;
+ while (j < len) {
+ output[idx++] = value[j++];
+ }
+ } else if (!strict) {
+ output[idx++] = value;
+ }
+ }
+ return output;
+ };
+
+ // Flatten out an array, either recursively (by default), or just one level.
+ _.flatten = function(array, shallow) {
+ return flatten(array, shallow, false);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iteratee, context) {
+ if (!_.isBoolean(isSorted)) {
+ context = iteratee;
+ iteratee = isSorted;
+ isSorted = false;
+ }
+ if (iteratee != null) iteratee = cb(iteratee, context);
+ var result = [];
+ var seen = [];
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var value = array[i],
+ computed = iteratee ? iteratee(value, i, array) : value;
+ if (isSorted) {
+ if (!i || seen !== computed) result.push(value);
+ seen = computed;
+ } else if (iteratee) {
+ if (!_.contains(seen, computed)) {
+ seen.push(computed);
+ result.push(value);
+ }
+ } else if (!_.contains(result, value)) {
+ result.push(value);
+ }
+ }
+ return result;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(flatten(arguments, true, true));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays.
+ _.intersection = function(array) {
+ var result = [];
+ var argsLength = arguments.length;
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var item = array[i];
+ if (_.contains(result, item)) continue;
+ for (var j = 1; j < argsLength; j++) {
+ if (!_.contains(arguments[j], item)) break;
+ }
+ if (j === argsLength) result.push(item);
+ }
+ return result;
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = flatten(arguments, true, true, 1);
+ return _.filter(array, function(value){
+ return !_.contains(rest, value);
+ });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ return _.unzip(arguments);
+ };
+
+ // Complement of _.zip. Unzip accepts an array of arrays and groups
+ // each array's elements on shared indices
+ _.unzip = function(array) {
+ var length = array && _.max(array, getLength).length || 0;
+ var result = Array(length);
+
+ for (var index = 0; index < length; index++) {
+ result[index] = _.pluck(array, index);
+ }
+ return result;
+ };
+
+ // Converts lists into objects. Pass either a single array of `[key, value]`
+ // pairs, or two parallel arrays of the same length -- one of keys, and one of
+ // the corresponding values.
+ _.object = function(list, values) {
+ var result = {};
+ for (var i = 0, length = getLength(list); i < length; i++) {
+ if (values) {
+ result[list[i]] = values[i];
+ } else {
+ result[list[i][0]] = list[i][1];
+ }
+ }
+ return result;
+ };
+
+ // Generator function to create the findIndex and findLastIndex functions
+ function createPredicateIndexFinder(dir) {
+ return function(array, predicate, context) {
+ predicate = cb(predicate, context);
+ var length = getLength(array);
+ var index = dir > 0 ? 0 : length - 1;
+ for (; index >= 0 && index < length; index += dir) {
+ if (predicate(array[index], index, array)) return index;
+ }
+ return -1;
+ };
+ }
+
+ // Returns the first index on an array-like that passes a predicate test
+ _.findIndex = createPredicateIndexFinder(1);
+ _.findLastIndex = createPredicateIndexFinder(-1);
+
+ // Use a comparator function to figure out the smallest index at which
+ // an object should be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iteratee, context) {
+ iteratee = cb(iteratee, context, 1);
+ var value = iteratee(obj);
+ var low = 0, high = getLength(array);
+ while (low < high) {
+ var mid = Math.floor((low + high) / 2);
+ if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
+ }
+ return low;
+ };
+
+ // Generator function to create the indexOf and lastIndexOf functions
+ function createIndexFinder(dir, predicateFind, sortedIndex) {
+ return function(array, item, idx) {
+ var i = 0, length = getLength(array);
+ if (typeof idx == 'number') {
+ if (dir > 0) {
+ i = idx >= 0 ? idx : Math.max(idx + length, i);
+ } else {
+ length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
+ }
+ } else if (sortedIndex && idx && length) {
+ idx = sortedIndex(array, item);
+ return array[idx] === item ? idx : -1;
+ }
+ if (item !== item) {
+ idx = predicateFind(slice.call(array, i, length), _.isNaN);
+ return idx >= 0 ? idx + i : -1;
+ }
+ for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
+ if (array[idx] === item) return idx;
+ }
+ return -1;
+ };
+ }
+
+ // Return the position of the first occurrence of an item in an array,
+ // or -1 if the item is not included in the array.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
+ _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (stop == null) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = step || 1;
+
+ var length = Math.max(Math.ceil((stop - start) / step), 0);
+ var range = Array(length);
+
+ for (var idx = 0; idx < length; idx++, start += step) {
+ range[idx] = start;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Determines whether to execute a function as a constructor
+ // or a normal function with the provided arguments
+ var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
+ if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
+ var self = baseCreate(sourceFunc.prototype);
+ var result = sourceFunc.apply(self, args);
+ if (_.isObject(result)) return result;
+ return self;
+ };
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
+ // available.
+ _.bind = function(func, context) {
+ if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
+ var args = slice.call(arguments, 2);
+ var bound = function() {
+ return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
+ };
+ return bound;
+ };
+
+ // Partially apply a function by creating a version that has had some of its
+ // arguments pre-filled, without changing its dynamic `this` context. _ acts
+ // as a placeholder, allowing any combination of arguments to be pre-filled.
+ _.partial = function(func) {
+ var boundArgs = slice.call(arguments, 1);
+ var bound = function() {
+ var position = 0, length = boundArgs.length;
+ var args = Array(length);
+ for (var i = 0; i < length; i++) {
+ args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
+ }
+ while (position < arguments.length) args.push(arguments[position++]);
+ return executeBound(func, bound, this, this, args);
+ };
+ return bound;
+ };
+
+ // Bind a number of an object's methods to that object. Remaining arguments
+ // are the method names to be bound. Useful for ensuring that all callbacks
+ // defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var i, length = arguments.length, key;
+ if (length <= 1) throw new Error('bindAll must be passed function names');
+ for (i = 1; i < length; i++) {
+ key = arguments[i];
+ obj[key] = _.bind(obj[key], obj);
+ }
+ return obj;
+ };
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memoize = function(key) {
+ var cache = memoize.cache;
+ var address = '' + (hasher ? hasher.apply(this, arguments) : key);
+ if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
+ return cache[address];
+ };
+ memoize.cache = {};
+ return memoize;
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){
+ return func.apply(null, args);
+ }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = _.partial(_.delay, _, 1);
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time. Normally, the throttled function will run
+ // as much as it can, without ever going more than once per `wait` duration;
+ // but if you'd like to disable the execution on the leading edge, pass
+ // `{leading: false}`. To disable execution on the trailing edge, ditto.
+ _.throttle = function(func, wait, options) {
+ var context, args, result;
+ var timeout = null;
+ var previous = 0;
+ if (!options) options = {};
+ var later = function() {
+ previous = options.leading === false ? 0 : _.now();
+ timeout = null;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ };
+ return function() {
+ var now = _.now();
+ if (!previous && options.leading === false) previous = now;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0 || remaining > wait) {
+ if (timeout) {
+ clearTimeout(timeout);
+ timeout = null;
+ }
+ previous = now;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds. If `immediate` is passed, trigger the function on the
+ // leading edge, instead of the trailing.
+ _.debounce = function(func, wait, immediate) {
+ var timeout, args, context, timestamp, result;
+
+ var later = function() {
+ var last = _.now() - timestamp;
+
+ if (last < wait && last >= 0) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ }
+ }
+ };
+
+ return function() {
+ context = this;
+ args = arguments;
+ timestamp = _.now();
+ var callNow = immediate && !timeout;
+ if (!timeout) timeout = setTimeout(later, wait);
+ if (callNow) {
+ result = func.apply(context, args);
+ context = args = null;
+ }
+
+ return result;
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return _.partial(wrapper, func);
+ };
+
+ // Returns a negated version of the passed-in predicate.
+ _.negate = function(predicate) {
+ return function() {
+ return !predicate.apply(this, arguments);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var args = arguments;
+ var start = args.length - 1;
+ return function() {
+ var i = start;
+ var result = args[start].apply(this, arguments);
+ while (i--) result = args[i].call(this, result);
+ return result;
+ };
+ };
+
+ // Returns a function that will only be executed on and after the Nth call.
+ _.after = function(times, func) {
+ return function() {
+ if (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ };
+
+ // Returns a function that will only be executed up to (but not including) the Nth call.
+ _.before = function(times, func) {
+ var memo;
+ return function() {
+ if (--times > 0) {
+ memo = func.apply(this, arguments);
+ }
+ if (times <= 1) func = null;
+ return memo;
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = _.partial(_.before, 2);
+
+ // Object Functions
+ // ----------------
+
+ // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
+ var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
+ var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
+ 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
+
+ function collectNonEnumProps(obj, keys) {
+ var nonEnumIdx = nonEnumerableProps.length;
+ var constructor = obj.constructor;
+ var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
+
+ // Constructor is a special case.
+ var prop = 'constructor';
+ if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
+
+ while (nonEnumIdx--) {
+ prop = nonEnumerableProps[nonEnumIdx];
+ if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
+ keys.push(prop);
+ }
+ }
+ }
+
+ // Retrieve the names of an object's own properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ if (nativeKeys) return nativeKeys(obj);
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve all the property names of an object.
+ _.allKeys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ var keys = [];
+ for (var key in obj) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var values = Array(length);
+ for (var i = 0; i < length; i++) {
+ values[i] = obj[keys[i]];
+ }
+ return values;
+ };
+
+ // Returns the results of applying the iteratee to each element of the object
+ // In contrast to _.map it returns an object
+ _.mapObject = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = _.keys(obj),
+ length = keys.length,
+ results = {},
+ currentKey;
+ for (var index = 0; index < length; index++) {
+ currentKey = keys[index];
+ results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Convert an object into a list of `[key, value]` pairs.
+ _.pairs = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var pairs = Array(length);
+ for (var i = 0; i < length; i++) {
+ pairs[i] = [keys[i], obj[keys[i]]];
+ }
+ return pairs;
+ };
+
+ // Invert the keys and values of an object. The values must be serializable.
+ _.invert = function(obj) {
+ var result = {};
+ var keys = _.keys(obj);
+ for (var i = 0, length = keys.length; i < length; i++) {
+ result[obj[keys[i]]] = keys[i];
+ }
+ return result;
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = createAssigner(_.allKeys);
+
+ // Assigns a given object with all the own properties in the passed-in object(s)
+ // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
+ _.extendOwn = _.assign = createAssigner(_.keys);
+
+ // Returns the first key on an object that passes a predicate test
+ _.findKey = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = _.keys(obj), key;
+ for (var i = 0, length = keys.length; i < length; i++) {
+ key = keys[i];
+ if (predicate(obj[key], key, obj)) return key;
+ }
+ };
+
+ // Return a copy of the object only containing the whitelisted properties.
+ _.pick = function(object, oiteratee, context) {
+ var result = {}, obj = object, iteratee, keys;
+ if (obj == null) return result;
+ if (_.isFunction(oiteratee)) {
+ keys = _.allKeys(obj);
+ iteratee = optimizeCb(oiteratee, context);
+ } else {
+ keys = flatten(arguments, false, false, 1);
+ iteratee = function(value, key, obj) { return key in obj; };
+ obj = Object(obj);
+ }
+ for (var i = 0, length = keys.length; i < length; i++) {
+ var key = keys[i];
+ var value = obj[key];
+ if (iteratee(value, key, obj)) result[key] = value;
+ }
+ return result;
+ };
+
+ // Return a copy of the object without the blacklisted properties.
+ _.omit = function(obj, iteratee, context) {
+ if (_.isFunction(iteratee)) {
+ iteratee = _.negate(iteratee);
+ } else {
+ var keys = _.map(flatten(arguments, false, false, 1), String);
+ iteratee = function(value, key) {
+ return !_.contains(keys, key);
+ };
+ }
+ return _.pick(obj, iteratee, context);
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = createAssigner(_.allKeys, true);
+
+ // Creates an object that inherits from the given prototype object.
+ // If additional properties are provided then they will be added to the
+ // created object.
+ _.create = function(prototype, props) {
+ var result = baseCreate(prototype);
+ if (props) _.extendOwn(result, props);
+ return result;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Returns whether an object has a given set of `key:value` pairs.
+ _.isMatch = function(object, attrs) {
+ var keys = _.keys(attrs), length = keys.length;
+ if (object == null) return !length;
+ var obj = Object(object);
+ for (var i = 0; i < length; i++) {
+ var key = keys[i];
+ if (attrs[key] !== obj[key] || !(key in obj)) return false;
+ }
+ return true;
+ };
+
+
+ // Internal recursive comparison function for `isEqual`.
+ var eq = function(a, b, aStack, bStack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
+ if (a === b) return a !== 0 || 1 / a === 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className !== toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, regular expressions, dates, and booleans are compared by value.
+ case '[object RegExp]':
+ // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return '' + a === '' + b;
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive.
+ // Object(NaN) is equivalent to NaN
+ if (+a !== +a) return +b !== +b;
+ // An `egal` comparison is performed for other numeric values.
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a === +b;
+ }
+
+ var areArrays = className === '[object Array]';
+ if (!areArrays) {
+ if (typeof a != 'object' || typeof b != 'object') return false;
+
+ // Objects with different constructors are not equivalent, but `Object`s or `Array`s
+ // from different frames are.
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
+ _.isFunction(bCtor) && bCtor instanceof bCtor)
+ && ('constructor' in a && 'constructor' in b)) {
+ return false;
+ }
+ }
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+
+ // Initializing stack of traversed objects.
+ // It's done here since we only need them for objects and arrays comparison.
+ aStack = aStack || [];
+ bStack = bStack || [];
+ var length = aStack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (aStack[length] === a) return bStack[length] === b;
+ }
+
+ // Add the first object to the stack of traversed objects.
+ aStack.push(a);
+ bStack.push(b);
+
+ // Recursively compare objects and arrays.
+ if (areArrays) {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ length = a.length;
+ if (length !== b.length) return false;
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (length--) {
+ if (!eq(a[length], b[length], aStack, bStack)) return false;
+ }
+ } else {
+ // Deep compare objects.
+ var keys = _.keys(a), key;
+ length = keys.length;
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
+ if (_.keys(b).length !== length) return false;
+ while (length--) {
+ // Deep compare each member
+ key = keys[length];
+ if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ aStack.pop();
+ bStack.pop();
+ return true;
+ };
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (obj == null) return true;
+ if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
+ return _.keys(obj).length === 0;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) === '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ var type = typeof obj;
+ return type === 'function' || type === 'object' && !!obj;
+ };
+
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
+ _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
+ _['is' + name] = function(obj) {
+ return toString.call(obj) === '[object ' + name + ']';
+ };
+ });
+
+ // Define a fallback version of the method in browsers (ahem, IE < 9), where
+ // there isn't any inspectable "Arguments" type.
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return _.has(obj, 'callee');
+ };
+ }
+
+ // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
+ // IE 11 (#1621), and in Safari 8 (#1929).
+ if (typeof /./ != 'function' && typeof Int8Array != 'object') {
+ _.isFunction = function(obj) {
+ return typeof obj == 'function' || false;
+ };
+ }
+
+ // Is a given object a finite number?
+ _.isFinite = function(obj) {
+ return isFinite(obj) && !isNaN(parseFloat(obj));
+ };
+
+ // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && obj !== +obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Shortcut function for checking if an object has a given property directly
+ // on itself (in other words, not on a prototype).
+ _.has = function(obj, key) {
+ return obj != null && hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iteratees.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Predicate-generating functions. Often useful outside of Underscore.
+ _.constant = function(value) {
+ return function() {
+ return value;
+ };
+ };
+
+ _.noop = function(){};
+
+ _.property = property;
+
+ // Generates a function for a given object that returns a given property.
+ _.propertyOf = function(obj) {
+ return obj == null ? function(){} : function(key) {
+ return obj[key];
+ };
+ };
+
+ // Returns a predicate for checking whether an object has a given set of
+ // `key:value` pairs.
+ _.matcher = _.matches = function(attrs) {
+ attrs = _.extendOwn({}, attrs);
+ return function(obj) {
+ return _.isMatch(obj, attrs);
+ };
+ };
+
+ // Run a function **n** times.
+ _.times = function(n, iteratee, context) {
+ var accum = Array(Math.max(0, n));
+ iteratee = optimizeCb(iteratee, context, 1);
+ for (var i = 0; i < n; i++) accum[i] = iteratee(i);
+ return accum;
+ };
+
+ // Return a random integer between min and max (inclusive).
+ _.random = function(min, max) {
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + Math.floor(Math.random() * (max - min + 1));
+ };
+
+ // A (possibly faster) way to get the current timestamp as an integer.
+ _.now = Date.now || function() {
+ return new Date().getTime();
+ };
+
+ // List of HTML entities for escaping.
+ var escapeMap = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '`': '`'
+ };
+ var unescapeMap = _.invert(escapeMap);
+
+ // Functions for escaping and unescaping strings to/from HTML interpolation.
+ var createEscaper = function(map) {
+ var escaper = function(match) {
+ return map[match];
+ };
+ // Regexes for identifying a key that needs to be escaped
+ var source = '(?:' + _.keys(map).join('|') + ')';
+ var testRegexp = RegExp(source);
+ var replaceRegexp = RegExp(source, 'g');
+ return function(string) {
+ string = string == null ? '' : '' + string;
+ return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
+ };
+ };
+ _.escape = createEscaper(escapeMap);
+ _.unescape = createEscaper(unescapeMap);
+
+ // If the value of the named `property` is a function then invoke it with the
+ // `object` as context; otherwise, return it.
+ _.result = function(object, property, fallback) {
+ var value = object == null ? void 0 : object[property];
+ if (value === void 0) {
+ value = fallback;
+ }
+ return _.isFunction(value) ? value.call(object) : value;
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = ++idCounter + '';
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /(.)^/;
+
+ // Certain characters need to be escaped so that they can be put into a
+ // string literal.
+ var escapes = {
+ "'": "'",
+ '\\': '\\',
+ '\r': 'r',
+ '\n': 'n',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
+
+ var escapeChar = function(match) {
+ return '\\' + escapes[match];
+ };
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ // NB: `oldSettings` only exists for backwards compatibility.
+ _.template = function(text, settings, oldSettings) {
+ if (!settings && oldSettings) settings = oldSettings;
+ settings = _.defaults({}, settings, _.templateSettings);
+
+ // Combine delimiters into one regular expression via alternation.
+ var matcher = RegExp([
+ (settings.escape || noMatch).source,
+ (settings.interpolate || noMatch).source,
+ (settings.evaluate || noMatch).source
+ ].join('|') + '|$', 'g');
+
+ // Compile the template source, escaping string literals appropriately.
+ var index = 0;
+ var source = "__p+='";
+ text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+ source += text.slice(index, offset).replace(escaper, escapeChar);
+ index = offset + match.length;
+
+ if (escape) {
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+ } else if (interpolate) {
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+ } else if (evaluate) {
+ source += "';\n" + evaluate + "\n__p+='";
+ }
+
+ // Adobe VMs need the match returned to produce the correct offest.
+ return match;
+ });
+ source += "';\n";
+
+ // If a variable is not specified, place data values in local scope.
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+ source = "var __t,__p='',__j=Array.prototype.join," +
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
+ source + 'return __p;\n';
+
+ try {
+ var render = new Function(settings.variable || 'obj', '_', source);
+ } catch (e) {
+ e.source = source;
+ throw e;
+ }
+
+ var template = function(data) {
+ return render.call(this, data, _);
+ };
+
+ // Provide the compiled source as a convenience for precompilation.
+ var argument = settings.variable || 'obj';
+ template.source = 'function(' + argument + '){\n' + source + '}';
+
+ return template;
+ };
+
+ // Add a "chain" function. Start chaining a wrapped Underscore object.
+ _.chain = function(obj) {
+ var instance = _(obj);
+ instance._chain = true;
+ return instance;
+ };
+
+ // OOP
+ // ---------------
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(instance, obj) {
+ return instance._chain ? _(obj).chain() : obj;
+ };
+
+ // Add your own custom functions to the Underscore object.
+ _.mixin = function(obj) {
+ _.each(_.functions(obj), function(name) {
+ var func = _[name] = obj[name];
+ _.prototype[name] = function() {
+ var args = [this._wrapped];
+ push.apply(args, arguments);
+ return result(this, func.apply(_, args));
+ };
+ });
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ var obj = this._wrapped;
+ method.apply(obj, arguments);
+ if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
+ return result(this, obj);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ _.each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ return result(this, method.apply(this._wrapped, arguments));
+ };
+ });
+
+ // Extracts the result from a wrapped and chained object.
+ _.prototype.value = function() {
+ return this._wrapped;
+ };
+
+ // Provide unwrapping proxy for some methods used in engine operations
+ // such as arithmetic and JSON stringification.
+ _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
+
+ _.prototype.toString = function() {
+ return '' + this._wrapped;
+ };
+
+ // AMD registration happens at the end for compatibility with AMD loaders
+ // that may not enforce next-turn semantics on modules. Even though general
+ // practice for AMD registration is to be anonymous, underscore registers
+ // as a named module because, like jQuery, it is a base library that is
+ // popular enough to be bundled in a third party lib, but not be part of
+ // an AMD load request. Those cases could generate an error when an
+ // anonymous define() is called outside of a loader request.
+ if (typeof define === 'function' && define.amd) {
+ define('underscore', [], function() {
+ return _;
+ });
+ }
+}.call(this));
diff --git a/deployed/windwalker/media/windwalker/js/core/underscore.min.js b/deployed/windwalker/media/windwalker/js/core/underscore.min.js
new file mode 100644
index 00000000..11cb9651
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/core/underscore.min.js
@@ -0,0 +1 @@
+(function(){var root=this,previousUnderscore=root._,ArrayProto=Array.prototype,ObjProto=Object.prototype,FuncProto=Function.prototype,push=ArrayProto.push,slice=ArrayProto.slice,toString=ObjProto.toString,hasOwnProperty=ObjProto.hasOwnProperty,nativeIsArray=Array.isArray,nativeKeys=Object.keys,nativeBind=FuncProto.bind,nativeCreate=Object.create,Ctor=function(){},_=function(obj){if(obj instanceof _)return obj;if(!(this instanceof _))return new _(obj);this._wrapped=obj};if(typeof exports!=='undefined'){if(typeof module!=='undefined'&&module.exports)exports=module.exports=_;exports._=_}else root._=_;_.VERSION='1.8.3';var optimizeCb=function(func,context,argCount){if(context===void(0))return func;switch(argCount==null?3:argCount){case 1:return function(value){return func.call(context,value)};case 2:return function(value,other){return func.call(context,value,other)};case 3:return function(value,index,collection){return func.call(context,value,index,collection)};case 4:return function(accumulator,value,index,collection){return func.call(context,accumulator,value,index,collection)}};return function(){return func.apply(context,arguments)}},cb=function(value,context,argCount){if(value==null)return _.identity;if(_.isFunction(value))return optimizeCb(value,context,argCount);if(_.isObject(value))return _.matcher(value);return _.property(value)};_.iteratee=function(value,context){return cb(value,context,Infinity)};var createAssigner=function(keysFunc,undefinedOnly){return function(obj){var length=arguments.length;if(length<2||obj==null)return obj;for(var index=1;index=0&&length<=MAX_ARRAY_INDEX};_.each=_.forEach=function(obj,iteratee,context){iteratee=optimizeCb(iteratee,context);var i,length;if(isArrayLike(obj)){for(i=0,length=obj.length;i=0&&index0?0:length-1;if(arguments.length<3){memo=obj[keys?keys[index]:index];index+=dir};return iterator(obj,iteratee,memo,keys,index,length)}};_.reduce=_.foldl=_.inject=createReduce(1);_.reduceRight=_.foldr=createReduce(-1);_.find=_.detect=function(obj,predicate,context){var key;if(isArrayLike(obj)){key=_.findIndex(obj,predicate,context)}else key=_.findKey(obj,predicate,context);if(key!==void(0)&&key!==-1)return obj[key]};_.filter=_.select=function(obj,predicate,context){var results=[];predicate=cb(predicate,context);_.each(obj,function(value,index,list){if(predicate(value,index,list))results.push(value)});return results};_.reject=function(obj,predicate,context){return _.filter(obj,_.negate(cb(predicate)),context)};_.every=_.all=function(obj,predicate,context){predicate=cb(predicate,context);var keys=!isArrayLike(obj)&&_.keys(obj),length=(keys||obj).length;for(var index=0;index=0};_.invoke=function(obj,method){var args=slice.call(arguments,2),isFunc=_.isFunction(method);return _.map(obj,function(value){var func=isFunc?method:value[method];return func==null?func:func.apply(value,args)})};_.pluck=function(obj,key){return _.map(obj,_.property(key))};_.where=function(obj,attrs){return _.filter(obj,_.matcher(attrs))};_.findWhere=function(obj,attrs){return _.find(obj,_.matcher(attrs))};_.max=function(obj,iteratee,context){var result=-Infinity,lastComputed=-Infinity,value,computed;if(iteratee==null&&obj!=null){obj=isArrayLike(obj)?obj:_.values(obj);for(var i=0,length=obj.length;iresult)result=value}}else{iteratee=cb(iteratee,context);_.each(obj,function(value,index,list){computed=iteratee(value,index,list);if(computed>lastComputed||computed===-Infinity&&result===-Infinity){result=value;lastComputed=computed}})};return result};_.min=function(obj,iteratee,context){var result=Infinity,lastComputed=Infinity,value,computed;if(iteratee==null&&obj!=null){obj=isArrayLike(obj)?obj:_.values(obj);for(var i=0,length=obj.length;ib||a===void(0))return 1;if(a0?0:length-1;for(;index>=0&&index0){i=idx>=0?idx:Math.max(idx+length,i)}else length=idx>=0?Math.min(idx+1,length):idx+length+1}else if(sortedIndex&&idx&&length){idx=sortedIndex(array,item);return array[idx]===item?idx:-1};if(item!==item){idx=predicateFind(slice.call(array,i,length),_.isNaN);return idx>=0?idx+i:-1};for(idx=dir>0?i:length-1;idx>=0&&idxwait){if(timeout){clearTimeout(timeout);timeout=null};previous=now;result=func.apply(context,args);if(!timeout)context=args=null}else if(!timeout&&options.trailing!==false)timeout=setTimeout(later,remaining);return result}};_.debounce=function(func,wait,immediate){var timeout,args,context,timestamp,result,later=function(){var last=_.now()-timestamp;if(last=0){timeout=setTimeout(later,wait-last)}else{timeout=null;if(!immediate){result=func.apply(context,args);if(!timeout)context=args=null}}};return function(){context=this;args=arguments;timestamp=_.now();var callNow=immediate&&!timeout;if(!timeout)timeout=setTimeout(later,wait);if(callNow){result=func.apply(context,args);context=args=null};return result}};_.wrap=function(func,wrapper){return _.partial(wrapper,func)};_.negate=function(predicate){return function(){return!predicate.apply(this,arguments)}};_.compose=function(){var args=arguments,start=args.length-1;return function(){var i=start,result=args[start].apply(this,arguments);while(i--)result=args[i].call(this,result);return result}};_.after=function(times,func){return function(){if(--times<1)return func.apply(this,arguments)}};_.before=function(times,func){var memo;return function(){if(--times>0)memo=func.apply(this,arguments);if(times<=1)func=null;return memo}};_.once=_.partial(_.before,2);var hasEnumBug=!{toString:null}.propertyIsEnumerable('toString'),nonEnumerableProps=['valueOf','isPrototypeOf','toString','propertyIsEnumerable','hasOwnProperty','toLocaleString'];function collectNonEnumProps(obj,keys){var nonEnumIdx=nonEnumerableProps.length,constructor=obj.constructor,proto=(_.isFunction(constructor)&&constructor.prototype)||ObjProto,prop='constructor';if(_.has(obj,prop)&&!_.contains(keys,prop))keys.push(prop);while(nonEnumIdx--){prop=nonEnumerableProps[nonEnumIdx];if(prop in obj&&obj[prop]!==proto[prop]&&!_.contains(keys,prop))keys.push(prop)}};_.keys=function(obj){if(!_.isObject(obj))return[];if(nativeKeys)return nativeKeys(obj);var keys=[];for(var key in obj)if(_.has(obj,key))keys.push(key);if(hasEnumBug)collectNonEnumProps(obj,keys);return keys};_.allKeys=function(obj){if(!_.isObject(obj))return[];var keys=[];for(var key in obj)keys.push(key);if(hasEnumBug)collectNonEnumProps(obj,keys);return keys};_.values=function(obj){var keys=_.keys(obj),length=keys.length,values=Array(length);for(var i=0;i':'>','"':'"',"'":''','`':'`'},unescapeMap=_.invert(escapeMap),createEscaper=function(map){var escaper=function(match){return map[match]},source='(?:'+_.keys(map).join('|')+')',testRegexp=RegExp(source),replaceRegexp=RegExp(source,'g');return function(string){string=string==null?'':''+string;return testRegexp.test(string)?string.replace(replaceRegexp,escaper):string}};_.escape=createEscaper(escapeMap);_.unescape=createEscaper(unescapeMap);_.result=function(object,property,fallback){var value=object==null?void(0):object[property];if(value===void(0))value=fallback;return _.isFunction(value)?value.call(object):value};var idCounter=0;_.uniqueId=function(prefix){var id=++idCounter+'';return prefix?prefix+id:id};_.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var noMatch=/(.)^/,escapes={"'":"'",'\\':'\\','\r':'r','\n':'n','\u2028':'u2028','\u2029':'u2029'},escaper=/\\|'|\r|\n|\u2028|\u2029/g,escapeChar=function(match){return'\\'+escapes[match]};_.template=function(text,settings,oldSettings){if(!settings&&oldSettings)settings=oldSettings;settings=_.defaults({},settings,_.templateSettings);var matcher=RegExp([(settings.escape||noMatch).source,(settings.interpolate||noMatch).source,(settings.evaluate||noMatch).source].join('|')+'|$','g'),index=0,source="__p+='";text.replace(matcher,function(match,escape,interpolate,evaluate,offset){source+=text.slice(index,offset).replace(escaper,escapeChar);index=offset+match.length;if(escape){source+="'+\n((__t=("+escape+"))==null?'':_.escape(__t))+\n'"}else if(interpolate){source+="'+\n((__t=("+interpolate+"))==null?'':__t)+\n'"}else if(evaluate)source+="';\n"+evaluate+"\n__p+='";return match});source+="';\n";if(!settings.variable)source='with(obj||{}){\n'+source+'}\n';source="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+source+'return __p;\n';try{var render=new Function(settings.variable||'obj','_',source)}catch(e){e.source=source;throw e};var template=function(data){return render.call(this,data,_)},argument=settings.variable||'obj';template.source='function('+argument+'){\n'+source+'}';return template};_.chain=function(obj){var instance=_(obj);instance._chain=true;return instance};var result=function(instance,obj){return instance._chain?_(obj).chain():obj};_.mixin=function(obj){_.each(_.functions(obj),function(name){var func=_[name]=obj[name];_.prototype[name]=function(){var args=[this._wrapped];push.apply(args,arguments);return result(this,func.apply(_,args))}})};_.mixin(_);_.each(['pop','push','reverse','shift','sort','splice','unshift'],function(name){var method=ArrayProto[name];_.prototype[name]=function(){var obj=this._wrapped;method.apply(obj,arguments);if((name==='shift'||name==='splice')&&obj.length===0)delete obj[0];return result(this,obj)}});_.each(['concat','join','slice'],function(name){var method=ArrayProto[name];_.prototype[name]=function(){return result(this,method.apply(this._wrapped,arguments))}});_.prototype.value=function(){return this._wrapped};_.prototype.valueOf=_.prototype.toJSON=_.prototype.value;_.prototype.toString=function(){return''+this._wrapped};if(typeof define==='function'&&define.amd)define('underscore',[],function(){return _})}.call(this))
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/core/underscore.string.js b/deployed/windwalker/media/windwalker/js/core/underscore.string.js
new file mode 100644
index 00000000..70ded80b
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/core/underscore.string.js
@@ -0,0 +1,1179 @@
+/* underscore.string 3.2.1 | MIT licensed | http://epeli.github.com/underscore.string/ */
+
+!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.s=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 ? str.match(new RegExp('.{1,' + step + '}', 'g')) : [str];
+};
+
+},{}],5:[function(_dereq_,module,exports){
+var capitalize = _dereq_('./capitalize');
+var camelize = _dereq_('./camelize');
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function classify(str) {
+ str = makeString(str);
+ return capitalize(camelize(str.replace(/[\W_]/g, ' ')).replace(/\s/g, ''));
+};
+
+},{"./camelize":1,"./capitalize":2,"./helper/makeString":21}],6:[function(_dereq_,module,exports){
+var trim = _dereq_('./trim');
+
+module.exports = function clean(str) {
+ return trim(str).replace(/\s\s+/g, ' ');
+};
+
+},{"./trim":62}],7:[function(_dereq_,module,exports){
+
+var makeString = _dereq_('./helper/makeString');
+
+var from = "ąàáäâãåæăćčĉęèéëêĝĥìíïîĵłľńňòóöőôõðøśșšŝťțŭùúüűûñÿýçżźž",
+ to = "aaaaaaaaaccceeeeeghiiiijllnnoooooooossssttuuuuuunyyczzz";
+
+from += from.toUpperCase();
+to += to.toUpperCase();
+
+module.exports = function cleanDiacritics(str) {
+ return makeString(str).replace(/.{1}/g, function(c){
+ var index = from.indexOf(c);
+ return index === -1 ? c : to.charAt(index);
+ });
+};
+
+},{"./helper/makeString":21}],8:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function(str, substr) {
+ str = makeString(str);
+ substr = makeString(substr);
+
+ if (str.length === 0 || substr.length === 0) return 0;
+
+ return str.split(substr).length - 1;
+};
+
+},{"./helper/makeString":21}],9:[function(_dereq_,module,exports){
+var trim = _dereq_('./trim');
+
+module.exports = function dasherize(str) {
+ return trim(str).replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();
+};
+
+},{"./trim":62}],10:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function decapitalize(str) {
+ str = makeString(str);
+ return str.charAt(0).toLowerCase() + str.slice(1);
+};
+
+},{"./helper/makeString":21}],11:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+function getIndent(str) {
+ var matches = str.match(/^[\s\\t]*/gm);
+ var indent = matches[0].length;
+
+ for (var i = 1; i < matches.length; i++) {
+ indent = Math.min(matches[i].length, indent);
+ }
+
+ return indent;
+}
+
+module.exports = function dedent(str, pattern) {
+ str = makeString(str);
+ var indent = getIndent(str);
+ var reg;
+
+ if (indent === 0) return str;
+
+ if (typeof pattern === 'string') {
+ reg = new RegExp('^' + pattern, 'gm');
+ } else {
+ reg = new RegExp('^[ \\t]{' + indent + '}', 'gm');
+ }
+
+ return str.replace(reg, '');
+};
+
+},{"./helper/makeString":21}],12:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+var toPositive = _dereq_('./helper/toPositive');
+
+module.exports = function endsWith(str, ends, position) {
+ str = makeString(str);
+ ends = '' + ends;
+ if (typeof position == 'undefined') {
+ position = str.length - ends.length;
+ } else {
+ position = Math.min(toPositive(position), str.length) - ends.length;
+ }
+ return position >= 0 && str.indexOf(ends, position) === position;
+};
+
+},{"./helper/makeString":21,"./helper/toPositive":23}],13:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+var escapeChars = _dereq_('./helper/escapeChars');
+var reversedEscapeChars = {};
+
+var regexString = "[";
+for(var key in escapeChars) {
+ regexString += key;
+}
+regexString += "]";
+
+var regex = new RegExp( regexString, 'g');
+
+module.exports = function escapeHTML(str) {
+
+ return makeString(str).replace(regex, function(m) {
+ return '&' + escapeChars[m] + ';';
+ });
+};
+
+},{"./helper/escapeChars":18,"./helper/makeString":21}],14:[function(_dereq_,module,exports){
+module.exports = function() {
+ var result = {};
+
+ for (var prop in this) {
+ if (!this.hasOwnProperty(prop) || prop.match(/^(?:include|contains|reverse|join)$/)) continue;
+ result[prop] = this[prop];
+ }
+
+ return result;
+};
+
+},{}],15:[function(_dereq_,module,exports){
+// Underscore.string
+// (c) 2010 Esa-Matti Suuronen
+// Underscore.string is freely distributable under the terms of the MIT license.
+// Documentation: https://github.com/epeli/underscore.string
+// Some code is borrowed from MooTools and Alexandru Marasteanu.
+// Version '3.2.1'
+
+'use strict';
+
+function s(value) {
+ /* jshint validthis: true */
+ if (!(this instanceof s)) return new s(value);
+ this._wrapped = value;
+}
+
+s.VERSION = '3.2.1';
+
+s.isBlank = _dereq_('./isBlank');
+s.stripTags = _dereq_('./stripTags');
+s.capitalize = _dereq_('./capitalize');
+s.decapitalize = _dereq_('./decapitalize');
+s.chop = _dereq_('./chop');
+s.trim = _dereq_('./trim');
+s.clean = _dereq_('./clean');
+s.cleanDiacritics = _dereq_('./cleanDiacritics');
+s.count = _dereq_('./count');
+s.chars = _dereq_('./chars');
+s.swapCase = _dereq_('./swapCase');
+s.escapeHTML = _dereq_('./escapeHTML');
+s.unescapeHTML = _dereq_('./unescapeHTML');
+s.splice = _dereq_('./splice');
+s.insert = _dereq_('./insert');
+s.replaceAll = _dereq_('./replaceAll');
+s.include = _dereq_('./include');
+s.join = _dereq_('./join');
+s.lines = _dereq_('./lines');
+s.dedent = _dereq_('./dedent');
+s.reverse = _dereq_('./reverse');
+s.startsWith = _dereq_('./startsWith');
+s.endsWith = _dereq_('./endsWith');
+s.pred = _dereq_('./pred');
+s.succ = _dereq_('./succ');
+s.titleize = _dereq_('./titleize');
+s.camelize = _dereq_('./camelize');
+s.underscored = _dereq_('./underscored');
+s.dasherize = _dereq_('./dasherize');
+s.classify = _dereq_('./classify');
+s.humanize = _dereq_('./humanize');
+s.ltrim = _dereq_('./ltrim');
+s.rtrim = _dereq_('./rtrim');
+s.truncate = _dereq_('./truncate');
+s.prune = _dereq_('./prune');
+s.words = _dereq_('./words');
+s.pad = _dereq_('./pad');
+s.lpad = _dereq_('./lpad');
+s.rpad = _dereq_('./rpad');
+s.lrpad = _dereq_('./lrpad');
+s.sprintf = _dereq_('./sprintf');
+s.vsprintf = _dereq_('./vsprintf');
+s.toNumber = _dereq_('./toNumber');
+s.numberFormat = _dereq_('./numberFormat');
+s.strRight = _dereq_('./strRight');
+s.strRightBack = _dereq_('./strRightBack');
+s.strLeft = _dereq_('./strLeft');
+s.strLeftBack = _dereq_('./strLeftBack');
+s.toSentence = _dereq_('./toSentence');
+s.toSentenceSerial = _dereq_('./toSentenceSerial');
+s.slugify = _dereq_('./slugify');
+s.surround = _dereq_('./surround');
+s.quote = _dereq_('./quote');
+s.unquote = _dereq_('./unquote');
+s.repeat = _dereq_('./repeat');
+s.naturalCmp = _dereq_('./naturalCmp');
+s.levenshtein = _dereq_('./levenshtein');
+s.toBoolean = _dereq_('./toBoolean');
+s.exports = _dereq_('./exports');
+s.escapeRegExp = _dereq_('./helper/escapeRegExp');
+s.wrap = _dereq_('./wrap');
+
+// Aliases
+s.strip = s.trim;
+s.lstrip = s.ltrim;
+s.rstrip = s.rtrim;
+s.center = s.lrpad;
+s.rjust = s.lpad;
+s.ljust = s.rpad;
+s.contains = s.include;
+s.q = s.quote;
+s.toBool = s.toBoolean;
+s.camelcase = s.camelize;
+
+
+// Implement chaining
+s.prototype = {
+ value: function value() {
+ return this._wrapped;
+ }
+};
+
+function fn2method(key, fn) {
+ if (typeof fn !== "function") return;
+ s.prototype[key] = function() {
+ var args = [this._wrapped].concat(Array.prototype.slice.call(arguments));
+ var res = fn.apply(null, args);
+ // if the result is non-string stop the chain and return the value
+ return typeof res === 'string' ? new s(res) : res;
+ };
+}
+
+// Copy functions to instance methods for chaining
+for (var key in s) fn2method(key, s[key]);
+
+fn2method("tap", function tap(string, fn) {
+ return fn(string);
+});
+
+function prototype2method(methodName) {
+ fn2method(methodName, function(context) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return String.prototype[methodName].apply(context, args);
+ });
+}
+
+var prototypeMethods = [
+ "toUpperCase",
+ "toLowerCase",
+ "split",
+ "replace",
+ "slice",
+ "substring",
+ "substr",
+ "concat"
+];
+
+for (var key in prototypeMethods) prototype2method(prototypeMethods[key]);
+
+
+module.exports = s;
+
+},{"./camelize":1,"./capitalize":2,"./chars":3,"./chop":4,"./classify":5,"./clean":6,"./cleanDiacritics":7,"./count":8,"./dasherize":9,"./decapitalize":10,"./dedent":11,"./endsWith":12,"./escapeHTML":13,"./exports":14,"./helper/escapeRegExp":19,"./humanize":24,"./include":25,"./insert":26,"./isBlank":27,"./join":28,"./levenshtein":29,"./lines":30,"./lpad":31,"./lrpad":32,"./ltrim":33,"./naturalCmp":34,"./numberFormat":35,"./pad":36,"./pred":37,"./prune":38,"./quote":39,"./repeat":40,"./replaceAll":41,"./reverse":42,"./rpad":43,"./rtrim":44,"./slugify":45,"./splice":46,"./sprintf":47,"./startsWith":48,"./strLeft":49,"./strLeftBack":50,"./strRight":51,"./strRightBack":52,"./stripTags":53,"./succ":54,"./surround":55,"./swapCase":56,"./titleize":57,"./toBoolean":58,"./toNumber":59,"./toSentence":60,"./toSentenceSerial":61,"./trim":62,"./truncate":63,"./underscored":64,"./unescapeHTML":65,"./unquote":66,"./vsprintf":67,"./words":68,"./wrap":69}],16:[function(_dereq_,module,exports){
+var makeString = _dereq_('./makeString');
+
+module.exports = function adjacent(str, direction) {
+ str = makeString(str);
+ if (str.length === 0) {
+ return '';
+ }
+ return str.slice(0, -1) + String.fromCharCode(str.charCodeAt(str.length - 1) + direction);
+};
+
+},{"./makeString":21}],17:[function(_dereq_,module,exports){
+var escapeRegExp = _dereq_('./escapeRegExp');
+
+module.exports = function defaultToWhiteSpace(characters) {
+ if (characters == null)
+ return '\\s';
+ else if (characters.source)
+ return characters.source;
+ else
+ return '[' + escapeRegExp(characters) + ']';
+};
+
+},{"./escapeRegExp":19}],18:[function(_dereq_,module,exports){
+/* We're explicitly defining the list of entities we want to escape.
+nbsp is an HTML entity, but we don't want to escape all space characters in a string, hence its omission in this map.
+
+*/
+var escapeChars = {
+ '¢' : 'cent',
+ '£' : 'pound',
+ '¥' : 'yen',
+ '€': 'euro',
+ '©' :'copy',
+ '®' : 'reg',
+ '<' : 'lt',
+ '>' : 'gt',
+ '"' : 'quot',
+ '&' : 'amp',
+ "'": '#39'
+};
+
+module.exports = escapeChars;
+
+},{}],19:[function(_dereq_,module,exports){
+var makeString = _dereq_('./makeString');
+
+module.exports = function escapeRegExp(str) {
+ return makeString(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+},{"./makeString":21}],20:[function(_dereq_,module,exports){
+/*
+We're explicitly defining the list of entities that might see in escape HTML strings
+*/
+var htmlEntities = {
+ nbsp: ' ',
+ cent: '¢',
+ pound: '£',
+ yen: '¥',
+ euro: '€',
+ copy: '©',
+ reg: '®',
+ lt: '<',
+ gt: '>',
+ quot: '"',
+ amp: '&',
+ apos: "'"
+};
+
+module.exports = htmlEntities;
+
+},{}],21:[function(_dereq_,module,exports){
+/**
+ * Ensure some object is a coerced to a string
+ **/
+module.exports = function makeString(object) {
+ if (object == null) return '';
+ return '' + object;
+};
+
+},{}],22:[function(_dereq_,module,exports){
+module.exports = function strRepeat(str, qty){
+ if (qty < 1) return '';
+ var result = '';
+ while (qty > 0) {
+ if (qty & 1) result += str;
+ qty >>= 1, str += str;
+ }
+ return result;
+};
+
+},{}],23:[function(_dereq_,module,exports){
+module.exports = function toPositive(number) {
+ return number < 0 ? 0 : (+number || 0);
+};
+
+},{}],24:[function(_dereq_,module,exports){
+var capitalize = _dereq_('./capitalize');
+var underscored = _dereq_('./underscored');
+var trim = _dereq_('./trim');
+
+module.exports = function humanize(str) {
+ return capitalize(trim(underscored(str).replace(/_id$/, '').replace(/_/g, ' ')));
+};
+
+},{"./capitalize":2,"./trim":62,"./underscored":64}],25:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function include(str, needle) {
+ if (needle === '') return true;
+ return makeString(str).indexOf(needle) !== -1;
+};
+
+},{"./helper/makeString":21}],26:[function(_dereq_,module,exports){
+var splice = _dereq_('./splice');
+
+module.exports = function insert(str, i, substr) {
+ return splice(str, i, 0, substr);
+};
+
+},{"./splice":46}],27:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function isBlank(str) {
+ return (/^\s*$/).test(makeString(str));
+};
+
+},{"./helper/makeString":21}],28:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+var slice = [].slice;
+
+module.exports = function join() {
+ var args = slice.call(arguments),
+ separator = args.shift();
+
+ return args.join(makeString(separator));
+};
+
+},{"./helper/makeString":21}],29:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+/**
+ * Based on the implementation here: https://github.com/hiddentao/fast-levenshtein
+ */
+module.exports = function levenshtein(str1, str2) {
+ 'use strict';
+ str1 = makeString(str1);
+ str2 = makeString(str2);
+
+ // Short cut cases
+ if (str1 === str2) return 0;
+ if (!str1 || !str2) return Math.max(str1.length, str2.length);
+
+ // two rows
+ var prevRow = new Array(str2.length + 1);
+
+ // initialise previous row
+ for (var i = 0; i < prevRow.length; ++i) {
+ prevRow[i] = i;
+ }
+
+ // calculate current row distance from previous row
+ for (i = 0; i < str1.length; ++i) {
+ var nextCol = i + 1;
+
+ for (var j = 0; j < str2.length; ++j) {
+ var curCol = nextCol;
+
+ // substution
+ nextCol = prevRow[j] + ( (str1.charAt(i) === str2.charAt(j)) ? 0 : 1 );
+ // insertion
+ var tmp = curCol + 1;
+ if (nextCol > tmp) {
+ nextCol = tmp;
+ }
+ // deletion
+ tmp = prevRow[j + 1] + 1;
+ if (nextCol > tmp) {
+ nextCol = tmp;
+ }
+
+ // copy current col value into previous (in preparation for next iteration)
+ prevRow[j] = curCol;
+ }
+
+ // copy last col value into previous (in preparation for next iteration)
+ prevRow[j] = nextCol;
+ }
+
+ return nextCol;
+};
+
+},{"./helper/makeString":21}],30:[function(_dereq_,module,exports){
+module.exports = function lines(str) {
+ if (str == null) return [];
+ return String(str).split(/\r\n?|\n/);
+};
+
+},{}],31:[function(_dereq_,module,exports){
+var pad = _dereq_('./pad');
+
+module.exports = function lpad(str, length, padStr) {
+ return pad(str, length, padStr);
+};
+
+},{"./pad":36}],32:[function(_dereq_,module,exports){
+var pad = _dereq_('./pad');
+
+module.exports = function lrpad(str, length, padStr) {
+ return pad(str, length, padStr, 'both');
+};
+
+},{"./pad":36}],33:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+var defaultToWhiteSpace = _dereq_('./helper/defaultToWhiteSpace');
+var nativeTrimLeft = String.prototype.trimLeft;
+
+module.exports = function ltrim(str, characters) {
+ str = makeString(str);
+ if (!characters && nativeTrimLeft) return nativeTrimLeft.call(str);
+ characters = defaultToWhiteSpace(characters);
+ return str.replace(new RegExp('^' + characters + '+'), '');
+};
+
+},{"./helper/defaultToWhiteSpace":17,"./helper/makeString":21}],34:[function(_dereq_,module,exports){
+module.exports = function naturalCmp(str1, str2) {
+ if (str1 == str2) return 0;
+ if (!str1) return -1;
+ if (!str2) return 1;
+
+ var cmpRegex = /(\.\d+|\d+|\D+)/g,
+ tokens1 = String(str1).match(cmpRegex),
+ tokens2 = String(str2).match(cmpRegex),
+ count = Math.min(tokens1.length, tokens2.length);
+
+ for (var i = 0; i < count; i++) {
+ var a = tokens1[i],
+ b = tokens2[i];
+
+ if (a !== b) {
+ var num1 = +a;
+ var num2 = +b;
+ if (num1 === num1 && num2 === num2) {
+ return num1 > num2 ? 1 : -1;
+ }
+ return a < b ? -1 : 1;
+ }
+ }
+
+ if (tokens1.length != tokens2.length)
+ return tokens1.length - tokens2.length;
+
+ return str1 < str2 ? -1 : 1;
+};
+
+},{}],35:[function(_dereq_,module,exports){
+module.exports = function numberFormat(number, dec, dsep, tsep) {
+ if (isNaN(number) || number == null) return '';
+
+ number = number.toFixed(~~dec);
+ tsep = typeof tsep == 'string' ? tsep : ',';
+
+ var parts = number.split('.'),
+ fnums = parts[0],
+ decimals = parts[1] ? (dsep || '.') + parts[1] : '';
+
+ return fnums.replace(/(\d)(?=(?:\d{3})+$)/g, '$1' + tsep) + decimals;
+};
+
+},{}],36:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+var strRepeat = _dereq_('./helper/strRepeat');
+
+module.exports = function pad(str, length, padStr, type) {
+ str = makeString(str);
+ length = ~~length;
+
+ var padlen = 0;
+
+ if (!padStr)
+ padStr = ' ';
+ else if (padStr.length > 1)
+ padStr = padStr.charAt(0);
+
+ switch (type) {
+ case 'right':
+ padlen = length - str.length;
+ return str + strRepeat(padStr, padlen);
+ case 'both':
+ padlen = length - str.length;
+ return strRepeat(padStr, Math.ceil(padlen / 2)) + str + strRepeat(padStr, Math.floor(padlen / 2));
+ default: // 'left'
+ padlen = length - str.length;
+ return strRepeat(padStr, padlen) + str;
+ }
+};
+
+},{"./helper/makeString":21,"./helper/strRepeat":22}],37:[function(_dereq_,module,exports){
+var adjacent = _dereq_('./helper/adjacent');
+
+module.exports = function succ(str) {
+ return adjacent(str, -1);
+};
+
+},{"./helper/adjacent":16}],38:[function(_dereq_,module,exports){
+/**
+ * _s.prune: a more elegant version of truncate
+ * prune extra chars, never leaving a half-chopped word.
+ * @author github.com/rwz
+ */
+var makeString = _dereq_('./helper/makeString');
+var rtrim = _dereq_('./rtrim');
+
+module.exports = function prune(str, length, pruneStr) {
+ str = makeString(str);
+ length = ~~length;
+ pruneStr = pruneStr != null ? String(pruneStr) : '...';
+
+ if (str.length <= length) return str;
+
+ var tmpl = function(c) {
+ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' ';
+ },
+ template = str.slice(0, length + 1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA'
+
+ if (template.slice(template.length - 2).match(/\w\w/))
+ template = template.replace(/\s*\S+$/, '');
+ else
+ template = rtrim(template.slice(0, template.length - 1));
+
+ return (template + pruneStr).length > str.length ? str : str.slice(0, template.length) + pruneStr;
+};
+
+},{"./helper/makeString":21,"./rtrim":44}],39:[function(_dereq_,module,exports){
+var surround = _dereq_('./surround');
+
+module.exports = function quote(str, quoteChar) {
+ return surround(str, quoteChar || '"');
+};
+
+},{"./surround":55}],40:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+var strRepeat = _dereq_('./helper/strRepeat');
+
+module.exports = function repeat(str, qty, separator) {
+ str = makeString(str);
+
+ qty = ~~qty;
+
+ // using faster implementation if separator is not needed;
+ if (separator == null) return strRepeat(str, qty);
+
+ // this one is about 300x slower in Google Chrome
+ for (var repeat = []; qty > 0; repeat[--qty] = str) {}
+ return repeat.join(separator);
+};
+
+},{"./helper/makeString":21,"./helper/strRepeat":22}],41:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function replaceAll(str, find, replace, ignorecase) {
+ var flags = (ignorecase === true)?'gi':'g';
+ var reg = new RegExp(find, flags);
+
+ return makeString(str).replace(reg, replace);
+};
+
+},{"./helper/makeString":21}],42:[function(_dereq_,module,exports){
+var chars = _dereq_('./chars');
+
+module.exports = function reverse(str) {
+ return chars(str).reverse().join('');
+};
+
+},{"./chars":3}],43:[function(_dereq_,module,exports){
+var pad = _dereq_('./pad');
+
+module.exports = function rpad(str, length, padStr) {
+ return pad(str, length, padStr, 'right');
+};
+
+},{"./pad":36}],44:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+var defaultToWhiteSpace = _dereq_('./helper/defaultToWhiteSpace');
+var nativeTrimRight = String.prototype.trimRight;
+
+module.exports = function rtrim(str, characters) {
+ str = makeString(str);
+ if (!characters && nativeTrimRight) return nativeTrimRight.call(str);
+ characters = defaultToWhiteSpace(characters);
+ return str.replace(new RegExp(characters + '+$'), '');
+};
+
+},{"./helper/defaultToWhiteSpace":17,"./helper/makeString":21}],45:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+var defaultToWhiteSpace = _dereq_('./helper/defaultToWhiteSpace');
+var trim = _dereq_('./trim');
+var dasherize = _dereq_('./dasherize');
+var cleanDiacritics = _dereq_("./cleanDiacritics");
+
+module.exports = function slugify(str) {
+ return trim(dasherize(cleanDiacritics(str).replace(/[^\w\s-]/g, '-')), '-');
+};
+
+},{"./cleanDiacritics":7,"./dasherize":9,"./helper/defaultToWhiteSpace":17,"./helper/makeString":21,"./trim":62}],46:[function(_dereq_,module,exports){
+var chars = _dereq_('./chars');
+
+module.exports = function splice(str, i, howmany, substr) {
+ var arr = chars(str);
+ arr.splice(~~i, ~~howmany, substr);
+ return arr.join('');
+};
+
+},{"./chars":3}],47:[function(_dereq_,module,exports){
+// sprintf() for JavaScript 0.7-beta1
+// http://www.diveintojavascript.com/projects/javascript-sprintf
+//
+// Copyright (c) Alexandru Marasteanu
+// All rights reserved.
+var strRepeat = _dereq_('./helper/strRepeat');
+var toString = Object.prototype.toString;
+var sprintf = (function() {
+ function get_type(variable) {
+ return toString.call(variable).slice(8, -1).toLowerCase();
+ }
+
+ var str_repeat = strRepeat;
+
+ var str_format = function() {
+ if (!str_format.cache.hasOwnProperty(arguments[0])) {
+ str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
+ }
+ return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
+ };
+
+ str_format.format = function(parse_tree, argv) {
+ var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
+ for (i = 0; i < tree_length; i++) {
+ node_type = get_type(parse_tree[i]);
+ if (node_type === 'string') {
+ output.push(parse_tree[i]);
+ }
+ else if (node_type === 'array') {
+ match = parse_tree[i]; // convenience purposes only
+ if (match[2]) { // keyword argument
+ arg = argv[cursor];
+ for (k = 0; k < match[2].length; k++) {
+ if (!arg.hasOwnProperty(match[2][k])) {
+ throw new Error(sprintf('[_.sprintf] property "%s" does not exist', match[2][k]));
+ }
+ arg = arg[match[2][k]];
+ }
+ } else if (match[1]) { // positional argument (explicit)
+ arg = argv[match[1]];
+ }
+ else { // positional argument (implicit)
+ arg = argv[cursor++];
+ }
+
+ if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
+ throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));
+ }
+ switch (match[8]) {
+ case 'b': arg = arg.toString(2); break;
+ case 'c': arg = String.fromCharCode(arg); break;
+ case 'd': arg = parseInt(arg, 10); break;
+ case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
+ case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
+ case 'o': arg = arg.toString(8); break;
+ case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
+ case 'u': arg = Math.abs(arg); break;
+ case 'x': arg = arg.toString(16); break;
+ case 'X': arg = arg.toString(16).toUpperCase(); break;
+ }
+ arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
+ pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
+ pad_length = match[6] - String(arg).length;
+ pad = match[6] ? str_repeat(pad_character, pad_length) : '';
+ output.push(match[5] ? arg + pad : pad + arg);
+ }
+ }
+ return output.join('');
+ };
+
+ str_format.cache = {};
+
+ str_format.parse = function(fmt) {
+ var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
+ while (_fmt) {
+ if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
+ parse_tree.push(match[0]);
+ }
+ else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
+ parse_tree.push('%');
+ }
+ else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
+ if (match[2]) {
+ arg_names |= 1;
+ var field_list = [], replacement_field = match[2], field_match = [];
+ if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
+ field_list.push(field_match[1]);
+ while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
+ if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
+ field_list.push(field_match[1]);
+ }
+ else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
+ field_list.push(field_match[1]);
+ }
+ else {
+ throw new Error('[_.sprintf] huh?');
+ }
+ }
+ }
+ else {
+ throw new Error('[_.sprintf] huh?');
+ }
+ match[2] = field_list;
+ }
+ else {
+ arg_names |= 2;
+ }
+ if (arg_names === 3) {
+ throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported');
+ }
+ parse_tree.push(match);
+ }
+ else {
+ throw new Error('[_.sprintf] huh?');
+ }
+ _fmt = _fmt.substring(match[0].length);
+ }
+ return parse_tree;
+ };
+
+ return str_format;
+})();
+
+module.exports = sprintf;
+
+},{"./helper/strRepeat":22}],48:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+var toPositive = _dereq_('./helper/toPositive');
+
+module.exports = function startsWith(str, starts, position) {
+ str = makeString(str);
+ starts = '' + starts;
+ position = position == null ? 0 : Math.min(toPositive(position), str.length);
+ return str.lastIndexOf(starts, position) === position;
+};
+
+},{"./helper/makeString":21,"./helper/toPositive":23}],49:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function strLeft(str, sep) {
+ str = makeString(str);
+ sep = makeString(sep);
+ var pos = !sep ? -1 : str.indexOf(sep);
+ return~ pos ? str.slice(0, pos) : str;
+};
+
+},{"./helper/makeString":21}],50:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function strLeftBack(str, sep) {
+ str = makeString(str);
+ sep = makeString(sep);
+ var pos = str.lastIndexOf(sep);
+ return~ pos ? str.slice(0, pos) : str;
+};
+
+},{"./helper/makeString":21}],51:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function strRight(str, sep) {
+ str = makeString(str);
+ sep = makeString(sep);
+ var pos = !sep ? -1 : str.indexOf(sep);
+ return~ pos ? str.slice(pos + sep.length, str.length) : str;
+};
+
+},{"./helper/makeString":21}],52:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function strRightBack(str, sep) {
+ str = makeString(str);
+ sep = makeString(sep);
+ var pos = !sep ? -1 : str.lastIndexOf(sep);
+ return~ pos ? str.slice(pos + sep.length, str.length) : str;
+};
+
+},{"./helper/makeString":21}],53:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function stripTags(str) {
+ return makeString(str).replace(/<\/?[^>]+>/g, '');
+};
+
+},{"./helper/makeString":21}],54:[function(_dereq_,module,exports){
+var adjacent = _dereq_('./helper/adjacent');
+
+module.exports = function succ(str) {
+ return adjacent(str, 1);
+};
+
+},{"./helper/adjacent":16}],55:[function(_dereq_,module,exports){
+module.exports = function surround(str, wrapper) {
+ return [wrapper, str, wrapper].join('');
+};
+
+},{}],56:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function swapCase(str) {
+ return makeString(str).replace(/\S/g, function(c) {
+ return c === c.toUpperCase() ? c.toLowerCase() : c.toUpperCase();
+ });
+};
+
+},{"./helper/makeString":21}],57:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function titleize(str) {
+ return makeString(str).toLowerCase().replace(/(?:^|\s|-)\S/g, function(c) {
+ return c.toUpperCase();
+ });
+};
+
+},{"./helper/makeString":21}],58:[function(_dereq_,module,exports){
+var trim = _dereq_('./trim');
+
+function boolMatch(s, matchers) {
+ var i, matcher, down = s.toLowerCase();
+ matchers = [].concat(matchers);
+ for (i = 0; i < matchers.length; i += 1) {
+ matcher = matchers[i];
+ if (!matcher) continue;
+ if (matcher.test && matcher.test(s)) return true;
+ if (matcher.toLowerCase() === down) return true;
+ }
+}
+
+module.exports = function toBoolean(str, trueValues, falseValues) {
+ if (typeof str === "number") str = "" + str;
+ if (typeof str !== "string") return !!str;
+ str = trim(str);
+ if (boolMatch(str, trueValues || ["true", "1"])) return true;
+ if (boolMatch(str, falseValues || ["false", "0"])) return false;
+};
+
+},{"./trim":62}],59:[function(_dereq_,module,exports){
+var trim = _dereq_('./trim');
+
+module.exports = function toNumber(num, precision) {
+ if (num == null) return 0;
+ var factor = Math.pow(10, isFinite(precision) ? precision : 0);
+ return Math.round(num * factor) / factor;
+};
+
+},{"./trim":62}],60:[function(_dereq_,module,exports){
+var rtrim = _dereq_('./rtrim');
+
+module.exports = function toSentence(array, separator, lastSeparator, serial) {
+ separator = separator || ', ';
+ lastSeparator = lastSeparator || ' and ';
+ var a = array.slice(),
+ lastMember = a.pop();
+
+ if (array.length > 2 && serial) lastSeparator = rtrim(separator) + lastSeparator;
+
+ return a.length ? a.join(separator) + lastSeparator + lastMember : lastMember;
+};
+
+},{"./rtrim":44}],61:[function(_dereq_,module,exports){
+var toSentence = _dereq_('./toSentence');
+
+module.exports = function toSentenceSerial(array, sep, lastSep) {
+ return toSentence(array, sep, lastSep, true);
+};
+
+},{"./toSentence":60}],62:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+var defaultToWhiteSpace = _dereq_('./helper/defaultToWhiteSpace');
+var nativeTrim = String.prototype.trim;
+
+module.exports = function trim(str, characters) {
+ str = makeString(str);
+ if (!characters && nativeTrim) return nativeTrim.call(str);
+ characters = defaultToWhiteSpace(characters);
+ return str.replace(new RegExp('^' + characters + '+|' + characters + '+$', 'g'), '');
+};
+
+},{"./helper/defaultToWhiteSpace":17,"./helper/makeString":21}],63:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+
+module.exports = function truncate(str, length, truncateStr) {
+ str = makeString(str);
+ truncateStr = truncateStr || '...';
+ length = ~~length;
+ return str.length > length ? str.slice(0, length) + truncateStr : str;
+};
+
+},{"./helper/makeString":21}],64:[function(_dereq_,module,exports){
+var trim = _dereq_('./trim');
+
+module.exports = function underscored(str) {
+ return trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
+};
+
+},{"./trim":62}],65:[function(_dereq_,module,exports){
+var makeString = _dereq_('./helper/makeString');
+var htmlEntities = _dereq_('./helper/htmlEntities');
+
+module.exports = function unescapeHTML(str) {
+ return makeString(str).replace(/\&([^;]+);/g, function(entity, entityCode) {
+ var match;
+
+ if (entityCode in htmlEntities) {
+ return htmlEntities[entityCode];
+ } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
+ return String.fromCharCode(parseInt(match[1], 16));
+ } else if (match = entityCode.match(/^#(\d+)$/)) {
+ return String.fromCharCode(~~match[1]);
+ } else {
+ return entity;
+ }
+ });
+};
+
+},{"./helper/htmlEntities":20,"./helper/makeString":21}],66:[function(_dereq_,module,exports){
+module.exports = function unquote(str, quoteChar) {
+ quoteChar = quoteChar || '"';
+ if (str[0] === quoteChar && str[str.length - 1] === quoteChar)
+ return str.slice(1, str.length - 1);
+ else return str;
+};
+
+},{}],67:[function(_dereq_,module,exports){
+var sprintf = _dereq_('./sprintf');
+
+module.exports = function vsprintf(fmt, argv) {
+ argv.unshift(fmt);
+ return sprintf.apply(null, argv);
+};
+
+},{"./sprintf":47}],68:[function(_dereq_,module,exports){
+var isBlank = _dereq_('./isBlank');
+var trim = _dereq_('./trim');
+
+module.exports = function words(str, delimiter) {
+ if (isBlank(str)) return [];
+ return trim(str, delimiter).split(delimiter || /\s+/);
+};
+
+},{"./isBlank":27,"./trim":62}],69:[function(_dereq_,module,exports){
+// Wrap
+// wraps a string by a certain width
+
+makeString = _dereq_('./helper/makeString');
+
+module.exports = function wrap(str, options){
+ str = makeString(str);
+
+ options = options || {};
+
+ width = options.width || 75;
+ seperator = options.seperator || '\n';
+ cut = options.cut || false;
+ preserveSpaces = options.preserveSpaces || false;
+ trailingSpaces = options.trailingSpaces || false;
+
+ if(width <= 0){
+ return str;
+ }
+
+ else if(!cut){
+
+ words = str.split(" ");
+ result = "";
+ current_column = 0;
+
+ while(words.length > 0){
+
+ // if adding a space and the next word would cause this line to be longer than width...
+ if(1 + words[0].length + current_column > width){
+ //start a new line if this line is not already empty
+ if(current_column > 0){
+ // add a space at the end of the line is preserveSpaces is true
+ if (preserveSpaces){
+ result += ' ';
+ current_column++;
+ }
+ // fill the rest of the line with spaces if trailingSpaces option is true
+ else if(trailingSpaces){
+ while(current_column < width){
+ result += ' ';
+ current_column++;
+ }
+ }
+ //start new line
+ result += seperator;
+ current_column = 0;
+ }
+ }
+
+ // if not at the begining of the line, add a space in front of the word
+ if(current_column > 0){
+ result += " ";
+ current_column++;
+ }
+
+ // tack on the next word, update current column, a pop words array
+ result += words[0];
+ current_column += words[0].length;
+ words.shift();
+
+ }
+
+ // fill the rest of the line with spaces if trailingSpaces option is true
+ if(trailingSpaces){
+ while(current_column < width){
+ result += ' ';
+ current_column++;
+ }
+ }
+
+ return result;
+
+ }
+
+ else {
+
+ index = 0;
+ result = "";
+
+ // walk through each character and add seperators where appropriate
+ while(index < str.length){
+ if(index % width == 0 && index > 0){
+ result += seperator;
+ }
+ result += str.charAt(index);
+ index++;
+ }
+
+ // fill the rest of the line with spaces if trailingSpaces option is true
+ if(trailingSpaces){
+ while(index % width > 0){
+ result += ' ';
+ index++;
+ }
+ }
+
+ return result;
+ }
+};
+},{"./helper/makeString":21}]},{},[15])
+(15)
+});
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/core/underscore.string.min.js b/deployed/windwalker/media/windwalker/js/core/underscore.string.min.js
new file mode 100644
index 00000000..b32f5132
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/core/underscore.string.min.js
@@ -0,0 +1 @@
+!function(e){if("object"==typeof exports){module.exports=e()}else if("function"==typeof define&&define.amd){define(e)}else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.s=e()}}(function(){var define,module,exports;return(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")};var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)};return n[o].exports};var i=typeof require=="function"&&require;for(var o=0;o0?str.match(new RegExp('.{1,'+step+'}','g')):[str]}},{}],5:[function(_dereq_,module,exports){var capitalize=_dereq_('./capitalize'),camelize=_dereq_('./camelize'),makeString=_dereq_('./helper/makeString');module.exports=function classify(str){str=makeString(str);return capitalize(camelize(str.replace(/[\W_]/g,' ')).replace(/\s/g,''))}},{"./camelize":1,"./capitalize":2,"./helper/makeString":21}],6:[function(_dereq_,module,exports){var trim=_dereq_('./trim');module.exports=function clean(str){return trim(str).replace(/\s\s+/g,' ')}},{"./trim":62}],7:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString'),from="ąàáäâãåæăćčĉęèéëêĝĥìíïîĵłľńňòóöőôõðøśșšŝťțŭùúüűûñÿýçżźž",to="aaaaaaaaaccceeeeeghiiiijllnnoooooooossssttuuuuuunyyczzz";from+=from.toUpperCase();to+=to.toUpperCase();module.exports=function cleanDiacritics(str){return makeString(str).replace(/.{1}/g,function(c){var index=from.indexOf(c);return index===-1?c:to.charAt(index)})}},{"./helper/makeString":21}],8:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function(str,substr){str=makeString(str);substr=makeString(substr);if(str.length===0||substr.length===0)return 0;return str.split(substr).length-1}},{"./helper/makeString":21}],9:[function(_dereq_,module,exports){var trim=_dereq_('./trim');module.exports=function dasherize(str){return trim(str).replace(/([A-Z])/g,'-$1').replace(/[-_\s]+/g,'-').toLowerCase()}},{"./trim":62}],10:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function decapitalize(str){str=makeString(str);return str.charAt(0).toLowerCase()+str.slice(1)}},{"./helper/makeString":21}],11:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');function getIndent(str){var matches=str.match(/^[\s\\t]*/gm),indent=matches[0].length;for(var i=1;i=0&&str.indexOf(ends,position)===position}},{"./helper/makeString":21,"./helper/toPositive":23}],13:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString'),escapeChars=_dereq_('./helper/escapeChars'),reversedEscapeChars={},regexString="[";for(var key in escapeChars)regexString+=key;regexString+="]";var regex=new RegExp(regexString,'g');module.exports=function escapeHTML(str){return makeString(str).replace(regex,function(m){return'&'+escapeChars[m]+';'})}},{"./helper/escapeChars":18,"./helper/makeString":21}],14:[function(_dereq_,module,exports){module.exports=function(){var result={};for(var prop in this){if(!this.hasOwnProperty(prop)||prop.match(/^(?:include|contains|reverse|join)$/))continue;result[prop]=this[prop]};return result}},{}],15:[function(_dereq_,module,exports){'use strict';function s(value){if(!(this instanceof s))return new s(value);this._wrapped=value};s.VERSION='3.2.1';s.isBlank=_dereq_('./isBlank');s.stripTags=_dereq_('./stripTags');s.capitalize=_dereq_('./capitalize');s.decapitalize=_dereq_('./decapitalize');s.chop=_dereq_('./chop');s.trim=_dereq_('./trim');s.clean=_dereq_('./clean');s.cleanDiacritics=_dereq_('./cleanDiacritics');s.count=_dereq_('./count');s.chars=_dereq_('./chars');s.swapCase=_dereq_('./swapCase');s.escapeHTML=_dereq_('./escapeHTML');s.unescapeHTML=_dereq_('./unescapeHTML');s.splice=_dereq_('./splice');s.insert=_dereq_('./insert');s.replaceAll=_dereq_('./replaceAll');s.include=_dereq_('./include');s.join=_dereq_('./join');s.lines=_dereq_('./lines');s.dedent=_dereq_('./dedent');s.reverse=_dereq_('./reverse');s.startsWith=_dereq_('./startsWith');s.endsWith=_dereq_('./endsWith');s.pred=_dereq_('./pred');s.succ=_dereq_('./succ');s.titleize=_dereq_('./titleize');s.camelize=_dereq_('./camelize');s.underscored=_dereq_('./underscored');s.dasherize=_dereq_('./dasherize');s.classify=_dereq_('./classify');s.humanize=_dereq_('./humanize');s.ltrim=_dereq_('./ltrim');s.rtrim=_dereq_('./rtrim');s.truncate=_dereq_('./truncate');s.prune=_dereq_('./prune');s.words=_dereq_('./words');s.pad=_dereq_('./pad');s.lpad=_dereq_('./lpad');s.rpad=_dereq_('./rpad');s.lrpad=_dereq_('./lrpad');s.sprintf=_dereq_('./sprintf');s.vsprintf=_dereq_('./vsprintf');s.toNumber=_dereq_('./toNumber');s.numberFormat=_dereq_('./numberFormat');s.strRight=_dereq_('./strRight');s.strRightBack=_dereq_('./strRightBack');s.strLeft=_dereq_('./strLeft');s.strLeftBack=_dereq_('./strLeftBack');s.toSentence=_dereq_('./toSentence');s.toSentenceSerial=_dereq_('./toSentenceSerial');s.slugify=_dereq_('./slugify');s.surround=_dereq_('./surround');s.quote=_dereq_('./quote');s.unquote=_dereq_('./unquote');s.repeat=_dereq_('./repeat');s.naturalCmp=_dereq_('./naturalCmp');s.levenshtein=_dereq_('./levenshtein');s.toBoolean=_dereq_('./toBoolean');s.exports=_dereq_('./exports');s.escapeRegExp=_dereq_('./helper/escapeRegExp');s.wrap=_dereq_('./wrap');s.strip=s.trim;s.lstrip=s.ltrim;s.rstrip=s.rtrim;s.center=s.lrpad;s.rjust=s.lpad;s.ljust=s.rpad;s.contains=s.include;s.q=s.quote;s.toBool=s.toBoolean;s.camelcase=s.camelize;s.prototype={value:function value(){return this._wrapped}};function fn2method(key,fn){if(typeof fn!=="function")return;s.prototype[key]=function(){var args=[this._wrapped].concat(Array.prototype.slice.call(arguments)),res=fn.apply(null,args);return typeof res==='string'?new s(res):res}};for(var key in s)fn2method(key,s[key]);fn2method("tap",function tap(string,fn){return fn(string)});function prototype2method(methodName){fn2method(methodName,function(context){var args=Array.prototype.slice.call(arguments,1);return String.prototype[methodName].apply(context,args)})};var prototypeMethods=["toUpperCase","toLowerCase","split","replace","slice","substring","substr","concat"];for(var key in prototypeMethods)prototype2method(prototypeMethods[key]);module.exports=s},{"./camelize":1,"./capitalize":2,"./chars":3,"./chop":4,"./classify":5,"./clean":6,"./cleanDiacritics":7,"./count":8,"./dasherize":9,"./decapitalize":10,"./dedent":11,"./endsWith":12,"./escapeHTML":13,"./exports":14,"./helper/escapeRegExp":19,"./humanize":24,"./include":25,"./insert":26,"./isBlank":27,"./join":28,"./levenshtein":29,"./lines":30,"./lpad":31,"./lrpad":32,"./ltrim":33,"./naturalCmp":34,"./numberFormat":35,"./pad":36,"./pred":37,"./prune":38,"./quote":39,"./repeat":40,"./replaceAll":41,"./reverse":42,"./rpad":43,"./rtrim":44,"./slugify":45,"./splice":46,"./sprintf":47,"./startsWith":48,"./strLeft":49,"./strLeftBack":50,"./strRight":51,"./strRightBack":52,"./stripTags":53,"./succ":54,"./surround":55,"./swapCase":56,"./titleize":57,"./toBoolean":58,"./toNumber":59,"./toSentence":60,"./toSentenceSerial":61,"./trim":62,"./truncate":63,"./underscored":64,"./unescapeHTML":65,"./unquote":66,"./vsprintf":67,"./words":68,"./wrap":69}],16:[function(_dereq_,module,exports){var makeString=_dereq_('./makeString');module.exports=function adjacent(str,direction){str=makeString(str);if(str.length===0)return'';return str.slice(0,-1)+String.fromCharCode(str.charCodeAt(str.length-1)+direction)}},{"./makeString":21}],17:[function(_dereq_,module,exports){var escapeRegExp=_dereq_('./escapeRegExp');module.exports=function defaultToWhiteSpace(characters){if(characters==null){return'\\s'}else if(characters.source){return characters.source}else return'['+escapeRegExp(characters)+']'}},{"./escapeRegExp":19}],18:[function(_dereq_,module,exports){var escapeChars={'¢':'cent','£':'pound','¥':'yen','€':'euro','©':'copy','®':'reg','<':'lt','>':'gt','"':'quot','&':'amp',"'":'#39'};module.exports=escapeChars},{}],19:[function(_dereq_,module,exports){var makeString=_dereq_('./makeString');module.exports=function escapeRegExp(str){return makeString(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g,'\\$1')}},{"./makeString":21}],20:[function(_dereq_,module,exports){var htmlEntities={nbsp:' ',cent:'¢',pound:'£',yen:'¥',euro:'€',copy:'©',reg:'®',lt:'<',gt:'>',quot:'"',amp:'&',apos:"'"};module.exports=htmlEntities},{}],21:[function(_dereq_,module,exports){module.exports=function makeString(object){if(object==null)return'';return''+object}},{}],22:[function(_dereq_,module,exports){module.exports=function strRepeat(str,qty){if(qty<1)return'';var result='';while(qty>0){if(qty&1)result+=str;qty>>=1,str+=str};return result}},{}],23:[function(_dereq_,module,exports){module.exports=function toPositive(number){return number<0?0:(+number||0)}},{}],24:[function(_dereq_,module,exports){var capitalize=_dereq_('./capitalize'),underscored=_dereq_('./underscored'),trim=_dereq_('./trim');module.exports=function humanize(str){return capitalize(trim(underscored(str).replace(/_id$/,'').replace(/_/g,' ')))}},{"./capitalize":2,"./trim":62,"./underscored":64}],25:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function include(str,needle){if(needle==='')return true;return makeString(str).indexOf(needle)!==-1}},{"./helper/makeString":21}],26:[function(_dereq_,module,exports){var splice=_dereq_('./splice');module.exports=function insert(str,i,substr){return splice(str,i,0,substr)}},{"./splice":46}],27:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function isBlank(str){return/^\s*$/.test(makeString(str))}},{"./helper/makeString":21}],28:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString'),slice=[].slice;module.exports=function join(){var args=slice.call(arguments),separator=args.shift();return args.join(makeString(separator))}},{"./helper/makeString":21}],29:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function levenshtein(str1,str2){'use strict';str1=makeString(str1);str2=makeString(str2);if(str1===str2)return 0;if(!str1||!str2)return Math.max(str1.length,str2.length);var prevRow=new Array(str2.length+1);for(var i=0;itmp)nextCol=tmp;tmp=prevRow[j+1]+1;if(nextCol>tmp)nextCol=tmp;prevRow[j]=curCol};prevRow[j]=nextCol};return nextCol}},{"./helper/makeString":21}],30:[function(_dereq_,module,exports){module.exports=function lines(str){if(str==null)return[];return String(str).split(/\r\n?|\n/)}},{}],31:[function(_dereq_,module,exports){var pad=_dereq_('./pad');module.exports=function lpad(str,length,padStr){return pad(str,length,padStr)}},{"./pad":36}],32:[function(_dereq_,module,exports){var pad=_dereq_('./pad');module.exports=function lrpad(str,length,padStr){return pad(str,length,padStr,'both')}},{"./pad":36}],33:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString'),defaultToWhiteSpace=_dereq_('./helper/defaultToWhiteSpace'),nativeTrimLeft=String.prototype.trimLeft;module.exports=function ltrim(str,characters){str=makeString(str);if(!characters&&nativeTrimLeft)return nativeTrimLeft.call(str);characters=defaultToWhiteSpace(characters);return str.replace(new RegExp('^'+characters+'+'),'')}},{"./helper/defaultToWhiteSpace":17,"./helper/makeString":21}],34:[function(_dereq_,module,exports){module.exports=function naturalCmp(str1,str2){if(str1==str2)return 0;if(!str1)return-1;if(!str2)return 1;var cmpRegex=/(\.\d+|\d+|\D+)/g,tokens1=String(str1).match(cmpRegex),tokens2=String(str2).match(cmpRegex),count=Math.min(tokens1.length,tokens2.length);for(var i=0;inum2?1:-1;return a1)padStr=padStr.charAt(0);switch(type){case'right':padlen=length-str.length;return str+strRepeat(padStr,padlen);case'both':padlen=length-str.length;return strRepeat(padStr,Math.ceil(padlen/2))+str+strRepeat(padStr,Math.floor(padlen/2));default:padlen=length-str.length;return strRepeat(padStr,padlen)+str}}},{"./helper/makeString":21,"./helper/strRepeat":22}],37:[function(_dereq_,module,exports){var adjacent=_dereq_('./helper/adjacent');module.exports=function succ(str){return adjacent(str,-1)}},{"./helper/adjacent":16}],38:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString'),rtrim=_dereq_('./rtrim');module.exports=function prune(str,length,pruneStr){str=makeString(str);length=~~length;pruneStr=pruneStr!=null?String(pruneStr):'...';if(str.length<=length)return str;var tmpl=function(c){return c.toUpperCase()!==c.toLowerCase()?'A':' '},template=str.slice(0,length+1).replace(/.(?=\W*\w*$)/g,tmpl);if(template.slice(template.length-2).match(/\w\w/)){template=template.replace(/\s*\S+$/,'')}else template=rtrim(template.slice(0,template.length-1));return(template+pruneStr).length>str.length?str:str.slice(0,template.length)+pruneStr}},{"./helper/makeString":21,"./rtrim":44}],39:[function(_dereq_,module,exports){var surround=_dereq_('./surround');module.exports=function quote(str,quoteChar){return surround(str,quoteChar||'"')}},{"./surround":55}],40:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString'),strRepeat=_dereq_('./helper/strRepeat');module.exports=function repeat(str,qty,separator){str=makeString(str);qty=~~qty;if(separator==null)return strRepeat(str,qty);for(var repeat=[];qty>0;repeat[--qty]=str);return repeat.join(separator)}},{"./helper/makeString":21,"./helper/strRepeat":22}],41:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function replaceAll(str,find,replace,ignorecase){var flags=(ignorecase===true)?'gi':'g',reg=new RegExp(find,flags);return makeString(str).replace(reg,replace)}},{"./helper/makeString":21}],42:[function(_dereq_,module,exports){var chars=_dereq_('./chars');module.exports=function reverse(str){return chars(str).reverse().join('')}},{"./chars":3}],43:[function(_dereq_,module,exports){var pad=_dereq_('./pad');module.exports=function rpad(str,length,padStr){return pad(str,length,padStr,'right')}},{"./pad":36}],44:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString'),defaultToWhiteSpace=_dereq_('./helper/defaultToWhiteSpace'),nativeTrimRight=String.prototype.trimRight;module.exports=function rtrim(str,characters){str=makeString(str);if(!characters&&nativeTrimRight)return nativeTrimRight.call(str);characters=defaultToWhiteSpace(characters);return str.replace(new RegExp(characters+'+$'),'')}},{"./helper/defaultToWhiteSpace":17,"./helper/makeString":21}],45:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString'),defaultToWhiteSpace=_dereq_('./helper/defaultToWhiteSpace'),trim=_dereq_('./trim'),dasherize=_dereq_('./dasherize'),cleanDiacritics=_dereq_("./cleanDiacritics");module.exports=function slugify(str){return trim(dasherize(cleanDiacritics(str).replace(/[^\w\s-]/g,'-')),'-')}},{"./cleanDiacritics":7,"./dasherize":9,"./helper/defaultToWhiteSpace":17,"./helper/makeString":21,"./trim":62}],46:[function(_dereq_,module,exports){var chars=_dereq_('./chars');module.exports=function splice(str,i,howmany,substr){var arr=chars(str);arr.splice(~~i,~~howmany,substr);return arr.join('')}},{"./chars":3}],47:[function(_dereq_,module,exports){var strRepeat=_dereq_('./helper/strRepeat'),toString=Object.prototype.toString,sprintf=(function(){function get_type(variable){return toString.call(variable).slice(8,-1).toLowerCase()};var str_repeat=strRepeat,str_format=function(){if(!str_format.cache.hasOwnProperty(arguments[0]))str_format.cache[arguments[0]]=str_format.parse(arguments[0]);return str_format.format.call(null,str_format.cache[arguments[0]],arguments)};str_format.format=function(parse_tree,argv){var cursor=1,tree_length=parse_tree.length,node_type='',arg,output=[],i,k,match,pad,pad_character,pad_length;for(i=0;i=0?'+'+arg:arg);pad_character=match[4]?match[4]=='0'?'0':match[4].charAt(1):' ';pad_length=match[6]-String(arg).length;pad=match[6]?str_repeat(pad_character,pad_length):'';output.push(match[5]?arg+pad:pad+arg)}};return output.join('')};str_format.cache={};str_format.parse=function(fmt){var _fmt=fmt,match=[],parse_tree=[],arg_names=0;while(_fmt){if((match=/^[^\x25]+/.exec(_fmt))!==null){parse_tree.push(match[0])}else if((match=/^\x25{2}/.exec(_fmt))!==null){parse_tree.push('%')}else if((match=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt))!==null){if(match[2]){arg_names|=1;var field_list=[],replacement_field=match[2],field_match=[];if((field_match=/^([a-z_][a-z_\d]*)/i.exec(replacement_field))!==null){field_list.push(field_match[1]);while((replacement_field=replacement_field.substring(field_match[0].length))!=='')if((field_match=/^\.([a-z_][a-z_\d]*)/i.exec(replacement_field))!==null){field_list.push(field_match[1])}else if((field_match=/^\[(\d+)\]/.exec(replacement_field))!==null){field_list.push(field_match[1])}else throw new Error('[_.sprintf] huh?')}else throw new Error('[_.sprintf] huh?');match[2]=field_list}else arg_names|=2;if(arg_names===3)throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported');parse_tree.push(match)}else throw new Error('[_.sprintf] huh?');_fmt=_fmt.substring(match[0].length)};return parse_tree};return str_format})();module.exports=sprintf},{"./helper/strRepeat":22}],48:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString'),toPositive=_dereq_('./helper/toPositive');module.exports=function startsWith(str,starts,position){str=makeString(str);starts=''+starts;position=position==null?0:Math.min(toPositive(position),str.length);return str.lastIndexOf(starts,position)===position}},{"./helper/makeString":21,"./helper/toPositive":23}],49:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function strLeft(str,sep){str=makeString(str);sep=makeString(sep);var pos=!sep?-1:str.indexOf(sep);return~pos?str.slice(0,pos):str}},{"./helper/makeString":21}],50:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function strLeftBack(str,sep){str=makeString(str);sep=makeString(sep);var pos=str.lastIndexOf(sep);return~pos?str.slice(0,pos):str}},{"./helper/makeString":21}],51:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function strRight(str,sep){str=makeString(str);sep=makeString(sep);var pos=!sep?-1:str.indexOf(sep);return~pos?str.slice(pos+sep.length,str.length):str}},{"./helper/makeString":21}],52:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function strRightBack(str,sep){str=makeString(str);sep=makeString(sep);var pos=!sep?-1:str.lastIndexOf(sep);return~pos?str.slice(pos+sep.length,str.length):str}},{"./helper/makeString":21}],53:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function stripTags(str){return makeString(str).replace(/<\/?[^>]+>/g,'')}},{"./helper/makeString":21}],54:[function(_dereq_,module,exports){var adjacent=_dereq_('./helper/adjacent');module.exports=function succ(str){return adjacent(str,1)}},{"./helper/adjacent":16}],55:[function(_dereq_,module,exports){module.exports=function surround(str,wrapper){return[wrapper,str,wrapper].join('')}},{}],56:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function swapCase(str){return makeString(str).replace(/\S/g,function(c){return c===c.toUpperCase()?c.toLowerCase():c.toUpperCase()})}},{"./helper/makeString":21}],57:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function titleize(str){return makeString(str).toLowerCase().replace(/(?:^|\s|-)\S/g,function(c){return c.toUpperCase()})}},{"./helper/makeString":21}],58:[function(_dereq_,module,exports){var trim=_dereq_('./trim');function boolMatch(s,matchers){var i,matcher,down=s.toLowerCase();matchers=[].concat(matchers);for(i=0;i2&&serial)lastSeparator=rtrim(separator)+lastSeparator;return a.length?a.join(separator)+lastSeparator+lastMember:lastMember}},{"./rtrim":44}],61:[function(_dereq_,module,exports){var toSentence=_dereq_('./toSentence');module.exports=function toSentenceSerial(array,sep,lastSep){return toSentence(array,sep,lastSep,true)}},{"./toSentence":60}],62:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString'),defaultToWhiteSpace=_dereq_('./helper/defaultToWhiteSpace'),nativeTrim=String.prototype.trim;module.exports=function trim(str,characters){str=makeString(str);if(!characters&&nativeTrim)return nativeTrim.call(str);characters=defaultToWhiteSpace(characters);return str.replace(new RegExp('^'+characters+'+|'+characters+'+$','g'),'')}},{"./helper/defaultToWhiteSpace":17,"./helper/makeString":21}],63:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString');module.exports=function truncate(str,length,truncateStr){str=makeString(str);truncateStr=truncateStr||'...';length=~~length;return str.length>length?str.slice(0,length)+truncateStr:str}},{"./helper/makeString":21}],64:[function(_dereq_,module,exports){var trim=_dereq_('./trim');module.exports=function underscored(str){return trim(str).replace(/([a-z\d])([A-Z]+)/g,'$1_$2').replace(/[-\s]+/g,'_').toLowerCase()}},{"./trim":62}],65:[function(_dereq_,module,exports){var makeString=_dereq_('./helper/makeString'),htmlEntities=_dereq_('./helper/htmlEntities');module.exports=function unescapeHTML(str){return makeString(str).replace(/\&([^;]+);/g,function(entity,entityCode){var match;if(entityCode in htmlEntities){return htmlEntities[entityCode]}else if(match=entityCode.match(/^#x([\da-fA-F]+)$/)){return String.fromCharCode(parseInt(match[1],16))}else if(match=entityCode.match(/^#(\d+)$/)){return String.fromCharCode(~~match[1])}else return entity})}},{"./helper/htmlEntities":20,"./helper/makeString":21}],66:[function(_dereq_,module,exports){module.exports=function unquote(str,quoteChar){quoteChar=quoteChar||'"';if(str[0]===quoteChar&&str[str.length-1]===quoteChar){return str.slice(1,str.length-1)}else return str}},{}],67:[function(_dereq_,module,exports){var sprintf=_dereq_('./sprintf');module.exports=function vsprintf(fmt,argv){argv.unshift(fmt);return sprintf.apply(null,argv)}},{"./sprintf":47}],68:[function(_dereq_,module,exports){var isBlank=_dereq_('./isBlank'),trim=_dereq_('./trim');module.exports=function words(str,delimiter){if(isBlank(str))return[];return trim(str,delimiter).split(delimiter||/\s+/)}},{"./isBlank":27,"./trim":62}],69:[function(_dereq_,module,exports){makeString=_dereq_('./helper/makeString');module.exports=function wrap(str,options){str=makeString(str);options=options||{};width=options.width||75;seperator=options.seperator||'\n';cut=options.cut||false;preserveSpaces=options.preserveSpaces||false;trailingSpaces=options.trailingSpaces||false;if(width<=0){return str}else if(!cut){words=str.split(" ");result="";current_column=0;while(words.length>0){if(1+words[0].length+current_column>width)if(current_column>0){if(preserveSpaces){result+=' ';current_column++}else if(trailingSpaces)while(current_column0){result+=" ";current_column++};result+=words[0];current_column+=words[0].length;words.shift()};if(trailingSpaces)while(current_column0)result+=seperator;result+=str.charAt(index);index++};if(trailingSpaces)while(index%width>0){result+=' ';index++};return result}}},{"./helper/makeString":21}]},{},[15])(15)})
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/css/elfinder.min.css b/deployed/windwalker/media/windwalker/js/elfinder/css/elfinder.min.css
new file mode 100644
index 00000000..52e58c09
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/elfinder/css/elfinder.min.css
@@ -0,0 +1,9 @@
+/*!
+ * elFinder - file manager for web
+ * Version 2.1_n (Nightly: 9724cf7) (2013-05-26)
+ * http://elfinder.org
+ *
+ * Copyright 2009-2012, Studio 42
+ * Licensed under a 3 clauses BSD license
+ */
+.elfinder-dialog-resize{margin-top:.3em}.elfinder-resize-type{float:left;margin-bottom:.4em}.elfinder-resize-control{padding-top:3em}.elfinder-resize-control input[type=text]{border:1px solid #aaa;text-align:right}.elfinder-resize-preview{width:400px;height:400px;padding:10px;background:#fff;border:1px solid #aaa;float:right;position:relative;overflow:auto}.elfinder-resize-handle{position:relative}.elfinder-resize-handle-hline,.elfinder-resize-handle-vline{position:absolute;background-image:url("../img/crop.gif")}.elfinder-resize-handle-hline{width:100%;height:1px!important;background-repeat:repeat-x}.elfinder-resize-handle-vline{width:1px!important;height:100%;background-repeat:repeat-y}.elfinder-resize-handle-hline-top{top:0;left:0}.elfinder-resize-handle-hline-bottom{bottom:0;left:0}.elfinder-resize-handle-vline-left{top:0;left:0}.elfinder-resize-handle-vline-right{top:0;right:0}.elfinder-resize-handle-point{position:absolute;width:8px;height:8px;border:1px solid #777;background:0 0}.elfinder-resize-handle-point-n{top:0;left:50%;margin-top:-5px;margin-left:-5px}.elfinder-resize-handle-point-ne{top:0;right:0;margin-top:-5px;margin-right:-5px}.elfinder-resize-handle-point-e{top:50%;right:0;margin-top:-5px;margin-right:-5px}.elfinder-resize-handle-point-se{bottom:0;right:0;margin-bottom:-5px;margin-right:-5px}.elfinder-resize-handle-point-s{bottom:0;left:50%;margin-bottom:-5px;margin-left:-5px}.elfinder-resize-handle-point-sw{bottom:0;left:0;margin-bottom:-5px;margin-left:-5px}.elfinder-resize-handle-point-w{top:50%;left:0;margin-top:-5px;margin-left:-5px}.elfinder-resize-handle-point-nw{top:0;left:0;margin-top:-5px;margin-left:-5px}.elfinder-resize-spinner{position:absolute;width:200px;height:30px;top:50%;margin-top:-25px;left:50%;margin-left:-100px;text-align:center;background:url(../img/progress.gif) center bottom repeat-x}.elfinder-resize-row{margin-bottom:7px;position:relative}.elfinder-resize-label{float:left;width:80px;padding-top:3px}.elfinder-resize-reset{width:16px;height:16px;position:absolute;margin-top:-8px}.elfinder-dialog .elfinder-dialog-resize .ui-resizable-e{height:100%;width:10px}.elfinder-dialog .elfinder-dialog-resize .ui-resizable-s{width:100%;height:10px}.elfinder-dialog .elfinder-dialog-resize .ui-resizable-se{background:0 0;bottom:0;right:0;margin-right:-7px;margin-bottom:-7px}.elfinder-dialog-resize .ui-icon-grip-solid-vertical{position:absolute;top:50%;right:0;margin-top:-8px;margin-right:-11px}.elfinder-dialog-resize .ui-icon-grip-solid-horizontal{position:absolute;left:50%;bottom:0;margin-left:-8px;margin-bottom:-11px}.elfinder-resize-row .elfinder-buttonset{float:right}.elfinder-resize-rotate-slider{float:left;width:195px;margin:7px 7px 0}.elfinder-file-edit{width:99%;height:99%;margin:0;padding:2px;border:1px solid #ccc}.elfinder-help{margin-bottom:.5em}.elfinder-help .ui-tabs-panel{padding:.5em}.elfinder-dialog .ui-tabs .ui-tabs-nav li a{padding:.2em 1em}.elfinder-help-shortcuts{height:300px;padding:1em;margin:.5em 0;overflow:auto}.elfinder-help-shortcut{white-space:nowrap;clear:both}.elfinder-help-shortcut-pattern{float:left;width:160px}.elfinder-help-logo{width:100px;height:96px;float:left;margin-right:1em;background:url('../img/logo.png') center center no-repeat}.elfinder-help h3{font-size:1.5em;margin:.2em 0 .3em}.elfinder-help-separator{clear:both;padding:.5em}.elfinder-help-link{padding:2px}.elfinder-help .ui-priority-secondary{font-size:.9em}.elfinder-help .ui-priority-primary{margin-bottom:7px}.elfinder-help-team{clear:both;text-align:right;border-bottom:1px solid #ccc;margin:.5em 0;font-size:.9em}.elfinder-help-team div{float:left}.elfinder-help-license{font-size:.9em}.elfinder-help-disabled{font-weight:700;text-align:center;margin:90px 0}.elfinder-help .elfinder-dont-panic{display:block;border:1px solid transparent;width:200px;height:200px;margin:30px auto;text-decoration:none;text-align:center;position:relative;background:#d90004;-moz-box-shadow:5px 5px 9px #111;-webkit-box-shadow:5px 5px 9px #111;box-shadow:5px 5px 9px #111;background:-moz-radial-gradient(80px 80px,circle farthest-corner,#d90004 35%,#960004 100%);background:-webkit-gradient(radial,80 80,60,80 80,120,from(#d90004),to(#960004));-moz-border-radius:100px;-webkit-border-radius:100px;border-radius:100px;outline:none}.elfinder-help .elfinder-dont-panic span{font-size:3em;font-weight:700;text-align:center;color:#fff;position:absolute;left:0;top:45px}.elfinder{padding:0;position:relative;display:block}.elfinder-rtl{text-align:right;direction:rtl}.elfinder-workzone{padding:0;position:relative;overflow:hidden}.elfinder-lock,.elfinder-perms,.elfinder-symlink{position:absolute;width:16px;height:16px;background-image:url(../img/toolbar.png);background-repeat:no-repeat;background-position:0 -528px}.elfinder-na .elfinder-perms{background-position:0 -96px}.elfinder-ro .elfinder-perms{background-position:0 -64px}.elfinder-wo .elfinder-perms{background-position:0 -80px}.elfinder-lock{background-position:0 -656px}.elfinder-drag-helper{width:60px;height:50px;padding:0 0 0 25px;z-index:100000}.elfinder-drag-helper-icon-plus{position:absolute;width:16px;height:16px;left:43px;top:55px;background:url('../img/toolbar.png') 0 -544px no-repeat;display:none}.elfinder-drag-helper-plus .elfinder-drag-helper-icon-plus{display:block}.elfinder-drag-num{position:absolute;top:0;left:0;width:16px;height:14px;text-align:center;padding-top:2px;font-weight:700;color:#fff;background-color:red;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}.elfinder-drag-helper .elfinder-cwd-icon{margin:0 0 0 -24px;float:left}.elfinder-overlay{opacity:0;filter:Alpha(Opacity=0)}.elfinder .elfinder-panel{position:relative;background-image:none;padding:7px 12px}.elfinder-contextmenu,.elfinder-contextmenu-sub{display:none;position:absolute;border:1px solid #aaa;background:#fff;color:#555;padding:4px 0}.elfinder-contextmenu-sub{top:5px}.elfinder-contextmenu-ltr .elfinder-contextmenu-sub{margin-left:-5px}.elfinder-contextmenu-rtl .elfinder-contextmenu-sub{margin-right:-5px}.elfinder-contextmenu-item{position:relative;display:block;padding:4px 30px;text-decoration:none;white-space:nowrap;cursor:default}.elfinder-contextmenu .elfinder-contextmenu-item span{display:block}.elfinder-contextmenu-ltr .elfinder-contextmenu-item{text-align:left}.elfinder-contextmenu-rtl .elfinder-contextmenu-item{text-align:right}.elfinder-contextmenu-ltr .elfinder-contextmenu-sub .elfinder-contextmenu-item{padding-left:12px}.elfinder-contextmenu-rtl .elfinder-contextmenu-sub .elfinder-contextmenu-item{padding-right:12px}.elfinder-contextmenu-arrow,.elfinder-contextmenu-icon{position:absolute;top:50%;margin-top:-8px}.elfinder-contextmenu-ltr .elfinder-contextmenu-icon{left:8px}.elfinder-contextmenu-rtl .elfinder-contextmenu-icon{right:8px}.elfinder-contextmenu-arrow{width:16px;height:16px;background:url('../img/arrows-normal.png') 5px 4px no-repeat}.elfinder-contextmenu-ltr .elfinder-contextmenu-arrow{right:5px}.elfinder-contextmenu-rtl .elfinder-contextmenu-arrow{left:5px;background-position:0 -10px}.elfinder-contextmenu .ui-state-hover{border:0 solid;background-image:none}.elfinder-contextmenu-separator{height:0;border-top:1px solid #ccc;margin:0 1px}.elfinder-cwd-wrapper{overflow:auto;position:relative;padding:2px;margin:0}.elfinder-cwd-wrapper-list{padding:0}.elfinder-cwd{position:relative;cursor:default;padding:0;margin:0;-moz-user-select:-moz-none;-khtml-user-select:none;-webkit-user-select:none;user-select:none}.elfinder .elfinder-cwd-wrapper.elfinder-droppable-active{padding:0;border:2px solid #8cafed}.elfinder-cwd-view-icons .elfinder-cwd-file{width:120px;height:80px;padding-bottom:2px;cursor:default;border:none}.elfinder-ltr .elfinder-cwd-view-icons .elfinder-cwd-file{float:left;margin:0 3px 12px 0}.elfinder-rtl .elfinder-cwd-view-icons .elfinder-cwd-file{float:right;margin:0 0 5px 3px}.elfinder-cwd-view-icons .elfinder-cwd-file .ui-state-hover{border:0 solid}.elfinder-cwd-view-icons .elfinder-cwd-file-wrapper{width:52px;height:52px;margin:1px auto;padding:2px;position:relative}.elfinder-cwd-view-icons .elfinder-cwd-filename{text-align:center;white-space:pre;overflow:hidden;text-overflow:ellipsis;-o-text-overflow:ellipsis;margin:3px 1px 0;padding:1px;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}.elfinder-cwd-view-icons .elfinder-perms{bottom:4px;right:2px}.elfinder-cwd-view-icons .elfinder-lock{top:-3px;right:-2px}.elfinder-cwd-view-icons .elfinder-symlink{bottom:6px;left:0}.elfinder-cwd-icon{display:block;width:48px;height:48px;margin:0 auto;background:url('../img/icons-big.png') 0 0 no-repeat;-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box}.elfinder-cwd .elfinder-droppable-active .elfinder-cwd-icon{background-position:0 -100px}.elfinder-cwd-icon-directory{background-position:0 -50px}.elfinder-cwd-icon-application{background-position:0 -150px}.elfinder-cwd-icon-x-empty,.elfinder-cwd-icon-text{background-position:0 -200px}.elfinder-cwd-icon-image,.elfinder-cwd-icon-vnd-adobe-photoshop,.elfinder-cwd-icon-postscript{background-position:0 -250px}.elfinder-cwd-icon-audio{background-position:0 -300px}.elfinder-cwd-icon-video,.elfinder-cwd-icon-flash-video{background-position:0 -350px}.elfinder-cwd-icon-rtf,.elfinder-cwd-icon-rtfd{background-position:0 -401px}.elfinder-cwd-icon-pdf{background-position:0 -450px}.elfinder-cwd-icon-ms-excel,.elfinder-cwd-icon-msword,.elfinder-cwd-icon-vnd-ms-excel,.elfinder-cwd-icon-vnd-ms-excel-addin-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-excel-sheet-binary-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-excel-sheet-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-excel-template-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-office,.elfinder-cwd-icon-vnd-ms-powerpoint,.elfinder-cwd-icon-vnd-ms-powerpoint-addin-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-powerpoint-presentation-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-powerpoint-slide-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-powerpoint-slideshow-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-powerpoint-template-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-word,.elfinder-cwd-icon-vnd-ms-word-document-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-word-template-macroEnabled-12,.elfinder-cwd-icon-vnd-oasis-opendocument-chart,.elfinder-cwd-icon-vnd-oasis-opendocument-database,.elfinder-cwd-icon-vnd-oasis-opendocument-formula,.elfinder-cwd-icon-vnd-oasis-opendocument-graphics,.elfinder-cwd-icon-vnd-oasis-opendocument-graphics-template,.elfinder-cwd-icon-vnd-oasis-opendocument-image,.elfinder-cwd-icon-vnd-oasis-opendocument-presentation,.elfinder-cwd-icon-vnd-oasis-opendocument-presentation-template,.elfinder-cwd-icon-vnd-oasis-opendocument-spreadsheet,.elfinder-cwd-icon-vnd-oasis-opendocument-spreadsheet-template,.elfinder-cwd-icon-vnd-oasis-opendocument-text,.elfinder-cwd-icon-vnd-oasis-opendocument-text-master,.elfinder-cwd-icon-vnd-oasis-opendocument-text-template,.elfinder-cwd-icon-vnd-oasis-opendocument-text-web,.elfinder-cwd-icon-vnd-openofficeorg-extension,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-presentation,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-slide,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-slideshow,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-template,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-spreadsheetml-sheet,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-spreadsheetml-template,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-wordprocessingml-document,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-wordprocessingml-template{background-position:0 -500px}.elfinder-cwd-icon-html{background-position:0 -550px}.elfinder-cwd-icon-css{background-position:0 -600px}.elfinder-cwd-icon-javascript,.elfinder-cwd-icon-x-javascript{background-position:0 -650px}.elfinder-cwd-icon-x-perl{background-position:0 -700px}.elfinder-cwd-icon-x-python{background-position:0 -750px}.elfinder-cwd-icon-x-ruby{background-position:0 -800px}.elfinder-cwd-icon-x-sh,.elfinder-cwd-icon-x-shellscript{background-position:0 -850px}.elfinder-cwd-icon-x-c,.elfinder-cwd-icon-x-csrc,.elfinder-cwd-icon-x-chdr,.elfinder-cwd-icon-x-c--,.elfinder-cwd-icon-x-c--src,.elfinder-cwd-icon-x-c--hdr,.elfinder-cwd-icon-x-java,.elfinder-cwd-icon-x-java-source{background-position:0 -900px}.elfinder-cwd-icon-x-php{background-position:0 -950px}.elfinder-cwd-icon-xml{background-position:0 -1000px}.elfinder-cwd-icon-zip,.elfinder-cwd-icon-x-zip,.elfinder-cwd-icon-x-7z-compressed{background-position:0 -1050px}.elfinder-cwd-icon-x-gzip,.elfinder-cwd-icon-x-tar{background-position:0 -1100px}.elfinder-cwd-icon-x-bzip,.elfinder-cwd-icon-x-bzip2{background-position:0 -1150px}.elfinder-cwd-icon-x-rar,.elfinder-cwd-icon-x-rar-compressed{background-position:0 -1200px}.elfinder-cwd-icon-x-shockwave-flash{background-position:0 -1250px}.elfinder-cwd-icon-group{background-position:0 -1300px}.elfinder-cwd input{width:100%;border:0 solid;margin:0;padding:0}.elfinder-cwd-view-icons input,.elfinder-cwd-view-icons{text-align:center}.elfinder-cwd table{width:100%;border-collapse:collapse;border:0 solid;margin:0 0 10px}.elfinder .elfinder-cwd table thead tr{border-left:0 solid;border-top:0 solid;border-right:0 solid}.elfinder .elfinder-cwd table td{padding:3px 12px;white-space:pre;overflow:hidden;text-align:right;cursor:default;border:0 solid}.elfinder-ltr .elfinder-cwd table td{text-align:right}.elfinder-ltr .elfinder-cwd table td:first-child{text-align:left}.elfinder-rtl .elfinder-cwd table td{text-align:left}.elfinder-rtl .elfinder-cwd table td:first-child{text-align:right}.elfinder-odd-row{background:#eee}.elfinder-cwd-view-list .elfinder-cwd-file-wrapper{width:97%;position:relative}.elfinder-ltr .elfinder-cwd-view-list .elfinder-cwd-file-wrapper{padding-left:23px}.elfinder-rtl .elfinder-cwd-view-list .elfinder-cwd-file-wrapper{padding-right:23px}.elfinder-cwd-view-list .elfinder-perms,.elfinder-cwd-view-list .elfinder-lock,.elfinder-cwd-view-list .elfinder-symlink{top:50%;margin-top:-6px}.elfinder-ltr .elfinder-cwd-view-list .elfinder-perms{left:7px}.elfinder-ltr .elfinder-cwd-view-list .elfinder-lock{left:9px;top:0}.elfinder-ltr .elfinder-cwd-view-list .elfinder-symlink{left:-7px}.elfinder-cwd-view-list td .elfinder-cwd-icon{width:16px;height:16px;position:absolute;top:50%;margin-top:-8px;background-image:url(../img/icons-small.png)}.elfinder-ltr .elfinder-cwd-view-list .elfinder-cwd-icon{left:0}.elfinder-rtl .elfinder-cwd-view-list .elfinder-cwd-icon{right:0}.std42-dialog{padding:0;position:absolute;left:auto;right:auto}.std42-dialog .ui-dialog-titlebar{border-left:0 solid transparent;border-top:0 solid transparent;border-right:0 solid transparent;-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;font-weight:400;padding:.2em 1em}.std42-dialog .ui-dialog-titlebar-close,.std42-dialog .ui-dialog-titlebar-close:hover{padding:1px}.elfinder-rtl .elfinder-dialog .ui-dialog-titlebar{text-align:right}.elfinder-rtl .elfinder-dialog .ui-dialog-titlebar .ui-dialog-titlebar-close{right:auto;left:.3em}.std42-dialog .ui-dialog-content{padding:.3em .5em}.std42-dialog .ui-dialog-buttonpane{border:0 solid;margin:0;padding:.5em .7em}.std42-dialog .ui-dialog-buttonpane button{margin:0 0 0 .4em;padding:0;outline:0 solid}.std42-dialog .ui-dialog-buttonpane button span{padding:2px 9px}.elfinder-dialog .ui-resizable-e,.elfinder-dialog .ui-resizable-s{width:0;height:0}.std42-dialog .ui-button input{cursor:pointer}.elfinder-dialog-icon{position:absolute;width:32px;height:32px;left:12px;top:50%;margin-top:-15px;background:url("../img/dialogs.png") 0 0 no-repeat}.elfinder-rtl .elfinder-dialog-icon{left:auto;right:12px}.elfinder-dialog-error .ui-dialog-content,.elfinder-dialog-confirm .ui-dialog-content{padding-left:56px;min-height:35px}.elfinder-rtl .elfinder-dialog-error .ui-dialog-content,.elfinder-rtl .elfinder-dialog-confirm .ui-dialog-content{padding-left:0;padding-right:56px}.elfinder-dialog-notify .ui-dialog-titlebar-close{display:none}.elfinder-dialog-notify .ui-dialog-content{padding:0}.elfinder-notify{border-bottom:1px solid #ccc;position:relative;padding:.5em;text-align:center;overflow:hidden}.elfinder-ltr .elfinder-notify{padding-left:30px}.elfinder-rtl .elfinder-notify{padding-right:30px}.elfinder-notify:last-child{border:0 solid}.elfinder-notify-progressbar{width:180px;height:8px;border:1px solid #aaa;background:#f5f5f5;margin:5px auto;overflow:hidden}.elfinder-notify-progress{width:100%;height:8px;background:url(../img/progress.gif) center center repeat-x}.elfinder-notify-progressbar,.elfinder-notify-progress{-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px}.elfinder-dialog-icon-open,.elfinder-dialog-icon-file,.elfinder-dialog-icon-reload{background-position:0 -225px}.elfinder-dialog-icon-mkdir{background-position:0 -64px}.elfinder-dialog-icon-mkfile{background-position:0 -96px}.elfinder-dialog-icon-copy,.elfinder-dialog-icon-prepare,.elfinder-dialog-icon-move{background-position:0 -128px}.elfinder-dialog-icon-upload{background-position:0 -160px}.elfinder-dialog-icon-rm{background-position:0 -192px}.elfinder-dialog-icon-download{background-position:0 -260px}.elfinder-dialog-icon-save{background-position:0 -295px}.elfinder-dialog-icon-rename{background-position:0 -330px}.elfinder-dialog-icon-archive,.elfinder-dialog-icon-extract{background-position:0 -365px}.elfinder-dialog-icon-search{background-position:0 -402px}.elfinder-dialog-icon-resize,.elfinder-dialog-icon-loadimg,.elfinder-dialog-icon-netmount,.elfinder-dialog-icon-netunmount,.elfinder-dialog-icon-dim{background-position:0 -434px}.elfinder-dialog-confirm-applyall{padding-top:3px}.elfinder-dialog-confirm .elfinder-dialog-icon{background-position:0 -32px}.elfinder-info-title .elfinder-cwd-icon{float:left;width:48px;height:48px;margin-right:1em}.elfinder-info-title strong{display:block;padding:.3em 0 .5em}.elfinder-info-tb{min-width:200px;border:0 solid;margin:1em .2em}.elfinder-info-tb td{white-space:nowrap;padding:2px}.elfinder-info-tb tr td:first-child{text-align:right}.elfinder-info-tb span{float:left}.elfinder-info-tb a{outline:none;text-decoration:underline}.elfinder-info-tb a:hover{text-decoration:none}.elfinder-info-spinner{width:14px;height:14px;float:left;background:url("../img/spinner-mini.gif") center center no-repeat;margin:0 5px}.elfinder-netmount-tb{margin:0 auto}.elfinder-netmount-tb input{border:1px solid #ccc}.elfinder-upload-dropbox{text-align:center;padding:2em 0;border:3px dashed #aaa}.elfinder-upload-dropbox.ui-state-hover{background:#dfdfdf;border:3px dashed #555}.elfinder-upload-dialog-or{margin:.3em 0;text-align:center}.elfinder-upload-dialog-wrapper{text-align:center}.elfinder-upload-dialog-wrapper .ui-button{position:relative;overflow:hidden}.elfinder-upload-dialog-wrapper .ui-button form{position:absolute;right:0;top:0;opacity:0;filter:Alpha(Opacity=0)}.elfinder-upload-dialog-wrapper .ui-button form input{padding:0 20px;font-size:3em}.dialogelfinder .dialogelfinder-drag{border-left:0 solid;border-top:0 solid;border-right:0 solid;font-weight:400;padding:2px 12px;cursor:move;position:relative;text-align:left}.elfinder-rtl .dialogelfinder-drag{text-align:right}.dialogelfinder-drag-close{position:absolute;top:50%;margin-top:-8px}.elfinder-ltr .dialogelfinder-drag-close{right:12px}.elfinder-rtl .dialogelfinder-drag-close{left:12px}.elfinder-contextmenu .elfinder-contextmenu-item span{font-size:.76em}.elfinder-cwd-view-icons .elfinder-cwd-filename,.elfinder-cwd-view-list td{font-size:.7em}.std42-dialog .ui-dialog-titlebar{font-size:.82em}.std42-dialog .ui-dialog-content{font-size:.72em}.std42-dialog .ui-dialog-buttonpane{font-size:.76em}.elfinder-info-tb{font-size:.9em}.elfinder-upload-dropbox,.elfinder-upload-dialog-or{font-size:1.2em}.dialogelfinder .dialogelfinder-drag{font-size:.9em}.elfinder .elfinder-navbar{font-size:.72em}.elfinder-place-drag .elfinder-navbar-dir{font-size:.9em}.elfinder-quicklook-title{font-size:.7em}.elfinder-quicklook-info-data{font-size:.72em}.elfinder-quicklook-preview-text-wrapper{font-size:.9em}.elfinder-button-menu-item{font-size:.72em}.elfinder-button-search input{font-size:.8em}.elfinder-statusbar div{font-size:.7em}.elfinder-drag-num{font-size:12px}.elfinder .elfinder-navbar{width:230px;padding:3px 5px;background-image:none;border-top:0 solid;border-bottom:0 solid;overflow:auto;display:none;position:relative;-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;user-select:none}.elfinder-ltr .elfinder-navbar{float:left;border-left:0 solid}.elfinder-rtl .elfinder-navbar{float:right;border-right:0 solid}.elfinder-ltr .ui-resizable-e{margin-left:10px}.elfinder-tree{display:table;width:100%;margin:0 0 .5em}.elfinder-navbar-dir{position:relative;display:block;white-space:nowrap;padding:3px 12px;margin:0;outline:0 solid;border:1px solid transparent;cursor:default}.elfinder-ltr .elfinder-navbar-dir{padding-left:35px}.elfinder-rtl .elfinder-navbar-dir{padding-right:35px}.elfinder-navbar-arrow{width:12px;height:14px;position:absolute;display:none;top:50%;margin-top:-8px;background-image:url("../img/arrows-normal.png");background-repeat:no-repeat}.ui-state-active .elfinder-navbar-arrow{background-image:url("../img/arrows-active.png")}.elfinder-navbar-collapsed .elfinder-navbar-arrow{display:block}.elfinder-ltr .elfinder-navbar-collapsed .elfinder-navbar-arrow{background-position:0 4px;left:0}.elfinder-rtl .elfinder-navbar-collapsed .elfinder-navbar-arrow{background-position:0 -10px;right:0}.elfinder-ltr .elfinder-navbar-expanded .elfinder-navbar-arrow,.elfinder-rtl .elfinder-navbar-expanded .elfinder-navbar-arrow{background-position:0 -21px}.elfinder-navbar-icon{width:16px;height:16px;position:absolute;top:50%;margin-top:-8px;background-image:url("../img/toolbar.png");background-repeat:no-repeat;background-position:0 -16px}.elfinder-ltr .elfinder-navbar-icon{left:14px}.elfinder-rtl .elfinder-navbar-icon{right:14px}.elfinder-tree .elfinder-navbar-root .elfinder-navbar-icon{background-position:0 0}.elfinder-places .elfinder-navbar-root .elfinder-navbar-icon{background-position:0 -48px}.ui-state-active .elfinder-navbar-icon,.elfinder-droppable-active .elfinder-navbar-icon,.ui-state-hover .elfinder-navbar-icon{background-position:0 -32px}.elfinder-navbar-subtree{display:none}.elfinder-ltr .elfinder-navbar-subtree{margin-left:12px}.elfinder-rtl .elfinder-navbar-subtree{margin-right:12px}.elfinder-navbar-spinner{width:14px;height:14px;position:absolute;display:block;top:50%;margin-top:-7px;background:url("../img/spinner-mini.gif") center center no-repeat}.elfinder-ltr .elfinder-navbar-spinner{left:0;margin-left:-2px}.elfinder-rtl .elfinder-navbar-spinner{right:0;margin-right:-2px}.elfinder-navbar .elfinder-perms{top:50%;margin-top:-8px}.elfinder-navbar .elfinder-lock{top:-2px}.elfinder-ltr .elfinder-navbar .elfinder-perms{left:18px}.elfinder-rtl .elfinder-navbar .elfinder-perms{right:18px}.elfinder-ltr .elfinder-navbar .elfinder-lock{left:18px}.elfinder-rtl .elfinder-navbar .elfinder-lock{right:18px}.elfinder-ltr .elfinder-navbar .elfinder-symlink{left:8px}.elfinder-rtl .elfinder-navbar .elfinder-symlink{right:8px}.elfinder-navbar .ui-resizable-handle{width:12px;background:url('../img/resize.png') center center no-repeat;left:0}.elfinder-nav-handle-icon{position:absolute;top:50%;margin:-8px 2px 0;opacity:.5;filter:Alpha(Opacity=50)}.elfinder-places{border:1px solid transparent}.elfinder-places.elfinder-droppable-active{border:1px solid #8cafed}.elfinder-quicklook{position:absolute;background:url("../img/quicklook-bg.png");display:none;overflow:hidden;border-radius:7px;-moz-border-radius:7px;-webkit-border-radius:7px;padding:20px 0 40px}.elfinder-quicklook .ui-resizable-se{width:14px;height:14px;right:5px;bottom:3px;background:url("../img/toolbar.png") 0 -496px no-repeat}.elfinder-quicklook-fullscreen{border-radius:0;-moz-border-radius:0;-webkit-border-radius:0;-webkit-background-clip:padding-box;padding:0;background:#000;z-index:90000;display:block}.elfinder-quicklook-fullscreen .elfinder-quicklook-titlebar{display:none}.elfinder-quicklook-fullscreen .elfinder-quicklook-preview{border:0 solid}.elfinder-quicklook-titlebar{text-align:center;background:#777;position:absolute;left:0;top:0;width:100%;height:20px;-moz-border-radius-topleft:7px;-webkit-border-top-left-radius:7px;border-top-left-radius:7px;-moz-border-radius-topright:7px;-webkit-border-top-right-radius:7px;border-top-right-radius:7px;cursor:move}.elfinder-quicklook-title{color:#fff;white-space:nowrap;overflow:hidden;padding:2px 0}.elfinder-quicklook-titlebar .ui-icon{position:absolute;left:4px;top:50%;margin-top:-8px;width:16px;height:16px;cursor:default}.elfinder-quicklook-preview{overflow:hidden;position:relative;border:0 solid;border-left:1px solid transparent;border-right:1px solid transparent;height:100%}.elfinder-quicklook-info-wrapper{position:absolute;width:100%;left:0;top:50%;margin-top:-50px}.elfinder-quicklook-info{padding:0 12px 0 112px}.elfinder-quicklook-info .elfinder-quicklook-info-data:first-child{color:#fff;font-weight:700;padding-bottom:.5em}.elfinder-quicklook-info-data{padding-bottom:.2em;color:#fff}.elfinder-quicklook .elfinder-cwd-icon{position:absolute;left:32px;top:50%;margin-top:-20px}.elfinder-quicklook-preview img{display:block;margin:0 auto}.elfinder-quicklook-navbar{position:absolute;left:50%;bottom:4px;width:140px;height:32px;padding:0;margin-left:-70px;border:1px solid transparent;border-radius:19px;-moz-border-radius:19px;-webkit-border-radius:19px}.elfinder-quicklook-fullscreen .elfinder-quicklook-navbar{width:188px;margin-left:-94px;padding:5px;border:1px solid #eee;background:#000}.elfinder-quicklook-fullscreen .elfinder-quicklook-navbar-icon-close,.elfinder-quicklook-fullscreen .elfinder-quicklook-navbar-separator{display:inline}.elfinder-quicklook-navbar-icon{width:32px;height:32px;margin:0 7px;float:left;background:url("../img/quicklook-icons.png") 0 0 no-repeat}.elfinder-quicklook-navbar-icon-fullscreen{background-position:0 -64px}.elfinder-quicklook-navbar-icon-fullscreen-off{background-position:0 -96px}.elfinder-quicklook-navbar-icon-prev{background-position:0 0}.elfinder-quicklook-navbar-icon-next{background-position:0 -32px}.elfinder-quicklook-navbar-icon-close{background-position:0 -128px;display:none}.elfinder-quicklook-navbar-separator{width:1px;height:32px;float:left;border-left:1px solid #fff;display:none}.elfinder-quicklook-preview-text-wrapper{width:100%;height:100%;background:#fff;color:#222;overflow:auto}pre.elfinder-quicklook-preview-text{margin:0;padding:3px 9px}.elfinder-quicklook-preview-html,.elfinder-quicklook-preview-pdf{width:100%;height:100%;background:#fff;border:0 solid;margin:0}.elfinder-quicklook-preview-flash{width:100%;height:100%}.elfinder-quicklook-preview-audio{width:100%;position:absolute;bottom:0;left:0}embed.elfinder-quicklook-preview-audio{height:30px;background:0 0}.elfinder-quicklook-preview-video{width:100%;height:100%}.elfinder-statusbar{text-align:center;font-weight:400;padding:.2em .5em;border-right:0 solid transparent;border-bottom:0 solid transparent;border-left:0 solid transparent}.elfinder-statusbar a{text-decoration:none}.elfinder-path{max-width:30%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-o-text-overflow:ellipsis}.elfinder-ltr .elfinder-path{float:left}.elfinder-rtl .elfinder-path{float:right}.elfinder-stat-size{white-space:nowrap}.elfinder-ltr .elfinder-stat-size{float:right}.elfinder-rtl .elfinder-stat-size{float:left}.elfinder-stat-selected{white-space:nowrap;overflow:hidden}.elfinder-toolbar{padding:4px 0 3px;border-left:0 solid transparent;border-top:0 solid transparent;border-right:0 solid transparent}.elfinder-buttonset{margin:1px 4px;float:left;background:0 0;padding:0;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px}.elfinder .elfinder-button{width:16px;height:16px;margin:0;padding:4px;float:left;overflow:hidden;position:relative;border:0 solid}.elfinder .ui-icon-search{cursor:pointer}.elfinder-button:first-child{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.elfinder-button:last-child{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.elfinder-toolbar-button-separator{float:left;padding:0;height:24px;border-top:0 solid;border-right:0 solid;border-bottom:0 solid;width:0}.elfinder .elfinder-button.ui-state-disabled{opacity:1;filter:Alpha(Opacity=100)}.elfinder .elfinder-button.ui-state-disabled .elfinder-button-icon{opacity:.4;filter:Alpha(Opacity=40)}.elfinder-rtl .elfinder-buttonset{float:right}.elfinder-button-icon{width:16px;height:16px;display:block;background:url('../img/toolbar.png') no-repeat}.elfinder-button-icon-home{background-position:0 0}.elfinder-button-icon-back{background-position:0 -112px}.elfinder-button-icon-forward{background-position:0 -128px}.elfinder-button-icon-up{background-position:0 -144px}.elfinder-button-icon-reload{background-position:0 -160px}.elfinder-button-icon-open{background-position:0 -176px}.elfinder-button-icon-mkdir{background-position:0 -192px}.elfinder-button-icon-mkfile{background-position:0 -208px}.elfinder-button-icon-rm{background-position:0 -224px}.elfinder-button-icon-copy{background-position:0 -240px}.elfinder-button-icon-cut{background-position:0 -256px}.elfinder-button-icon-paste{background-position:0 -272px}.elfinder-button-icon-getfile{background-position:0 -288px}.elfinder-button-icon-duplicate{background-position:0 -304px}.elfinder-button-icon-rename{background-position:0 -320px}.elfinder-button-icon-edit{background-position:0 -336px}.elfinder-button-icon-quicklook{background-position:0 -352px}.elfinder-button-icon-upload{background-position:0 -368px}.elfinder-button-icon-download{background-position:0 -384px}.elfinder-button-icon-info{background-position:0 -400px}.elfinder-button-icon-extract{background-position:0 -416px}.elfinder-button-icon-archive{background-position:0 -432px}.elfinder-button-icon-view{background-position:0 -448px}.elfinder-button-icon-view-list{background-position:0 -464px}.elfinder-button-icon-help{background-position:0 -480px}.elfinder-button-icon-resize{background-position:0 -512px}.elfinder-button-icon-search{background-position:0 -561px}.elfinder-button-icon-sort{background-position:0 -577px}.elfinder-button-icon-rotate-r{background-position:0 -625px}.elfinder-button-icon-rotate-l{background-position:0 -641px}.elfinder-button-icon-netunmount{background-position:0 -96px}.elfinder-button-icon-pixlr{background-position:0 -673px}.elfinder .elfinder-menubutton{overflow:visible}.elfinder-button-menu{position:absolute;left:0;top:25px;padding:3px 0}.elfinder-button-menu-item{white-space:nowrap;cursor:default;padding:5px 19px;position:relative}.elfinder-button-menu .ui-state-hover{border:0 solid}.elfinder-button-menu-item-separated{border-top:1px solid #ccc}.elfinder-button-menu-item .ui-icon{width:16px;height:16px;position:absolute;left:2px;top:50%;margin-top:-8px;display:none}.elfinder-button-menu-item-selected .ui-icon{display:block}.elfinder-button-menu-item-selected-asc .ui-icon-arrowthick-1-n,.elfinder-button-menu-item-selected-desc .ui-icon-arrowthick-1-s{display:none}.elfinder-button form{position:absolute;top:0;right:0;opacity:0;filter:Alpha(Opacity=0);cursor:pointer}.elfinder .elfinder-button form input{background:0 0;cursor:default}.elfinder .elfinder-button-search{border:0 solid;background:0 0;padding:0;margin:1px 4px;height:auto;min-height:26px;float:right;width:202px}.elfinder-ltr .elfinder-button-search{float:right;margin-right:10px}.elfinder-rtl .elfinder-button-search{float:left;margin-left:10px}.elfinder-button-search input{width:160px;height:22px;padding:0 20px;line-height:22px;border:1px solid #aaa;-moz-border-radius:12px;-webkit-border-radius:12px;border-radius:12px;outline:0 solid}.elfinder-rtl .elfinder-button-search input{direction:rtl}.elfinder-button-search .ui-icon{position:absolute;height:18px;top:50%;margin:-9px 4px 0;opacity:.6;filter:Alpha(Opacity=60)}.elfinder-ltr .elfinder-button-search .ui-icon-search{left:0}.elfinder-rtl .elfinder-button-search .ui-icon-search,.elfinder-ltr .elfinder-button-search .ui-icon-close{right:0}.elfinder-rtl .elfinder-button-search .ui-icon-close{left:0}
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/css/index.html b/deployed/windwalker/media/windwalker/js/elfinder/css/index.html
new file mode 100644
index 00000000..3af63015
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/elfinder/css/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/css/theme.css b/deployed/windwalker/media/windwalker/js/elfinder/css/theme.css
new file mode 100644
index 00000000..add4bee5
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/elfinder/css/theme.css
@@ -0,0 +1,50 @@
+/**
+ * MacOS X like theme for elFinder.
+ * Required jquery ui "smoothness" theme.
+ *
+ * @author Dmitry (dio) Levashov
+ **/
+
+/* dialogs */
+.std42-dialog, .std42-dialog .ui-widget-content { background-color:#ededed; background-image:none; background-clip: content-box; }
+
+/* navbar */
+.elfinder .elfinder-navbar { background:#dde4eb; }
+.elfinder-navbar .ui-state-hover { background:transparent; border-color:transparent; }
+.elfinder-navbar .ui-state-active { background: #3875d7; border-color:#3875d7; color:#fff; }
+.elfinder-navbar .elfinder-droppable-active {background:#A7C6E5 !important;}
+/* disabled elfinder */
+.elfinder-disabled .elfinder-navbar .ui-state-active { background: #dadada; border-color:#aaa; color:#fff; }
+
+
+/* current directory */
+/* selected file in "icons" view */
+.elfinder-cwd-view-icons .elfinder-cwd-file .ui-state-hover { background:#ccc; }
+/* list view*/
+.elfinder-cwd table tr:nth-child(odd) { background-color:#edf3fe; }
+.elfinder-cwd table tr { border-top:1px solid #fff; }
+
+/* common selected background/color */
+.elfinder-cwd-view-icons .elfinder-cwd-file .elfinder-cwd-filename.ui-state-hover,
+.elfinder-cwd table td.ui-state-hover,
+.elfinder-button-menu .ui-state-hover { background: #3875d7; color:#fff;}
+/* disabled elfinder */
+.elfinder-disabled .elfinder-cwd-view-icons .elfinder-cwd-file .elfinder-cwd-filename.ui-state-hover,
+.elfinder-disabled .elfinder-cwd table td.ui-state-hover { background:#dadada;}
+
+/* statusbar */
+.elfinder .elfinder-statusbar { color:#555; }
+.elfinder .elfinder-statusbar a { text-decoration:none; color:#555;}
+
+
+.std42-dialog .elfinder-help, .std42-dialog .elfinder-help .ui-widget-content { background:#fff;}
+
+/* contextmenu */
+.elfinder-contextmenu .ui-state-hover { background: #3875d7; color:#fff; }
+.elfinder-contextmenu .ui-state-hover .elfinder-contextmenu-arrow { background-image:url('../img/arrows-active.png'); }
+
+
+
+
+
+
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/files/index.html b/deployed/windwalker/media/windwalker/js/elfinder/files/index.html
new file mode 100644
index 00000000..3af63015
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/elfinder/files/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/arrows-active.png b/deployed/windwalker/media/windwalker/js/elfinder/img/arrows-active.png
new file mode 100644
index 00000000..2ad71094
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/arrows-active.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/arrows-normal.png b/deployed/windwalker/media/windwalker/js/elfinder/img/arrows-normal.png
new file mode 100644
index 00000000..9d8b4d2a
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/arrows-normal.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/crop.gif b/deployed/windwalker/media/windwalker/js/elfinder/img/crop.gif
new file mode 100644
index 00000000..72ea7ccb
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/crop.gif differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/dialogs.png b/deployed/windwalker/media/windwalker/js/elfinder/img/dialogs.png
new file mode 100644
index 00000000..20de3574
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/dialogs.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/icons-big.png b/deployed/windwalker/media/windwalker/js/elfinder/img/icons-big.png
new file mode 100644
index 00000000..00be0a6b
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/icons-big.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/icons-small.png b/deployed/windwalker/media/windwalker/js/elfinder/img/icons-small.png
new file mode 100644
index 00000000..95849dce
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/icons-small.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/index.html b/deployed/windwalker/media/windwalker/js/elfinder/img/index.html
new file mode 100644
index 00000000..3af63015
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/elfinder/img/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/logo.png b/deployed/windwalker/media/windwalker/js/elfinder/img/logo.png
new file mode 100644
index 00000000..c1036de6
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/logo.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/progress.gif b/deployed/windwalker/media/windwalker/js/elfinder/img/progress.gif
new file mode 100644
index 00000000..8bab11e3
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/progress.gif differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/quicklook-bg.png b/deployed/windwalker/media/windwalker/js/elfinder/img/quicklook-bg.png
new file mode 100644
index 00000000..aedeadd6
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/quicklook-bg.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/quicklook-icons.png b/deployed/windwalker/media/windwalker/js/elfinder/img/quicklook-icons.png
new file mode 100644
index 00000000..76df30c9
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/quicklook-icons.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/resize.png b/deployed/windwalker/media/windwalker/js/elfinder/img/resize.png
new file mode 100644
index 00000000..6ec17cd3
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/resize.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/spinner-mini.gif b/deployed/windwalker/media/windwalker/js/elfinder/img/spinner-mini.gif
new file mode 100644
index 00000000..5b33f7e5
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/spinner-mini.gif differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/toolbar.png b/deployed/windwalker/media/windwalker/js/elfinder/img/toolbar.png
new file mode 100644
index 00000000..aaf3445c
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/toolbar.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/volume_icon_dropbox.png b/deployed/windwalker/media/windwalker/js/elfinder/img/volume_icon_dropbox.png
new file mode 100644
index 00000000..13a0d1ec
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/volume_icon_dropbox.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/volume_icon_ftp.png b/deployed/windwalker/media/windwalker/js/elfinder/img/volume_icon_ftp.png
new file mode 100644
index 00000000..605729d3
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/volume_icon_ftp.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/volume_icon_local.png b/deployed/windwalker/media/windwalker/js/elfinder/img/volume_icon_local.png
new file mode 100644
index 00000000..2c024e40
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/volume_icon_local.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/img/volume_icon_sql.png b/deployed/windwalker/media/windwalker/js/elfinder/img/volume_icon_sql.png
new file mode 100644
index 00000000..0792546d
Binary files /dev/null and b/deployed/windwalker/media/windwalker/js/elfinder/img/volume_icon_sql.png differ
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/index.html b/deployed/windwalker/media/windwalker/js/elfinder/index.html
new file mode 100644
index 00000000..3af63015
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/elfinder/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/js/elfinder.min.js b/deployed/windwalker/media/windwalker/js/elfinder/js/elfinder.min.js
new file mode 100644
index 00000000..b03685a6
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/elfinder/js/elfinder.min.js
@@ -0,0 +1,27 @@
+/*!
+ * elFinder - file manager for web
+ * Version 2.1_n (Nightly: 8221e18) (2013-06-26)
+ * http://elfinder.org
+ *
+ * Copyright 2009-2012, Studio 42
+ * Licensed under a 3 clauses BSD license
+ */
+(function(a){window.elFinder=function(b,c){this.time("load");var d=this,b=a(b),e=a("
").append(b.contents()),f=b.attr("style"),g=b.attr("id")||"",h="elfinder-"+(g||Math.random().toString().substr(2,7)),i="mousedown."+h,j="keydown."+h,k="keypress."+h,l=!0,m=!0,n=["enable","disable","load","open","reload","select","add","remove","change","dblclick","getfile","lockfiles","unlockfiles","dragstart","dragstop"],o={},p="",q={path:"",url:"",tmbUrl:"",disabled:[],separator:"/",archives:[],extract:[],copyOverwrite:!0,tmb:!1},r={},s=[],t={},u={},v=[],w=[],x=[],y=new d.command(d),z="auto",A=400,B=a(document.createElement("audio")).hide().appendTo("body")[0],C,D=function(b){if(b.init)r={};else for(var c in r)r.hasOwnProperty(c)&&r[c].mime!="directory"&&r[c].phash==p&&a.inArray(c,w)===-1&&delete r[c];p=b.cwd.hash,E(b.files),r[p]||E([b.cwd]),d.lastDir(p)},E=function(a){var b=a.length,c;while(b--){c=a[b];if(c.name&&c.hash&&c.mime){if(!c.phash){var e="volume_"+c.name,f=d.i18n(e);e!=f&&(c.i18=f)}r[c.hash]=c}}},F=function(b){var c=b.keyCode,e=!!b.ctrlKey||!!b.metaKey;l&&(a.each(u,function(a,f){f.type==b.type&&f.keyCode==c&&f.shiftKey==b.shiftKey&&f.ctrlKey==e&&f.altKey==b.altKey&&(b.preventDefault(),b.stopPropagation(),f.callback(b,d),d.debug("shortcut-exec",a+" : "+f.description))}),c==9&&!a(b.target).is(":input")&&b.preventDefault())},G=new Date,H,I;this.api=null,this.newAPI=!1,this.oldAPI=!1,this.OS=navigator.userAgent.indexOf("Mac")!==-1?"mac":navigator.userAgent.indexOf("Win")!==-1?"win":"other",this.UA=function(){var a=!document.uniqueID&&!window.opera&&!window.sidebar&&window.localStorage&&typeof window.orientation=="undefined";return{ltIE6:typeof window.addEventListener=="undefined"&&typeof document.documentElement.style.maxHeight=="undefined",ltIE7:typeof window.addEventListener=="undefined"&&typeof document.querySelectorAll=="undefined",ltIE8:typeof window.addEventListener=="undefined"&&typeof document.getElementsByClassName=="undefined",IE:document.uniqueID,Firefox:window.sidebar,Opera:window.opera,Webkit:a,Chrome:a&&window.chrome,Safari:a&&!window.chrome,Mobile:typeof window.orientation!="undefined"}}(),this.options=a.extend(!0,{},this._options,c||{}),c.ui&&(this.options.ui=c.ui),c.commands&&(this.options.commands=c.commands),c.uiOptions&&c.uiOptions.toolbar&&(this.options.uiOptions.toolbar=c.uiOptions.toolbar),a.extend(this.options.contextmenu,c.contextmenu),this.requestType=/^(get|post)$/i.test(this.options.requestType)?this.options.requestType.toLowerCase():"get",this.customData=a.isPlainObject(this.options.customData)?this.options.customData:{},this.id=g,this.uploadURL=c.urlUpload||c.url,this.namespace=h,this.lang=this.i18[this.options.lang]&&this.i18[this.options.lang].messages?this.options.lang:"en",I=this.lang=="en"?this.i18.en:a.extend(!0,{},this.i18.en,this.i18[this.lang]),this.direction=I.direction,this.messages=I.messages,this.dateFormat=this.options.dateFormat||I.dateFormat,this.fancyFormat=this.options.fancyDateFormat||I.fancyDateFormat,this.today=(new Date(G.getFullYear(),G.getMonth(),G.getDate())).getTime()/1e3,this.yesterday=this.today-86400,H=this.options.UTCDate?"UTC":"",this.getHours="get"+H+"Hours",this.getMinutes="get"+H+"Minutes",this.getSeconds="get"+H+"Seconds",this.getDate="get"+H+"Date",this.getDay="get"+H+"Day",this.getMonth="get"+H+"Month",this.getFullYear="get"+H+"FullYear",this.cssClass="ui-helper-reset ui-helper-clearfix ui-widget ui-widget-content ui-corner-all elfinder elfinder-"+(this.direction=="rtl"?"rtl":"ltr")+" "+this.options.cssClass,this.storage=function(){try{return"localStorage"in window&&window.localStorage!==null?d.localStorage:d.cookie}catch(a){return d.cookie}}(),this.viewType=this.storage("view")||this.options.defaultView||"icons",this.sortType=this.storage("sortType")||this.options.sortType||"name",this.sortOrder=this.storage("sortOrder")||this.options.sortOrder||"asc",this.sortStickFolders=this.storage("sortStickFolders"),this.sortStickFolders===null?this.sortStickFolders=!!this.options.sortStickFolders:this.sortStickFolders=!!this.sortStickFolders,this.sortRules=a.extend(!0,{},this._sortRules,this.options.sortsRules),a.each(this.sortRules,function(a,b){typeof b!="function"&&delete d.sortRules[a]}),this.compare=a.proxy(this.compare,this),this.notifyDelay=this.options.notifyDelay>0?parseInt(this.options.notifyDelay):500,this.draggable={appendTo:"body",addClasses:!0,delay:30,revert:!0,refreshPositions:!0,cursor:"move",cursorAt:{left:50,top:47},drag:function(a,b){b.helper.data("locked")||b.helper.toggleClass("elfinder-drag-helper-plus",a.shiftKey||a.ctrlKey||a.metaKey)},start:function(b,c){var d=a.map(c.helper.data("files")||[],function(a){return a||null}),e,f;e=d.length;while(e--){f=d[e];if(r[f].locked){c.helper.addClass("elfinder-drag-helper-plus").data("locked",!0);break}}},stop:function(){d.trigger("focus").trigger("dragstop")},helper:function(b,c){var e=this.id?a(this):a(this).parents("[id]:first"),f=a('
'),g=function(a){return'
'},h,i;return d.trigger("dragstart",{target:e[0],originalEvent:b}),h=e.is("."+d.res("class","cwdfile"))?d.selected():[d.navId2Hash(e.attr("id"))],f.append(g(r[h[0]].mime)).data("files",h).data("locked",!1),(i=h.length)>1&&f.append(g(r[h[i-1]].mime)+''+i+" "),f}},this.droppable={tolerance:"pointer",accept:".elfinder-cwd-file-wrapper,.elfinder-navbar-dir,.elfinder-cwd-file",hoverClass:this.res("class","adroppable"),drop:function(b,c){var e=a(this),f=a.map(c.helper.data("files")||[],function(a){return a||null}),g=[],h="class",i,j,k,l;e.is("."+d.res(h,"cwd"))?j=p:e.is("."+d.res(h,"cwdfile"))?j=e.attr("id"):e.is("."+d.res(h,"navdir"))&&(j=d.navId2Hash(e.attr("id"))),i=f.length;while(i--)l=f[i],l!=j&&r[l].phash!=j&&g.push(l);g.length&&(c.helper.hide(),d.clipboard(g,!(b.ctrlKey||b.shiftKey||b.metaKey||c.helper.data("locked"))),d.exec("paste",j),d.trigger("drop",{files:f}))}},this.enabled=function(){return b.is(":visible")&&l},this.visible=function(){return b.is(":visible")},this.root=function(a){var b=r[a||p],c;while(b&&b.phash)b=r[b.phash];if(b)return b.hash;while(c in r&&r.hasOwnProperty(c)){b=r[c];if(!b.phash&&!b.mime=="directory"&&b.read)return b.hash}return""},this.cwd=function(){return r[p]||{}},this.option=function(a){return q[a]||""},this.file=function(a){return r[a]},this.files=function(){return a.extend(!0,{},r)},this.parents=function(a){var b=[],c;while(c=this.file(a))b.unshift(c.hash),a=c.phash;return b},this.path2array=function(a,b){var c,d=[];while(a&&(c=r[a])&&c.hash)d.unshift(b&&c.i18?c.i18:c.name),a=c.phash;return d},this.path=function(a,b){return r[a]&&r[a].path?r[a].path:this.path2array(a,b).join(q.separator)},this.url=function(b){var c=r[b];if(!c||!c.read)return"";c.url=="1"&&this.request({data:{cmd:"url",target:b},preventFail:!0,options:{async:!1}}).done(function(a){c.url=a.url||""}).fail(function(){c.url=""});if(c.url)return c.url;if(q.url)return q.url+a.map(this.path2array(b),function(a){return encodeURIComponent(a)}).slice(1).join("/");var d=a.extend({},this.customData,{cmd:"file",target:c.hash});return this.oldAPI&&(d.cmd="open",d.current=c.phash),this.options.url+(this.options.url.indexOf("?")===-1?"?":"&")+a.param(d,!0)},this.tmb=function(a){var b=r[a],c=b&&b.tmb&&b.tmb!=1?q.tmbUrl+b.tmb:"";return c&&(this.UA.Opera||this.UA.IE)&&(c+="?_="+(new Date).getTime()),c},this.selected=function(){return s.slice(0)},this.selectedFiles=function(){return a.map(s,function(b){return r[b]?a.extend({},r[b]):null})},this.fileByName=function(a,b){var c;for(c in r)if(r.hasOwnProperty(c)&&r[c].phash==b&&r[c].name==a)return r[c]},this.validResponse=function(a,b){return b.error||this.rules[this.rules[a]?a:"defaults"](b)},this.request=function(b){var c=this,d=this.options,e=a.Deferred(),f=a.extend({},d.customData,{mimes:d.onlyMimes},b.data||b),g=f.cmd,h=!b.preventDefault&&!b.preventFail,i=!b.preventDefault&&!b.preventDone,j=a.extend({},b.notify),k=!!b.raw,l=b.syncOnFail,m,b=a.extend({url:d.url,async:!0,type:this.requestType,dataType:"json",cache:!1,data:f},b.options||{}),n=function(
+b){b.warning&&c.error(b.warning),g=="open"&&D(a.extend(!0,{},b)),b.removed&&b.removed.length&&c.remove(b),b.added&&b.added.length&&c.add(b),b.changed&&b.changed.length&&c.change(b),c.trigger(g,b),b.sync&&c.sync()},o=function(a,b){var c;switch(b){case"abort":c=a.quiet?"":["errConnect","errAbort"];break;case"timeout":c=["errConnect","errTimeout"];break;case"parsererror":c=["errResponse","errDataNotJSON"];break;default:a.status==403?c=["errConnect","errAccess"]:a.status==404?c=["errConnect","errNotFound"]:c="errConnect"}e.reject(c,a,b)},p=function(b){if(k)return e.resolve(b);if(!b)return e.reject(["errResponse","errDataEmpty"],r);if(!a.isPlainObject(b))return e.reject(["errResponse","errDataNotJSON"],r);if(b.error)return e.reject(b.error,r);if(!c.validResponse(g,b))return e.reject("errResponse",r);b=c.normalize(b),c.api||(c.api=b.api||1,c.newAPI=c.api>=2,c.oldAPI=!c.newAPI),b.options&&(q=a.extend({},q,b.options)),b.netDrivers&&(c.netDrivers=b.netDrivers),e.resolve(b),b.debug&&c.debug("backend-debug",b.debug)},r,s;i&&e.done(n),e.fail(function(a){a&&(h?c.error(a):c.debug("error",c.i18n(a)))});if(!g)return e.reject("errCmdReq");l&&e.fail(function(a){a&&c.sync()}),j.type&&j.cnt&&(m=setTimeout(function(){c.notify(j),e.always(function(){j.cnt=-(parseInt(j.cnt)||0),c.notify(j)})},c.notifyDelay),e.always(function(){clearTimeout(m)}));if(g=="open")while(s=x.pop())s.state()=="pending"&&(s.quiet=!0,s.abort());return delete b.preventFail,r=this.transport.send(b).fail(o).done(p),g=="open"&&(x.unshift(r),e.always(function(){var b=a.inArray(r,x);b!==-1&&x.splice(b,1)})),e},this.diff=function(b){var c={},d=[],e=[],f=[],g=function(a){var b=f.length;while(b--)if(f[b].hash==a)return!0};return a.each(b,function(a,b){c[b.hash]=b}),a.each(r,function(a,b){!c[a]&&e.push(a)}),a.each(c,function(b,c){var e=r[b];e?a.each(c,function(a){if(c[a]!=e[a])return f.push(c),!1}):d.push(c)}),a.each(e,function(b,d){var h=r[d],i=h.phash;i&&h.mime=="directory"&&a.inArray(i,e)===-1&&c[i]&&!g(i)&&f.push(c[i])}),{added:d,removed:e,changed:f}},this.sync=function(){var b=this,c=a.Deferred().done(function(){b.trigger("sync")}),d={data:{cmd:"open",init:1,target:p,tree:this.ui.tree?1:0},preventDefault:!0},e={data:{cmd:"tree",target:p==this.root()?p:this.file(p).phash},preventDefault:!0};return a.when(this.request(d),this.request(e)).fail(function(a){c.reject(a),a&&b.request({data:{cmd:"open",target:b.lastDir(""),tree:1,init:1},notify:{type:"open",cnt:1,hideCnt:!0},preventDefault:!0})}).done(function(a,d){var e=b.diff(a.files.concat(d&&d.tree?d.tree:[]));return e.added.push(a.cwd),e.removed.length&&b.remove(e),e.added.length&&b.add(e),e.changed.length&&b.change(e),c.resolve(e)}),c},this.upload=function(a){return this.transport.upload(a,this)},this.bind=function(a,b){var c;if(typeof b=="function"){a=(""+a).toLowerCase().split(/\s+/);for(c=0;c-1&&c.splice(d,1),b=null,this},this.trigger=function(b,c){var b=b.toLowerCase(),d=t[b]||[],e,f;this.debug("event-"+b,c);if(d.length){b=a.Event(b);for(e=0;e0?e:e.charCodeAt(0):a.ui.keyCode[e],e&&!u[d]&&(u[d]={keyCode:e,altKey:a.inArray("ALT",g)!=-1,ctrlKey:a.inArray("CTRL",g)!=-1,shiftKey:a.inArray("SHIFT",g)!=-1,type:b.type||"keydown",callback:b.callback,description:b.description,pattern:d})}return this},this.shortcuts=function(){var b=[];return a.each(u,function(a,c){b.push([c.pattern,d.i18n(c.description)])}),b},this.clipboard=function(b,c){var d=function(){return a.map(v,function(a){return a.hash})};return b!==void 0&&(v.length&&this.trigger("unlockfiles",{files:d()}),w=[],v=a.map(b||[],function(a){var b=r[a];return b?(w.push(a),{hash:a,phash:b.phash,name:b.name,mime:b.mime,read:b.read,locked:b.locked,cut:!!c}):null}),this.trigger("changeclipboard",{clipboard:v.slice(0,v.length)}),c&&this.trigger("lockfiles",{files:d()})),v.slice(0,v.length)},this.isCommandEnabled=function(b){return this._commands[b]?a.inArray(b,q.disabled)===-1:!1},this.exec=function(b,c,d){return this._commands[b]&&this.isCommandEnabled(b)?this._commands[b].exec(c,d):a.Deferred().reject("No such command")},this.dialog=function(c,d){return a("
").append(c).appendTo(b).elfinderdialog(d)},this.getUI=function(a){return this.ui[a]||b},this.command=function(a){return a===void 0?this._commands:this._commands[a]},this.resize=function(a,c){b.css("width",a).height(c).trigger("resize"),this.trigger("resize",{width:b.width(),height:b.height()})},this.restoreSize=function(){this.resize(z,A)},this.show=function(){b.show(),this.enable().trigger("show")},this.hide=function(){this.disable().trigger("hide"),b.hide()},this.destroy=function(){b&&b[0].elfinder&&(this.trigger("destroy").disable(),t={},u={},a(document).add(b).unbind("."+this.namespace),d.trigger=function(){},b.children().remove(),b.append(e.contents()).removeClass(this.cssClass).attr("style",f),b[0].elfinder=null,C&&clearInterval(C))};if(!(a.fn.selectable&&a.fn.draggable&&a.fn.droppable))return alert(this.i18n("errJqui"));if(!b.length)return alert(this.i18n("errNode"));if(!this.options.url)return alert(this.i18n("errURL"));a.extend(a.ui.keyCode,{F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120}),this.dragUpload=!1,this.xhrUpload=(typeof XMLHttpRequestUpload!="undefined"||typeof XMLHttpRequestEventTarget!="undefined")&&typeof File!="undefined"&&typeof FormData!="undefined",this.transport={},typeof this.options.transport=="object"&&(this.transport=this.options.transport,typeof this.transport.init=="function"&&this.transport.init(this)),typeof this.transport.send!="function"&&(this.transport.send=function(b){return a.ajax(b)}),this.transport.upload=="iframe"?this.transport.upload=a.proxy(this.uploads.iframe,this):typeof this.transport.upload=="function"?this.dragUpload=!!this.options.dragUploadAllow:this.xhrUpload&&!!this.options.dragUploadAllow?(this.transport.upload=a.proxy(this.uploads.xhr,this),this.dragUpload=!0):this.transport.upload=a.proxy(this.uploads.iframe,this),this.error=function(){var a=arguments[0];return arguments.length==1&&typeof a=="function"?d.bind("error",a):d.trigger("error",{error:a})},a.each(["enable","disable","load","open","reload","select","add","remove","change","dblclick","getfile","lockfiles","unlockfiles","dragstart","dragstop","search","searchend","viewchange"],function(b,c){d[c]=function(){var b=arguments[0];return arguments.length==1&&typeof b=="function"?d.bind(c,b):d.trigger(c,a.isPlainObject(b)?b:{})}}),this.enable(function(){!l&&d.visible()&&d.ui.overlay.is(":hidden")&&(l=!0,a("texarea:focus,input:focus,button").blur(),b.removeClass("elfinder-disabled"))}).disable(function(){m=l,l=!1,b.addClass("elfinder-disabled")}).open(function(){s=[]}).select(function(b){s=a.map(b.data.selected||b.data.value||[],function(a){return r[a]?a:null})}).error(function(b){var c={cssClass:"elfinder-dialog-error",title:d.i18n(d.i18n("error")),resizable:!1,destroyOnClose:!0,buttons:{}};c.buttons[d.i18n(d.i18n("btnClose"))]=function(){a(this).elfinderdialog("close")},d.dialog(' '+d.i18n(b.data.error),c)}).bind("tree parents",function(a){E(a.data.tree||[])}).bind("tmb",function(b){a.each(b.data.images||[],function(a,b){r[a]&&(r[a].tmb=b)})}).add(function(a){E(a.data.added||[])}).change(function(b){a.each(b.data.changed||[],function(b,c){var d=c.hash;r[d]=r[d]?a.extend(r[d],c):c})}).remove(function(b){var c=b.data.removed||[],d=c.length,e=function(b){var c=r[b];c&&(c.mime=="directory"&&c.dirs&&a.each(r,function(a,c){c.phash==b&&e(a)}),delete r[b])};while(d--)e(c[d])}).bind("search",function(a){E(a.data.files)}).bind("rm",function(b){var c=B.canPlayType&&B.canPlayType('audio/wav; codecs="1"'
+);c&&c!=""&&c!="no"&&a(B).html('')[0].play()}),a.each(this.options.handlers,function(a,b){d.bind(a,b)}),this.history=new this.history(this),typeof this.options.getFileCallback=="function"&&this.commands.getfile&&(this.bind("dblclick",function(a){a.preventDefault(),d.exec("getfile").fail(function(){d.exec("open")})}),this.shortcut({pattern:"enter",description:this.i18n("cmdgetfile"),callback:function(){d.exec("getfile").fail(function(){d.exec(d.OS=="mac"?"rename":"open")})}}).shortcut({pattern:"ctrl+enter",description:this.i18n(this.OS=="mac"?"cmdrename":"cmdopen"),callback:function(){d.exec(d.OS=="mac"?"rename":"open")}})),this._commands={},a.isArray(this.options.commands)||(this.options.commands=[]),a.each(["open","reload","back","forward","up","home","info","quicklook","getfile","help"],function(b,c){a.inArray(c,d.options.commands)===-1&&d.options.commands.push(c)}),a.each(this.options.commands,function(b,c){var e=d.commands[c];a.isFunction(e)&&!d._commands[c]&&(e.prototype=y,d._commands[c]=new e,d._commands[c].setup(c,d.options.commandsOptions[c]||{}))}),b.addClass(this.cssClass).bind(i,function(){!l&&d.enable()}),this.ui={workzone:a("
").appendTo(b).elfinderworkzone(this),navbar:a("
").appendTo(b).elfindernavbar(this,this.options.uiOptions.navbar||{}),contextmenu:a("
").appendTo(b).elfindercontextmenu(this),overlay:a("
").appendTo(b).elfinderoverlay({show:function(){d.disable()},hide:function(){m&&d.enable()}}),cwd:a("
").appendTo(b).elfindercwd(this,this.options.uiOptions.cwd||{}),notify:this.dialog("",{cssClass:"elfinder-dialog-notify",position:{top:"12px",right:"12px"},resizable:!1,autoOpen:!1,title:" ",width:280}),statusbar:a('').hide().appendTo(b)},a.each(this.options.ui||[],function(c,e){var f="elfinder"+e,g=d.options.uiOptions[e]||{};!d.ui[e]&&a.fn[f]&&(d.ui[e]=a("<"+(g.tag||"div")+"/>").appendTo(b)[f](d,g))}),b[0].elfinder=this,this.options.resizable&&a.fn.resizable&&b.resizable({handles:"se",minWidth:300,minHeight:200}),this.options.width&&(z=this.options.width),this.options.height&&(A=parseInt(this.options.height)),d.resize(z,A),a(document).bind("click."+this.namespace,function(c){l&&!a(c.target).closest(b).length&&d.disable()}).bind(j+" "+k,F),this.trigger("init").request({data:{cmd:"open",target:d.lastDir(),init:1,tree:this.ui.tree?1:0},preventDone:!0,notify:{type:"open",cnt:1,hideCnt:!0},freeze:!0}).fail(function(){d.trigger("fail").disable().lastDir(""),t={},u={},a(document).add(b).unbind("."+this.namespace),d.trigger=function(){}}).done(function(b){d.load().debug("api",d.api),b=a.extend(!0,{},b),D(b),d.trigger("open",b)}),this.one("load",function(){b.trigger("resize"),d.options.sync>1e3&&(C=setInterval(function(){d.sync()},d.options.sync))})},elFinder.prototype={res:function(a,b){return this.resources[a]&&this.resources[a][b]},i18:{en:{translator:"",language:"English",direction:"ltr",dateFormat:"d.m.Y H:i",fancyDateFormat:"$1 H:i",messages:{}},months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]},kinds:{unknown:"Unknown",directory:"Folder",symlink:"Alias","symlink-broken":"AliasBroken","application/x-empty":"TextPlain","application/postscript":"Postscript","application/vnd.ms-office":"MsOffice","application/vnd.ms-word":"MsWord","application/vnd.openxmlformats-officedocument.wordprocessingml.document":"MsWord","application/vnd.ms-word.document.macroEnabled.12":"MsWord","application/vnd.openxmlformats-officedocument.wordprocessingml.template":"MsWord","application/vnd.ms-word.template.macroEnabled.12":"MsWord","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":"MsWord","application/vnd.ms-excel":"MsExcel","application/vnd.ms-excel.sheet.macroEnabled.12":"MsExcel","application/vnd.openxmlformats-officedocument.spreadsheetml.template":"MsExcel","application/vnd.ms-excel.template.macroEnabled.12":"MsExcel","application/vnd.ms-excel.sheet.binary.macroEnabled.12":"MsExcel","application/vnd.ms-excel.addin.macroEnabled.12":"MsExcel","application/vnd.ms-powerpoint":"MsPP","application/vnd.openxmlformats-officedocument.presentationml.presentation":"MsPP","application/vnd.ms-powerpoint.presentation.macroEnabled.12":"MsPP","application/vnd.openxmlformats-officedocument.presentationml.slideshow":"MsPP","application/vnd.ms-powerpoint.slideshow.macroEnabled.12":"MsPP","application/vnd.openxmlformats-officedocument.presentationml.template":"MsPP","application/vnd.ms-powerpoint.template.macroEnabled.12":"MsPP","application/vnd.ms-powerpoint.addin.macroEnabled.12":"MsPP","application/vnd.openxmlformats-officedocument.presentationml.slide":"MsPP","application/vnd.ms-powerpoint.slide.macroEnabled.12":"MsPP","application/pdf":"PDF","application/xml":"XML","application/vnd.oasis.opendocument.text":"OO","application/vnd.oasis.opendocument.text-template":"OO","application/vnd.oasis.opendocument.text-web":"OO","application/vnd.oasis.opendocument.text-master":"OO","application/vnd.oasis.opendocument.graphics":"OO","application/vnd.oasis.opendocument.graphics-template":"OO","application/vnd.oasis.opendocument.presentation":"OO","application/vnd.oasis.opendocument.presentation-template":"OO","application/vnd.oasis.opendocument.spreadsheet":"OO","application/vnd.oasis.opendocument.spreadsheet-template":"OO","application/vnd.oasis.opendocument.chart":"OO","application/vnd.oasis.opendocument.formula":"OO","application/vnd.oasis.opendocument.database":"OO","application/vnd.oasis.opendocument.image":"OO","application/vnd.openofficeorg.extension":"OO","application/x-shockwave-flash":"AppFlash","application/flash-video":"Flash video","application/x-bittorrent":"Torrent","application/javascript":"JS","application/rtf":"RTF","application/rtfd":"RTF","application/x-font-ttf":"TTF","application/x-font-otf":"OTF","application/x-rpm":"RPM","application/x-web-config":"TextPlain","application/xhtml+xml":"HTML","application/docbook+xml":"DOCBOOK","application/x-awk":"AWK","application/x-gzip":"GZIP","application/x-bzip2":"BZIP","application/zip":"ZIP","application/x-zip":"ZIP","application/x-rar":"RAR","application/x-tar":"TAR","application/x-7z-compressed":"7z","application/x-jar":"JAR","text/plain":"TextPlain","text/x-php":"PHP","text/html":"HTML","text/javascript":"JS","text/css":"CSS","text/rtf":"RTF","text/rtfd":"RTF","text/x-c":"C","text/x-csrc":"C","text/x-chdr":"CHeader","text/x-c++":"CPP","text/x-c++src":"CPP","text/x-c++hdr":"CPPHeader","text/x-shellscript":"Shell","application/x-csh":"Shell","text/x-python":"Python","text/x-java":"Java","text/x-java-source":"Java","text/x-ruby":"Ruby","text/x-perl":"Perl","text/x-sql":"SQL","text/xml":"XML","text/x-comma-separated-values":"CSV","image/x-ms-bmp":"BMP","image/jpeg":"JPEG","image/gif":"GIF","image/png":"PNG","image/tiff":"TIFF","image/x-targa":"TGA","image/vnd.adobe.photoshop":"PSD","image/xbm":"XBITMAP","image/pxm":"PXM","audio/mpeg":"AudioMPEG","audio/midi":"AudioMIDI","audio/ogg":"AudioOGG","audio/mp4":"AudioMPEG4","audio/x-m4a":"AudioMPEG4","audio/wav":"AudioWAV","audio/x-mp3-playlist":"AudioPlaylist","video/x-dv":"VideoDV","video/mp4":"VideoMPEG4","video/mpeg":"VideoMPEG","video/x-msvideo":"VideoAVI","video/quicktime":"VideoMOV","video/x-ms-wmv":"VideoWM","video/x-flv":"VideoFlash","video/x-matroska":"VideoMKV","video/ogg":"VideoOGG"},rules:{defaults:function(b){return!b||b.added&&!a.isArray(b.added)||b.removed&&!a.isArray(b.removed)||b.changed&&!a.isArray(b.changed)?!1:!0},open:function(b){return b&&b.cwd&&b.files&&a.isPlainObject(b.cwd)&&a.isArray(b.files)},tree:function(b){return b&&b.tree&&a.isArray(b.tree)},parents:function(b){return b&&b.tree&&a.isArray(b.tree)},tmb:function(b){return b&&b.images&&(a.isPlainObject(b.images)||a.isArray(b.images))},upload:function(b){return b&&(a.isPlainObject(b.added)||a.isArray(b.added))},search:function(
+b){return b&&b.files&&a.isArray(b.files)}},commands:{},parseUploadData:function(b){var c;if(!a.trim(b))return{error:["errResponse","errDataEmpty"]};try{c=a.parseJSON(b)}catch(d){return{error:["errResponse","errDataNotJSON"]}}return this.validResponse("upload",c)?(c=this.normalize(c),c.removed=a.map(c.added||[],function(a){return a.hash}),c):{error:["errResponse"]}},iframeCnt:0,uploads:{checkFile:function(b,c){if(b.type=="data"){var d=a.Deferred(),e=[],f=[],g=[],h=[],i=0,j=function(b){var d=function(a){return Array.prototype.slice.call(a||[])},k=function(b,c){var d=a.Deferred();return typeof b=="undefined"?d.reject("empty"):b.isFile?b.file(function(a){d.resolve(a)},function(a){d.reject()}):d.reject("dirctory"),d.promise()};b.readEntries(function(a){if(!a.length){var l=h.length-1,m=function(a){k(h[a]).done(function(b){(c.OS!="win"||!b.name.match(/^(?:desktop\.ini|thumbs\.db)$/i))&&(c.OS!="mac"||!b.name.match(/^\.ds_store$/i))&&(f.push(h[a].fullPath),e.push(b))}).fail(function(b){b=="dirctory"?g.push(h[a]):b!="empty"}).always(function(){i--,a0?g.push(k):(i=0,d=k.createReader(),i++,j(d)))};return k(b.files.items),setTimeout(function r(){i>0?setTimeout(r,10):g.length>0?(k([g.shift()],!0),setTimeout(r,10)):d.resolve([e,f])},10),d.promise()}if(b.type=="files")return b.files;var l=[],m,n=b.files[0];if(b.type=="html"){m=/ ]+src=["']?([^"'> ]+)/ig;var o=[],p="",q;while(o=m.exec(n))p=o[1].replace(/&/g,"&"),p.match(/^http/)&&a.inArray(p,l)==-1&&l.push(p);q=n.match(/<\/a>/i);if(q&&q.length==1){m=/]+href=["']?([^"'> ]+)((?:.|\s)+)<\/a>/i;if(o=m.exec(n))o[2].match(/ "{}|\\^\[\]`\s]+)/ig;while(o=m.exec(n))p=o[1].replace(/&/g,"&"),a.inArray(p,l)==-1&&l.push(p)}return l},iframe:function(b,c){var d=c?c:this,e=b.input?b.input:!1,f=e?!1:d.uploads.checkFile(b,d),g=a.Deferred().fail(function(a){a&&d.error(a)}).done(function(a){a.warning&&d.error(a.warning),a.removed&&d.remove(a),a.added&&d.add(a),a.changed&&d.change(a),d.trigger("upload",a),a.sync&&d.sync()}),h="iframe-"+d.namespace+ ++d.iframeCnt,i=a(''),j=this.UA.IE,k=function(){p&&clearTimeout(p),o&&clearTimeout(o),n&&d.notify({type:"upload",cnt:-m}),setTimeout(function(){j&&a('').appendTo(i),i.remove(),l.remove()},100)},l=a('').bind("load",function(){l.unbind("load").bind("load",function(){var a=d.parseUploadData(l.contents().text());k(),a.error?g.reject(a.error):g.resolve(a)}),o=setTimeout(function(){n=!0,d.notify({type:"upload",cnt:m})},d.options.notifyDelay),d.options.iframeTimeout>0&&(p=setTimeout(function(){k(),g.reject([errors.connect,errors.timeout])},d.options.iframeTimeout)),i.submit()}),m,n,o,p;if(f&&f.length)a.each(f,function(a,b){i.append(' ')}),m=1;else{if(!(e&&a(e).is(":file")&&a(e).val()))return g.reject();i.append(e),m=e.files?e.files.length:1}return i.append(' ').append(' ').append(a(e).attr("name","upload[]")),a.each(d.options.onlyMimes||[],function(a,b){i.append(' ')}),a.each(d.options.customData,function(a,b){i.append(' ')}),i.appendTo("body"),l.appendTo("body"),g},xhr:function(b,c){var d=c?c:this,e=a.Deferred().fail(function(a){a&&d.error(a)}).done(function(a){a.warning&&d.error(a.warning),a.removed&&d.remove(a),a.added&&d.add(a),a.changed&&d.change(a),d.trigger("upload",a),a.sync&&d.sync()}).always(function(){m&&clearTimeout(m),k&&d.notify({type:"upload",cnt:-i,progress:100*i})}),f=new XMLHttpRequest,g=new FormData,h=b.input?b.input.files:d.uploads.checkFile(b,d),i=h.length,j=5,k=!1,l=function(){return setTimeout(function(){k=!0,d.notify({type:"upload",cnt:i,progress:j*i})},d.options.notifyDelay)},m;if(b.type!="data"&&!i)return e.reject();f.addEventListener("error",function(){e.reject("errConnect")},!1),f.addEventListener("abort",function(){e.reject(["errConnect","errAbort"])},!1),f.addEventListener("load",function(){var a=f.status,b;if(a>500)return e.reject("errResponse");if(a!=200)return e.reject("errConnect");if(f.readyState!=4)return e.reject(["errConnect","errTimeout"]);if(!f.responseText)return e.reject(["errResponse","errDataEmpty"]);b=d.parseUploadData(f.responseText),b.error?e.reject(b.error):e.resolve(b)},!1),f.upload.addEventListener("progress",function(a){var b=j,c;a.lengthComputable&&(c=parseInt(a.loaded*100/a.total),c>0&&!m&&(m=l()),c-b>4&&(j=c,k&&d.notify({type:"upload",cnt:0,progress:(j-b)*i})))},!1);var n=function(b,c){f.open("POST",d.uploadURL,!0),g.append("cmd","upload"),g.append(d.newAPI?"target":"current",d.cwd().hash),a.each(d.options.customData,function(a,b){g.append(a,b)}),a.each(d.options.onlyMimes,function(a,b){g.append("mimes["+a+"]",b)}),a.each(b,function(a,b){g.append("upload[]",b)}),c&&a.each(c,function(a,b){g.append("upload_path[]",b)}),f.onreadystatechange=function(){f.readyState==4&&f.status==0&&e.reject(["errConnect","errAbort"])},f.send(g)};b.type!="data"?n(h):h.done(function(a){i=a[0].length,n(a[0],a[1])}).fail(function(){e.reject()});if(!this.UA.Safari||!b.files)m=l();return e}},one:function(b,c){var d=this,e=a.proxy(c,function(a){return setTimeout(function(){d.unbind(a.type,e)},3),c.apply(this,arguments)});return this.bind(b,e)},localStorage:function(a,b){var c=window.localStorage;a="elfinder-"+a+this.id;if(b===null)return console.log("remove",a),c.removeItem(a);if(b!==void 0)try{c.setItem(a,b)}catch(d){c.clear(),c.setItem(a,b)}return c.getItem(a)},cookie:function(b,c){var d,e,f,g;b="elfinder-"+b+this.id;if(c===void 0){if(document.cookie&&document.cookie!=""){f=document.cookie.split(";"),b+="=";for(g=0;g "),escape:function(a){return this._node.text(a).html()},normalize:function(b){var c=function(a){return a&&a.hash&&a.name&&a.mime?(a.mime=="application/x-empty"&&(a.mime="text/plain"),a):null};return b.files&&(b.files=a.map(b.files,c)),b.tree&&(b.tree=a.map(b.tree,c)),b.added&&(b.added=a.map(b.added,c)),b.changed&&(b.changed=a.map(b.changed,c)),b.api&&(b.init=!0),b},setSort:function(a,b,c){this.storage("sortType",this.sortType=this.sortRules[a]?a:"name"),this.storage("sortOrder",this.sortOrder=/asc|desc/.test(b)?b:"asc"),this.storage("sortStickFolders",(this.sortStickFolders=!!c)?1:""),this.trigger("sortchange")},_sortRules:{name:function(a,b){return a.name.toLowerCase().localeCompare(b.name.toLowerCase())},size:function(a,b){var c=parseInt(a.size)||0,d=parseInt(b.size)||0;return c==d?0:c>d?1:-1},kind:function(a,b){return a.mime.localeCompare(b.mime)},date:function(a,b){var c=a.ts||a.date,d=b.ts||b.date;return c==d?0:c>d?1:-1}},compare:function(a,b){var c=this,d=c.sortType,e=c.sortOrder=="asc",f=c.sortStickFolders,g=c.sortRules,h=g[d],i=a.mime=="directory",j=b.mime=="directory",k;if(f){if(i&&!j)return-1;if(!i&&j)return 1}return k=e?h(a,b):h(b,a),d!="name"&&k==0?k=e?g.name(a,b):g.name(
+b,a):k},sortFiles:function(a){return a.sort(this.compare)},notify:function(b){var c=b.type,d=this.messages["ntf"+c]?this.i18n("ntf"+c):this.i18n("ntfsmth"),e=this.ui.notify,f=e.children(".elfinder-notify-"+c),g='',h=b.cnt,i=b.progress>=0&&b.progress<=100?b.progress:0,j,k,l;return c?(f.length||(f=a(g.replace(/\{type\}/g,c).replace(/\{msg\}/g,d)).appendTo(e).data("cnt",0),i&&f.data({progress:0,total:0})),j=h+parseInt(f.data("cnt")),j>0?(!b.hideCnt&&f.children(".elfinder-notify-cnt").text("("+j+")"),e.is(":hidden")&&e.elfinderdialog("open"),f.data("cnt",j),i<100&&(k=f.data("total"))>=0&&(l=f.data("progress"))>=0&&(k=h+parseInt(f.data("total")),l=i+l,i=parseInt(l/k),f.data({progress:l,total:k}),e.find(".elfinder-notify-progress").animate({width:(i<100?i:100)+"%"},20))):(f.remove(),!e.children().length&&e.elfinderdialog("close")),this):this},confirm:function(b){var c=!1,d={cssClass:"elfinder-dialog-confirm",modal:!0,resizable:!1,title:this.i18n(b.title||"confirmReq"),buttons:{},close:function(){!c&&b.cancel.callback(),a(this).elfinderdialog("destroy")}},e=this.i18n("apllyAll"),f,g;return b.reject&&(d.buttons[this.i18n(b.reject.label)]=function(){b.reject.callback(!!g&&!!g.prop("checked")),c=!0,a(this).elfinderdialog("close")}),d.buttons[this.i18n(b.accept.label)]=function(){b.accept.callback(!!g&&!!g.prop("checked")),c=!0,a(this).elfinderdialog("close")},d.buttons[this.i18n(b.cancel.label)]=function(){a(this).elfinderdialog("close")},b.all&&(b.reject&&(d.width=370),d.create=function(){g=a(' '),a(this).next().children().before(a(""+e+" ").prepend(g))},d.open=function(){var b=a(this).next(),c=parseInt(b.children(":first").outerWidth()+b.children(":last").outerWidth());c>parseInt(b.width())&&a(this).closest(".elfinder-dialog").width(c+30)}),this.dialog(' '+this.i18n(b.text),d)},uniqueName:function(a,b){var c=0,d="",e,f;a=this.i18n(a),b=b||this.cwd().hash,(e=a.indexOf(".txt"))!=-1&&(d=".txt",a=a.substr(0,e)),f=a+d;if(!this.fileByName(f,b))return f;while(c<1e4){f=a+" "+ ++c+d;if(!this.fileByName(f,b))return f}return a+Math.random()+d},i18n:function(){var b=this,c=this.messages,d=[],e=[],f=function(a){var c;if(a.indexOf("#")===0)if(c=b.file(a.substr(1)))return c.name;return a},g,h,i;for(g=0;g0&&d[b]&&e.push(b),d[b]||""}),d[g]=i}return a.map(d,function(b,c){return a.inArray(c,e)===-1?b:null}).join(" ")},mime2class:function(a){var b="elfinder-cwd-icon-";return a=a.split("/"),b+a[0]+(a[0]!="image"&&a[1]?" "+b+a[1].replace(/(\.|\+)/g,"-"):"")},mime2kind:function(a){var b=typeof a=="object"?a.mime:a,c;a.alias?c="Alias":this.kinds[b]?c=this.kinds[b]:b.indexOf("text")===0?c="Text":b.indexOf("image")===0?c="Image":b.indexOf("audio")===0?c="Audio":b.indexOf("video")===0?c="Video":b.indexOf("application")===0?c="App":c=b;return this.messages["kind"+c]?this.i18n("kind"+c):b;var b,c},formatDate:function(a,b){var c=this,b=b||a.ts,d=c.i18,e,f,g,h,i,j,k,l,m,n,o;return c.options.clientFormatDate&&b>0?(e=new Date(b*1e3),l=e[c.getHours](),m=l>12?l-12:l,n=e[c.getMinutes](),o=e[c.getSeconds](),h=e[c.getDate](),i=e[c.getDay](),j=e[c.getMonth]()+1,k=e[c.getFullYear](),f=b>=this.yesterday?this.fancyFormat:this.dateFormat,g=f.replace(/[a-z]/gi,function(a){switch(a){case"d":return h>9?h:"0"+h;case"j":return h;case"D":return c.i18n(d.daysShort[i]);case"l":return c.i18n(d.days[i]);case"m":return j>9?j:"0"+j;case"n":return j;case"M":return c.i18n(d.monthsShort[j-1]);case"F":return c.i18n(d.months[j-1]);case"Y":return k;case"y":return(""+k).substr(2);case"H":return l>9?l:"0"+l;case"G":return l;case"g":return m;case"h":return m>9?m:"0"+m;case"a":return l>12?"pm":"am";case"A":return l>12?"PM":"AM";case"i":return n>9?n:"0"+n;case"s":return o>9?o:"0"+o}return a}),b>=this.yesterday?g.replace("$1",this.i18n(b>=this.today?"Today":"Yesterday")):g):a.date?a.date.replace(/([a-z]+)\s/i,function(a,b){return c.i18n(b)+" "}):c.i18n("dateUnknown")},perms2class:function(a){var b="";return!a.read&&!a.write?b="elfinder-na":a.read?a.write||(b="elfinder-ro"):b="elfinder-wo",b},formatPermissions:function(a){var b=[];return a.read&&b.push(this.i18n("read")),a.write&&b.push(this.i18n("write")),b.length?b.join(" "+this.i18n("and")+" "):this.i18n("noaccess")},formatSize:function(a){var b=1,c="b";return a=="unknown"?this.i18n("unknown"):(a>1073741824?(b=1073741824,c="GB"):a>1048576?(b=1048576,c="MB"):a>1024&&(b=1024,c="KB"),a/=b,(a>0?b>=1048576?a.toFixed(2):Math.round(a):0)+" "+c)},navHash2Id:function(a){return"nav-"+a},navId2Hash:function(a){return typeof a=="string"?a.substr(4):!1},log:function(a){return window.console&&window.console.log&&window.console.log(a),this},debug:function(b,c){var d=this.options.debug;return(d=="all"||d===!0||a.isArray(d)&&a.inArray(b,d)!=-1)&&window.console&&window.console.log&&window.console.log("elfinder debug: ["+b+"] ["+this.id+"]",c),this},time:function(a){window.console&&window.console.time&&window.console.time(a)},timeEnd:function(a){window.console&&window.console.timeEnd&&window.console.timeEnd(a)}},elFinder.prototype.version="2.1_n (Nightly: 8221e18)",a.fn.elfinder=function(a){return a=="instance"?this.getElFinder():this.each(function(){var b=typeof a=="string"?a:"";this.elfinder||new elFinder(this,typeof a=="object"?a:{});switch(b){case"close":case"hide":this.elfinder.hide();break;case"open":case"show":this.elfinder.show();break;case"destroy":this.elfinder.destroy()}})},a.fn.getElFinder=function(){var a;return this.each(function(){if(this.elfinder)return a=this.elfinder,!1}),a},elFinder.prototype._options={url:"",requestType:"get",transport:{},urlUpload:"",dragUploadAllow:"auto",iframeTimeout:0,customData:{},handlers:{},lang:"en",cssClass:"",commands:["open","reload","home","up","back","forward","getfile","quicklook","download","rm","duplicate","rename","mkdir","mkfile","upload","copy","cut","paste","edit","extract","archive","search","info","view","help","resize","sort","netmount","netunmount","pixlr"],commandsOptions:{getfile:{onlyURL:!1,multiple:!1,folders:!1,oncomplete:""},upload:{ui:"uploadbutton"},quicklook:{autoplay:!0,jplayer:"extensions/jplayer"},edit:{mimes:[],editors:[]},netmount:{ftp:{inputs:{host:a(' '),port:a(' '),path:a(' '),user:a(' '),pass:a(' ')}},dropbox:{inputs:{host:a(' '),path:a(' '),user:a(' '),pass:a(' ')},select:function(b){a("#elfinder-cmd-netmout-dropbox-host").find("span").length&&b.request({data:{cmd:"netmount",protocol:"dropbox",host:"dropbox.com",user:"init",pass:"init",options:{url:b.uploadURL}},preventDefault:!0}).done(function(c){a("#elfinder-cmd-netmout-dropbox-host").html(c.body.replace(/\{msg:([^}]+)\}/g,function(a,c){return b.i18n(c,"Dropbox.com")}))}).fail(function(){})}}},help:{view:["about","shortcuts","help"]}},getFileCallback:null,defaultView:"icons",ui:["toolbar","tree","path","stat"],uiOptions:{toolbar:[["back","forward"],["netmount"],["mkdir","mkfile","upload"],["open","download","getfile"],["info"],["quicklook"],["copy","cut","paste"],["rm"],["duplicate","rename","edit","resize","pixlr"],["extract","archive"],["search"],["view","sort"],["help"]],tree:{openRootOnLoad:!0,syncTree:!0},navbar:{minWidth:150,maxWidth:500},cwd:{oldSchool:!1}},onlyMimes:[],sortRules:{}
+,sortType:"name",sortOrder:"asc",sortStickFolders:!0,clientFormatDate:!0,UTCDate:!1,dateFormat:"",fancyDateFormat:"",width:"auto",height:400,resizable:!0,notifyDelay:500,allowShortcuts:!0,rememberLastDir:!0,showFiles:30,showThreshold:50,validName:!1,sync:0,loadTmbs:5,cookie:{expires:30,domain:"",path:"/",secure:!1},contextmenu:{navbar:["open","|","copy","cut","paste","duplicate","|","rm","|","info","netunmount"],cwd:["reload","back","|","upload","mkdir","mkfile","paste","|","sort","|","info"],files:["getfile","|","open","quicklook","|","download","|","copy","cut","paste","duplicate","|","rm","|","edit","rename","resize","pixlr","|","archive","extract","|","info"]},debug:["error","warning","event-destroy"]},elFinder.prototype.history=function(b){var c=this,d=!0,e=[],f,g=function(){e=[b.cwd().hash],f=0,d=!0},h=function(h){return h&&c.canForward()||!h&&c.canBack()?(d=!1,b.exec("open",e[h?++f:--f]).fail(g)):a.Deferred().reject()};this.canBack=function(){return f>0},this.canForward=function(){return f=0&&c>f+1&&e.splice(f+1),e[e.length-1]!=g&&e.push(g),f=e.length-1),d=!0}).reload(g)},elFinder.prototype.command=function(b){this.fm=b,this.name="",this.title="",this.state=-1,this.alwaysEnabled=!1,this._disabled=!1,this.disableOnSearch=!1,this.updateOnSelect=!0,this._handlers={enable:function(){this.update(void 0,this.value)},disable:function(){this.update(-1,this.value)},"open reload load":function(a){this._disabled=!this.alwaysEnabled&&!this.fm.isCommandEnabled(this.name),this.update(void 0,this.value),this.change()}},this.handlers={},this.shortcuts=[],this.options={ui:"button"},this.setup=function(b,c){var d=this,e=this.fm,f,g;this.name=b,this.title=e.messages["cmd"+b]?e.i18n("cmd"+b):b,this.options=a.extend({},this.options,c),this.listeners=[],this.updateOnSelect&&(this._handlers.select=function(){this.update(void 0,this.value)}),a.each(a.extend({},d._handlers,d.handlers),function(b,c){e.bind(b,a.proxy(c,d))});for(f=0;f-1},this.active=function(){return this.state>0},this.getstate=function(){return-1},this.update=function(a,b){var c=this.state,d=this.value;this._disabled?this.state=-1:this.state=a!==void 0?a:this.getstate(),this.value=b,(c!=this.state||d!=this.value)&&this.change()},this.change=function(a){var b,c;if(typeof a=="function")this.listeners.push(a);else for(c=0;c ',lock:' ',symlink:' ',navicon:' ',navspinner:' ',navdir:' {symlink}{permissions}{name}
'},mimes:{text:["application/x-empty","application/javascript","application/xhtml+xml","audio/x-mp3-playlist","application/x-web-config","application/docbook+xml","application/x-php","application/x-perl","application/x-awk","application/x-config","application/x-csh","application/xml"]},mixin:{make:function(){var b=this.fm,c=this.name,d=b.getUI("cwd"),e=a.Deferred().fail(function(a){d.trigger("unselectall"),a&&b.error(a)}).always(function(){k.remove(),j.remove(),b.enable()}),f="tmp_"+parseInt(Math.random()*1e5),g=b.cwd().hash,h=new Date,i={hash:f,name:b.uniqueName(this.prefix),mime:this.mime,read:!0,write:!0,date:"Today "+h.getHours()+":"+h.getMinutes()},j=d.trigger("create."+b.namespace,i).find("#"+f),k=a(' ').keydown(function(b){b.stopImmediatePropagation(),b.keyCode==a.ui.keyCode.ESCAPE?e.reject():b.keyCode==a.ui.keyCode.ENTER&&k.blur()}).mousedown(function(a){a.stopPropagation()}).blur(function(){var d=a.trim(k.val()),h=k.parent();if(h.length){if(!d)return e.reject("errInvName");if(b.fileByName(d,g))return e.reject(["errExists",d]);h.html(b.escape(d)),b.lockfiles({files:[f]}),b.request({data:{cmd:c,name:d,target:g},notify:{type:c,cnt:1},preventFail:!0,syncOnFail:!0}).fail(function(a){e.reject(a)}).done(function(a){e.resolve(a)})}});return this.disabled()||!j.length?e.reject():(b.disable(),j.find(".elfinder-cwd-filename").empty("").append(k.val(i.name)),k.select().focus(),e)}}},a.fn.dialogelfinder=function(b){var c="elfinderPosition",d="elfinderDestroyOnClose";this.not(".elfinder").each(function(){var e=a(document),f=a('"),g=a(' ').appendTo(f).click(function(a){a.preventDefault(),h.dialogelfinder("close")}),h=a(this).addClass("dialogelfinder").css("position","absolute").hide().appendTo("body").draggable({handle:".dialogelfinder-drag",containment:"window"}).elfinder(b).prepend(f),i=h.elfinder("instance");h.width(parseInt(h.width())||840).data(d,!!b.destroyOnClose).find(".elfinder-toolbar").removeClass("ui-corner-top"),b.position&&h.data(c,b.position),b.autoOpen!==!1&&a(this).dialogelfinder("open")});if(b=="open"){var e=a(this),f=e.data(c)||{top:parseInt(a(document).scrollTop()+(a(window).height()g&&(g=c+1)}),e.zIndex(g).css(f).show().trigger("resize"),setTimeout(function(){e.trigger("resize").mousedown()},200))}else if(b=="close"){var e=a(this);e.is(":visible")&&(e.data(d)?e.elfinder("destroy").remove():e.elfinder("close"))}else if(b=="instance")return a(this).getElFinder();return this},elFinder&&elFinder.prototype&&typeof elFinder.prototype.i18=="object"&&(elFinder.prototype.i18.en={translator:"Troex Nevelin <troex@fury.scancode.ru>",language:"English",direction:"ltr",dateFormat:"M d, Y h:i A",fancyDateFormat:"$1 h:i A",messages:{error:"Error",errUnknown:"Unknown error.",errUnknownCmd:"Unknown command.",errJqui:"Invalid jQuery UI configuration. Selectable, draggable and droppable components must be included.",errNode:"elFinder requires DOM Element to be created.",errURL:"Invalid elFinder configuration! URL option is not set.",errAccess:"Access denied.",errConnect:"Unable to connect to backend.",errAbort:"Connection aborted.",errTimeout:"Connection timeout.",errNotFound:"Backend not found.",errResponse:"Invalid backend response.",errConf:"Invalid backend configuration.",errJSON:"PHP JSON module not installed.",errNoVolumes:"Readable volumes not available."
+,errCmdParams:'Invalid parameters for command "$1".',errDataNotJSON:"Data is not JSON.",errDataEmpty:"Data is empty.",errCmdReq:"Backend request requires command name.",errOpen:'Unable to open "$1".',errNotFolder:"Object is not a folder.",errNotFile:"Object is not a file.",errRead:'Unable to read "$1".',errWrite:'Unable to write into "$1".',errPerm:"Permission denied.",errLocked:'"$1" is locked and can not be renamed, moved or removed.',errExists:'File named "$1" already exists.',errInvName:"Invalid file name.",errFolderNotFound:"Folder not found.",errFileNotFound:"File not found.",errTrgFolderNotFound:'Target folder "$1" not found.',errPopup:"Browser prevented opening popup window. To open file enable it in browser options.",errMkdir:'Unable to create folder "$1".',errMkfile:'Unable to create file "$1".',errRename:'Unable to rename "$1".',errCopyFrom:'Copying files from volume "$1" not allowed.',errCopyTo:'Copying files to volume "$1" not allowed.',errUpload:"Upload error.",errUploadFile:'Unable to upload "$1".',errUploadNoFiles:"No files found for upload.",errUploadTotalSize:"Data exceeds the maximum allowed size.",errUploadFileSize:"File exceeds maximum allowed size.",errUploadMime:"File type not allowed.",errUploadTransfer:'"$1" transfer error.',errNotReplace:'Object "$1" already exists at this location and can not be replaced by object with another type.',errReplace:'Unable to replace "$1".',errSave:'Unable to save "$1".',errCopy:'Unable to copy "$1".',errMove:'Unable to move "$1".',errCopyInItself:'Unable to copy "$1" into itself.',errRm:'Unable to remove "$1".',errRmSrc:"Unable remove source file(s).",errExtract:'Unable to extract files from "$1".',errArchive:"Unable to create archive.",errArcType:"Unsupported archive type.",errNoArchive:"File is not archive or has unsupported archive type.",errCmdNoSupport:"Backend does not support this command.",errReplByChild:"The folder “$1” can’t be replaced by an item it contains.",errArcSymlinks:"For security reason denied to unpack archives contains symlinks or files with not allowed names.",errArcMaxSize:"Archive files exceeds maximum allowed size.",errResize:'Unable to resize "$1".',errUsupportType:"Unsupported file type.",errNotUTF8Content:'File "$1" is not in UTF-8 and cannot be edited.',errNetMount:'Unable to mount "$1".',errNetMountNoDriver:"Unsupported protocol.",errNetMountFailed:"Mount failed.",errNetMountHostReq:"Host required.",errSessionExpires:"Your session has expired due to inactivity.",errCreatingTempDir:'Unable to create temporary directory: "$1"',errFtpDownloadFile:'Unable to download file from FTP: "$1"',errFtpUploadFile:'Unable to upload file to FTP: "$1"',errFtpMkdir:'Unable to create remote directory on FTP: "$1"',errArchiveExec:'Error while archiving files: "$1"',errExtractExec:'Error while extracting files: "$1"',errNetUnMount:"Unable to unmount",cmdarchive:"Create archive",cmdback:"Back",cmdcopy:"Copy",cmdcut:"Cut",cmddownload:"Download",cmdduplicate:"Duplicate",cmdedit:"Edit file",cmdextract:"Extract files from archive",cmdforward:"Forward",cmdgetfile:"Select files",cmdhelp:"About this software",cmdhome:"Home",cmdinfo:"Get info",cmdmkdir:"New folder",cmdmkfile:"New text file",cmdopen:"Open",cmdpaste:"Paste",cmdquicklook:"Preview",cmdreload:"Reload",cmdrename:"Rename",cmdrm:"Delete",cmdsearch:"Find files",cmdup:"Go to parent directory",cmdupload:"Upload files",cmdview:"View",cmdresize:"Resize & Rotate",cmdsort:"Sort",cmdnetmount:"Mount network volume",cmdnetunmount:"Unmount",cmdpixlr:"Edit on Pixlr",btnClose:"Close",btnSave:"Save",btnRm:"Remove",btnApply:"Apply",btnCancel:"Cancel",btnNo:"No",btnYes:"Yes",btnMount:"Mount",btnApprove:"Goto $1 & approve",btnUnmount:"Unmount",ntfopen:"Open folder",ntffile:"Open file",ntfreload:"Reload folder content",ntfmkdir:"Creating directory",ntfmkfile:"Creating files",ntfrm:"Delete files",ntfcopy:"Copy files",ntfmove:"Move files",ntfprepare:"Prepare to copy files",ntfrename:"Rename files",ntfupload:"Uploading files",ntfdownload:"Downloading files",ntfsave:"Save files",ntfarchive:"Creating archive",ntfextract:"Extracting files from archive",ntfsearch:"Searching files",ntfresize:"Resizing images",ntfsmth:"Doing something",ntfloadimg:"Loading image",ntfnetmount:"Mounting network volume",ntfnetunmount:"Unmounting network volume",ntfdim:"Acquiring image dimension",dateUnknown:"unknown",Today:"Today",Yesterday:"Yesterday",Jan:"Jan",Feb:"Feb",Mar:"Mar",Apr:"Apr",May:"May",Jun:"Jun",Jul:"Jul",Aug:"Aug",Sep:"Sep",Oct:"Oct",Nov:"Nov",Dec:"Dec",sortname:"by name",sortkind:"by kind",sortsize:"by size",sortdate:"by date",sortFoldersFirst:"Folders first",confirmReq:"Confirmation required",confirmRm:"Are you sure you want to remove files? This cannot be undone!",confirmRepl:"Replace old file with new one?",apllyAll:"Apply to all",name:"Name",size:"Size",perms:"Permissions",modify:"Modified",kind:"Kind",read:"read",write:"write",noaccess:"no access",and:"and",unknown:"unknown",selectall:"Select all files",selectfiles:"Select file(s)",selectffile:"Select first file",selectlfile:"Select last file",viewlist:"List view",viewicons:"Icons view",places:"Places",calc:"Calculate",path:"Path",aliasfor:"Alias for",locked:"Locked",dim:"Dimensions",files:"Files",folders:"Folders",items:"Items",yes:"yes",no:"no",link:"Link",searcresult:"Search results",selected:"selected items",about:"About",shortcuts:"Shortcuts",help:"Help",webfm:"Web file manager",ver:"Version",protocolver:"protocol version",homepage:"Project home",docs:"Documentation",github:"Fork us on Github",twitter:"Follow us on twitter",facebook:"Join us on facebook",team:"Team",chiefdev:"chief developer",developer:"developer",contributor:"contributor",maintainer:"maintainer",translator:"translator",icons:"Icons",dontforget:"and don't forget to take your towel",shortcutsof:"Shortcuts disabled",dropFiles:"Drop files here",dropFilesBrowser:"Drop or paste files from browser",or:"or",selectForUpload:"Select files to upload",moveFiles:"Move files",copyFiles:"Copy files",rmFromPlaces:"Remove from places",aspectRatio:"Aspect ratio",scale:"Scale",width:"Width",height:"Height",resize:"Resize",crop:"Crop",rotate:"Rotate","rotate-cw":"Rotate 90 degrees CW","rotate-ccw":"Rotate 90 degrees CCW",degree:"°",netMountDialogTitle:"Mount network volume",protocol:"Protocol",host:"Host",port:"Port",user:"User",pass:"Password",confirmUnmount:"Are you unmount $1?",kindUnknown:"Unknown",kindFolder:"Folder",kindAlias:"Alias",kindAliasBroken:"Broken alias",kindApp:"Application",kindPostscript:"Postscript document",kindMsOffice:"Microsoft Office document",kindMsWord:"Microsoft Word document",kindMsExcel:"Microsoft Excel document",kindMsPP:"Microsoft Powerpoint presentation",kindOO:"Open Office document",kindAppFlash:"Flash application",kindPDF:"Portable Document Format (PDF)",kindTorrent:"Bittorrent file",kind7z:"7z archive",kindTAR:"TAR archive",kindGZIP:"GZIP archive",kindBZIP:"BZIP archive",kindZIP:"ZIP archive",kindRAR:"RAR archive",kindJAR:"Java JAR file",kindTTF:"True Type font",kindOTF:"Open Type font",kindRPM:"RPM package",kindText:"Text document",kindTextPlain:"Plain text",kindPHP:"PHP source",kindCSS:"Cascading style sheet",kindHTML:"HTML document",kindJS:"Javascript source",kindRTF:"Rich Text Format",kindC:"C source",kindCHeader:"C header source",kindCPP:"C++ source",kindCPPHeader:"C++ header source",kindShell:"Unix shell script",kindPython:"Python source",kindJava:"Java source",kindRuby:"Ruby source",kindPerl:"Perl script",kindSQL:"SQL source",kindXML:"XML document",kindAWK:"AWK source",kindCSV:"Comma separated values",kindDOCBOOK:"Docbook XML document",kindImage:"Image",kindBMP:"BMP image",kindJPEG:"JPEG image",kindGIF:"GIF Image",kindPNG:"PNG Image",kindTIFF:"TIFF image",kindTGA:"TGA image",kindPSD:"Adobe Photoshop image",kindXBITMAP:"X bitmap image",kindPXM:"Pixelmator image",kindAudio:"Audio media",kindAudioMPEG:"MPEG audio",kindAudioMPEG4:"MPEG-4 audio",kindAudioMIDI:"MIDI audio",kindAudioOGG:"Ogg Vorbis audio",kindAudioWAV:"WAV audio",AudioPlaylist:"MP3 playlist",kindVideo:"Video media",kindVideoDV:"DV movie",kindVideoMPEG:"MPEG movie",kindVideoMPEG4:"MPEG-4 movie",kindVideoAVI:"AVI movie",kindVideoMOV:"Quick Time movie"
+,kindVideoWM:"Windows Media movie",kindVideoFlash:"Flash movie",kindVideoMKV:"Matroska movie",kindVideoOGG:"Ogg movie"}}),a.fn.elfinderbutton=function(b){return this.each(function(){var c="class",d=b.fm,e=d.res(c,"disabled"),f=d.res(c,"active"),g=d.res(c,"hover"),h="elfinder-button-menu-item",i="elfinder-button-menu-item-selected",j,k=a(this).addClass("ui-state-default elfinder-button").attr("title",b.title).append(' ').hover(function(a){!k.is("."+e)&&k[a.type=="mouseleave"?"removeClass":"addClass"](g)}).click(function(a){k.is("."+e)||(j&&b.variants.length>1?(j.is(":hidden")&&b.fm.getUI().click(),a.stopPropagation(),j.slideToggle(100)):b.exec())}),l=function(){j.hide()};a.isArray(b.variants)&&(k.addClass("elfinder-menubutton"),j=a('').hide().appendTo(k).zIndex(12+k.zIndex()).delegate("."+h,"mouseenter mouseleave",function(){a(this).toggleClass(g)}).delegate("."+h,"click",function(c){c.preventDefault(),c.stopPropagation(),k.removeClass(g),b.exec(b.fm.selected(),a(this).data("value"))}),b.fm.bind("disable select",l).getUI().click(l),b.change(function(){j.html(""),a.each(b.variants,function(c,d){j.append(a(''+d[1]+"
").data("value",d[0]).addClass(d[0]==b.value?i:""))})})),b.change(function(){b.disabled()?k.removeClass(f+" "+g).addClass(e):(k.removeClass(e),k[b.active()?"addClass":"removeClass"](f))}).change()})},a.fn.elfindercontextmenu=function(b){return this.each(function(){var c=a(this).addClass("ui-helper-reset ui-widget ui-state-default ui-corner-all elfinder-contextmenu elfinder-contextmenu-"+b.direction).hide().appendTo("body").delegate(".elfinder-contextmenu-item","mouseenter mouseleave",function(){a(this).toggleClass("ui-state-hover")}),d=b.direction=="ltr"?"left":"right",e=a.extend({},b.options.contextmenu),f='',g=function(b,c,d){return a(f.replace("{icon}",c?"elfinder-button-icon-"+c:"").replace("{label}",b)).click(function(a){a.stopPropagation(),a.stopPropagation(),d()})},h=function(e,f){var g=a(window),h=c.outerWidth(),i=c.outerHeight(),j=g.width(),k=g.height(),l=g.scrollTop(),m=g.scrollLeft(),n={top:(f+i0?f-i:f)+l,left:(e+h'),h=!1;return}j=b.command(e);if(j&&j.getstate(f)!=-1){if(j.variants){if(!j.variants.length)return;k=g(j.title,j.name,function(){}),l=a('').appendTo(k.append('')),k.addClass("elfinder-contextmenu-group").hover(function(){l.toggle()}),a.each(j.variants,function(b,c){l.append(a('").click(function(a){a.stopPropagation(),i(),j.exec(f,c[0])}))})}else k=g(j.title,j.name,function(){i(),j.exec(f)});c.append(k),h=!0}})},k=function(b){a.each(b,function(a,b){var d;b.label&&typeof b.callback=="function"&&(d=g(b.label,b.icon,function(){i(),b.callback()}),c.append(d))})};b.one("load",function(){b.bind("contextmenu",function(a){var b=a.data;i(),b.type&&b.targets?j(b.type,b.targets):b.raw&&k(b.raw),c.children().length&&h(b.x,b.y)}).one("destroy",function(){c.remove()}).bind("disable select",i).getUI().click(i)})})},a.fn.elfindercwd=function(b,c){return this.not(".elfinder-cwd").each(function(){var d=b.viewType=="list",e="undefined",f="select."+b.namespace,g="unselect."+b.namespace,h="disable."+b.namespace,i="enable."+b.namespace,j="class",k=b.res(j,"cwdfile"),l="."+k,m="ui-selected",n=b.res(j,"disabled"),o=b.res(j,"draggable"),p=b.res(j,"droppable"),q=b.res(j,"hover"),r=b.res(j,"adroppable"),s=k+"-tmp",t=b.options.loadTmbs>0?b.options.loadTmbs:5,u="",v=[],w={icon:'',row:' {marker}{name}
{perms} {date} {size} {kind} '},x=b.res("tpl","perms"),y=b.res("tpl","lock"),z=b.res("tpl","symlink"),A={permsclass:function(a){return b.perms2class(a)},perms:function(a){return b.formatPermissions(a)},dirclass:function(a){return a.mime=="directory"?"directory":""},mime:function(a){return b.mime2class(a.mime)},size:function(a){return b.formatSize(a.size)},date:function(a){return b.formatDate(a)},kind:function(a){return b.mime2kind(a)},marker:function(a){return(a.alias||a.mime=="symlink-broken"?z:"")+(!a.read||!a.write?x:"")+(a.locked?y:"")},tooltip:function(a){var c=b.formatDate(a)+(a.size>0?" ("+b.formatSize(a.size)+")":"");return a.tooltip?b.escape(a.tooltip).replace(/"/g,""").replace(/\r/g,"
")+"
"+c:c}},B=function(a){return a.name=b.escape(a.name),w[d?"row":"icon"].replace(/\{([a-z]+)\}/g,function(b,c){return A[c]?A[c](a):a[c]?a[c]:""})},C=!1,D=function(b,c){function r(a,b){return a[b+"All"]("[id]:not(."+n+"):not(.elfinder-cwd-parent):first")}var e=a.ui.keyCode,h=b==e.LEFT||b==e.UP,i=X.find("[id]."+m),j=h?"first:":"last",k,l,o,p,q;if(i.length){k=i.filter(h?":first":":last"),o=r(k,h?"prev":"next");if(!o.length)l=k;else if(d||b==e.LEFT||b==e.RIGHT)l=o;else{p=k.position().top,q=k.position().left,l=k;if(h){do l=l.prev("[id]");while(l.length&&!(l.position().topp&&l.position().left>=q));l.is("."+n)&&(l=r(l,"prev")),l.length||(o=X.find("[id]:not(."+n+"):last"),o.position().top>p&&(l=o))}}}else l=X.find("[id]:not(."+n+"):not(.elfinder-cwd-parent):"+(h?"last":"first"));l&&l.length&&!l.is(".elfinder-cwd-parent")&&(c?l=k.add(k[h?"prevUntil":"nextUntil"]("#"+l.attr("id"))).add(l):i.trigger(g),l.trigger(f),K(l.filter(h?":first":":last")),J())},E=[],F=function(a){X.find("#"+a).trigger(f)},G=function(){var c=b.cwd().hash;X.find("[id]:not(."+m+"):not(.elfinder-cwd-parent)").trigger(f),E=a.map(b.files(),function(a){return a.phash==c?a.hash:null}),J()},H=function(){E=[],X.find("[id]."+m).trigger(g),J()},I=function(){return E},J=function(){b.trigger("select",{selected:E})},K=function(a){var b=a.position().top,c=a.outerHeight(!0),d=Y.scrollTop(),e=Y.innerHeight();b+c>d+e?Y.scrollTop(parseInt(b+c-e)):b").load(function(){b.find(".elfinder-cwd-icon").css
+("background","url('"+c+"') center center no-repeat")}).attr("src",c)}(g,d+c):(e=!1,(f=M(b))!=-1&&(L[f].tmb=c))}),e},S=function(a){var c=[];if(b.oldAPI){b.request({data:{cmd:"tmb",current:b.cwd().hash},preventFail:!0}).done(function(a){R(a.images||[])&&a.tmb&&S()});return}c=c=a.splice(0,t),c.length&&b.request({data:{cmd:"tmb",targets:c},preventFail:!0}).done(function(b){R(b.images||[])&&S(a)})},T=function(a){var c=d?X.find("tbody"):X,e=a.length,f=[],g={},h=!1,i=function(a){var c=X.find("[id]:first"),d;while(c.length){d=b.file(c.attr("id"));if(!c.is(".elfinder-cwd-parent")&&d&&b.compare(a,d)<0)return c;c=c.next("[id]")}},j=function(a){var c=L.length,d;for(d=0;d=0?L.splice(n,0,k):c.append(B(k)),X.find("#"+l).length&&(k.mime=="directory"?h=!0:k.tmb&&(k.tmb===1?f.push(l):g[l]=k.tmb))}R(g),f.length&&S(f),h&&Q()},U=function(a){var c=a.length,d,e,f;while(c--){d=a[c];if((e=X.find("#"+d)).length)try{e.detach()}catch(g){b.debug("error",g)}else(f=M(d))!=-1&&L.splice(f,1)}},V={name:b.i18n("name"),perm:b.i18n("perms"),mod:b.i18n("modify"),size:b.i18n("size"),kind:b.i18n("kind")},W=function(e,f){var g=b.cwd().hash;H();try{X.children("table,"+l).remove()}catch(h){X.html("")}X.removeClass("elfinder-cwd-view-icons elfinder-cwd-view-list").addClass("elfinder-cwd-view-"+(d?"list":"icons")),Y[d?"addClass":"removeClass"]("elfinder-cwd-wrapper-list"),d&&X.html(''+V.name+" "+V.perm+" "+V.mod+" "+V.size+" "+V.kind+"
"),L=a.map(e,function(a){return f||a.phash==g?a:null}),L=b.sortFiles(L),Y.bind(N,O).trigger(N),g=b.cwd().phash;if(c.oldSchool&&g&&!u){var i=a.extend(!0,{},b.file(g),{name:"..",mime:"directory"});i=a(B(i)).addClass("elfinder-cwd-parent").bind("mousedown click mouseup dblclick mouseenter",function(a){a.preventDefault(),a.stopPropagation()}).dblclick(function(){b.exec("open",this.id)}),(d?X.find("tbody"):X).prepend(i)}},X=a(this).addClass("ui-helper-clearfix elfinder-cwd").attr("unselectable","on").delegate(l,"click."+b.namespace,function(b){var c=this.id?a(this):a(this).parents("[id]:first"),d=c.prevAll("."+m+":first"),e=c.nextAll("."+m+":first"),h=d.length,i=e.length,j;b.stopImmediatePropagation(),b.shiftKey&&(h||i)?(j=h?c.prevUntil("#"+d.attr("id")):c.nextUntil("#"+e.attr("id")),j.add(c).trigger(f)):b.ctrlKey||b.metaKey?c.trigger(c.is("."+m)?g:f):(H(),c.trigger(f)),J()}).delegate(l,"dblclick."+b.namespace,function(a){b.dblclick({file:this.id})}).delegate(l,"mouseenter."+b.namespace,function(c){var e=a(this),f=d?e:e.children();!e.is("."+s)&&!f.is("."+o+",."+n)&&f.draggable(b.draggable)}).delegate(l,f,function(b){var c=a(this),d=c.attr("id");!C&&!c.is("."+n)&&(c.addClass(m).children().addClass(q),a.inArray(d,E)===-1&&E.push(d))}).delegate(l,g,function(b){var c=a(this),d=c.attr("id"),e;C||(a(this).removeClass(m).children().removeClass(q),e=a.inArray(d,E),e!==-1&&E.splice(e,1))}).delegate(l,h,function(){var b=a(this).removeClass(m).addClass(n),c=(d?b:b.children()).removeClass(q);b.is("."+p)&&b.droppable("disable"),c.is("."+o)&&c.draggable("disable"),!d&&c.removeClass(n)}).delegate(l,i,function(){var b=a(this).removeClass(n),c=d?b:b.children();b.is("."+p)&&b.droppable("enable"),c.is("."+o)&&c.draggable("enable")}).delegate(l,"scrolltoview",function(){K(a(this))}).delegate(l,"mouseenter mouseleave",function(c){b.trigger("hover",{hash:a(this).attr("id"),type:c.type}),a(this).toggleClass("ui-state-hover")}).bind("contextmenu."+b.namespace,function(c){var d=a(c.target).closest("."+k);d.length&&(c.stopPropagation(),c.preventDefault(),d.is("."+n)||(d.is("."+m)||(H(),d.trigger(f),J()),b.trigger("contextmenu",{type:"files",targets:b.selected(),x:c.clientX,y:c.clientY})))}).selectable({filter:l,stop:J,selected:function(b,c){a(c.selected).trigger(f)},unselected:function(b,c){a(c.unselected).trigger(g)}}).droppable(P).bind("create."+b.namespace,function(b,c){var e=d?X.find("tbody"):X,f=e.find(".elfinder-cwd-parent"),c=a(B(c)).addClass(s);H(),f.length?f.after(c):e.prepend(c),X.scrollTop(0)}).bind("unselectall",H).bind("selectfile",function(a,b){X.find("#"+b).trigger(f),J()}),Y=a('
').bind("contextmenu",function(a){a.preventDefault(),b.trigger("contextmenu",{type:"cwd",targets:[b.cwd().hash],x:a.clientX,y:a.clientY})}),Z=function(){var b=0;Y.siblings(".elfinder-panel:visible").each(function(){b+=a(this).outerHeight(!0)}),Y.height(ba.height()-b)},_=a(this).parent().resize(Z),ba=_.children(".elfinder-workzone").append(Y.append(this));b.dragUpload&&(Y[0].addEventListener("dragenter",function(a){a.preventDefault(),a.stopPropagation(),Y.addClass(r)},!1),Y[0].addEventListener("dragleave",function(a){a.preventDefault(),a.stopPropagation(),a.target==X[0]&&Y.removeClass(r)},!1),Y[0].addEventListener("dragover",function(a){a.preventDefault(),a.stopPropagation()},!1),Y[0].addEventListener("drop",function(a){a.preventDefault(),Y.removeClass(r);var c=!1,d="";a.dataTransfer&&a.dataTransfer.items&&a.dataTransfer.items.length?(c=a.dataTransfer,d="data"):a.dataTransfer&&a.dataTransfer.files&&a.dataTransfer.files.length?(c=a.dataTransfer.files,d="files"):a.dataTransfer.getData("text/html")?(c=[a.dataTransfer.getData("text/html")],d="html"):a.dataTransfer.getData("text")&&(c=[a.dataTransfer.getData("text")],d="text"),c&&b.exec("upload",{files:c,type:d})},!1)),b.bind("open",function(a){W(a.data.files)}).bind("search",function(a){v=a.data.files,W(v,!0)}).bind("searchend",function(){v=[],u&&(u="",W(b.files()))}).bind("searchstart",function(a){u=a.data.query}).bind("sortchange",function(){W(u?v:b.files(),!!u)}).bind("viewchange",function(){var c=b.selected(),e=b.storage("view")=="list";e!=d&&(d=e,W(b.files()),a.each(c,function(a,b){F(b)}),J()),Z()}).add(function(c){var d=b.cwd().hash,e=u?a.map(c.data.added||[],function(a){return a.name.indexOf(u)===-1?null:a}):a.map(c.data.added||[],function(a){return a.phash==d?a:null});T(e)}).change(function(c){var d=b.cwd().hash,e=b.selected(),f;u?a.each(c.data.changed||[],function(b,c){U([c.hash]),c.name.indexOf(u)!==-1&&(T([c]),a.inArray(c.hash,e)!==-1&&F(c.hash))}):a.each(a.map(c.data.changed||[],function(a){return a.phash==d?a:null}),function(b,c){U([c.hash]),T([c]),a.inArray(c.hash,e)!==-1&&F(c.hash)}),J()}).remove(function(a){U(a.data.removed||[]),J()}).bind("open add search searchend",function(){X.css("height","auto"),X.outerHeight(!0) '),l=a('
').append(k),m=a('
').hide().append(c).appendTo(d).draggable({handle:".ui-dialog-titlebar",containment:"document"}).css({width:b.width,height:b.height}).mousedown(function(b){b.stopPropagation(),a(document).mousedown(),m.is("."+e)||(d.find("."+f+":visible").removeClass(e),m.addClass(e).zIndex(n()+1))}).bind("open",function(){b.modal&&j.elfinderoverlay("show"),m.trigger("totop"),typeof b.open=="function"&&a.proxy(b.open,c[0])(),m.is("."+g)||d.find("."+f+":visible").not("."+g).each(function(){var b=a(this),c=parseInt(b.css("top")),d=parseInt(b.css("left")),e=parseInt(m.css("top")),f=parseInt(m.css("left"));b[0]!=m[0]&&(c==e||d==f)&&m.css({top:c+10+"px",left:d+10+"px"})})}).bind("close",function(){var e=d.find(".elfinder-dialog:visible"),f=n();b.modal&&j.elfinderoverlay("hide"),e.length?e.each(function(){var b=a(this);if(b.zIndex()>=f)return b.trigger("totop"),!1}):setTimeout(function(){d.mousedown().click()},10),typeof b.close=="function"?a.proxy(b.close,c[0])():b.destroyOnClose&&m.hide().remove()}).bind("totop",function(){a(this).mousedown().find(".ui-button:first").focus().end().find(":text:first").focus()}),n=function(){var b=d.zIndex()+10;return d.find("."+f+":visible").each(function(){var c;this!=m[0]&&(c=a(this).zIndex(),c>b&&(b=c))}),b},o;b.position||(o=parseInt((d.height()-m.outerHeight())/2-42),b.position={top:(o>0?o:0)+"px",left:parseInt((d.width()-m.outerWidth())/2)+"px"}),m.css(b.position),b.closeOnEscape&&a(document).bind("keyup."+i,function(b){b.keyCode==a.ui.keyCode.ESCAPE&&m.is("."+e)&&(c.elfinderdialog("close"),a(document).unbind("keyup."+i))}),m.prepend(a('").prepend(a(' ').mousedown(function(a){a.preventDefault(),c.elfinderdialog("close")}))),a.each(b.buttons,function(b,d){var e=a(''+b+" ").click(a.proxy(d,c[0])).hover(function(b){a(this)[b.type=="mouseenter"?"focus":"blur"]()}).focus(function(){a(this).addClass(h)}).blur(function(){a(this).removeClass(h)}).keydown(function(b){var c;b.keyCode==a.ui.keyCode.ENTER?a(this).click():b.keyCode==a.ui.keyCode.TAB&&(c=a(this).next(".ui-button"),c.length?c.focus():a(this).parent().children(".ui-button:first").focus())});k.append(e)}),k.children().length&&m.append(l),b.resizable&&a.fn.resizable&&m.resizable({minWidth:b.minWidth,minHeight:b.minHeight,alsoResize:this}),typeof b.create=="function"&&a.proxy(b.create,this)(),b.autoOpen&&c.elfinderdialog("open")}),this},a.fn.elfinderdialog.defaults={cssClass:"",title:"",modal:!1,resizable:!0,autoOpen:!0,closeOnEscape:!0,destroyOnClose:!1,buttons:{},position:null,width:320,height:"auto",minWidth:200,minHeight:110},a.fn.elfindernavbar=function(b,c){return this.not(".elfinder-navbar").each(function(){var d=a(this).addClass("ui-state-default elfinder-navbar"),e=d.parent().resize(function(){d.height(f.height()-g)}),f=e.children(".elfinder-workzone").append(d),g=d.outerHeight()-d.height(),h=b.direction=="ltr",i;a.fn.resizable&&(i=d.resizable({handles:h?"e":"w",minWidth:c.minWidth||150,maxWidth:c.maxWidth||500}).bind("resize scroll",function(){var a=b.UA.Opera&&d.scrollLeft()?20:2;i.css({top:parseInt(d.scrollTop())+"px",left:h?"auto":parseInt(d.scrollLeft()+a),right:h?parseInt(d.scrollLeft()-a)*-1:"auto"})}).find(".ui-resizable-handle").zIndex(d.zIndex()+10),h||d.resize(function(){d.css("left",null).css("right",0)}),b.one("open",function(){setTimeout(function(){d.trigger("resize")},150)}))}),this},a.fn.elfinderoverlay=function(b){this.filter(":not(.elfinder-overlay)").each(function(){b=a.extend({},b),a(this).addClass("ui-widget-overlay elfinder-overlay").hide().mousedown(function(a){a.preventDefault(),a.stopPropagation()}).data({cnt:0,show:typeof b.show=="function"?b.show:function(){},hide:typeof b.hide=="function"?b.hide:function(){}})});if(b=="show"){var c=this.eq(0),d=c.data("cnt")+1,e=c.data("show");c.data("cnt",d),c.is(":hidden")&&(c.zIndex(c.parent().zIndex()+1),c.show(),e())}if(b=="hide"){var c=this.eq(0),d=c.data("cnt")-1,f=c.data("hide");c.data("cnt",d),d==0&&c.is(":visible")&&(c.hide(),f())}return this},a.fn.elfinderpanel=function(b){return this.each(function(){var c=a(this).addClass("elfinder-panel ui-state-default ui-corner-all"),d="margin-"+(b.direction=="ltr"?"left":"right");b.one("load",function(a){var e=b.getUI("navbar");c.css(d,parseInt(e.outerWidth(!0))),e.bind("resize",function(){c.is(":visible")&&c.css(d,parseInt(e.outerWidth(!0)))})})})},a.fn.elfinderpath=function(b){return this.each(function(){var c=a(this).addClass("elfinder-path").html(" ").delegate("a","click",function(c){var d=a(this).attr("href").substr(1);c.preventDefault(),d!=b.cwd().hash&&b.exec("open",d)}).prependTo(b.getUI("statusbar").show());b.bind("open searchend",function(){var d=[];a.each(b.parents(b.cwd().hash),function(a,c){d.push(''+b.escape(b.file(c).name)+" ")}),c.html(d.join(b.option("separator")))}).bind("search",function(){c.html(b.i18n("searcresult"))})})},a.fn.elfinderplaces=function(b,c){return this.each(function(){var d=[],e="class",f=b.res(e,"navdir"),g=b.res(e,"navcollapse"),h=b.res(e,"navexpand"),i=b.res(e,"hover"),j=b.res(e,"treeroot"),k=b.res("tpl","navdir"),l=b.res("tpl","perms"),m=a(b.res("tpl","navspinner")),n=function(a){return a.substr(6)},o=function(a){return"place-"+a},p=function(){b.storage("places",d.join(","))},q=function(c){return a(k.replace(/\{id\}/,o(c.hash)).replace(/\{name\}/,b.escape(c.name)).replace(/\{cssclass\}/,b.perms2class(c)).replace(/\{permissions\}/,!c.read||!c.write?l:"").replace(/\{symlink\}/,""))},r=function(c){var e=q(c);w.children().length&&a.each(w.children(),function(){var b=a(this);if(c.name.localeCompare(b.children("."+f).text())<0)return!e.insertBefore(b)}),d.push(c.hash),!e.parent().length&&w.append(e),v.addClass(g),e.draggable({appendTo:"body",revert:!1,helper:function(){var c=a(this);return c.children().removeClass("ui-state-hover"),a('
').append(c.clone()).data("hash",n(c.children(":first").attr("id")))},start:function(){a(this).hide()},stop:function(b,c){var d=x.offset().top,e=x.offset().left,f=x.width(),g=x.height(),h=b.clientX,i=b.clientY;h>e&&hd&&i0&&v.click()}).always(function(){m.remove()})),b.remove(function(b){a.each(b.data.removed,function(a,b){s(b)}),p()}).change(function(b){a.each(b.data.changed,function(b,c){a.inArray(c.hash,d)!==-1&&(s(c.hash),c.mime=="directory"&&r(c))}),p()}).bind("sync",function(){d.length&&(v.prepend(m),b.request({data:{cmd:"info",targets:d},preventDefault:!0}).done(function(b){a.each(b.files||[],function(b,c){a.inArray(c.hash,d)===-1&&s(c.hash)}),p()}).always(function(){m.remove()}))})})})},a.fn.elfindersearchbutton=function(b){return this.each(function(){var c=!1,d=a(this).hide().addClass("ui-widget-content elfinder-button "+b.fm.res("class","searchbtn")+""),e=function(){var d=a.trim(g.val());d?b.exec(d).done(function(){c=!0,g.focus()}):b.fm.trigger("searchend")},f=function(){g.val(""),c&&(c=!1,b.fm.trigger("searchend"))},g=a(' ').appendTo(d).keypress(function(a){a.stopPropagation()}).keydown(function(a){a.stopPropagation(),a.keyCode==13&&e(),a.keyCode==27&&(a.preventDefault(),f())});a(' ').appendTo(d).click(e),a(' ').appendTo(d).click(f),setTimeout(function(){d.parent().detach(),b.fm.getUI("toolbar").prepend(d.show());if(b.fm.UA.ltIE7){var a=d.children(b.fm.direction=="ltr"?".ui-icon-close":".ui-icon-search");a.css({right:"",left:parseInt(d.width())-a.outerWidth(!0)})}},200),b.fm.error(function(){g.unbind("keydown")}).select(function(){g.blur()}).bind("searchend",function(){g.val("")}).viewchange(f).shortcut({pattern:"ctrl+f f3",description:b.title,callback:function(){g.select().focus()}})})},a.fn.elfindersortbutton=function(b){return this.each(function(){var c=b.fm,d=b.name,e="class",f=c.res(e,"disabled"),g=c.res(e,"hover"),h="elfinder-button-menu-item",i=h+"-selected",j=i+"-asc",k=i+"-desc",l=a(this).addClass("ui-state-default elfinder-button elfinder-menubutton elfiner-button-"+d).attr("title",b.title).append(' ').hover(function(a){!l.is("."+f)&&l.toggleClass(g)}).click(function(a){l.is("."+f)||(a.stopPropagation(),m.is(":hidden")&&b.fm.getUI().click(),m.slideToggle(100))}),m=a('').hide().appendTo(l).zIndex(12+l.zIndex()).delegate("."+h,"mouseenter mouseleave",function(){a(this).toggleClass(g)}).delegate("."+h,"click",function(a){a.preventDefault(),a.stopPropagation(),o()}),n=function(){m.children(":not(:last)").removeClass(i+" "+j+" "+k).filter('[rel="'+c.sortType+'"]').addClass(i+" "+(c.sortOrder=="asc"?j:k)),m.children(":last").toggleClass(i,c.sortStickFolders)},o=function(){m.hide()};a.each(c.sortRules,function(b,d){m.append(a(' '+c.i18n("sort"+b)+"
").data("type",b))}),m.children().click(function(d){var e=a(this).attr("rel");b.exec([],{type:e,order:e==c.sortType?c.sortOrder=="asc"?"desc":"asc":c.sortOrder,stick:c.sortStickFolders})}),a(' '+c.i18n("sortFoldersFirst")+"
").appendTo(m).click(function(){b.exec([],{type:c.sortType,order:c.sortOrder,stick:!c.sortStickFolders})}),c.bind("disable select",o).getUI().click(o),c.bind("sortchange",n),m.children().length>1?b.change(function(){l.toggleClass(f,b.disabled()),n()}).change():l.addClass(f)})},a.fn.elfinderstat=function(b){return this.each(function(){var c=a(this).addClass("elfinder-stat-size"),d=a('
'),e=b.i18n("size").toLowerCase(),f=b.i18n("items").toLowerCase(),g=b.i18n("selected"),h=function(d,g){var h=0,i=0;a.each(d,function(a,b){if(!g||b.phash==g)h++,i+=parseInt(b.size)||0}),c.html(f+": "+h+", "+e+": "+b.formatSize(i))};b.getUI("statusbar").prepend(c).append(d).show(),b.bind("open reload add remove change searchend",function(){h(b.files(),b.cwd().hash)}).search(function(a){h(a.data.files)}).select(function(){var c=0,f=0,h=b.selectedFiles();if(h.length==1){c=h[0].size,d.html(b.escape(h[0].name)+(c>0?", "+b.formatSize(c):""));return}a.each(h,function(a,b){f++,c+=parseInt(b.size)||0}),d.html(f?g+": "+f+", "+e+": "+b.formatSize(c):" ")})})},a.fn.elfindertoolbar=function(b,c){return this.not(".elfinder-toolbar").each(function(){var d=b._commands,e=a(this).addClass("ui-helper-clearfix ui-widget-header ui-corner-top elfinder-toolbar"),f=c||[],g=f.length,h,i,j,k;e.prev().length&&e.parent().prepend(this);while(g--)if(f[g]){j=a('
'),h=f[g].length;while(h--)if(i=d[f[g][h]])k="elfinder"+i.options.ui,a.fn[k]&&j.prepend(a("
")[k](i));j.children().length&&e.prepend(j),j.children(":gt(0)").before(' ')}e.children().length&&e.show()}),this},a.fn.elfindertree=function(b,c){var d=b.res("class","tree");return this.not("."+d).each(function(){var e="class",f=b.res(e,"treeroot"),g=c.openRootOnLoad,h=b.res(e,"navsubtree"),i=b.res(e,"treedir"),j=b.res(e,"navcollapse"),k=b.res(e,"navexpand"),l="elfinder-subtree-loaded",m=b.res(e,"navarrow"),n=b.res(e,"active"),o=b.res(e,"adroppable"),p=b.res(e,"hover"),q=b.res(e,"disabled"),r=b.res(e,"draggable"),s=b.res(e,"droppable"),t=function(a){var b=L.offset().left;return b<=a&&a<=b+L.width()},u=b.droppable.drop,v=a.extend(!0,{},b.droppable,{over:function(b){var c=a(this),d=p+" "+o;t(b.clientX)?(c.addClass(d),c.is("."+j+":not(."+k+")")&&setTimeout(function(){c.is("."+o)&&c.children("."+m).click()},500)):c.removeClass(d)},out:function(){a(this).removeClass(p+" "+o)},drop:function(a,b){t(a.clientX)&&u.call(this,a,b)}}),w=a(b.res("tpl","navspinner")),x=b.res("tpl","navdir"),y=b.res("tpl","perms"),z=b.res("tpl","lock"),A=b.res("tpl","symlink"),B={id:function(a){return b.navHash2Id(a.hash)},cssclass:function(a){return(a.phash?"":f)+" "+i+" "+b.perms2class(a)+" "+(a.dirs&&!a.link?j:"")},permissions:function(a){return!a.read||!a.write?y:""},symlink:function(a){return a.alias?A:""},style:function(a){return a.icon?"style=\"background-image:url('"+a.icon+"')\"":""}},C=function(a){return a.name=b.escape(a.i18||a.name),x.replace(/(?:\{([a-z]+)\})/ig,function(b,c){return a[c]||(B[c]?B[c](a):"")})},D=function(b){return a.map(b||[],function(a){return a.mime=="directory"?a:null})},E=function(a){return a?K.find("#"+b.navHash2Id(a)).next("."+h):K},F=function(c,d){var e=c.children(":first"),f;while(e.length){f=b.file(b.navId2Hash(e.children("[id]").attr("id")));if((f=b.file(b.navId2Hash(e.children("[id]").attr("id"))))&&d.name.toLowerCase().localeCompare(f.name.toLowerCase())<0)return e;e=e.next()}return a("")},G=function(a){var c=a.length,d=[],e=a.length,f,g,h,i,j=!0;while(e--){f=a[e];if(K.find("#"+b.navHash2Id(f.hash)).length)continue;(h=E(f.phash)).length?(g=C(f),f.phash&&(i=F(h,f)).length?i.before(g):(h[j||f.phash?"append":"prepend"](g),j=!1)):d.push(f)}if(d.length&&d.length0}).addClass(d)})},K=a(this).addClass
+(d).delegate("."+i,"mouseenter mouseleave",function(c){var d=a(this),e=c.type=="mouseenter";d.is("."+o+" ,."+q)||(e&&!d.is("."+f+",."+r+",.elfinder-na,.elfinder-wo")&&d.draggable(b.draggable),d.toggleClass(p,e))}).delegate("."+i,"dropover dropout drop",function(b){a(this)[b.type=="dropover"?"addClass":"removeClass"](o+" "+p)}).delegate("."+i,"click",function(c){var d=a(this),e=b.navId2Hash(d.attr("id")),f=b.file(e);b.trigger("searchend"),e!=b.cwd().hash&&!d.is("."+q)?b.exec("open",f.thash||e):d.is("."+j)&&d.children("."+m).click()}).delegate("."+i+"."+j+" ."+m,"click",function(c){var d=a(this),e=d.parent("."+i),f=e.next("."+h);c.stopPropagation(),e.is("."+l)?(e.toggleClass(k),f.slideToggle()):(w.insertBefore(d),e.removeClass(j),b.request({cmd:"tree",target:b.navId2Hash(e.attr("id"))}).done(function(a){G(D(a.tree)),f.children().length&&(e.addClass(j+" "+k),f.slideDown()),H()}).always(function(a){w.remove(),e.addClass(l)}))}).delegate("."+i,"contextmenu",function(c){c.preventDefault(),b.trigger("contextmenu",{type:"navbar",targets:[b.navId2Hash(a(this).attr("id"))],x:c.clientX,y:c.clientY})}),L=b.getUI("navbar").append(K).show();b.open(function(a){var b=a.data,c=D(b.files);b.init&&K.empty(),c.length&&(G(c),J(c,l)),H()}).add(function(a){var b=D(a.data.added);b.length&&(G(b),J(b,j))}).change(function(c){var d=D(c.data.changed),e=d.length,f,g,j,m,n,o,p,q,r;while(e--){f=d[e];if((g=K.find("#"+b.navHash2Id(f.hash))).length){if(f.phash){m=g.closest("."+h),n=E(f.phash),o=g.parent().next(),p=F(n,f);if(!n.length)continue;if(n[0]!==m[0]||o.get(0)!==p.get(0))p.length?p.before(g):n.append(g)}q=g.is("."+k),r=g.is("."+l),j=a(C(f)),g.replaceWith(j.children("."+i)),f.dirs&&(q||r)&&(g=K.find("#"+b.navHash2Id(f.hash)))&&g.next("."+h).children().length&&(q&&g.addClass(k),r&&g.addClass(l))}}H(),I()}).remove(function(a){var c=a.data.removed,d=c.length,e,f;while(d--)(e=K.find("#"+b.navHash2Id(c[d]))).length&&(f=e.closest("."+h),e.parent().detach(),f.children().length||f.hide().prev("."+i).removeClass(j+" "+k+" "+l))}).bind("search searchend",function(a){K.find("#"+b.navHash2Id(b.cwd().hash))[a.type=="search"?"removeClass":"addClass"](n)}).bind("lockfiles unlockfiles",function(c){var d=c.type=="lockfiles",e=d?"disable":"enable",f=a.map(c.data.files||[],function(a){var c=b.file(a);return c&&c.mime=="directory"?a:null});a.each(f,function(a,c){var f=K.find("#"+b.navHash2Id(c));f.length&&(f.is("."+r)&&f.draggable(e),f.is("."+s)&&f.droppable(n),f[d?"addClass":"removeClass"](q))})})}),this},a.fn.elfinderuploadbutton=function(b){return this.each(function(){var c=a(this).elfinderbutton(b).unbind("click"),d=a("").appendTo(c),e=a(' ').change(function(){var c=a(this);c.val()&&(b.exec({input:c.remove()[0]}),e.clone(!0).appendTo(d))});d.append(e.clone(!0)),b.change(function(){d[b.disabled()?"hide":"show"]()}).change()})},a.fn.elfinderviewbutton=function(b){return this.each(function(){var c=a(this).elfinderbutton(b),d=c.children(".elfinder-button-icon");b.change(function(){var a=b.value=="icons";d.toggleClass("elfinder-button-icon-view-list",a),c.attr("title",b.fm.i18n(a?"viewlist":"viewicons"))})})},a.fn.elfinderworkzone=function(b){var c="elfinder-workzone";return this.not("."+c).each(function(){var b=a(this).addClass(c),d=b.outerHeight(!0)-b.height(),e=b.parent();e.add(window).bind("resize",function(){var f=e.height();e.children(":visible:not(."+c+")").each(function(){var b=a(this);b.css("position")!="absolute"&&(f-=b.outerHeight(!0))}),b.height(f-d)})}),this},elFinder.prototype.commands.archive=function(){var b=this,c=b.fm,d=[];this.variants=[],this.disableOnSearch=!0,c.bind("open reload",function(){b.variants=[],a.each(d=c.option("archivers").create||[],function(a,d){b.variants.push([d,c.mime2kind(d)])}),b.change()}),this.getstate=function(){return!this._disabled&&d.length&&c.selected().length&&c.cwd().write?0:-1},this.exec=function(b,e){var f=this.files(b),g=f.length,h=e||d[0],i=c.cwd(),j=["errArchive","errPerm","errCreatingTempDir","errFtpDownloadFile","errFtpUploadFile","errFtpMkdir","errArchiveExec","errExtractExec","errRm"],k=a.Deferred().fail(function(a){a&&c.error(a)}),l;if(!(this.enabled()&&g&&d.length&&a.inArray(h,d)!==-1))return k.reject();if(!i.write)return k.reject(j);for(l=0;l';return a(h).appendTo("body").ready(function(){setTimeout(function(){a(h).each(function(){a("#"+a(this).attr("id")).remove()})},c.UA.Firefox?2e4+1e4*j:1e3)}),c.trigger("download",{files:f}),g.resolve(b)}},elFinder.prototype.commands.duplicate=function(){var b=this.fm;this.getstate=function(c){var c=this.files(c),d=c.length;return!this._disabled&&d&&b.cwd().write&&a.map(c,function(a){return a.phash&&a.read?a:null}).length==d?0:-1},this.exec=function(b){var c=this.fm,d=this.files(b),e=d.length,f=a.Deferred().fail(function(a){a&&c.error(a)}),g=[];return!e||this._disabled?f.reject():(a.each(d,function(a,b){if(!b.read||!c.file(b.phash).write)return!f.reject(["errCopy",b.name,"errPerm"])}),f.state()=="rejected"?f:c.request({data:{cmd:"duplicate",targets:this.hashes(b)},notify:{type:"copy",cnt:e}}))}},elFinder.prototype.commands.edit=function(){var b=this,c=this.fm,d=c.res("mimes","text")||[],e=function(c){return a.map(c,function(c){return(c.mime.indexOf("text/")===0||a.inArray(c.mime,d)!==-1)&&c.mime.indexOf("text/rtf")&&(!b.onlyMimes.length||a.inArray(c.mime,b.onlyMimes)!==-1)&&c.read&&c.write?c:null})},f=function(d,e,f){var g=a.Deferred(),h=a('"),i=function(){h.editor&&h.editor.save(h[0],h.editor.instance),g.resolve(h.getContent()),h.elfinderdialog("close")},j=function(){g.reject(),h.elfinderdialog("close")},k={title:e.name,width:b.options.dialogWidth||450,buttons:{},close:function(){h.editor&&h.editor.close(h[0],h.editor.instance),a(this).elfinderdialog("destroy")},open:function(){c.disable(),h.focus(),h[0].setSelectionRange&&h[0].setSelectionRange(0,0),h.editor&&h.editor.load(h[0])}};return h.getContent=function(
+){return h.val()},a.each(b.options.editors||[],function(b,c){if(a.inArray(e.mime,c.mimes||[])!==-1&&typeof c.load=="function"&&typeof c.save=="function")return h.editor={load:c.load,save:c.save,close:typeof c.close=="function"?c.close:function(){},instance:null},!1}),h.editor||h.keydown(function(a){var b=a.keyCode,c,d;a.stopPropagation(),b==9&&(a.preventDefault(),this.setSelectionRange&&(c=this.value,d=this.selectionStart,this.value=c.substr(0,d)+"\t"+c.substr(this.selectionEnd),d+=1,this.setSelectionRange(d,d)));if(a.ctrlKey||a.metaKey){if(b==81||b==87)a.preventDefault(),j();b==83&&(a.preventDefault(),i())}}),k.buttons[c.i18n("Save")]=i,k.buttons[c.i18n("Cancel")]=j,c.dialog(h,k).attr("id",d),g.promise()},g=function(b){var d=b.hash,e=c.options,g=a.Deferred(),h={cmd:"file",target:d},i=c.url(d)||c.options.url,j="edit-"+c.namespace+"-"+b.hash,k=c.getUI().find("#"+j),l;return k.length?(k.elfinderdialog("toTop"),g.resolve()):!b.read||!b.write?(l=["errOpen",b.name,"errPerm"],c.error(l),g.reject(l)):(c.request({data:{cmd:"get",target:d},notify:{type:"openfile",cnt:1},syncOnFail:!0}).done(function(a){f(j,b,a.content).done(function(a){c.request({options:{type:"post"},data:{cmd:"put",target:d,content:a},notify:{type:"save",cnt:1},syncOnFail:!0}).fail(function(a){g.reject(a)}).done(function(a){a.changed&&a.changed.length&&c.change(a),g.resolve(a)})})}).fail(function(a){g.reject(a)}),g.promise())};this.shortcuts=[{pattern:"ctrl+e"}],this.init=function(){this.onlyMimes=this.options.mimes||[]},this.getstate=function(a){var a=this.files(a),b=a.length;return!this._disabled&&b&&e(a).length==b?0:-1},this.exec=function(b){var c=e(this.files(b)),d=[],f;if(this.disabled())return a.Deferred().reject();while(f=c.shift())d.push(g(f));return d.length?a.when.apply(null,d):a.Deferred().reject()}},elFinder.prototype.commands.extract=function(){var b=this,c=b.fm,d=[],e=function(b){return a.map(b,function(b){return b.read&&a.inArray(b.mime,d)!==-1?b:null})};this.disableOnSearch=!0,c.bind("open reload",function(){d=c.option("archivers").extract||[],b.change()}),this.getstate=function(a){var a=this.files(a),b=a.length;return!this._disabled&&b&&this.fm.cwd().write&&e(a).length==b?0:-1},this.exec=function(b){var e=this.files(b),f=a.Deferred(),g=e.length,h,i,j,k=!1,l=!1,m=a.map(c.files(b),function(a){return a.name}),n={};a.map(c.files(b),function(a){n[a.name]=a});var o=function(a){switch(a){case"overwrite_all":k=!0;break;case"omit_all":l=!0}},p=function(b){!b.read||!c.file(b.phash).write?(i=["errExtract",b.name,"errPerm"],c.error(i),f.reject(i)):a.inArray(b.mime,d)===-1?(i=["errExtract",b.name,"errNoArchive"],c.error(i),f.reject(i)):c.request({data:{cmd:"extract",target:b.hash},notify:{type:"extract",cnt:1},syncOnFail:!0}).fail(function(a){f.state()!="rejected"&&f.reject(a)}).done(function(){})},q=function(b,d){var e=b[d],i=e.name.replace(/\.((tar\.(gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(gz|bz2)|[a-z0-9]{1,4})$/ig,""),r=a.inArray(i,m)>=0;r&&n[i].mime!="directory"?c.confirm({title:c.i18n("ntfextract"),text:c.i18n(["errExists",i,"confirmRepl"]),accept:{label:"btnYes",callback:function(a){j=a?"overwrite_all":"overwrite",o(j);if(!k&&!l)"overwrite"==j&&p(e),d+11}):(p(e),d+10&&q(e,0),f):f.reject()}},elFinder.prototype.commands.forward=function(){this.alwaysEnabled=!0,this.updateOnSelect=!0,this.shortcuts=[{pattern:"ctrl+right"}],this.getstate=function(){return this.fm.history.canForward()?0:-1},this.exec=function(){return this.fm.history.forward()}},elFinder.prototype.commands.getfile=function(){var b=this,c=this.fm,d=function(c){var d=b.options;return c=a.map(c,function(a){return a.mime!="directory"||d.folders?a:null}),d.multiple||c.length==1?c:[]};this.alwaysEnabled=!0,this.callback=c.options.getFileCallback,this._disabled=typeof this.callback=="function",this.getstate=function(a){var a=this.files(a),b=a.length;return this.callback&&b&&d(a).length==b?0:-1},this.exec=function(c){var d=this.fm,e=this.options,f=this.files(c),g=f.length,h=d.option("url"),i=d.option("tmbUrl"),j=a.Deferred().done(function(a){d.trigger("getfile",{files:a}),b.callback(a,d),e.oncomplete=="close"?d.hide():e.oncomplete=="destroy"&&d.destroy()}),k=function(b){return e.onlyURL?e.multiple?a.map(f,function(a){return a.url}):f[0].url:e.multiple?f:f[0]},l=[],m,n,o;if(this.getstate()==-1)return j.reject();for(m=0;m {link} ',e='',f='',g=/\{url\}/,h=/\{link\}/,i=/\{author\}/,j=/\{work\}/,k="replace",l="ui-priority-primary",m="ui-priority-secondary",n="elfinder-help-license",o='{title} ',p=['','"),a.inArray("about",d)!==-1&&s(),a.inArray("shortcuts",d)!==-1&&t(),a.inArray("help",d)!==-1&&u(),p.push("
"),v=a(p.join("")),b.one("load",function(){v.find("#apiver").text(b.api)}),v.find(".ui-tabs-nav li").hover(function(){a(this).toggleClass("ui-state-hover")}).children().click(function(b){var c=a(this);b.preventDefault(),b.stopPropagation(),c.is(".ui-tabs-selected")||(c.parent().addClass("ui-tabs-selected ui-state-active").siblings().removeClass("ui-tabs-selected").removeClass("ui-state-active"),v.find(".ui-tabs-panel").hide().filter(c.attr("href")).show())}).filter(":first").click()},200),this.getstate=function(){return 0},this.exec=function(){this.dialog||(this.dialog=this.fm.dialog(v,{title:this.title,width:530,autoOpen:!1,destroyOnClose:!1})),this.dialog.elfinderdialog("open").find(".ui-tabs-nav li a:first").click()}},elFinder.prototype.commands.home=function(){this.title="Home",this.alwaysEnabled=!0,this.updateOnSelect=!1,this.shortcuts=[{pattern:"ctrl+home ctrl+shift+up",description:"Home"}],this.getstate=function(){var a=this.fm.root(),b=this.fm.cwd().hash;return a&&b&&a!=b?0:-1},this.exec=function(){return this.fm.exec("open",this.fm.root())}},elFinder.prototype.commands.info=function(){var b="msg",c=this.fm,d="elfinder-info-spinner",e={calc:c.i18n("calc"),size:c.i18n("size"),unknown:c.i18n("unknown"),path:c.i18n("path"),aliasfor:c.i18n("aliasfor"),modify:c.i18n("modify"),perms:c.i18n("perms"),locked:c.i18n("locked"),dim:c.i18n("dim"),kind:c.i18n("kind"),files:c.i18n("files"),folders:c.i18n("folders"),items:c.i18n("items"),yes:c.i18n("yes"),no:c.i18n("no"),link:c.i18n("link")};this.tpl={main:' {title}
',itemTitle:'{name} {kind} ',groupTitle:"{items}: {num} ",row:"{label} : {value} ",spinner:'{text} '},this.alwaysEnabled=!0,this.updateOnSelect=!1,this.shortcuts=[{pattern:"ctrl+i"}],this.init=function(){a.each(e,function(a,b){e[a]=c.i18n(b)})},this.getstate=function(){return 0},this.exec=function(b){var c=this.files(b);c.length||(c=this.files([this.fm.cwd().hash]));var f=this,g=this.fm,h=this.tpl,i=h.row,j=c.length,k=[],l=h.main,m="{label}",n="{value}",o={title:this.title,width:"auto",close:function(){a(this).elfinderdialog("destroy")}},p=[],q=function(a){s.find("."+d).parent().text(a)},r=g.namespace+"-info-"+a.map(c,function(a){return a.hash}).join("-"),s=g.getUI().find("#"+r),t,u,v,w,x;if(!j)return a.Deferred().reject();if(s.length)return s.elfinderdialog("toTop"),a.Deferred().resolve();j==1?(v=c[0],l=l.replace("{class}",g.mime2class(v.mime)),w=h.itemTitle.replace("{name}",g.escape(v.i18||v.name)).replace("{kind}",g.mime2kind(v)),v.tmb&&(u=g.option("tmbUrl")+v.tmb),v.read?v.mime!="directory"||v.alias?t=g.formatSize(v.size):(t=h.spinner.replace("{text}",e.calc),p.push(v.hash)):t=e.unknown,k.push(i.replace(m,e.size).replace(n,t)),v.alias&&k.push(i.replace(m,e.aliasfor).replace(n,v.alias)),k.push(i.replace(m,e.path).replace(n,g.escape(g.path(v.hash,!0)))),v.read&&k.push(i.replace(m,e.link).replace(n,''+v.name+" ")),v.dim?k.push(i.replace(m,e.dim).replace(n,v.dim)):v.mime.indexOf("image")!==-1&&(v.width&&v.height?k.push(i.replace(m,e.dim).replace(n,v.width+"x"+v.height)):(k.push(i.replace(m,e.dim).replace(n,h.spinner.replace("{text}",e.calc))),g.request({data:{cmd:"dim",target:v.hash},preventDefault:!0}).fail(function(){q(e.unknown)}).done(function(a){q(a.dim||e.unknown);if(a.dim){var b=a.dim.split("x"),c=g.file(v.hash);c.width=b[0],c.height=b[1]}}))),k.push(i.replace(m,e.modify).replace(n,g.formatDate(v))),k.push(i.replace(m,e.perms).replace(n,g.formatPermissions(v))),k.push(i.replace(m,e.locked).replace(n,v.locked?e.yes:e.no))):(l=l.replace("{class}","elfinder-cwd-icon-group"),w=h.groupTitle.replace("{items}",e.items).replace("{num}",j),x=a.map(c,function(a){return a.mime=="directory"?1:null}).length,x?(k.push(i.replace(m,e.kind).replace(n,x==j?e.folders:e.folders+" "+x+", "+e.files+" "+(j-x))),k.push(i.replace(m,e.size).replace(n,h.spinner.replace("{text}",e.calc))),p=a.map(c,function(a){return a.hash})):(t=0,a.each(c,function(a,b){var c=parseInt(b.size);c>=0&&t>=0?t+=c:t="unknown"}),k.push(i.replace(m,e.kind).replace(n,e.files)),k.push(i.replace(m,e.size).replace(n,g.formatSize(t))))),l=l.replace("{title}",w).replace("{content}",k.join("")),s=g.dialog(l,o),s.attr("id",r),u&&a(" ").load(function(){s.find(".elfinder-cwd-icon").css("background",'url("'+u+'") center center no-repeat')}).attr("src",u),p.length&&g.request({data:{cmd:"size",targets:p},preventDefault:!0}).fail(function(){q(e.unknown)}).done(function(a){var b=parseInt(a.size);q(b>=0?g.formatSize(b):e.unknown)})}},elFinder.prototype.commands.mkdir=function(){this.disableOnSearch=!0,this.updateOnSelect=!1,this.mime="directory",this.prefix="untitled folder",this.exec=a.proxy(this.fm.res("mixin","make"),this),this.shortcuts=[{pattern:"ctrl+shift+n"}],this.getstate=function(){return!this._disabled&&this.fm.cwd().write?0:-1}},elFinder.prototype.commands.mkfile=function(){this.disableOnSearch=!0,this.updateOnSelect=!1,this.mime="text/plain",this.prefix="untitled file.txt",this.exec=a.proxy(this.fm.res("mixin","make"),this),this.getstate=function(){return!this._disabled&&this.fm.cwd().write?0:-1}},elFinder.prototype.commands.netmount=function(){var b=this;this.alwaysEnabled=!0,this.updateOnSelect=!1,this.drivers=[],this.handlers={load:function(){this.drivers=this.fm.netDrivers}},this.getstate=function(){return this.drivers.length?0:-1},this.exec=function(){var c=b.fm,d=a.Deferred(),e=b.options,f=function(){var f={protocol:a(" ").change(function(){var a=this.value;h.find(".elfinder-netmount-tr").hide(),h.find(".elfinder-netmount-tr-"+a).show(),typeof e[a].select=="function"&&e[a].select(c)})},g={title:c.i18n("netMountDialogTitle"),resizable:!1,modal:!0,destroyOnClose:!0,close:function(){delete b.dialog,d.state()=="pending"&&d.reject()},buttons:{}},h=a(''),i=a("
");return h.append(a(" ").append(a(""+c.i18n("protocol")+" ")).append(a(" ").append(f.protocol))),a.each(b.drivers,function(b,d){f.protocol.append(''+c.i18n(d)+" "),a.each(e[d].inputs,function(b,e){e.attr("name",b),e.attr("type")!="hidden"?(e.addClass("ui-corner-all elfinder-netmount-inputs-"+d),h.append(a(" ").addClass("elfinder-netmount-tr elfinder-netmount-tr-"+d).append(a(""+c.i18n(b)+" ")).append(a(" ").append(e)))):(e.addClass("elfinder-netmount-inputs-"+d),i.append(e))})}),h.append(i),h.find(".elfinder-netmount-tr").hide(),g.buttons[c.i18n("btnMount")]=function(){var c=f.protocol.val(),e={cmd:"netmount",protocol:c};a.each(h.find("input.elfinder-netmount-inputs-"+c),function(b,c){var d;typeof c.val=="function"?d=a.trim(c.val()):d=a.trim(c.value),d&&(e[c.name]=d)});if(!e.host)return b.fm.trigger("error",{error:"errNetMountHostReq"});b.fm.request({data:e,notify:{type:"netmount",cnt:1,hideCnt:!0}}).done(function(){d.resolve()}).fail(function(a){d.reject(a)}),b.dialog.elfinderdialog("close")},g.buttons[c.i18n("btnCancel")]=function(){b.dialog.elfinderdialog("close")},c.dialog(h,g).ready(function(){f.protocol.change()})};return b.dialog||(b.dialog=f()),d.promise()}},elFinder.prototype.commands.netunmount=function(){var b=this;this.alwaysEnabled=!0,this.updateOnSelect=!1,this.drivers=[],this.handlers={load:function(){this.drivers=this.fm.netDrivers}},this.getstate=function(a){var b=this.fm;return!!a&&this.drivers.length&&!this._disabled&&b.file(a[0]
+).netkey?0:-1},this.exec=function(b){var c=this,d=this.fm,e=a.Deferred().fail(function(a){a&&d.error(a)}),f=d.file(b[0]);return this._disabled?e.reject():(e.state()=="pending"&&d.confirm({title:c.title,text:d.i18n("confirmUnmount",f.name),accept:{label:"btnUnmount",callback:function(){d.request({data:{cmd:"netmount",protocol:"netunmount",host:f.netkey,user:f.hash,pass:"dum"},notify:{type:"netunmount",cnt:1,hideCnt:!0},preventFail:!0}).fail(function(a){e.reject(a)}).done(function(a){var b=d.root()==f.hash;a.removed=[f.hash],d.remove(a);if(b){var c=d.files();for(var g in c)if(d.file(g).mime=="directory"){d.exec("open",g);break}}e.resolve()})}},cancel:{label:"btnCancel",callback:function(){e.reject()}}}),e)}},elFinder.prototype.commands.open=function(){this.alwaysEnabled=!0,this._handlers={dblclick:function(a){a.preventDefault(),this.exec()},"select enable disable reload":function(a){this.update(a.type=="disable"?-1:void 0)}},this.shortcuts=[{pattern:"ctrl+down numpad_enter"+(this.fm.OS!="mac"&&" enter")}],this.getstate=function(b){var b=this.files(b),c=b.length;return c==1?0:c?a.map(b,function(a){return a.mime=="directory"?null:a}).length==c?0:-1:-1},this.exec=function(b){var c=this.fm,d=a.Deferred().fail(function(a){a&&c.error(a)}),e=this.files(b),f=e.length,g,h,i,j,k,l,m,n;if(!f)return d.reject();if(f==1&&(g=e[0])&&g.mime=="directory")return g&&!g.read?d.reject(["errOpen",g.name,"errPerm"]):c.request({data:{cmd:"open",target:g.thash||g.hash},notify:{type:"open",cnt:1,hideCnt:!0},syncOnFail:!0});e=a.map(e,function(a){return a.mime!="directory"?a:null});if(f!=e.length)return d.reject();f=e.length;while(f--){g=e[f];if(!g.read)return d.reject(["errOpen",g.name,"errPerm"]);(h=c.url(g.hash))||(h=c.options.url,h=h+(h.indexOf("?")===-1?"?":"&")+(c.oldAPI?"cmd=open¤t="+g.phash:"cmd=file")+"&target="+g.hash),k=m=Math.round(2*a(window).width()/3),l=n=Math.round(2*a(window).height()/3),parseInt(g.width)&&parseInt(g.height)?(k=parseInt(g.width),l=parseInt(g.height)):g.dim&&(i=g.dim.split("x"),k=parseInt(i[0]),l=parseInt(i[1])),m>=k&&n>=l?(m=k,n=l):k-m>l-n?n=Math.round(l*(m/k)):m=Math.round(k*(n/l)),j="width="+m+",height="+n;if(!window.open(h,"_blank",j+",top=50,left=50,scrollbars=yes,resizable=yes"))return d.reject("errPopup")}return d.resolve(b)}},elFinder.prototype.commands.paste=function(){this.updateOnSelect=!1,this.handlers={changeclipboard:function(){this.update()}},this.shortcuts=[{pattern:"ctrl+v shift+insert"}],this.getstate=function(b){if(this._disabled)return-1;if(b){if(a.isArray(b)){if(b.length!=1)return-1;b=this.fm.file(b[0])}}else b=this.fm.cwd();return this.fm.clipboard().length&&b.mime=="directory"&&b.write?0:-1},this.exec=function(b){var c=this,d=c.fm,b=b?this.files(b)[0]:d.cwd(),e=d.clipboard(),f=e.length,g=f?e[0].cut:!1,h=g?"errMove":"errCopy",i=[],j=[],k=a.Deferred().fail(function(a){a&&d.error(a)}),l=function(b){return b.length&&d._commands.duplicate?d.exec("duplicate",b):a.Deferred().resolve()},m=function(e){var f=a.Deferred(),h=[],i=function(b,c){var d=[],e=b.length;while(e--)a.inArray(b[e].name,c)!==-1&&d.unshift(e);return d},j=function(a){var b=h[a],c=e[b],i=a==h.length-1;if(!c)return;d.confirm({title:d.i18n(g?"moveFiles":"copyFiles"),text:d.i18n(["errExists",c.name,"confirmRepl"]),all:!i,accept:{label:"btnYes",callback:function(b){!i&&!b?j(++a):l(e)}},reject:{label:"btnNo",callback:function(b){var c;if(b){c=h.length;while(a "),i={title:"Pixlr Editor or Pixlr Express ?",width:"auto",close:function(){a(this).elfinderdialog("destroy")}};return f?(h.css("text-align","center").append(a(" ").css("margin","30px").append("Pixlr Editor").button().click(function(){return g("editor"),a(this).elfinderdialog("destroy"),!1})).append(a(" ").css("margin","30px").append("Pixlr Express").button().click(function(){return g("express"),a(this).elfinderdialog("destroy"),!1})),dialog=c.dialog(h,i),d.resolve()):d.reject()}},elFinder.prototype.commands.quicklook=function(){var b=this,c=b.fm,d=0,e=1,f=2,g=d,h="elfinder-quicklook-navbar-icon",i="elfinder-quicklook-fullscreen",j=function(b){a(document).trigger(a.Event("keydown",{keyCode:b,ctrlKey:!1,shiftKey:!1,altKey:!1,metaKey:!1}))},k=function(a){return{opacity:0,width:20,height:c.view=="list"?1:20,top:a.offset().top+"px",left:a.offset().left+"px"}},l=function(){var b=a(window);return{opacity:1,width:n,height:o,top:parseInt((b.height()-o)/2+b.scrollTop()),left:parseInt((b.width()-n)/2+b.scrollLeft())}},m=function(a){var b=document.createElement(a.substr(0,a.indexOf("/"))),c=!1;try{c=b.canPlayType&&b.canPlayType(a)}catch(d){}return c&&c!==""&&c!="no"},n,o,p,q,r=a('
'),s=a("
"),t=a('
'),u=a('
').mousedown(function(d){var e=b.window,f=e.is("."+i),g="scroll."+c.namespace,j=a(window);d.stopPropagation(),f?(e.css(e.data("position")).unbind("mousemove"),j.unbind(g).trigger(b.resize).unbind(b.resize),v.unbind("mouseenter").unbind("mousemove")):(e.data("position",{left:e.css("left"),top:e.css("top"),width:e.width(),height:e.height()}).css({width:"100%",height:"100%"}),a(window).bind(g,function(){e.css({left:parseInt(a(window).scrollLeft())+"px",top:parseInt(a(window).scrollTop())+"px"})}).bind(b.resize,function(a){b.preview.trigger("changesize")}).trigger(g).trigger(b.resize),e.bind("mousemove",function(a){v.stop(!0,!0).show().delay(3e3).fadeOut("slow")}).mousemove(),v.mouseenter(function(){v.stop(!0,!0).show()}).mousemove(function(a){a.stopPropagation()})),v.attr("style","").draggable(f?"destroy":{}),e.toggleClass(i),a(this).toggleClass(h+"-fullscreen-off"),a.fn.resizable&&p.add(e).resizable(f?"enable":"disable").removeClass("ui-state-disabled"
+)}),v=a('
').append(a('
').mousedown(function(){j(37)})).append(u).append(a('
').mousedown(function(){j(39)})).append('
').append(a('
').mousedown(function(){b.window.trigger("close")}));this.resize="resize."+c.namespace,this.info=a('
').append(s).append(t),this.preview=a('
').bind("change",function(a){b.info.attr("style","").hide(),s.removeAttr("class").attr("style",""),t.html("")}).bind("update",function(c){var d=b.fm,e=b.preview,f=c.file,g='{value}
',h;f?(!f.read&&c.stopImmediatePropagation(),b.window.data("hash",f.hash),b.preview.unbind("changesize").trigger("change").children().remove(),r.html(d.escape(f.name)),t.html(g.replace(/\{value\}/,f.name)+g.replace(/\{value\}/,d.mime2kind(f))+(f.mime=="directory"?"":g.replace(/\{value\}/,d.formatSize(f.size)))+g.replace(/\{value\}/,d.i18n("modify")+": "+d.formatDate(f))),s.addClass("elfinder-cwd-icon ui-corner-all "+d.mime2class(f.mime)),f.tmb&&a(" ").hide().appendTo(b.preview).load(function(){s.css("background",'url("'+h+'") center center no-repeat'),a(this).remove()}).attr("src",h=d.tmb(f.hash)),b.info.delay(100).fadeIn(10)):c.stopImmediatePropagation()}),this.window=a('
').click(function(a){a.stopPropagation()}).append(a('
').append(r).append(a(' ').mousedown(function(a){a.stopPropagation(),b.window.trigger("close")}))).append(this.preview.add(v)).append(b.info.hide()).draggable({handle:"div.elfinder-quicklook-titlebar"}).bind("open",function(a){var c=b.window,d=b.value,h;b.closed()&&d&&(h=q.find("#"+d.hash)).length&&(v.attr("style",""),g=e,h.trigger("scrolltoview"),c.css(k(h)).show().animate(l(),550,function(){g=f,b.update(1,b.value)}))}).bind("close",function(a){var c=b.window,f=b.preview.trigger("change"),h=b.value,j=q.find("#"+c.data("hash")),l=function(){g=d,c.hide(),f.children().remove(),b.update(0,b.value)};b.opened()&&(g=e,c.is("."+i)&&u.mousedown(),j.length?c.animate(k(j),500,l):l())}),this.alwaysEnabled=!0,this.value=null,this.handlers={select:function(){this.update(void 0,this.fm.selectedFiles()[0])},error:function(){b.window.is(":visible")&&b.window.data("hash","").trigger("close")},"searchshow searchhide":function(){this.opened()&&this.window.trigger("close")}},this.shortcuts=[{pattern:"space"}],this.support={audio:{ogg:m('audio/ogg; codecs="vorbis"'),mp3:m("audio/mpeg;"),wav:m('audio/wav; codecs="1"'),m4a:m("audio/x-m4a;")||m("audio/aac;")},video:{ogg:m('video/ogg; codecs="theora"'),webm:m('video/webm; codecs="vp8, vorbis"'),mp4:m('video/mp4; codecs="avc1.42E01E"')||m('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')}},this.closed=function(){return g==d},this.opened=function(){return g==f},this.init=function(){var d=this.options,e=this.window,f=this.preview,g,h;n=d.width>0?parseInt(d.width):450,o=d.height>0?parseInt(d.height):300,c.one("load",function(){p=c.getUI(),q=c.getUI("cwd"),e.appendTo("body").zIndex(100+p.zIndex()),a(document).keydown(function(a){a.keyCode==27&&b.opened()&&e.trigger("close")}),a.fn.resizable&&e.resizable({handles:"se",minWidth:350,minHeight:120,resize:function(){f.trigger("changesize")}}),b.change(function(){b.opened()&&(b.value?f.trigger(a.Event("update",{file:b.value})):e.trigger("close"))}),a.each(c.commands.quicklook.plugins||[],function(a,c){typeof c=="function"&&new c(b)}),f.bind("update",function(){b.info.show()})})},this.getstate=function(){return this.fm.selected().length==1?g==f?1:0:-1},this.exec=function(){this.enabled()&&this.window.trigger(this.opened()?"close":"open")},this.hideinfo=function(){this.info.stop(!0).hide()}},elFinder.prototype.commands.quicklook.plugins=[function(b){var c=["image/jpeg","image/png","image/gif"],d=b.preview;a.each(navigator.mimeTypes,function(b,d){var e=d.type;e.indexOf("image/")===0&&a.inArray(e,c)&&c.push(e)}),d.bind("update",function(e){var f=e.file,g;a.inArray(f.mime,c)!==-1&&(e.stopImmediatePropagation(),g=a(" ").hide().appendTo(d).load(function(){setTimeout(function(){var a=(g.width()/g.height()).toFixed(2);d.bind("changesize",function(){var b=parseInt(d.width()),c=parseInt(d.height()),e,f;a<(b/c).toFixed(2)?(f=c,e=Math.floor(f*a)):(e=b,f=Math.floor(e/a)),g.width(e).height(f).css("margin-top",f ').appendTo(d)[0].contentWindow.document,doc.open(),doc.write(c.content),doc.close()}))})},function(b){var c=b.fm,d=c.res("mimes","text"),e=b.preview;e.bind("update",function(f){var g=f.file,h=g.mime,i;if(h.indexOf("text/")===0||a.inArray(h,d)!==-1)f.stopImmediatePropagation(),e.one("change",function(){i.state()=="pending"&&i.reject()}),i=c.request({data:{cmd:"get",target:g.hash},preventDefault:!0}).done(function(d){b.hideinfo(),a('").appendTo(e)})})},function(b){var c=b.fm,d="application/pdf",e=b.preview,f=!1;c.UA.Safari&&c.OS=="mac"||c.UA.IE?f=!0:a.each(navigator.plugins,function(b,c){a.each(c,function(a,b){if(b.type==d)return!(f=!0)})}),f&&e.bind("update",function(f){var g=f.file,h;g.mime==d&&(f.stopImmediatePropagation(),e.one("change",function(){h.unbind("load").remove()}),h=a('').hide().appendTo(e).load(function(){b.hideinfo(),h.show()}).attr("src",c.url(g.hash)))})},function(b){var c=b.fm,d="application/x-shockwave-flash",e=b.preview,f=!1;a.each(navigator.plugins,function(b,c){a.each(c,function(a,b){if(b.type==d)return!(f=!0)})}),f&&e.bind("update",function(f){var g=f.file,h;g.mime==d&&(f.stopImmediatePropagation(),b.hideinfo(),e.append(h=a(' ')))})},function(b){var c=b.preview,d=!!b.options.autoplay,e={"audio/mpeg":"mp3","audio/mpeg3":"mp3","audio/mp3":"mp3","audio/x-mpeg3":"mp3","audio/x-mp3":"mp3","audio/x-wav":"wav","audio/wav":"wav","audio/x-m4a":"m4a","audio/aac":"m4a","audio/mp4":"m4a","audio/x-mp4":"m4a","audio/ogg":"ogg"},f;c.bind("update",function(g){var h=g.file,i=e[h.mime];b.support.audio[i]&&(g.stopImmediatePropagation(),f=a(' ').appendTo(c),d&&f[0].play())}).bind("change",function(){f&&f.parent().length&&(f[0].pause(),f.remove(),f=null)})},function(b){var c=b.preview,d=!!b.options.autoplay,e={"video/mp4":"mp4","video/x-m4v":"mp4","video/ogg":"ogg","application/ogg":"ogg","video/webm":"webm"},f;c.bind("update",function(g){var h=g.file,i=e[h.mime];b.support.video[i]&&(g.stopImmediatePropagation(),b.hideinfo(),f=a(' ').appendTo(c),d&&f[0].play())}).bind("change",function(){f&&f.parent().length&&(f[0].pause(),f.remove(),f=null)})},function(b){var c=b.preview,d=[],e;a.each(navigator.plugins,function(b,c){a.each(c,function(a,b){(b.type.indexOf("audio/")===0||b.type.indexOf("video/")===0)&&d.push(b.type)})}),c.bind("update",function(f){var g=f.file,h=g.mime,i;a.inArray(g.mime,d)!==-1&&(f.stopImmediatePropagation(),(i=h.indexOf("video/")===0)&&b.hideinfo(),e=a(' ').appendTo(c))}).bind("change",function(){e&&e.parent().length&&(e.remove(),e=null)})}],elFinder.prototype.commands.reload=function(){this.alwaysEnabled=!0,this.updateOnSelect=!0,this.shortcuts=[{pattern:"ctrl+shift+r f5"}],this.getstate=function(){return 0},this.exec=function(){var a=this.fm,b=a.sync(),c=setTimeout(function(){a.notify({type:"reload",cnt:1,hideCnt:!0}),b.always(function(){a.notify({type:"reload",cnt:-1})})},a.notifyDelay);return b.always(function(){clearTimeout(c),a.trigger("reload")})}},elFinder.prototype.commands.rename=function(){this.shortcuts=[{pattern:"f2"+(this.fm.OS=="mac"?" enter":"")}],this.getstate=function(){var a=this.fm.selectedFiles();return!this._disabled&&a.length==1&&a[0].phash&&!a[0].locked?0:-1},this.exec=function(){var b=this.fm,c=b.getUI("cwd"),d=b.selected(),e=d.length,f=b.file(d.shift()),g=".elfinder-cwd-filename",h=a.Deferred().fail(function(a){var d=i.parent(),e=b.escape(f.name);d.length?(i.remove(),d.html(e)):(c.find("#"+f.hash).find(g).html(e),setTimeout(function(){c.find("#"+f.hash).click()},50)),a&&b.error(a)}).always(function(){b.enable()}),i=a(' ').keydown(function(b){b.stopPropagation(),b.stopImmediatePropagation(),b.keyCode==a.ui.keyCode.ESCAPE?h.reject():b.keyCode==a.ui.keyCode.ENTER&&i.blur()}).mousedown(function(a){a.stopPropagation()}).dblclick(function(a){a.stopPropagation(),a.preventDefault()}).blur(function(){var c=a.trim(i.val()),d=i.parent();if(d.length){i[0].setSelectionRange&&i[0].setSelectionRange(0,0);if(c==f.name)return h.reject();if(!c)return h.reject("errInvName");if(b.fileByName(c,f.phash))return h.reject(["errExists",c]);d.html(b.escape(c)),b.lockfiles({files:[f.hash]}),b.request({data:{cmd:"rename",target:f.hash,name:c},notify:{type:"rename",cnt:1}}).fail(function(a){h.reject(),b.sync()}).done(function(a){h.resolve(a)}).always(function(){b.unlockfiles({files:[f.hash]})})}}),j=c.find("#"+f.hash).find(g).empty().append(i.val(f.name)),k=i.val().replace(/\.((tar\.(gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(gz|bz2)|[a-z0-9]{1,4})$/ig,"");return this.disabled()?h.reject():!f||e>1||!j.length?h.reject("errCmdParams",this.title):f.locked?h.reject(["errLocked",f.name]):(b.one("select",function(){i.parent().length&&f&&a.inArray(f.hash,b.selected())===-1&&i.blur()}),i.select().focus(),i[0].setSelectionRange&&i[0].setSelectionRange(0,k.length),h)}},elFinder.prototype.commands.resize=function(){this.updateOnSelect=!1,this.getstate=function(){var a=this.fm.selectedFiles();return!this._disabled&&a.length==1&&a[0].read&&a[0].write&&a[0].mime.indexOf("image/")!==-1?0:-1},this.exec=function(b){var c=this.fm,d=this.files(b),e=a.Deferred(),f=function(b,d){var f=a('
'),g=' ',h='
',i='
',j=a('
'),k=a('
'),l=a(''+c.i18n("ntfloadimg")+"
"),m=a('
'),n=a('
'),o=a('
'),p=a('
'),q='
',r='
',s=' ',t=a('
'),u=a(r).attr("title",c.i18n("rotate-cw")).append(a(' ').click(function(){S-=90,ba.update(S)})),v=a(r).attr("title",c.i18n("rotate-ccw")).append(a(' ').click(function(){S+=90,ba.update(S)})),w=a(" "),x=a('
'),y=a('
').append(''+c.i18n("resize")+" ").append(''+c.i18n("crop")+" ").append(''+c.i18n("rotate")+" "),z=a("input",y).change(function(){var b=a("input:checked",y).val();Y(),bb(!0),bc(!0),bd(!0),b=="resize"?(o.show(),t.hide(),p.hide(),bb()):b=="crop"?(t.hide(),o.hide(),p.show(),bc()):b=="rotate"&&(o.hide(),p.hide(),t.show(),bd())}),A=a(' ').change(function(){N=!!A.prop("checked"),Z.fixHeight(),bb(!0),bb()}),B=a(g).change(function(){var a=parseInt(B.val()),b=parseInt(N?a/J:C.val());a>0&&b>0&&(Z.updateView(a,b),C.val(b))}),C=a(g).change(function(){var a=parseInt(C.val()),b=parseInt(N?a*J:B.val());b>0&&a>0&&(Z.updateView(b,a),B.val(b))}),D=a(g),E=a(g),F=a(g),G=a(g),H=a(' ').change(function(){ba.update()}),I=a('
').slider({min:0,max:359,value:H.val(),animate:!0,change:function(a,b){b.value!=I.slider("value")&&ba.update(b.value)},slide:function(a,b){ba.update(b.value,!1)}}),J=1,K=1,L=0,M=0,N=!0,O=0,P=0,Q=0,R=0,S=0,T=a(" ").load(function(){l.remove(),L=T.width(),M=T.height(),J=L/M,Z.updateView(L,M),m.append(T.show()).show(),B.val(L),C.val(M);var b=Math.min(O,P)/Math.sqrt(Math.pow(L,2)+Math.pow(M,2));Q=L*b,R=M*b,j.find("input,select").removeAttr("disabled").filter(":text").keydown(function(b){var c=b.keyCode,d;b.stopPropagation();if(c>=37&&c<=40||c==a.ui.keyCode.BACKSPACE||c==a.ui.keyCode.DELETE||c==65&&(b.ctrlKey||b.metaKey)||c==27)return;c==9&&(d=a(this).parent()[b.shiftKey?"prev":"next"](".elfinder-resize-row").children(":text"),d.length&&d.focus());if(c==13){be();return}c>=48&&c<=57||c>=96&&c<=105||b.preventDefault()}).filter(":first").focus(),bb(),x.hover(function(){x.toggleClass("ui-state-hover")}).click(Y)}).error(function(){l.text("Unable to load image").css("background","transparent")}),U=a("
"),V=a(" "),W=a("
"),X=a(" "),Y=function(){B.val(L),C.val(M),Z.updateView(L,M)},Z={update:function(){B.val(parseInt(T.width()/K)),C.val(parseInt(T.height()/K))},updateView:function(a,b){a>O||b>P?a/O>b/P?T.width(O).height(Math.ceil(T.width()/J)):T.height(P).width(Math.ceil(T.height()*J)):T.width(a).height(b),K=T.width()/a,w.text("1 : "+(1/K).toFixed(2)),Z.updateHandle()},updateHandle:function(){m.width(T.width()).height(T.height())},fixWidth:function(){var a,b;N&&(b=C.val(),b=parseInt(b*J),Z.updateView(a,b),B.val(a))},fixHeight:function(){var a,b;N&&(a=B.val(),b=parseInt(a/J),Z.updateView(a,b),C.val(b))}},_={update:function(){F.val(parseInt(n.width()/K)),G.val(parseInt(n.height()/K)),D.val(parseInt((n.offset().left-V.offset().left)/K)),E.val(parseInt((n.offset().top-V.offset().top)/K))},resize_update:function(){_.update(),W.width(n.width()),W.height(n.height())}},ba={mouseStartAngle:0,imageStartAngle:0,imageBeingRotated:!1,update:function(a,b){typeof a=="undefined"&&(S=a=parseInt(H.val())),typeof b=="undefined"&&(b=!0),!b||c.UA.Opera||c.UA.ltIE8?X.rotate(a):X.animate({rotate:a+"deg"}),a%=360,a<0&&(a+=360),H.val(parseInt(a)),I.slider("value",H.val())},execute:function(a){if(!ba.imageBeingRotated)return;var b=ba.getCenter(X),c=a.pageX-b[0],d=a.pageY-b[1],e=Math.atan2(d,c),f=e-ba.mouseStartAngle+ba.imageStartAngle;return f=Math.round(parseFloat(f)*180/Math.PI),a.shiftKey&&(f=Math.round((f+6)/15)*15),X.rotate(f),f%=360,f<0&&(f+=360),H.val(f),I.slider("value",H.val()),!1},start:function(b){ba.imageBeingRotated=!0;var c=ba.getCenter(X),d=b.pageX-c[0],e=b.pageY-c[1];return ba.mouseStartAngle=Math.atan2(e,d),ba.imageStartAngle=parseFloat(X.rotate())*Math.PI/180,a(document).mousemove(ba.execute),!1},stop:function(b){if(!ba.imageBeingRotated)return;return a(document).unbind("mousemove",ba.execute),setTimeout(function(){ba.imageBeingRotated=!1},10),!1},getCenter:function(a){var b=X.rotate();X.rotate(0);var c=X.offset(),d=c.left+X.width()/2,e=c.top+X.height()/2;return X.rotate(b),Array(d,e)}},bb=
+function(b){a.fn.resizable&&(b?(m.filter(":ui-resizable").resizable("destroy"),m.hide()):(m.show(),m.resizable({alsoResize:T,aspectRatio:N,resize:Z.update,stop:Z.fixHeight})))},bc=function(b){a.fn.draggable&&a.fn.resizable&&(b?(n.filter(":ui-resizable").resizable("destroy"),n.filter(":ui-draggable").draggable("destroy"),U.hide()):(V.width(T.width()).height(T.height()),W.width(T.width()).height(T.height()),n.width(V.width()).height(V.height()).offset(V.offset()).resizable({containment:U,resize:_.resize_update,handles:"all"}).draggable({handle:W,containment:V,drag:_.update}),U.show().width(T.width()).height(T.height()),_.update()))},bd=function(b){a.fn.draggable&&a.fn.resizable&&(b?X.hide():X.show().width(Q).height(R).css("margin-top",(P-R)/2+"px").css("margin-left",(O-Q)/2+"px"))},be=function(){var d,g,h,i,j,k=a("input:checked",y).val();B.add(C).change();if(k=="resize")d=parseInt(B.val())||0,g=parseInt(C.val())||0;else if(k=="crop")d=parseInt(F.val())||0,g=parseInt(G.val())||0,h=parseInt(D.val())||0,i=parseInt(E.val())||0;else if(k="rotate"){d=L,g=M,j=parseInt(H.val())||0;if(j<0||j>360)return c.error("Invalid rotate degree");if(j==0||j==360)return c.error("Image dose not rotated")}if(k!="rotate"){if(d<=0||g<=0)return c.error("Invalid image size");if(d==L&&g==M)return c.error("Image size not changed")}f.elfinderdialog("close"),c.request({data:{cmd:"resize",target:b.hash,width:d,height:g,x:h,y:i,degree:j,mode:k},notify:{type:"resize",cnt:1}}).fail(function(a){e.reject(a)}).done(function(){e.resolve()})},bf={},bg="elfinder-resize-handle-hline",bh="elfinder-resize-handle-vline",bi="elfinder-resize-handle-point",bj=c.url(b.hash);X.mousedown(ba.start),a(document).mouseup(ba.stop),o.append(a(h).append(a(i).text(c.i18n("width"))).append(B).append(x)).append(a(h).append(a(i).text(c.i18n("height"))).append(C)).append(a(h).append(a(" ").text(c.i18n("aspectRatio")).prepend(A))).append(a(h).append(c.i18n("scale")+" ").append(w)),p.append(a(h).append(a(i).text("X")).append(D)).append(a(h).append(a(i).text("Y")).append(E)).append(a(h).append(a(i).text(c.i18n("width"))).append(F)).append(a(h).append(a(i).text(c.i18n("height"))).append(G)),t.append(a(h).append(a(i).text(c.i18n("rotate"))).append(a('').append(a('
').append(H).append(a("
").text(c.i18n("degree")))).append(a(q).append(u).append(a(s)).append(v))).append(I)),f.append(y),j.append(a(h)).append(o).append(p.hide()).append(t.hide()).find("input,select").attr("disabled","disabled"),m.append('
').append('
').append('
').append('
').append('
').append('
').append('
'),k.append(l).append(m.hide()).append(T.hide()),n.css("position","absolute").append('
').append('
').append('
').append('
').append('
').append('
').append('
').append('
').append('
').append('
').append('
').append('
'),k.append(U.css("position","absolute").hide().append(V).append(n.append(W))),k.append(X.hide()),k.css("overflow","hidden"),f.append(k).append(j),bf[c.i18n("btnCancel")]=function(){f.elfinderdialog("close")},bf[c.i18n("btnApply")]=be,c.dialog(f,{title:b.name,width:650,resizable:!1,destroyOnClose:!0,buttons:bf,open:function(){k.zIndex(1+a(this).parent().zIndex())}}).attr("id",d),c.UA.ltIE8&&a(".elfinder-dialog").css("filter",""),x.css("left",B.position().left+B.width()+12),W.css({opacity:.2,"background-color":"#fff",position:"absolute"}),n.css("cursor","move"),n.find(".elfinder-resize-handle-point").css({"background-color":"#fff",opacity:.5,"border-color":"#000"}),X.css("cursor","pointer"),y.buttonset(),O=k.width()-(m.outerWidth()-m.width()),P=k.height()-(m.outerHeight()-m.height()),T.attr("src",bj+(bj.indexOf("?")===-1?"?":"&")+"_="+Math.random()),V.attr("src",T.attr("src")),X.attr("src",T.attr("src"))},g,h;return!d.length||d[0].mime.indexOf("image/")===-1?e.reject():(g="resize-"+c.namespace+"-"+d[0].hash,h=c.getUI().find("#"+g),h.length?(h.elfinderdialog("toTop"),e.resolve()):(f(d[0],g),e))}},function(a){var b=function(a,b){var c=0;for(c in b)if(typeof a[b[c]]!="undefined")return b[c];return a[b[c]]="",b[c]};a.cssHooks.rotate={get:function(b,c,d){return a(b).rotate()},set:function(b,c){return a(b).rotate(c),c}},a.cssHooks.transform={get:function(a,c,d){var e=b(a.style,["WebkitTransform","MozTransform","OTransform","msTransform","transform"]);return a.style[e]},set:function(a,c){var d=b(a.style,["WebkitTransform","MozTransform","OTransform","msTransform","transform"]);return a.style[d]=c,c}},a.fn.rotate=function(a){if(typeof a=="undefined"){if(!window.opera){var b=this.css("transform").match(/rotate\((.*?)\)/);return b&&b[1]?parseInt(b[1]):0}var b=this.css("transform").match(/rotate\((.*?)\)/);return b&&b[1]?Math.round(parseFloat(b[1])*180/Math.PI):0}return this.css("transform",this.css("transform").replace(/none|rotate\(.*?\)/,"")+"rotate("+parseInt(a)+"deg)"),this},a.fx.step.rotate=function(b){b.state==0&&(b.start=a(b.elem).rotate(),b.now=b.start),a(b.elem).rotate(b.now)};if(typeof window.addEventListener=="undefined"&&typeof document.getElementsByClassName=="undefined"){var c=function(a){var b=a,c=b.offsetLeft,d=b.offsetTop;while(b.offsetParent){b=b.offsetParent;if(b!=document.body&&b.currentStyle["position"]!="static")break;b!=document.body&&b!=document.documentElement&&(c-=b.scrollLeft,d-=b.scrollTop),c+=b.offsetLeft,d+=b.offsetTop}return{x:c,y:d}},d=function(a){if(a.currentStyle["position"]!="static")return;var b=c(a);a.style.position="absolute",a.style.left=b.x+"px",a.style.top=b.y+"px"},e=function(a,b){var c,e=1,f=1,g=1,h=1;if(typeof a.style["msTransform"]!="undefined")return!0;d(a),c=b.match(/rotate\((.*?)\)/);var i=c&&c[1]?parseInt(c[1]):0;i%=360,i<0&&(i=360+i);var j=i*Math.PI/180,k=Math.cos(j),l=Math.sin(j);e*=k,f*=-l,g*=l,h*=k,a.style.filter=(a.style.filter||"").replace(/progid:DXImageTransform\.Microsoft\.Matrix\([^)]*\)/,"")+("progid:DXImageTransform.Microsoft.Matrix(M11="+e+",M12="+f+",M21="+g+",M22="+h+",FilterType='bilinear',sizingMethod='auto expand')");var m=parseInt(a.style.width||a.width||0),n=parseInt(a.style.height||a.height||0),j=i*Math.PI/180,o=Math.abs(Math.cos(j)),p=Math.abs(Math.sin(j)),q=(m-(m*o+n*p))/2,r=(n-(m*p+n*o))/2;return a.style.marginLeft=Math.floor(q)+"px",a.style.marginTop=Math.floor(r)+"px",!0},f=a.cssHooks.transform.set;a.cssHooks.transform.set=function(a,b){return f.apply(this,[a,b]),e(a,b),b}}}(jQuery),elFinder.prototype.commands.rm=function(){this.shortcuts=[{pattern:"delete ctrl+backspace"}],this.getstate=function(b){var c=this.fm;return b=b||c.selected(),!this._disabled&&b.length&&a.map(b,function(a){var b=c.file(a);return b&&b.phash&&!b.locked?a:null}).length==b.length?0:-1},this.exec=function(b){var c=this,d=this.fm,e=a.Deferred().fail(function(a){a&&d.error(a)}),f=this.files(b),g=f.length,h=d.cwd().hash,i=!1;return!g||this._disabled?e.reject():(a.each(f,function(a,b){if(!b.phash)return!e.reject(["errRm",b.name,"errPerm"]);if(b.locked)return!e.reject(["errLocked",b.name]);b.hash==h&&(i=d.root(b.hash))}),e.state()=="pending"&&(f=this.hashes(b),d.confirm({title:c.title,text:"confirmRm",accept:{label:"btnRm",callback:function(){d.lockfiles({files:f}),d.request({data:{cmd:"rm",targets:f},notify:{type:"rm",cnt:g},preventFail:!0}).fail(function(a){e.reject(a)}).done(function(a){e.done(a),i&&d.exec("open",i)}).always(function(){d.unlockfiles({files:f})})}},cancel:{label:"btnCancel",callback:function(){e.reject()}}})),e)}},elFinder.prototype.commands.search=function(){this.title="Find files",this.options={ui:"searchbutton"},this.alwaysEnabled=!0,this.updateOnSelect=!1,this.getstate=function(){return 0},this.exec=function(b){var c=this.fm;
+return typeof b=="string"&&b?(c.trigger("searchstart",{query:b}),c.request({data:{cmd:"search",q:b},notify:{type:"search",cnt:1,hideCnt:!0}})):(c.getUI("toolbar").find("."+c.res("class","searchbtn")+" :text").focus(),a.Deferred().reject())}},elFinder.prototype.commands.sort=function(){this.options={ui:"sortbutton"},this.getstate=function(){return 0},this.exec=function(b,c){var d=this.fm,c=a.extend({type:d.sortType,order:d.sortOrder,stick:d.sortStickFolders},c);return this.fm.setSort(c.type,c.order,c.stick),a.Deferred().resolve()}},elFinder.prototype.commands.up=function(){this.alwaysEnabled=!0,this.updateOnSelect=!1,this.shortcuts=[{pattern:"ctrl+up"}],this.getstate=function(){return this.fm.cwd().phash?0:-1},this.exec=function(){return this.fm.cwd().phash?this.fm.exec("open",this.fm.cwd().phash):a.Deferred().reject()}},elFinder.prototype.commands.upload=function(){var b=this.fm.res("class","hover");this.disableOnSearch=!0,this.updateOnSelect=!1,this.shortcuts=[{pattern:"ctrl+u"}],this.getstate=function(){return!this._disabled&&this.fm.cwd().write?0:-1},this.exec=function(c){var d=this.fm,e=function(a){g.elfinderdialog("close"),d.upload(a).fail(function(a){f.reject(a)}).done(function(a){f.resolve(a)})},f,g,h,i,j,k;return this.disabled()?a.Deferred().reject():c&&(c.input||c.files)?d.upload(c):(f=a.Deferred(),h=a('
').change(function(){e({input:h[0]})}),i=a('
'+d.i18n("selectForUpload")+"
").append(a("
").append(h)).hover(function(){i.toggleClass(b)}),g=a('
').append(i),k=a('
').focus(function(){if(this.innerHTML){var a=this.innerHTML.replace(/
]*>/gi," "),b=a.match(/<[^>]+>/)?"html":"text";this.innerHTML="",e({files:[a],type:b})}}).bind("dragenter mouseover",function(){this.focus(),a(k).addClass(b)}).bind("dragleave mouseout",function(){this.blur(),a(k).removeClass(b)}).bind("mouseup keyup",function(){setTimeout(function(){a(k).focus()},100)}),d.dragUpload?(j=a('
'+d.i18n("dropFiles")+"
").prependTo(g).after('
'+d.i18n("or")+"
").after(k).after("
"+d.i18n("dropFilesBrowser")+"
").after('
'+d.i18n("or")+"
")[0],j.addEventListener("dragenter",function(c){c.stopPropagation(),c.preventDefault(),a(j).addClass(b)},!1),j.addEventListener("dragleave",function(c){c.stopPropagation(),c.preventDefault(),a(j).removeClass(b)},!1),j.addEventListener("dragover",function(c){c.stopPropagation(),c.preventDefault(),a(j).addClass(b)},!1),j.addEventListener("drop",function(a){a.stopPropagation(),a.preventDefault();var b=!1,c="";a.dataTransfer&&a.dataTransfer.items&&a.dataTransfer.items.length?(b=a.dataTransfer.items,c="data"):a.dataTransfer&&a.dataTransfer.files&&a.dataTransfer.files.length?(b=a.dataTransfer.files,c="files"):a.dataTransfer.getData("text/html")?(b=[a.dataTransfer.getData("text/html")],c="html"):a.dataTransfer.getData("text")&&(b=[a.dataTransfer.getData("text")],c="text"),b&&e({files:b,type:c})},!1)):a("
"+d.i18n("dropFilesBrowser")+"
").append(k).prependTo(g).after('
'+d.i18n("or")+"
")[0],d.dialog(g,{title:this.title,modal:!0,resizable:!1,destroyOnClose:!0}),f)}},elFinder.prototype.commands.view=function(){this.value=this.fm.viewType,this.alwaysEnabled=!0,this.updateOnSelect=!1,this.options={ui:"viewbutton"},this.getstate=function(){return 0},this.exec=function(){var a=this.fm.storage("view",this.value=="list"?"icons":"list");this.fm.viewchange(),this.update(void 0,a)}}})(jQuery)
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/js/i18n/elfinder.LANG.js b/deployed/windwalker/media/windwalker/js/elfinder/js/i18n/elfinder.LANG.js
new file mode 100644
index 00000000..4fab35c5
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/elfinder/js/i18n/elfinder.LANG.js
@@ -0,0 +1,355 @@
+/**
+ * elFinder translation template
+ * use this file to create new translation
+ * submit new translation via https://github.com/Studio-42/elFinder/issues
+ * or make a pull request
+ */
+
+/**
+ * XXXXX translation
+ * @author Translator Name
+ * @version 201x-xx-xx
+ */
+if (elFinder && elFinder.prototype && typeof(elFinder.prototype.i18) == 'object') {
+ elFinder.prototype.i18.REPLACE_WITH_xx_OR_xx_YY_LANG_CODE = {
+ translator : 'Translator name <translator@email.tld>',
+ language : 'Language of translation in your language',
+ direction : 'ltr',
+ dateFormat : 'd.m.Y H:i',
+ fancyDateFormat : '$1 H:i',
+ messages : {
+
+ /********************************** errors **********************************/
+ 'error' : 'Error',
+ 'errUnknown' : 'Unknown error.',
+ 'errUnknownCmd' : 'Unknown command.',
+ 'errJqui' : 'Invalid jQuery UI configuration. Selectable, draggable and droppable components must be included.',
+ 'errNode' : 'elFinder requires DOM Element to be created.',
+ 'errURL' : 'Invalid elFinder configuration! URL option is not set.',
+ 'errAccess' : 'Access denied.',
+ 'errConnect' : 'Unable to connect to backend.',
+ 'errAbort' : 'Connection aborted.',
+ 'errTimeout' : 'Connection timeout.',
+ 'errNotFound' : 'Backend not found.',
+ 'errResponse' : 'Invalid backend response.',
+ 'errConf' : 'Invalid backend configuration.',
+ 'errJSON' : 'PHP JSON module not installed.',
+ 'errNoVolumes' : 'Readable volumes not available.',
+ 'errCmdParams' : 'Invalid parameters for command "$1".',
+ 'errDataNotJSON' : 'Data is not JSON.',
+ 'errDataEmpty' : 'Data is empty.',
+ 'errCmdReq' : 'Backend request requires command name.',
+ 'errOpen' : 'Unable to open "$1".',
+ 'errNotFolder' : 'Object is not a folder.',
+ 'errNotFile' : 'Object is not a file.',
+ 'errRead' : 'Unable to read "$1".',
+ 'errWrite' : 'Unable to write into "$1".',
+ 'errPerm' : 'Permission denied.',
+ 'errLocked' : '"$1" is locked and can not be renamed, moved or removed.',
+ 'errExists' : 'File named "$1" already exists.',
+ 'errInvName' : 'Invalid file name.',
+ 'errFolderNotFound' : 'Folder not found.',
+ 'errFileNotFound' : 'File not found.',
+ 'errTrgFolderNotFound' : 'Target folder "$1" not found.',
+ 'errPopup' : 'Browser prevented opening popup window. To open file enable it in browser options.',
+ 'errMkdir' : 'Unable to create folder "$1".',
+ 'errMkfile' : 'Unable to create file "$1".',
+ 'errRename' : 'Unable to rename "$1".',
+ 'errCopyFrom' : 'Copying files from volume "$1" not allowed.',
+ 'errCopyTo' : 'Copying files to volume "$1" not allowed.',
+ 'errUploadCommon' : 'Upload error.',
+ 'errUpload' : 'Unable to upload "$1".',
+ 'errUploadNoFiles' : 'No files found for upload.',
+ 'errMaxSize' : 'Data exceeds the maximum allowed size.',
+ 'errFileMaxSize' : 'File exceeds maximum allowed size.',
+ 'errUploadMime' : 'File type not allowed.',
+ 'errUploadTransfer' : '"$1" transfer error.',
+ 'errSave' : 'Unable to save "$1".',
+ 'errCopy' : 'Unable to copy "$1".',
+ 'errMove' : 'Unable to move "$1".',
+ 'errCopyInItself' : 'Unable to copy "$1" into itself.',
+ 'errRm' : 'Unable to remove "$1".',
+ 'errExtract' : 'Unable to extract files from "$1".',
+ 'errArchive' : 'Unable to create archive.',
+ 'errArcType' : 'Unsupported archive type.',
+ 'errNoArchive' : 'File is not archive or has unsupported archive type.',
+ 'errCmdNoSupport' : 'Backend does not support this command.',
+ 'errReplByChild' : 'The folder “$1” can’t be replaced by an item it contains.',
+ 'errArcSymlinks' : 'For security reason denied to unpack archives contains symlinks or files with not allowed names.', // edited 24.06.2012
+ 'errArcMaxSize' : 'Archive files exceeds maximum allowed size.',
+ 'errResize' : 'Unable to resize "$1".',
+ 'errUsupportType' : 'Unsupported file type.',
+ 'errNotUTF8Content' : 'File "$1" is not in UTF-8 and cannot be edited.', // added 9.11.2011
+ 'errNetMount' : 'Unable to mount "$1".', // added 17.04.2012
+ 'errNetMountNoDriver' : 'Unsupported protocol.', // added 17.04.2012
+ 'errNetMountFailed' : 'Mount failed.', // added 17.04.2012
+ 'errNetMountHostReq' : 'Host required.', // added 18.04.2012
+ /******************************* commands names ********************************/
+ 'cmdarchive' : 'Create archive',
+ 'cmdback' : 'Back',
+ 'cmdcopy' : 'Copy',
+ 'cmdcut' : 'Cut',
+ 'cmddownload' : 'Download',
+ 'cmdduplicate' : 'Duplicate',
+ 'cmdedit' : 'Edit file',
+ 'cmdextract' : 'Extract files from archive',
+ 'cmdforward' : 'Forward',
+ 'cmdgetfile' : 'Select files',
+ 'cmdhelp' : 'About this software',
+ 'cmdhome' : 'Home',
+ 'cmdinfo' : 'Get info',
+ 'cmdmkdir' : 'New folder',
+ 'cmdmkfile' : 'New text file',
+ 'cmdopen' : 'Open',
+ 'cmdpaste' : 'Paste',
+ 'cmdquicklook' : 'Preview',
+ 'cmdreload' : 'Reload',
+ 'cmdrename' : 'Rename',
+ 'cmdrm' : 'Delete',
+ 'cmdsearch' : 'Find files',
+ 'cmdup' : 'Go to parent directory',
+ 'cmdupload' : 'Upload files',
+ 'cmdview' : 'View',
+ 'cmdresize' : 'Resize image',
+ 'cmdsort' : 'Sort',
+
+ /*********************************** buttons ***********************************/
+ 'btnClose' : 'Close',
+ 'btnSave' : 'Save',
+ 'btnRm' : 'Remove',
+ 'btnApply' : 'Apply',
+ 'btnCancel' : 'Cancel',
+ 'btnNo' : 'No',
+ 'btnYes' : 'Yes',
+
+ /******************************** notifications ********************************/
+ 'ntfopen' : 'Open folder',
+ 'ntffile' : 'Open file',
+ 'ntfreload' : 'Reload folder content',
+ 'ntfmkdir' : 'Creating directory',
+ 'ntfmkfile' : 'Creating files',
+ 'ntfrm' : 'Delete files',
+ 'ntfcopy' : 'Copy files',
+ 'ntfmove' : 'Move files',
+ 'ntfprepare' : 'Prepare to copy files',
+ 'ntfrename' : 'Rename files',
+ 'ntfupload' : 'Uploading files',
+ 'ntfdownload' : 'Downloading files',
+ 'ntfsave' : 'Save files',
+ 'ntfarchive' : 'Creating archive',
+ 'ntfextract' : 'Extracting files from archive',
+ 'ntfsearch' : 'Searching files',
+ 'ntfsmth' : 'Doing something >_<',
+ 'ntfloadimg' : 'Loading image',
+ 'ntfnetmount' : 'Mounting network volume', // added 18.04.2012
+
+ /************************************ dates **********************************/
+ 'dateUnknown' : 'unknown',
+ 'Today' : 'Today',
+ 'Yesterday' : 'Yesterday',
+ 'Jan' : 'Jan',
+ 'Feb' : 'Feb',
+ 'Mar' : 'Mar',
+ 'Apr' : 'Apr',
+ 'May' : 'May',
+ 'Jun' : 'Jun',
+ 'Jul' : 'Jul',
+ 'Aug' : 'Aug',
+ 'Sep' : 'Sep',
+ 'Oct' : 'Oct',
+ 'Nov' : 'Nov',
+ 'Dec' : 'Dec',
+ 'January' : 'January',
+ 'February' : 'February',
+ 'March' : 'March',
+ 'April' : 'April',
+ 'May' : 'May',
+ 'June' : 'June',
+ 'July' : 'July',
+ 'August' : 'August',
+ 'September' : 'September',
+ 'October' : 'October',
+ 'November' : 'November',
+ 'December' : 'December',
+ 'Sunday' : 'Sunday',
+ 'Monday' : 'Monday',
+ 'Tuesday' : 'Tuesday',
+ 'Wednesday' : 'Wednesday',
+ 'Thursday' : 'Thursday',
+ 'Friday' : 'Friday',
+ 'Saturday' : 'Saturday',
+ 'Sun' : 'Sun',
+ 'Mon' : 'Mon',
+ 'Tue' : 'Tue',
+ 'Wed' : 'Wed',
+ 'Thu' : 'Thu',
+ 'Fri' : 'Fri',
+ 'Sat' : 'Sat',
+ /******************************** sort variants ********************************/
+ 'sortname' : 'by name',
+ 'sortkind' : 'by kind',
+ 'sortsize' : 'by size',
+ 'sortdate' : 'by date',
+ 'sortFoldersFirst' : 'Folders first', // added 22.06.2012
+
+ /********************************** messages **********************************/
+ 'confirmReq' : 'Confirmation required',
+ 'confirmRm' : 'Are you sure you want to remove files? This cannot be undone!',
+ 'confirmRepl' : 'Replace old file with new one?',
+ 'apllyAll' : 'Apply to all',
+ 'name' : 'Name',
+ 'size' : 'Size',
+ 'perms' : 'Permissions',
+ 'modify' : 'Modified',
+ 'kind' : 'Kind',
+ 'read' : 'read',
+ 'write' : 'write',
+ 'noaccess' : 'no access',
+ 'and' : 'and',
+ 'unknown' : 'unknown',
+ 'selectall' : 'Select all files',
+ 'selectfiles' : 'Select file(s)',
+ 'selectffile' : 'Select first file',
+ 'selectlfile' : 'Select last file',
+ 'viewlist' : 'List view',
+ 'viewicons' : 'Icons view',
+ 'places' : 'Places',
+ 'calc' : 'Calculate',
+ 'path' : 'Path',
+ 'aliasfor' : 'Alias for',
+ 'locked' : 'Locked',
+ 'dim' : 'Dimensions',
+ 'files' : 'Files',
+ 'folders' : 'Folders',
+ 'items' : 'Items',
+ 'yes' : 'yes',
+ 'no' : 'no',
+ 'link' : 'Link',
+ 'searcresult' : 'Search results',
+ 'selected' : 'selected items',
+ 'about' : 'About',
+ 'shortcuts' : 'Shortcuts',
+ 'help' : 'Help',
+ 'webfm' : 'Web file manager',
+ 'ver' : 'Version',
+ 'protocolver' : 'protocol version',
+ 'homepage' : 'Project home',
+ 'docs' : 'Documentation',
+ 'github' : 'Fork us on Github',
+ 'twitter' : 'Follow us on twitter',
+ 'facebook' : 'Join us on facebook',
+ 'team' : 'Team',
+ 'chiefdev' : 'chief developer',
+ 'developer' : 'developer',
+ 'contributor' : 'contributor',
+ 'maintainer' : 'maintainer',
+ 'translator' : 'translator',
+ 'icons' : 'Icons',
+ 'dontforget' : 'and don\'t forget to take your towel',
+ 'shortcutsof' : 'Shortcuts disabled',
+ 'dropFiles' : 'Drop files here',
+ 'or' : 'or',
+ 'selectForUpload' : 'Select files to upload',
+ 'moveFiles' : 'Move files',
+ 'copyFiles' : 'Copy files',
+ 'rmFromPlaces' : 'Remove from places',
+ 'untitled folder' : 'untitled folder',
+ 'untitled file.txt' : 'untitled file.txt',
+ 'aspectRatio' : 'Aspect ratio',
+ 'scale' : 'Scale',
+ 'width' : 'Width',
+ 'height' : 'Height',
+ 'mode' : 'Mode',
+ 'resize' : 'Resize',
+ 'crop' : 'Crop',
+ 'rotate' : 'Rotate',
+ 'rotate-cw' : 'Rotate 90 degrees CW',
+ 'rotate-ccw' : 'Rotate 90 degrees CCW',
+ 'degree' : 'Degree',
+ 'netMountDialogTitle' : 'Mount network volume', // added 18.04.2012
+ 'protocol' : 'Protocol', // added 18.04.2012
+ 'host' : 'Host', // added 18.04.2012
+ 'port' : 'Port', // added 18.04.2012
+ 'user' : 'User', // added 18.04.2012
+ 'pass' : 'Password', // added 18.04.2012
+ /********************************** mimetypes **********************************/
+ 'kindUnknown' : 'Unknown',
+ 'kindFolder' : 'Folder',
+ 'kindAlias' : 'Alias',
+ 'kindAliasBroken' : 'Broken alias',
+ // applications
+ 'kindApp' : 'Application',
+ 'kindPostscript' : 'Postscript document',
+ 'kindMsOffice' : 'Microsoft Office document',
+ 'kindMsWord' : 'Microsoft Word document',
+ 'kindMsExcel' : 'Microsoft Excel document',
+ 'kindMsPP' : 'Microsoft Powerpoint presentation',
+ 'kindOO' : 'Open Office document',
+ 'kindAppFlash' : 'Flash application',
+ 'kindPDF' : 'Portable Document Format (PDF)',
+ 'kindTorrent' : 'Bittorrent file',
+ 'kind7z' : '7z archive',
+ 'kindTAR' : 'TAR archive',
+ 'kindGZIP' : 'GZIP archive',
+ 'kindBZIP' : 'BZIP archive',
+ 'kindZIP' : 'ZIP archive',
+ 'kindRAR' : 'RAR archive',
+ 'kindJAR' : 'Java JAR file',
+ 'kindTTF' : 'True Type font',
+ 'kindOTF' : 'Open Type font',
+ 'kindRPM' : 'RPM package',
+ // texts
+ 'kindText' : 'Text document',
+ 'kindTextPlain' : 'Plain text',
+ 'kindPHP' : 'PHP source',
+ 'kindCSS' : 'Cascading style sheet',
+ 'kindHTML' : 'HTML document',
+ 'kindJS' : 'Javascript source',
+ 'kindRTF' : 'Rich Text Format',
+ 'kindC' : 'C source',
+ 'kindCHeader' : 'C header source',
+ 'kindCPP' : 'C++ source',
+ 'kindCPPHeader' : 'C++ header source',
+ 'kindShell' : 'Unix shell script',
+ 'kindPython' : 'Python source',
+ 'kindJava' : 'Java source',
+ 'kindRuby' : 'Ruby source',
+ 'kindPerl' : 'Perl script',
+ 'kindSQL' : 'SQL source',
+ 'kindXML' : 'XML document',
+ 'kindAWK' : 'AWK source',
+ 'kindCSV' : 'Comma separated values',
+ 'kindDOCBOOK' : 'Docbook XML document',
+ // images
+ 'kindImage' : 'Image',
+ 'kindBMP' : 'BMP image',
+ 'kindJPEG' : 'JPEG image',
+ 'kindGIF' : 'GIF Image',
+ 'kindPNG' : 'PNG Image',
+ 'kindTIFF' : 'TIFF image',
+ 'kindTGA' : 'TGA image',
+ 'kindPSD' : 'Adobe Photoshop image',
+ 'kindXBITMAP' : 'X bitmap image',
+ 'kindPXM' : 'Pixelmator image',
+ // media
+ 'kindAudio' : 'Audio media',
+ 'kindAudioMPEG' : 'MPEG audio',
+ 'kindAudioMPEG4' : 'MPEG-4 audio',
+ 'kindAudioMIDI' : 'MIDI audio',
+ 'kindAudioOGG' : 'Ogg Vorbis audio',
+ 'kindAudioWAV' : 'WAV audio',
+ 'AudioPlaylist' : 'MP3 playlist',
+ 'kindVideo' : 'Video media',
+ 'kindVideoDV' : 'DV movie',
+ 'kindVideoMPEG' : 'MPEG movie',
+ 'kindVideoMPEG4' : 'MPEG-4 movie',
+ 'kindVideoAVI' : 'AVI movie',
+ 'kindVideoMOV' : 'Quick Time movie',
+ 'kindVideoWM' : 'Windows Media movie',
+ 'kindVideoFlash' : 'Flash movie',
+ 'kindVideoMKV' : 'Matroska movie',
+ 'kindVideoOGG' : 'Ogg movie'
+ }
+ }
+}
+
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/js/i18n/elfinder.zh_TW.js b/deployed/windwalker/media/windwalker/js/elfinder/js/i18n/elfinder.zh_TW.js
new file mode 100644
index 00000000..b601851f
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/elfinder/js/i18n/elfinder.zh_TW.js
@@ -0,0 +1,353 @@
+/**
+ * Traditional Chinese translation
+ * @author Yuwei Chuang
+ * @version 2013-05-07
+ */
+if (elFinder && elFinder.prototype && typeof(elFinder.prototype.i18) == 'object') {
+ elFinder.prototype.i18.zh_TW = {
+ translator : 'Yuwei Chuang <ywchuang.tw@gmail.com>',
+ language : '正體中文',
+ direction : 'ltr',
+ dateFormat : 'M d, Y h:i A', // Mar 13, 2012 05:27 PM
+ fancyDateFormat : '$1 H:i',
+ messages : {
+
+ /********************************** errors **********************************/
+ 'error' : '錯誤',
+ 'errUnknown' : '未知的錯誤.',
+ 'errUnknownCmd' : '未知的指令.',
+ 'errJqui' : '無效的 jQuery UI 設定. 必須包含 Selectable, draggable 以及 droppable 元件.',
+ 'errNode' : 'elFinder 需要能建立 DOM 元素.',
+ 'errURL' : '無效的 elFinder 設定! 尚未設定 URL 選項.',
+ 'errAccess' : '拒絕存取.',
+ 'errConnect' : '無法連線至後端.',
+ 'errAbort' : '連線中斷.',
+ 'errTimeout' : '連線逾時.',
+ 'errNotFound' : '後端不存在.',
+ 'errResponse' : '無效的後端回復.',
+ 'errConf' : '無效的後端設定.',
+ 'errJSON' : '未安裝 PHP JSON 模組.',
+ 'errNoVolumes' : '無可讀取的 volumes.',
+ 'errCmdParams' : '無效的參數, 指令: "$1".',
+ 'errDataNotJSON' : '資料不是 JSON 格式.',
+ 'errDataEmpty' : '沒有資料.',
+ 'errCmdReq' : '後端請求需要命令名稱.',
+ 'errOpen' : '無法打開 "$1".',
+ 'errNotFolder' : '非資料夾.',
+ 'errNotFile' : '非檔案.',
+ 'errRead' : '無法讀取 "$1".',
+ 'errWrite' : '無法寫入 "$1".',
+ 'errPerm' : '無權限.',
+ 'errLocked' : '"$1" 被鎖定,不能重新命名, 移動或删除.',
+ 'errExists' : '檔案 "$1" 已經存在了.',
+ 'errInvName' : '無效的檔案名稱.',
+ 'errFolderNotFound' : '未找到資料夾.',
+ 'errFileNotFound' : '未找到檔案.',
+ 'errTrgFolderNotFound' : '未找到目標資料夾 "$1".',
+ 'errPopup' : '連覽器攔截了彈跳視窗. 請在瀏覽器選項允許彈跳視窗.',
+ 'errMkdir' : '不能建立資料夾 "$1".',
+ 'errMkfile' : '不能建立檔案 "$1".',
+ 'errRename' : '不能重新命名 "$1".',
+ 'errCopyFrom' : '不允許從 volume "$1" 複製.',
+ 'errCopyTo' : '不允複製到 volume "$1".',
+ 'errUpload' : '上船錯誤.',
+ 'errUploadFile' : '無法上傳 "$1".',
+ 'errUploadNoFiles' : '未找到要上傳的檔案.',
+ 'errUploadTotalSize' : '資料超過了最大允許大小.',
+ 'errUploadFileSize' : '檔案超過了最大允許大小.',
+ 'errUploadMime' : '不允許的檔案類型.',
+ 'errUploadTransfer' : '"$1" 傳輸錯誤.',
+ 'errNotReplace' : '"$1" 已經存在此位置, 不能被其他的替换.', // new
+ 'errReplace' : '無法替换 "$1".',
+ 'errSave' : '無法保存 "$1".',
+ 'errCopy' : '無法複製 "$1".',
+ 'errMove' : '無法移動 "$1".',
+ 'errCopyInItself' : '無法移動 "$1" 到原有位置.',
+ 'errRm' : '無法删除 "$1".',
+ 'errRmSrc' : '無法删除來源檔案.',
+ 'errExtract' : '無法從 "$1" 解壓縮檔案.',
+ 'errArchive' : '無法建立壓縮膽案.',
+ 'errArcType' : '不支援的壓縮格式.',
+ 'errNoArchive' : '檔案不是壓縮檔案, 或者不支援該壓缩格式.',
+ 'errCmdNoSupport' : '後端不支援該指令.',
+ 'errReplByChild' : '資料夾 “$1” 不能被它所包含的檔案(資料夾)替换.',
+ 'errArcSymlinks' : '出于安全上的考量,禁止解壓縮檔案包含不允許的檔案名稱.',
+ 'errArcMaxSize' : '壓縮檔案超過最大允許檔案大小範圍.',
+ 'errResize' : '無法重新調整大小 "$1".',
+ 'errUsupportType' : '不支援的檔案格式.',
+ 'errNotUTF8Content' : '檔案 "$1" 不是 UTF-8 格式, 不能編輯.', // added 9.11.2011
+ 'errNetMount' : '無法掛載 "$1".', // added 17.04.2012
+ 'errNetMountNoDriver' : '不支援該通訊協議.', // added 17.04.2012
+ 'errNetMountFailed' : '掛載失敗.', // added 17.04.2012
+ 'errNetMountHostReq' : '需要指定主機位置.', // added 18.04.2012
+ /******************************* commands names ********************************/
+ 'cmdarchive' : '建立壓縮檔案',
+ 'cmdback' : '後退',
+ 'cmdcopy' : '複製',
+ 'cmdcut' : '剪下',
+ 'cmddownload' : '下載',
+ 'cmdduplicate' : '建立副本',
+ 'cmdedit' : '編輯檔案',
+ 'cmdextract' : '從壓縮檔案解壓縮',
+ 'cmdforward' : '前進',
+ 'cmdgetfile' : '選擇檔案',
+ 'cmdhelp' : '關於本軟體',
+ 'cmdhome' : '首頁',
+ 'cmdinfo' : '查看關於',
+ 'cmdmkdir' : '建立資料夾',
+ 'cmdmkfile' : '建立文字檔案',
+ 'cmdopen' : '打開',
+ 'cmdpaste' : '貼上',
+ 'cmdquicklook' : '預覽',
+ 'cmdreload' : '更新',
+ 'cmdrename' : '重新命名',
+ 'cmdrm' : '删除',
+ 'cmdsearch' : '搜尋檔案',
+ 'cmdup' : '移到上一層資料夾',
+ 'cmdupload' : '上傳檔案',
+ 'cmdview' : '查看',
+ 'cmdresize' : '重新調整大小',
+ 'cmdsort' : '排序',
+ 'cmdnetmount' : '掛載 net volume', // added 18.04.2012
+
+ /*********************************** buttons ***********************************/
+ 'btnClose' : '關閉',
+ 'btnSave' : '儲存',
+ 'btnRm' : '删除',
+ 'btnApply' : '使用',
+ 'btnCancel' : '取消',
+ 'btnNo' : '否',
+ 'btnYes' : '是',
+ 'btnMount' : '掛載', // added 18.04.2012
+ /******************************** notifications ********************************/
+ 'ntfopen' : '打開資料夾',
+ 'ntffile' : '打開檔案',
+ 'ntfreload' : '更新資料夾内容',
+ 'ntfmkdir' : '建立資料夾',
+ 'ntfmkfile' : '建立檔案',
+ 'ntfrm' : '删除檔案',
+ 'ntfcopy' : '複製檔案',
+ 'ntfmove' : '移動檔案',
+ 'ntfprepare' : '準備複製檔案',
+ 'ntfrename' : '重新命名檔案',
+ 'ntfupload' : '上傳檔案',
+ 'ntfdownload' : '下載檔案',
+ 'ntfsave' : '儲存檔案',
+ 'ntfarchive' : '建立壓縮檔案',
+ 'ntfextract' : '從壓縮檔案解壓縮',
+ 'ntfsearch' : '搜尋檔案',
+ 'ntfresize' : '正在更改尺寸',
+ 'ntfsmth' : '正在忙 >_<',
+ 'ntfloadimg' : '正在讀取圖片',
+ 'ntfnetmount' : '正在掛載 net volume', // added 18.04.2012
+
+ /************************************ dates **********************************/
+ 'dateUnknown' : '未知',
+ 'Today' : '今天',
+ 'Yesterday' : '昨天',
+ 'Jan' : '一月',
+ 'Feb' : '二月',
+ 'Mar' : '三月',
+ 'Apr' : '四月',
+ 'May' : '五月',
+ 'Jun' : '六月',
+ 'Jul' : '七月',
+ 'Aug' : '八月',
+ 'Sep' : '九月',
+ 'Oct' : '十月',
+ 'Nov' : '十一月',
+ 'Dec' : '十二月',
+ 'January' : '一月',
+ 'February' : '二月',
+ 'March' : '三月',
+ 'April' : '四月',
+ 'May' : '五月',
+ 'June' : '六月',
+ 'July' : '七月',
+ 'August' : '八月',
+ 'September' : '九月',
+ 'October' : '十月',
+ 'November' : '十一月',
+ 'December' : '十二月',
+ 'Sunday' : '星期日',
+ 'Monday' : '星期一',
+ 'Tuesday' : '星期二',
+ 'Wednesday' : '星期三',
+ 'Thursday' : '星期四',
+ 'Friday' : '星期五',
+ 'Saturday' : '星期六',
+ 'Sun' : '周日',
+ 'Mon' : '周一',
+ 'Tue' : '周二',
+ 'Wed' : '周三',
+ 'Thu' : '周四',
+ 'Fri' : '周五',
+ 'Sat' : '周六',
+ /******************************** sort variants ********************************/
+ 'sortnameDirsFirst' : '按名稱 (資料夾在最前)',
+ 'sortkindDirsFirst' : '按類型 (資料夾在最前)',
+ 'sortsizeDirsFirst' : '按大小 (資料夾在最前)',
+ 'sortdateDirsFirst' : '按日期 (資料夾在最前)',
+ 'sortname' : '按名稱',
+ 'sortkind' : '按類型',
+ 'sortsize' : '按大小',
+ 'sortdate' : '按日期',
+
+ /********************************** messages **********************************/
+ 'confirmReq' : '請確認',
+ 'confirmRm' : '確定要删除檔案嗎? 該操作不可回復!',
+ 'confirmRepl' : '用新的檔案替换原有檔案?',
+ 'apllyAll' : '全部使用',
+ 'name' : '名稱',
+ 'size' : '大小',
+ 'perms' : '權限',
+ 'modify' : '修改于',
+ 'kind' : '類別',
+ 'read' : '讀取',
+ 'write' : '寫入',
+ 'noaccess' : '無權限',
+ 'and' : '和',
+ 'unknown' : '未知',
+ 'selectall' : '選擇所有檔案',
+ 'selectfiles' : '選擇檔案',
+ 'selectffile' : '選擇第一個檔案',
+ 'selectlfile' : '選擇最後一個檔案',
+ 'viewlist' : '列表檢視',
+ 'viewicons' : '圖示檢視',
+ 'places' : '位置',
+ 'calc' : '計算',
+ 'path' : '路徑',
+ 'aliasfor' : '别名',
+ 'locked' : '鎖定',
+ 'dim' : '尺寸',
+ 'files' : '檔案',
+ 'folders' : '資料夾',
+ 'items' : '項目',
+ 'yes' : '是',
+ 'no' : '否',
+ 'link' : '連結',
+ 'searcresult' : '搜尋结果',
+ 'selected' : '選取的項目',
+ 'about' : '關於',
+ 'shortcuts' : '快捷鍵',
+ 'help' : '幫助',
+ 'webfm' : '網路檔案總管',
+ 'ver' : '版本',
+ 'protocolver' : '協定版本',
+ 'homepage' : '首頁',
+ 'docs' : '文件',
+ 'github' : 'Fork us on Github',
+ 'twitter' : 'Follow us on twitter',
+ 'facebook' : 'Join us on facebook',
+ 'team' : '團隊',
+ 'chiefdev' : '首席開發者',
+ 'developer' : '開發者',
+ 'contributor' : '貢獻者',
+ 'maintainer' : '維護者',
+ 'translator' : '翻譯',
+ 'icons' : '圖示',
+ 'dontforget' : '别忘了帶上你擦汗的毛巾',
+ 'shortcutsof' : '快捷鍵已禁用',
+ 'dropFiles' : '把檔案拖到此處',
+ 'or' : '或者',
+ 'selectForUpload' : '選擇要上傳的檔案',
+ 'moveFiles' : '移動檔案',
+ 'copyFiles' : '複製檔案',
+ 'rmFromPlaces' : '從位置中删除',
+ 'untitled folder' : '未命名資料夾',
+ 'untitled file.txt' : '未命名檔案.txt',
+ 'aspectRatio' : '保持比例',
+ 'scale' : '寬高比',
+ 'width' : '寬',
+ 'height' : '高',
+ 'mode' : '模式',
+ 'resize' : '重新調整大小',
+ 'crop' : '裁切',
+ 'rotate' : '旋轉',
+ 'rotate-cw' : '順時針旋轉90度',
+ 'rotate-ccw' : '逆時針旋轉90度',
+ 'degree' : '度',
+ 'port' : '接口', // added 18.04.2012
+ 'user' : '使用者', // added 18.04.2012
+ 'pass' : '密碼', // added 18.04.2012
+
+ /********************************** mimetypes **********************************/
+ 'kindUnknown' : '未知',
+ 'kindFolder' : '資料夾',
+ 'kindAlias' : '别名',
+ 'kindAliasBroken' : '錯誤的别名',
+ // applications
+ 'kindApp' : '應用程式',
+ 'kindPostscript' : 'Postscript 文件',
+ 'kindMsOffice' : 'Microsoft Office 文件',
+ 'kindMsWord' : 'Microsoft Word 文件',
+ 'kindMsExcel' : 'Microsoft Excel 文件',
+ 'kindMsPP' : 'Microsoft Powerpoint 簡報',
+ 'kindOO' : 'Open Office 文件',
+ 'kindAppFlash' : 'Flash 應用程式',
+ 'kindPDF' : 'Portable Document Format (PDF)',
+ 'kindTorrent' : 'Bittorrent 檔案',
+ 'kind7z' : '7z 壓縮檔案',
+ 'kindTAR' : 'TAR 壓縮檔案',
+ 'kindGZIP' : 'GZIP 壓縮檔案',
+ 'kindBZIP' : 'BZIP 壓縮檔案',
+ 'kindZIP' : 'ZIP 壓縮檔案',
+ 'kindRAR' : 'RAR 壓縮檔案',
+ 'kindJAR' : 'Java JAR 檔案',
+ 'kindTTF' : 'True Type 字體',
+ 'kindOTF' : 'Open Type 字體',
+ 'kindRPM' : 'RPM 封裝',
+ // texts
+ 'kindText' : '文字檔案',
+ 'kindTextPlain' : '純文字',
+ 'kindPHP' : 'PHP 程式碼',
+ 'kindCSS' : 'CSS',
+ 'kindHTML' : 'HTML 文件',
+ 'kindJS' : 'Javascript 程式碼',
+ 'kindRTF' : '富文字格式(RTF)',
+ 'kindC' : 'C 程式碼',
+ 'kindCHeader' : 'C 標頭檔',
+ 'kindCPP' : 'C++ 程式碼',
+ 'kindCPPHeader' : 'C++ 標頭檔',
+ 'kindShell' : 'Unix Shell 脚本',
+ 'kindPython' : 'Python 程式碼',
+ 'kindJava' : 'Java 程式碼',
+ 'kindRuby' : 'Ruby 程式碼',
+ 'kindPerl' : 'Perl 程式碼',
+ 'kindSQL' : 'SQL 脚本',
+ 'kindXML' : 'XML 文件',
+ 'kindAWK' : 'AWK 程式碼',
+ 'kindCSV' : '逗號分隔值檔案(CSV)',
+ 'kindDOCBOOK' : 'Docbook XML 文件',
+ // images
+ 'kindImage' : '圖片',
+ 'kindBMP' : 'BMP 圖片',
+ 'kindJPEG' : 'JPEG 圖片',
+ 'kindGIF' : 'GIF 圖片',
+ 'kindPNG' : 'PNG 圖片',
+ 'kindTIFF' : 'TIFF 圖片',
+ 'kindTGA' : 'TGA 圖片',
+ 'kindPSD' : 'Adobe Photoshop 圖片',
+ 'kindXBITMAP' : 'X bitmap 圖片',
+ 'kindPXM' : 'Pixelmator 圖片',
+ // media
+ 'kindAudio' : '聲音',
+ 'kindAudioMPEG' : 'MPEG 聲音',
+ 'kindAudioMPEG4' : 'MPEG-4 聲音',
+ 'kindAudioMIDI' : 'MIDI 聲音',
+ 'kindAudioOGG' : 'Ogg Vorbis 聲音',
+ 'kindAudioWAV' : 'WAV 聲音',
+ 'AudioPlaylist' : 'MP3 播放列表',
+ 'kindVideo' : '影片',
+ 'kindVideoDV' : 'DV 影片',
+ 'kindVideoMPEG' : 'MPEG 影片',
+ 'kindVideoMPEG4' : 'MPEG-4 影片',
+ 'kindVideoAVI' : 'AVI 影片',
+ 'kindVideoMOV' : 'Quick Time 影片',
+ 'kindVideoWM' : 'Windows Media 影片',
+ 'kindVideoFlash' : 'Flash 影片',
+ 'kindVideoMKV' : 'Matroska 影片',
+ 'kindVideoOGG' : 'Ogg 影片'
+ }
+ }
+}
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/js/i18n/index.html b/deployed/windwalker/media/windwalker/js/elfinder/js/i18n/index.html
new file mode 100644
index 00000000..3af63015
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/elfinder/js/i18n/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/elfinder/js/index.html b/deployed/windwalker/media/windwalker/js/elfinder/js/index.html
new file mode 100644
index 00000000..3af63015
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/elfinder/js/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/index.html b/deployed/windwalker/media/windwalker/js/index.html
new file mode 100644
index 00000000..2efb97f3
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/index.html
@@ -0,0 +1 @@
+
diff --git a/deployed/windwalker/media/windwalker/js/jquery/index.html b/deployed/windwalker/media/windwalker/js/jquery/index.html
new file mode 100644
index 00000000..2efb97f3
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/jquery/index.html
@@ -0,0 +1 @@
+
diff --git a/deployed/windwalker/media/windwalker/js/jquery/jquery-ui.min.js b/deployed/windwalker/media/windwalker/js/jquery/jquery-ui.min.js
new file mode 100644
index 00000000..ee884416
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/jquery/jquery-ui.min.js
@@ -0,0 +1,125 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.core.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){function c(b,c){var e=b.nodeName.toLowerCase();if("area"===e){var f=b.parentNode,g=f.name,h;return!b.href||!g||f.nodeName.toLowerCase()!=="map"?!1:(h=a("img[usemap=#"+g+"]")[0],!!h&&d(h))}return(/input|select|textarea|button|object/.test(e)?!b.disabled:"a"==e?b.href||c:c)&&d(b)}function d(b){return!a(b).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.ui=a.ui||{};if(a.ui.version)return;a.extend(a.ui,{version:"1.8.24",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}}),a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(b,c){return typeof b=="number"?this.each(function(){var d=this;setTimeout(function(){a(d).focus(),c&&c.call(d)},b)}):this._focus.apply(this,arguments)},scrollParent:function(){var b;return a.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?b=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.curCSS(this,"position",1))&&/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0):b=this.parents().filter(function(){return/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0),/fixed/.test(this.css("position"))||!b.length?a(document):b},zIndex:function(c){if(c!==b)return this.css("zIndex",c);if(this.length){var d=a(this[0]),e,f;while(d.length&&d[0]!==document){e=d.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){f=parseInt(d.css("zIndex"),10);if(!isNaN(f)&&f!==0)return f}d=d.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),a("").outerWidth(1).jquery||a.each(["Width","Height"],function(c,d){function h(b,c,d,f){return a.each(e,function(){c-=parseFloat(a.curCSS(b,"padding"+this,!0))||0,d&&(c-=parseFloat(a.curCSS(b,"border"+this+"Width",!0))||0),f&&(c-=parseFloat(a.curCSS(b,"margin"+this,!0))||0)}),c}var e=d==="Width"?["Left","Right"]:["Top","Bottom"],f=d.toLowerCase(),g={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){return c===b?g["inner"+d].call(this):this.each(function(){a(this).css(f,h(this,c)+"px")})},a.fn["outer"+d]=function(b,c){return typeof b!="number"?g["outer"+d].call(this,b):this.each(function(){a(this).css(f,h(this,b,!0,c)+"px")})}}),a.extend(a.expr[":"],{data:a.expr.createPseudo?a.expr.createPseudo(function(b){return function(c){return!!a.data(c,b)}}):function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return c(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var d=a.attr(b,"tabindex"),e=isNaN(d);return(e||d>=0)&&c(b,!e)}}),a(function(){var b=document.body,c=b.appendChild(c=document.createElement("div"));c.offsetHeight,a.extend(c.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),a.support.minHeight=c.offsetHeight===100,a.support.selectstart="onselectstart"in c,b.removeChild(c).style.display="none"}),a.curCSS||(a.curCSS=a.css),a.extend(a.ui,{plugin:{add:function(b,c,d){var e=a.ui[b].prototype;for(var f in d)e.plugins[f]=e.plugins[f]||[],e.plugins[f].push([c,d[f]])},call:function(a,b,c){var d=a.plugins[b];if(!d||!a.element[0].parentNode)return;for(var e=0;e0?!0:(b[d]=1,e=b[d]>0,b[d]=0,e)},isOverAxis:function(a,b,c){return a>b&&a=9||!!b.button?this._mouseStarted?(this._mouseDrag(b),b.preventDefault()):(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,b)!==!1,this._mouseStarted?this._mouseDrag(b):this._mouseUp(b)),!this._mouseStarted):this._mouseUp(b)},_mouseUp:function(b){return a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,b.target==this._mouseDownEvent.target&&a.data(b.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(b)),!1},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(a){return this.mouseDelayMet},_mouseStart:function(a){},_mouseDrag:function(a){},_mouseStop:function(a){},_mouseCapture:function(a){return!0}})})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.position.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.ui=a.ui||{};var c=/left|center|right/,d=/top|center|bottom/,e="center",f={},g=a.fn.position,h=a.fn.offset;a.fn.position=function(b){if(!b||!b.of)return g.apply(this,arguments);b=a.extend({},b);var h=a(b.of),i=h[0],j=(b.collision||"flip").split(" "),k=b.offset?b.offset.split(" "):[0,0],l,m,n;return i.nodeType===9?(l=h.width(),m=h.height(),n={top:0,left:0}):i.setTimeout?(l=h.width(),m=h.height(),n={top:h.scrollTop(),left:h.scrollLeft()}):i.preventDefault?(b.at="left top",l=m=0,n={top:b.of.pageY,left:b.of.pageX}):(l=h.outerWidth(),m=h.outerHeight(),n=h.offset()),a.each(["my","at"],function(){var a=(b[this]||"").split(" ");a.length===1&&(a=c.test(a[0])?a.concat([e]):d.test(a[0])?[e].concat(a):[e,e]),a[0]=c.test(a[0])?a[0]:e,a[1]=d.test(a[1])?a[1]:e,b[this]=a}),j.length===1&&(j[1]=j[0]),k[0]=parseInt(k[0],10)||0,k.length===1&&(k[1]=k[0]),k[1]=parseInt(k[1],10)||0,b.at[0]==="right"?n.left+=l:b.at[0]===e&&(n.left+=l/2),b.at[1]==="bottom"?n.top+=m:b.at[1]===e&&(n.top+=m/2),n.left+=k[0],n.top+=k[1],this.each(function(){var c=a(this),d=c.outerWidth(),g=c.outerHeight(),h=parseInt(a.curCSS(this,"marginLeft",!0))||0,i=parseInt(a.curCSS(this,"marginTop",!0))||0,o=d+h+(parseInt(a.curCSS(this,"marginRight",!0))||0),p=g+i+(parseInt(a.curCSS(this,"marginBottom",!0))||0),q=a.extend({},n),r;b.my[0]==="right"?q.left-=d:b.my[0]===e&&(q.left-=d/2),b.my[1]==="bottom"?q.top-=g:b.my[1]===e&&(q.top-=g/2),f.fractions||(q.left=Math.round(q.left),q.top=Math.round(q.top)),r={left:q.left-h,top:q.top-i},a.each(["left","top"],function(c,e){a.ui.position[j[c]]&&a.ui.position[j[c]][e](q,{targetWidth:l,targetHeight:m,elemWidth:d,elemHeight:g,collisionPosition:r,collisionWidth:o,collisionHeight:p,offset:k,my:b.my,at:b.at})}),a.fn.bgiframe&&c.bgiframe(),c.offset(a.extend(q,{using:b.using}))})},a.ui.position={fit:{left:function(b,c){var d=a(window),e=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft();b.left=e>0?b.left-e:Math.max(b.left-c.collisionPosition.left,b.left)},top:function(b,c){var d=a(window),e=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop();b.top=e>0?b.top-e:Math.max(b.top-c.collisionPosition.top,b.top)}},flip:{left:function(b,c){if(c.at[0]===e)return;var d=a(window),f=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft(),g=c.my[0]==="left"?-c.elemWidth:c.my[0]==="right"?c.elemWidth:0,h=c.at[0]==="left"?c.targetWidth:-c.targetWidth,i=-2*c.offset[0];b.left+=c.collisionPosition.left<0?g+h+i:f>0?g+h+i:0},top:function(b,c){if(c.at[1]===e)return;var d=a(window),f=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(),g=c.my[1]==="top"?-c.elemHeight:c.my[1]==="bottom"?c.elemHeight:0,h=c.at[1]==="top"?c.targetHeight:-c.targetHeight,i=-2*c.offset[1];b.top+=c.collisionPosition.top<0?g+h+i:f>0?g+h+i:0}}},a.offset.setOffset||(a.offset.setOffset=function(b,c){/static/.test(a.curCSS(b,"position"))&&(b.style.position="relative");var d=a(b),e=d.offset(),f=parseInt(a.curCSS(b,"top",!0),10)||0,g=parseInt(a.curCSS(b,"left",!0),10)||0,h={top:c.top-e.top+f,left:c.left-e.left+g};"using"in c?c.using.call(b,h):d.css(h)},a.fn.offset=function(b){var c=this[0];return!c||!c.ownerDocument?null:b?a.isFunction(b)?this.each(function(c){a(this).offset(b.call(this,c,a(this).offset()))}):this.each(function(){a.offset.setOffset(this,b)}):h.call(this)}),a.curCSS||(a.curCSS=a.css),function(){var b=document.getElementsByTagName("body")[0],c=document.createElement("div"),d,e,g,h,i;d=document.createElement(b?"div":"body"),g={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},b&&a.extend(g,{position:"absolute",left:"-1000px",top:"-1000px"});for(var j in g)d.style[j]=g[j];d.appendChild(c),e=b||document.documentElement,e.insertBefore(d,e.firstChild),c.style.cssText="position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;",h=a(c).offset(function(a,b){return b}).offset(),d.innerHTML="",e.removeChild(d),i=h.top+h.left+(b?2e3:0),f.fractions=i>21&&i<22}()})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.draggable.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.widget("ui.draggable",a.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1},_create:function(){this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},destroy:function(){if(!this.element.data("draggable"))return;return this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy(),this},_mouseCapture:function(b){var c=this.options;return this.helper||c.disabled||a(b.target).is(".ui-resizable-handle")?!1:(this.handle=this._getHandle(b),this.handle?(c.iframeFix&&a(c.iframeFix===!0?"iframe":c.iframeFix).each(function(){a('
').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(a(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(b){var c=this.options;return this.helper=this._createHelper(b),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),a.ui.ddmanager&&(a.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,c.cursorAt&&this._adjustOffsetFromHelper(c.cursorAt),c.containment&&this._setContainment(),this._trigger("start",b)===!1?(this._clear(),!1):(this._cacheHelperProportions(),a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this._mouseDrag(b,!0),a.ui.ddmanager&&a.ui.ddmanager.dragStart(this,b),!0)},_mouseDrag:function(b,c){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute");if(!c){var d=this._uiHash();if(this._trigger("drag",b,d)===!1)return this._mouseUp({}),!1;this.position=d.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";return a.ui.ddmanager&&a.ui.ddmanager.drag(this,b),!1},_mouseStop:function(b){var c=!1;a.ui.ddmanager&&!this.options.dropBehaviour&&(c=a.ui.ddmanager.drop(this,b)),this.dropped&&(c=this.dropped,this.dropped=!1);var d=this.element[0],e=!1;while(d&&(d=d.parentNode))d==document&&(e=!0);if(!e&&this.options.helper==="original")return!1;if(this.options.revert=="invalid"&&!c||this.options.revert=="valid"&&c||this.options.revert===!0||a.isFunction(this.options.revert)&&this.options.revert.call(this.element,c)){var f=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){f._trigger("stop",b)!==!1&&f._clear()})}else this._trigger("stop",b)!==!1&&this._clear();return!1},_mouseUp:function(b){return a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),a.ui.ddmanager&&a.ui.ddmanager.dragStop(this,b),a.ui.mouse.prototype._mouseUp.call(this,b)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(b){var c=!this.options.handle||!a(this.options.handle,this.element).length?!0:!1;return a(this.options.handle,this.element).find("*").andSelf().each(function(){this==b.target&&(c=!0)}),c},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b])):c.helper=="clone"?this.element.clone().removeAttr("id"):this.element;return d.parents("body").length||d.appendTo(c.appendTo=="parent"?this.element[0].parentNode:c.appendTo),d[0]!=this.element[0]&&!/(fixed|absolute)/.test(d.css("position"))&&d.css("position","absolute"),d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[b.containment=="document"?0:a(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,b.containment=="document"?0:a(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(b.containment=="document"?0:a(window).scrollLeft())+a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(b.containment=="document"?0:a(window).scrollTop())+(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)&&b.containment.constructor!=Array){var c=a(b.containment),d=c[0];if(!d)return;var e=c.offset(),f=a(d).css("overflow")!="hidden";this.containment=[(parseInt(a(d).css("borderLeftWidth"),10)||0)+(parseInt(a(d).css("paddingLeft"),10)||0),(parseInt(a(d).css("borderTopWidth"),10)||0)+(parseInt(a(d).css("paddingTop"),10)||0),(f?Math.max(d.scrollWidth,d.offsetWidth):d.offsetWidth)-(parseInt(a(d).css("borderLeftWidth"),10)||0)-(parseInt(a(d).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(f?Math.max(d.scrollHeight,d.offsetHeight):d.offsetHeight)-(parseInt(a(d).css("borderTopWidth"),10)||0)-(parseInt(a(d).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=c}else b.containment.constructor==Array&&(this.containment=b.containment)},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName),f=b.pageX,g=b.pageY;if(this.originalPosition){var h;if(this.containment){if(this.relative_container){var i=this.relative_container.offset();h=[this.containment[0]+i.left,this.containment[1]+i.top,this.containment[2]+i.left,this.containment[3]+i.top]}else h=this.containment;b.pageX-this.offset.click.lefth[2]&&(f=h[2]+this.offset.click.left),b.pageY-this.offset.click.top>h[3]&&(g=h[3]+this.offset.click.top)}if(c.grid){var j=c.grid[1]?this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1]:this.originalPageY;g=h?j-this.offset.click.toph[3]?j-this.offset.click.toph[2]?k-this.offset.click.left=0;k--){var l=d.snapElements[k].left,m=l+d.snapElements[k].width,n=d.snapElements[k].top,o=n+d.snapElements[k].height;if(!(l-f=k&&g<=l||h>=k&&h<=l||gl)&&(e>=i&&e<=j||f>=i&&f<=j||ej);default:return!1}},a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(b,c){var d=a.ui.ddmanager.droppables[b.options.scope]||[],e=c?c.type:null,f=(b.currentItem||b.element).find(":data(droppable)").andSelf();g:for(var h=0;h ').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=c.handles||(a(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var d=this.handles.split(",");this.handles={};for(var e=0;e
');h.css({zIndex:c.zIndex}),"se"==f&&h.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[f]=".ui-resizable-"+f,this.element.append(h)}}this._renderAxis=function(b){b=b||this.element;for(var c in this.handles){this.handles[c].constructor==String&&(this.handles[c]=a(this.handles[c],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var d=a(this.handles[c],this.element),e=0;e=/sw|ne|nw|se|n|s/.test(c)?d.outerHeight():d.outerWidth();var f=["padding",/ne|nw|n/.test(c)?"Top":/se|sw|s/.test(c)?"Bottom":/^e$/.test(c)?"Right":"Left"].join("");b.css(f,e),this._proportionallyResize()}if(!a(this.handles[c]).length)continue}},this._renderAxis(this.element),this._handles=a(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!b.resizing){if(this.className)var a=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=a&&a[1]?a[1]:"se"}}),c.autoHide&&(this._handles.hide(),a(this.element).addClass("ui-resizable-autohide").hover(function(){if(c.disabled)return;a(this).removeClass("ui-resizable-autohide"),b._handles.show()},function(){if(c.disabled)return;b.resizing||(a(this).addClass("ui-resizable-autohide"),b._handles.hide())})),this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(b){a(b).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){b(this.element);var c=this.element;c.after(this.originalElement.css({position:c.css("position"),width:c.outerWidth(),height:c.outerHeight(),top:c.css("top"),left:c.css("left")})).remove()}return this.originalElement.css("resize",this.originalResizeStyle),b(this.originalElement),this},_mouseCapture:function(b){var c=!1;for(var d in this.handles)a(this.handles[d])[0]==b.target&&(c=!0);return!this.options.disabled&&c},_mouseStart:function(b){var d=this.options,e=this.element.position(),f=this.element;this.resizing=!0,this.documentScroll={top:a(document).scrollTop(),left:a(document).scrollLeft()},(f.is(".ui-draggable")||/absolute/.test(f.css("position")))&&f.css({position:"absolute",top:e.top,left:e.left}),this._renderProxy();var g=c(this.helper.css("left")),h=c(this.helper.css("top"));d.containment&&(g+=a(d.containment).scrollLeft()||0,h+=a(d.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:g,top:h},this.size=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalSize=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalPosition={left:g,top:h},this.sizeDiff={width:f.outerWidth()-f.width(),height:f.outerHeight()-f.height()},this.originalMousePosition={left:b.pageX,top:b.pageY},this.aspectRatio=typeof d.aspectRatio=="number"?d.aspectRatio:this.originalSize.width/this.originalSize.height||1;var i=a(".ui-resizable-"+this.axis).css("cursor");return a("body").css("cursor",i=="auto"?this.axis+"-resize":i),f.addClass("ui-resizable-resizing"),this._propagate("start",b),!0},_mouseDrag:function(b){var c=this.helper,d=this.options,e={},f=this,g=this.originalMousePosition,h=this.axis,i=b.pageX-g.left||0,j=b.pageY-g.top||0,k=this._change[h];if(!k)return!1;var l=k.apply(this,[b,i,j]),m=a.browser.msie&&a.browser.version<7,n=this.sizeDiff;this._updateVirtualBoundaries(b.shiftKey);if(this._aspectRatio||b.shiftKey)l=this._updateRatio(l,b);return l=this._respectSize(l,b),this._propagate("resize",b),c.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",b,this.ui()),!1},_mouseStop:function(b){this.resizing=!1;var c=this.options,d=this;if(this._helper){var e=this._proportionallyResizeElements,f=e.length&&/textarea/i.test(e[0].nodeName),g=f&&a.ui.hasScroll(e[0],"left")?0:d.sizeDiff.height,h=f?0:d.sizeDiff.width,i={width:d.helper.width()-h,height:d.helper.height()-g},j=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,k=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;c.animate||this.element.css(a.extend(i,{top:k,left:j})),d.helper.height(d.size.height),d.helper.width(d.size.width),this._helper&&!c.animate&&this._proportionallyResize()}return a("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",b),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(a){var b=this.options,c,e,f,g,h;h={minWidth:d(b.minWidth)?b.minWidth:0,maxWidth:d(b.maxWidth)?b.maxWidth:Infinity,minHeight:d(b.minHeight)?b.minHeight:0,maxHeight:d(b.maxHeight)?b.maxHeight:Infinity};if(this._aspectRatio||a)c=h.minHeight*this.aspectRatio,f=h.minWidth/this.aspectRatio,e=h.maxHeight*this.aspectRatio,g=h.maxWidth/this.aspectRatio,c>h.minWidth&&(h.minWidth=c),f>h.minHeight&&(h.minHeight=f),ea.width,k=d(a.height)&&e.minHeight&&e.minHeight>a.height;j&&(a.width=e.minWidth),k&&(a.height=e.minHeight),h&&(a.width=e.maxWidth),i&&(a.height=e.maxHeight);var l=this.originalPosition.left+this.originalSize.width,m=this.position.top+this.size.height,n=/sw|nw|w/.test(g),o=/nw|ne|n/.test(g);j&&n&&(a.left=l-e.minWidth),h&&n&&(a.left=l-e.maxWidth),k&&o&&(a.top=m-e.minHeight),i&&o&&(a.top=m-e.maxHeight);var p=!a.width&&!a.height;return p&&!a.left&&a.top?a.top=null:p&&!a.top&&a.left&&(a.left=null),a},_proportionallyResize:function(){var b=this.options;if(!this._proportionallyResizeElements.length)return;var c=this.helper||this.element;for(var d=0;d');var d=a.browser.msie&&a.browser.version<7,e=d?1:0,f=d?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+f,height:this.element.outerHeight()+f,position:"absolute",left:this.elementOffset.left-e+"px",top:this.elementOffset.top-e+"px",zIndex:++c.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(a,b,c){return{width:this.originalSize.width+b}},w:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{left:f.left+b,width:e.width-b}},n:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{top:f.top+c,height:e.height-c}},s:function(a,b,c){return{height:this.originalSize.height+c}},se:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},sw:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,c,d]))},ne:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},nw:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,c,d]))}},_propagate:function(b,c){a.ui.plugin.call(this,b,[c,this.ui()]),b!="resize"&&this._trigger(b,c,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),a.extend(a.ui.resizable,{version:"1.8.24"}),a.ui.plugin.add("resizable","alsoResize",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=function(b){a(b).each(function(){var b=a(this);b.data("resizable-alsoresize",{width:parseInt(b.width(),10),height:parseInt(b.height(),10),left:parseInt(b.css("left"),10),top:parseInt(b.css("top"),10)})})};typeof e.alsoResize=="object"&&!e.alsoResize.parentNode?e.alsoResize.length?(e.alsoResize=e.alsoResize[0],f(e.alsoResize)):a.each(e.alsoResize,function(a){f(a)}):f(e.alsoResize)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.originalSize,g=d.originalPosition,h={height:d.size.height-f.height||0,width:d.size.width-f.width||0,top:d.position.top-g.top||0,left:d.position.left-g.left||0},i=function(b,d){a(b).each(function(){var b=a(this),e=a(this).data("resizable-alsoresize"),f={},g=d&&d.length?d:b.parents(c.originalElement[0]).length?["width","height"]:["width","height","top","left"];a.each(g,function(a,b){var c=(e[b]||0)+(h[b]||0);c&&c>=0&&(f[b]=c||null)}),b.css(f)})};typeof e.alsoResize=="object"&&!e.alsoResize.nodeType?a.each(e.alsoResize,function(a,b){i(a,b)}):i(e.alsoResize)},stop:function(b,c){a(this).removeData("resizable-alsoresize")}}),a.ui.plugin.add("resizable","animate",{stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d._proportionallyResizeElements,g=f.length&&/textarea/i.test(f[0].nodeName),h=g&&a.ui.hasScroll(f[0],"left")?0:d.sizeDiff.height,i=g?0:d.sizeDiff.width,j={width:d.size.width-i,height:d.size.height-h},k=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,l=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;d.element.animate(a.extend(j,l&&k?{top:l,left:k}:{}),{duration:e.animateDuration,easing:e.animateEasing,step:function(){var c={width:parseInt(d.element.css("width"),10),height:parseInt(d.element.css("height"),10),top:parseInt(d.element.css("top"),10),left:parseInt(d.element.css("left"),10)};f&&f.length&&a(f[0]).css({width:c.width,height:c.height}),d._updateCache(c),d._propagate("resize",b)}})}}),a.ui.plugin.add("resizable","containment",{start:function(b,d){var e=a(this).data("resizable"),f=e.options,g=e.element,h=f.containment,i=h instanceof a?h.get(0):/parent/.test(h)?g.parent().get(0):h;if(!i)return;e.containerElement=a(i);if(/document/.test(h)||h==document)e.containerOffset={left:0,top:0},e.containerPosition={left:0,top:0},e.parentData={element:a(document),left:0,top:0,width:a(document).width(),height:a(document).height()||document.body.parentNode.scrollHeight};else{var j=a(i),k=[];a(["Top","Right","Left","Bottom"]).each(function(a,b){k[a]=c(j.css("padding"+b))}),e.containerOffset=j.offset(),e.containerPosition=j.position(),e.containerSize={height:j.innerHeight()-k[3],width:j.innerWidth()-k[1]};var l=e.containerOffset,m=e.containerSize.height,n=e.containerSize.width,o=a.ui.hasScroll(i,"left")?i.scrollWidth:n,p=a.ui.hasScroll(i)?i.scrollHeight:m;e.parentData={element:i,left:l.left,top:l.top,width:o,height:p}}},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.containerSize,g=d.containerOffset,h=d.size,i=d.position,j=d._aspectRatio||b.shiftKey,k={top:0,left:0},l=d.containerElement;l[0]!=document&&/static/.test(l.css("position"))&&(k=g),i.left<(d._helper?g.left:0)&&(d.size.width=d.size.width+(d._helper?d.position.left-g.left:d.position.left-k.left),j&&(d.size.height=d.size.width/d.aspectRatio),d.position.left=e.helper?g.left:0),i.top<(d._helper?g.top:0)&&(d.size.height=d.size.height+(d._helper?d.position.top-g.top:d.position.top),j&&(d.size.width=d.size.height*d.aspectRatio),d.position.top=d._helper?g.top:0),d.offset.left=d.parentData.left+d.position.left,d.offset.top=d.parentData.top+d.position.top;var m=Math.abs((d._helper?d.offset.left-k.left:d.offset.left-k.left)+d.sizeDiff.width),n=Math.abs((d._helper?d.offset.top-k.top:d.offset.top-g.top)+d.sizeDiff.height),o=d.containerElement.get(0)==d.element.parent().get(0),p=/relative|absolute/.test(d.containerElement.css("position"));o&&p&&(m-=d.parentData.left),m+d.size.width>=d.parentData.width&&(d.size.width=d.parentData.width-m,j&&(d.size.height=d.size.width/d.aspectRatio)),n+d.size.height>=d.parentData.height&&(d.size.height=d.parentData.height-n,j&&(d.size.width=d.size.height*d.aspectRatio))},stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.position,g=d.containerOffset,h=d.containerPosition,i=d.containerElement,j=a(d.helper),k=j.offset(),l=j.outerWidth()-d.sizeDiff.width,m=j.outerHeight()-d.sizeDiff.height;d._helper&&!e.animate&&/relative/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m}),d._helper&&!e.animate&&/static/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m})}}),a.ui.plugin.add("resizable","ghost",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size;d.ghost=d.originalElement.clone(),d.ghost.css({opacity:.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof e.ghost=="string"?e.ghost:""),d.ghost.appendTo(d.helper)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})},stop:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.helper&&d.helper.get(0).removeChild(d.ghost.get(0))}}),a.ui.plugin.add("resizable","grid",{resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size,g=d.originalSize,h=d.originalPosition,i=d.axis,j=e._aspectRatio||b.shiftKey;e.grid=typeof e.grid=="number"?[e.grid,e.grid]:e.grid;var k=Math.round((f.width-g.width)/(e.grid[0]||1))*(e.grid[0]||1),l=Math.round((f.height-g.height)/(e.grid[1]||1))*(e.grid[1]||1);/^(se|s|e)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l):/^(ne)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l):/^(sw)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.left=h.left-k):(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l,d.position.left=h.left-k)}});var c=function(a){return parseInt(a,10)||0},d=function(a){return!isNaN(parseInt(a,10))}})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.selectable.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.widget("ui.selectable",a.ui.mouse,{options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var b=this;this.element.addClass("ui-selectable"),this.dragged=!1;var c;this.refresh=function(){c=a(b.options.filter,b.element[0]),c.addClass("ui-selectee"),c.each(function(){var b=a(this),c=b.offset();a.data(this,"selectable-item",{element:this,$element:b,left:c.left,top:c.top,right:c.left+b.outerWidth(),bottom:c.top+b.outerHeight(),startselected:!1,selected:b.hasClass("ui-selected"),selecting:b.hasClass("ui-selecting"),unselecting:b.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=c.addClass("ui-selectee"),this._mouseInit(),this.helper=a("
")},destroy:function(){return this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable"),this._mouseDestroy(),this},_mouseStart:function(b){var c=this;this.opos=[b.pageX,b.pageY];if(this.options.disabled)return;var d=this.options;this.selectees=a(d.filter,this.element[0]),this._trigger("start",b),a(d.appendTo).append(this.helper),this.helper.css({left:b.clientX,top:b.clientY,width:0,height:0}),d.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var d=a.data(this,"selectable-item");d.startselected=!0,!b.metaKey&&!b.ctrlKey&&(d.$element.removeClass("ui-selected"),d.selected=!1,d.$element.addClass("ui-unselecting"),d.unselecting=!0,c._trigger("unselecting",b,{unselecting:d.element}))}),a(b.target).parents().andSelf().each(function(){var d=a.data(this,"selectable-item");if(d){var e=!b.metaKey&&!b.ctrlKey||!d.$element.hasClass("ui-selected");return d.$element.removeClass(e?"ui-unselecting":"ui-selected").addClass(e?"ui-selecting":"ui-unselecting"),d.unselecting=!e,d.selecting=e,d.selected=e,e?c._trigger("selecting",b,{selecting:d.element}):c._trigger("unselecting",b,{unselecting:d.element}),!1}})},_mouseDrag:function(b){var c=this;this.dragged=!0;if(this.options.disabled)return;var d=this.options,e=this.opos[0],f=this.opos[1],g=b.pageX,h=b.pageY;if(e>g){var i=g;g=e,e=i}if(f>h){var i=h;h=f,f=i}return this.helper.css({left:e,top:f,width:g-e,height:h-f}),this.selectees.each(function(){var i=a.data(this,"selectable-item");if(!i||i.element==c.element[0])return;var j=!1;d.tolerance=="touch"?j=!(i.left>g||i.righth||i.bottome&&i.rightf&&i.bottom *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var a=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},destroy:function(){a.Widget.prototype.destroy.call(this),this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--)this.items[b].item.removeData(this.widgetName+"-item");return this},_setOption:function(b,c){b==="disabled"?(this.options[b]=c,this.widget()[c?"addClass":"removeClass"]("ui-sortable-disabled")):a.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(b,c){var d=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(b);var e=null,f=this,g=a(b.target).parents().each(function(){if(a.data(this,d.widgetName+"-item")==f)return e=a(this),!1});a.data(b.target,d.widgetName+"-item")==f&&(e=a(b.target));if(!e)return!1;if(this.options.handle&&!c){var h=!1;a(this.options.handle,e).find("*").andSelf().each(function(){this==b.target&&(h=!0)});if(!h)return!1}return this.currentItem=e,this._removeCurrentsFromItems(),!0},_mouseStart:function(b,c,d){var e=this.options,f=this;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(b),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,e.cursorAt&&this._adjustOffsetFromHelper(e.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),e.containment&&this._setContainment(),e.cursor&&(a("body").css("cursor")&&(this._storedCursor=a("body").css("cursor")),a("body").css("cursor",e.cursor)),e.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",e.opacity)),e.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",e.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",b,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!d)for(var g=this.containers.length-1;g>=0;g--)this.containers[g]._trigger("activate",b,f._uiHash(this));return a.ui.ddmanager&&(a.ui.ddmanager.current=this),a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(b),!0},_mouseDrag:function(b){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var c=this.options,d=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-b.pageY=0;e--){var f=this.items[e],g=f.item[0],h=this._intersectsWithPointer(f);if(!h)continue;if(f.instance!==this.currentContainer)continue;if(g!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=g&&!a.ui.contains(this.placeholder[0],g)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],g):!0)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(f))this._rearrange(b,f);else break;this._trigger("change",b,this._uiHash());break}}return this._contactContainers(b),a.ui.ddmanager&&a.ui.ddmanager.drag(this,b),this._trigger("sort",b,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(b,c){if(!b)return;a.ui.ddmanager&&!this.options.dropBehaviour&&a.ui.ddmanager.drop(this,b);if(this.options.revert){var d=this,e=d.placeholder.offset();d.reverting=!0,a(this.helper).animate({left:e.left-this.offset.parent.left-d.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-d.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){d._clear(b)})}else this._clear(b,c);return!1},cancel:function(){var b=this;if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("deactivate",null,b._uiHash(this)),this.containers[c].containerCache.over&&(this.containers[c]._trigger("out",null,b._uiHash(this)),this.containers[c].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),a.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?a(this.domPosition.prev).after(this.currentItem):a(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];return b=b||{},a(c).each(function(){var c=(a(b.item||this).attr(b.attribute||"id")||"").match(b.expression||/(.+)[-=_](.+)/);c&&d.push((b.key||c[1]+"[]")+"="+(b.key&&b.expression?c[1]:c[2]))}),!d.length&&b.key&&d.push(b.key+"="),d.join("&")},toArray:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];return b=b||{},c.each(function(){d.push(a(b.item||this).attr(b.attribute||"id")||"")}),d},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,d=this.positionAbs.top,e=d+this.helperProportions.height,f=a.left,g=f+a.width,h=a.top,i=h+a.height,j=this.offset.click.top,k=this.offset.click.left,l=d+j>h&&d+jf&&b+ka[this.floating?"width":"height"]?l:f0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){return this._refreshItems(a),this.refreshPositions(),this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(b){var c=this,d=[],e=[],f=this._connectWith();if(f&&b)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&e.push([a.isFunction(j.options.items)?j.options.items.call(j.element):a(j.options.items,j.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),j])}}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var g=e.length-1;g>=0;g--)e[g][0].each(function(){d.push(this)});return a(d)},_removeCurrentsFromItems:function(){var a=this.currentItem.find(":data("+this.widgetName+"-item)");for(var b=0;b=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&(e.push([a.isFunction(j.options.items)?j.options.items.call(j.element[0],b,{item:this.currentItem}):a(j.options.items,j.element),j]),this.containers.push(j))}}for(var g=e.length-1;g>=0;g--){var k=e[g][1],l=e[g][0];for(var i=0,m=l.length;i=0;c--){var d=this.items[c];if(d.instance!=this.currentContainer&&this.currentContainer&&d.item[0]!=this.currentItem[0])continue;var e=this.options.toleranceElement?a(this.options.toleranceElement,d.item):d.item;b||(d.width=e.outerWidth(),d.height=e.outerHeight());var f=e.offset();d.left=f.left,d.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var c=this.containers.length-1;c>=0;c--){var f=this.containers[c].element.offset();this.containers[c].containerCache.left=f.left,this.containers[c].containerCache.top=f.top,this.containers[c].containerCache.width=this.containers[c].element.outerWidth(),this.containers[c].containerCache.height=this.containers[c].element.outerHeight()}return this},_createPlaceholder:function(b){var c=b||this,d=c.options;if(!d.placeholder||d.placeholder.constructor==String){var e=d.placeholder;d.placeholder={element:function(){var b=a(document.createElement(c.currentItem[0].nodeName)).addClass(e||c.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return e||(b.style.visibility="hidden"),b},update:function(a,b){if(e&&!d.forcePlaceholderSize)return;b.height()||b.height(c.currentItem.innerHeight()-parseInt(c.currentItem.css("paddingTop")||0,10)-parseInt(c.currentItem.css("paddingBottom")||0,10)),b.width()||b.width(c.currentItem.innerWidth()-parseInt(c.currentItem.css("paddingLeft")||0,10)-parseInt(c.currentItem.css("paddingRight")||0,10))}}}c.placeholder=a(d.placeholder.element.call(c.element,c.currentItem)),c.currentItem.after(c.placeholder),d.placeholder.update(c,c.placeholder)},_contactContainers:function(b){var c=null,d=null;for(var e=this.containers.length-1;e>=0;e--){if(a.ui.contains(this.currentItem[0],this.containers[e].element[0]))continue;if(this._intersectsWith(this.containers[e].containerCache)){if(c&&a.ui.contains(this.containers[e].element[0],c.element[0]))continue;c=this.containers[e],d=e}else this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",b,this._uiHash(this)),this.containers[e].containerCache.over=0)}if(!c)return;if(this.containers.length===1)this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1;else if(this.currentContainer!=this.containers[d]){var f=1e4,g=null,h=this.positionAbs[this.containers[d].floating?"left":"top"];for(var i=this.items.length-1;i>=0;i--){if(!a.ui.contains(this.containers[d].element[0],this.items[i].item[0]))continue;var j=this.containers[d].floating?this.items[i].item.offset().left:this.items[i].item.offset().top;Math.abs(j-h)0?"down":"up")}if(!g&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[d],g?this._rearrange(b,g,null,!0):this._rearrange(b,null,this.containers[d].element,!0),this._trigger("change",b,this._uiHash()),this.containers[d]._trigger("change",b,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1}},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b,this.currentItem])):c.helper=="clone"?this.currentItem.clone():this.currentItem;return d.parents("body").length||a(c.appendTo!="parent"?c.appendTo:this.currentItem[0].parentNode)[0].appendChild(d[0]),d[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(d[0].style.width==""||c.forceHelperSize)&&d.width(this.currentItem.width()),(d[0].style.height==""||c.forceHelperSize)&&d.height(this.currentItem.height()),d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)){var c=a(b.containment)[0],d=a(b.containment).offset(),e=a(c).css("overflow")!="hidden";this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(e?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(e?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var f=b.pageX,g=b.pageY;if(this.originalPosition){this.containment&&(b.pageX-this.offset.click.leftthis.containment[2]&&(f=this.containment[2]+this.offset.click.left),b.pageY-this.offset.click.top>this.containment[3]&&(g=this.containment[3]+this.offset.click.top));if(c.grid){var h=this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1];g=this.containment?h-this.offset.click.topthis.containment[3]?h-this.offset.click.topthis.containment[2]?i-this.offset.click.left=0;f--)c||d.push(function(a){return function(b){a._trigger("deactivate",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over&&(d.push(function(a){return function(b){a._trigger("out",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over=0);this._storedCursor&&a("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!c){this._trigger("beforeStop",b,this._uiHash());for(var f=0;f li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:!1,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var b=this,c=b.options;b.running=0,b.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"),b.headers=b.element.find(c.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){if(c.disabled)return;a(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){if(c.disabled)return;a(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){if(c.disabled)return;a(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){if(c.disabled)return;a(this).removeClass("ui-state-focus")}),b.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");if(c.navigation){var d=b.element.find("a").filter(c.navigationFilter).eq(0);if(d.length){var e=d.closest(".ui-accordion-header");e.length?b.active=e:b.active=d.closest(".ui-accordion-content").prev()}}b.active=b._findActive(b.active||c.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top"),b.active.next().addClass("ui-accordion-content-active"),b._createIcons(),b.resize(),b.element.attr("role","tablist"),b.headers.attr("role","tab").bind("keydown.accordion",function(a){return b._keydown(a)}).next().attr("role","tabpanel"),b.headers.not(b.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide(),b.active.length?b.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):b.headers.eq(0).attr("tabIndex",0),a.browser.safari||b.headers.find("a").attr("tabIndex",-1),c.event&&b.headers.bind(c.event.split(" ").join(".accordion ")+".accordion",function(a){b._clickHandler.call(b,a,this),a.preventDefault()})},_createIcons:function(){var b=this.options;b.icons&&(a(" ").addClass("ui-icon "+b.icons.header).prependTo(this.headers),this.active.children(".ui-icon").toggleClass(b.icons.header).toggleClass(b.icons.headerSelected),this.element.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.children(".ui-icon").remove(),this.element.removeClass("ui-accordion-icons")},destroy:function(){var b=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex"),this.headers.find("a").removeAttr("tabIndex"),this._destroyIcons();var c=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");return(b.autoHeight||b.fillHeight)&&c.css("height",""),a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments),b=="active"&&this.activate(c),b=="icons"&&(this._destroyIcons(),c&&this._createIcons()),b=="disabled"&&this.headers.add(this.headers.next())[c?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(b){if(this.options.disabled||b.altKey||b.ctrlKey)return;var c=a.ui.keyCode,d=this.headers.length,e=this.headers.index(b.target),f=!1;switch(b.keyCode){case c.RIGHT:case c.DOWN:f=this.headers[(e+1)%d];break;case c.LEFT:case c.UP:f=this.headers[(e-1+d)%d];break;case c.SPACE:case c.ENTER:this._clickHandler({target:b.target},b.target),b.preventDefault()}return f?(a(b.target).attr("tabIndex",-1),a(f).attr("tabIndex",0),f.focus(),!1):!0},resize:function(){var b=this.options,c;if(b.fillSpace){if(a.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}c=this.element.parent().height(),a.browser.msie&&this.element.parent().css("overflow",d),this.headers.each(function(){c-=a(this).outerHeight(!0)}),this.headers.next().each(function(){a(this).height(Math.max(0,c-a(this).innerHeight()+a(this).height()))}).css("overflow","auto")}else b.autoHeight&&(c=0,this.headers.next().each(function(){c=Math.max(c,a(this).height("").height())}).height(c));return this},activate:function(a){this.options.active=a;var b=this._findActive(a)[0];return this._clickHandler({target:b},b),this},_findActive:function(b){return b?typeof b=="number"?this.headers.filter(":eq("+b+")"):this.headers.not(this.headers.not(b)):b===!1?a([]):this.headers.filter(":eq(0)")},_clickHandler:function(b,c){var d=this.options;if(d.disabled)return;if(!b.target){if(!d.collapsible)return;this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header),this.active.next().addClass("ui-accordion-content-active");var e=this.active.next(),f={options:d,newHeader:a([]),oldHeader:d.active,newContent:a([]),oldContent:e},g=this.active=a([]);this._toggle(g,e,f);return}var h=a(b.currentTarget||c),i=h[0]===this.active[0];d.active=d.collapsible&&i?!1:this.headers.index(h);if(this.running||!d.collapsible&&i)return;var j=this.active,g=h.next(),e=this.active.next(),f={options:d,newHeader:i&&d.collapsible?a([]):h,oldHeader:this.active,newContent:i&&d.collapsible?a([]):g,oldContent:e},k=this.headers.index(this.active[0])>this.headers.index(h[0]);this.active=i?a([]):h,this._toggle(g,e,f,i,k),j.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header),i||(h.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected),h.next().addClass("ui-accordion-content-active"));return},_toggle:function(b,c,d,e,f){var g=this,h=g.options;g.toShow=b,g.toHide=c,g.data=d;var i=function(){if(!g)return;return g._completed.apply(g,arguments)};g._trigger("changestart",null,g.data),g.running=c.size()===0?b.size():c.size();if(h.animated){var j={};h.collapsible&&e?j={toShow:a([]),toHide:c,complete:i,down:f,autoHeight:h.autoHeight||h.fillSpace}:j={toShow:b,toHide:c,complete:i,down:f,autoHeight:h.autoHeight||h.fillSpace},h.proxied||(h.proxied=h.animated),h.proxiedDuration||(h.proxiedDuration=h.duration),h.animated=a.isFunction(h.proxied)?h.proxied(j):h.proxied,h.duration=a.isFunction(h.proxiedDuration)?h.proxiedDuration(j):h.proxiedDuration;var k=a.ui.accordion.animations,l=h.duration,m=h.animated;m&&!k[m]&&!a.easing[m]&&(m="slide"),k[m]||(k[m]=function(a){this.slide(a,{easing:m,duration:l||700})}),k[m](j)}else h.collapsible&&e?b.toggle():(c.hide(),b.show()),i(!0);c.prev().attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).blur(),b.prev().attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;if(this.running)return;this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""}),this.toHide.removeClass("ui-accordion-content-active"),this.toHide.length&&(this.toHide.parent()[0].className=this.toHide.parent()[0].className),this._trigger("change",null,this.data)}}),a.extend(a.ui.accordion,{version:"1.8.24",animations:{slide:function(b,c){b=a.extend({easing:"swing",duration:300},b,c);if(!b.toHide.size()){b.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},b);return}if(!b.toShow.size()){b.toHide.animate({height:"hide",paddingTop:"hide",paddingBottom:"hide"},b);return}var d=b.toShow.css("overflow"),e=0,f={},g={},h=["height","paddingTop","paddingBottom"],i,j=b.toShow;i=j[0].style.width,j.width(j.parent().width()-parseFloat(j.css("paddingLeft"))-parseFloat(j.css("paddingRight"))-(parseFloat(j.css("borderLeftWidth"))||0)-(parseFloat(j.css("borderRightWidth"))||0)),a.each(h,function(c,d){g[d]="hide";var e=(""+a.css(b.toShow[0],d)).match(/^([\d+-.]+)(.*)$/);f[d]={value:e[1],unit:e[2]||"px"}}),b.toShow.css({height:0,overflow:"hidden"}).show(),b.toHide.filter(":hidden").each(b.complete).end().filter(":visible").animate(g,{step:function(a,c){c.prop=="height"&&(e=c.end-c.start===0?0:(c.now-c.start)/(c.end-c.start)),b.toShow[0].style[c.prop]=e*f[c.prop].value+f[c.prop].unit},duration:b.duration,easing:b.easing,complete:function(){b.autoHeight||b.toShow.css("height",""),b.toShow.css({width:i,overflow:d}),b.complete()}})},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1e3:200})}}})})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.autocomplete.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){var c=0;a.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var b=this,c=this.element[0].ownerDocument,d;this.isMultiLine=this.element.is("textarea"),this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(b.options.disabled||b.element.propAttr("readOnly"))return;d=!1;var e=a.ui.keyCode;switch(c.keyCode){case e.PAGE_UP:b._move("previousPage",c);break;case e.PAGE_DOWN:b._move("nextPage",c);break;case e.UP:b._keyEvent("previous",c);break;case e.DOWN:b._keyEvent("next",c);break;case e.ENTER:case e.NUMPAD_ENTER:b.menu.active&&(d=!0,c.preventDefault());case e.TAB:if(!b.menu.active)return;b.menu.select(c);break;case e.ESCAPE:b.element.val(b.term),b.close(c);break;default:clearTimeout(b.searching),b.searching=setTimeout(function(){b.term!=b.element.val()&&(b.selectedItem=null,b.search(null,c))},b.options.delay)}}).bind("keypress.autocomplete",function(a){d&&(d=!1,a.preventDefault())}).bind("focus.autocomplete",function(){if(b.options.disabled)return;b.selectedItem=null,b.previous=b.element.val()}).bind("blur.autocomplete",function(a){if(b.options.disabled)return;clearTimeout(b.searching),b.closing=setTimeout(function(){b.close(a),b._change(a)},150)}),this._initSource(),this.menu=a("").addClass("ui-autocomplete").appendTo(a(this.options.appendTo||"body",c)[0]).mousedown(function(c){var d=b.menu.element[0];a(c.target).closest(".ui-menu-item").length||setTimeout(function(){a(document).one("mousedown",function(c){c.target!==b.element[0]&&c.target!==d&&!a.ui.contains(d,c.target)&&b.close()})},1),setTimeout(function(){clearTimeout(b.closing)},13)}).menu({focus:function(a,c){var d=c.item.data("item.autocomplete");!1!==b._trigger("focus",a,{item:d})&&/^key/.test(a.originalEvent.type)&&b.element.val(d.value)},selected:function(a,d){var e=d.item.data("item.autocomplete"),f=b.previous;b.element[0]!==c.activeElement&&(b.element.focus(),b.previous=f,setTimeout(function(){b.previous=f,b.selectedItem=e},1)),!1!==b._trigger("select",a,{item:e})&&b.element.val(e.value),b.term=b.element.val(),b.close(a),b.selectedItem=e},blur:function(a,c){b.menu.element.is(":visible")&&b.element.val()!==b.term&&b.element.val(b.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu"),a.fn.bgiframe&&this.menu.element.bgiframe(),b.beforeunloadHandler=function(){b.element.removeAttr("autocomplete")},a(window).bind("beforeunload",b.beforeunloadHandler)},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup"),this.menu.element.remove(),a(window).unbind("beforeunload",this.beforeunloadHandler),a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments),b==="source"&&this._initSource(),b==="appendTo"&&this.menu.element.appendTo(a(c||"body",this.element[0].ownerDocument)[0]),b==="disabled"&&c&&this.xhr&&this.xhr.abort()},_initSource:function(){var b=this,c,d;a.isArray(this.options.source)?(c=this.options.source,this.source=function(b,d){d(a.ui.autocomplete.filter(c,b.term))}):typeof this.options.source=="string"?(d=this.options.source,this.source=function(c,e){b.xhr&&b.xhr.abort(),b.xhr=a.ajax({url:d,data:c,dataType:"json",success:function(a,b){e(a)},error:function(){e([])}})}):this.source=this.options.source},search:function(a,b){a=a!=null?a:this.element.val(),this.term=this.element.val();if(a.length").data("item.autocomplete",c).append(a(" ").text(c.label)).appendTo(b)},_move:function(a,b){if(!this.menu.element.is(":visible")){this.search(null,b);return}if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term),this.menu.deactivate();return}this.menu[a](b)},widget:function(){return this.menu.element},_keyEvent:function(a,b){if(!this.isMultiLine||this.menu.element.is(":visible"))this._move(a,b),b.preventDefault()}}),a.extend(a.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")},filter:function(b,c){var d=new RegExp(a.ui.autocomplete.escapeRegex(c),"i");return a.grep(b,function(a){return d.test(a.label||a.value||a)})}})})(jQuery),function(a){a.widget("ui.menu",{_create:function(){var b=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(c){if(!a(c.target).closest(".ui-menu-item a").length)return;c.preventDefault(),b.select(c)}),this.refresh()},refresh:function(){var b=this,c=this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem");c.children("a").addClass("ui-corner-all").attr("tabindex",-1).mouseenter(function(c){b.activate(c,a(this).parent())}).mouseleave(function(){b.deactivate()})},activate:function(a,b){this.deactivate();if(this.hasScroll()){var c=b.offset().top-this.element.offset().top,d=this.element.scrollTop(),e=this.element.height();c<0?this.element.scrollTop(d+c):c>=e&&this.element.scrollTop(d+c-e+b.height())}this.active=b.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end(),this._trigger("focus",a,{item:b})},deactivate:function(){if(!this.active)return;this.active.children("a").removeClass("ui-state-hover").removeAttr("id"),this._trigger("blur"),this.active=null},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(a,b,c){if(!this.active){this.activate(c,this.element.children(b));return}var d=this.active[a+"All"](".ui-menu-item").eq(0);d.length?this.activate(c,d):this.activate(c,this.element.children(b))},nextPage:function(b){if(this.hasScroll()){if(!this.active||this.last()){this.activate(b,this.element.children(".ui-menu-item:first"));return}var c=this.active.offset().top,d=this.element.height(),e=this.element.children(".ui-menu-item").filter(function(){var b=a(this).offset().top-c-d+a(this).height();return b<10&&b>-10});e.length||(e=this.element.children(".ui-menu-item:last")),this.activate(b,e)}else this.activate(b,this.element.children(".ui-menu-item").filter(!this.active||this.last()?":first":":last"))},previousPage:function(b){if(this.hasScroll()){if(!this.active||this.first()){this.activate(b,this.element.children(".ui-menu-item:last"));return}var c=this.active.offset().top,d=this.element.height(),e=this.element.children(".ui-menu-item").filter(function(){var b=a(this).offset().top-c+d-a(this).height();return b<10&&b>-10});e.length||(e=this.element.children(".ui-menu-item:first")),this.activate(b,e)}else this.activate(b,this.element.children(".ui-menu-item").filter(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()",this.element[0].ownerDocument).addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,e=d.primary&&d.secondary,f=[];d.primary||d.secondary?(this.options.text&&f.push("ui-button-text-icon"+(e?"s":d.primary?"-primary":"-secondary")),d.primary&&b.prepend(" "),d.secondary&&b.append(" "),this.options.text||(f.push(e?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||b.attr("title",c))):f.push("ui-button-text-only"),b.addClass(f.join(" "))}}),a.widget("ui.buttonset",{options:{items:":button, :submit, :reset, :checkbox, :radio, a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c),a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){var b=this.element.css("direction")==="rtl";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(b?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(b?"ui-corner-left":"ui-corner-right").end().end()},destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy"),a.Widget.prototype.destroy.call(this)}})})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.dialog.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){var c="ui-dialog ui-widget ui-widget-content ui-corner-all ",d={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},e={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};a.widget("ui.dialog",{options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",collision:"fit",using:function(b){var c=a(this).css(b).offset().top;c<0&&a(this).css("top",b.top-c)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.options.title=this.options.title||this.originalTitle;var b=this,d=b.options,e=d.title||" ",f=a.ui.dialog.getTitleId(b.element),g=(b.uiDialog=a("
")).appendTo(document.body).hide().addClass(c+d.dialogClass).css({zIndex:d.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(c){d.closeOnEscape&&!c.isDefaultPrevented()&&c.keyCode&&c.keyCode===a.ui.keyCode.ESCAPE&&(b.close(c),c.preventDefault())}).attr({role:"dialog","aria-labelledby":f}).mousedown(function(a){b.moveToTop(!1,a)}),h=b.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g),i=(b.uiDialogTitlebar=a("
")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g),j=a(' ').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){j.addClass("ui-state-hover")},function(){j.removeClass("ui-state-hover")}).focus(function(){j.addClass("ui-state-focus")}).blur(function(){j.removeClass("ui-state-focus")}).click(function(a){return b.close(a),!1}).appendTo(i),k=(b.uiDialogTitlebarCloseText=a(" ")).addClass("ui-icon ui-icon-closethick").text(d.closeText).appendTo(j),l=a(" ").addClass("ui-dialog-title").attr("id",f).html(e).prependTo(i);a.isFunction(d.beforeclose)&&!a.isFunction(d.beforeClose)&&(d.beforeClose=d.beforeclose),i.find("*").add(i).disableSelection(),d.draggable&&a.fn.draggable&&b._makeDraggable(),d.resizable&&a.fn.resizable&&b._makeResizable(),b._createButtons(d.buttons),b._isOpen=!1,a.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;return a.overlay&&a.overlay.destroy(),a.uiDialog.hide(),a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),a.uiDialog.remove(),a.originalTitle&&a.element.attr("title",a.originalTitle),a},widget:function(){return this.uiDialog},close:function(b){var c=this,d,e;if(!1===c._trigger("beforeClose",b))return;return c.overlay&&c.overlay.destroy(),c.uiDialog.unbind("keypress.ui-dialog"),c._isOpen=!1,c.options.hide?c.uiDialog.hide(c.options.hide,function(){c._trigger("close",b)}):(c.uiDialog.hide(),c._trigger("close",b)),a.ui.dialog.overlay.resize(),c.options.modal&&(d=0,a(".ui-dialog").each(function(){this!==c.uiDialog[0]&&(e=a(this).css("z-index"),isNaN(e)||(d=Math.max(d,e)))}),a.ui.dialog.maxZ=d),c},isOpen:function(){return this._isOpen},moveToTop:function(b,c){var d=this,e=d.options,f;return e.modal&&!b||!e.stack&&!e.modal?d._trigger("focus",c):(e.zIndex>a.ui.dialog.maxZ&&(a.ui.dialog.maxZ=e.zIndex),d.overlay&&(a.ui.dialog.maxZ+=1,d.overlay.$el.css("z-index",a.ui.dialog.overlay.maxZ=a.ui.dialog.maxZ)),f={scrollTop:d.element.scrollTop(),scrollLeft:d.element.scrollLeft()},a.ui.dialog.maxZ+=1,d.uiDialog.css("z-index",a.ui.dialog.maxZ),d.element.attr(f),d._trigger("focus",c),d)},open:function(){if(this._isOpen)return;var b=this,c=b.options,d=b.uiDialog;return b.overlay=c.modal?new a.ui.dialog.overlay(b):null,b._size(),b._position(c.position),d.show(c.show),b.moveToTop(!0),c.modal&&d.bind("keydown.ui-dialog",function(b){if(b.keyCode!==a.ui.keyCode.TAB)return;var c=a(":tabbable",this),d=c.filter(":first"),e=c.filter(":last");if(b.target===e[0]&&!b.shiftKey)return d.focus(1),!1;if(b.target===d[0]&&b.shiftKey)return e.focus(1),!1}),a(b.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus(),b._isOpen=!0,b._trigger("open"),b},_createButtons:function(b){var c=this,d=!1,e=a("
").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),f=a("
").addClass("ui-dialog-buttonset").appendTo(e);c.uiDialog.find(".ui-dialog-buttonpane").remove(),typeof b=="object"&&b!==null&&a.each(b,function(){return!(d=!0)}),d&&(a.each(b,function(b,d){d=a.isFunction(d)?{click:d,text:b}:d;var e=a(' ').click(function(){d.click.apply(c.element[0],arguments)}).appendTo(f);a.each(d,function(a,b){if(a==="click")return;a in e?e[a](b):e.attr(a,b)}),a.fn.button&&e.button()}),e.appendTo(c.uiDialog))},_makeDraggable:function(){function f(a){return{position:a.position,offset:a.offset}}var b=this,c=b.options,d=a(document),e;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(d,g){e=c.height==="auto"?"auto":a(this).height(),a(this).height(a(this).height()).addClass("ui-dialog-dragging"),b._trigger("dragStart",d,f(g))},drag:function(a,c){b._trigger("drag",a,f(c))},stop:function(g,h){c.position=[h.position.left-d.scrollLeft(),h.position.top-d.scrollTop()],a(this).removeClass("ui-dialog-dragging").height(e),b._trigger("dragStop",g,f(h)),a.ui.dialog.overlay.resize()}})},_makeResizable:function(c){function h(a){return{originalPosition:a.originalPosition,originalSize:a.originalSize,position:a.position,size:a.size}}c=c===b?this.options.resizable:c;var d=this,e=d.options,f=d.uiDialog.css("position"),g=typeof c=="string"?c:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:g,start:function(b,c){a(this).addClass("ui-dialog-resizing"),d._trigger("resizeStart",b,h(c))},resize:function(a,b){d._trigger("resize",a,h(b))},stop:function(b,c){a(this).removeClass("ui-dialog-resizing"),e.height=a(this).height(),e.width=a(this).width(),d._trigger("resizeStop",b,h(c)),a.ui.dialog.overlay.resize()}}).css("position",f).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(b){var c=[],d=[0,0],e;if(b){if(typeof b=="string"||typeof b=="object"&&"0"in b)c=b.split?b.split(" "):[b[0],b[1]],c.length===1&&(c[1]=c[0]),a.each(["left","top"],function(a,b){+c[a]===c[a]&&(d[a]=c[a],c[a]=b)}),b={my:c.join(" "),at:c.join(" "),offset:d.join(" ")};b=a.extend({},a.ui.dialog.prototype.options.position,b)}else b=a.ui.dialog.prototype.options.position;e=this.uiDialog.is(":visible"),e||this.uiDialog.show(),this.uiDialog.css({top:0,left:0}).position(a.extend({of:window},b)),e||this.uiDialog.hide()},_setOptions:function(b){var c=this,f={},g=!1;a.each(b,function(a,b){c._setOption(a,b),a in d&&(g=!0),a in e&&(f[a]=b)}),g&&this._size(),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",f)},_setOption:function(b,d){var e=this,f=e.uiDialog;switch(b){case"beforeclose":b="beforeClose";break;case"buttons":e._createButtons(d);break;case"closeText":e.uiDialogTitlebarCloseText.text(""+d);break;case"dialogClass":f.removeClass(e.options.dialogClass).addClass(c+d);break;case"disabled":d?f.addClass("ui-dialog-disabled"):f.removeClass("ui-dialog-disabled");break;case"draggable":var g=f.is(":data(draggable)");g&&!d&&f.draggable("destroy"),!g&&d&&e._makeDraggable();break;case"position":e._position(d);break;case"resizable":var h=f.is(":data(resizable)");h&&!d&&f.resizable("destroy"),h&&typeof d=="string"&&f.resizable("option","handles",d),!h&&d!==!1&&e._makeResizable(d);break;case"title":a(".ui-dialog-title",e.uiDialogTitlebar).html(""+(d||" "))}a.Widget.prototype._setOption.apply(e,arguments)},_size:function(){var b=this.options,c,d,e=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0}),b.minWidth>b.width&&(b.width=b.minWidth),c=this.uiDialog.css({height:"auto",width:b.width}).height(),d=Math.max(0,b.minHeight-c);if(b.height==="auto")if(a.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();var f=this.element.css("height","auto").height();e||this.uiDialog.hide(),this.element.height(Math.max(f,d))}else this.element.height(Math.max(b.height-c,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}}),a.extend(a.ui.dialog,{version:"1.8.24",uuid:0,maxZ:0,getTitleId:function(a){var b=a.attr("id");return b||(this.uuid+=1,b=this.uuid),"ui-dialog-title-"+b},overlay:function(b){this.$el=a.ui.dialog.overlay.create(b)}}),a.extend(a.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:a.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(b){this.instances.length===0&&(setTimeout(function(){a.ui.dialog.overlay.instances.length&&a(document).bind(a.ui.dialog.overlay.events,function(b){if(a(b.target).zIndex()").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});return a.fn.bgiframe&&c.bgiframe(),this.instances.push(c),c},destroy:function(b){var c=a.inArray(b,this.instances);c!=-1&&this.oldInstances.push(this.instances.splice(c,1)[0]),this.instances.length===0&&a([document,window]).unbind(".dialog-overlay"),b.remove();var d=0;a.each(this.instances,function(){d=Math.max(d,this.css("z-index"))}),this.maxZ=d},height:function(){var b,c;return a.browser.msie&&a.browser.version<7?(b=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),c=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight),b
",g=d.values&&d.values.length||1,h=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"+(d.disabled?" ui-slider-disabled ui-disabled":"")),this.range=a([]),d.range&&(d.range===!0&&(d.values||(d.values=[this._valueMin(),this._valueMin()]),d.values.length&&d.values.length!==2&&(d.values=[d.values[0],d.values[0]])),this.range=a("
").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(d.range==="min"||d.range==="max"?" ui-slider-range-"+d.range:"")));for(var i=e.length;ic&&(f=c,g=a(this),i=b)}),c.range===!0&&this.values(1)===c.min&&(i+=1,g=a(this.handles[i])),j=this._start(b,i),j===!1?!1:(this._mouseSliding=!0,h._handleIndex=i,g.addClass("ui-state-active").focus(),k=g.offset(),l=!a(b.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:b.pageX-k.left-g.width()/2,top:b.pageY-k.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(b,i,e),this._animateOff=!0,!0))},_mouseStart:function(a){return!0},_mouseDrag:function(a){var b={x:a.pageX,y:a.pageY},c=this._normValueFromMouse(b);return this._slide(a,this._handleIndex,c),!1},_mouseStop:function(a){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(a,this._handleIndex),this._change(a,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b,c,d,e,f;return this.orientation==="horizontal"?(b=this.elementSize.width,c=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(b=this.elementSize.height,c=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),d=c/b,d>1&&(d=1),d<0&&(d=0),this.orientation==="vertical"&&(d=1-d),e=this._valueMax()-this._valueMin(),f=this._valueMin()+d*e,this._trimAlignValue(f)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};return this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("start",a,c)},_slide:function(a,b,c){var d,e,f;this.options.values&&this.options.values.length?(d=this.values(b?0:1),this.options.values.length===2&&this.options.range===!0&&(b===0&&c>d||b===1&&c1){this.options.values[b]=this._trimAlignValue(c),this._refreshValue(),this._change(null,b);return}if(!arguments.length)return this._values();if(!a.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(b):this.value();d=this.options.values,e=arguments[0];for(f=0;f=this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=(a-this._valueMin())%b,d=a-c;return Math.abs(c)*2>=b&&(d+=c>0?b:-b),parseFloat(d.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var b=this.options.range,c=this.options,d=this,e=this._animateOff?!1:c.animate,f,g={},h,i,j,k;this.options.values&&this.options.values.length?this.handles.each(function(b,i){f=(d.values(b)-d._valueMin())/(d._valueMax()-d._valueMin())*100,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",a(this).stop(1,1)[e?"animate":"css"](g,c.animate),d.options.range===!0&&(d.orientation==="horizontal"?(b===0&&d.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({width:f-h+"%"},{queue:!1,duration:c.animate})):(b===0&&d.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({height:f-h+"%"},{queue:!1,duration:c.animate}))),h=f}):(i=this.value(),j=this._valueMin(),k=this._valueMax(),f=k!==j?(i-j)/(k-j)*100:0,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",this.handle.stop(1,1)[e?"animate":"css"](g,c.animate),b==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},c.animate),b==="max"&&this.orientation==="horizontal"&&this.range[e?"animate":"css"]({width:100-f+"%"},{queue:!1,duration:c.animate}),b==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},c.animate),b==="max"&&this.orientation==="vertical"&&this.range[e?"animate":"css"]({height:100-f+"%"},{queue:!1,duration:c.animate}))}}),a.extend(a.ui.slider,{version:"1.8.24"})})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.tabs.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){function e(){return++c}function f(){return++d}var c=0,d=0;a.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:!1,cookie:null,collapsible:!1,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"
",remove:null,select:null,show:null,spinner:"Loading… ",tabTemplate:"#{label} "},_create:function(){this._tabify(!0)},_setOption:function(a,b){if(a=="selected"){if(this.options.collapsible&&b==this.options.selected)return;this.select(b)}else this.options[a]=b,this._tabify()},_tabId:function(a){return a.title&&a.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+e()},_sanitizeSelector:function(a){return a.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+f());return a.cookie.apply(null,[b].concat(a.makeArray(arguments)))},_ui:function(a,b){return{tab:a,panel:b,index:this.anchors.index(a)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=a(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function m(b,c){b.css("display",""),!a.support.opacity&&c.opacity&&b[0].style.removeAttribute("filter")}var d=this,e=this.options,f=/^#.+/;this.list=this.element.find("ol,ul").eq(0),this.lis=a(" > li:has(a[href])",this.list),this.anchors=this.lis.map(function(){return a("a",this)[0]}),this.panels=a([]),this.anchors.each(function(b,c){var g=a(c).attr("href"),h=g.split("#")[0],i;h&&(h===location.toString().split("#")[0]||(i=a("base")[0])&&h===i.href)&&(g=c.hash,c.href=g);if(f.test(g))d.panels=d.panels.add(d.element.find(d._sanitizeSelector(g)));else if(g&&g!=="#"){a.data(c,"href.tabs",g),a.data(c,"load.tabs",g.replace(/#.*$/,""));var j=d._tabId(c);c.href="#"+j;var k=d.element.find("#"+j);k.length||(k=a(e.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(d.panels[b-1]||d.list),k.data("destroy.tabs",!0)),d.panels=d.panels.add(k)}else e.disabled.push(b)}),c?(this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"),this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.lis.addClass("ui-state-default ui-corner-top"),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom"),e.selected===b?(location.hash&&this.anchors.each(function(a,b){if(b.hash==location.hash)return e.selected=a,!1}),typeof e.selected!="number"&&e.cookie&&(e.selected=parseInt(d._cookie(),10)),typeof e.selected!="number"&&this.lis.filter(".ui-tabs-selected").length&&(e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))),e.selected=e.selected||(this.lis.length?0:-1)):e.selected===null&&(e.selected=-1),e.selected=e.selected>=0&&this.anchors[e.selected]||e.selected<0?e.selected:0,e.disabled=a.unique(e.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(a,b){return d.lis.index(a)}))).sort(),a.inArray(e.selected,e.disabled)!=-1&&e.disabled.splice(a.inArray(e.selected,e.disabled),1),this.panels.addClass("ui-tabs-hide"),this.lis.removeClass("ui-tabs-selected ui-state-active"),e.selected>=0&&this.anchors.length&&(d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash)).removeClass("ui-tabs-hide"),this.lis.eq(e.selected).addClass("ui-tabs-selected ui-state-active"),d.element.queue("tabs",function(){d._trigger("show",null,d._ui(d.anchors[e.selected],d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash))[0]))}),this.load(e.selected)),a(window).bind("unload",function(){d.lis.add(d.anchors).unbind(".tabs"),d.lis=d.anchors=d.panels=null})):e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")),this.element[e.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible"),e.cookie&&this._cookie(e.selected,e.cookie);for(var g=0,h;h=this.lis[g];g++)a(h)[a.inArray(g,e.disabled)!=-1&&!a(h).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");e.cache===!1&&this.anchors.removeData("cache.tabs"),this.lis.add(this.anchors).unbind(".tabs");if(e.event!=="mouseover"){var i=function(a,b){b.is(":not(.ui-state-disabled)")&&b.addClass("ui-state-"+a)},j=function(a,b){b.removeClass("ui-state-"+a)};this.lis.bind("mouseover.tabs",function(){i("hover",a(this))}),this.lis.bind("mouseout.tabs",function(){j("hover",a(this))}),this.anchors.bind("focus.tabs",function(){i("focus",a(this).closest("li"))}),this.anchors.bind("blur.tabs",function(){j("focus",a(this).closest("li"))})}var k,l;e.fx&&(a.isArray(e.fx)?(k=e.fx[0],l=e.fx[1]):k=l=e.fx);var n=l?function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.hide().removeClass("ui-tabs-hide").animate(l,l.duration||"normal",function(){m(c,l),d._trigger("show",null,d._ui(b,c[0]))})}:function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.removeClass("ui-tabs-hide"),d._trigger("show",null,d._ui(b,c[0]))},o=k?function(a,b){b.animate(k,k.duration||"normal",function(){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),m(b,k),d.element.dequeue("tabs")})}:function(a,b,c){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),d.element.dequeue("tabs")};this.anchors.bind(e.event+".tabs",function(){var b=this,c=a(b).closest("li"),f=d.panels.filter(":not(.ui-tabs-hide)"),g=d.element.find(d._sanitizeSelector(b.hash));if(c.hasClass("ui-tabs-selected")&&!e.collapsible||c.hasClass("ui-state-disabled")||c.hasClass("ui-state-processing")||d.panels.filter(":animated").length||d._trigger("select",null,d._ui(this,g[0]))===!1)return this.blur(),!1;e.selected=d.anchors.index(this),d.abort();if(e.collapsible){if(c.hasClass("ui-tabs-selected"))return e.selected=-1,e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){o(b,f)}).dequeue("tabs"),this.blur(),!1;if(!f.length)return e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this)),this.blur(),!1}e.cookie&&d._cookie(e.selected,e.cookie);if(g.length)f.length&&d.element.queue("tabs",function(){o(b,f)}),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this));else throw"jQuery UI Tabs: Mismatching fragment identifier.";a.browser.msie&&this.blur()}),this.anchors.bind("click.tabs",function(){return!1})},_getIndex:function(a){return typeof a=="string"&&(a=this.anchors.index(this.anchors.filter("[href$='"+a+"']"))),a},destroy:function(){var b=this.options;return this.abort(),this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs"),this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.anchors.each(function(){var b=a.data(this,"href.tabs");b&&(this.href=b);var c=a(this).unbind(".tabs");a.each(["href","load","cache"],function(a,b){c.removeData(b+".tabs")})}),this.lis.unbind(".tabs").add(this.panels).each(function(){a.data(this,"destroy.tabs")?a(this).remove():a(this).removeClass(["ui-state-default","ui-corner-top","ui-tabs-selected","ui-state-active","ui-state-hover","ui-state-focus","ui-state-disabled","ui-tabs-panel","ui-widget-content","ui-corner-bottom","ui-tabs-hide"].join(" "))}),b.cookie&&this._cookie(null,b.cookie),this},add:function(c,d,e){e===b&&(e=this.anchors.length);var f=this,g=this.options,h=a(g.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,d)),i=c.indexOf("#")?this._tabId(a("a",h)[0]):c.replace("#","");h.addClass("ui-state-default ui-corner-top").data("destroy.tabs",!0);var j=f.element.find("#"+i);return j.length||(j=a(g.panelTemplate).attr("id",i).data("destroy.tabs",!0)),j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"),e>=this.lis.length?(h.appendTo(this.list),j.appendTo(this.list[0].parentNode)):(h.insertBefore(this.lis[e]),j.insertBefore(this.panels[e])),g.disabled=a.map(g.disabled,function(a,b){return a>=e?++a:a}),this._tabify(),this.anchors.length==1&&(g.selected=0,h.addClass("ui-tabs-selected ui-state-active"),j.removeClass("ui-tabs-hide"),this.element.queue("tabs",function(){f._trigger("show",null,f._ui(f.anchors[0],f.panels[0]))}),this.load(0)),this._trigger("add",null,this._ui(this.anchors[e],this.panels[e])),this},remove:function(b){b=this._getIndex(b);var c=this.options,d=this.lis.eq(b).remove(),e=this.panels.eq(b).remove();return d.hasClass("ui-tabs-selected")&&this.anchors.length>1&&this.select(b+(b+1=b?--a:a}),this._tabify(),this._trigger("remove",null,this._ui(d.find("a")[0],e[0])),this},enable:function(b){b=this._getIndex(b);var c=this.options;if(a.inArray(b,c.disabled)==-1)return;return this.lis.eq(b).removeClass("ui-state-disabled"),c.disabled=a.grep(c.disabled,function(a,c){return a!=b}),this._trigger("enable",null,this._ui(this.anchors[b],this.panels[b])),this},disable:function(a){a=this._getIndex(a);var b=this,c=this.options;return a!=c.selected&&(this.lis.eq(a).addClass("ui-state-disabled"),c.disabled.push(a),c.disabled.sort(),this._trigger("disable",null,this._ui(this.anchors[a],this.panels[a]))),this},select:function(a){a=this._getIndex(a);if(a==-1)if(this.options.collapsible&&this.options.selected!=-1)a=this.options.selected;else return this;return this.anchors.eq(a).trigger(this.options.event+".tabs"),this},load:function(b){b=this._getIndex(b);var c=this,d=this.options,e=this.anchors.eq(b)[0],f=a.data(e,"load.tabs");this.abort();if(!f||this.element.queue("tabs").length!==0&&a.data(e,"cache.tabs")){this.element.dequeue("tabs");return}this.lis.eq(b).addClass("ui-state-processing");if(d.spinner){var g=a("span",e);g.data("label.tabs",g.html()).html(d.spinner)}return this.xhr=a.ajax(a.extend({},d.ajaxOptions,{url:f,success:function(f,g){c.element.find(c._sanitizeSelector(e.hash)).html(f),c._cleanup(),d.cache&&a.data(e,"cache.tabs",!0),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.success(f,g)}catch(h){}},error:function(a,f,g){c._cleanup(),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.error(a,f,b,e)}catch(g){}}})),c.element.dequeue("tabs"),this},abort:function(){return this.element.queue([]),this.panels.stop(!1,!0),this.element.queue("tabs",this.element.queue("tabs").splice(-2,2)),this.xhr&&(this.xhr.abort(),delete this.xhr),this._cleanup(),this},url:function(a,b){return this.anchors.eq(a).removeData("cache.tabs").data("load.tabs",b),this},length:function(){return this.anchors.length}}),a.extend(a.ui.tabs,{version:"1.8.24"}),a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(a,b){var c=this,d=this.options,e=c._rotate||(c._rotate=function(b){clearTimeout(c.rotation),c.rotation=setTimeout(function(){var a=d.selected;c.select(++a'))}function bindHover(a){var b="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return a.bind("mouseout",function(a){var c=$(a.target).closest(b);if(!c.length)return;c.removeClass("ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover")}).bind("mouseover",function(c){var d=$(c.target).closest(b);if($.datepicker._isDisabledDatepicker(instActive.inline?a.parent()[0]:instActive.input[0])||!d.length)return;d.parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),d.addClass("ui-state-hover"),d.hasClass("ui-datepicker-prev")&&d.addClass("ui-datepicker-prev-hover"),d.hasClass("ui-datepicker-next")&&d.addClass("ui-datepicker-next-hover")})}function extendRemove(a,b){$.extend(a,b);for(var c in b)if(b[c]==null||b[c]==undefined)a[c]=b[c];return a}function isArray(a){return a&&($.browser.safari&&typeof a=="object"&&a.length||a.constructor&&a.constructor.toString().match(/\Array\(\)/))}$.extend($.ui,{datepicker:{version:"1.8.24"}});var PROP_NAME="datepicker",dpuuid=(new Date).getTime(),instActive;$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){return extendRemove(this._defaults,a||{}),this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase(),inline=nodeName=="div"||nodeName=="span";target.id||(this.uuid+=1,target.id="dp"+this.uuid);var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{}),nodeName=="input"?this._connectDatepicker(target,inst):inline&&this._inlineDatepicker(target,inst)},_newInst:function(a,b){var c=a[0].id.replace(/([^A-Za-z0-9_-])/g,"\\\\$1");return{id:c,input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:b?bindHover($('
')):this.dpDiv}},_connectDatepicker:function(a,b){var c=$(a);b.append=$([]),b.trigger=$([]);if(c.hasClass(this.markerClassName))return;this._attachments(c,b),c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(a,c,d){b.settings[c]=d}).bind("getData.datepicker",function(a,c){return this._get(b,c)}),this._autoSize(b),$.data(a,PROP_NAME,b),b.settings.disabled&&this._disableDatepicker(a)},_attachments:function(a,b){var c=this._get(b,"appendText"),d=this._get(b,"isRTL");b.append&&b.append.remove(),c&&(b.append=$(''+c+" "),a[d?"before":"after"](b.append)),a.unbind("focus",this._showDatepicker),b.trigger&&b.trigger.remove();var e=this._get(b,"showOn");(e=="focus"||e=="both")&&a.focus(this._showDatepicker);if(e=="button"||e=="both"){var f=this._get(b,"buttonText"),g=this._get(b,"buttonImage");b.trigger=$(this._get(b,"buttonImageOnly")?$(" ").addClass(this._triggerClass).attr({src:g,alt:f,title:f}):$(' ').addClass(this._triggerClass).html(g==""?f:$(" ").attr({src:g,alt:f,title:f}))),a[d?"before":"after"](b.trigger),b.trigger.click(function(){return $.datepicker._datepickerShowing&&$.datepicker._lastInput==a[0]?$.datepicker._hideDatepicker():$.datepicker._datepickerShowing&&$.datepicker._lastInput!=a[0]?($.datepicker._hideDatepicker(),$.datepicker._showDatepicker(a[0])):$.datepicker._showDatepicker(a[0]),!1})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var d=function(a){var b=0,c=0;for(var d=0;db&&(b=a[d].length,c=d);return c};b.setMonth(d(this._get(a,c.match(/MM/)?"monthNames":"monthNamesShort"))),b.setDate(d(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=$(a);if(c.hasClass(this.markerClassName))return;c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(a,c,d){b.settings[c]=d}).bind("getData.datepicker",function(a,c){return this._get(b,c)}),$.data(a,PROP_NAME,b),this._setDate(b,this._getDefaultDate(b),!0),this._updateDatepicker(b),this._updateAlternate(b),b.settings.disabled&&this._disableDatepicker(a),b.dpDiv.css("display","block")},_dialogDatepicker:function(a,b,c,d,e){var f=this._dialogInst;if(!f){this.uuid+=1;var g="dp"+this.uuid;this._dialogInput=$(' '),this._dialogInput.keydown(this._doKeyDown),$("body").append(this._dialogInput),f=this._dialogInst=this._newInst(this._dialogInput,!1),f.settings={},$.data(this._dialogInput[0],PROP_NAME,f)}extendRemove(f.settings,d||{}),b=b&&b.constructor==Date?this._formatDate(f,b):b,this._dialogInput.val(b),this._pos=e?e.length?e:[e.pageX,e.pageY]:null;if(!this._pos){var h=document.documentElement.clientWidth,i=document.documentElement.clientHeight,j=document.documentElement.scrollLeft||document.body.scrollLeft,k=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[h/2-100+j,i/2-150+k]}return this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),f.settings.onSelect=c,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),$.blockUI&&$.blockUI(this.dpDiv),$.data(this._dialogInput[0],PROP_NAME,f),this},_destroyDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!b.hasClass(this.markerClassName))return;var d=a.nodeName.toLowerCase();$.removeData(a,PROP_NAME),d=="input"?(c.append.remove(),c.trigger.remove(),b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):(d=="div"||d=="span")&&b.removeClass(this.markerClassName).empty()},_enableDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!b.hasClass(this.markerClassName))return;var d=a.nodeName.toLowerCase();if(d=="input")a.disabled=!1,c.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""});else if(d=="div"||d=="span"){var e=b.children("."+this._inlineClass);e.children().removeClass("ui-state-disabled"),e.find("select.ui-datepicker-month, select.ui-datepicker-year").removeAttr("disabled")}this._disabledInputs=$.map(this._disabledInputs,function(b){return b==a?null:b})},_disableDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!b.hasClass(this.markerClassName))return;var d=a.nodeName.toLowerCase();if(d=="input")a.disabled=!0,c.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"});else if(d=="div"||d=="span"){var e=b.children("."+this._inlineClass);e.children().addClass("ui-state-disabled"),e.find("select.ui-datepicker-month, select.ui-datepicker-year").attr("disabled","disabled")}this._disabledInputs=$.map(this._disabledInputs,function(b){return b==a?null:b}),this._disabledInputs[this._disabledInputs.length]=a},_isDisabledDatepicker:function(a){if(!a)return!1;for(var b=0;b-1}},_doKeyUp:function(a){var b=$.datepicker._getInst(a.target);if(b.input.val()!=b.lastVal)try{var c=$.datepicker.parseDate($.datepicker._get(b,"dateFormat"),b.input?b.input.val():null,$.datepicker._getFormatConfig(b));c&&($.datepicker._setDateFromField(b),$.datepicker._updateAlternate(b),$.datepicker._updateDatepicker(b))}catch(d){$.datepicker.log(d)}return!0},_showDatepicker:function(a){a=a.target||a,a.nodeName.toLowerCase()!="input"&&(a=$("input",a.parentNode)[0]);if($.datepicker._isDisabledDatepicker(a)||$.datepicker._lastInput==a)return;var b=$.datepicker._getInst(a);$.datepicker._curInst&&$.datepicker._curInst!=b&&($.datepicker._curInst.dpDiv.stop(!0,!0),b&&$.datepicker._datepickerShowing&&$.datepicker._hideDatepicker($.datepicker._curInst.input[0]));var c=$.datepicker._get(b,"beforeShow"),d=c?c.apply(a,[a,b]):{};if(d===!1)return;extendRemove(b.settings,d),b.lastVal=null,$.datepicker._lastInput=a,$.datepicker._setDateFromField(b),$.datepicker._inDialog&&(a.value=""),$.datepicker._pos||($.datepicker._pos=$.datepicker._findPos(a),$.datepicker._pos[1]+=a.offsetHeight);var e=!1;$(a).parents().each(function(){return e|=$(this).css("position")=="fixed",!e}),e&&$.browser.opera&&($.datepicker._pos[0]-=document.documentElement.scrollLeft,$.datepicker._pos[1]-=document.documentElement.scrollTop);var f={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null,b.dpDiv.empty(),b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),$.datepicker._updateDatepicker(b),f=$.datepicker._checkOffset(b,f,e),b.dpDiv.css({position:$.datepicker._inDialog&&$.blockUI?"static":e?"fixed":"absolute",display:"none",left:f.left+"px",top:f.top+"px"});if(!b.inline){var g=$.datepicker._get(b,"showAnim"),h=$.datepicker._get(b,"duration"),i=function(){var a=b.dpDiv.find("iframe.ui-datepicker-cover");if(!!a.length){var c=$.datepicker._getBorders(b.dpDiv);a.css({left:-c[0],top:-c[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})}};b.dpDiv.zIndex($(a).zIndex()+1),$.datepicker._datepickerShowing=!0,$.effects&&$.effects[g]?b.dpDiv.show(g,$.datepicker._get(b,"showOptions"),h,i):b.dpDiv[g||"show"](g?h:null,i),(!g||!h)&&i(),b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus(),$.datepicker._curInst=b}},_updateDatepicker:function(a){var b=this;b.maxRows=4;var c=$.datepicker._getBorders(a.dpDiv);instActive=a,a.dpDiv.empty().append(this._generateHTML(a)),this._attachHandlers(a);var d=a.dpDiv.find("iframe.ui-datepicker-cover");!d.length||d.css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}),a.dpDiv.find("."+this._dayOverClass+" a").mouseover();var e=this._getNumberOfMonths(a),f=e[1],g=17;a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),f>1&&a.dpDiv.addClass("ui-datepicker-multi-"+f).css("width",g*f+"em"),a.dpDiv[(e[0]!=1||e[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi"),a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),a==$.datepicker._curInst&&$.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input[0]!=document.activeElement&&a.input.focus();if(a.yearshtml){var h=a.yearshtml;setTimeout(function(){h===a.yearshtml&&a.yearshtml&&a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml),h=a.yearshtml=null},0)}},_getBorders:function(a){var b=function(a){return{thin:1,medium:2,thick:3}[a]||a};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var d=a.dpDiv.outerWidth(),e=a.dpDiv.outerHeight(),f=a.input?a.input.outerWidth():0,g=a.input?a.input.outerHeight():0,h=document.documentElement.clientWidth+(c?0:$(document).scrollLeft()),i=document.documentElement.clientHeight+(c?0:$(document).scrollTop());return b.left-=this._get(a,"isRTL")?d-f:0,b.left-=c&&b.left==a.input.offset().left?$(document).scrollLeft():0,b.top-=c&&b.top==a.input.offset().top+g?$(document).scrollTop():0,b.left-=Math.min(b.left,b.left+d>h&&h>d?Math.abs(b.left+d-h):0),b.top-=Math.min(b.top,b.top+e>i&&i>e?Math.abs(e+g):0),b},_findPos:function(a){var b=this._getInst(a),c=this._get(b,"isRTL");while(a&&(a.type=="hidden"||a.nodeType!=1||$.expr.filters.hidden(a)))a=a[c?"previousSibling":"nextSibling"];var d=$(a).offset();return[d.left,d.top]},_hideDatepicker:function(a){var b=this._curInst;if(!b||a&&b!=$.data(a,PROP_NAME))return;if(this._datepickerShowing){var c=this._get(b,"showAnim"),d=this._get(b,"duration"),e=function(){$.datepicker._tidyDialog(b)};$.effects&&$.effects[c]?b.dpDiv.hide(c,$.datepicker._get(b,"showOptions"),d,e):b.dpDiv[c=="slideDown"?"slideUp":c=="fadeIn"?"fadeOut":"hide"](c?d:null,e),c||e(),this._datepickerShowing=!1;var f=this._get(b,"onClose");f&&f.apply(b.input?b.input[0]:null,[b.input?b.input.val():"",b]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),$.blockUI&&($.unblockUI(),$("body").append(this.dpDiv))),this._inDialog=!1}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(!$.datepicker._curInst)return;var b=$(a.target),c=$.datepicker._getInst(b[0]);(b[0].id!=$.datepicker._mainDivId&&b.parents("#"+$.datepicker._mainDivId).length==0&&!b.hasClass($.datepicker.markerClassName)&&!b.closest("."+$.datepicker._triggerClass).length&&$.datepicker._datepickerShowing&&(!$.datepicker._inDialog||!$.blockUI)||b.hasClass($.datepicker.markerClassName)&&$.datepicker._curInst!=c)&&$.datepicker._hideDatepicker()},_adjustDate:function(a,b,c){var d=$(a),e=this._getInst(d[0]);if(this._isDisabledDatepicker(d[0]))return;this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c),this._updateDatepicker(e)},_gotoToday:function(a){var b=$(a),c=this._getInst(b[0]);if(this._get(c,"gotoCurrent")&&c.currentDay)c.selectedDay=c.currentDay,c.drawMonth=c.selectedMonth=c.currentMonth,c.drawYear=c.selectedYear=c.currentYear;else{var d=new Date;c.selectedDay=d.getDate(),c.drawMonth=c.selectedMonth=d.getMonth(),c.drawYear=c.selectedYear=d.getFullYear()}this._notifyChange(c),this._adjustDate(b)},_selectMonthYear:function(a,b,c){var d=$(a),e=this._getInst(d[0]);e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10),this._notifyChange(e),this._adjustDate(d)},_selectDay:function(a,b,c,d){var e=$(a);if($(d).hasClass(this._unselectableClass)||this._isDisabledDatepicker(e[0]))return;var f=this._getInst(e[0]);f.selectedDay=f.currentDay=$("a",d).html(),f.selectedMonth=f.currentMonth=b,f.selectedYear=f.currentYear=c,this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))},_clearDate:function(a){var b=$(a),c=this._getInst(b[0]);this._selectDate(b,"")},_selectDate:function(a,b){var c=$(a),d=this._getInst(c[0]);b=b!=null?b:this._formatDate(d),d.input&&d.input.val(b),this._updateAlternate(d);var e=this._get(d,"onSelect");e?e.apply(d.input?d.input[0]:null,[b,d]):d.input&&d.input.trigger("change"),d.inline?this._updateDatepicker(d):(this._hideDatepicker(),this._lastInput=d.input[0],typeof d.input[0]!="object"&&d.input.focus(),this._lastInput=null)},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")||this._get(a,"dateFormat"),d=this._getDate(a),e=this.formatDate(c,d,this._getFormatConfig(a));$(b).each(function(){$(this).val(e)})}},noWeekends:function(a){var b=a.getDay();return[b>0&&b<6,""]},iso8601Week:function(a){var b=new Date(a.getTime());b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null;var d=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff;d=typeof d!="string"?d:(new Date).getFullYear()%100+parseInt(d,10);var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,g=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,h=(c?c.monthNames:null)||this._defaults.monthNames,i=-1,j=-1,k=-1,l=-1,m=!1,n=function(b){var c=s+1-1){j=1,k=l;do{var u=this._getDaysInMonth(i,j-1);if(k<=u)break;j++,k-=u}while(!0)}var t=this._daylightSavingAdjust(new Date(i,j-1,k));if(t.getFullYear()!=i||t.getMonth()+1!=j||t.getDate()!=k)throw"Invalid date";return t},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1e7,formatDate:function(a,b,c){if(!b)return"";var d=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,e=(c?c.dayNames:null)||this._defaults.dayNames,f=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,h=function(b){var c=m+112?a.getHours()+2:0),a):null},_setDate:function(a,b,c){var d=!b,e=a.selectedMonth,f=a.selectedYear,g=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=g.getDate(),a.drawMonth=a.selectedMonth=a.currentMonth=g.getMonth(),a.drawYear=a.selectedYear=a.currentYear=g.getFullYear(),(e!=a.selectedMonth||f!=a.selectedYear)&&!c&&this._notifyChange(a),this._adjustInstDate(a),a.input&&a.input.val(d?"":this._formatDate(a))},_getDate:function(a){var b=!a.currentYear||a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return b},_attachHandlers:function(a){var b=this._get(a,"stepMonths"),c="#"+a.id.replace(/\\\\/g,"\\");a.dpDiv.find("[data-handler]").map(function(){var a={prev:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(c,-b,"M")},next:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(c,+b,"M")},hide:function(){window["DP_jQuery_"+dpuuid].datepicker._hideDatepicker()},today:function(){window["DP_jQuery_"+dpuuid].datepicker._gotoToday(c)},selectDay:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectDay(c,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(c,this,"M"),!1},selectYear:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(c,this,"Y"),!1}};$(this).bind(this.getAttribute("data-event"),a[this.getAttribute("data-handler")])})},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),d=this._get(a,"showButtonPanel"),e=this._get(a,"hideIfNoPrevNext"),f=this._get(a,"navigationAsDateFormat"),g=this._getNumberOfMonths(a),h=this._get(a,"showCurrentAtPos"),i=this._get(a,"stepMonths"),j=g[0]!=1||g[1]!=1,k=this._daylightSavingAdjust(a.currentDay?new Date(a.currentYear,a.currentMonth,a.currentDay):new Date(9999,9,9)),l=this._getMinMaxDate(a,"min"),m=this._getMinMaxDate(a,"max"),n=a.drawMonth-h,o=a.drawYear;n<0&&(n+=12,o--);if(m){var p=this._daylightSavingAdjust(new Date(m.getFullYear(),m.getMonth()-g[0]*g[1]+1,m.getDate()));p=l&&pp)n--,n<0&&(n=11,o--)}a.drawMonth=n,a.drawYear=o;var q=this._get(a,"prevText");q=f?this.formatDate(q,this._daylightSavingAdjust(new Date(o,n-i,1)),this._getFormatConfig(a)):q;var r=this._canAdjustMonth(a,-1,o,n)?''+q+" ":e?"":''+q+" ",s=this._get(a,"nextText");s=f?this.formatDate(s,this._daylightSavingAdjust(new Date(o,n+i,1)),this._getFormatConfig(a)):s;var t=this._canAdjustMonth(a,1,o,n)?''+s+" ":e?"":''+s+" ",u=this._get(a,"currentText"),v=this._get(a,"gotoCurrent")&&a.currentDay?k:b;u=f?this.formatDate(u,v,this._getFormatConfig(a)):u;var w=a.inline?"":''+this._get(a,"closeText")+" ",x=d?''+(c?w:"")+(this._isInRange(a,v)?''+u+" ":"")+(c?"":w)+"
":"",y=parseInt(this._get(a,"firstDay"),10);y=isNaN(y)?0:y;var z=this._get(a,"showWeek"),A=this._get(a,"dayNames"),B=this._get(a,"dayNamesShort"),C=this._get(a,"dayNamesMin"),D=this._get(a,"monthNames"),E=this._get(a,"monthNamesShort"),F=this._get(a,"beforeShowDay"),G=this._get(a,"showOtherMonths"),H=this._get(a,"selectOtherMonths"),I=this._get(a,"calculateWeek")||this.iso8601Week,J=this._getDefaultDate(a),K="";for(var L=0;L'}Q+=''+"";var R=z?''+this._get(a,"weekHeader")+" ":"";for(var S=0;S<7;S++){var T=(S+y)%7;R+="=5?' class="ui-datepicker-week-end"':"")+">"+''+C[T]+" "}Q+=R+" ";var U=this._getDaysInMonth(o,n);o==a.selectedYear&&n==a.selectedMonth&&(a.selectedDay=Math.min(a.selectedDay,U));var V=(this._getFirstDayOfMonth(o,n)-y+7)%7,W=Math.ceil((V+U)/7),X=j?this.maxRows>W?this.maxRows:W:W;this.maxRows=X;var Y=this._daylightSavingAdjust(new Date(o,n,1-V));for(var Z=0;Z";var _=z?''+this._get(a,"calculateWeek")(Y)+" ":"";for(var S=0;S<7;S++){var ba=F?F.apply(a.input?a.input[0]:null,[Y]):[!0,""],bb=Y.getMonth()!=n,bc=bb&&!H||!ba[0]||l&&Ym;_+='"+(bb&&!G?" ":bc?''+Y.getDate()+" ":''+Y.getDate()+" ")+" ",Y.setDate(Y.getDate()+1),Y=this._daylightSavingAdjust(Y)}Q+=_+""}n++,n>11&&(n=0,o++),Q+="
"+(j?""+(g[0]>0&&N==g[1]-1?'
':""):""),M+=Q}K+=M}return K+=x+($.browser.msie&&parseInt($.browser.version,10)<7&&!a.inline?'':""),a._keyEvent=!1,K},_generateMonthYearHeader:function(a,b,c,d,e,f,g,h){var i=this._get(a,"changeMonth"),j=this._get(a,"changeYear"),k=this._get(a,"showMonthAfterYear"),l='',m="";if(f||!i)m+=''+g[b]+" ";else{var n=d&&d.getFullYear()==c,o=e&&e.getFullYear()==c;m+='';for(var p=0;p<12;p++)(!n||p>=d.getMonth())&&(!o||p<=e.getMonth())&&(m+='"+h[p]+" ");m+=" "}k||(l+=m+(f||!i||!j?" ":""));if(!a.yearshtml){a.yearshtml="";if(f||!j)l+=''+c+" ";else{var q=this._get(a,"yearRange").split(":"),r=(new Date).getFullYear(),s=function(a){var b=a.match(/c[+-].*/)?c+parseInt(a.substring(1),10):a.match(/[+-].*/)?r+parseInt(a,10):parseInt(a,10);return isNaN(b)?r:b},t=s(q[0]),u=Math.max(t,s(q[1]||""));t=d?Math.max(t,d.getFullYear()):t,u=e?Math.min(u,e.getFullYear()):u,a.yearshtml+='';for(;t<=u;t++)a.yearshtml+='"+t+" ";a.yearshtml+=" ",l+=a.yearshtml,a.yearshtml=null}}return l+=this._get(a,"yearSuffix"),k&&(l+=(f||!i||!j?" ":"")+m),l+="
",l},_adjustInstDate:function(a,b,c){var d=a.drawYear+(c=="Y"?b:0),e=a.drawMonth+(c=="M"?b:0),f=Math.min(a.selectedDay,this._getDaysInMonth(d,e))+(c=="D"?b:0),g=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(d,e,f)));a.selectedDay=g.getDate(),a.drawMonth=a.selectedMonth=g.getMonth(),a.drawYear=a.selectedYear=g.getFullYear(),(c=="M"||c=="Y")&&this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max"),e=c&&bd?d:e,e},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");b&&b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){var b=this._get(a,"numberOfMonths");return b==null?[1,1]:typeof b=="number"?[1,b]:b},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,d){var e=this._getNumberOfMonths(a),f=this._daylightSavingAdjust(new Date(c,d+(b<0?b:e[0]*e[1]),1));return b<0&&f.setDate(this._getDaysInMonth(f.getFullYear(),f.getMonth())),this._isInRange(a,f)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!d||b.getTime()<=d.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");return b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10),{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,d){b||(a.currentDay=a.selectedDay,a.currentMonth=a.selectedMonth,a.currentYear=a.selectedYear);var e=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(d,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),e,this._getFormatConfig(a))}}),$.fn.datepicker=function(a){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv),$.datepicker.initialized=!0);var b=Array.prototype.slice.call(arguments,1);return typeof a!="string"||a!="isDisabled"&&a!="getDate"&&a!="widget"?a=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b)):this.each(function(){typeof a=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this].concat(b)):$.datepicker._attachDatepicker(this,a)}):$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.8.24",window["DP_jQuery_"+dpuuid]=$})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.progressbar.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=a("").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove(),a.Widget.prototype.destroy.apply(this,arguments)},value:function(a){return a===b?this._value():(this._setOption("value",a),this)},_setOption:function(b,c){b==="value"&&(this.options.value=c,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),a.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;return typeof a!="number"&&(a=0),Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var a=this.value(),b=this._percentage();this.oldValue!==a&&(this.oldValue=a,this._trigger("change")),this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(b.toFixed(0)+"%"),this.element.attr("aria-valuenow",a)}}),a.extend(a.ui.progressbar,{version:"1.8.24"})})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.effects.core.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+jQuery.effects||function(a,b){function c(b){var c;return b&&b.constructor==Array&&b.length==3?b:(c=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b))?[parseInt(c[1],10),parseInt(c[2],10),parseInt(c[3],10)]:(c=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b))?[parseFloat(c[1])*2.55,parseFloat(c[2])*2.55,parseFloat(c[3])*2.55]:(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b))?[parseInt(c[1],16),parseInt(c[2],16),parseInt(c[3],16)]:(c=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b))?[parseInt(c[1]+c[1],16),parseInt(c[2]+c[2],16),parseInt(c[3]+c[3],16)]:(c=/rgba\(0, 0, 0, 0\)/.exec(b))?e.transparent:e[a.trim(b).toLowerCase()]}function d(b,d){var e;do{e=(a.curCSS||a.css)(b,d);if(e!=""&&e!="transparent"||a.nodeName(b,"body"))break;d="backgroundColor"}while(b=b.parentNode);return c(e)}function h(){var a=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,b={},c,d;if(a&&a.length&&a[0]&&a[a[0]]){var e=a.length;while(e--)c=a[e],typeof a[c]=="string"&&(d=c.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()}),b[d]=a[c])}else for(c in a)typeof a[c]=="string"&&(b[c]=a[c]);return b}function i(b){var c,d;for(c in b)d=b[c],(d==null||a.isFunction(d)||c in g||/scrollbar/.test(c)||!/color/i.test(c)&&isNaN(parseFloat(d)))&&delete b[c];return b}function j(a,b){var c={_:0},d;for(d in b)a[d]!=b[d]&&(c[d]=b[d]);return c}function k(b,c,d,e){typeof b=="object"&&(e=c,d=null,c=b,b=c.effect),a.isFunction(c)&&(e=c,d=null,c={});if(typeof c=="number"||a.fx.speeds[c])e=d,d=c,c={};return a.isFunction(d)&&(e=d,d=null),c=c||{},d=d||c.duration,d=a.fx.off?0:typeof d=="number"?d:d in a.fx.speeds?a.fx.speeds[d]:a.fx.speeds._default,e=e||c.complete,[b,c,d,e]}function l(b){return!b||typeof b=="number"||a.fx.speeds[b]?!0:typeof b=="string"&&!a.effects[b]?!0:!1}a.effects={},a.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","borderColor","color","outlineColor"],function(b,e){a.fx.step[e]=function(a){a.colorInit||(a.start=d(a.elem,e),a.end=c(a.end),a.colorInit=!0),a.elem.style[e]="rgb("+Math.max(Math.min(parseInt(a.pos*(a.end[0]-a.start[0])+a.start[0],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[1]-a.start[1])+a.start[1],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[2]-a.start[2])+a.start[2],10),255),0)+")"}});var e={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},f=["add","remove","toggle"],g={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};a.effects.animateClass=function(b,c,d,e){return a.isFunction(d)&&(e=d,d=null),this.queue(function(){var g=a(this),k=g.attr("style")||" ",l=i(h.call(this)),m,n=g.attr("class")||"";a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),m=i(h.call(this)),g.attr("class",n),g.animate(j(l,m),{queue:!1,duration:c,easing:d,complete:function(){a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),typeof g.attr("style")=="object"?(g.attr("style").cssText="",g.attr("style").cssText=k):g.attr("style",k),e&&e.apply(this,arguments),a.dequeue(this)}})})},a.fn.extend({_addClass:a.fn.addClass,addClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{add:b},c,d,e]):this._addClass(b)},_removeClass:a.fn.removeClass,removeClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{remove:b},c,d,e]):this._removeClass(b)},_toggleClass:a.fn.toggleClass,toggleClass:function(c,d,e,f,g){return typeof d=="boolean"||d===b?e?a.effects.animateClass.apply(this,[d?{add:c}:{remove:c},e,f,g]):this._toggleClass(c,d):a.effects.animateClass.apply(this,[{toggle:c},d,e,f])},switchClass:function(b,c,d,e,f){return a.effects.animateClass.apply(this,[{add:c,remove:b},d,e,f])}}),a.extend(a.effects,{version:"1.8.24",save:function(a,b){for(var c=0;c").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e=document.activeElement;try{e.id}catch(f){e=document.body}return b.wrap(d),(b[0]===e||a.contains(b[0],e))&&a(e).focus(),d=b.parent(),b.css("position")=="static"?(d.css({position:"relative"}),b.css({position:"relative"})):(a.extend(c,{position:b.css("position"),zIndex:b.css("z-index")}),a.each(["top","left","bottom","right"],function(a,d){c[d]=b.css(d),isNaN(parseInt(c[d],10))&&(c[d]="auto")}),b.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),d.css(c).show()},removeWrapper:function(b){var c,d=document.activeElement;return b.parent().is(".ui-effects-wrapper")?(c=b.parent().replaceWith(b),(b[0]===d||a.contains(b[0],d))&&a(d).focus(),c):b},setTransition:function(b,c,d,e){return e=e||{},a.each(c,function(a,c){var f=b.cssUnit(c);f[0]>0&&(e[c]=f[0]*d+f[1])}),e}}),a.fn.extend({effect:function(b,c,d,e){var f=k.apply(this,arguments),g={options:f[1],duration:f[2],callback:f[3]},h=g.options.mode,i=a.effects[b];return a.fx.off||!i?h?this[h](g.duration,g.callback):this.each(function(){g.callback&&g.callback.call(this)}):i.call(this,g)},_show:a.fn.show,show:function(a){if(l(a))return this._show.apply(this,arguments);var b=k.apply(this,arguments);return b[1].mode="show",this.effect.apply(this,b)},_hide:a.fn.hide,hide:function(a){if(l(a))return this._hide.apply(this,arguments);var b=k.apply(this,arguments);return b[1].mode="hide",this.effect.apply(this,b)},__toggle:a.fn.toggle,toggle:function(b){if(l(b)||typeof b=="boolean"||a.isFunction(b))return this.__toggle.apply(this,arguments);var c=k.apply(this,arguments);return c[1].mode="toggle",this.effect.apply(this,c)},cssUnit:function(b){var c=this.css(b),d=[];return a.each(["em","px","%","pt"],function(a,b){c.indexOf(b)>0&&(d=[parseFloat(c),b])}),d}});var m={};a.each(["Quad","Cubic","Quart","Quint","Expo"],function(a,b){m[b]=function(b){return Math.pow(b,a+2)}}),a.extend(m,{Sine:function(a){return 1-Math.cos(a*Math.PI/2)},Circ:function(a){return 1-Math.sqrt(1-a*a)},Elastic:function(a){return a===0||a===1?a:-Math.pow(2,8*(a-1))*Math.sin(((a-1)*80-7.5)*Math.PI/15)},Back:function(a){return a*a*(3*a-2)},Bounce:function(a){var b,c=4;while(a<((b=Math.pow(2,--c))-1)/11);return 1/Math.pow(4,3-c)-7.5625*Math.pow((b*3-2)/22-a,2)}}),a.each(m,function(b,c){a.easing["easeIn"+b]=c,a.easing["easeOut"+b]=function(a){return 1-c(1-a)},a.easing["easeInOut"+b]=function(a){return a<.5?c(a*2)/2:c(a*-2+2)/-2+1}})}(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.effects.blind.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.effects.blind=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"vertical";a.effects.save(c,d),c.show();var g=a.effects.createWrapper(c).css({overflow:"hidden"}),h=f=="vertical"?"height":"width",i=f=="vertical"?g.height():g.width();e=="show"&&g.css(h,0);var j={};j[h]=e=="show"?i:0,g.animate(j,b.duration,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.effects.bounce.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.effects.bounce=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"effect"),f=b.options.direction||"up",g=b.options.distance||20,h=b.options.times||5,i=b.duration||250;/show|hide/.test(e)&&d.push("opacity"),a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var j=f=="up"||f=="down"?"top":"left",k=f=="up"||f=="left"?"pos":"neg",g=b.options.distance||(j=="top"?c.outerHeight(!0)/3:c.outerWidth(!0)/3);e=="show"&&c.css("opacity",0).css(j,k=="pos"?-g:g),e=="hide"&&(g=g/(h*2)),e!="hide"&&h--;if(e=="show"){var l={opacity:1};l[j]=(k=="pos"?"+=":"-=")+g,c.animate(l,i/2,b.options.easing),g=g/2,h--}for(var m=0;m").css({position:"absolute",visibility:"visible",left:-j*(g/d),top:-i*(h/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:g/d,height:h/c,left:f.left+j*(g/d)+(b.options.mode=="show"?(j-Math.floor(d/2))*(g/d):0),top:f.top+i*(h/c)+(b.options.mode=="show"?(i-Math.floor(c/2))*(h/c):0),opacity:b.options.mode=="show"?0:1}).animate({left:f.left+j*(g/d)+(b.options.mode=="show"?0:(j-Math.floor(d/2))*(g/d)),top:f.top+i*(h/c)+(b.options.mode=="show"?0:(i-Math.floor(c/2))*(h/c)),opacity:b.options.mode=="show"?1:0},b.duration||500);setTimeout(function(){b.options.mode=="show"?e.css({visibility:"visible"}):e.css({visibility:"visible"}).hide(),b.callback&&b.callback.apply(e[0]),e.dequeue(),a("div.ui-effects-explode").remove()},b.duration||500)})}})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.effects.fade.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.effects.fade=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"hide");c.animate({opacity:d},{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.effects.fold.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.effects.fold=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.size||15,g=!!b.options.horizFirst,h=b.duration?b.duration/2:a.fx.speeds._default/2;a.effects.save(c,d),c.show();var i=a.effects.createWrapper(c).css({overflow:"hidden"}),j=e=="show"!=g,k=j?["width","height"]:["height","width"],l=j?[i.width(),i.height()]:[i.height(),i.width()],m=/([0-9]+)%/.exec(f);m&&(f=parseInt(m[1],10)/100*l[e=="hide"?0:1]),e=="show"&&i.css(g?{height:0,width:f}:{height:f,width:0});var n={},p={};n[k[0]]=e=="show"?l[0]:f,p[k[1]]=e=="show"?l[1]:0,i.animate(n,h,b.options.easing).animate(p,h,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.effects.highlight.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.effects.highlight=function(b){return this.queue(function(){var c=a(this),d=["backgroundImage","backgroundColor","opacity"],e=a.effects.setMode(c,b.options.mode||"show"),f={backgroundColor:c.css("backgroundColor")};e=="hide"&&(f.opacity=0),a.effects.save(c,d),c.show().css({backgroundImage:"none",backgroundColor:b.options.color||"#ffff99"}).animate(f,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),e=="show"&&!a.support.opacity&&this.style.removeAttribute("filter"),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.effects.pulsate.js
+* Copyright (C) 2013 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.effects.pulsate=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"show"),e=(b.options.times||5)*2-1,f=b.duration?b.duration/2:a.fx.speeds._default/2,g=c.is(":visible"),h=0;g||(c.css("opacity",0).show(),h=1),(d=="hide"&&g||d=="show"&&!g)&&e--;for(var i=0;i').appendTo(document.body).addClass(b.options.className).css({top:g.top,left:g.left,height:c.innerHeight(),width:c.innerWidth(),position:"absolute"}).animate(f,b.duration,b.options.easing,function(){h.remove(),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);;
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/jquery/jquery.highlight.js b/deployed/windwalker/media/windwalker/js/jquery/jquery.highlight.js
new file mode 100644
index 00000000..9dcf3c7a
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/jquery/jquery.highlight.js
@@ -0,0 +1,108 @@
+/*
+ * jQuery Highlight plugin
+ *
+ * Based on highlight v3 by Johann Burkard
+ * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
+ *
+ * Code a little bit refactored and cleaned (in my humble opinion).
+ * Most important changes:
+ * - has an option to highlight only entire words (wordsOnly - false by default),
+ * - has an option to be case sensitive (caseSensitive - false by default)
+ * - highlight element tag and class names can be specified in options
+ *
+ * Usage:
+ * // wrap every occurrance of text 'lorem' in content
+ * // with (default options)
+ * $('#content').highlight('lorem');
+ *
+ * // search for and highlight more terms at once
+ * // so you can save some time on traversing DOM
+ * $('#content').highlight(['lorem', 'ipsum']);
+ * $('#content').highlight('lorem ipsum');
+ *
+ * // search only for entire word 'lorem'
+ * $('#content').highlight('lorem', { wordsOnly: true });
+ *
+ * // don't ignore case during search of term 'lorem'
+ * $('#content').highlight('lorem', { caseSensitive: true });
+ *
+ * // wrap every occurrance of term 'ipsum' in content
+ * // with
+ * $('#content').highlight('ipsum', { element: 'em', className: 'important' });
+ *
+ * // remove default highlight
+ * $('#content').unhighlight();
+ *
+ * // remove custom highlight
+ * $('#content').unhighlight({ element: 'em', className: 'important' });
+ *
+ *
+ * Copyright (c) 2009 Bartek Szopka
+ *
+ * Licensed under MIT license.
+ *
+ */
+
+jQuery.extend({
+ highlight: function (node, re, nodeName, className) {
+ if (node.nodeType === 3) {
+ var match = node.data.match(re);
+ if (match) {
+ var highlight = document.createElement(nodeName || 'span');
+ highlight.className = className || 'highlight';
+ var wordNode = node.splitText(match.index);
+ wordNode.splitText(match[0].length);
+ var wordClone = wordNode.cloneNode(true);
+ highlight.appendChild(wordClone);
+ wordNode.parentNode.replaceChild(highlight, wordNode);
+ return 1; //skip added node in parent
+ }
+ } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
+ !/(script|style)/i.test(node.tagName) && // ignore script and style nodes
+ !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
+ for (var i = 0; i < node.childNodes.length; i++) {
+ i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
+ }
+ }
+ return 0;
+ }
+});
+
+jQuery.fn.unhighlight = function (options) {
+ var settings = { className: 'highlight', element: 'span' };
+ jQuery.extend(settings, options);
+
+ return this.find(settings.element + "." + settings.className).each(function () {
+ var parent = this.parentNode;
+ parent.replaceChild(this.firstChild, this);
+ parent.normalize();
+ }).end();
+};
+
+jQuery.fn.highlight = function (words, options) {
+ var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
+ jQuery.extend(settings, options);
+
+ if (words.constructor === String) {
+ words = [words];
+ }
+ words = jQuery.grep(words, function(word, i){
+ return word != '';
+ });
+ words = jQuery.map(words, function(word, i) {
+ return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
+ });
+ if (words.length == 0) { return this; };
+
+ var flag = settings.caseSensitive ? "" : "i";
+ var pattern = "(" + words.join("|") + ")";
+ if (settings.wordsOnly) {
+ pattern = "\\b" + pattern + "\\b";
+ }
+ var re = new RegExp(pattern, flag);
+
+ return this.each(function () {
+ jQuery.highlight(this, re, settings.element, settings.className);
+ });
+};
+
diff --git a/deployed/windwalker/media/windwalker/js/jquery/jquery.highlight.min.js b/deployed/windwalker/media/windwalker/js/jquery/jquery.highlight.min.js
new file mode 100644
index 00000000..2bfb7990
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/jquery/jquery.highlight.min.js
@@ -0,0 +1 @@
+jQuery.extend({highlight:function(node,re,nodeName,className){if(node.nodeType===3){var match=node.data.match(re);if(match){var highlight=document.createElement(nodeName||'span');highlight.className=className||'highlight';var wordNode=node.splitText(match.index);wordNode.splitText(match[0].length);var wordClone=wordNode.cloneNode(true);highlight.appendChild(wordClone);wordNode.parentNode.replaceChild(highlight,wordNode);return 1}}else if((node.nodeType===1&&node.childNodes)&&!/(script|style)/i.test(node.tagName)&&!(node.tagName===nodeName.toUpperCase()&&node.className===className))for(var i=0;i 0) {
+ return false;
+ }
+
+ //Quit if we're not on a valid handle
+ this.handle = this._getHandle(event);
+ if (!this.handle) {
+ return false;
+ }
+
+ this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
+
+ return true;
+
+ },
+
+ _blockFrames: function( selector ) {
+ this.iframeBlocks = this.document.find( selector ).map(function() {
+ var iframe = $( this );
+
+ return $( "" )
+ .css( "position", "absolute" )
+ .appendTo( iframe.parent() )
+ .outerWidth( iframe.outerWidth() )
+ .outerHeight( iframe.outerHeight() )
+ .offset( iframe.offset() )[ 0 ];
+ });
+ },
+
+ _unblockFrames: function() {
+ if ( this.iframeBlocks ) {
+ this.iframeBlocks.remove();
+ delete this.iframeBlocks;
+ }
+ },
+
+ _blurActiveElement: function( event ) {
+ var document = this.document[ 0 ];
+
+ // Only need to blur if the event occurred on the draggable itself, see #10527
+ if ( !this.handleElement.is( event.target ) ) {
+ return;
+ }
+
+ // support: IE9
+ // IE9 throws an "Unspecified error" accessing document.activeElement from an
").css({position:"absolute",visibility:"visible",left:-j*width,top:-i*height}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:width,height:height,left:left+(show?mx*width:0),top:top+(show?my*height:0),opacity:show?0:1}).animate({left:left+(show?0:mx*width),top:top+(show?0:my*height),opacity:show?1:0},o.duration||500,o.easing,childComplete)}};function animComplete(){el.css({visibility:"visible"});$(pieces).remove();if(!show)el.hide();done()}}}));(function(factory){if(typeof define==="function"&&define.amd){define(["jquery","./effect"],factory)}else factory(jQuery)}(function($){return $.effects.effect.fade=function(o,done){var el=$(this),mode=$.effects.setMode(el,o.mode||"toggle");el.animate({opacity:mode},{queue:false,duration:o.duration,easing:o.easing,complete:done})}}));(function(factory){if(typeof define==="function"&&define.amd){define(["jquery","./effect"],factory)}else factory(jQuery)}(function($){return $.effects.effect.fold=function(o,done){var el=$(this),props=["position","top","bottom","left","right","height","width"],mode=$.effects.setMode(el,o.mode||"hide"),show=mode==="show",hide=mode==="hide",size=o.size||15,percent=/([0-9]+)%/.exec(size),horizFirst=!!o.horizFirst,widthFirst=show!==horizFirst,ref=widthFirst?["width","height"]:["height","width"],duration=o.duration/2,wrapper,distance,animation1={},animation2={};$.effects.save(el,props);el.show();wrapper=$.effects.createWrapper(el).css({overflow:"hidden"});distance=widthFirst?[wrapper.width(),wrapper.height()]:[wrapper.height(),wrapper.width()];if(percent)size=parseInt(percent[1],10)/100*distance[hide?0:1];if(show)wrapper.css(horizFirst?{height:0,width:size}:{height:size,width:0});animation1[ref[0]]=show?distance[0]:size;animation2[ref[1]]=show?distance[1]:0;wrapper.animate(animation1,duration,o.easing).animate(animation2,duration,o.easing,function(){if(hide)el.hide();$.effects.restore(el,props);$.effects.removeWrapper(el);done()})}}));(function(factory){if(typeof define==="function"&&define.amd){define(["jquery","./effect"],factory)}else factory(jQuery)}(function($){return $.effects.effect.highlight=function(o,done){var elem=$(this),props=["backgroundImage","backgroundColor","opacity"],mode=$.effects.setMode(elem,o.mode||"show"),animation={backgroundColor:elem.css("backgroundColor")};if(mode==="hide")animation.opacity=0;$.effects.save(elem,props);elem.show().css({backgroundImage:"none",backgroundColor:o.color||"#ffff99"}).animate(animation,{queue:false,duration:o.duration,easing:o.easing,complete:function(){if(mode==="hide")elem.hide();$.effects.restore(elem,props);done()}})}}));(function(factory){if(typeof define==="function"&&define.amd){define(["jquery","./effect","./effect-scale"],factory)}else factory(jQuery)}(function($){return $.effects.effect.puff=function(o,done){var elem=$(this),mode=$.effects.setMode(elem,o.mode||"hide"),hide=mode==="hide",percent=parseInt(o.percent,10)||150,factor=percent/100,original={height:elem.height(),width:elem.width(),outerHeight:elem.outerHeight(),outerWidth:elem.outerWidth()};$.extend(o,{effect:"scale",queue:false,fade:true,mode:mode,complete:done,percent:hide?percent:100,from:hide?original:{height:original.height*factor,width:original.width*factor,outerHeight:original.outerHeight*factor,outerWidth:original.outerWidth*factor}});elem.effect(o)}}));(function(factory){if(typeof define==="function"&&define.amd){define(["jquery","./effect"],factory)}else factory(jQuery)}(function($){return $.effects.effect.pulsate=function(o,done){var elem=$(this),mode=$.effects.setMode(elem,o.mode||"show"),show=mode==="show",hide=mode==="hide",showhide=(show||mode==="hide"),anims=((o.times||5)*2)+(showhide?1:0),duration=o.duration/anims,animateTo=0,queue=elem.queue(),queuelen=queue.length,i;if(show||!elem.is(":visible")){elem.css("opacity",0).show();animateTo=1};for(i=1;i1)queue.splice.apply(queue,[1,0].concat(queue.splice(queuelen,anims+1)));elem.dequeue()}}));(function(factory){if(typeof define==="function"&&define.amd){define(["jquery","./effect","./effect-size"],factory)}else factory(jQuery)}(function($){return $.effects.effect.scale=function(o,done){var el=$(this),options=$.extend(true,{},o),mode=$.effects.setMode(el,o.mode||"effect"),percent=parseInt(o.percent,10)||(parseInt(o.percent,10)===0?0:(mode==="hide"?0:100)),direction=o.direction||"both",origin=o.origin,original={height:el.height(),width:el.width(),outerHeight:el.outerHeight(),outerWidth:el.outerWidth()},factor={y:direction!=="horizontal"?(percent/100):1,x:direction!=="vertical"?(percent/100):1};options.effect="size";options.queue=false;options.complete=done;if(mode!=="effect"){options.origin=origin||["middle","center"];options.restore=true};options.from=o.from||(mode==="show"?{height:0,width:0,outerHeight:0,outerWidth:0}:original);options.to={height:original.height*factor.y,width:original.width*factor.x,outerHeight:original.outerHeight*factor.y,outerWidth:original.outerWidth*factor.x};if(options.fade){if(mode==="show"){options.from.opacity=0;options.to.opacity=1};if(mode==="hide"){options.from.opacity=1;options.to.opacity=0}};el.effect(options)}}));(function(factory){if(typeof define==="function"&&define.amd){define(["jquery","./effect"],factory)}else factory(jQuery)}(function($){return $.effects.effect.shake=function(o,done){var el=$(this),props=["position","top","bottom","left","right","height","width"],mode=$.effects.setMode(el,o.mode||"effect"),direction=o.direction||"left",distance=o.distance||20,times=o.times||3,anims=times*2+1,speed=Math.round(o.duration/anims),ref=(direction==="up"||direction==="down")?"top":"left",positiveMotion=(direction==="up"||direction==="left"),animation={},animation1={},animation2={},i,queue=el.queue(),queuelen=queue.length;$.effects.save(el,props);el.show();$.effects.createWrapper(el);animation[ref]=(positiveMotion?"-=":"+=")+distance;animation1[ref]=(positiveMotion?"+=":"-=")+distance*2;animation2[ref]=(positiveMotion?"-=":"+=")+distance*2;el.animate(animation,speed,o.easing);for(i=1;i1)queue.splice.apply(queue,[1,0].concat(queue.splice(queuelen,anims+1)));el.dequeue()}}));(function(factory){if(typeof define==="function"&&define.amd){define(["jquery","./effect"],factory)}else factory(jQuery)}(function($){return $.effects.effect.slide=function(o,done){var el=$(this),props=["position","top","bottom","left","right","width","height"],mode=$.effects.setMode(el,o.mode||"show"),show=mode==="show",direction=o.direction||"left",ref=(direction==="up"||direction==="down")?"top":"left",positiveMotion=(direction==="up"||direction==="left"),distance,animation={};$.effects.save(el,props);el.show();distance=o.distance||el[ref==="top"?"outerHeight":"outerWidth"](true);$.effects.createWrapper(el).css({overflow:"hidden"});if(show)el.css(ref,positiveMotion?(isNaN(distance)?"-"+distance:-distance):distance);animation[ref]=(show?(positiveMotion?"+=":"-="):(positiveMotion?"-=":"+="))+distance;el.animate(animation,{queue:false,duration:o.duration,easing:o.easing,complete:function(){if(mode==="hide")el.hide();$.effects.restore(el,props);$.effects.removeWrapper(el);done()}})}}));(function(factory){if(typeof define==="function"&&define.amd){define(["jquery","./effect"],factory)}else factory(jQuery)}(function($){return $.effects.effect.size=function(o,done){var original,baseline,factor,el=$(this),props0=["position","top","bottom","left","right","width","height","overflow","opacity"],props1=["position","top","bottom","left","right","overflow","opacity"],props2=["width","height","overflow"],cProps=["fontSize"],vProps=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],hProps=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],mode=$.effects.setMode(el,o.mode||"effect"),restore=o.restore||mode!=="effect",scale=o.scale||"both",origin=o.origin||["middle","center"],position=el.css("position"),props=restore?props0:props1,zero={height:0,width:0,outerHeight:0,outerWidth:0};if(mode==="show")el.show();original={height:el.height(),width:el.width(),outerHeight:el.outerHeight(),outerWidth:el.outerWidth()};if(o.mode==="toggle"&&mode==="show"){el.from=o.to||zero;el.to=o.from||original}else{el.from=o.from||(mode==="show"?zero:original);el.to=o.to||(mode==="hide"?zero:original)};factor={from:{y:el.from.height/original.height,x:el.from.width/original.width},to:{y:el.to.height/original.height,x:el.to.width/original.width}};if(scale==="box"||scale==="both"){if(factor.from.y!==factor.to.y){props=props.concat(vProps);el.from=$.effects.setTransition(el,vProps,factor.from.y,el.from);el.to=$.effects.setTransition(el,vProps,factor.to.y,el.to)};if(factor.from.x!==factor.to.x){props=props.concat(hProps);el.from=$.effects.setTransition(el,hProps,factor.from.x,el.from);el.to=$.effects.setTransition(el,hProps,factor.to.x,el.to)}};if(scale==="content"||scale==="both")if(factor.from.y!==factor.to.y){props=props.concat(cProps).concat(props2);el.from=$.effects.setTransition(el,cProps,factor.from.y,el.from);el.to=$.effects.setTransition(el,cProps,factor.to.y,el.to)};$.effects.save(el,props);el.show();$.effects.createWrapper(el);el.css("overflow","hidden").css(el.from);if(origin){baseline=$.effects.getBaseline(origin,original);el.from.top=(original.outerHeight-el.outerHeight())*baseline.y;el.from.left=(original.outerWidth-el.outerWidth())*baseline.x;el.to.top=(original.outerHeight-el.to.outerHeight)*baseline.y;el.to.left=(original.outerWidth-el.to.outerWidth)*baseline.x};el.css(el.from);if(scale==="content"||scale==="both"){vProps=vProps.concat(["marginTop","marginBottom"]).concat(cProps);hProps=hProps.concat(["marginLeft","marginRight"]);props2=props0.concat(vProps).concat(hProps);el.find("*[width]").each(function(){var child=$(this),c_original={height:child.height(),width:child.width(),outerHeight:child.outerHeight(),outerWidth:child.outerWidth()};if(restore)$.effects.save(child,props2);child.from={height:c_original.height*factor.from.y,width:c_original.width*factor.from.x,outerHeight:c_original.outerHeight*factor.from.y,outerWidth:c_original.outerWidth*factor.from.x};child.to={height:c_original.height*factor.to.y,width:c_original.width*factor.to.x,outerHeight:c_original.height*factor.to.y,outerWidth:c_original.width*factor.to.x};if(factor.from.y!==factor.to.y){child.from=$.effects.setTransition(child,vProps,factor.from.y,child.from);child.to=$.effects.setTransition(child,vProps,factor.to.y,child.to)};if(factor.from.x!==factor.to.x){child.from=$.effects.setTransition(child,hProps,factor.from.x,child.from);child.to=$.effects.setTransition(child,hProps,factor.to.x,child.to)};child.css(child.from);child.animate(child.to,o.duration,o.easing,function(){if(restore)$.effects.restore(child,props2)})})};el.animate(el.to,{queue:false,duration:o.duration,easing:o.easing,complete:function(){if(el.to.opacity===0)el.css("opacity",el.from.opacity);if(mode==="hide")el.hide();$.effects.restore(el,props);if(!restore)if(position==="static"){el.css({position:"relative",top:el.to.top,left:el.to.left})}else $.each(["top","left"],function(idx,pos){el.css(pos,function(_,str){var val=parseInt(str,10),toRef=idx?el.to.left:el.to.top;if(str==="auto")return toRef+"px";return val+toRef+"px"})});$.effects.removeWrapper(el);done()}})}}));(function(factory){if(typeof define==="function"&&define.amd){define(["jquery","./effect"],factory)}else factory(jQuery)}(function($){return $.effects.effect.transfer=function(o,done){var elem=$(this),target=$(o.to),targetFixed=target.css("position")==="fixed",body=$("body"),fixTop=targetFixed?body.scrollTop():0,fixLeft=targetFixed?body.scrollLeft():0,endPosition=target.offset(),animation={top:endPosition.top-fixTop,left:endPosition.left-fixLeft,height:target.innerHeight(),width:target.innerWidth()},startPosition=elem.offset(),transfer=$("
").appendTo(document.body).addClass(o.className).css({top:startPosition.top-fixTop,left:startPosition.left-fixLeft,height:elem.innerHeight(),width:elem.innerWidth(),position:targetFixed?"fixed":"absolute"}).animate(animation,o.duration,o.easing,function(){transfer.remove();done()})}}))
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/jquery/jquery.ui.resizable.js b/deployed/windwalker/media/windwalker/js/jquery/jquery.ui.resizable.js
new file mode 100644
index 00000000..c45ff3b6
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/jquery/jquery.ui.resizable.js
@@ -0,0 +1,1152 @@
+/*!
+ * jQuery UI Resizable 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/resizable/
+ */
+(function( factory ) {
+ if ( typeof define === "function" && define.amd ) {
+
+ // AMD. Register as an anonymous module.
+ define([
+ "jquery",
+ "./core",
+ "./mouse",
+ "./widget"
+ ], factory );
+ } else {
+
+ // Browser globals
+ factory( jQuery );
+ }
+}(function( $ ) {
+
+$.widget("ui.resizable", $.ui.mouse, {
+ version: "1.11.4",
+ widgetEventPrefix: "resize",
+ options: {
+ alsoResize: false,
+ animate: false,
+ animateDuration: "slow",
+ animateEasing: "swing",
+ aspectRatio: false,
+ autoHide: false,
+ containment: false,
+ ghost: false,
+ grid: false,
+ handles: "e,s,se",
+ helper: false,
+ maxHeight: null,
+ maxWidth: null,
+ minHeight: 10,
+ minWidth: 10,
+ // See #7960
+ zIndex: 90,
+
+ // callbacks
+ resize: null,
+ start: null,
+ stop: null
+ },
+
+ _num: function( value ) {
+ return parseInt( value, 10 ) || 0;
+ },
+
+ _isNumber: function( value ) {
+ return !isNaN( parseInt( value, 10 ) );
+ },
+
+ _hasScroll: function( el, a ) {
+
+ if ( $( el ).css( "overflow" ) === "hidden") {
+ return false;
+ }
+
+ var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
+ has = false;
+
+ if ( el[ scroll ] > 0 ) {
+ return true;
+ }
+
+ // TODO: determine which cases actually cause this to happen
+ // if the element doesn't have the scroll set, see if it's possible to
+ // set the scroll
+ el[ scroll ] = 1;
+ has = ( el[ scroll ] > 0 );
+ el[ scroll ] = 0;
+ return has;
+ },
+
+ _create: function() {
+
+ var n, i, handle, axis, hname,
+ that = this,
+ o = this.options;
+ this.element.addClass("ui-resizable");
+
+ $.extend(this, {
+ _aspectRatio: !!(o.aspectRatio),
+ aspectRatio: o.aspectRatio,
+ originalElement: this.element,
+ _proportionallyResizeElements: [],
+ _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
+ });
+
+ // Wrap the element if it cannot hold child nodes
+ if (this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)) {
+
+ this.element.wrap(
+ $("
").css({
+ position: this.element.css("position"),
+ width: this.element.outerWidth(),
+ height: this.element.outerHeight(),
+ top: this.element.css("top"),
+ left: this.element.css("left")
+ })
+ );
+
+ this.element = this.element.parent().data(
+ "ui-resizable", this.element.resizable( "instance" )
+ );
+
+ this.elementIsWrapper = true;
+
+ this.element.css({
+ marginLeft: this.originalElement.css("marginLeft"),
+ marginTop: this.originalElement.css("marginTop"),
+ marginRight: this.originalElement.css("marginRight"),
+ marginBottom: this.originalElement.css("marginBottom")
+ });
+ this.originalElement.css({
+ marginLeft: 0,
+ marginTop: 0,
+ marginRight: 0,
+ marginBottom: 0
+ });
+ // support: Safari
+ // Prevent Safari textarea resize
+ this.originalResizeStyle = this.originalElement.css("resize");
+ this.originalElement.css("resize", "none");
+
+ this._proportionallyResizeElements.push( this.originalElement.css({
+ position: "static",
+ zoom: 1,
+ display: "block"
+ }) );
+
+ // support: IE9
+ // avoid IE jump (hard set the margin)
+ this.originalElement.css({ margin: this.originalElement.css("margin") });
+
+ this._proportionallyResize();
+ }
+
+ this.handles = o.handles ||
+ ( !$(".ui-resizable-handle", this.element).length ?
+ "e,s,se" : {
+ n: ".ui-resizable-n",
+ e: ".ui-resizable-e",
+ s: ".ui-resizable-s",
+ w: ".ui-resizable-w",
+ se: ".ui-resizable-se",
+ sw: ".ui-resizable-sw",
+ ne: ".ui-resizable-ne",
+ nw: ".ui-resizable-nw"
+ } );
+
+ this._handles = $();
+ if ( this.handles.constructor === String ) {
+
+ if ( this.handles === "all") {
+ this.handles = "n,e,s,w,se,sw,ne,nw";
+ }
+
+ n = this.handles.split(",");
+ this.handles = {};
+
+ for (i = 0; i < n.length; i++) {
+
+ handle = $.trim(n[i]);
+ hname = "ui-resizable-" + handle;
+ axis = $("
");
+
+ axis.css({ zIndex: o.zIndex });
+
+ // TODO : What's going on here?
+ if ("se" === handle) {
+ axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
+ }
+
+ this.handles[handle] = ".ui-resizable-" + handle;
+ this.element.append(axis);
+ }
+
+ }
+
+ this._renderAxis = function(target) {
+
+ var i, axis, padPos, padWrapper;
+
+ target = target || this.element;
+
+ for (i in this.handles) {
+
+ if (this.handles[i].constructor === String) {
+ this.handles[i] = this.element.children( this.handles[ i ] ).first().show();
+ } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
+ this.handles[ i ] = $( this.handles[ i ] );
+ this._on( this.handles[ i ], { "mousedown": that._mouseDown });
+ }
+
+ if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)) {
+
+ axis = $(this.handles[i], this.element);
+
+ padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
+
+ padPos = [ "padding",
+ /ne|nw|n/.test(i) ? "Top" :
+ /se|sw|s/.test(i) ? "Bottom" :
+ /^e$/.test(i) ? "Right" : "Left" ].join("");
+
+ target.css(padPos, padWrapper);
+
+ this._proportionallyResize();
+ }
+
+ this._handles = this._handles.add( this.handles[ i ] );
+ }
+ };
+
+ // TODO: make renderAxis a prototype function
+ this._renderAxis(this.element);
+
+ this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
+ this._handles.disableSelection();
+
+ this._handles.mouseover(function() {
+ if (!that.resizing) {
+ if (this.className) {
+ axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
+ }
+ that.axis = axis && axis[1] ? axis[1] : "se";
+ }
+ });
+
+ if (o.autoHide) {
+ this._handles.hide();
+ $(this.element)
+ .addClass("ui-resizable-autohide")
+ .mouseenter(function() {
+ if (o.disabled) {
+ return;
+ }
+ $(this).removeClass("ui-resizable-autohide");
+ that._handles.show();
+ })
+ .mouseleave(function() {
+ if (o.disabled) {
+ return;
+ }
+ if (!that.resizing) {
+ $(this).addClass("ui-resizable-autohide");
+ that._handles.hide();
+ }
+ });
+ }
+
+ this._mouseInit();
+ },
+
+ _destroy: function() {
+
+ this._mouseDestroy();
+
+ var wrapper,
+ _destroy = function(exp) {
+ $(exp)
+ .removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
+ .removeData("resizable")
+ .removeData("ui-resizable")
+ .unbind(".resizable")
+ .find(".ui-resizable-handle")
+ .remove();
+ };
+
+ // TODO: Unwrap at same DOM position
+ if (this.elementIsWrapper) {
+ _destroy(this.element);
+ wrapper = this.element;
+ this.originalElement.css({
+ position: wrapper.css("position"),
+ width: wrapper.outerWidth(),
+ height: wrapper.outerHeight(),
+ top: wrapper.css("top"),
+ left: wrapper.css("left")
+ }).insertAfter( wrapper );
+ wrapper.remove();
+ }
+
+ this.originalElement.css("resize", this.originalResizeStyle);
+ _destroy(this.originalElement);
+
+ return this;
+ },
+
+ _mouseCapture: function(event) {
+ var i, handle,
+ capture = false;
+
+ for (i in this.handles) {
+ handle = $(this.handles[i])[0];
+ if (handle === event.target || $.contains(handle, event.target)) {
+ capture = true;
+ }
+ }
+
+ return !this.options.disabled && capture;
+ },
+
+ _mouseStart: function(event) {
+
+ var curleft, curtop, cursor,
+ o = this.options,
+ el = this.element;
+
+ this.resizing = true;
+
+ this._renderProxy();
+
+ curleft = this._num(this.helper.css("left"));
+ curtop = this._num(this.helper.css("top"));
+
+ if (o.containment) {
+ curleft += $(o.containment).scrollLeft() || 0;
+ curtop += $(o.containment).scrollTop() || 0;
+ }
+
+ this.offset = this.helper.offset();
+ this.position = { left: curleft, top: curtop };
+
+ this.size = this._helper ? {
+ width: this.helper.width(),
+ height: this.helper.height()
+ } : {
+ width: el.width(),
+ height: el.height()
+ };
+
+ this.originalSize = this._helper ? {
+ width: el.outerWidth(),
+ height: el.outerHeight()
+ } : {
+ width: el.width(),
+ height: el.height()
+ };
+
+ this.sizeDiff = {
+ width: el.outerWidth() - el.width(),
+ height: el.outerHeight() - el.height()
+ };
+
+ this.originalPosition = { left: curleft, top: curtop };
+ this.originalMousePosition = { left: event.pageX, top: event.pageY };
+
+ this.aspectRatio = (typeof o.aspectRatio === "number") ?
+ o.aspectRatio :
+ ((this.originalSize.width / this.originalSize.height) || 1);
+
+ cursor = $(".ui-resizable-" + this.axis).css("cursor");
+ $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
+
+ el.addClass("ui-resizable-resizing");
+ this._propagate("start", event);
+ return true;
+ },
+
+ _mouseDrag: function(event) {
+
+ var data, props,
+ smp = this.originalMousePosition,
+ a = this.axis,
+ dx = (event.pageX - smp.left) || 0,
+ dy = (event.pageY - smp.top) || 0,
+ trigger = this._change[a];
+
+ this._updatePrevProperties();
+
+ if (!trigger) {
+ return false;
+ }
+
+ data = trigger.apply(this, [ event, dx, dy ]);
+
+ this._updateVirtualBoundaries(event.shiftKey);
+ if (this._aspectRatio || event.shiftKey) {
+ data = this._updateRatio(data, event);
+ }
+
+ data = this._respectSize(data, event);
+
+ this._updateCache(data);
+
+ this._propagate("resize", event);
+
+ props = this._applyChanges();
+
+ if ( !this._helper && this._proportionallyResizeElements.length ) {
+ this._proportionallyResize();
+ }
+
+ if ( !$.isEmptyObject( props ) ) {
+ this._updatePrevProperties();
+ this._trigger( "resize", event, this.ui() );
+ this._applyChanges();
+ }
+
+ return false;
+ },
+
+ _mouseStop: function(event) {
+
+ this.resizing = false;
+ var pr, ista, soffseth, soffsetw, s, left, top,
+ o = this.options, that = this;
+
+ if (this._helper) {
+
+ pr = this._proportionallyResizeElements;
+ ista = pr.length && (/textarea/i).test(pr[0].nodeName);
+ soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height;
+ soffsetw = ista ? 0 : that.sizeDiff.width;
+
+ s = {
+ width: (that.helper.width() - soffsetw),
+ height: (that.helper.height() - soffseth)
+ };
+ left = (parseInt(that.element.css("left"), 10) +
+ (that.position.left - that.originalPosition.left)) || null;
+ top = (parseInt(that.element.css("top"), 10) +
+ (that.position.top - that.originalPosition.top)) || null;
+
+ if (!o.animate) {
+ this.element.css($.extend(s, { top: top, left: left }));
+ }
+
+ that.helper.height(that.size.height);
+ that.helper.width(that.size.width);
+
+ if (this._helper && !o.animate) {
+ this._proportionallyResize();
+ }
+ }
+
+ $("body").css("cursor", "auto");
+
+ this.element.removeClass("ui-resizable-resizing");
+
+ this._propagate("stop", event);
+
+ if (this._helper) {
+ this.helper.remove();
+ }
+
+ return false;
+
+ },
+
+ _updatePrevProperties: function() {
+ this.prevPosition = {
+ top: this.position.top,
+ left: this.position.left
+ };
+ this.prevSize = {
+ width: this.size.width,
+ height: this.size.height
+ };
+ },
+
+ _applyChanges: function() {
+ var props = {};
+
+ if ( this.position.top !== this.prevPosition.top ) {
+ props.top = this.position.top + "px";
+ }
+ if ( this.position.left !== this.prevPosition.left ) {
+ props.left = this.position.left + "px";
+ }
+ if ( this.size.width !== this.prevSize.width ) {
+ props.width = this.size.width + "px";
+ }
+ if ( this.size.height !== this.prevSize.height ) {
+ props.height = this.size.height + "px";
+ }
+
+ this.helper.css( props );
+
+ return props;
+ },
+
+ _updateVirtualBoundaries: function(forceAspectRatio) {
+ var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
+ o = this.options;
+
+ b = {
+ minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0,
+ maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity,
+ minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0,
+ maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity
+ };
+
+ if (this._aspectRatio || forceAspectRatio) {
+ pMinWidth = b.minHeight * this.aspectRatio;
+ pMinHeight = b.minWidth / this.aspectRatio;
+ pMaxWidth = b.maxHeight * this.aspectRatio;
+ pMaxHeight = b.maxWidth / this.aspectRatio;
+
+ if (pMinWidth > b.minWidth) {
+ b.minWidth = pMinWidth;
+ }
+ if (pMinHeight > b.minHeight) {
+ b.minHeight = pMinHeight;
+ }
+ if (pMaxWidth < b.maxWidth) {
+ b.maxWidth = pMaxWidth;
+ }
+ if (pMaxHeight < b.maxHeight) {
+ b.maxHeight = pMaxHeight;
+ }
+ }
+ this._vBoundaries = b;
+ },
+
+ _updateCache: function(data) {
+ this.offset = this.helper.offset();
+ if (this._isNumber(data.left)) {
+ this.position.left = data.left;
+ }
+ if (this._isNumber(data.top)) {
+ this.position.top = data.top;
+ }
+ if (this._isNumber(data.height)) {
+ this.size.height = data.height;
+ }
+ if (this._isNumber(data.width)) {
+ this.size.width = data.width;
+ }
+ },
+
+ _updateRatio: function( data ) {
+
+ var cpos = this.position,
+ csize = this.size,
+ a = this.axis;
+
+ if (this._isNumber(data.height)) {
+ data.width = (data.height * this.aspectRatio);
+ } else if (this._isNumber(data.width)) {
+ data.height = (data.width / this.aspectRatio);
+ }
+
+ if (a === "sw") {
+ data.left = cpos.left + (csize.width - data.width);
+ data.top = null;
+ }
+ if (a === "nw") {
+ data.top = cpos.top + (csize.height - data.height);
+ data.left = cpos.left + (csize.width - data.width);
+ }
+
+ return data;
+ },
+
+ _respectSize: function( data ) {
+
+ var o = this._vBoundaries,
+ a = this.axis,
+ ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width),
+ ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
+ isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width),
+ isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
+ dw = this.originalPosition.left + this.originalSize.width,
+ dh = this.position.top + this.size.height,
+ cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
+ if (isminw) {
+ data.width = o.minWidth;
+ }
+ if (isminh) {
+ data.height = o.minHeight;
+ }
+ if (ismaxw) {
+ data.width = o.maxWidth;
+ }
+ if (ismaxh) {
+ data.height = o.maxHeight;
+ }
+
+ if (isminw && cw) {
+ data.left = dw - o.minWidth;
+ }
+ if (ismaxw && cw) {
+ data.left = dw - o.maxWidth;
+ }
+ if (isminh && ch) {
+ data.top = dh - o.minHeight;
+ }
+ if (ismaxh && ch) {
+ data.top = dh - o.maxHeight;
+ }
+
+ // Fixing jump error on top/left - bug #2330
+ if (!data.width && !data.height && !data.left && data.top) {
+ data.top = null;
+ } else if (!data.width && !data.height && !data.top && data.left) {
+ data.left = null;
+ }
+
+ return data;
+ },
+
+ _getPaddingPlusBorderDimensions: function( element ) {
+ var i = 0,
+ widths = [],
+ borders = [
+ element.css( "borderTopWidth" ),
+ element.css( "borderRightWidth" ),
+ element.css( "borderBottomWidth" ),
+ element.css( "borderLeftWidth" )
+ ],
+ paddings = [
+ element.css( "paddingTop" ),
+ element.css( "paddingRight" ),
+ element.css( "paddingBottom" ),
+ element.css( "paddingLeft" )
+ ];
+
+ for ( ; i < 4; i++ ) {
+ widths[ i ] = ( parseInt( borders[ i ], 10 ) || 0 );
+ widths[ i ] += ( parseInt( paddings[ i ], 10 ) || 0 );
+ }
+
+ return {
+ height: widths[ 0 ] + widths[ 2 ],
+ width: widths[ 1 ] + widths[ 3 ]
+ };
+ },
+
+ _proportionallyResize: function() {
+
+ if (!this._proportionallyResizeElements.length) {
+ return;
+ }
+
+ var prel,
+ i = 0,
+ element = this.helper || this.element;
+
+ for ( ; i < this._proportionallyResizeElements.length; i++) {
+
+ prel = this._proportionallyResizeElements[i];
+
+ // TODO: Seems like a bug to cache this.outerDimensions
+ // considering that we are in a loop.
+ if (!this.outerDimensions) {
+ this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
+ }
+
+ prel.css({
+ height: (element.height() - this.outerDimensions.height) || 0,
+ width: (element.width() - this.outerDimensions.width) || 0
+ });
+
+ }
+
+ },
+
+ _renderProxy: function() {
+
+ var el = this.element, o = this.options;
+ this.elementOffset = el.offset();
+
+ if (this._helper) {
+
+ this.helper = this.helper || $("
");
+
+ this.helper.addClass(this._helper).css({
+ width: this.element.outerWidth() - 1,
+ height: this.element.outerHeight() - 1,
+ position: "absolute",
+ left: this.elementOffset.left + "px",
+ top: this.elementOffset.top + "px",
+ zIndex: ++o.zIndex //TODO: Don't modify option
+ });
+
+ this.helper
+ .appendTo("body")
+ .disableSelection();
+
+ } else {
+ this.helper = this.element;
+ }
+
+ },
+
+ _change: {
+ e: function(event, dx) {
+ return { width: this.originalSize.width + dx };
+ },
+ w: function(event, dx) {
+ var cs = this.originalSize, sp = this.originalPosition;
+ return { left: sp.left + dx, width: cs.width - dx };
+ },
+ n: function(event, dx, dy) {
+ var cs = this.originalSize, sp = this.originalPosition;
+ return { top: sp.top + dy, height: cs.height - dy };
+ },
+ s: function(event, dx, dy) {
+ return { height: this.originalSize.height + dy };
+ },
+ se: function(event, dx, dy) {
+ return $.extend(this._change.s.apply(this, arguments),
+ this._change.e.apply(this, [ event, dx, dy ]));
+ },
+ sw: function(event, dx, dy) {
+ return $.extend(this._change.s.apply(this, arguments),
+ this._change.w.apply(this, [ event, dx, dy ]));
+ },
+ ne: function(event, dx, dy) {
+ return $.extend(this._change.n.apply(this, arguments),
+ this._change.e.apply(this, [ event, dx, dy ]));
+ },
+ nw: function(event, dx, dy) {
+ return $.extend(this._change.n.apply(this, arguments),
+ this._change.w.apply(this, [ event, dx, dy ]));
+ }
+ },
+
+ _propagate: function(n, event) {
+ $.ui.plugin.call(this, n, [ event, this.ui() ]);
+ (n !== "resize" && this._trigger(n, event, this.ui()));
+ },
+
+ plugins: {},
+
+ ui: function() {
+ return {
+ originalElement: this.originalElement,
+ element: this.element,
+ helper: this.helper,
+ position: this.position,
+ size: this.size,
+ originalSize: this.originalSize,
+ originalPosition: this.originalPosition
+ };
+ }
+
+});
+
+/*
+ * Resizable Extensions
+ */
+
+$.ui.plugin.add("resizable", "animate", {
+
+ stop: function( event ) {
+ var that = $(this).resizable( "instance" ),
+ o = that.options,
+ pr = that._proportionallyResizeElements,
+ ista = pr.length && (/textarea/i).test(pr[0].nodeName),
+ soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height,
+ soffsetw = ista ? 0 : that.sizeDiff.width,
+ style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
+ left = (parseInt(that.element.css("left"), 10) +
+ (that.position.left - that.originalPosition.left)) || null,
+ top = (parseInt(that.element.css("top"), 10) +
+ (that.position.top - that.originalPosition.top)) || null;
+
+ that.element.animate(
+ $.extend(style, top && left ? { top: top, left: left } : {}), {
+ duration: o.animateDuration,
+ easing: o.animateEasing,
+ step: function() {
+
+ var data = {
+ width: parseInt(that.element.css("width"), 10),
+ height: parseInt(that.element.css("height"), 10),
+ top: parseInt(that.element.css("top"), 10),
+ left: parseInt(that.element.css("left"), 10)
+ };
+
+ if (pr && pr.length) {
+ $(pr[0]).css({ width: data.width, height: data.height });
+ }
+
+ // propagating resize, and updating values for each animation step
+ that._updateCache(data);
+ that._propagate("resize", event);
+
+ }
+ }
+ );
+ }
+
+});
+
+$.ui.plugin.add( "resizable", "containment", {
+
+ start: function() {
+ var element, p, co, ch, cw, width, height,
+ that = $( this ).resizable( "instance" ),
+ o = that.options,
+ el = that.element,
+ oc = o.containment,
+ ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
+
+ if ( !ce ) {
+ return;
+ }
+
+ that.containerElement = $( ce );
+
+ if ( /document/.test( oc ) || oc === document ) {
+ that.containerOffset = {
+ left: 0,
+ top: 0
+ };
+ that.containerPosition = {
+ left: 0,
+ top: 0
+ };
+
+ that.parentData = {
+ element: $( document ),
+ left: 0,
+ top: 0,
+ width: $( document ).width(),
+ height: $( document ).height() || document.body.parentNode.scrollHeight
+ };
+ } else {
+ element = $( ce );
+ p = [];
+ $([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) {
+ p[ i ] = that._num( element.css( "padding" + name ) );
+ });
+
+ that.containerOffset = element.offset();
+ that.containerPosition = element.position();
+ that.containerSize = {
+ height: ( element.innerHeight() - p[ 3 ] ),
+ width: ( element.innerWidth() - p[ 1 ] )
+ };
+
+ co = that.containerOffset;
+ ch = that.containerSize.height;
+ cw = that.containerSize.width;
+ width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
+ height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
+
+ that.parentData = {
+ element: ce,
+ left: co.left,
+ top: co.top,
+ width: width,
+ height: height
+ };
+ }
+ },
+
+ resize: function( event ) {
+ var woset, hoset, isParent, isOffsetRelative,
+ that = $( this ).resizable( "instance" ),
+ o = that.options,
+ co = that.containerOffset,
+ cp = that.position,
+ pRatio = that._aspectRatio || event.shiftKey,
+ cop = {
+ top: 0,
+ left: 0
+ },
+ ce = that.containerElement,
+ continueResize = true;
+
+ if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
+ cop = co;
+ }
+
+ if ( cp.left < ( that._helper ? co.left : 0 ) ) {
+ that.size.width = that.size.width +
+ ( that._helper ?
+ ( that.position.left - co.left ) :
+ ( that.position.left - cop.left ) );
+
+ if ( pRatio ) {
+ that.size.height = that.size.width / that.aspectRatio;
+ continueResize = false;
+ }
+ that.position.left = o.helper ? co.left : 0;
+ }
+
+ if ( cp.top < ( that._helper ? co.top : 0 ) ) {
+ that.size.height = that.size.height +
+ ( that._helper ?
+ ( that.position.top - co.top ) :
+ that.position.top );
+
+ if ( pRatio ) {
+ that.size.width = that.size.height * that.aspectRatio;
+ continueResize = false;
+ }
+ that.position.top = that._helper ? co.top : 0;
+ }
+
+ isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
+ isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
+
+ if ( isParent && isOffsetRelative ) {
+ that.offset.left = that.parentData.left + that.position.left;
+ that.offset.top = that.parentData.top + that.position.top;
+ } else {
+ that.offset.left = that.element.offset().left;
+ that.offset.top = that.element.offset().top;
+ }
+
+ woset = Math.abs( that.sizeDiff.width +
+ (that._helper ?
+ that.offset.left - cop.left :
+ (that.offset.left - co.left)) );
+
+ hoset = Math.abs( that.sizeDiff.height +
+ (that._helper ?
+ that.offset.top - cop.top :
+ (that.offset.top - co.top)) );
+
+ if ( woset + that.size.width >= that.parentData.width ) {
+ that.size.width = that.parentData.width - woset;
+ if ( pRatio ) {
+ that.size.height = that.size.width / that.aspectRatio;
+ continueResize = false;
+ }
+ }
+
+ if ( hoset + that.size.height >= that.parentData.height ) {
+ that.size.height = that.parentData.height - hoset;
+ if ( pRatio ) {
+ that.size.width = that.size.height * that.aspectRatio;
+ continueResize = false;
+ }
+ }
+
+ if ( !continueResize ) {
+ that.position.left = that.prevPosition.left;
+ that.position.top = that.prevPosition.top;
+ that.size.width = that.prevSize.width;
+ that.size.height = that.prevSize.height;
+ }
+ },
+
+ stop: function() {
+ var that = $( this ).resizable( "instance" ),
+ o = that.options,
+ co = that.containerOffset,
+ cop = that.containerPosition,
+ ce = that.containerElement,
+ helper = $( that.helper ),
+ ho = helper.offset(),
+ w = helper.outerWidth() - that.sizeDiff.width,
+ h = helper.outerHeight() - that.sizeDiff.height;
+
+ if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
+ $( this ).css({
+ left: ho.left - cop.left - co.left,
+ width: w,
+ height: h
+ });
+ }
+
+ if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
+ $( this ).css({
+ left: ho.left - cop.left - co.left,
+ width: w,
+ height: h
+ });
+ }
+ }
+});
+
+$.ui.plugin.add("resizable", "alsoResize", {
+
+ start: function() {
+ var that = $(this).resizable( "instance" ),
+ o = that.options;
+
+ $(o.alsoResize).each(function() {
+ var el = $(this);
+ el.data("ui-resizable-alsoresize", {
+ width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
+ left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
+ });
+ });
+ },
+
+ resize: function(event, ui) {
+ var that = $(this).resizable( "instance" ),
+ o = that.options,
+ os = that.originalSize,
+ op = that.originalPosition,
+ delta = {
+ height: (that.size.height - os.height) || 0,
+ width: (that.size.width - os.width) || 0,
+ top: (that.position.top - op.top) || 0,
+ left: (that.position.left - op.left) || 0
+ };
+
+ $(o.alsoResize).each(function() {
+ var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
+ css = el.parents(ui.originalElement[0]).length ?
+ [ "width", "height" ] :
+ [ "width", "height", "top", "left" ];
+
+ $.each(css, function(i, prop) {
+ var sum = (start[prop] || 0) + (delta[prop] || 0);
+ if (sum && sum >= 0) {
+ style[prop] = sum || null;
+ }
+ });
+
+ el.css(style);
+ });
+ },
+
+ stop: function() {
+ $(this).removeData("resizable-alsoresize");
+ }
+});
+
+$.ui.plugin.add("resizable", "ghost", {
+
+ start: function() {
+
+ var that = $(this).resizable( "instance" ), o = that.options, cs = that.size;
+
+ that.ghost = that.originalElement.clone();
+ that.ghost
+ .css({
+ opacity: 0.25,
+ display: "block",
+ position: "relative",
+ height: cs.height,
+ width: cs.width,
+ margin: 0,
+ left: 0,
+ top: 0
+ })
+ .addClass("ui-resizable-ghost")
+ .addClass(typeof o.ghost === "string" ? o.ghost : "");
+
+ that.ghost.appendTo(that.helper);
+
+ },
+
+ resize: function() {
+ var that = $(this).resizable( "instance" );
+ if (that.ghost) {
+ that.ghost.css({
+ position: "relative",
+ height: that.size.height,
+ width: that.size.width
+ });
+ }
+ },
+
+ stop: function() {
+ var that = $(this).resizable( "instance" );
+ if (that.ghost && that.helper) {
+ that.helper.get(0).removeChild(that.ghost.get(0));
+ }
+ }
+
+});
+
+$.ui.plugin.add("resizable", "grid", {
+
+ resize: function() {
+ var outerDimensions,
+ that = $(this).resizable( "instance" ),
+ o = that.options,
+ cs = that.size,
+ os = that.originalSize,
+ op = that.originalPosition,
+ a = that.axis,
+ grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
+ gridX = (grid[0] || 1),
+ gridY = (grid[1] || 1),
+ ox = Math.round((cs.width - os.width) / gridX) * gridX,
+ oy = Math.round((cs.height - os.height) / gridY) * gridY,
+ newWidth = os.width + ox,
+ newHeight = os.height + oy,
+ isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
+ isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
+ isMinWidth = o.minWidth && (o.minWidth > newWidth),
+ isMinHeight = o.minHeight && (o.minHeight > newHeight);
+
+ o.grid = grid;
+
+ if (isMinWidth) {
+ newWidth += gridX;
+ }
+ if (isMinHeight) {
+ newHeight += gridY;
+ }
+ if (isMaxWidth) {
+ newWidth -= gridX;
+ }
+ if (isMaxHeight) {
+ newHeight -= gridY;
+ }
+
+ if (/^(se|s|e)$/.test(a)) {
+ that.size.width = newWidth;
+ that.size.height = newHeight;
+ } else if (/^(ne)$/.test(a)) {
+ that.size.width = newWidth;
+ that.size.height = newHeight;
+ that.position.top = op.top - oy;
+ } else if (/^(sw)$/.test(a)) {
+ that.size.width = newWidth;
+ that.size.height = newHeight;
+ that.position.left = op.left - ox;
+ } else {
+ if ( newHeight - gridY <= 0 || newWidth - gridX <= 0) {
+ outerDimensions = that._getPaddingPlusBorderDimensions( this );
+ }
+
+ if ( newHeight - gridY > 0 ) {
+ that.size.height = newHeight;
+ that.position.top = op.top - oy;
+ } else {
+ newHeight = gridY - outerDimensions.height;
+ that.size.height = newHeight;
+ that.position.top = op.top + os.height - newHeight;
+ }
+ if ( newWidth - gridX > 0 ) {
+ that.size.width = newWidth;
+ that.position.left = op.left - ox;
+ } else {
+ newWidth = gridX - outerDimensions.width;
+ that.size.width = newWidth;
+ that.position.left = op.left + os.width - newWidth;
+ }
+ }
+ }
+
+});
+
+return $.ui.resizable;
+
+}));
diff --git a/deployed/windwalker/media/windwalker/js/jquery/jquery.ui.resizable.min.js b/deployed/windwalker/media/windwalker/js/jquery/jquery.ui.resizable.min.js
new file mode 100644
index 00000000..f62b49bd
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/jquery/jquery.ui.resizable.min.js
@@ -0,0 +1 @@
+(function(factory){if(typeof define==="function"&&define.amd){define(["jquery","./core","./mouse","./widget"],factory)}else factory(jQuery)}(function($){$.widget("ui.resizable",$.ui.mouse,{version:"1.11.4",widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(value){return parseInt(value,10)||0},_isNumber:function(value){return!isNaN(parseInt(value,10))},_hasScroll:function(el,a){if($(el).css("overflow")==="hidden")return false;var scroll=(a&&a==="left")?"scrollLeft":"scrollTop",has=false;if(el[scroll]>0)return true;el[scroll]=1;has=(el[scroll]>0);el[scroll]=0;return has},_create:function(){var n,i,handle,axis,hname,that=this,o=this.options;this.element.addClass("ui-resizable");$.extend(this,{_aspectRatio:!!(o.aspectRatio),aspectRatio:o.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:o.helper||o.ghost||o.animate?o.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)){this.element.wrap($("
").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()};this.handles=o.handles||(!$(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});this._handles=$();if(this.handles.constructor===String){if(this.handles==="all")this.handles="n,e,s,w,se,sw,ne,nw";n=this.handles.split(",");this.handles={};for(i=0;i");axis.css({zIndex:o.zIndex});if("se"===handle)axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[handle]=".ui-resizable-"+handle;this.element.append(axis)}};this._renderAxis=function(target){var i,axis,padPos,padWrapper;target=target||this.element;for(i in this.handles){if(this.handles[i].constructor===String){this.handles[i]=this.element.children(this.handles[i]).first().show()}else if(this.handles[i].jquery||this.handles[i].nodeType){this.handles[i]=$(this.handles[i]);this._on(this.handles[i],{mousedown:that._mouseDown})};if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)){axis=$(this.handles[i],this.element);padWrapper=/sw|ne|nw|se|n|s/.test(i)?axis.outerHeight():axis.outerWidth();padPos=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");target.css(padPos,padWrapper);this._proportionallyResize()};this._handles=this._handles.add(this.handles[i])}};this._renderAxis(this.element);this._handles=this._handles.add(this.element.find(".ui-resizable-handle"));this._handles.disableSelection();this._handles.mouseover(function(){if(!that.resizing){if(this.className)axis=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);that.axis=axis&&axis[1]?axis[1]:"se"}});if(o.autoHide){this._handles.hide();$(this.element).addClass("ui-resizable-autohide").mouseenter(function(){if(o.disabled)return;$(this).removeClass("ui-resizable-autohide");that._handles.show()}).mouseleave(function(){if(o.disabled)return;if(!that.resizing){$(this).addClass("ui-resizable-autohide");that._handles.hide()}})};this._mouseInit()},_destroy:function(){this._mouseDestroy();var wrapper,_destroy=function(exp){$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){_destroy(this.element);wrapper=this.element;this.originalElement.css({position:wrapper.css("position"),width:wrapper.outerWidth(),height:wrapper.outerHeight(),top:wrapper.css("top"),left:wrapper.css("left")}).insertAfter(wrapper);wrapper.remove()};this.originalElement.css("resize",this.originalResizeStyle);_destroy(this.originalElement);return this},_mouseCapture:function(event){var i,handle,capture=false;for(i in this.handles){handle=$(this.handles[i])[0];if(handle===event.target||$.contains(handle,event.target))capture=true};return!this.options.disabled&&capture},_mouseStart:function(event){var curleft,curtop,cursor,o=this.options,el=this.element;this.resizing=true;this._renderProxy();curleft=this._num(this.helper.css("left"));curtop=this._num(this.helper.css("top"));if(o.containment){curleft+=$(o.containment).scrollLeft()||0;curtop+=$(o.containment).scrollTop()||0};this.offset=this.helper.offset();this.position={left:curleft,top:curtop};this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:el.width(),height:el.height()};this.originalSize=this._helper?{width:el.outerWidth(),height:el.outerHeight()}:{width:el.width(),height:el.height()};this.sizeDiff={width:el.outerWidth()-el.width(),height:el.outerHeight()-el.height()};this.originalPosition={left:curleft,top:curtop};this.originalMousePosition={left:event.pageX,top:event.pageY};this.aspectRatio=(typeof o.aspectRatio==="number")?o.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);cursor=$(".ui-resizable-"+this.axis).css("cursor");$("body").css("cursor",cursor==="auto"?this.axis+"-resize":cursor);el.addClass("ui-resizable-resizing");this._propagate("start",event);return true},_mouseDrag:function(event){var data,props,smp=this.originalMousePosition,a=this.axis,dx=(event.pageX-smp.left)||0,dy=(event.pageY-smp.top)||0,trigger=this._change[a];this._updatePrevProperties();if(!trigger)return false;data=trigger.apply(this,[event,dx,dy]);this._updateVirtualBoundaries(event.shiftKey);if(this._aspectRatio||event.shiftKey)data=this._updateRatio(data,event);data=this._respectSize(data,event);this._updateCache(data);this._propagate("resize",event);props=this._applyChanges();if(!this._helper&&this._proportionallyResizeElements.length)this._proportionallyResize();if(!$.isEmptyObject(props)){this._updatePrevProperties();this._trigger("resize",event,this.ui());this._applyChanges()};return false},_mouseStop:function(event){this.resizing=false;var pr,ista,soffseth,soffsetw,s,left,top,o=this.options,that=this;if(this._helper){pr=this._proportionallyResizeElements;ista=pr.length&&/textarea/i.test(pr[0].nodeName);soffseth=ista&&this._hasScroll(pr[0],"left")?0:that.sizeDiff.height;soffsetw=ista?0:that.sizeDiff.width;s={width:(that.helper.width()-soffsetw),height:(that.helper.height()-soffseth)};left=(parseInt(that.element.css("left"),10)+(that.position.left-that.originalPosition.left))||null;top=(parseInt(that.element.css("top"),10)+(that.position.top-that.originalPosition.top))||null;if(!o.animate)this.element.css($.extend(s,{top:top,left:left}));that.helper.height(that.size.height);that.helper.width(that.size.width);if(this._helper&&!o.animate)this._proportionallyResize()};$("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",event);if(this._helper)this.helper.remove();return false},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left};this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var props={};if(this.position.top!==this.prevPosition.top)props.top=this.position.top+"px";if(this.position.left!==this.prevPosition.left)props.left=this.position.left+"px";if(this.size.width!==this.prevSize.width)props.width=this.size.width+"px";if(this.size.height!==this.prevSize.height)props.height=this.size.height+"px";this.helper.css(props);return props},_updateVirtualBoundaries:function(forceAspectRatio){var pMinWidth,pMaxWidth,pMinHeight,pMaxHeight,b,o=this.options;b={minWidth:this._isNumber(o.minWidth)?o.minWidth:0,maxWidth:this._isNumber(o.maxWidth)?o.maxWidth:Infinity,minHeight:this._isNumber(o.minHeight)?o.minHeight:0,maxHeight:this._isNumber(o.maxHeight)?o.maxHeight:Infinity};if(this._aspectRatio||forceAspectRatio){pMinWidth=b.minHeight*this.aspectRatio;pMinHeight=b.minWidth/this.aspectRatio;pMaxWidth=b.maxHeight*this.aspectRatio;pMaxHeight=b.maxWidth/this.aspectRatio;if(pMinWidth>b.minWidth)b.minWidth=pMinWidth;if(pMinHeight>b.minHeight)b.minHeight=pMinHeight;if(pMaxWidthdata.width),isminh=this._isNumber(data.height)&&o.minHeight&&(o.minHeight>data.height),dw=this.originalPosition.left+this.originalSize.width,dh=this.position.top+this.size.height,cw=/sw|nw|w/.test(a),ch=/nw|ne|n/.test(a);if(isminw)data.width=o.minWidth;if(isminh)data.height=o.minHeight;if(ismaxw)data.width=o.maxWidth;if(ismaxh)data.height=o.maxHeight;if(isminw&&cw)data.left=dw-o.minWidth;if(ismaxw&&cw)data.left=dw-o.maxWidth;if(isminh&&ch)data.top=dh-o.minHeight;if(ismaxh&&ch)data.top=dh-o.maxHeight;if(!data.width&&!data.height&&!data.left&&data.top){data.top=null}else if(!data.width&&!data.height&&!data.top&&data.left)data.left=null;return data},_getPaddingPlusBorderDimensions:function(element){var i=0,widths=[],borders=[element.css("borderTopWidth"),element.css("borderRightWidth"),element.css("borderBottomWidth"),element.css("borderLeftWidth")],paddings=[element.css("paddingTop"),element.css("paddingRight"),element.css("paddingBottom"),element.css("paddingLeft")];for(;i<4;i++){widths[i]=(parseInt(borders[i],10)||0);widths[i]+=(parseInt(paddings[i],10)||0)};return{height:widths[0]+widths[2],width:widths[1]+widths[3]}},_proportionallyResize:function(){if(!this._proportionallyResizeElements.length)return;var prel,i=0,element=this.helper||this.element;for(;i");this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++o.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(event,dx){return{width:this.originalSize.width+dx}},w:function(event,dx){var cs=this.originalSize,sp=this.originalPosition;return{left:sp.left+dx,width:cs.width-dx}},n:function(event,dx,dy){var cs=this.originalSize,sp=this.originalPosition;return{top:sp.top+dy,height:cs.height-dy}},s:function(event,dx,dy){return{height:this.originalSize.height+dy}},se:function(event,dx,dy){return $.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[event,dx,dy]))},sw:function(event,dx,dy){return $.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[event,dx,dy]))},ne:function(event,dx,dy){return $.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[event,dx,dy]))},nw:function(event,dx,dy){return $.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[event,dx,dy]))}},_propagate:function(n,event){$.ui.plugin.call(this,n,[event,this.ui()]);(n!=="resize"&&this._trigger(n,event,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});$.ui.plugin.add("resizable","animate",{stop:function(event){var that=$(this).resizable("instance"),o=that.options,pr=that._proportionallyResizeElements,ista=pr.length&&/textarea/i.test(pr[0].nodeName),soffseth=ista&&that._hasScroll(pr[0],"left")?0:that.sizeDiff.height,soffsetw=ista?0:that.sizeDiff.width,style={width:(that.size.width-soffsetw),height:(that.size.height-soffseth)},left=(parseInt(that.element.css("left"),10)+(that.position.left-that.originalPosition.left))||null,top=(parseInt(that.element.css("top"),10)+(that.position.top-that.originalPosition.top))||null;that.element.animate($.extend(style,top&&left?{top:top,left:left}:{}),{duration:o.animateDuration,easing:o.animateEasing,step:function(){var data={width:parseInt(that.element.css("width"),10),height:parseInt(that.element.css("height"),10),top:parseInt(that.element.css("top"),10),left:parseInt(that.element.css("left"),10)};if(pr&&pr.length)$(pr[0]).css({width:data.width,height:data.height});that._updateCache(data);that._propagate("resize",event)}})}});$.ui.plugin.add("resizable","containment",{start:function(){var element,p,co,ch,cw,width,height,that=$(this).resizable("instance"),o=that.options,el=that.element,oc=o.containment,ce=(oc instanceof $)?oc.get(0):(/parent/.test(oc))?el.parent().get(0):oc;if(!ce)return;that.containerElement=$(ce);if(/document/.test(oc)||oc===document){that.containerOffset={left:0,top:0};that.containerPosition={left:0,top:0};that.parentData={element:$(document),left:0,top:0,width:$(document).width(),height:$(document).height()||document.body.parentNode.scrollHeight}}else{element=$(ce);p=[];$(["Top","Right","Left","Bottom"]).each(function(i,name){p[i]=that._num(element.css("padding"+name))});that.containerOffset=element.offset();that.containerPosition=element.position();that.containerSize={height:(element.innerHeight()-p[3]),width:(element.innerWidth()-p[1])};co=that.containerOffset;ch=that.containerSize.height;cw=that.containerSize.width;width=(that._hasScroll(ce,"left")?ce.scrollWidth:cw);height=(that._hasScroll(ce)?ce.scrollHeight:ch);that.parentData={element:ce,left:co.left,top:co.top,width:width,height:height}}},resize:function(event){var woset,hoset,isParent,isOffsetRelative,that=$(this).resizable("instance"),o=that.options,co=that.containerOffset,cp=that.position,pRatio=that._aspectRatio||event.shiftKey,cop={top:0,left:0},ce=that.containerElement,continueResize=true;if(ce[0]!==document&&/static/.test(ce.css("position")))cop=co;if(cp.left<(that._helper?co.left:0)){that.size.width=that.size.width+(that._helper?(that.position.left-co.left):(that.position.left-cop.left));if(pRatio){that.size.height=that.size.width/that.aspectRatio;continueResize=false};that.position.left=o.helper?co.left:0};if(cp.top<(that._helper?co.top:0)){that.size.height=that.size.height+(that._helper?(that.position.top-co.top):that.position.top);if(pRatio){that.size.width=that.size.height*that.aspectRatio;continueResize=false};that.position.top=that._helper?co.top:0};isParent=that.containerElement.get(0)===that.element.parent().get(0);isOffsetRelative=/relative|absolute/.test(that.containerElement.css("position"));if(isParent&&isOffsetRelative){that.offset.left=that.parentData.left+that.position.left;that.offset.top=that.parentData.top+that.position.top}else{that.offset.left=that.element.offset().left;that.offset.top=that.element.offset().top};woset=Math.abs(that.sizeDiff.width+(that._helper?that.offset.left-cop.left:(that.offset.left-co.left)));hoset=Math.abs(that.sizeDiff.height+(that._helper?that.offset.top-cop.top:(that.offset.top-co.top)));if(woset+that.size.width>=that.parentData.width){that.size.width=that.parentData.width-woset;if(pRatio){that.size.height=that.size.width/that.aspectRatio;continueResize=false}};if(hoset+that.size.height>=that.parentData.height){that.size.height=that.parentData.height-hoset;if(pRatio){that.size.width=that.size.height*that.aspectRatio;continueResize=false}};if(!continueResize){that.position.left=that.prevPosition.left;that.position.top=that.prevPosition.top;that.size.width=that.prevSize.width;that.size.height=that.prevSize.height}},stop:function(){var that=$(this).resizable("instance"),o=that.options,co=that.containerOffset,cop=that.containerPosition,ce=that.containerElement,helper=$(that.helper),ho=helper.offset(),w=helper.outerWidth()-that.sizeDiff.width,h=helper.outerHeight()-that.sizeDiff.height;if(that._helper&&!o.animate&&/relative/.test(ce.css("position")))$(this).css({left:ho.left-cop.left-co.left,width:w,height:h});if(that._helper&&!o.animate&&/static/.test(ce.css("position")))$(this).css({left:ho.left-cop.left-co.left,width:w,height:h})}});$.ui.plugin.add("resizable","alsoResize",{start:function(){var that=$(this).resizable("instance"),o=that.options;$(o.alsoResize).each(function(){var el=$(this);el.data("ui-resizable-alsoresize",{width:parseInt(el.width(),10),height:parseInt(el.height(),10),left:parseInt(el.css("left"),10),top:parseInt(el.css("top"),10)})})},resize:function(event,ui){var that=$(this).resizable("instance"),o=that.options,os=that.originalSize,op=that.originalPosition,delta={height:(that.size.height-os.height)||0,width:(that.size.width-os.width)||0,top:(that.position.top-op.top)||0,left:(that.position.left-op.left)||0};$(o.alsoResize).each(function(){var el=$(this),start=$(this).data("ui-resizable-alsoresize"),style={},css=el.parents(ui.originalElement[0]).length?["width","height"]:["width","height","top","left"];$.each(css,function(i,prop){var sum=(start[prop]||0)+(delta[prop]||0);if(sum&&sum>=0)style[prop]=sum||null});el.css(style)})},stop:function(){$(this).removeData("resizable-alsoresize")}});$.ui.plugin.add("resizable","ghost",{start:function(){var that=$(this).resizable("instance"),o=that.options,cs=that.size;that.ghost=that.originalElement.clone();that.ghost.css({opacity:0.25,display:"block",position:"relative",height:cs.height,width:cs.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof o.ghost==="string"?o.ghost:"");that.ghost.appendTo(that.helper)},resize:function(){var that=$(this).resizable("instance");if(that.ghost)that.ghost.css({position:"relative",height:that.size.height,width:that.size.width})},stop:function(){var that=$(this).resizable("instance");if(that.ghost&&that.helper)that.helper.get(0).removeChild(that.ghost.get(0))}});$.ui.plugin.add("resizable","grid",{resize:function(){var outerDimensions,that=$(this).resizable("instance"),o=that.options,cs=that.size,os=that.originalSize,op=that.originalPosition,a=that.axis,grid=typeof o.grid==="number"?[o.grid,o.grid]:o.grid,gridX=(grid[0]||1),gridY=(grid[1]||1),ox=Math.round((cs.width-os.width)/gridX)*gridX,oy=Math.round((cs.height-os.height)/gridY)*gridY,newWidth=os.width+ox,newHeight=os.height+oy,isMaxWidth=o.maxWidth&&(o.maxWidthnewWidth),isMinHeight=o.minHeight&&(o.minHeight>newHeight);o.grid=grid;if(isMinWidth)newWidth+=gridX;if(isMinHeight)newHeight+=gridY;if(isMaxWidth)newWidth-=gridX;if(isMaxHeight)newHeight-=gridY;if(/^(se|s|e)$/.test(a)){that.size.width=newWidth;that.size.height=newHeight}else if(/^(ne)$/.test(a)){that.size.width=newWidth;that.size.height=newHeight;that.position.top=op.top-oy}else if(/^(sw)$/.test(a)){that.size.width=newWidth;that.size.height=newHeight;that.position.left=op.left-ox}else{if(newHeight-gridY<=0||newWidth-gridX<=0)outerDimensions=that._getPaddingPlusBorderDimensions(this);if(newHeight-gridY>0){that.size.height=newHeight;that.position.top=op.top-oy}else{newHeight=gridY-outerDimensions.height;that.size.height=newHeight;that.position.top=op.top+os.height-newHeight};if(newWidth-gridX>0){that.size.width=newWidth;that.position.left=op.left-ox}else{newWidth=gridX-outerDimensions.width;that.size.width=newWidth;that.position.left=op.left+os.width-newWidth}}}});return $.ui.resizable}))
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/jquery/jquery.ui.selectable.js b/deployed/windwalker/media/windwalker/js/jquery/jquery.ui.selectable.js
new file mode 100644
index 00000000..63da644b
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/jquery/jquery.ui.selectable.js
@@ -0,0 +1,287 @@
+/*!
+ * jQuery UI Selectable 1.11.4
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/selectable/
+ */
+(function( factory ) {
+ if ( typeof define === "function" && define.amd ) {
+
+ // AMD. Register as an anonymous module.
+ define([
+ "jquery",
+ "./core",
+ "./mouse",
+ "./widget"
+ ], factory );
+ } else {
+
+ // Browser globals
+ factory( jQuery );
+ }
+}(function( $ ) {
+
+return $.widget("ui.selectable", $.ui.mouse, {
+ version: "1.11.4",
+ options: {
+ appendTo: "body",
+ autoRefresh: true,
+ distance: 0,
+ filter: "*",
+ tolerance: "touch",
+
+ // callbacks
+ selected: null,
+ selecting: null,
+ start: null,
+ stop: null,
+ unselected: null,
+ unselecting: null
+ },
+ _create: function() {
+ var selectees,
+ that = this;
+
+ this.element.addClass("ui-selectable");
+
+ this.dragged = false;
+
+ // cache selectee children based on filter
+ this.refresh = function() {
+ selectees = $(that.options.filter, that.element[0]);
+ selectees.addClass("ui-selectee");
+ selectees.each(function() {
+ var $this = $(this),
+ pos = $this.offset();
+ $.data(this, "selectable-item", {
+ element: this,
+ element: $this,
+ left: pos.left,
+ top: pos.top,
+ right: pos.left + $this.outerWidth(),
+ bottom: pos.top + $this.outerHeight(),
+ startselected: false,
+ selected: $this.hasClass("ui-selected"),
+ selecting: $this.hasClass("ui-selecting"),
+ unselecting: $this.hasClass("ui-unselecting")
+ });
+ });
+ };
+ this.refresh();
+
+ this.selectees = selectees.addClass("ui-selectee");
+
+ this._mouseInit();
+
+ this.helper = $("
");
+ },
+
+ _destroy: function() {
+ this.selectees
+ .removeClass("ui-selectee")
+ .removeData("selectable-item");
+ this.element
+ .removeClass("ui-selectable ui-selectable-disabled");
+ this._mouseDestroy();
+ },
+
+ _mouseStart: function(event) {
+ var that = this,
+ options = this.options;
+
+ this.opos = [ event.pageX, event.pageY ];
+
+ if (this.options.disabled) {
+ return;
+ }
+
+ this.selectees = $(options.filter, this.element[0]);
+
+ this._trigger("start", event);
+
+ $(options.appendTo).append(this.helper);
+ // position helper (lasso)
+ this.helper.css({
+ "left": event.pageX,
+ "top": event.pageY,
+ "width": 0,
+ "height": 0
+ });
+
+ if (options.autoRefresh) {
+ this.refresh();
+ }
+
+ this.selectees.filter(".ui-selected").each(function() {
+ var selectee = $.data(this, "selectable-item");
+ selectee.startselected = true;
+ if (!event.metaKey && !event.ctrlKey) {
+ selectee.element.removeClass("ui-selected");
+ selectee.selected = false;
+ selectee.element.addClass("ui-unselecting");
+ selectee.unselecting = true;
+ // selectable UNSELECTING callback
+ that._trigger("unselecting", event, {
+ unselecting: selectee.element
+ });
+ }
+ });
+
+ $(event.target).parents().addBack().each(function() {
+ var doSelect,
+ selectee = $.data(this, "selectable-item");
+ if (selectee) {
+ doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.element.hasClass("ui-selected");
+ selectee.element
+ .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
+ .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
+ selectee.unselecting = !doSelect;
+ selectee.selecting = doSelect;
+ selectee.selected = doSelect;
+ // selectable (UN)SELECTING callback
+ if (doSelect) {
+ that._trigger("selecting", event, {
+ selecting: selectee.element
+ });
+ } else {
+ that._trigger("unselecting", event, {
+ unselecting: selectee.element
+ });
+ }
+ return false;
+ }
+ });
+
+ },
+
+ _mouseDrag: function(event) {
+
+ this.dragged = true;
+
+ if (this.options.disabled) {
+ return;
+ }
+
+ var tmp,
+ that = this,
+ options = this.options,
+ x1 = this.opos[0],
+ y1 = this.opos[1],
+ x2 = event.pageX,
+ y2 = event.pageY;
+
+ if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
+ if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
+ this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 });
+
+ this.selectees.each(function() {
+ var selectee = $.data(this, "selectable-item"),
+ hit = false;
+
+ //prevent helper from being selected if appendTo: selectable
+ if (!selectee || selectee.element === that.element[0]) {
+ return;
+ }
+
+ if (options.tolerance === "touch") {
+ hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
+ } else if (options.tolerance === "fit") {
+ hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
+ }
+
+ if (hit) {
+ // SELECT
+ if (selectee.selected) {
+ selectee.element.removeClass("ui-selected");
+ selectee.selected = false;
+ }
+ if (selectee.unselecting) {
+ selectee.element.removeClass("ui-unselecting");
+ selectee.unselecting = false;
+ }
+ if (!selectee.selecting) {
+ selectee.element.addClass("ui-selecting");
+ selectee.selecting = true;
+ // selectable SELECTING callback
+ that._trigger("selecting", event, {
+ selecting: selectee.element
+ });
+ }
+ } else {
+ // UNSELECT
+ if (selectee.selecting) {
+ if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
+ selectee.element.removeClass("ui-selecting");
+ selectee.selecting = false;
+ selectee.element.addClass("ui-selected");
+ selectee.selected = true;
+ } else {
+ selectee.element.removeClass("ui-selecting");
+ selectee.selecting = false;
+ if (selectee.startselected) {
+ selectee.element.addClass("ui-unselecting");
+ selectee.unselecting = true;
+ }
+ // selectable UNSELECTING callback
+ that._trigger("unselecting", event, {
+ unselecting: selectee.element
+ });
+ }
+ }
+ if (selectee.selected) {
+ if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
+ selectee.element.removeClass("ui-selected");
+ selectee.selected = false;
+
+ selectee.element.addClass("ui-unselecting");
+ selectee.unselecting = true;
+ // selectable UNSELECTING callback
+ that._trigger("unselecting", event, {
+ unselecting: selectee.element
+ });
+ }
+ }
+ }
+ });
+
+ return false;
+ },
+
+ _mouseStop: function(event) {
+ var that = this;
+
+ this.dragged = false;
+
+ $(".ui-unselecting", this.element[0]).each(function() {
+ var selectee = $.data(this, "selectable-item");
+ selectee.element.removeClass("ui-unselecting");
+ selectee.unselecting = false;
+ selectee.startselected = false;
+ that._trigger("unselected", event, {
+ unselected: selectee.element
+ });
+ });
+ $(".ui-selecting", this.element[0]).each(function() {
+ var selectee = $.data(this, "selectable-item");
+ selectee.element.removeClass("ui-selecting").addClass("ui-selected");
+ selectee.selecting = false;
+ selectee.selected = true;
+ selectee.startselected = true;
+ that._trigger("selected", event, {
+ selected: selectee.element
+ });
+ });
+ this._trigger("stop", event);
+
+ this.helper.remove();
+
+ return false;
+ }
+
+});
+
+}));
diff --git a/deployed/windwalker/media/windwalker/js/jquery/jquery.ui.selectable.min.js b/deployed/windwalker/media/windwalker/js/jquery/jquery.ui.selectable.min.js
new file mode 100644
index 00000000..a6ea60a0
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/jquery/jquery.ui.selectable.min.js
@@ -0,0 +1 @@
+(function(factory){if(typeof define==="function"&&define.amd){define(["jquery","./core","./mouse","./widget"],factory)}else factory(jQuery)}(function($){return $.widget("ui.selectable",$.ui.mouse,{version:"1.11.4",options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var selectees,that=this;this.element.addClass("ui-selectable");this.dragged=false;this.refresh=function(){selectees=$(that.options.filter,that.element[0]);selectees.addClass("ui-selectee");selectees.each(function(){var $this=$(this),pos=$this.offset();$.data(this,"selectable-item",{element:this,element:$this,left:pos.left,top:pos.top,right:pos.left+$this.outerWidth(),bottom:pos.top+$this.outerHeight(),startselected:false,selected:$this.hasClass("ui-selected"),selecting:$this.hasClass("ui-selecting"),unselecting:$this.hasClass("ui-unselecting")})})};this.refresh();this.selectees=selectees.addClass("ui-selectee");this._mouseInit();this.helper=$("
")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled");this._mouseDestroy()},_mouseStart:function(event){var that=this,options=this.options;this.opos=[event.pageX,event.pageY];if(this.options.disabled)return;this.selectees=$(options.filter,this.element[0]);this._trigger("start",event);$(options.appendTo).append(this.helper);this.helper.css({left:event.pageX,top:event.pageY,width:0,height:0});if(options.autoRefresh)this.refresh();this.selectees.filter(".ui-selected").each(function(){var selectee=$.data(this,"selectable-item");selectee.startselected=true;if(!event.metaKey&&!event.ctrlKey){selectee.element.removeClass("ui-selected");selectee.selected=false;selectee.element.addClass("ui-unselecting");selectee.unselecting=true;that._trigger("unselecting",event,{unselecting:selectee.element})}});$(event.target).parents().addBack().each(function(){var doSelect,selectee=$.data(this,"selectable-item");if(selectee){doSelect=(!event.metaKey&&!event.ctrlKey)||!selectee.element.hasClass("ui-selected");selectee.element.removeClass(doSelect?"ui-unselecting":"ui-selected").addClass(doSelect?"ui-selecting":"ui-unselecting");selectee.unselecting=!doSelect;selectee.selecting=doSelect;selectee.selected=doSelect;if(doSelect){that._trigger("selecting",event,{selecting:selectee.element})}else that._trigger("unselecting",event,{unselecting:selectee.element});return false}})},_mouseDrag:function(event){this.dragged=true;if(this.options.disabled)return;var tmp,that=this,options=this.options,x1=this.opos[0],y1=this.opos[1],x2=event.pageX,y2=event.pageY;if(x1>x2){tmp=x2;x2=x1;x1=tmp};if(y1>y2){tmp=y2;y2=y1;y1=tmp};this.helper.css({left:x1,top:y1,width:x2-x1,height:y2-y1});this.selectees.each(function(){var selectee=$.data(this,"selectable-item"),hit=false;if(!selectee||selectee.element===that.element[0])return;if(options.tolerance==="touch"){hit=(!(selectee.left>x2||selectee.righty2||selectee.bottomx1&&selectee.righty1&&selectee.bottom select');
+ this.inputs = this.element.find('input, select, textarea');
+ this.submitButton = this.element.find('button.quickadd_submit');
+
+ this.options = $.extend(true, {}, defaultOptions, options);
+
+ this.options.option = this.options.quickadd_handler;
+ this.options.formctrl = element.selector.substr(1);
+
+ // Remove all required and set default
+ this.inputs.each(function (e) {
+ var $input = $(this);
+
+ $input.removeClass('required')
+ .removeAttr('required')
+ .removeAttr('aria-required');
+
+ $input.attr('default', $input.val());
+ });
+
+ this.registerEvents();
+ };
+
+ QuickAdd.prototype = {
+ /**
+ * Register Events.
+ */
+ registerEvents: function () {
+ var self = this;
+
+ this.submitButton.on('click', function (event) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ self.createItem();
+ });
+
+ this.inputs.on('keydown', function (event) {
+ if (event.keyCode == 13) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ if (event.ctrlKey || event.metaKey) {
+ self.createItem();
+ }
+ }
+ });
+ },
+
+ /**
+ * Create item ajax.
+ */
+ createItem: function () {
+ var data = {};
+ var self = this;
+
+ this.submitButton.attr('disabled', true);
+
+ $.each(this.options, function (i) {
+ data[i] = this;
+ });
+
+ $.each(this.inputs, function (i) {
+ var $input = $(this);
+
+ data[$input.attr('name')] = $input.val();
+ });
+
+ $.ajax({
+ url: 'index.php',
+ data: data,
+ dataType: 'json',
+ mwthod: 'POST'
+ }).done(function (data, status, jqXHR) {
+ if (data.Result) {
+ self.inputs.each(function (i) {
+ var $input = $(this);
+
+ $input.val($input.attr('default'));
+ });
+
+ // Hide Modal
+ self.element.modal('hide');
+
+ var optionText = data.data[self.options.value_field];
+ var optionValue = data.data[self.options.key_field];
+
+ // Add new Option in Select
+ if (self.select.length) {
+ self.select.append(
+ $('', {
+ text: optionText,
+ value: optionValue
+ })
+ );
+
+ self.select.val(optionValue);
+ }
+
+ // Add Title for Modal input
+ var selectId = '#' + self.options.formctrl.replace('_quickadd', '');
+ var modalName = $(selectId + '_name');
+ var modalId = $(selectId + '_id');
+
+ // Wait and highlight for chosen
+ var chzn = self.control.find('> .chzn-container .chzn-single span');
+
+ if (chzn.length > 0) {
+ setTimeout(function () {
+ self.select.trigger("liszt:updated");
+ $(chzn).effect('highlight');
+ }, 500);
+ }
+ else {
+ // Wait and highlight
+ setTimeout(function () {
+ $(self.select).effect('highlight');
+ }, 500);
+ }
+
+ // Wait and highlight for modal
+ if (modalName.length) {
+ setTimeout(function () {
+ modalName.attr('value', optionText);
+ modalId.attr('value', optionValue);
+ $(modalName).effect('highlight');
+ }, 500);
+ }
+ }
+ else {
+ alert(data.errorMsg);
+ }
+
+ }).fail(function (jqXHR, status, error) {
+ alert(status);
+ }).always(function () {
+ self.submitButton.attr('disabled', false);
+ });
+ }
+ };
+
+ /**
+ * Push to plugin.
+ *
+ * @param {Object} options
+ *
+ * @returns {*}
+ */
+ $.fn[plugin] = function (options) {
+ if (!$.data(this, "windwalker." + plugin)) {
+ $.data(this, "windwalker." + plugin, new QuickAdd(this, options));
+ }
+
+ return $.data(this, "windwalker." + plugin);
+ };
+
+})(jQuery);
diff --git a/deployed/windwalker/media/windwalker/js/quickadd.min.js b/deployed/windwalker/media/windwalker/js/quickadd.min.js
new file mode 100644
index 00000000..93f8828e
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/quickadd.min.js
@@ -0,0 +1 @@
+(function($){var plugin="quickadd";var defaultOptions={task:"quickAddAjax",ajax:1};var QuickAdd=function(element,options){this.element=element;this.control=element.parents(".controls");this.select=this.control.find("> select");this.inputs=this.element.find("input, select, textarea");this.submitButton=this.element.find("button.quickadd_submit");this.options=$.extend(true,{},defaultOptions,options);this.options.option=this.options.quickadd_handler;this.options.formctrl=element.selector.substr(1);this.inputs.each(function(e){var $input=$(this);$input.removeClass("required").removeAttr("required").removeAttr("aria-required");$input.attr("default",$input.val());});this.registerEvents();};QuickAdd.prototype={registerEvents:function(){var self=this;this.submitButton.on("click",function(event){event.preventDefault();event.stopPropagation();console.log("Hello");self.createItem();});this.inputs.on("keydown",function(event){if(event.keyCode==13){event.preventDefault();event.stopPropagation();if(event.ctrlKey||event.metaKey){self.createItem();}}});},createItem:function(){var data={};var self=this;this.submitButton.attr("disabled",true);$.each(this.options,function(i){data[i]=this;});$.each(this.inputs,function(i){var $input=$(this);data[$input.attr("name")]=$input.val();});$.ajax({url:"index.php",data:data,dataType:"json",mwthod:"POST"}).done(function(data,status,jqXHR){if(data.Result){self.inputs.each(function(i){var $input=$(this);$input.val($input.attr("default"));});self.element.modal("hide");var optionText=data.data[self.options.value_field];var optionValue=data.data[self.options.key_field];if(self.select.length){self.select.append($(" ",{text:optionText,value:optionValue}));self.select.val(optionValue);}var selectId="#"+self.options.formctrl.replace("_quickadd","");var modalName=$(selectId+"_name");var modalId=$(selectId+"_id");var chzn=self.control.find("> .chzn-container .chzn-single span");if(chzn.length>0){setTimeout(function(){self.select.trigger("liszt:updated");$(chzn).effect("highlight");},500);}else{setTimeout(function(){$(self.select).effect("highlight");},500);}if(modalName.length){setTimeout(function(){modalName.attr("value",optionText);modalId.attr("value",optionValue);$(modalName).effect("highlight");},500);}}else{alert(data.errorMsg);}}).fail(function(jqXHR,status,error){alert(status);}).always(function(){self.submitButton.attr("disabled",false);});}};$.fn[plugin]=function(options){if(!$.data(this,"windwalker."+plugin)){$.data(this,"windwalker."+plugin,new QuickAdd(this,options));}return $.data(this,"windwalker."+plugin);};})(jQuery);
\ No newline at end of file
diff --git a/deployed/windwalker/media/windwalker/js/windwalker-admin.js b/deployed/windwalker/media/windwalker/js/windwalker-admin.js
new file mode 100644
index 00000000..d4f7961d
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/windwalker-admin.js
@@ -0,0 +1,16 @@
+/**
+ * Part of Windwalker project.
+ *
+ * @copyright Copyright (C) 2016 {ORGANIZATION}. All rights reserved.
+ * @license GNU General Public License version 2 or later.
+ */
+
+;(function($)
+{
+ "use strict";
+
+ window.Windwalker = {
+
+ }
+
+})(jQuery);
diff --git a/deployed/windwalker/media/windwalker/js/windwalker.js b/deployed/windwalker/media/windwalker/js/windwalker.js
new file mode 100644
index 00000000..5b2966c7
--- /dev/null
+++ b/deployed/windwalker/media/windwalker/js/windwalker.js
@@ -0,0 +1,16 @@
+/**
+ * Part of Windwalker project.
+ *
+ * @copyright Copyright (C) 2016 {ORGANIZATION}. All rights reserved.
+ * @license GNU General Public License version 2 or later.
+ */
+
+;(function($)
+{
+ "use strict";
+
+ window.WindwalkerAdmin = {
+
+ }
+
+})(jQuery);