+ * [
+ * 'joins' => [
+ * "JOIN table2 t2 ON t2.id=t1.id"
+ * ],
+ * 'group' => 'field',
+ * 'having' => 'field',
+ * 'order' => 'field',
+ * 'start' => 0,
+ * 'limit' => 0
+ * ]
+ *
+ *
+ * @see Database::groups()
+ * @see Database::having()
+ * @see Database::order()
+ *
+ * @return string
+ */
+ public function flags($arrFlags)
+ {
+ $ret = '';
+
+ if (isset($arrFlags['group'])) {
+ $ret .= $this->groups($arrFlags['group']);
+ }
+
+ if (isset($arrFlags['having']) && is_array($arrFlags['having'])) {
+ $having = " HAVING";
+ foreach ($arrFlags['having'] as $x => $h) {
+ $having .= $this->parseClause($h, $x);
+ }
+ if (strlen($having) > strlen(" HAVING")) {
+ $ret .= $having;
+ }
+ }
+
+ if (isset($arrFlags['order'])) {
+ $ret .= $this->order($arrFlags['order']);
+ }
+
+ if (isset($arrFlags['limit']) && (is_string($arrFlags['limit']) || is_numeric($arrFlags['limit']))) {
+ $ret .= " LIMIT ";
+ if (isset($arrFlags['start']) && (is_string($arrFlags['start']) || is_numeric($arrFlags['start']))) {
+ $ret .= "{$arrFlags['start']},";
+ }
+ $ret .= "{$arrFlags['limit']}";
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Function to parse SQL GROUP BY statements
+ *
+ * @param mixed $groups
+ *
+ * @return string
+ */
+ public function groups($groups)
+ {
+ $ret = '';
+ if (is_array($groups) && count($groups)) {
+ $ret .= " GROUP BY";
+
+ foreach ($groups as $grp) {
+ $ret .= " $grp";
+
+ if ($grp != end($groups)) {
+ $ret .= ",";
+ }
+ }
+ } elseif (is_string($groups)) {
+ $ret .= " GROUP BY {$groups}";
+ } else {
+ throw (new Exception("Error in datatype for groups " . gettype($groups), E_ERROR));
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Function to parse SQL ORDER BY statements
+ *
+ * @param mixed $order
+ *
+ * @return string
+ */
+ public function order($order)
+ {
+ $ret = '';
+ if (is_array($order)) {
+ $ret .= " ORDER BY";
+
+ foreach ($order as $ord) {
+ $ret .= " {$ord['field']} {$ord['sort']}";
+
+ if ($ord != end($order)) {
+ $ret .= ",";
+ }
+ }
+ } elseif (is_string($order)) {
+ $ret .= " ORDER BY {$order}";
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Function to see if a constraint exists
+ *
+ * @param string $strConstraintId
+ *
+ * @return boolean
+ */
+ public function isConstraint($strConstraintId)
+ {
+ $res = $this->_c->query("SELECT * FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_NAME = '{$strConstraintId}'");
+
+ if ($res->num_rows) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Function to parse where and having clauses
+ *
+ * @param array $arrClause
+ * @param int $intIndex
+ */
+ public function parseClause($arrClause, $intIndex)
+ {
+ $ret = null;
+
+ $this->_logger->debug("Parsing clause", $arrClause);
+
+ if (! isset($arrClause['field']) && isset($arrClause['close-paren']) && $arrClause['close-paren']) {
+ $ret .= ")";
+ return $ret;
+ } elseif ($intIndex > 0 && ! isset($arrClause['sql_op'])) {
+ $this->_logger->warning("Missing sql_op field to identify how current and previous WHERE clause statements should be linked ('AND', 'OR', 'XOR', etc), skipped", [
+ 'clause' => implode(",", $arrClause)
+ ]);
+ return;
+ }
+
+ $op = '=';
+ if (isset($arrClause['op'])) {
+ $op = $arrClause['op'];
+ }
+
+ switch ($op) {
+ case self::BETWEEN:
+ if (! isset($arrClause['field']) || ! isset($arrClause['low']) || ! isset($arrClause['high'])) {
+ $this->_logger->warning("Missing field, low, or high for BETWEEN where clause, skipping");
+ return;
+ }
+ break;
+ default:
+ if (! isset($arrClause['field']) || ! isset($arrClause['value'])) {
+ $this->_logger->warning("Missing field or value for WHERE clause, skipping", $arrClause);
+ return;
+ }
+ }
+
+ if ($intIndex > 0) {
+ $ret .= " {$arrClause['sql_op']}";
+ }
+
+ if (isset($arrClause['open-paren']) && $arrClause['open-paren']) {
+ $ret .= " (";
+ }
+
+ if (isset($arrClause['backticks']) && ! $arrClause['backticks']) {
+ $field = $arrClause['field'];
+ } else {
+ $field = "`{$arrClause['field']}`";
+ }
+
+ if ($op == self::IN || $op == self::NOT_IN) {
+ if (is_string($arrClause['value'])) {
+ $ret .= " {$field} {$op} " . (strpos($arrClause['value'], '(') !== false ? $arrClause['value'] : "({$arrClause['value']})");
+ } elseif (is_array($arrClause['value'])) {
+ $ret .= " {$field} {$op} (" . implode(",", array_map([
+ $this,
+ '_escape'
+ ], $arrClause['value'])) . ")";
+ } else {
+ $this->_logger->error("Invalid datatype for IN WHERE clause, only string and array allowed " . gettype($arrClause['value']), $arrClause);
+ throw new Exception("Invalid datatype for IN WHERE clause", E_ERROR);
+ }
+ } elseif ($op == self::BETWEEN) {
+ $ret .= " {$field} BETWEEN {$this->_escape($arrClause['low'])} AND {$this->_escape($arrClause['high'])}";
+ } else {
+ if (isset($arrClause['escape']) && ! $arrClause['escape']) {
+ $value = $arrClause['value'];
+ } else {
+ $value = $this->_escape($arrClause['value']);
+ }
+
+ if (isset($arrClause['case_insensitive']) && $arrClause['case_insensitive']) {
+ $ret .= " LOWER({$field}) {$op} LOWER({$this->_escape($arrClause['value'])})";
+ } elseif (preg_match("/\(SELECT/", $arrClause['value'])) {
+ $ret .= " {$field} {$op} {$arrClause['value']}";
+ } else {
+ $ret .= " {$field} {$op} {$value}";
+ }
+ }
+
+ if (isset($arrClause['close-paren']) && $arrClause['close-paren']) {
+ $ret .= ")";
+ }
+
+ return $ret;
+ }
+}
diff --git a/inc/vendor/godsgood33/php-db/tests/DatabaseTest.php b/inc/vendor/godsgood33/php-db/tests/DatabaseTest.php
new file mode 100644
index 0000000..366efad
--- /dev/null
+++ b/inc/vendor/godsgood33/php-db/tests/DatabaseTest.php
@@ -0,0 +1,794 @@
+db = new Database(realpath(__DIR__));
+ // Database::$autorun = true;
+ }
+
+ public function testCanCreateDatabaseInstance()
+ {
+ $this->assertInstanceOf("Godsgood33\Php_Db\Database", $this->db);
+ }
+
+ public function testGetSchema()
+ {
+ $schema = $this->db->getSchema();
+ $this->assertEquals("db", $schema);
+ }
+
+ public function testSetSchemaWithNonExistentSchema()
+ {
+ $ret = $this->db->setSchema("george");
+ $this->assertFalse($ret);
+ }
+
+ public function testDatabaseConnection()
+ {
+ $this->assertTrue($this->db->isConnected());
+ }
+
+ public function testPassInMysqliConnection()
+ {
+ $conn = new mysqli(PHP_DB_SERVER, PHP_DB_USER, PHP_DB_PWD, PHP_DB_SCHEMA);
+ if ($conn->connect_errno) {
+ fwrite(STDOUT, $conn->connect_error);
+ }
+
+ $this->db = new Database(realpath(__DIR__), $conn);
+
+ $this->assertInstanceOf("Godsgood33\Php_Db\Database", $this->db);
+ }
+
+ public function testSetLogLevel()
+ {
+ $this->db->setLogLevel(Logger::DEBUG);
+ $this->assertEquals(Logger::DEBUG, $this->db->getLogLevel());
+ }
+
+ /**
+ * @expectedException TypeError
+ */
+ public function testSelectWithInvalidTableName()
+ {
+ $this->db->select(new stdClass());
+ }
+
+ public function testSelectWithNoParameters()
+ {
+ // query table with NO parameters
+ $this->db->select("test");
+ $this->assertEquals("SELECT * FROM test", $this->db->getSql());
+ }
+
+ public function testSelectWithNullFieldParameter()
+ {
+ // query table with null fields parameter
+ $this->db->select("test", null);
+ $this->assertEquals("SELECT * FROM test", $this->db->getSql());
+ }
+
+ public function testSelectWithOneArrayParameter()
+ {
+ // query table with one parameter
+ $this->db->select("test", [
+ 'id'
+ ]);
+ $this->assertEquals("SELECT `id` FROM test", $this->db->getSql());
+ }
+
+ public function testSelectWithTwoArrayParameters()
+ {
+ // query table with 2 parameters
+ $this->db->select("test", [
+ 'id',
+ 'name'
+ ]);
+ $this->assertEquals("SELECT `id`,`name` FROM test", $this->db->getSql());
+ }
+
+ public function testSelectWithOneStringParameter()
+ {
+ // query table with string parameter
+ $this->db->select("test", 'id');
+ $this->assertEquals("SELECT id FROM test", $this->db->getSql());
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testSelectWithStdClassParameter()
+ {
+ // query table with object parameter
+ $this->db->select("test", new stdClass());
+ $this->assertEquals("SELECT FROM test", $this->db->getSql());
+ }
+
+ /**
+ * @expectedException TypeError
+ */
+ public function testSelectWithNullWhereParameter()
+ {
+ // query table with null where parameter
+ $this->db->select("test", 'id', null);
+ $this->assertEquals("SELECT id FROM test", $this->db->getSql());
+ }
+
+ public function testSelectWithEmptyArrayWhereParameter()
+ {
+ // query table with empty array where paramter
+ $this->db->select("test", 'id', []);
+ $this->assertEquals("SELECT id FROM test", $this->db->getSql());
+ }
+
+ public function testSelectWithImcompleteWhereArrayParameter()
+ {
+ // query with incomplete WHERE clause
+ $this->db->select("test", 'id', [
+ [
+ 'field' => 'id'
+ ]
+ ]);
+ $this->assertEquals("SELECT id FROM test", $this->db->getSql());
+ }
+
+ public function testGroupWithString()
+ {
+ // $this->markTestIncomplete();
+
+ // query with single group by string
+ $sql = $this->db->groups('name');
+ $this->assertEquals(" GROUP BY name", $sql);
+ }
+
+ public function testGroupWithArray()
+ {
+ // query with array group by string
+ $sql = $this->db->groups([
+ 'name',
+ 'id'
+ ]);
+ $this->assertEquals(" GROUP BY name, id", $sql);
+ }
+
+ /**
+ * @expectedException Exception
+ */
+ public function testGroupWrongUnknownDataType()
+ {
+ // $this->markTestIncomplete();
+
+ // query group with invalid datatype (stdClass) should throw Exception
+ $this->db->groups(new stdClass());
+ }
+
+ public function testOrderWithString()
+ {
+ // $this->markTestIncomplete();
+
+ // query with single name order parameter
+ $sql = $this->db->order("name");
+ $this->assertEquals(" ORDER BY name", $sql);
+ }
+
+ public function testOrderWithArray()
+ {
+ // query with order array
+ $sql = $this->db->order([
+ [
+ 'field' => 'id',
+ 'sort' => 'ASC'
+ ],
+ [
+ 'field' => 'name',
+ 'sort' => 'DESC'
+ ]
+ ]);
+ $this->assertEquals(" ORDER BY id ASC, name DESC", $sql);
+ }
+
+ public function testOrderWithObject()
+ {
+ // query with invalid datatype (stdClass) will return empty string
+ $sql = $this->db->order(new stdClass());
+ $this->assertEquals("", $sql);
+ }
+
+ public function testFlags()
+ {
+ // $this->markTestIncomplete();
+
+ // query flags with all parameters
+ $sql = $this->db->flags([
+ 'group' => 'name',
+ 'order' => 'name',
+ 'having' => [
+ [
+ 'field' => 'id',
+ 'op' => '=',
+ 'value' => 1
+ ]
+ ],
+ 'limit' => '10',
+ 'start' => '5'
+ ]);
+ $this->assertEquals(" GROUP BY name HAVING `id` = '1' ORDER BY name LIMIT 5,10", $sql);
+ }
+
+ public function testCreateTemporaryTable()
+ {
+ $this->db->select("test");
+ $this->db->createTable('test2', true);
+ $this->assertEquals("CREATE TEMPORARY TABLE IF NOT EXISTS test2 AS (SELECT * FROM test)", $this->db->getSql());
+ }
+
+ public function testCreateTable()
+ {
+ // Database::$autorun = false;
+ $this->db->createTable('test', false, $this->db->select("test"));
+ $this->assertEquals("CREATE TABLE IF NOT EXISTS test AS (SELECT * FROM test)", $this->db->getSql());
+ // Database::$autorun = true;
+ }
+
+ public function testCreateTableWithArrayParameter()
+ {
+ $this->db->createTable("test", true, [
+ [
+ 'field' => 'id',
+ 'datatype' => 'int(11)',
+ 'option' => 'PRIMARY KEY'
+ ],
+ [
+ 'field' => 'name',
+ 'datatype' => 'varchar(100)',
+ 'default' => null
+ ],
+ [
+ 'field' => 'email',
+ 'datatype' => 'varchar(100)',
+ 'default' => ''
+ ]
+ ]);
+ $this->assertEquals("CREATE TEMPORARY TABLE IF NOT EXISTS test (`id` int(11) PRIMARY KEY,`name` varchar(100),`email` varchar(100) DEFAULT '')", $this->db->getSql());
+ }
+
+ public function testCreateTableJson()
+ {
+ $json = json_decode(file_get_contents(dirname(dirname(__FILE__)) . "/examples/create_table_json.json"));
+
+ $this->db->createTableJson($json->tables[0]);
+ $this->assertEquals("CREATE TABLE IF NOT EXISTS `settings` (`id` int(11) AUTO_INCREMENT NOT NULL,`meta_key` varchar(100) NOT NULL,`meta_value` mediumtext DEFAULT NULL, UNIQUE(`meta_key`), PRIMARY KEY(`id`))", $this->db->getSql());
+ }
+
+ public function testCreateTableJson2()
+ {
+ $json = json_decode(file_get_contents(dirname(dirname(__FILE__)) . "/examples/create_table_json.json"));
+
+ $this->db->createTableJson($json->tables[1]);
+ $this->assertEquals("CREATE TABLE IF NOT EXISTS `test` (`id` int(11) AUTO_INCREMENT NOT NULL,`fk` int(11) NOT NULL,`default` tinyint(1) DEFAULT '0',`enum` enum('1','2') DEFAULT '1', INDEX `default_idx` (`default`), CONSTRAINT `con_1` FOREIGN KEY (`fk`) REFERENCES `db`.`test` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, PRIMARY KEY(`id`,`fk`))", $this->db->getSql());
+ }
+
+ public function testCreateTableJson3()
+ {
+ $json = json_decode(file_get_contents(dirname(dirname(__FILE__)) . "/examples/create_table_json.json"));
+
+ $this->db->createTableJson($json->tables[2]);
+ $this->assertEquals("CREATE TABLE IF NOT EXISTS `test2` (`id` int(11) AUTO_INCREMENT NOT NULL, PRIMARY KEY(`id`))", $this->db->getSql());
+ }
+
+ public function testTableExists()
+ {
+ $tbl_count = $this->db->tableExists('db', 'settings');
+ $this->assertEquals(1, $tbl_count);
+ }
+
+ public function testMultipleTableExists()
+ {
+ $tbl_count = $this->db->tableExists('db', 'test%');
+ $this->assertEquals(2, $tbl_count);
+ }
+
+ public function testTableNotPresent()
+ {
+ $tbl_not_present = $this->db->tableExists('db', "users");
+ $this->assertFalse($tbl_not_present);
+ }
+
+ public function testAlterTableAddColumn()
+ {
+ $new = new stdClass();
+ $new->name = 'newCol';
+ $new->dataType = 'tinyint(1)';
+ $new->nn = false;
+ $new->default = null;
+
+ $this->db->alterTable('test', Database::ADD_COLUMN, $new);
+ $this->assertEquals("ALTER TABLE test ADD COLUMN `newCol` tinyint(1) DEFAULT NULL", $this->db->getSql());
+ }
+
+ public function testAlterTableModifyColumn()
+ {
+ $mod = new stdClass();
+ $mod->name = 'default';
+ $mod->new_name = 'default2';
+ $mod->dataType = 'int(1)';
+ $mod->nn = true;
+ $mod->default = 1;
+
+ $this->db->alterTable("test", Database::MODIFY_COLUMN, $mod);
+ $this->assertEquals("ALTER TABLE test MODIFY COLUMN `default` `default2` int(1) NOT NULL DEFAULT '1'", $this->db->getSql());
+ }
+
+ public function testAlterTableDropColumn()
+ {
+ $drop = new stdClass();
+ $drop->name = 'newCol';
+
+ $this->db->alterTable("test", Database::DROP_COLUMN, [
+ $drop
+ ]);
+ $this->assertEquals("ALTER TABLE test DROP COLUMN `newCol`", $this->db->getSql());
+ }
+
+ public function testSelectCountWithNoParameters()
+ {
+ $this->db->selectCount("test");
+ $this->assertEquals("SELECT COUNT(1) AS 'count' FROM test", $this->db->getSql());
+ }
+
+ /**
+ * @expectedException TypeError
+ */
+ public function testSelectCountWithStdClassParameterForTable()
+ {
+ $this->db->selectCount(new stdClass());
+ }
+
+ public function testSelectCountWithArrayWhereParameter()
+ {
+ $this->db->selectCount("test", [
+ [
+ 'field' => 'name',
+ 'value' => 'Ed'
+ ]
+ ], [
+ 'joins' => [
+ "JOIN settings s ON s.id = test.id"
+ ]
+ ]);
+ $this->assertEquals("SELECT COUNT(1) AS 'count' FROM test JOIN settings s ON s.id = test.id WHERE `name` = 'Ed'", $this->db->getSql());
+ }
+
+ public function testInsertWithOneElementArrayParameter()
+ {
+ // query with one parameter
+ $this->db->insert("test", [
+ 'id' => 1
+ ]);
+ $this->assertEquals("INSERT INTO test (`id`) VALUES ('1')", $this->db->getSql());
+ }
+
+ public function testInsertWithTwoElementArrayParameter()
+ {
+ // query with 2 parameters
+ $this->db->insert("test", [
+ 'id' => 1,
+ 'name' => 'Ed'
+ ], true);
+ $this->assertEquals("INSERT IGNORE INTO test (`id`,`name`) VALUES ('1','Ed')", $this->db->getSql());
+ }
+
+ public function testInsertWithSelectStatement()
+ {
+ // insert query using SELECT statement
+ $this->db->insert("test", "SELECT id FROM settings");
+ $this->assertEquals("INSERT INTO test SELECT id FROM settings", $this->db->getSql());
+ }
+
+ /**
+ * @expectedException TypeError
+ */
+ public function testInsertInvalidTableNameDataType()
+ {
+ $this->db->insert(new stdClass());
+ }
+
+ /**
+ * @expectedException Error
+ */
+ public function testInsertInvalidParameterDataType()
+ {
+ $this->db->insert("test", new stdClass());
+ }
+
+ public function testEInsert()
+ {
+ // extended insert query with fields and 2 items
+ $this->db->extendedInsert("test", [
+ 'id',
+ 'name'
+ ], [
+ [
+ 1,
+ 'Ed'
+ ],
+ [
+ 2,
+ 'Frank'
+ ]
+ ]);
+ $this->assertEquals("INSERT INTO test (`id`,`name`) VALUES ('1','Ed'),('2','Frank')", $this->db->getSql());
+ }
+
+ /**
+ * @expectedException TypeError
+ */
+ public function testEInsertInvalidTableNameDatatype()
+ {
+ $this->db->extendedInsert(new stdClass(), [], []);
+ }
+
+ /**
+ * @expectedException Error
+ */
+ public function testEInsertDifferentFieldValuePairs()
+ {
+ $this->db->extendedInsert('test', [
+ 'id',
+ 'name'
+ ], [
+ [
+ 1
+ ],
+ [
+ 2
+ ]
+ ]);
+ }
+
+ /**
+ * @expectedException Error
+ */
+ public function testEInsertDifferentFieldValuePairs2()
+ {
+ $this->db->extendedInsert('test', [
+ 'id',
+ 'name'
+ ], [
+ [
+ 1,
+ 'Ed'
+ ],
+ [
+ 2
+ ]
+ ]);
+ }
+
+ public function testUpdateWithOneElementArrayParameter()
+ {
+ $this->db->update('test', [
+ 'name' => 'Frank'
+ ]);
+ $this->assertEquals("UPDATE test SET `name`='Frank'", $this->db->getSql());
+ }
+
+ public function testUpdateWithOneElementAndWhereArray()
+ {
+ $this->db->update('test', [
+ 'name' => 'Frank'
+ ], [
+ [
+ 'field' => 'id',
+ 'value' => 1
+ ]
+ ]);
+ $this->assertEquals("UPDATE test SET `name`='Frank' WHERE `id` = '1'", $this->db->getSql());
+ }
+
+ public function testUpdateWithOneElementAndJoinClause()
+ {
+ $this->db->update('test t', [
+ 't.name' => 'Frank'
+ ], [], [
+ 'joins' => [
+ "JOIN settings s ON s.id=t.id"
+ ]
+ ]);
+ $this->assertEquals("UPDATE test t JOIN settings s ON s.id=t.id SET t.name='Frank'", $this->db->getSql());
+ }
+
+ public function testUpdateWithOneElementAndLimitClause()
+ {
+ $this->db->update('test', [
+ 'name' => 'Frank'
+ ], [], [
+ 'limit' => 1
+ ]);
+ $this->assertEquals("UPDATE test SET `name`='Frank' LIMIT 1", $this->db->getSql());
+ }
+
+ /**
+ * @expectedException TypeError
+ */
+ public function testUpdateInvalidTableNameDatatype()
+ {
+ $this->db->update(new stdClass(), []);
+ }
+
+ public function testEUpdateWithArrayList()
+ {
+ $this->db->extendedUpdate("test", "settings", "id", [
+ 'name'
+ ]);
+ $this->assertEquals("UPDATE test tbu INNER JOIN settings o USING (id) SET tbu.`name` = o.`name`", $this->db->getSql());
+ }
+
+ public function testEUpdateWithStringList()
+ {
+ $this->db->extendedUpdate("test", "settings", "id", "name");
+ $this->assertEquals("UPDATE test tbu INNER JOIN settings o USING (id) SET tbu.`name` = o.`name`", $this->db->getSql());
+ }
+
+ /**
+ * @expectedException Exception
+ */
+ public function testEUpdateInvalidParamDatatype()
+ {
+ $this->db->extendedUpdate('test', 'settings', 'id', new stdClass());
+ }
+
+ public function testReplace()
+ {
+ $this->db->replace("test", [
+ 'id' => 1
+ ]);
+ $this->assertEquals("REPLACE INTO test (`id`) VALUES ('1')", $this->db->getSql());
+ }
+
+ /**
+ * @expectedException TypeError
+ */
+ public function testReplaceInvalidTableNameDatatype()
+ {
+ $this->db->replace(new stdClass(), []);
+ }
+
+ public function testEReplace()
+ {
+ $this->db->extendedReplace("test", [
+ 'id',
+ 'name'
+ ], [
+ [
+ 1,
+ 'Ed'
+ ],
+ [
+ 2,
+ 'Frank'
+ ]
+ ]);
+ $this->assertEquals("REPLACE INTO test (`id`,`name`) VALUES ('1','Ed'),('2','Frank')", $this->db->getSql());
+ }
+
+ /**
+ * @expectedException TypeError
+ */
+ public function testEReplaceInvalidTableNameDatatype()
+ {
+ $this->db->extendedReplace(new stdClass(), [], []);
+ }
+
+ public function testFieldExists()
+ {
+ $id_exists = $this->db->fieldExists('test', 'id');
+ $this->assertTrue($id_exists);
+ }
+
+ public function testFieldDoesNotExist()
+ {
+ $phone_not_exists = $this->db->fieldExists('test', 'phone');
+ $this->assertFalse($phone_not_exists);
+ }
+
+ public function testFieldData()
+ {
+ $id = new stdClass();
+ $id->name = 'id';
+ $id->orgname = 'id';
+ $id->table = 'test2';
+ $id->orgtable = 'test2';
+ $id->def = null;
+ $id->db = 'db';
+ $id->catalog = 'def';
+ $id->max_length = 0;
+ $id->length = 11;
+ $id->charsetnr = 63;
+ $id->flags = 49667;
+ $id->type = 3;
+ $id->decimals = 0;
+
+ // query all fields in table
+ $fd = $this->db->fieldData("test2");
+ $this->assertEquals([
+ 'id' => $id
+ ], $fd);
+
+ // query single field in table
+ $fd = $this->db->fieldData('test2', 'id');
+ $this->assertEquals([
+ 'id' => $id
+ ], $fd);
+
+ // query array of fields in table
+ $fd = $this->db->fieldData('test2', [
+ 'id'
+ ]);
+ $this->assertEquals([
+ 'id' => $id
+ ], $fd);
+
+ // invalid datatype for field name
+ $fd = $this->db->fieldData('test2', new stdClass());
+ $this->assertEquals(null, $fd);
+ }
+
+ public function testEscapeDontEscapeNow()
+ {
+ // $this->markTestIncomplete();
+ $ret = $this->db->_escape('NOW()', false);
+ $this->assertEquals("NOW()", $ret);
+ }
+
+ public function testEscapeDontEscapeBackticks()
+ {
+ $ret = $this->db->_escape("t.`id`", false);
+ $this->assertEquals("t.`id`", $ret);
+ }
+
+ public function testEscapeEscapeDateTime()
+ {
+ $dt = new DateTime("2017-01-01 00:00:00");
+ $ret = $this->db->_escape($dt);
+ $this->assertEquals("'2017-01-01 00:00:00'", $ret);
+ }
+
+ public function testEscapeBoolean()
+ {
+ $ret = $this->db->_escape(true);
+ $this->assertEquals("'1'", $ret);
+ }
+
+ public function testEscapeClassWithEscapeMethod()
+ {
+ $tc = new TestClass();
+ $tc->var = "test's";
+ $ret = $this->db->_escape($tc);
+ $this->assertEquals("test\'s", $ret);
+ }
+
+ public function testEscapeUnknownClassToEscape()
+ {
+ // $this->markTestIncomplete();
+ $tc2 = new TestClass2();
+ $tc2->var = "test";
+ $ret = $this->db->_escape($tc2);
+
+ $this->assertEquals("", $ret);
+ }
+
+ public function testDeleteBasic()
+ {
+ $this->db->delete("test");
+ $this->assertEquals("DELETE FROM test", $this->db->getSql());
+ }
+
+ public function testDeleteWithWhereClause()
+ {
+ $this->db->delete('test', [
+ 'id'
+ ], [
+ [
+ 'field' => 'id',
+ 'op' => '=',
+ 'value' => 1
+ ]
+ ]);
+ $this->assertEquals("DELETE id FROM test WHERE `id` = '1'", $this->db->getSql());
+ }
+
+ public function testDeleteWithJoin()
+ {
+ $this->db->delete('test t', [], [], [
+ 'joins' => "JOIN settings s ON s.id=t.id"
+ ]);
+ $this->assertEquals("DELETE FROM test t JOIN settings s ON s.id=t.id", $this->db->getSql());
+ }
+
+ /**
+ * @expectedException TypeError
+ */
+ public function testDeleteInvalidTableNameDatatype()
+ {
+ $this->db->delete(new stdClass());
+ }
+
+ public function testTruncate()
+ {
+ $this->db->truncate('test');
+ $this->assertEquals("TRUNCATE TABLE test", $this->db->getSql());
+ }
+
+ /**
+ * @expectedException TypeError
+ */
+ public function testTruncateInvalidTableNameDatatype()
+ {
+ $this->db->truncate(new stdClass());
+ }
+
+ public function testDropSettingsTable()
+ {
+ // Database::$autorun = false;
+ $sql = $this->db->drop("settings");
+ $this->assertEquals("DROP TABLE IF EXISTS `settings`", $sql);
+ // Database::$autorun = true;
+ }
+
+ public function testDropTestTable()
+ {
+ // Database::$autorun = false;
+ $sql = $this->db->drop("test");
+ $this->assertEquals("DROP TABLE IF EXISTS `test`", $sql);
+ // Database::$autorun = true;
+ }
+
+ public function testDropView()
+ {
+ // Database::$autorun = false;
+ $sql = $this->db->drop("test", "view");
+ $this->assertEquals("DROP VIEW IF EXISTS `test`", $sql);
+ // Database::$autorun = true;
+ }
+
+ /**
+ * @expectedException TypeError
+ */
+ public function testDropInvalidTableNameDatatype()
+ {
+ $this->db->drop(new stdClass());
+ }
+
+ /**
+ * @expectedException TypeError
+ */
+ public function testDropInvalidTypeDatatype()
+ {
+ $this->db->drop('test', new stdClass());
+ }
+
+ public function testSetSchema()
+ {
+ // set the schema and validate that it is what we set it to
+ $this->db->setSchema("test");
+ $row = $this->db->query("SELECT DATABASE()");
+ $this->assertEquals("test", $row->fetch_array()[0]);
+ }
+}
\ No newline at end of file
diff --git a/inc/vendor/godsgood33/php-db/tests/TestClass.php b/inc/vendor/godsgood33/php-db/tests/TestClass.php
new file mode 100644
index 0000000..836a54c
--- /dev/null
+++ b/inc/vendor/godsgood33/php-db/tests/TestClass.php
@@ -0,0 +1,24 @@
+var);
+ }
+}
\ No newline at end of file
diff --git a/inc/vendor/godsgood33/php-db/tests/TestClass2.php b/inc/vendor/godsgood33/php-db/tests/TestClass2.php
new file mode 100644
index 0000000..4d01a9e
--- /dev/null
+++ b/inc/vendor/godsgood33/php-db/tests/TestClass2.php
@@ -0,0 +1,5 @@
+add($complexString2);
+```
+or pass all values to the appropriate function
+```
+$complexString1 = '1.23-4.56i';
+$complexString2 = '2.34+5.67i';
+
+echo Complex\add($complexString1, $complexString2);
+```
+If you want to perform the same operation against multiple values (e.g. to add three or more complex numbers), then you can pass multiple arguments to any of the operations.
+
+You can pass these arguments as Complex objects, or as an array or string that will parse to a complex object.
+
+## Using functions
+
+When calling any of the available functions for a complex value, you can either call the relevant method for the Complex object
+```
+$complexString = '1.23-4.56i';
+
+$complexObject = new Complex\Complex($complexString);
+echo $complexObject->sinh();
+```
+or you can call the function as you would in procedural code, passing the Complex object as an argument
+```
+$complexString = '1.23-4.56i';
+
+$complexObject = new Complex\Complex($complexString);
+echo Complex\sinh($complexObject);
+```
+When called procedurally using the function, you can pass in the argument as a Complex object, or as an array or string that will parse to a complex object.
+```
+$complexString = '1.23-4.56i';
+
+echo Complex\sinh($complexString);
+```
+
+In the case of the `pow()` function (the only implemented function that requires an additional argument) you need to pass both arguments when calling the function procedurally
+
+```
+$complexString = '1.23-4.56i';
+
+$complexObject = new Complex\Complex($complexString);
+echo Complex\pow($complexObject, 2);
+```
+or pass the additional argument when calling the method
+```
+$complexString = '1.23-4.56i';
+
+$complexObject = new Complex\Complex($complexString);
+echo $complexObject->pow(2);
+```
diff --git a/inc/vendor/markbaker/complex/classes/Autoloader.php b/inc/vendor/markbaker/complex/classes/Autoloader.php
new file mode 100644
index 0000000..9a8fcc1
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/Autoloader.php
@@ -0,0 +1,53 @@
+regex = $regex;
+ parent::__construct($it, $regex);
+ }
+}
+
+class FilenameFilter extends FilesystemRegexFilter
+{
+ // Filter files against the regex
+ public function accept()
+ {
+ return (!$this->isFile() || preg_match($this->regex, $this->getFilename()));
+ }
+}
+
+
+$srcFolder = __DIR__ . DIRECTORY_SEPARATOR . 'src';
+$srcDirectory = new RecursiveDirectoryIterator($srcFolder);
+
+$filteredFileList = new FilenameFilter($srcDirectory, '/(?:php)$/i');
+$filteredFileList = new FilenameFilter($filteredFileList, '/^(?!.*(Complex|Exception)\.php).*$/i');
+
+foreach (new RecursiveIteratorIterator($filteredFileList) as $file) {
+ if ($file->isFile()) {
+ include_once $file;
+ }
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/Complex.php b/inc/vendor/markbaker/complex/classes/src/Complex.php
new file mode 100644
index 0000000..5671eb2
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/Complex.php
@@ -0,0 +1,387 @@
+ 0.0 && empty($suffix)) {
+ $suffix = 'i';
+ }
+
+ // Set parsed values in our properties
+ $this->realPart = (float) $realPart;
+ $this->imaginaryPart = (float) $imaginaryPart;
+ $this->suffix = strtolower($suffix);
+ }
+
+ /**
+ * Gets the real part of this complex number
+ *
+ * @return Float
+ */
+ public function getReal()
+ {
+ return $this->realPart;
+ }
+
+ /**
+ * Gets the imaginary part of this complex number
+ *
+ * @return Float
+ */
+ public function getImaginary()
+ {
+ return $this->imaginaryPart;
+ }
+
+ /**
+ * Gets the suffix of this complex number
+ *
+ * @return String
+ */
+ public function getSuffix()
+ {
+ return $this->suffix;
+ }
+
+ /**
+ * Returns true if this is a real value, false if a complex value
+ *
+ * @return Bool
+ */
+ public function isReal()
+ {
+ return $this->imaginaryPart == 0.0;
+ }
+
+ /**
+ * Returns true if this is a complex value, false if a real value
+ *
+ * @return Bool
+ */
+ public function isComplex()
+ {
+ return !$this->isReal();
+ }
+
+ public function format()
+ {
+ $str = "";
+ if ($this->imaginaryPart != 0.0) {
+ if (\abs($this->imaginaryPart) != 1.0) {
+ $str .= $this->imaginaryPart . $this->suffix;
+ } else {
+ $str .= (($this->imaginaryPart < 0.0) ? '-' : '') . $this->suffix;
+ }
+ }
+ if ($this->realPart != 0.0) {
+ if (($str) && ($this->imaginaryPart > 0.0)) {
+ $str = "+" . $str;
+ }
+ $str = $this->realPart . $str;
+ }
+ if (!$str) {
+ $str = "0.0";
+ }
+
+ return $str;
+ }
+
+ public function __toString()
+ {
+ return $this->format();
+ }
+
+ /**
+ * Validates whether the argument is a valid complex number, converting scalar or array values if possible
+ *
+ * @param mixed $complex The value to validate
+ * @return Complex
+ * @throws Exception If the argument isn't a Complex number or cannot be converted to one
+ */
+ public static function validateComplexArgument($complex)
+ {
+ if (is_scalar($complex) || is_array($complex)) {
+ $complex = new Complex($complex);
+ } elseif (!is_object($complex) || !($complex instanceof Complex)) {
+ throw new Exception('Value is not a valid complex number');
+ }
+
+ return $complex;
+ }
+
+ /**
+ * Returns the reverse of this complex number
+ *
+ * @return Complex
+ */
+ public function reverse()
+ {
+ return new Complex(
+ $this->imaginaryPart,
+ $this->realPart,
+ ($this->realPart == 0.0) ? null : $this->suffix
+ );
+ }
+
+ public function invertImaginary()
+ {
+ return new Complex(
+ $this->realPart,
+ $this->imaginaryPart * -1,
+ ($this->imaginaryPart == 0.0) ? null : $this->suffix
+ );
+ }
+
+ public function invertReal()
+ {
+ return new Complex(
+ $this->realPart * -1,
+ $this->imaginaryPart,
+ ($this->imaginaryPart == 0.0) ? null : $this->suffix
+ );
+ }
+
+ protected static $functions = [
+ 'abs',
+ 'acos',
+ 'acosh',
+ 'acot',
+ 'acoth',
+ 'acsc',
+ 'acsch',
+ 'argument',
+ 'asec',
+ 'asech',
+ 'asin',
+ 'asinh',
+ 'atan',
+ 'atanh',
+ 'conjugate',
+ 'cos',
+ 'cosh',
+ 'cot',
+ 'coth',
+ 'csc',
+ 'csch',
+ 'exp',
+ 'inverse',
+ 'ln',
+ 'log2',
+ 'log10',
+ 'negative',
+ 'pow',
+ 'rho',
+ 'sec',
+ 'sech',
+ 'sin',
+ 'sinh',
+ 'sqrt',
+ 'tan',
+ 'tanh',
+ 'theta',
+ ];
+
+ protected static $operations = [
+ 'add',
+ 'subtract',
+ 'multiply',
+ 'divideby',
+ 'divideinto',
+ ];
+
+ /**
+ * Returns the result of the function call or operation
+ *
+ * @return Complex|float
+ * @throws Exception|\InvalidArgumentException
+ */
+ public function __call($functionName, $arguments)
+ {
+ $functionName = strtolower(str_replace('_', '', $functionName));
+
+ // Test for function calls
+ if (in_array($functionName, self::$functions)) {
+ $functionName = "\\" . __NAMESPACE__ . "\\{$functionName}";
+ return $functionName($this, ...$arguments);
+ }
+ // Test for operation calls
+ if (in_array($functionName, self::$operations)) {
+ $functionName = "\\" . __NAMESPACE__ . "\\{$functionName}";
+ return $functionName($this, ...$arguments);
+ }
+ throw new Exception('Function or Operation does not exist');
+ }
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/Exception.php b/inc/vendor/markbaker/complex/classes/src/Exception.php
new file mode 100644
index 0000000..a2beb73
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/Exception.php
@@ -0,0 +1,13 @@
+getReal() - $invsqrt->getImaginary(),
+ $complex->getImaginary() + $invsqrt->getReal()
+ );
+ $log = ln($adjust);
+
+ return new Complex(
+ $log->getImaginary(),
+ -1 * $log->getReal()
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/acosh.php b/inc/vendor/markbaker/complex/classes/src/functions/acosh.php
new file mode 100644
index 0000000..18a992e
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/acosh.php
@@ -0,0 +1,34 @@
+isReal() && ($complex->getReal() > 1)) {
+ return new Complex(\acosh($complex->getReal()));
+ }
+
+ $acosh = acos($complex)
+ ->reverse();
+ if ($acosh->getReal() < 0.0) {
+ $acosh = $acosh->invertReal();
+ }
+
+ return $acosh;
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/acot.php b/inc/vendor/markbaker/complex/classes/src/functions/acot.php
new file mode 100644
index 0000000..11bee46
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/acot.php
@@ -0,0 +1,25 @@
+getReal() == 0.0 && $complex->getImaginary() == 0.0) {
+ return INF;
+ }
+
+ return asin(inverse($complex));
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/acsch.php b/inc/vendor/markbaker/complex/classes/src/functions/acsch.php
new file mode 100644
index 0000000..bb45d34
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/acsch.php
@@ -0,0 +1,29 @@
+getReal() == 0.0 && $complex->getImaginary() == 0.0) {
+ return INF;
+ }
+
+ return asinh(inverse($complex));
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/argument.php b/inc/vendor/markbaker/complex/classes/src/functions/argument.php
new file mode 100644
index 0000000..d7209cc
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/argument.php
@@ -0,0 +1,28 @@
+getReal() == 0.0 && $complex->getImaginary() == 0.0) {
+ return INF;
+ }
+
+ return acos(inverse($complex));
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/asech.php b/inc/vendor/markbaker/complex/classes/src/functions/asech.php
new file mode 100644
index 0000000..b36c40e
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/asech.php
@@ -0,0 +1,29 @@
+getReal() == 0.0 && $complex->getImaginary() == 0.0) {
+ return INF;
+ }
+
+ return acosh(inverse($complex));
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/asin.php b/inc/vendor/markbaker/complex/classes/src/functions/asin.php
new file mode 100644
index 0000000..9c982ac
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/asin.php
@@ -0,0 +1,37 @@
+getReal() - $complex->getImaginary(),
+ $invsqrt->getImaginary() + $complex->getReal()
+ );
+ $log = ln($adjust);
+
+ return new Complex(
+ $log->getImaginary(),
+ -1 * $log->getReal()
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/asinh.php b/inc/vendor/markbaker/complex/classes/src/functions/asinh.php
new file mode 100644
index 0000000..c1243fd
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/asinh.php
@@ -0,0 +1,33 @@
+isReal() && ($complex->getReal() > 1)) {
+ return new Complex(\asinh($complex->getReal()));
+ }
+
+ $asinh = clone $complex;
+ $asinh = $asinh->reverse()
+ ->invertReal();
+ $asinh = asin($asinh);
+ return $asinh->reverse()
+ ->invertImaginary();
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/atan.php b/inc/vendor/markbaker/complex/classes/src/functions/atan.php
new file mode 100644
index 0000000..2c75dcf
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/atan.php
@@ -0,0 +1,45 @@
+isReal()) {
+ return new Complex(\atan($complex->getReal()));
+ }
+
+ $t1Value = new Complex(-1 * $complex->getImaginary(), $complex->getReal());
+ $uValue = new Complex(1, 0);
+
+ $d1Value = clone $uValue;
+ $d1Value = subtract($d1Value, $t1Value);
+ $d2Value = add($t1Value, $uValue);
+ $uResult = $d1Value->divideBy($d2Value);
+ $uResult = ln($uResult);
+
+ return new Complex(
+ (($uResult->getImaginary() == M_PI) ? -M_PI : $uResult->getImaginary()) * -0.5,
+ $uResult->getReal() * 0.5,
+ $complex->getSuffix()
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/atanh.php b/inc/vendor/markbaker/complex/classes/src/functions/atanh.php
new file mode 100644
index 0000000..c53f2a9
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/atanh.php
@@ -0,0 +1,38 @@
+isReal()) {
+ $real = $complex->getReal();
+ if ($real >= -1.0 && $real <= 1.0) {
+ return new Complex(\atanh($real));
+ } else {
+ return new Complex(\atanh(1 / $real), (($real < 0.0) ? M_PI_2 : -1 * M_PI_2));
+ }
+ }
+
+ $iComplex = clone $complex;
+ $iComplex = $iComplex->invertImaginary()
+ ->reverse();
+ return atan($iComplex)
+ ->invertReal()
+ ->reverse();
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/conjugate.php b/inc/vendor/markbaker/complex/classes/src/functions/conjugate.php
new file mode 100644
index 0000000..bd1984b
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/conjugate.php
@@ -0,0 +1,28 @@
+getReal(),
+ -1 * $complex->getImaginary(),
+ $complex->getSuffix()
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/cos.php b/inc/vendor/markbaker/complex/classes/src/functions/cos.php
new file mode 100644
index 0000000..80a4683
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/cos.php
@@ -0,0 +1,34 @@
+isReal()) {
+ return new Complex(\cos($complex->getReal()));
+ }
+
+ return conjugate(
+ new Complex(
+ \cos($complex->getReal()) * \cosh($complex->getImaginary()),
+ \sin($complex->getReal()) * \sinh($complex->getImaginary()),
+ $complex->getSuffix()
+ )
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/cosh.php b/inc/vendor/markbaker/complex/classes/src/functions/cosh.php
new file mode 100644
index 0000000..a4bea65
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/cosh.php
@@ -0,0 +1,32 @@
+isReal()) {
+ return new Complex(\cosh($complex->getReal()));
+ }
+
+ return new Complex(
+ \cosh($complex->getReal()) * \cos($complex->getImaginary()),
+ \sinh($complex->getReal()) * \sin($complex->getImaginary()),
+ $complex->getSuffix()
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/cot.php b/inc/vendor/markbaker/complex/classes/src/functions/cot.php
new file mode 100644
index 0000000..339101e
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/cot.php
@@ -0,0 +1,29 @@
+getReal() == 0.0 && $complex->getImaginary() == 0.0) {
+ return new Complex(INF);
+ }
+
+ return inverse(tan($complex));
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/coth.php b/inc/vendor/markbaker/complex/classes/src/functions/coth.php
new file mode 100644
index 0000000..7fe705a
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/coth.php
@@ -0,0 +1,24 @@
+getReal() == 0.0 && $complex->getImaginary() == 0.0) {
+ return INF;
+ }
+
+ return inverse(sin($complex));
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/csch.php b/inc/vendor/markbaker/complex/classes/src/functions/csch.php
new file mode 100644
index 0000000..f450098
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/csch.php
@@ -0,0 +1,29 @@
+getReal() == 0.0 && $complex->getImaginary() == 0.0) {
+ return INF;
+ }
+
+ return inverse(sinh($complex));
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/exp.php b/inc/vendor/markbaker/complex/classes/src/functions/exp.php
new file mode 100644
index 0000000..4cac696
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/exp.php
@@ -0,0 +1,34 @@
+getReal() == 0.0) && (\abs($complex->getImaginary()) == M_PI)) {
+ return new Complex(-1.0, 0.0);
+ }
+
+ $rho = \exp($complex->getReal());
+
+ return new Complex(
+ $rho * \cos($complex->getImaginary()),
+ $rho * \sin($complex->getImaginary()),
+ $complex->getSuffix()
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/inverse.php b/inc/vendor/markbaker/complex/classes/src/functions/inverse.php
new file mode 100644
index 0000000..7d3182a
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/inverse.php
@@ -0,0 +1,29 @@
+getReal() == 0.0 && $complex->getImaginary() == 0.0) {
+ throw new \InvalidArgumentException('Division by zero');
+ }
+
+ return $complex->divideInto(1.0);
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/ln.php b/inc/vendor/markbaker/complex/classes/src/functions/ln.php
new file mode 100644
index 0000000..39071cf
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/ln.php
@@ -0,0 +1,33 @@
+getReal() == 0.0) && ($complex->getImaginary() == 0.0)) {
+ throw new \InvalidArgumentException();
+ }
+
+ return new Complex(
+ \log(rho($complex)),
+ theta($complex),
+ $complex->getSuffix()
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/log10.php b/inc/vendor/markbaker/complex/classes/src/functions/log10.php
new file mode 100644
index 0000000..694d3d0
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/log10.php
@@ -0,0 +1,32 @@
+getReal() == 0.0) && ($complex->getImaginary() == 0.0)) {
+ throw new \InvalidArgumentException();
+ } elseif (($complex->getReal() > 0.0) && ($complex->getImaginary() == 0.0)) {
+ return new Complex(\log10($complex->getReal()), 0.0, $complex->getSuffix());
+ }
+
+ return ln($complex)
+ ->multiply(\log10(Complex::EULER));
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/log2.php b/inc/vendor/markbaker/complex/classes/src/functions/log2.php
new file mode 100644
index 0000000..081f2c4
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/log2.php
@@ -0,0 +1,32 @@
+getReal() == 0.0) && ($complex->getImaginary() == 0.0)) {
+ throw new \InvalidArgumentException();
+ } elseif (($complex->getReal() > 0.0) && ($complex->getImaginary() == 0.0)) {
+ return new Complex(\log($complex->getReal(), 2), 0.0, $complex->getSuffix());
+ }
+
+ return ln($complex)
+ ->multiply(\log(Complex::EULER, 2));
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/negative.php b/inc/vendor/markbaker/complex/classes/src/functions/negative.php
new file mode 100644
index 0000000..dbd1192
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/negative.php
@@ -0,0 +1,31 @@
+getReal(),
+ -1 * $complex->getImaginary(),
+ $complex->getSuffix()
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/pow.php b/inc/vendor/markbaker/complex/classes/src/functions/pow.php
new file mode 100644
index 0000000..18ee269
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/pow.php
@@ -0,0 +1,40 @@
+getImaginary() == 0.0 && $complex->getReal() >= 0.0) {
+ return new Complex(\pow($complex->getReal(), $power));
+ }
+
+ $rValue = \sqrt(($complex->getReal() * $complex->getReal()) + ($complex->getImaginary() * $complex->getImaginary()));
+ $rPower = \pow($rValue, $power);
+ $theta = $complex->argument() * $power;
+ if ($theta == 0) {
+ return new Complex(1);
+ }
+
+ return new Complex($rPower * \cos($theta), $rPower * \sin($theta), $complex->getSuffix());
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/rho.php b/inc/vendor/markbaker/complex/classes/src/functions/rho.php
new file mode 100644
index 0000000..750f3f9
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/rho.php
@@ -0,0 +1,28 @@
+getReal() * $complex->getReal()) +
+ ($complex->getImaginary() * $complex->getImaginary())
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/sec.php b/inc/vendor/markbaker/complex/classes/src/functions/sec.php
new file mode 100644
index 0000000..7dd43ea
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/sec.php
@@ -0,0 +1,25 @@
+isReal()) {
+ return new Complex(\sin($complex->getReal()));
+ }
+
+ return new Complex(
+ \sin($complex->getReal()) * \cosh($complex->getImaginary()),
+ \cos($complex->getReal()) * \sinh($complex->getImaginary()),
+ $complex->getSuffix()
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/sinh.php b/inc/vendor/markbaker/complex/classes/src/functions/sinh.php
new file mode 100644
index 0000000..4c0f650
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/sinh.php
@@ -0,0 +1,32 @@
+isReal()) {
+ return new Complex(\sinh($complex->getReal()));
+ }
+
+ return new Complex(
+ \sinh($complex->getReal()) * \cos($complex->getImaginary()),
+ \cosh($complex->getReal()) * \sin($complex->getImaginary()),
+ $complex->getSuffix()
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/sqrt.php b/inc/vendor/markbaker/complex/classes/src/functions/sqrt.php
new file mode 100644
index 0000000..9c171b8
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/sqrt.php
@@ -0,0 +1,29 @@
+getSuffix());
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/tan.php b/inc/vendor/markbaker/complex/classes/src/functions/tan.php
new file mode 100644
index 0000000..014d798
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/tan.php
@@ -0,0 +1,40 @@
+isReal()) {
+ return new Complex(\tan($complex->getReal()));
+ }
+
+ $real = $complex->getReal();
+ $imaginary = $complex->getImaginary();
+ $divisor = 1 + \pow(\tan($real), 2) * \pow(\tanh($imaginary), 2);
+ if ($divisor == 0.0) {
+ throw new \InvalidArgumentException('Division by zero');
+ }
+
+ return new Complex(
+ \pow(sech($imaginary)->getReal(), 2) * \tan($real) / $divisor,
+ \pow(sec($real)->getReal(), 2) * \tanh($imaginary) / $divisor,
+ $complex->getSuffix()
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/tanh.php b/inc/vendor/markbaker/complex/classes/src/functions/tanh.php
new file mode 100644
index 0000000..028741d
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/tanh.php
@@ -0,0 +1,35 @@
+getReal();
+ $imaginary = $complex->getImaginary();
+ $divisor = \cos($imaginary) * \cos($imaginary) + \sinh($real) * \sinh($real);
+ if ($divisor == 0.0) {
+ throw new \InvalidArgumentException('Division by zero');
+ }
+
+ return new Complex(
+ \sinh($real) * \cosh($real) / $divisor,
+ 0.5 * \sin(2 * $imaginary) / $divisor,
+ $complex->getSuffix()
+ );
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/functions/theta.php b/inc/vendor/markbaker/complex/classes/src/functions/theta.php
new file mode 100644
index 0000000..d12866c
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/functions/theta.php
@@ -0,0 +1,38 @@
+getReal() == 0.0) {
+ if ($complex->isReal()) {
+ return 0.0;
+ } elseif ($complex->getImaginary() < 0.0) {
+ return M_PI / -2;
+ }
+ return M_PI / 2;
+ } elseif ($complex->getReal() > 0.0) {
+ return \atan($complex->getImaginary() / $complex->getReal());
+ } elseif ($complex->getImaginary() < 0.0) {
+ return -(M_PI - \atan(\abs($complex->getImaginary()) / \abs($complex->getReal())));
+ }
+
+ return M_PI - \atan($complex->getImaginary() / \abs($complex->getReal()));
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/operations/add.php b/inc/vendor/markbaker/complex/classes/src/operations/add.php
new file mode 100644
index 0000000..10bd42f
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/operations/add.php
@@ -0,0 +1,46 @@
+isComplex() && $complex->isComplex() &&
+ $result->getSuffix() !== $complex->getSuffix()) {
+ throw new Exception('Suffix Mismatch');
+ }
+
+ $real = $result->getReal() + $complex->getReal();
+ $imaginary = $result->getImaginary() + $complex->getImaginary();
+
+ $result = new Complex(
+ $real,
+ $imaginary,
+ ($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
+ );
+ }
+
+ return $result;
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/operations/divideby.php b/inc/vendor/markbaker/complex/classes/src/operations/divideby.php
new file mode 100644
index 0000000..089e0ef
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/operations/divideby.php
@@ -0,0 +1,56 @@
+isComplex() && $complex->isComplex() &&
+ $result->getSuffix() !== $complex->getSuffix()) {
+ throw new Exception('Suffix Mismatch');
+ }
+ if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
+ throw new \InvalidArgumentException('Division by zero');
+ }
+
+ $delta1 = ($result->getReal() * $complex->getReal()) +
+ ($result->getImaginary() * $complex->getImaginary());
+ $delta2 = ($result->getImaginary() * $complex->getReal()) -
+ ($result->getReal() * $complex->getImaginary());
+ $delta3 = ($complex->getReal() * $complex->getReal()) +
+ ($complex->getImaginary() * $complex->getImaginary());
+
+ $real = $delta1 / $delta3;
+ $imaginary = $delta2 / $delta3;
+
+ $result = new Complex(
+ $real,
+ $imaginary,
+ ($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
+ );
+ }
+
+ return $result;
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/operations/divideinto.php b/inc/vendor/markbaker/complex/classes/src/operations/divideinto.php
new file mode 100644
index 0000000..3dfe085
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/operations/divideinto.php
@@ -0,0 +1,56 @@
+isComplex() && $complex->isComplex() &&
+ $result->getSuffix() !== $complex->getSuffix()) {
+ throw new Exception('Suffix Mismatch');
+ }
+ if ($result->getReal() == 0.0 && $result->getImaginary() == 0.0) {
+ throw new \InvalidArgumentException('Division by zero');
+ }
+
+ $delta1 = ($complex->getReal() * $result->getReal()) +
+ ($complex->getImaginary() * $result->getImaginary());
+ $delta2 = ($complex->getImaginary() * $result->getReal()) -
+ ($complex->getReal() * $result->getImaginary());
+ $delta3 = ($result->getReal() * $result->getReal()) +
+ ($result->getImaginary() * $result->getImaginary());
+
+ $real = $delta1 / $delta3;
+ $imaginary = $delta2 / $delta3;
+
+ $result = new Complex(
+ $real,
+ $imaginary,
+ ($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
+ );
+ }
+
+ return $result;
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/operations/multiply.php b/inc/vendor/markbaker/complex/classes/src/operations/multiply.php
new file mode 100644
index 0000000..bf2473e
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/operations/multiply.php
@@ -0,0 +1,48 @@
+isComplex() && $complex->isComplex() &&
+ $result->getSuffix() !== $complex->getSuffix()) {
+ throw new Exception('Suffix Mismatch');
+ }
+
+ $real = ($result->getReal() * $complex->getReal()) -
+ ($result->getImaginary() * $complex->getImaginary());
+ $imaginary = ($result->getReal() * $complex->getImaginary()) +
+ ($result->getImaginary() * $complex->getReal());
+
+ $result = new Complex(
+ $real,
+ $imaginary,
+ ($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
+ );
+ }
+
+ return $result;
+}
diff --git a/inc/vendor/markbaker/complex/classes/src/operations/subtract.php b/inc/vendor/markbaker/complex/classes/src/operations/subtract.php
new file mode 100644
index 0000000..075ef44
--- /dev/null
+++ b/inc/vendor/markbaker/complex/classes/src/operations/subtract.php
@@ -0,0 +1,46 @@
+isComplex() && $complex->isComplex() &&
+ $result->getSuffix() !== $complex->getSuffix()) {
+ throw new Exception('Suffix Mismatch');
+ }
+
+ $real = $result->getReal() - $complex->getReal();
+ $imaginary = $result->getImaginary() - $complex->getImaginary();
+
+ $result = new Complex(
+ $real,
+ $imaginary,
+ ($imaginary == 0.0) ? null : max($result->getSuffix(), $complex->getSuffix())
+ );
+ }
+
+ return $result;
+}
diff --git a/inc/vendor/markbaker/complex/composer.json b/inc/vendor/markbaker/complex/composer.json
new file mode 100644
index 0000000..cb05712
--- /dev/null
+++ b/inc/vendor/markbaker/complex/composer.json
@@ -0,0 +1,77 @@
+{
+ "name": "markbaker/complex",
+ "type": "library",
+ "description": "PHP Class for working with complex numbers",
+ "keywords": ["complex", "mathematics"],
+ "homepage": "https://github.com/MarkBaker/PHPComplex",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Mark Baker",
+ "email": "mark@lange.demon.co.uk"
+ }
+ ],
+ "require": {
+ "php": "^5.6.0|^7.0.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8.35|^5.4.0",
+ "phpdocumentor/phpdocumentor":"2.*",
+ "phpmd/phpmd": "2.*",
+ "sebastian/phpcpd": "2.*",
+ "phploc/phploc": "2.*",
+ "squizlabs/php_codesniffer": "^3.3.0",
+ "phpcompatibility/php-compatibility": "^8.0",
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3"
+ },
+ "autoload": {
+ "psr-4": {
+ "Complex\\": "classes/src/"
+ },
+ "files": [
+ "classes/src/functions/abs.php",
+ "classes/src/functions/acos.php",
+ "classes/src/functions/acosh.php",
+ "classes/src/functions/acot.php",
+ "classes/src/functions/acoth.php",
+ "classes/src/functions/acsc.php",
+ "classes/src/functions/acsch.php",
+ "classes/src/functions/argument.php",
+ "classes/src/functions/asec.php",
+ "classes/src/functions/asech.php",
+ "classes/src/functions/asin.php",
+ "classes/src/functions/asinh.php",
+ "classes/src/functions/atan.php",
+ "classes/src/functions/atanh.php",
+ "classes/src/functions/conjugate.php",
+ "classes/src/functions/cos.php",
+ "classes/src/functions/cosh.php",
+ "classes/src/functions/cot.php",
+ "classes/src/functions/coth.php",
+ "classes/src/functions/csc.php",
+ "classes/src/functions/csch.php",
+ "classes/src/functions/exp.php",
+ "classes/src/functions/inverse.php",
+ "classes/src/functions/ln.php",
+ "classes/src/functions/log2.php",
+ "classes/src/functions/log10.php",
+ "classes/src/functions/negative.php",
+ "classes/src/functions/pow.php",
+ "classes/src/functions/rho.php",
+ "classes/src/functions/sec.php",
+ "classes/src/functions/sech.php",
+ "classes/src/functions/sin.php",
+ "classes/src/functions/sinh.php",
+ "classes/src/functions/sqrt.php",
+ "classes/src/functions/tan.php",
+ "classes/src/functions/tanh.php",
+ "classes/src/functions/theta.php",
+ "classes/src/operations/add.php",
+ "classes/src/operations/subtract.php",
+ "classes/src/operations/multiply.php",
+ "classes/src/operations/divideby.php",
+ "classes/src/operations/divideinto.php"
+ ]
+ },
+ "minimum-stability": "dev"
+}
\ No newline at end of file
diff --git a/inc/vendor/markbaker/complex/examples/complexTest.php b/inc/vendor/markbaker/complex/examples/complexTest.php
new file mode 100644
index 0000000..7dafd8a
--- /dev/null
+++ b/inc/vendor/markbaker/complex/examples/complexTest.php
@@ -0,0 +1,154 @@
+add(456);
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456);
+$x->add(789.012);
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456, 78.90);
+$x->add(new Complex(-987.654, -32.1));
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456, 78.90);
+$x->add(-987.654);
+echo $x, PHP_EOL;
+
+$x = new Complex(-987.654, -32.1);
+$x->add(new Complex(0, 1));
+echo $x, PHP_EOL;
+
+$x = new Complex(-987.654, -32.1);
+$x->add(new Complex(0, -1));
+echo $x, PHP_EOL;
+
+
+echo PHP_EOL, 'Subtract', PHP_EOL;
+
+$x = new Complex(123);
+$x->subtract(456);
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456);
+$x->subtract(789.012);
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456, 78.90);
+$x->subtract(new Complex(-987.654, -32.1));
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456, 78.90);
+$x->subtract(-987.654);
+echo $x, PHP_EOL;
+
+$x = new Complex(-987.654, -32.1);
+$x->subtract(new Complex(0, 1));
+echo $x, PHP_EOL;
+
+$x = new Complex(-987.654, -32.1);
+$x->subtract(new Complex(0, -1));
+echo $x, PHP_EOL;
+
+
+echo PHP_EOL, 'Multiply', PHP_EOL;
+
+$x = new Complex(123);
+$x->multiply(456);
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456);
+$x->multiply(789.012);
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456, 78.90);
+$x->multiply(new Complex(-987.654, -32.1));
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456, 78.90);
+$x->multiply(-987.654);
+echo $x, PHP_EOL;
+
+$x = new Complex(-987.654, -32.1);
+$x->multiply(new Complex(0, 1));
+echo $x, PHP_EOL;
+
+$x = new Complex(-987.654, -32.1);
+$x->multiply(new Complex(0, -1));
+echo $x, PHP_EOL;
+
+
+echo PHP_EOL, 'Divide By', PHP_EOL;
+
+$x = new Complex(123);
+$x->divideBy(456);
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456);
+$x->divideBy(789.012);
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456, 78.90);
+$x->divideBy(new Complex(-987.654, -32.1));
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456, 78.90);
+$x->divideBy(-987.654);
+echo $x, PHP_EOL;
+
+$x = new Complex(-987.654, -32.1);
+$x->divideBy(new Complex(0, 1));
+echo $x, PHP_EOL;
+
+$x = new Complex(-987.654, -32.1);
+$x->divideBy(new Complex(0, -1));
+echo $x, PHP_EOL;
+
+
+echo PHP_EOL, 'Divide Into', PHP_EOL;
+
+$x = new Complex(123);
+$x->divideInto(456);
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456);
+$x->divideInto(789.012);
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456, 78.90);
+$x->divideInto(new Complex(-987.654, -32.1));
+echo $x, PHP_EOL;
+
+$x = new Complex(123.456, 78.90);
+$x->divideInto(-987.654);
+echo $x, PHP_EOL;
+
+$x = new Complex(-987.654, -32.1);
+$x->divideInto(new Complex(0, 1));
+echo $x, PHP_EOL;
+
+$x = new Complex(-987.654, -32.1);
+$x->divideInto(new Complex(0, -1));
+echo $x, PHP_EOL;
diff --git a/inc/vendor/markbaker/complex/examples/testFunctions.php b/inc/vendor/markbaker/complex/examples/testFunctions.php
new file mode 100644
index 0000000..4d5ed73
--- /dev/null
+++ b/inc/vendor/markbaker/complex/examples/testFunctions.php
@@ -0,0 +1,52 @@
+getMessage(), PHP_EOL;
+ }
+ }
+ echo PHP_EOL;
+ }
+}
diff --git a/inc/vendor/markbaker/complex/examples/testOperations.php b/inc/vendor/markbaker/complex/examples/testOperations.php
new file mode 100644
index 0000000..f791263
--- /dev/null
+++ b/inc/vendor/markbaker/complex/examples/testOperations.php
@@ -0,0 +1,34 @@
+ ', $result, PHP_EOL;
+
+echo PHP_EOL;
+
+echo 'Subtraction', PHP_EOL;
+
+$result = \Complex\subtract(...$values);
+echo '=> ', $result, PHP_EOL;
+
+echo PHP_EOL;
+
+echo 'Multiplication', PHP_EOL;
+
+$result = \Complex\multiply(...$values);
+echo '=> ', $result, PHP_EOL;
diff --git a/inc/vendor/markbaker/complex/license.md b/inc/vendor/markbaker/complex/license.md
new file mode 100644
index 0000000..5b4b156
--- /dev/null
+++ b/inc/vendor/markbaker/complex/license.md
@@ -0,0 +1,25 @@
+The MIT License (MIT)
+=====================
+
+Copyright © `2017` `Mark Baker`
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the “Software”), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/inc/vendor/pacificsec/cpe/.gitignore b/inc/vendor/pacificsec/cpe/.gitignore
new file mode 100644
index 0000000..a7a214c
--- /dev/null
+++ b/inc/vendor/pacificsec/cpe/.gitignore
@@ -0,0 +1,5 @@
+/.settings/
+/.buildpath
+/.project
+/vendor/
+/composer.lock
diff --git a/inc/vendor/pacificsec/cpe/README.md b/inc/vendor/pacificsec/cpe/README.md
index c855f04..d03c72c 100644
--- a/inc/vendor/pacificsec/cpe/README.md
+++ b/inc/vendor/pacificsec/cpe/README.md
@@ -22,3 +22,45 @@ Features
- CPE rich comparison.
- CPE Language parsing and evaluation.
- MIT Licensed.
+
+Getting Started
+--------
+- Clone repository
+
+```bash
+$ git clone https://github.com/pacificsec/cpe.git
+$ cd cpe
+```
+- Create a new PHP file to run tests
+
+```php
+unbindURI("cpe:/a:microsoft:internet_explorer%01%01%01%01:?:beta");
+var_dump($wfn);
+$wfn = $cpenu->unbindURI("cpe:/a:microsoft:internet_explorer:8.%2a:sp%3f");
+var_dump($wfn);
+$wfn = $cpenu->unbindURI("cpe:/a:microsoft:internet_explorer:8.%02:sp%01");
+var_dump($wfn);
+$wfn = $cpenu->unbindURI("cpe:/a:hp:insight_diagnostics:7.4.0.1570::~~online~win2003~x64~");
+var_dump($wfn);
+$wfn = $cpenu->unbindFS("cpe:2.3:a:micr\\?osoft:internet_explorer:8.0.6001:beta:*:*:*:*:*:*");
+var_dump($wfn);
+```
\ No newline at end of file
diff --git a/inc/vendor/pacificsec/cpe/composer.json b/inc/vendor/pacificsec/cpe/composer.json
new file mode 100644
index 0000000..b386db0
--- /dev/null
+++ b/inc/vendor/pacificsec/cpe/composer.json
@@ -0,0 +1,26 @@
+{
+ "name" : "pacificsec/cpe",
+ "type" : "library",
+ "description" : "CPE: Common Platform Enumeration for PHP",
+ "keywords" : [
+ "cpe",
+ "cve",
+ "security",
+ "pacificsec"
+ ],
+ "homepage" : "https://github.com/pacificsec/cpe",
+ "license" : "MIT",
+ "authors" : [{
+ "name" : "Antonio Franco",
+ "email" : "antonio.franco@pacificsec.com"
+ }
+ ],
+ "require" : {
+ "php" : ">=5.3.0"
+ },
+ "autoload" : {
+ "psr-4" : {
+ "PacificSec\\CPE\\" : "src"
+ }
+ }
+}
\ No newline at end of file
diff --git a/inc/vendor/pacificsec/cpe/src/Common/LogicalValue.php b/inc/vendor/pacificsec/cpe/src/Common/LogicalValue.php
new file mode 100644
index 0000000..5d13494
--- /dev/null
+++ b/inc/vendor/pacificsec/cpe/src/Common/LogicalValue.php
@@ -0,0 +1,44 @@
+.
+ *
+ * @see cpe.mitre.org for more information.
+ * @author Antonio Franco
+ * @email antonio.franco@pacificsec.com
+ */
+class LogicalValue {
+
+ private $any = false;
+ private $na = false;
+
+ // Object must be constructed with the string "ANY" or "NA".
+ public function __construct($type) {
+ if ($type == "ANY") {
+ $this->any = true;
+ } else if ($type == "NA") {
+ $this->na = true;
+ } else {
+ throw new Exception("LogicalValue must be ANY or NA");
+ }
+ }
+
+ public function isANY(){
+ return $this->any;
+ }
+
+ public function isNA(){
+ return $this->na;
+ }
+
+ public function __toString(){
+ if ($this->any){
+ return "ANY";
+ }
+ return "NA";
+ }
+}
\ No newline at end of file
diff --git a/inc/vendor/pacificsec/cpe/src/Common/Utilities.php b/inc/vendor/pacificsec/cpe/src/Common/Utilities.php
new file mode 100644
index 0000000..e1e1f03
--- /dev/null
+++ b/inc/vendor/pacificsec/cpe/src/Common/Utilities.php
@@ -0,0 +1,166 @@
+.
+ *
+ * @see cpe.mitre.org for more information.
+ * @author Antonio Franco
+ * @email antonio.franco@pacificsec.com
+ */
+class Utilities {
+
+ /**
+ * Searches string for special characters * and ?
+ * @param string $string to be searched
+ * @return bool true if string contains wildcard, false otherwise
+ */
+ public static function containsWildcards($string) {
+ if (strpos($string, "*") !== false || strpos($string, "?") !== false) {
+ if (!(strpos($string, "\\") !== false)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if given number is even or not
+ * @param int $num number to check
+ * @return bool true if number is even, false if not
+ */
+ public static function isEvenNumber($num) {
+ return (is_int($num) && $num % 2 == 0);
+ }
+
+ /**
+ * Counts the number of escape characters in the string beginning and ending
+ * at the given indices
+ * @param string $str string to search
+ * @param int $start beginning index
+ * @param int $end ending index
+ * @return number of escape characters in string
+ * @todo fix the use of $str. The Java version is also not using this variable.
+ */
+ public static function countEscapeCharacters($str, $start, $end) {
+ $result = 0;
+ $active = false;
+ $i = 0;
+ while ($i < $end) {
+ if ($active && ($i >= $start)) {
+ $result = $result + 1;
+ }
+ $i = $i + 1;
+ }
+ return $result;
+ }
+
+ /**
+ * Searches a string for the first unescaped colon and returns the index of
+ * that colon
+ * @param string $str string to search
+ * @return int index of first unescaped colon, or 0 if not found
+ */
+ public static function getUnescapedColonIndex($str) {
+ $found = false;
+ $colon_idx = 0;
+ $start_idx = 0;
+ // Find the first non-escaped colon.
+ while (!$found) {
+ $colon_idx = strpos($str, ":", $start_idx + 1);
+ // If no colon is found, return 0.
+ if ($colon_idx === false) {
+ return 0;
+ }
+ // Peek at character before colon.
+ if (substr($str, $colon_idx-1, 1) == "\\") {
+ // If colon is escaped, keep looking.
+ $start_idx = $colon_idx;
+ } else {
+ $found = true;
+ }
+ }
+ return $colon_idx;
+ }
+
+ /**
+ * Returns true if the string contains only
+ * alphanumeric characters or the underscore character,
+ * false otherwise.
+ * @param string $c the string in question
+ * @return bool true if $c is alphanumeric or underscore, false if not
+ */
+ public static function isAlphanum($c) {
+ return (preg_match("/^[a-zA-Z0-9\_]+$/", $c) ? true : false);
+ }
+
+ /**
+ * This function is not part of the reference implementation pseudo code
+ * found in the CPE 2.3 specification. It enforces two rules in the
+ * specification:
+ * URI must start with the characters "cpe:/"
+ * A URI may not contain more than 7 components
+ * If either rule is violated, a Exception is thrown.
+ * @param $in string with URI to be validated
+ */
+ public static function validateURI($in) {
+ // make sure uri starts with cpe:/
+ if (strpos(strtolower($in), "cpe:/") !== 0) {
+ throw new Exception("Error: URI must start with 'cpe:/'. Given: " . $in, 0);
+ }
+ // make sure uri doesn't contain more than 7 colons
+ $count = sizeof(explode(":", $in));
+ if ($count > 8) {
+ throw new Exception("Error parsing URI. Found " . ($count - 8) . " extra components in: " . $in, 0);
+ }
+ }
+
+ /**
+ * This function is not part of the reference implementation pseudo code
+ * found in the CPE 2.3 specification. It enforces three rules found in the
+ * specification:
+ * Formatted string must start with the characters "cpe:2.3:"
+ * A formatted string must contain 11 components
+ * A formatted string must not contain empty components
+ * If any rule is violated, a ParseException is thrown.
+ * @param $in string with FS to be validated
+ */
+ public static function validateFS($in) {
+ if (strpos(strtolower($in), "cpe:2.3:") !== 0) {
+ throw new Exception("Error: Formatted String must start with \"cpe:2.3\". Given: " . $in, 0);
+ }
+
+ $count = 0;
+ for ($i = 0; $i != strlen($in); $i++){
+ if (substr($in, $i, 1) == ":"){
+ if (substr($in, $i - 1, 1) != "\\"){
+ $count++;
+ }
+ if (($i+1) < strlen($in) && substr($in, $i+1, 1) == ":"){
+ throw new Exception("Error parsing formatted string. Found empty component", 0);
+ }
+ }
+ }
+ if ($count > 12){
+ $extra = $count - 12;
+ $s = "Error parsing formatted string. Found " . $extra . " extra component";
+ if ($extra > 1){
+ $s = $s . "s";
+ }
+ $s = $s . " in: " . $in;
+ throw new Exception($s, 0);
+ }
+ if ($count < 12){
+ $missing = 12 - $count;
+ $s = "Error parsing formatted string. Missing " . $missing . " component";
+ if ($missing > 1){
+ $s = $s . "s";
+ }
+ throw new Exception($s, 0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/inc/vendor/pacificsec/cpe/src/Common/WellFormedName.php b/inc/vendor/pacificsec/cpe/src/Common/WellFormedName.php
new file mode 100644
index 0000000..e3a7253
--- /dev/null
+++ b/inc/vendor/pacificsec/cpe/src/Common/WellFormedName.php
@@ -0,0 +1,210 @@
+.
+ *
+ * @see cpe.mitre.org for details.
+ * @author Antonio Franco
+ * @email antonio.franco@pacificsec.com
+ */
+class WellFormedName {
+
+ // Underlying wfn representation.
+ private $wfn = null;
+ // All permissible WFN attributes as defined by specification.
+ private $attributes = array("part", "vendor", "product", "version",
+ "update", "edition", "language", "sw_edition", "target_sw",
+ "target_hw", "other");
+
+ /**
+ * Constructs a new WellFormedName object, setting each component to the
+ * given parameter value. If a parameter is null, the component is set to
+ * the default value "ANY".
+ * @param $part string representing the part component
+ * @param $vendor string representing the vendor component
+ * @param $product string representing the product component
+ * @param $version string representing the version component
+ * @param $update string representing the update component
+ * @param $edition string representing the edition component
+ * @param $language string representing the language component
+ * @param $sw_edition string representing the sw_edition component
+ * @param $target_sw string representing the target_sw component
+ * @param $target_hw string representing the target_hw component
+ * @param $other string representing the other component
+ */
+ public function __construct($part = null, $vendor = null, $product = null, $version = null,
+ $update = null, $edition = null, $language = null, $sw_edition = null, $target_sw = null,
+ $target_hw = null, $other = null) {
+
+ $this->wfn = array();
+
+ // Constructs a new WellFormedName object, with all components set to the default value "ANY".
+ if ($part === null && $vendor === null && $product === null && $version === null &&
+ $update === null && $edition === null && $language === null && $sw_edition === null && $target_sw === null &&
+ $target_hw === null && $other === null){
+ foreach ($this->attributes as $a){
+ if ($a != "part"){
+ $this->set($a, new LogicalValue("ANY"));
+ }
+ }
+ return;
+ }
+
+ $this->set("part", $part);
+ $this->set("vendor", $vendor);
+ $this->set("product", $product);
+ $this->set("version", $version);
+ $this->set("update", $update);
+ $this->set("edition", $edition);
+ $this->set("language", $language);
+ $this->set("sw_edition", $sw_edition);
+ $this->set("target_sw", $target_sw);
+ $this->set("target_hw", $target_hw);
+ $this->set("other", $other);
+ }
+
+ /**
+ * @param $attribute string representing the component value to get
+ * @return string the string value of the given component, or default value "ANY"
+ * if the component does not exist
+ */
+ public function get($attribute){
+ if (array_key_exists($attribute, $this->wfn))
+ return $this->wfn[$attribute];
+ else
+ return new LogicalValue("ANY");
+ }
+
+ /**
+ * Sets the given attribute to value, if the attribute is in the list of
+ * permissible components
+ * @param $attribute string representing the component to set
+ * @param $value object or string representing the value of the given component
+ */
+ public final function set($attribute, $value){
+ // Iterate over permissible attributes.
+ foreach ($this->attributes as $a){
+ // If the argument is a valid attribute, set that attribute's value.
+ if ($attribute == $a) {
+ // check to see if we're setting a LogicalValue ANY or NA
+ if ($value instanceof LogicalValue){
+ // don't allow logical values in part component
+ if ($attribute == "part"){
+ var_dump($value); echo "If you are not automatically redirected, please go to the latest stable API documentation.
' > build/index.html + deploy: + provider: pages + skip-cleanup: true + local-dir: build + github-token: $GITHUB_TOKEN + on: + all_branches: true + condition: $TRAVIS_BRANCH =~ ^master|develop$ diff --git a/inc/vendor/phpoffice/phpspreadsheet/CHANGELOG.md b/inc/vendor/phpoffice/phpspreadsheet/CHANGELOG.md index e2a9bfa..42e6fc2 100644 --- a/inc/vendor/phpoffice/phpspreadsheet/CHANGELOG.md +++ b/inc/vendor/phpoffice/phpspreadsheet/CHANGELOG.md @@ -5,6 +5,95 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [1.4.0] - 2018-08-06 + +### Added + +- Add excel function EXACT(value1, value2) support - [#595](https://github.com/PHPOffice/PhpSpreadsheet/pull/595) +- Support workbook view attributes for Xlsx format - [#523](https://github.com/PHPOffice/PhpSpreadsheet/issues/523) +- Read and write hyperlink for drawing image - [#490](https://github.com/PHPOffice/PhpSpreadsheet/pull/490) +- Added calculation engine support for the new bitwise functions that were added in MS Excel 2013 + - BITAND() Returns a Bitwise 'And' of two numbers + - BITOR() Returns a Bitwise 'Or' of two number + - BITXOR() Returns a Bitwise 'Exclusive Or' of two numbers + - BITLSHIFT() Returns a number shifted left by a specified number of bits + - BITRSHIFT() Returns a number shifted right by a specified number of bits +- Added calculation engine support for other new functions that were added in MS Excel 2013 and MS Excel 2016 + - Text Functions + - CONCAT() Synonym for CONCATENATE() + - NUMBERVALUE() Converts text to a number, in a locale-independent way + - UNICHAR() Synonym for CHAR() in PHPSpreadsheet, which has always used UTF-8 internally + - UNIORD() Synonym for ORD() in PHPSpreadsheet, which has always used UTF-8 internally + - TEXTJOIN() Joins together two or more text strings, separated by a delimiter + - Logical Functions + - XOR() Returns a logical Exclusive Or of all arguments + - Date/Time Functions + - ISOWEEKNUM() Returns the ISO 8601 week number of the year for a given date + - Lookup and Reference Functions + - FORMULATEXT() Returns a formula as a string + - Financial Functions + - PDURATION() Calculates the number of periods required for an investment to reach a specified value + - RRI() Calculates the interest rate required for an investment to grow to a specified future value + - Engineering Functions + - ERF.PRECISE() Returns the error function integrated between 0 and a supplied limit + - ERFC.PRECISE() Synonym for ERFC + - Math and Trig Functions + - SEC() Returns the secant of an angle + - SECH() Returns the hyperbolic secant of an angle + - CSC() Returns the cosecant of an angle + - CSCH() Returns the hyperbolic cosecant of an angle + - COT() Returns the cotangent of an angle + - COTH() Returns the hyperbolic cotangent of an angle + - ACOT() Returns the cotangent of an angle + - ACOTH() Returns the hyperbolic cotangent of an angle +- Refactored Complex Engineering Functions to use external complex number library +- Added calculation engine support for the new complex number functions that were added in MS Excel 2013 + - IMCOSH() Returns the hyperbolic cosine of a complex number + - IMCOT() Returns the cotangent of a complex number + - IMCSC() Returns the cosecant of a complex number + - IMCSCH() Returns the hyperbolic cosecant of a complex number + - IMSEC() Returns the secant of a complex number + - IMSECH() Returns the hyperbolic secant of a complex number + - IMSINH() Returns the hyperbolic sine of a complex number + - IMTAN() Returns the tangent of a complex number + +### Fixed + +- Fix ISFORMULA() function to work with a cell reference to another worksheet +- Xlsx reader crashed when reading a file with workbook protection - [#553](https://github.com/PHPOffice/PhpSpreadsheet/pull/553) +- Cell formats with escaped spaces were causing incorrect date formatting - [#557](https://github.com/PHPOffice/PhpSpreadsheet/issues/557) +- Could not open CSV file containing HTML fragment - [#564](https://github.com/PHPOffice/PhpSpreadsheet/issues/564) +- Exclude the vendor folder in migration - [#481](https://github.com/PHPOffice/PhpSpreadsheet/issues/481) +- Chained operations on cell ranges involving borders operated on last cell only [#428](https://github.com/PHPOffice/PhpSpreadsheet/issues/428) +- Avoid memory exhaustion when cloning worksheet with a drawing [#437](https://github.com/PHPOffice/PhpSpreadsheet/issues/437) +- Migration tool keep variables containing $PHPExcel untouched [#598](https://github.com/PHPOffice/PhpSpreadsheet/issues/598) +- Rowspans/colspans were incorrect when adding worksheet using loadIntoExisting [#619](https://github.com/PHPOffice/PhpSpreadsheet/issues/619) + +## [1.3.1] - 2018-06-12 + +### Fixed + +- Ranges across Z and AA columns incorrectly threw an exception - [#545](https://github.com/PHPOffice/PhpSpreadsheet/issues/545) + +## [1.3.0] - 2018-06-10 + +### Added + +- Support to read Xlsm templates with form elements, macros, printer settings, protected elements and back compatibility drawing, and save result without losing important elements of document - [#435](https://github.com/PHPOffice/PhpSpreadsheet/issues/435) +- Expose sheet title maximum length as `Worksheet::SHEET_TITLE_MAXIMUM_LENGTH` - [#482](https://github.com/PHPOffice/PhpSpreadsheet/issues/482) +- Allow escape character to be set in CSV reader – [#492](https://github.com/PHPOffice/PhpSpreadsheet/issues/492) + +### Fixed + +- Subtotal 9 in a group that has other subtotals 9 exclude the totals of the other subtotals in the range - [#332](https://github.com/PHPOffice/PhpSpreadsheet/issues/332) +- `Helper\Html` support UTF-8 HTML input - [#444](https://github.com/PHPOffice/PhpSpreadsheet/issues/444) +- Xlsx loaded an extra empty comment for each real comment - [#375](https://github.com/PHPOffice/PhpSpreadsheet/issues/375) +- Xlsx reader do not read rows and columns filtered out in readFilter at all - [#370](https://github.com/PHPOffice/PhpSpreadsheet/issues/370) +- Make newer Excel versions properly recalculate formulas on document open - [#456](https://github.com/PHPOffice/PhpSpreadsheet/issues/456) +- `Coordinate::extractAllCellReferencesInRange()` throws an exception for an invalid range – [#519](https://github.com/PHPOffice/PhpSpreadsheet/issues/519) +- Fixed parsing of conditionals in COUNTIF functions - [#526](https://github.com/PHPOffice/PhpSpreadsheet/issues/526) +- Corruption errors for saved Xlsx docs with frozen panes - [#532](https://github.com/PHPOffice/PhpSpreadsheet/issues/532) + ## [1.2.1] - 2018-04-10 ### Fixed diff --git a/inc/vendor/phpoffice/phpspreadsheet/README.md b/inc/vendor/phpoffice/phpspreadsheet/README.md index 0a138d7..e63e26e 100644 --- a/inc/vendor/phpoffice/phpspreadsheet/README.md +++ b/inc/vendor/phpoffice/phpspreadsheet/README.md @@ -18,9 +18,7 @@ PhpSpreadsheet is a library written in pure PHP and providing a set of classes t ## Documentation -Read more about it, including install instructions, in the official documentation: - -https://phpspreadsheet.readthedocs.io +Read more about it, including install instructions, in the [official documentation](https://phpspreadsheet.readthedocs.io). Or check out the [API documentation](https://phpoffice.github.io/PhpSpreadsheet/master). Please ask your support questions on [StackOverflow](http://stackoverflow.com/questions/tagged/phpspreadsheet), or have a quick chat on [Gitter](https://gitter.im/PHPOffice/PhpSpreadsheet). diff --git a/inc/vendor/phpoffice/phpspreadsheet/composer.json b/inc/vendor/phpoffice/phpspreadsheet/composer.json index 1c033bb..4a08707 100644 --- a/inc/vendor/phpoffice/phpspreadsheet/composer.json +++ b/inc/vendor/phpoffice/phpspreadsheet/composer.json @@ -25,7 +25,7 @@ "scripts": { "check": [ "php-cs-fixer fix --ansi --dry-run --diff", - "phpcs --report-width=200 --report-summary --report-full samples/ src/ tests/ --ignore=samples/Header.php --standard=PSR2 -n", + "phpcs --report-width=200 samples/ src/ tests/ --ignore=samples/Header.php --standard=PSR2 -n", "phpunit --color=always" ], "fix": [ @@ -46,16 +46,17 @@ "ext-xmlwriter": "*", "ext-zip": "*", "ext-zlib": "*", - "psr/simple-cache": "^1.0" + "psr/simple-cache": "^1.0", + "markbaker/complex": "^1.4.1" }, "require-dev": { "tecnickcom/tcpdf": "^6.2", - "squizlabs/php_codesniffer": "^2.7", "phpunit/phpunit": "^5.7", "dompdf/dompdf": "^0.8.0", "mpdf/mpdf": "^7.0.0", "jpgraph/jpgraph": "^4.0", - "friendsofphp/php-cs-fixer": "@stable" + "friendsofphp/php-cs-fixer": "@stable", + "squizlabs/php_codesniffer": "^3.3" }, "suggest": { "mpdf/mpdf": "Option for rendering PDF with PDF Writer", diff --git a/inc/vendor/phpoffice/phpspreadsheet/composer.lock b/inc/vendor/phpoffice/phpspreadsheet/composer.lock index 2991465..fe9fbc6 100644 --- a/inc/vendor/phpoffice/phpspreadsheet/composer.lock +++ b/inc/vendor/phpoffice/phpspreadsheet/composer.lock @@ -1,11 +1,106 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e61a906bd83393400add286703f10557", + "content-hash": "66067b3ab7afd673a28cf0b31eb9ae20", "packages": [ + { + "name": "markbaker/complex", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPComplex.git", + "reference": "615f5443473cf37729666e2354fd8dfa2cb48e91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/615f5443473cf37729666e2354fd8dfa2cb48e91", + "reference": "615f5443473cf37729666e2354fd8dfa2cb48e91", + "shasum": "" + }, + "require": { + "php": "^5.6.0|^7.0.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3", + "phpdocumentor/phpdocumentor": "2.*", + "phploc/phploc": "2.*", + "phpmd/phpmd": "2.*", + "phpunit/phpunit": "^4.8.35|^5.4.0", + "sebastian/phpcpd": "2.*", + "squizlabs/php_codesniffer": "^3.1.1", + "wimg/php-compatibility": "^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Complex\\": "classes/src/" + }, + "files": [ + "classes/src/functions/abs.php", + "classes/src/functions/acos.php", + "classes/src/functions/acosh.php", + "classes/src/functions/acot.php", + "classes/src/functions/acoth.php", + "classes/src/functions/acsc.php", + "classes/src/functions/acsch.php", + "classes/src/functions/argument.php", + "classes/src/functions/asec.php", + "classes/src/functions/asech.php", + "classes/src/functions/asin.php", + "classes/src/functions/asinh.php", + "classes/src/functions/atan.php", + "classes/src/functions/atanh.php", + "classes/src/functions/conjugate.php", + "classes/src/functions/cos.php", + "classes/src/functions/cosh.php", + "classes/src/functions/cot.php", + "classes/src/functions/coth.php", + "classes/src/functions/csc.php", + "classes/src/functions/csch.php", + "classes/src/functions/exp.php", + "classes/src/functions/inverse.php", + "classes/src/functions/ln.php", + "classes/src/functions/log2.php", + "classes/src/functions/log10.php", + "classes/src/functions/negative.php", + "classes/src/functions/pow.php", + "classes/src/functions/rho.php", + "classes/src/functions/sec.php", + "classes/src/functions/sech.php", + "classes/src/functions/sin.php", + "classes/src/functions/sinh.php", + "classes/src/functions/sqrt.php", + "classes/src/functions/tan.php", + "classes/src/functions/tanh.php", + "classes/src/functions/theta.php", + "classes/src/operations/add.php", + "classes/src/operations/subtract.php", + "classes/src/operations/multiply.php", + "classes/src/operations/divideby.php", + "classes/src/operations/divideinto.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@lange.demon.co.uk" + } + ], + "description": "PHP Class for working with complex numbers", + "homepage": "https://github.com/MarkBaker/PHPComplex", + "keywords": [ + "complex", + "mathematics" + ], + "time": "2018-07-24T19:47:28+00:00" + }, { "name": "psr/simple-cache", "version": "1.0.0", @@ -2106,64 +2201,37 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "2.8.1", + "version": "3.3.1", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d" + "reference": "628a481780561150481a9ec74709092b9759b3ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d", - "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/628a481780561150481a9ec74709092b9759b3ec", + "reference": "628a481780561150481a9ec74709092b9759b3ec", "shasum": "" }, "require": { "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": ">=5.1.2" + "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, "bin": [ - "scripts/phpcs", - "scripts/phpcbf" + "bin/phpcs", + "bin/phpcbf" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "3.x-dev" } }, - "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -2180,7 +2248,7 @@ "phpcs", "standards" ], - "time": "2017-03-01T22:17:45+00:00" + "time": "2018-07-26T23:47:18+00:00" }, { "name": "symfony/console", diff --git a/inc/vendor/phpoffice/phpspreadsheet/docs/extra/extra.js b/inc/vendor/phpoffice/phpspreadsheet/docs/extra/extra.js deleted file mode 100644 index fdef958..0000000 --- a/inc/vendor/phpoffice/phpspreadsheet/docs/extra/extra.js +++ /dev/null @@ -1,57 +0,0 @@ -var nodemcu = nodemcu || {}; -(function () { - 'use strict'; - - $(document).ready(function () { - fixSearch(); - }); - - /* - * RTD messes up MkDocs' search feature by tinkering with the search box defined in the theme, see - * https://github.com/rtfd/readthedocs.org/issues/1088. This function sets up a DOM4 MutationObserver - * to react to changes to the search form (triggered by RTD on doc ready). It then reverts everything - * the RTD JS code modified. - */ - function fixSearch() { - var target = document.getElementById('rtd-search-form'); - var config = {attributes: true, childList: true}; - - var observer = new MutationObserver(function (mutations) { - // if it isn't disconnected it'll loop infinitely because the observed element is modified - observer.disconnect(); - var form = $('#rtd-search-form'); - form.empty(); - form.attr('action', 'https://' + window.location.hostname + '/en/' + determineSelectedBranch() + '/search.html'); - $('').attr({ - type: "text", - name: "q", - placeholder: "Search docs" - }).appendTo(form); - }); - - if (window.location.origin.indexOf('readthedocs') > -1) { - observer.observe(target, config); - } - } - - /** - * Analyzes the URL of the current page to find out what the selected GitHub branch is. It's usually - * part of the location path. The code needs to distinguish between running MkDocs standalone - * and docs served from RTD. If no valid branch could be determined 'dev' returned. - * - * @returns GitHub branch name - */ - function determineSelectedBranch() { - var branch = 'dev', path = window.location.pathname; - if (window.location.origin.indexOf('readthedocs') > -1) { - // path is like /en/foo
bar
'], + ]; + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Helper/MigratorTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Helper/MigratorTest.php new file mode 100644 index 0000000..a64cda8 --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Helper/MigratorTest.php @@ -0,0 +1,88 @@ +getMapping() as $classname) { + if (substr_count($classname, '\\')) { + self::assertTrue(class_exists($classname) || interface_exists($classname), 'mapping is wrong, class does not exists in project: ' . $classname); + } + } + } + + public function testReplace() + { + $input = <<<'STRING' +do(); + $fooobjPHPExcel->do(); + $objPHPExcel->do(); + $this->objPHPExcel->do(); + $this->PHPExcel->do(); + + return \PHPExcel_Cell::stringFromColumnIndex(9); + } +} +STRING; + + $expected = <<<'STRING' +do(); + $fooobjPHPExcel->do(); + $objPHPExcel->do(); + $this->objPHPExcel->do(); + $this->PHPExcel->do(); + + return \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex(9); + } +} +STRING; + + $migrator = new Migrator(); + self::assertSame($expected, $migrator->replace($input)); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Helper/SampleTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Helper/SampleTest.php new file mode 100644 index 0000000..be1f50c --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Helper/SampleTest.php @@ -0,0 +1,62 @@ +setOutputCallback(function () { + }); + + require $sample; + } + + public function providerSample() + { + $skipped = [ + 'Chart/32_Chart_read_write_PDF.php', // Unfortunately JpGraph is not up to date for latest PHP and raise many warnings + 'Chart/32_Chart_read_write_HTML.php', // idem + ]; + + // TCPDF does not support PHP 7.2 + if (version_compare(PHP_VERSION, '7.2.0') >= 0) { + $skipped[] = 'Pdf/21_Pdf_TCPDF.php'; + } + + // Unfortunately some tests are too long be ran with code-coverage + // analysis on Travis, so we need to exclude them + global $argv; + if (in_array('--coverage-clover', $argv)) { + $tooLongToBeCovered = [ + 'Basic/06_Largescale.php', + 'Basic/13_CalculationCyclicFormulae.php', + ]; + $skipped = array_merge($skipped, $tooLongToBeCovered); + } + + $helper = new Sample(); + $result = []; + foreach ($helper->getSamples() as $samples) { + foreach ($samples as $sample) { + if (!in_array($sample, $skipped)) { + $file = '../samples/' . $sample; + $result[] = [$file]; + } + } + } + + return $result; + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/IOFactoryTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/IOFactoryTest.php new file mode 100644 index 0000000..4c9c52d --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/IOFactoryTest.php @@ -0,0 +1,147 @@ +expectException(\InvalidArgumentException::class); + + IOFactory::identify('/non/existing/file'); + } + + public function testIdentifyExistingDirectoryThrowExceptions() + { + $this->expectException(\InvalidArgumentException::class); + + IOFactory::identify('.'); + } + + public function testRegisterInvalidWriter() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Writer\Exception::class); + + IOFactory::registerWriter('foo', 'bar'); + } + + public function testRegisterInvalidReader() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Reader\Exception::class); + + IOFactory::registerReader('foo', 'bar'); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/CsvTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/CsvTest.php new file mode 100644 index 0000000..eeddbb0 --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/CsvTest.php @@ -0,0 +1,109 @@ +getDelimiter()); + + $spreadsheet = $reader->load($filename); + + self::assertSame($expectedDelimiter, $reader->getDelimiter(), 'should be able to infer the delimiter'); + + $actual = $spreadsheet->getActiveSheet()->getCell($cell)->getValue(); + self::assertSame($expectedValue, $actual, 'should be able to retrieve correct value'); + } + + public function providerDelimiterDetection() + { + return [ + [ + __DIR__ . '/../../data/Reader/CSV/enclosure.csv', + ',', + 'C4', + 'username2', + ], + [ + __DIR__ . '/../../data/Reader/CSV/semicolon_separated.csv', + ';', + 'C2', + '25,5', + ], + [ + __DIR__ . '/../../data/Reader/HTML/csv_with_angle_bracket.csv', + ',', + 'B1', + 'Number of items with weight <= 50kg', + ], + [ + __DIR__ . '/../../../samples/Reader/sampleData/example1.csv', + ',', + 'I4', + '100%', + ], + [ + __DIR__ . '/../../../samples/Reader/sampleData/example2.csv', + ',', + 'D8', + -58.373161, + ], + ]; + } + + /** + * @dataProvider providerCanLoad + * + * @param bool $expected + * @param string $filename + */ + public function testCanLoad($expected, $filename) + { + $reader = new Csv(); + self::assertSame($expected, $reader->canRead($filename)); + } + + public function providerCanLoad() + { + return [ + [false, 'data/Reader/Ods/data.ods'], + [false, 'data/Reader/Xml/WithoutStyle.xml'], + [true, 'data/Reader/CSV/enclosure.csv'], + [true, 'data/Reader/CSV/semicolon_separated.csv'], + [true, 'data/Reader/CSV/contains_html.csv'], + [true, 'data/Reader/CSV/csv_without_extension'], + [true, 'data/Reader/HTML/csv_with_angle_bracket.csv'], + [true, 'data/Reader/CSV/empty.csv'], + [true, '../samples/Reader/sampleData/example1.csv'], + [true, '../samples/Reader/sampleData/example2.csv'], + ]; + } + + public function testEscapeCharacters() + { + $reader = (new Csv())->setEscapeCharacter('"'); + $worksheet = $reader->load(__DIR__ . '/../../data/Reader/CSV/backslash.csv') + ->getActiveSheet(); + + $expected = [ + ['field 1', 'field 2\\'], + ['field 3\\', 'field 4'], + ]; + + $this->assertSame('"', $reader->getEscapeCharacter()); + $this->assertSame($expected, $worksheet->toArray()); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/HtmlTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/HtmlTest.php new file mode 100644 index 0000000..9f9b11e --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/HtmlTest.php @@ -0,0 +1,46 @@ +canRead($filename)); + } + + public function providerCanReadVerySmallFile() + { + $padding = str_repeat('a', 2048); + + return [ + [true, ' ' . $padding . ' '], + [true, ' ' . $padding . ''], + [true, ''], + [false, ''], + ]; + } + + /** + * @dataProvider providerCanReadVerySmallFile + * + * @param bool $expected + * @param string $content + */ + public function testCanReadVerySmallFile($expected, $content) + { + $filename = tempnam(sys_get_temp_dir(), 'html'); + file_put_contents($filename, $content); + + $reader = new Html(); + $actual = $reader->canRead($filename); + unlink($filename); + + self::assertSame($expected, $actual); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/OdsTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/OdsTest.php new file mode 100644 index 0000000..a6edaee --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/OdsTest.php @@ -0,0 +1,225 @@ +spreadsheetOdsTest) { + $filename = __DIR__ . '/../../../samples/templates/OOCalcTest.ods'; + + // Load into this instance + $reader = new Ods(); + $this->spreadsheetOdsTest = $reader->loadIntoExisting($filename, new Spreadsheet()); + } + + return $this->spreadsheetOdsTest; + } + + /** + * @return Spreadsheet + */ + protected function loadDataFile() + { + if (!$this->spreadsheetData) { + $filename = __DIR__ . '/../../data/Reader/Ods/data.ods'; + + // Load into this instance + $reader = new Ods(); + $this->spreadsheetData = $reader->loadIntoExisting($filename, new Spreadsheet()); + } + + return $this->spreadsheetData; + } + + public function testReadFileProperties() + { + $filename = __DIR__ . '/../../data/Reader/Ods/data.ods'; + + // Load into this instance + $reader = new Ods(); + + // Test "listWorksheetNames" method + + self::assertEquals([ + 'Sheet1', + 'Second Sheet', + ], $reader->listWorksheetNames($filename)); + } + + public function testLoadWorksheets() + { + $spreadsheet = $this->loadDataFile(); + + self::assertInstanceOf('PhpOffice\PhpSpreadsheet\Spreadsheet', $spreadsheet); + + self::assertEquals(2, $spreadsheet->getSheetCount()); + + $firstSheet = $spreadsheet->getSheet(0); + self::assertInstanceOf('PhpOffice\PhpSpreadsheet\Worksheet\Worksheet', $firstSheet); + + $secondSheet = $spreadsheet->getSheet(1); + self::assertInstanceOf('PhpOffice\PhpSpreadsheet\Worksheet\Worksheet', $secondSheet); + } + + public function testReadValueAndComments() + { + $spreadsheet = $this->loadOdsTestFile(); + + $firstSheet = $spreadsheet->getSheet(0); + + self::assertEquals(29, $firstSheet->getHighestRow()); + self::assertEquals('N', $firstSheet->getHighestColumn()); + + // Simple cell value + self::assertEquals('Test String 1', $firstSheet->getCell('A1')->getValue()); + + // Merged cell + self::assertEquals('BOX', $firstSheet->getCell('B18')->getValue()); + + // Comments/Annotations + self::assertEquals( + 'Test for a simple colour-formatted string', + $firstSheet->getComment('A1')->getText()->getPlainText() + ); + + // Data types + self::assertEquals(DataType::TYPE_STRING, $firstSheet->getCell('A1')->getDataType()); + self::assertEquals(DataType::TYPE_NUMERIC, $firstSheet->getCell('B1')->getDataType()); // Int + + self::assertEquals(DataType::TYPE_NUMERIC, $firstSheet->getCell('B6')->getDataType()); // Float + self::assertEquals(1.23, $firstSheet->getCell('B6')->getValue()); + self::assertEquals(0, $firstSheet->getCell('G10')->getValue()); + + self::assertEquals(DataType::TYPE_NUMERIC, $firstSheet->getCell('A10')->getDataType()); // Date + self::assertEquals(22269.0, $firstSheet->getCell('A10')->getValue()); + + self::assertEquals(DataType::TYPE_NUMERIC, $firstSheet->getCell('A13')->getDataType()); // Time + self::assertEquals(25569.0625, $firstSheet->getCell('A13')->getValue()); + + self::assertEquals(DataType::TYPE_NUMERIC, $firstSheet->getCell('A15')->getDataType()); // Date + Time + self::assertEquals(22269.0625, $firstSheet->getCell('A15')->getValue()); + + self::assertEquals(DataType::TYPE_NUMERIC, $firstSheet->getCell('A11')->getDataType()); // Fraction + + self::assertEquals(DataType::TYPE_BOOL, $firstSheet->getCell('D6')->getDataType()); + self::assertTrue($firstSheet->getCell('D6')->getValue()); + + self::assertEquals(DataType::TYPE_FORMULA, $firstSheet->getCell('C6')->getDataType()); // Formula + self::assertEquals('=TRUE()', $firstSheet->getCell('C6')->getValue()); // Formula + + // Percentage, Currency + + $spreadsheet = $this->loadDataFile(); + + $firstSheet = $spreadsheet->getSheet(0); + + self::assertEquals(DataType::TYPE_NUMERIC, $firstSheet->getCell('A1')->getDataType()); // Percentage (10%) + self::assertEquals(0.1, $firstSheet->getCell('A1')->getValue()); + + self::assertEquals(DataType::TYPE_NUMERIC, $firstSheet->getCell('A2')->getDataType()); // Percentage (10.00%) + self::assertEquals(0.1, $firstSheet->getCell('A2')->getValue()); + + self::assertEquals(DataType::TYPE_NUMERIC, $firstSheet->getCell('A4')->getDataType()); // Currency (€10.00) + self::assertEquals(10, $firstSheet->getCell('A4')->getValue()); + + self::assertEquals(DataType::TYPE_NUMERIC, $firstSheet->getCell('A5')->getDataType()); // Currency ($20) + self::assertEquals(20, $firstSheet->getCell('A5')->getValue()); + } + + public function testReadColors() + { + $spreadsheet = $this->loadOdsTestFile(); + $firstSheet = $spreadsheet->getSheet(0); + + // Background color + + $style = $firstSheet->getCell('K3')->getStyle(); + + self::assertEquals('none', $style->getFill()->getFillType()); + self::assertEquals('FFFFFFFF', $style->getFill()->getStartColor()->getARGB()); + self::assertEquals('FF000000', $style->getFill()->getEndColor()->getARGB()); + } + + public function testReadRichText() + { + $spreadsheet = $this->loadOdsTestFile(); + $firstSheet = $spreadsheet->getSheet(0); + + self::assertEquals( + "I don't know if OOCalc supports Rich Text in the same way as Excel, " . + 'And this row should be autofit height with text wrap', + $firstSheet->getCell('A28')->getValue() + ); + } + + public function testReadCellsWithRepeatedSpaces() + { + $spreadsheet = $this->loadDataFile(); + $firstSheet = $spreadsheet->getSheet(0); + + self::assertEquals('This has 4 spaces before and 2 after ', $firstSheet->getCell('A8')->getValue()); + self::assertEquals('This only one after ', $firstSheet->getCell('A9')->getValue()); + self::assertEquals('Test with DIFFERENT styles and multiple spaces: ', $firstSheet->getCell('A10')->getValue()); + self::assertEquals("test with new \nLines", $firstSheet->getCell('A11')->getValue()); + } + + public function testReadHyperlinks() + { + $spreadsheet = $this->loadOdsTestFile(); + $firstSheet = $spreadsheet->getSheet(0); + + $hyperlink = $firstSheet->getCell('A29'); + + self::assertEquals(DataType::TYPE_STRING, $hyperlink->getDataType()); + self::assertEquals('PhpSpreadsheet', $hyperlink->getValue()); + self::assertEquals('https://github.com/PHPOffice/phpspreadsheet', $hyperlink->getHyperlink()->getUrl()); + } + + // Below some test for features not implemented yet + + public function testReadBoldItalicUnderline() + { + $this->markTestIncomplete('Features not implemented yet'); + + $spreadsheet = $this->loadOdsTestFile(); + $firstSheet = $spreadsheet->getSheet(0); + + // Font styles + + $style = $firstSheet->getCell('A1')->getStyle(); + self::assertEquals('FF000000', $style->getFont()->getColor()->getARGB()); + self::assertEquals(11, $style->getFont()->getSize()); + self::assertEquals(Font::UNDERLINE_NONE, $style->getFont()->getUnderline()); + + $style = $firstSheet->getCell('E3')->getStyle(); + self::assertEquals(Font::UNDERLINE_SINGLE, $style->getFont()->getUnderline()); + + $style = $firstSheet->getCell('E1')->getStyle(); + self::assertTrue($style->getFont()->getBold()); + self::assertTrue($style->getFont()->getItalic()); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/XlsxTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/XlsxTest.php new file mode 100644 index 0000000..fd14714 --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/XlsxTest.php @@ -0,0 +1,19 @@ +load($filename); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/XmlTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/XmlTest.php new file mode 100644 index 0000000..763e177 --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Reader/XmlTest.php @@ -0,0 +1,105 @@ +expectException(\PhpOffice\PhpSpreadsheet\Reader\Exception::class); + + $reader = $this->getMockForAbstractClass(BaseReader::class); + $expectedResult = 'FAILURE: Should throw an Exception rather than return a value'; + $result = $reader->securityScanFile($filename); + self::assertEquals($expectedResult, $result); + } + + public function providerInvalidXML() + { + $tests = []; + foreach (glob(__DIR__ . '/../../data/Reader/Xml/XEETestInvalidUTF*.xml') as $file) { + $tests[basename($file)] = [realpath($file)]; + } + + return $tests; + } + + /** + * @dataProvider providerInvalidSimpleXML + * + * @param $filename + */ + public function testInvalidSimpleXML($filename) + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Reader\Exception::class); + + $xmlReader = new Xml(); + $xmlReader->trySimpleXMLLoadString($filename); + } + + public function providerInvalidSimpleXML() + { + $tests = []; + foreach (glob(__DIR__ . '/../../data/Reader/Xml/XEETestInvalidSimpleXML*.xml') as $file) { + $tests[basename($file)] = [realpath($file)]; + } + + return $tests; + } + + /** + * @dataProvider providerValidXML + * + * @param mixed $filename + * @param mixed $expectedResult + */ + public function testValidXML($filename, $expectedResult) + { + $reader = $this->getMockForAbstractClass(BaseReader::class); + $result = $reader->securityScanFile($filename); + self::assertEquals($expectedResult, $result); + } + + public function providerValidXML() + { + $tests = []; + foreach (glob(__DIR__ . '/../../data/Reader/Xml/XEETestValid*.xml') as $file) { + $tests[basename($file)] = [realpath($file), file_get_contents($file)]; + } + + return $tests; + } + + /** + * Check if it can read XML Hyperlink correctly. + */ + public function testReadHyperlinks() + { + $reader = new Xml(); + $spreadsheet = $reader->load('../samples/templates/Excel2003XMLTest.xml'); + $firstSheet = $spreadsheet->getSheet(0); + + $hyperlink = $firstSheet->getCell('L1'); + + self::assertEquals(DataType::TYPE_STRING, $hyperlink->getDataType()); + self::assertEquals('PhpSpreadsheet', $hyperlink->getValue()); + self::assertEquals('http://phpspreadsheet.readthedocs.io/', $hyperlink->getHyperlink()->getUrl()); + } + + public function testReadWithoutStyle() + { + $reader = new Xml(); + $spreadsheet = $reader->load(__DIR__ . '/../../data/Reader/Xml/WithoutStyle.xml'); + self::assertSame('Test String 1', $spreadsheet->getActiveSheet()->getCell('A1')->getValue()); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/ReferenceHelperTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/ReferenceHelperTest.php new file mode 100644 index 0000000..08b290d --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/ReferenceHelperTest.php @@ -0,0 +1,56 @@ + $value) { + self::assertEquals($columnExpectedResult[$key], $value); + } + } + + public function testColumnReverseSort() + { + $columnBase = $columnExpectedResult = [ + 'A', 'B', 'Z', + 'AA', 'AB', 'AZ', + 'BA', 'BB', 'BZ', + 'ZA', 'ZB', 'ZZ', + 'AAA', 'AAB', 'AAZ', + 'ABA', 'ABB', 'ABZ', + 'AZA', 'AZB', 'AZZ', + 'BAA', 'BAB', 'BAZ', + 'BBA', 'BBB', 'BBZ', + 'BZA', 'BZB', 'BZZ', + ]; + shuffle($columnBase); + $columnExpectedResult = array_reverse($columnExpectedResult); + usort($columnBase, [ReferenceHelper::class, 'columnReverseSort']); + foreach ($columnBase as $key => $value) { + self::assertEquals($columnExpectedResult[$key], $value); + } + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/SettingsTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/SettingsTest.php new file mode 100644 index 0000000..6878986 --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/SettingsTest.php @@ -0,0 +1,40 @@ +prevValue = libxml_disable_entity_loader(); + libxml_disable_entity_loader(false); // Enable entity loader + } + + protected function tearDown() + { + libxml_disable_entity_loader($this->prevValue); + } + + public function testGetXMLSettings() + { + $result = Settings::getLibXmlLoaderOptions(); + self::assertTrue((bool) ((LIBXML_DTDLOAD | LIBXML_DTDATTR) & $result)); + self::assertFalse(libxml_disable_entity_loader()); + } + + public function testSetXMLSettings() + { + Settings::setLibXmlLoaderOptions(LIBXML_DTDLOAD | LIBXML_DTDATTR | LIBXML_DTDVALID); + $result = Settings::getLibXmlLoaderOptions(); + self::assertTrue((bool) ((LIBXML_DTDLOAD | LIBXML_DTDATTR | LIBXML_DTDVALID) & $result)); + self::assertFalse(libxml_disable_entity_loader()); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Shared/CodePageTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Shared/CodePageTest.php new file mode 100644 index 0000000..b0e5fbf --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Shared/CodePageTest.php @@ -0,0 +1,54 @@ +getMessage(), 'Unknown codepage: 12345'); + + return; + } + $this->fail('An expected exception has not been raised.'); + } + + public function testNumberToNameWithUnsupportedCodePage() + { + $unsupportedCodePage = 720; + + try { + CodePage::numberToName($unsupportedCodePage); + } catch (Exception $e) { + self::assertEquals($e->getMessage(), 'Code page 720 not supported.'); + + return; + } + $this->fail('An expected exception has not been raised.'); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Shared/DateTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Shared/DateTest.php new file mode 100644 index 0000000..4a5479e --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Shared/DateTest.php @@ -0,0 +1,171 @@ +getActiveSheet(); + + $argb = 'FFFF0000'; + $color = new Color($argb); + + $sheet->getStyle('A1:C1')->getBorders()->getTop()->setBorderStyle(Border::BORDER_THIN)->setColor($color); + $sheet->getStyle('A1:A3')->getBorders()->getLeft()->setBorderStyle(Border::BORDER_THIN)->setColor($color); + $sheet->getStyle('C1:C3')->getBorders()->getRight()->setBorderStyle(Border::BORDER_THIN)->setColor($color); + $sheet->getStyle('A3:C3')->getBorders()->getBottom()->setBorderStyle(Border::BORDER_THIN)->setColor($color); + + // upper row + $expectations = [ + // cell => Left/Right/Top/Bottom + 'A1' => 'LT', + 'B1' => 'T', + 'C1' => 'RT', + 'A2' => 'L', + 'B2' => '', + 'C2' => 'R', + 'A3' => 'LB', + 'B3' => 'B', + 'C3' => 'RB', + ]; + $sides = [ + 'L' => 'Left', + 'R' => 'Right', + 'T' => 'Top', + 'B' => 'Bottom', + ]; + + foreach ($expectations as $cell => $borders) { + $bs = $sheet->getStyle($cell)->getBorders(); + foreach ($sides as $sidekey => $side) { + $assertion = "setBorderStyle on a range of cells, $cell $side"; + $func = "get$side"; + $b = $bs->$func(); // boo + + if (strpos($borders, $sidekey) === false) { + self::assertSame(Border::BORDER_NONE, $b->getBorderStyle(), $assertion); + } else { + self::assertSame(Border::BORDER_THIN, $b->getBorderStyle(), $assertion); + self::assertSame($argb, $b->getColor()->getARGB(), $assertion); + } + } + } + } + + public function testBorderRangeDirectly() + { + // testcase for the underlying problem directly + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $style = $sheet->getStyle('A1:C1')->getBorders()->getTop()->setBorderStyle(Border::BORDER_THIN); + self::assertSame('A1:C1', $style->getSelectedCells(), 'getSelectedCells should not change after a style operation on a border range'); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Style/BorderTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Style/BorderTest.php new file mode 100644 index 0000000..7efe935 --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Style/BorderTest.php @@ -0,0 +1,26 @@ +getActiveSheet()->getStyle('A1')->getBorders(); + $allBorders = $borders->getAllBorders(); + $bottom = $borders->getBottom(); + + $actual = $bottom->getBorderStyle(); + self::assertSame(Border::BORDER_NONE, $actual, 'should default to none'); + + $allBorders->setBorderStyle(Border::BORDER_THIN); + + $actual = $bottom->getBorderStyle(); + self::assertSame(Border::BORDER_THIN, $actual, 'should have been set via allBorders'); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Style/ColorTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Style/ColorTest.php new file mode 100644 index 0000000..a99c899 --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Style/ColorTest.php @@ -0,0 +1,73 @@ +mockAutoFilterColumnObject = $this->getMockBuilder(Column::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->testAutoFilterRuleObject = new Column\Rule( + $this->mockAutoFilterColumnObject + ); + } + + public function testGetRuleType() + { + $result = $this->testAutoFilterRuleObject->getRuleType(); + self::assertEquals(Column\Rule::AUTOFILTER_RULETYPE_FILTER, $result); + } + + public function testSetRuleType() + { + $expectedResult = Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP; + + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterRuleObject->setRuleType($expectedResult); + self::assertInstanceOf(Column\Rule::class, $result); + + $result = $this->testAutoFilterRuleObject->getRuleType(); + self::assertEquals($expectedResult, $result); + } + + public function testSetValue() + { + $expectedResult = 100; + + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterRuleObject->setValue($expectedResult); + self::assertInstanceOf(Column\Rule::class, $result); + + $result = $this->testAutoFilterRuleObject->getValue(); + self::assertEquals($expectedResult, $result); + } + + public function testGetOperator() + { + $result = $this->testAutoFilterRuleObject->getOperator(); + self::assertEquals(Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL, $result); + } + + public function testSetOperator() + { + $expectedResult = Column\Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN; + + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterRuleObject->setOperator($expectedResult); + self::assertInstanceOf(Column\Rule::class, $result); + + $result = $this->testAutoFilterRuleObject->getOperator(); + self::assertEquals($expectedResult, $result); + } + + public function testSetGrouping() + { + $expectedResult = Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH; + + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterRuleObject->setGrouping($expectedResult); + self::assertInstanceOf(Column\Rule::class, $result); + + $result = $this->testAutoFilterRuleObject->getGrouping(); + self::assertEquals($expectedResult, $result); + } + + public function testGetParent() + { + $result = $this->testAutoFilterRuleObject->getParent(); + self::assertInstanceOf(Column::class, $result); + } + + public function testSetParent() + { + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterRuleObject->setParent($this->mockAutoFilterColumnObject); + self::assertInstanceOf(Column\Rule::class, $result); + } + + public function testClone() + { + $result = clone $this->testAutoFilterRuleObject; + self::assertInstanceOf(Column\Rule::class, $result); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/ColumnTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/ColumnTest.php new file mode 100644 index 0000000..9ce636d --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/ColumnTest.php @@ -0,0 +1,176 @@ +mockAutoFilterObject = $this->getMockBuilder(AutoFilter::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->mockAutoFilterObject->expects($this->any()) + ->method('testColumnInRange') + ->will($this->returnValue(3)); + + $this->testAutoFilterColumnObject = new AutoFilter\Column($this->testInitialColumn, $this->mockAutoFilterObject); + } + + public function testGetColumnIndex() + { + $result = $this->testAutoFilterColumnObject->getColumnIndex(); + self::assertEquals($this->testInitialColumn, $result); + } + + public function testSetColumnIndex() + { + $expectedResult = 'L'; + + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterColumnObject->setColumnIndex($expectedResult); + self::assertInstanceOf(AutoFilter\Column::class, $result); + + $result = $this->testAutoFilterColumnObject->getColumnIndex(); + self::assertEquals($expectedResult, $result); + } + + public function testGetParent() + { + $result = $this->testAutoFilterColumnObject->getParent(); + self::assertInstanceOf(AutoFilter::class, $result); + } + + public function testSetParent() + { + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterColumnObject->setParent($this->mockAutoFilterObject); + self::assertInstanceOf(AutoFilter\Column::class, $result); + } + + public function testGetFilterType() + { + $result = $this->testAutoFilterColumnObject->getFilterType(); + self::assertEquals(AutoFilter\Column::AUTOFILTER_FILTERTYPE_FILTER, $result); + } + + public function testSetFilterType() + { + $result = $this->testAutoFilterColumnObject->setFilterType(AutoFilter\Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER); + self::assertInstanceOf(AutoFilter\Column::class, $result); + + $result = $this->testAutoFilterColumnObject->getFilterType(); + self::assertEquals(AutoFilter\Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER, $result); + } + + public function testSetInvalidFilterTypeThrowsException() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $expectedResult = 'Unfiltered'; + + $this->testAutoFilterColumnObject->setFilterType($expectedResult); + } + + public function testGetJoin() + { + $result = $this->testAutoFilterColumnObject->getJoin(); + self::assertEquals(AutoFilter\Column::AUTOFILTER_COLUMN_JOIN_OR, $result); + } + + public function testSetJoin() + { + $result = $this->testAutoFilterColumnObject->setJoin(AutoFilter\Column::AUTOFILTER_COLUMN_JOIN_AND); + self::assertInstanceOf(AutoFilter\Column::class, $result); + + $result = $this->testAutoFilterColumnObject->getJoin(); + self::assertEquals(AutoFilter\Column::AUTOFILTER_COLUMN_JOIN_AND, $result); + } + + public function testSetInvalidJoinThrowsException() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $expectedResult = 'Neither'; + + $this->testAutoFilterColumnObject->setJoin($expectedResult); + } + + public function testSetAttributes() + { + $attributeSet = [ + 'val' => 100, + 'maxVal' => 200, + ]; + + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterColumnObject->setAttributes($attributeSet); + self::assertInstanceOf(AutoFilter\Column::class, $result); + } + + public function testGetAttributes() + { + $attributeSet = [ + 'val' => 100, + 'maxVal' => 200, + ]; + + $this->testAutoFilterColumnObject->setAttributes($attributeSet); + + $result = $this->testAutoFilterColumnObject->getAttributes(); + self::assertInternalType('array', $result); + self::assertCount(count($attributeSet), $result); + } + + public function testSetAttribute() + { + $attributeSet = [ + 'val' => 100, + 'maxVal' => 200, + ]; + + foreach ($attributeSet as $attributeName => $attributeValue) { + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterColumnObject->setAttribute($attributeName, $attributeValue); + self::assertInstanceOf(AutoFilter\Column::class, $result); + } + } + + public function testGetAttribute() + { + $attributeSet = [ + 'val' => 100, + 'maxVal' => 200, + ]; + + $this->testAutoFilterColumnObject->setAttributes($attributeSet); + + foreach ($attributeSet as $attributeName => $attributeValue) { + $result = $this->testAutoFilterColumnObject->getAttribute($attributeName); + self::assertEquals($attributeValue, $result); + } + $result = $this->testAutoFilterColumnObject->getAttribute('nonExistentAttribute'); + self::assertNull($result); + } + + public function testClone() + { + $originalRule = $this->testAutoFilterColumnObject->createRule(); + $result = clone $this->testAutoFilterColumnObject; + self::assertInstanceOf(AutoFilter\Column::class, $result); + self::assertCount(1, $result->getRules()); + self::assertContainsOnlyInstancesOf(AutoFilter\Column\Rule::class, $result->getRules()); + $clonedRule = $result->getRules()[0]; + self::assertNotSame($originalRule, $clonedRule); + self::assertSame($result, $clonedRule->getParent()); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/AutoFilterTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/AutoFilterTest.php new file mode 100644 index 0000000..6766aac --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/AutoFilterTest.php @@ -0,0 +1,336 @@ +mockWorksheetObject = $this->getMockBuilder(Worksheet::class) + ->disableOriginalConstructor() + ->getMock(); + $this->cellCollection = $this->getMockBuilder(Cells::class) + ->disableOriginalConstructor() + ->getMock(); + $this->mockWorksheetObject->expects($this->any()) + ->method('getCellCollection') + ->will($this->returnValue($this->cellCollection)); + + $this->testAutoFilterObject = new AutoFilter($this->testInitialRange, $this->mockWorksheetObject); + } + + public function testToString() + { + $expectedResult = $this->testInitialRange; + + // magic __toString should return the active autofilter range + $result = $this->testAutoFilterObject; + self::assertEquals($expectedResult, $result); + } + + public function testGetParent() + { + $result = $this->testAutoFilterObject->getParent(); + self::assertInstanceOf(Worksheet::class, $result); + } + + public function testSetParent() + { + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterObject->setParent($this->mockWorksheetObject); + self::assertInstanceOf(AutoFilter::class, $result); + } + + public function testGetRange() + { + $expectedResult = $this->testInitialRange; + + // Result should be the active autofilter range + $result = $this->testAutoFilterObject->getRange(); + self::assertEquals($expectedResult, $result); + } + + public function testSetRange() + { + $ranges = [ + 'G1:J512' => 'Worksheet1!G1:J512', + 'K1:N20' => 'K1:N20', + ]; + + foreach ($ranges as $actualRange => $fullRange) { + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterObject->setRange($fullRange); + self::assertInstanceOf(AutoFilter::class, $result); + + // Result should be the new autofilter range + $result = $this->testAutoFilterObject->getRange(); + self::assertEquals($actualRange, $result); + } + } + + public function testClearRange() + { + $expectedResult = ''; + + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterObject->setRange(''); + self::assertInstanceOf(AutoFilter::class, $result); + + // Result should be a clear range + $result = $this->testAutoFilterObject->getRange(); + self::assertEquals($expectedResult, $result); + } + + public function testSetRangeInvalidRange() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $expectedResult = 'A1'; + + $this->testAutoFilterObject->setRange($expectedResult); + } + + public function testGetColumnsEmpty() + { + // There should be no columns yet defined + $result = $this->testAutoFilterObject->getColumns(); + self::assertInternalType('array', $result); + self::assertCount(0, $result); + } + + public function testGetColumnOffset() + { + $columnIndexes = [ + 'H' => 0, + 'K' => 3, + 'M' => 5, + ]; + + // If we request a specific column by its column ID, we should get an + // integer returned representing the column offset within the range + foreach ($columnIndexes as $columnIndex => $columnOffset) { + $result = $this->testAutoFilterObject->getColumnOffset($columnIndex); + self::assertEquals($columnOffset, $result); + } + } + + public function testGetInvalidColumnOffset() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $invalidColumn = 'G'; + + $this->testAutoFilterObject->getColumnOffset($invalidColumn); + } + + public function testSetColumnWithString() + { + $expectedResult = 'L'; + + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterObject->setColumn($expectedResult); + self::assertInstanceOf(AutoFilter::class, $result); + + $result = $this->testAutoFilterObject->getColumns(); + // Result should be an array of \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\AutoFilter\Column + // objects for each column we set indexed by the column ID + self::assertInternalType('array', $result); + self::assertCount(1, $result); + self::assertArrayHasKey($expectedResult, $result); + self::assertInstanceOf(Column::class, $result[$expectedResult]); + } + + public function testSetInvalidColumnWithString() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $invalidColumn = 'A'; + + $this->testAutoFilterObject->setColumn($invalidColumn); + } + + public function testSetColumnWithColumnObject() + { + $expectedResult = 'M'; + $columnObject = new AutoFilter\Column($expectedResult); + + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterObject->setColumn($columnObject); + self::assertInstanceOf(AutoFilter::class, $result); + + $result = $this->testAutoFilterObject->getColumns(); + // Result should be an array of \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\AutoFilter\Column + // objects for each column we set indexed by the column ID + self::assertInternalType('array', $result); + self::assertCount(1, $result); + self::assertArrayHasKey($expectedResult, $result); + self::assertInstanceOf(Column::class, $result[$expectedResult]); + } + + public function testSetInvalidColumnWithObject() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $invalidColumn = 'E'; + $this->testAutoFilterObject->setColumn($invalidColumn); + } + + public function testSetColumnWithInvalidDataType() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $invalidColumn = 123.456; + $this->testAutoFilterObject->setColumn($invalidColumn); + } + + public function testGetColumns() + { + $columnIndexes = ['L', 'M']; + + foreach ($columnIndexes as $columnIndex) { + $this->testAutoFilterObject->setColumn($columnIndex); + } + + $result = $this->testAutoFilterObject->getColumns(); + // Result should be an array of \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\AutoFilter\Column + // objects for each column we set indexed by the column ID + self::assertInternalType('array', $result); + self::assertCount(count($columnIndexes), $result); + foreach ($columnIndexes as $columnIndex) { + self::assertArrayHasKey($columnIndex, $result); + self::assertInstanceOf(Column::class, $result[$columnIndex]); + } + } + + public function testGetColumn() + { + $columnIndexes = ['L', 'M']; + + foreach ($columnIndexes as $columnIndex) { + $this->testAutoFilterObject->setColumn($columnIndex); + } + + // If we request a specific column by its column ID, we should + // get a \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\AutoFilter\Column object returned + foreach ($columnIndexes as $columnIndex) { + $result = $this->testAutoFilterObject->getColumn($columnIndex); + self::assertInstanceOf(Column::class, $result); + } + } + + public function testGetColumnByOffset() + { + $columnIndexes = [ + 0 => 'H', + 3 => 'K', + 5 => 'M', + ]; + + // If we request a specific column by its offset, we should + // get a \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\AutoFilter\Column object returned + foreach ($columnIndexes as $columnIndex => $columnID) { + $result = $this->testAutoFilterObject->getColumnByOffset($columnIndex); + self::assertInstanceOf(Column::class, $result); + self::assertEquals($result->getColumnIndex(), $columnID); + } + } + + public function testGetColumnIfNotSet() + { + // If we request a specific column by its column ID, we should + // get a \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\AutoFilter\Column object returned + $result = $this->testAutoFilterObject->getColumn('K'); + self::assertInstanceOf(Column::class, $result); + } + + public function testGetColumnWithoutRangeSet() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + // Clear the range + $this->testAutoFilterObject->setRange(''); + $this->testAutoFilterObject->getColumn('A'); + } + + public function testClearRangeWithExistingColumns() + { + $expectedResult = ''; + + $columnIndexes = ['L', 'M', 'N']; + foreach ($columnIndexes as $columnIndex) { + $this->testAutoFilterObject->setColumn($columnIndex); + } + + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterObject->setRange(''); + self::assertInstanceOf(AutoFilter::class, $result); + + // Range should be cleared + $result = $this->testAutoFilterObject->getRange(); + self::assertEquals($expectedResult, $result); + + // Column array should be cleared + $result = $this->testAutoFilterObject->getColumns(); + self::assertInternalType('array', $result); + self::assertCount(0, $result); + } + + public function testSetRangeWithExistingColumns() + { + $expectedResult = 'G1:J512'; + + // These columns should be retained + $columnIndexes1 = ['I', 'J']; + foreach ($columnIndexes1 as $columnIndex) { + $this->testAutoFilterObject->setColumn($columnIndex); + } + // These columns should be discarded + $columnIndexes2 = ['K', 'L', 'M']; + foreach ($columnIndexes2 as $columnIndex) { + $this->testAutoFilterObject->setColumn($columnIndex); + } + + // Setters return the instance to implement the fluent interface + $result = $this->testAutoFilterObject->setRange($expectedResult); + self::assertInstanceOf(AutoFilter::class, $result); + + // Range should be correctly set + $result = $this->testAutoFilterObject->getRange(); + self::assertEquals($expectedResult, $result); + + // Only columns that existed in the original range and that + // still fall within the new range should be retained + $result = $this->testAutoFilterObject->getColumns(); + self::assertInternalType('array', $result); + self::assertCount(count($columnIndexes1), $result); + } + + public function testClone() + { + $columnIndexes = ['L', 'M']; + + foreach ($columnIndexes as $columnIndex) { + $this->testAutoFilterObject->setColumn($columnIndex); + } + + $result = clone $this->testAutoFilterObject; + self::assertInstanceOf(AutoFilter::class, $result); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/ColumnCellIteratorTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/ColumnCellIteratorTest.php new file mode 100644 index 0000000..46880e2 --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/ColumnCellIteratorTest.php @@ -0,0 +1,86 @@ +mockCell = $this->getMockBuilder(Cell::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->mockWorksheet = $this->getMockBuilder(Worksheet::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->mockWorksheet->expects($this->any()) + ->method('getHighestRow') + ->will($this->returnValue(5)); + $this->mockWorksheet->expects($this->any()) + ->method('getCellByColumnAndRow') + ->will($this->returnValue($this->mockCell)); + } + + public function testIteratorFullRange() + { + $iterator = new ColumnCellIterator($this->mockWorksheet, 'A'); + $ColumnCellIndexResult = 1; + self::assertEquals($ColumnCellIndexResult, $iterator->key()); + + foreach ($iterator as $key => $ColumnCell) { + self::assertEquals($ColumnCellIndexResult++, $key); + self::assertInstanceOf(Cell::class, $ColumnCell); + } + } + + public function testIteratorStartEndRange() + { + $iterator = new ColumnCellIterator($this->mockWorksheet, 'A', 2, 4); + $ColumnCellIndexResult = 2; + self::assertEquals($ColumnCellIndexResult, $iterator->key()); + + foreach ($iterator as $key => $ColumnCell) { + self::assertEquals($ColumnCellIndexResult++, $key); + self::assertInstanceOf(Cell::class, $ColumnCell); + } + } + + public function testIteratorSeekAndPrev() + { + $iterator = new ColumnCellIterator($this->mockWorksheet, 'A', 2, 4); + $columnIndexResult = 4; + $iterator->seek(4); + self::assertEquals($columnIndexResult, $iterator->key()); + + for ($i = 1; $i < $columnIndexResult - 1; ++$i) { + $iterator->prev(); + self::assertEquals($columnIndexResult - $i, $iterator->key()); + } + } + + public function testSeekOutOfRange() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $iterator = new ColumnCellIterator($this->mockWorksheet, 'A', 2, 4); + $iterator->seek(1); + } + + public function testPrevOutOfRange() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $iterator = new ColumnCellIterator($this->mockWorksheet, 'A', 2, 4); + $iterator->prev(); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/ColumnIteratorTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/ColumnIteratorTest.php new file mode 100644 index 0000000..7285961 --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/ColumnIteratorTest.php @@ -0,0 +1,85 @@ +mockColumn = $this->getMockBuilder(Column::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->mockWorksheet = $this->getMockBuilder(Worksheet::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->mockWorksheet->expects($this->any()) + ->method('getHighestColumn') + ->will($this->returnValue('E')); + } + + public function testIteratorFullRange() + { + $iterator = new ColumnIterator($this->mockWorksheet); + $columnIndexResult = 'A'; + self::assertEquals($columnIndexResult, $iterator->key()); + + foreach ($iterator as $key => $column) { + self::assertEquals($columnIndexResult++, $key); + self::assertInstanceOf(Column::class, $column); + } + } + + public function testIteratorStartEndRange() + { + $iterator = new ColumnIterator($this->mockWorksheet, 'B', 'D'); + $columnIndexResult = 'B'; + self::assertEquals($columnIndexResult, $iterator->key()); + + foreach ($iterator as $key => $column) { + self::assertEquals($columnIndexResult++, $key); + self::assertInstanceOf(Column::class, $column); + } + } + + public function testIteratorSeekAndPrev() + { + $ranges = range('A', 'E'); + $iterator = new ColumnIterator($this->mockWorksheet, 'B', 'D'); + $columnIndexResult = 'D'; + $iterator->seek('D'); + self::assertEquals($columnIndexResult, $iterator->key()); + + for ($i = 1; $i < array_search($columnIndexResult, $ranges); ++$i) { + $iterator->prev(); + $expectedResult = $ranges[array_search($columnIndexResult, $ranges) - $i]; + self::assertEquals($expectedResult, $iterator->key()); + } + } + + public function testSeekOutOfRange() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $iterator = new ColumnIterator($this->mockWorksheet, 'B', 'D'); + $iterator->seek('A'); + } + + public function testPrevOutOfRange() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $iterator = new ColumnIterator($this->mockWorksheet, 'B', 'D'); + $iterator->prev(); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/ColumnTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/ColumnTest.php new file mode 100644 index 0000000..b1e7b47 --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/ColumnTest.php @@ -0,0 +1,48 @@ +mockWorksheet = $this->getMockBuilder(Worksheet::class) + ->disableOriginalConstructor() + ->getMock(); + $this->mockWorksheet->expects($this->any()) + ->method('getHighestRow') + ->will($this->returnValue(5)); + } + + public function testInstantiateColumnDefault() + { + $column = new Column($this->mockWorksheet); + self::assertInstanceOf(Column::class, $column); + $columnIndex = $column->getColumnIndex(); + self::assertEquals('A', $columnIndex); + } + + public function testInstantiateColumnSpecified() + { + $column = new Column($this->mockWorksheet, 'E'); + self::assertInstanceOf(Column::class, $column); + $columnIndex = $column->getColumnIndex(); + self::assertEquals('E', $columnIndex); + } + + public function testGetCellIterator() + { + $column = new Column($this->mockWorksheet); + $cellIterator = $column->getCellIterator(); + self::assertInstanceOf(ColumnCellIterator::class, $cellIterator); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/DrawingTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/DrawingTest.php new file mode 100644 index 0000000..32bd97f --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/DrawingTest.php @@ -0,0 +1,40 @@ +getActiveSheet(); + + $gdImage = @imagecreatetruecolor(120, 20); + $textColor = imagecolorallocate($gdImage, 255, 255, 255); + imagestring($gdImage, 1, 5, 5, 'Created with PhpSpreadsheet', $textColor); + + $drawing = new MemoryDrawing(); + $drawing->setName('In-Memory image 1'); + $drawing->setDescription('In-Memory image 1'); + $drawing->setCoordinates('A1'); + $drawing->setImageResource($gdImage); + $drawing->setRenderingFunction( + MemoryDrawing::RENDERING_JPEG + ); + $drawing->setMimeType(MemoryDrawing::MIMETYPE_DEFAULT); + $drawing->setHeight(36); + $drawing->setWorksheet($aSheet); + + $originDrawingCount = count($aSheet->getDrawingCollection()); + $clonedWorksheet = clone $aSheet; + $clonedDrawingCount = count($clonedWorksheet->getDrawingCollection()); + + self::assertEquals($originDrawingCount, $clonedDrawingCount); + self::assertNotSame($aSheet, $clonedWorksheet); + self::assertNotSame($aSheet->getDrawingCollection(), $clonedWorksheet->getDrawingCollection()); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/RowCellIteratorTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/RowCellIteratorTest.php new file mode 100644 index 0000000..9346d0a --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/RowCellIteratorTest.php @@ -0,0 +1,88 @@ +mockCell = $this->getMockBuilder(Cell::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->mockWorksheet = $this->getMockBuilder(Worksheet::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->mockWorksheet->expects($this->any()) + ->method('getHighestColumn') + ->will($this->returnValue('E')); + $this->mockWorksheet->expects($this->any()) + ->method('getCellByColumnAndRow') + ->will($this->returnValue($this->mockCell)); + } + + public function testIteratorFullRange() + { + $iterator = new RowCellIterator($this->mockWorksheet); + $RowCellIndexResult = 'A'; + self::assertEquals($RowCellIndexResult, $iterator->key()); + + foreach ($iterator as $key => $RowCell) { + self::assertEquals($RowCellIndexResult++, $key); + self::assertInstanceOf(Cell::class, $RowCell); + } + } + + public function testIteratorStartEndRange() + { + $iterator = new RowCellIterator($this->mockWorksheet, 2, 'B', 'D'); + $RowCellIndexResult = 'B'; + self::assertEquals($RowCellIndexResult, $iterator->key()); + + foreach ($iterator as $key => $RowCell) { + self::assertEquals($RowCellIndexResult++, $key); + self::assertInstanceOf(Cell::class, $RowCell); + } + } + + public function testIteratorSeekAndPrev() + { + $ranges = range('A', 'E'); + $iterator = new RowCellIterator($this->mockWorksheet, 2, 'B', 'D'); + $RowCellIndexResult = 'D'; + $iterator->seek('D'); + self::assertEquals($RowCellIndexResult, $iterator->key()); + + for ($i = 1; $i < array_search($RowCellIndexResult, $ranges); ++$i) { + $iterator->prev(); + $expectedResult = $ranges[array_search($RowCellIndexResult, $ranges) - $i]; + self::assertEquals($expectedResult, $iterator->key()); + } + } + + public function testSeekOutOfRange() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $iterator = new RowCellIterator($this->mockWorksheet, 2, 'B', 'D'); + $iterator->seek(1); + } + + public function testPrevOutOfRange() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $iterator = new RowCellIterator($this->mockWorksheet, 2, 'B', 'D'); + $iterator->prev(); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/RowIteratorTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/RowIteratorTest.php new file mode 100644 index 0000000..63e26b3 --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/RowIteratorTest.php @@ -0,0 +1,83 @@ +mockRow = $this->getMockBuilder(Row::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->mockWorksheet = $this->getMockBuilder(Worksheet::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->mockWorksheet->expects($this->any()) + ->method('getHighestRow') + ->will($this->returnValue(5)); + } + + public function testIteratorFullRange() + { + $iterator = new RowIterator($this->mockWorksheet); + $rowIndexResult = 1; + self::assertEquals($rowIndexResult, $iterator->key()); + + foreach ($iterator as $key => $row) { + self::assertEquals($rowIndexResult++, $key); + self::assertInstanceOf(Row::class, $row); + } + } + + public function testIteratorStartEndRange() + { + $iterator = new RowIterator($this->mockWorksheet, 2, 4); + $rowIndexResult = 2; + self::assertEquals($rowIndexResult, $iterator->key()); + + foreach ($iterator as $key => $row) { + self::assertEquals($rowIndexResult++, $key); + self::assertInstanceOf(Row::class, $row); + } + } + + public function testIteratorSeekAndPrev() + { + $iterator = new RowIterator($this->mockWorksheet, 2, 4); + $columnIndexResult = 4; + $iterator->seek(4); + self::assertEquals($columnIndexResult, $iterator->key()); + + for ($i = 1; $i < $columnIndexResult - 1; ++$i) { + $iterator->prev(); + self::assertEquals($columnIndexResult - $i, $iterator->key()); + } + } + + public function testSeekOutOfRange() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $iterator = new RowIterator($this->mockWorksheet, 2, 4); + $iterator->seek(1); + } + + public function testPrevOutOfRange() + { + $this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class); + + $iterator = new RowIterator($this->mockWorksheet, 2, 4); + $iterator->prev(); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/RowTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/RowTest.php new file mode 100644 index 0000000..0b2822c --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/RowTest.php @@ -0,0 +1,48 @@ +mockWorksheet = $this->getMockBuilder(Worksheet::class) + ->disableOriginalConstructor() + ->getMock(); + $this->mockWorksheet->expects($this->any()) + ->method('getHighestColumn') + ->will($this->returnValue('E')); + } + + public function testInstantiateRowDefault() + { + $row = new Row($this->mockWorksheet); + self::assertInstanceOf(Row::class, $row); + $rowIndex = $row->getRowIndex(); + self::assertEquals(1, $rowIndex); + } + + public function testInstantiateRowSpecified() + { + $row = new Row($this->mockWorksheet, 5); + self::assertInstanceOf(Row::class, $row); + $rowIndex = $row->getRowIndex(); + self::assertEquals(5, $rowIndex); + } + + public function testGetCellIterator() + { + $row = new Row($this->mockWorksheet); + $cellIterator = $row->getCellIterator(); + self::assertInstanceOf(RowCellIterator::class, $cellIterator); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/WorksheetTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/WorksheetTest.php new file mode 100644 index 0000000..5dfa825 --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Worksheet/WorksheetTest.php @@ -0,0 +1,133 @@ +setTitle($testTitle); + self::assertSame($testTitle, $worksheet->getTitle()); + } + + public function setTitleInvalidProvider() + { + return [ + [str_repeat('a', 32), 'Maximum 31 characters allowed in sheet title.'], + ['invalid*title', 'Invalid character found in sheet title'], + ]; + } + + /** + * @param string $title + * @param string $expectMessage + * @dataProvider setTitleInvalidProvider + */ + public function testSetTitleInvalid($title, $expectMessage) + { + // First, test setting title with validation disabled -- should be successful + $worksheet = new Worksheet(); + $worksheet->setTitle($title, true, false); + + // Next, test again with validation enabled -- this time we should fail + $worksheet = new Worksheet(); + $this->expectException(\Exception::class); + $this->expectExceptionMessage($expectMessage); + $worksheet->setTitle($title); + } + + public function testSetTitleDuplicate() + { + // Create a Spreadsheet with three Worksheets (the first is created automatically) + $spreadsheet = new Spreadsheet(); + $spreadsheet->createSheet(); + $spreadsheet->createSheet(); + + // Set unique title -- should be unchanged + $sheet = $spreadsheet->getSheet(0); + $sheet->setTitle('Test Title'); + self::assertSame('Test Title', $sheet->getTitle()); + + // Set duplicate title -- should have numeric suffix appended + $sheet = $spreadsheet->getSheet(1); + $sheet->setTitle('Test Title'); + self::assertSame('Test Title 1', $sheet->getTitle()); + + // Set duplicate title with validation disabled -- should be unchanged + $sheet = $spreadsheet->getSheet(2); + $sheet->setTitle('Test Title', true, false); + self::assertSame('Test Title', $sheet->getTitle()); + } + + public function testSetCodeName() + { + $testCodeName = str_repeat('a', 31); + + $worksheet = new Worksheet(); + $worksheet->setCodeName($testCodeName); + self::assertSame($testCodeName, $worksheet->getCodeName()); + } + + public function setCodeNameInvalidProvider() + { + return [ + [str_repeat('a', 32), 'Maximum 31 characters allowed in sheet code name.'], + ['invalid*code*name', 'Invalid character found in sheet code name'], + ]; + } + + /** + * @param string $codeName + * @param string $expectMessage + * @dataProvider setCodeNameInvalidProvider + */ + public function testSetCodeNameInvalid($codeName, $expectMessage) + { + // First, test setting code name with validation disabled -- should be successful + $worksheet = new Worksheet(); + $worksheet->setCodeName($codeName, false); + + // Next, test again with validation enabled -- this time we should fail + $worksheet = new Worksheet(); + $this->expectException(\Exception::class); + $this->expectExceptionMessage($expectMessage); + $worksheet->setCodeName($codeName); + } + + public function testSetCodeNameDuplicate() + { + // Create a Spreadsheet with three Worksheets (the first is created automatically) + $spreadsheet = new Spreadsheet(); + $spreadsheet->createSheet(); + $spreadsheet->createSheet(); + + // Set unique code name -- should be massaged to Snake_Case + $sheet = $spreadsheet->getSheet(0); + $sheet->setCodeName('Test Code Name'); + self::assertSame('Test_Code_Name', $sheet->getCodeName()); + + // Set duplicate code name -- should be massaged and have numeric suffix appended + $sheet = $spreadsheet->getSheet(1); + $sheet->setCodeName('Test Code Name'); + self::assertSame('Test_Code_Name_1', $sheet->getCodeName()); + + // Set duplicate code name with validation disabled -- should be unchanged, and unmassaged + $sheet = $spreadsheet->getSheet(2); + $sheet->setCodeName('Test Code Name', false); + self::assertSame('Test Code Name', $sheet->getCodeName()); + } + + public function testFreezePaneSelectedCell() + { + $worksheet = new Worksheet(); + $worksheet->freezePane('B2'); + self::assertSame('B2', $worksheet->getTopLeftCell()); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Writer/Ods/ContentTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Writer/Ods/ContentTest.php new file mode 100644 index 0000000..0c9995a --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Writer/Ods/ContentTest.php @@ -0,0 +1,98 @@ +compatibilityMode = Functions::getCompatibilityMode(); + Functions::setCompatibilityMode(Functions::COMPATIBILITY_OPENOFFICE); + } + + protected function tearDown() + { + parent::tearDown(); + Functions::setCompatibilityMode($this->compatibilityMode); + } + + public function testWriteEmptySpreadsheet() + { + $content = new Content(new Ods(new Spreadsheet())); + $xml = $content->write(); + + self::assertXmlStringEqualsXmlFile($this->samplesPath . '/content-empty.xml', $xml); + } + + public function testWriteSpreadsheet() + { + $workbook = new Spreadsheet(); + + // Worksheet 1 + $worksheet1 = $workbook->getActiveSheet(); + $worksheet1->setCellValue('A1', 1); // Number + $worksheet1->setCellValue('B1', 12345.6789); // Number + $worksheet1->setCellValue('C1', '1'); // Number without cast + $worksheet1->setCellValueExplicit('D1', '01234', DataType::TYPE_STRING); // Number casted to string + $worksheet1->setCellValue('E1', 'Lorem ipsum'); // String + + $worksheet1->setCellValue('A2', true); // Boolean + $worksheet1->setCellValue('B2', false); // Boolean + $worksheet1->setCellValueExplicit( + 'C2', + '=IF(A3, CONCATENATE(A1, " ", A2), CONCATENATE(A2, " ", A1))', + DataType::TYPE_FORMULA + ); // Formula + + $worksheet1->setCellValue('D2', Date::PHPToExcel(1488635026)); // Date + $worksheet1->getStyle('D2') + ->getNumberFormat() + ->setFormatCode(NumberFormat::FORMAT_DATE_DATETIME); + + // Styles + $worksheet1->getStyle('A1')->getFont()->setBold(true); + $worksheet1->getStyle('B1')->getFont()->setItalic(true); + $worksheet1->getStyle('C1')->getFont()->setName('Courier'); + $worksheet1->getStyle('C1')->getFont()->setSize(14); + $worksheet1->getStyle('C1')->getFont()->setColor(new Color(Color::COLOR_BLUE)); + + $worksheet1->getStyle('C1')->getFill()->setFillType(Fill::FILL_SOLID); + $worksheet1->getStyle('C1')->getFill()->setStartColor(new Color(Color::COLOR_RED)); + + $worksheet1->getStyle('C1')->getFont()->setUnderline(Font::UNDERLINE_SINGLE); + $worksheet1->getStyle('C2')->getFont()->setUnderline(Font::UNDERLINE_DOUBLE); + $worksheet1->getStyle('D2')->getFont()->setUnderline(Font::UNDERLINE_NONE); + + // Worksheet 2 + $worksheet2 = $workbook->createSheet(); + $worksheet2->setTitle('New Worksheet'); + $worksheet2->setCellValue('A1', 2); + + // Write + $content = new Content(new Ods($workbook)); + $xml = $content->write(); + + self::assertXmlStringEqualsXmlFile($this->samplesPath . '/content-with-data.xml', $xml); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Writer/Xls/WorkbookTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Writer/Xls/WorkbookTest.php new file mode 100644 index 0000000..591f48f --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Writer/Xls/WorkbookTest.php @@ -0,0 +1,143 @@ +workbook = new Workbook($spreadsheet, $strTotal, $strUnique, $str_table, $colors, $parser); + } + + /** + * @dataProvider providerAddColor + * + * @param array $testColors + * @param array $expectedResult + */ + public function testAddColor(array $testColors, array $expectedResult) + { + $workbookReflection = new \ReflectionClass(Workbook::class); + $methodAddColor = $workbookReflection->getMethod('addColor'); + $propertyPalette = $workbookReflection->getProperty('palette'); + $methodAddColor->setAccessible(true); + $propertyPalette->setAccessible(true); + + foreach ($testColors as $testColor) { + $methodAddColor->invoke($this->workbook, $testColor); + } + + $palette = $propertyPalette->getValue($this->workbook); + + self::assertEquals($expectedResult, $palette); + } + + public function providerAddColor() + { + $this->setUp(); + + $workbookReflection = new \ReflectionClass(Workbook::class); + $propertyPalette = $workbookReflection->getProperty('palette'); + $propertyPalette->setAccessible(true); + + $palette = $propertyPalette->getValue($this->workbook); + + $newColor1 = [0x00, 0x00, 0x01, 0x00]; + $newColor2 = [0x00, 0x00, 0x02, 0x00]; + $newColor3 = [0x00, 0x00, 0x03, 0x00]; + + // Add one new color + $paletteTestOne = $palette; + $paletteTestOne[8] = $newColor1; + + // Add one new color + one existing color after index 8 + $paletteTestTwo = $paletteTestOne; + + // Add one new color + one existing color before index 9 + $paletteTestThree = $paletteTestOne; + $paletteTestThree[9] = $palette[8]; + + // Add three new color + $paletteTestFour = $palette; + $paletteTestFour[8] = $newColor1; + $paletteTestFour[9] = $newColor2; + $paletteTestFour[10] = $newColor3; + + // Add all existing color + $colorsAdd = array_map([$this, 'paletteToColor'], $palette); + $paletteTestFive = $palette; + + // Add new color after all existing color + $colorsAddTwo = array_map([$this, 'paletteToColor'], $palette); + $colorsAddTwo[] = $this->paletteToColor($newColor1); + $paletteTestSix = $palette; + + // Add one existing color + $paletteTestSeven = $palette; + + // Add two existing color + $paletteTestHeight = $palette; + + // Add last existing color and add one new color + $keyPalette = array_keys($palette); + $last = end($keyPalette); + $lastColor = $this->paletteToColor($palette[$last]); + $paletteTestNine = $palette; + + return [ + [[$this->paletteToColor($newColor1)], $paletteTestOne], + [[$this->paletteToColor($newColor1), $this->paletteToColor($palette[12])], $paletteTestTwo], + [[$this->paletteToColor($newColor1), $this->paletteToColor($palette[8])], $paletteTestThree], + [[$this->paletteToColor($newColor1), $this->paletteToColor($newColor2), $this->paletteToColor($newColor3)], $paletteTestFour], + [$colorsAdd, $paletteTestFive], + [$colorsAddTwo, $paletteTestSix], + [[$this->paletteToColor($palette[8])], $paletteTestSeven], + [[$this->paletteToColor($palette[25]), $this->paletteToColor($palette[10])], $paletteTestHeight], + [[$lastColor, $this->paletteToColor($newColor1)], $paletteTestNine], + ]; + } + + /** + * Change palette color to rgb string. + * + * @param array $palette palette color + * + * @return string rgb string + */ + private function paletteToColor($palette) + { + return $this->right('00' . dechex((int) ($palette[0])), 2) + . $this->right('00' . dechex((int) ($palette[1])), 2) + . $this->right('00' . dechex((int) ($palette[2])), 2); + } + + /** + * Return n right character in string. + * + * @param string $value text to get right character + * @param int $nbchar number of char at right of string + * + * @return string + */ + private function right($value, $nbchar) + { + return mb_substr($value, mb_strlen($value) - $nbchar, $nbchar); + } +} diff --git a/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Writer/Xlsx/UnparsedDataTest.php b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Writer/Xlsx/UnparsedDataTest.php new file mode 100644 index 0000000..c17d55d --- /dev/null +++ b/inc/vendor/phpoffice/phpspreadsheet/tests/PhpSpreadsheetTests/Writer/Xlsx/UnparsedDataTest.php @@ -0,0 +1,103 @@ +load($sampleFilename); + + $excel->getSheet(1)->setCellValue('B1', '222'); + + $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($excel); + $writer->save($resultFilename); + self::assertFileExists($resultFilename); + + $resultZip = new ZipArchive(); + $resultZip->open($resultFilename); + $resultContentTypesRaw = $resultZip->getFromName('[Content_Types].xml'); + $resultControlPropRaw = $resultZip->getFromName('xl/ctrlProps/ctrlProp1.xml'); + $resultDrawingRaw = $resultZip->getFromName('xl/drawings/drawing1.xml'); + $resultVmlDrawingRaw = $resultZip->getFromName('xl/drawings/vmlDrawing1.vml'); + $resultPrinterSettingsRaw = $resultZip->getFromName('xl/printerSettings/printerSettings1.bin'); + $resultVbaProjectRaw = $resultZip->getFromName('xl/vbaProject.bin'); + $resultWorkbookRaw = $resultZip->getFromName('xl/workbook.xml'); + $resultSheet1RelsRaw = $resultZip->getFromName('xl/worksheets/_rels/sheet1.xml.rels'); + $resultSheet1Raw = $resultZip->getFromName('xl/worksheets/sheet1.xml'); + $resultSheet2Raw = $resultZip->getFromName('xl/worksheets/sheet2.xml'); + if (false === $resultZip->close()) { + throw new Exception("Could not close zip file \"{$resultFilename}\"."); + } + unlink($resultFilename); + + // [Content_Types].xml + $this->assertTrue(strpos($resultContentTypesRaw, 'application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings') > 0, 'Content type for printerSettings not found!'); + $this->assertTrue(strpos($resultContentTypesRaw, 'application/vnd.ms-office.vbaProject') > 0, 'Content type for VbaProject not found!'); + $this->assertTrue(strpos($resultContentTypesRaw, 'application/vnd.ms-excel.controlproperties+xml') > 0, 'Content type for ctrlProp not found!'); + + // xl/ctrlProps/ctrlProp1.xml + $this->assertTrue(!empty($resultControlPropRaw), 'ctrlProp not found!'); + + // xl/drawings/drawing1.xml + $this->assertTrue(strpos($resultDrawingRaw, '