From 1f6f076ef40e80fa86712af6487e19ec800cd757 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 23 Dec 2011 13:22:57 +0400 Subject: [PATCH 001/418] UnifiedContainer clone fix + __clone added to UnifiedContainer + clone test for UnifiedContainer added to DAOTest --- main/UnifiedContainer/UnifiedContainer.class.php | 4 ++++ test/misc/DAOTest.class.php | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/main/UnifiedContainer/UnifiedContainer.class.php b/main/UnifiedContainer/UnifiedContainer.class.php index ee7d33a5bd..ff5e71695c 100644 --- a/main/UnifiedContainer/UnifiedContainer.class.php +++ b/main/UnifiedContainer/UnifiedContainer.class.php @@ -107,6 +107,10 @@ public function __wakeup() $this->worker = new $this->workerClass($this); } + public function __clone() { + $this->worker = clone $this->worker; + } + public function getParentObject() { return $this->parent; diff --git a/test/misc/DAOTest.class.php b/test/misc/DAOTest.class.php index 14f8dacb8a..815d461dc1 100644 --- a/test/misc/DAOTest.class.php +++ b/test/misc/DAOTest.class.php @@ -397,6 +397,18 @@ public function unified() return null; $this->assertEquals($user->getEncapsulants()->getCount(), 10); + + // unified container __clone + $dao = $user->getEncapsulants(); + $dao->setCriteria(Criteria::create()); // empty criteria + $cloneDao = clone $dao; + $cloneDao->setCriteria( // criteria with 1 expression + Criteria::create() + ->add( + Expression::gt('id',0) + ) + ); + $this->assertNotEquals($dao, $cloneDao); // they should be different } public function testWorkingWithCache() From 0137beb5f0f19b2c69bab6df7cce633557f8289c Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 23 Dec 2011 15:06:39 +0400 Subject: [PATCH 002/418] TestTables fix --- test/misc/TestTables.class.php | 36 ++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/test/misc/TestTables.class.php b/test/misc/TestTables.class.php index 6befdf2dd3..69bcc39a62 100644 --- a/test/misc/TestTables.class.php +++ b/test/misc/TestTables.class.php @@ -1,18 +1,18 @@ schema = $schema; - + // in case of unclean shutdown of previous tests foreach (DBTestPool::me()->getPool() as $name => $db) { foreach ($this->schema->getTableNames() as $name) { @@ -25,7 +25,7 @@ public function __construct() } catch (DatabaseException $e) { // ok } - + if ($db->hasSequences()) { foreach ( $this->schema->getTableByName($name)->getColumns() @@ -34,7 +34,7 @@ public function __construct() { try { if ($column->isAutoincrement()) - $db->queryRaw("DROP SEQUENCE {$name}_id;"); + $db->queryRaw("DROP SEQUENCE {$name}_id CASCADE;"); } catch (DatabaseException $e) { // ok } @@ -43,24 +43,30 @@ public function __construct() } } } - + public function create() { $pool = DBTestPool::me()->getPool(); - + foreach ($pool as $name => $db) { + try { + $this->drop(); + } catch(DatabaseException $e) { + // ok + } + foreach ($this->schema->getTables() as $name => $table) { $db->queryRaw($table->toDialectString($db->getDialect())); } } - + return $this; } - + public function drop() { $pool = DBTestPool::me()->getPool(); - + foreach ($pool as $name => $db) { foreach ($this->schema->getTableNames() as $name) { $db->queryRaw( @@ -68,19 +74,19 @@ public function drop() $db->getDialect() ) ); - + if ($db->hasSequences()) { foreach ( $this->schema->getTableByName($name)->getColumns() as $columnName => $column) { if ($column->isAutoincrement()) - $db->queryRaw("DROP SEQUENCE {$name}_id;"); + $db->queryRaw("DROP SEQUENCE {$name}_id CASCADE;"); } } } } - + return $this; } From 4e071c1e3d776078ec6c663362b5cdfba9e4df78 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 27 Dec 2011 18:15:05 +0400 Subject: [PATCH 003/418] CT++ view --- core/Exceptions/CtppException.class.php | 18 +++ main/Flow/CtppView.class.php | 145 ++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 core/Exceptions/CtppException.class.php create mode 100644 main/Flow/CtppView.class.php diff --git a/core/Exceptions/CtppException.class.php b/core/Exceptions/CtppException.class.php new file mode 100644 index 0000000000..d4a9c7bca0 --- /dev/null +++ b/core/Exceptions/CtppException.class.php @@ -0,0 +1,18 @@ + + * @date 2011.12.25 + */ +class CtppException extends BaseException {/*_*/} diff --git a/main/Flow/CtppView.class.php b/main/Flow/CtppView.class.php new file mode 100644 index 0000000000..2e9b64fe51 --- /dev/null +++ b/main/Flow/CtppView.class.php @@ -0,0 +1,145 @@ + + * @date 2011.12.25 + */ +class CtppView implements View, Stringable { + + /** + * @var ctpp + */ + protected $ctpp = null; + + /** + * @var string + */ + protected $bytecode = null; + + /** + * @var array + */ + protected $templatePaths = array(); + + /** + * @var null + */ + protected $templateName = null; + + /** + * @var string + */ + protected $templateExt = 'tmpl'; + + /** + * @var int + */ + protected $steps_limit = null; + + public static function create() { + return new self(); + } + + public function __construct() { + // проверяем подключен ли модуль CT++ + if( !extension_loaded('ctpp') ) { + throw new MissingModuleException('CT++ module not found!'); + } + // creating ct++ + $this->ctpp = new ctpp(); + } + + /** + * @param string $templateName + * @return CtppView + */ + public function setTemplateName($templateName) { + $this->templateName = $templateName; + return $this; + } + + /** + * @param array $templatePaths + * @return CtppView + */ + public function setTemplatePaths(array $templatePaths) { + $this->templatePaths = $templatePaths; + return $this; + } + + /** + * @param string $templatePath + * @return CtppView + */ + public function addTemplatePath($templatePath) { + $this->templatePaths[] = $templatePath; + return $this; + } + + /** + * @param string $templateExt + * @return CtppView + */ + public function setTemplateExt($templateExt) { + $this->templateExt = $templateExt; + return $this; + } + + /** + * @param int $steps_limit + * @return CtppView + */ + public function setStepsLimit($steps_limit) { + if( is_int($steps_limit) ) { + $this->steps_limit = $steps_limit; + } else { + throw new WrongArgumentException('Steps limit nust be integer!'); + } + + return $this; + } + + /** + * @param Model + * @return mixed + */ + public function render(/* Model */ $model = null) { + $this->makeByteCode(); + $this->setData( $model ); + return $this->ctpp->output( $this->bytecode ); + } + + /** + * @param Model + * @return mixed + */ + public function toString(/* Model */ $model = null) { + $this->makeByteCode(); + $this->setData( $model ); + $result = $this->ctpp->output_string( $this->bytecode ); + if( $result === false ) { + throw new CtppException( $this->ctpp->get_last_error() ); + } + return $result; + } + + private function makeByteCode() { + if( empty($this->templatePaths) ) { + throw new WrongStateException('Template paths are not defined!'); + } + if( empty($this->templateName) ) { + throw new WrongStateException('Template name is not defined!'); + } + // TODO: прикрутить кэширование байткода + // making bytecode + $this->ctpp->include_dirs( $this->templatePaths ); + $this->bytecode = $this->ctpp->parse_template( $this->templateName.'.'.$this->templateExt ); + } + + private function setData(Model $model = null) { + $this->ctpp->emit_params( $model->getList() ); + } + +} From 4449ac5dd02cf70a8070d9dcaea9acc66968013e Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 27 Dec 2011 18:15:23 +0400 Subject: [PATCH 004/418] UUID implementation --- core/Base/Assert.class.php | 96 ++-- core/DB/Dialect.class.php | 53 ++- core/DB/PgSQL.class.php | 106 +++-- core/DB/PostgresDialect.class.php | 73 +-- .../MissingModuleException.class.php | 18 + core/Form/Primitive.class.php | 123 +++-- .../PrimitiveUuidIdentifier.class.php | 20 + .../PrimitiveUuidIdentifierList.class.php | 134 ++++++ .../Primitives/PrimitiveUuidString.class.php | 32 ++ core/OSQL/DataType.class.php | 118 ++--- meta/types/UuidType.class.php | 31 ++ test/misc/DAOTest.class.php | 450 +++++++++--------- 12 files changed, 788 insertions(+), 466 deletions(-) create mode 100644 core/Exceptions/MissingModuleException.class.php create mode 100644 core/Form/Primitives/PrimitiveUuidIdentifier.class.php create mode 100644 core/Form/Primitives/PrimitiveUuidIdentifierList.class.php create mode 100644 core/Form/Primitives/PrimitiveUuidString.class.php create mode 100644 meta/types/UuidType.class.php diff --git a/core/Base/Assert.class.php b/core/Base/Assert.class.php index ea375b18d2..39843f2689 100644 --- a/core/Base/Assert.class.php +++ b/core/Base/Assert.class.php @@ -11,7 +11,7 @@ /** * Widely used assertions. - * + * * @ingroup Base **/ final class Assert extends StaticFactory @@ -23,7 +23,7 @@ public static function isTrue($boolean, $message = null) $message.', '.self::dumpArgument($boolean) ); } - + public static function isFalse($boolean, $message = null) { if ($boolean !== false) @@ -31,7 +31,7 @@ public static function isFalse($boolean, $message = null) $message.', '.self::dumpArgument($boolean) ); } - + public static function isNotFalse($boolean, $message = null) { if ($boolean === false) @@ -39,7 +39,7 @@ public static function isNotFalse($boolean, $message = null) $message.', '.self::dumpArgument($boolean) ); } - + public static function isNull($variable, $message = null) { if ($variable !== null) @@ -47,7 +47,7 @@ public static function isNull($variable, $message = null) $message.', '.self::dumpArgument($variable) ); } - + public static function isEmpty($variable, $message = null) { if (!empty($variable)) @@ -55,7 +55,7 @@ public static function isEmpty($variable, $message = null) $message.', '.self::dumpArgument($variable) ); } - + public static function isNotEmpty($variable, $message = null) { if (empty($variable)) @@ -63,23 +63,23 @@ public static function isNotEmpty($variable, $message = null) $message.', '.self::dumpArgument($variable) ); } - + public static function isIndexExists($array, $key, $message = null) { Assert::isArray($array); - + if (!array_key_exists($key, $array)) throw new WrongArgumentException( $message.', '.self::dumpArgument($key) ); } - + public static function isNotNull($variable, $message = null) { if ($variable === null) throw new WrongArgumentException($message); } - + public static function isScalar($variable, $message = null) { if (!is_scalar($variable)) @@ -87,7 +87,7 @@ public static function isScalar($variable, $message = null) $message.', '.self::dumpArgument($variable) ); } - + public static function isArray($variable, $message = null) { if (!is_array($variable)) @@ -95,17 +95,17 @@ public static function isArray($variable, $message = null) $message.', '.self::dumpArgument($variable) ); } - + public static function isNotEmptyArray(&$variable, $message = null) { self::isArray($variable, $message); - + if (!$variable) throw new WrongArgumentException( $message.', '.self::dumpArgument($variable) ); } - + public static function isInteger($variable, $message = null) { if ( @@ -118,7 +118,7 @@ public static function isInteger($variable, $message = null) $message.', '.self::dumpArgument($variable) ); } - + public static function isPositiveInteger($variable, $message = null) { if ( @@ -129,7 +129,7 @@ public static function isPositiveInteger($variable, $message = null) $message.', '.self::dumpArgument($variable) ); } - + public static function isFloat($variable, $message = null) { if (!self::checkFloat($variable)) @@ -137,7 +137,7 @@ public static function isFloat($variable, $message = null) $message.', '.self::dumpArgument($variable) ); } - + public static function isString($variable, $message = null) { if (!is_string($variable)) @@ -145,7 +145,7 @@ public static function isString($variable, $message = null) $message.', '.self::dumpArgument($variable) ); } - + public static function isBoolean($variable, $message = null) { if (!($variable === true || $variable === false)) @@ -153,7 +153,7 @@ public static function isBoolean($variable, $message = null) $message.', '.self::dumpArgument($variable) ); } - + public static function isTernaryBase($variable, $message = null) { if ( @@ -167,7 +167,7 @@ public static function isTernaryBase($variable, $message = null) $message.', '.self::dumpArgument($variable) ); } - + public static function brothers($first, $second, $message = null) { if (get_class($first) !== get_class($second)) @@ -175,7 +175,7 @@ public static function brothers($first, $second, $message = null) $message.', '.self::dumpOppositeArguments($first, $second) ); } - + public static function isEqual($first, $second, $message = null) { if ($first != $second) @@ -183,7 +183,7 @@ public static function isEqual($first, $second, $message = null) $message.', '.self::dumpOppositeArguments($first, $second) ); } - + public static function isNotEqual($first, $second, $message = null) { if ($first == $second) @@ -191,7 +191,7 @@ public static function isNotEqual($first, $second, $message = null) $message.', '.self::dumpOppositeArguments($first, $second) ); } - + public static function isSame($first, $second, $message = null) { if ($first !== $second) @@ -199,7 +199,7 @@ public static function isSame($first, $second, $message = null) $message.', '.self::dumpOppositeArguments($first, $second) ); } - + public static function isNotSame($first, $second, $message = null) { if ($first === $second) @@ -207,7 +207,7 @@ public static function isNotSame($first, $second, $message = null) $message.', '.self::dumpOppositeArguments($first, $second) ); } - + public static function isTypelessEqual($first, $second, $message = null) { if ($first != $second) @@ -215,7 +215,7 @@ public static function isTypelessEqual($first, $second, $message = null) $message.', '.self::dumpOppositeArguments($first, $second) ); } - + public static function isLesser($first, $second, $message = null) { if (!($first < $second)) @@ -223,7 +223,7 @@ public static function isLesser($first, $second, $message = null) $message.', '.self::dumpOppositeArguments($first, $second) ); } - + public static function isGreater($first, $second, $message = null) { if (!($first > $second)) @@ -231,7 +231,7 @@ public static function isGreater($first, $second, $message = null) $message.', '.self::dumpOppositeArguments($first, $second) ); } - + public static function isLesserOrEqual($first, $second, $message = null) { if (!($first <= $second)) @@ -239,7 +239,7 @@ public static function isLesserOrEqual($first, $second, $message = null) $message.', '.self::dumpOppositeArguments($first, $second) ); } - + public static function isGreaterOrEqual($first, $second, $message = null) { if (!($first >= $second)) @@ -247,7 +247,7 @@ public static function isGreaterOrEqual($first, $second, $message = null) $message.', '.self::dumpOppositeArguments($first, $second) ); } - + public static function isInstance($first, $second, $message = null) { if (!ClassUtils::isInstanceOf($first, $second)) @@ -255,7 +255,7 @@ public static function isInstance($first, $second, $message = null) $message.', '.self::dumpOppositeArguments($first, $second) ); } - + public static function classExists($className, $message = null) { if (!class_exists($className, true)) @@ -263,7 +263,7 @@ public static function classExists($className, $message = null) $message.', class "'.$className.'" does not exists' ); } - + public static function methodExists($object, $method, $message = null) { if (!method_exists($object, $method)) @@ -276,7 +276,7 @@ public static function isUnreachable($message = 'unreachable code reached') { throw new WrongArgumentException($message); } - + /// exceptionless methods //@{ public static function checkInteger($value) @@ -287,7 +287,7 @@ public static function checkInteger($value) && (strlen($value) == strlen((int) $value)) ); } - + public static function checkFloat($value) { return ( @@ -300,12 +300,36 @@ public static function checkScalar($value) { return is_scalar($value); } - + + /** + * Checking UUID + * @see http://tools.ietf.org/html/rfc4122 + * @param string $value + * @return boolean + */ + public static function checkUniversalUniqueIdentifier($value) + { + return ( + is_string($value) && + preg_match(PrimitiveUuidString::UUID_PATTERN, $value) + ); + } + + public static function isUniversalUniqueIdentifier($variable, $message = null) + { + if( + !self::checkUniversalUniqueIdentifier($variable) + ) + throw new WrongArgumentException( + $message.', '.self::dumpArgument($variable) + ); + } + public static function dumpArgument($argument) { return 'argument: ['.print_r($argument, true).']'; } - + public static function dumpOppositeArguments($first, $second) { return diff --git a/core/DB/Dialect.class.php b/core/DB/Dialect.class.php index 5c6b9e4641..0281371292 100644 --- a/core/DB/Dialect.class.php +++ b/core/DB/Dialect.class.php @@ -22,25 +22,25 @@ abstract class /* ANSI's */ Dialect const LITERAL_NULL = 'NULL'; const LITERAL_TRUE = 'TRUE'; const LITERAL_FALSE = 'FALSE'; - + abstract public function preAutoincrement(DBColumn $column); abstract public function postAutoincrement(DBColumn $column); - + abstract public function hasTruncate(); abstract public function hasMultipleTruncate(); abstract public function hasReturning(); - + /** must be implemented too: - + public static function quoteValue($value); **/ - + public static function quoteField($field) { return self::quoteTable($field); } - + public static function quoteTable($table) { return '"'.$table.'"'; @@ -50,7 +50,7 @@ public static function toCasted($field, $type) { return "CAST ({$field} AS {$type})"; } - + public static function timeZone($exist = false) { return @@ -58,7 +58,7 @@ public static function timeZone($exist = false) ? ' WITH TIME ZONE' : ' WITHOUT TIME ZONE'; } - + public static function dropTableMode($cascade = false) { return @@ -66,42 +66,45 @@ public static function dropTableMode($cascade = false) ? ' CASCADE' : ' RESTRICT'; } - + public function quoteBinary($data) { return $this->quoteValue($data); } - + public function unquoteBinary($data) { return $data; } - + public function typeToString(DataType $type) { if ($type->getId() == DataType::IP) return 'varchar(19)'; - + if ($type->getId() == DataType::IP_RANGE) return 'varchar(41)'; - + + if ($type->getId() == DataType::UUID) + return 'varchar(36)'; + return $type->getName(); } - + public function toFieldString($expression) { return $this->toNeededString($expression, 'quoteField'); } - + public function toValueString($expression) { return $this->toNeededString($expression, 'quoteValue'); } - + private function toNeededString($expression, $method) { $string = null; - + if (null !== $expression) { if ($expression instanceof DialectString) { if ($expression instanceof Query) @@ -112,10 +115,10 @@ private function toNeededString($expression, $method) $string .= $this->$method($expression); } } - + return $string; } - + public function fieldToString($field) { return @@ -123,7 +126,7 @@ public function fieldToString($field) ? $field->toDialectString($this) : $this->quoteField($field); } - + public function valueToString($value) { return @@ -131,27 +134,27 @@ public function valueToString($value) ? $value->toDialectString($this) : $this->quoteValue($value); } - + public function logicToString($logic) { return $logic; } - + public function literalToString($literal) { return $literal; } - + public function fullTextSearch($field, $words, $logic) { throw new UnimplementedFeatureException(); } - + public function fullTextRank($field, $words, $logic) { throw new UnimplementedFeatureException(); } - + public function quoteIpInRange($range, $ip) { throw new UnimplementedFeatureException(); diff --git a/core/DB/PgSQL.class.php b/core/DB/PgSQL.class.php index 7a450f7c2b..3258602247 100644 --- a/core/DB/PgSQL.class.php +++ b/core/DB/PgSQL.class.php @@ -25,7 +25,7 @@ public static function getDialect() { return PostgresDialect::me(); } - + /** * @return PgSQL **/ @@ -46,15 +46,15 @@ public function connect() throw new DatabaseException( 'can not connect to PostgreSQL server: '.pg_errormessage() ); - + if ($this->encoding) $this->setDbEncoding(); - + pg_set_error_verbosity($this->link, PGSQL_ERRORS_VERBOSE); return $this; } - + /** * @return PgSQL **/ @@ -65,38 +65,58 @@ public function disconnect() return $this; } - + public function isConnected() { return is_resource($this->link); } - + /** * misc **/ - + public function obtainSequence($sequence) { + $normalyzeSequence = mb_strtolower( trim( $sequence ) ); + if( + 'uuid' === $normalyzeSequence || + 'uuid_id' === $normalyzeSequence + ) { + return $this->obtainUuid(); + } + $res = $this->queryRaw("select nextval('{$sequence}') as seq"); $row = pg_fetch_assoc($res); pg_free_result($res); return $row['seq']; } - + + /** + * @return string + */ + protected function obtainUuid() + { + if( !extension_loaded('uuid') ) { + throw new MissingModuleException('UUID module not found!'); + } + + return uuid_create(); + } + /** * @return PgSQL **/ public function setDbEncoding() { pg_set_client_encoding($this->link, $this->encoding); - + return $this; } - + /** * query methods **/ - + public function queryRaw($queryString) { try { @@ -106,13 +126,13 @@ public function queryRaw($queryString) // pg_get_result() is too slow in our case list($error, ) = explode("\n", pg_errormessage($this->link)); $code = substr($error, 8, 5); - + if ($code == PostgresError::UNIQUE_VIOLATION) { $e = 'DuplicateObjectException'; $code = null; } else $e = 'PostgresDatabaseException'; - + throw new $e($error.' - '.$queryString, $code); } } @@ -125,11 +145,11 @@ public function queryCount(Query $query) { return pg_affected_rows($this->queryNull($query)); } - + public function queryRow(Query $query) { $res = $this->query($query); - + if ($this->checkSingle($res)) { $ret = pg_fetch_assoc($res); pg_free_result($res); @@ -137,11 +157,11 @@ public function queryRow(Query $query) } else return null; } - + public function queryColumn(Query $query) { $res = $this->query($query); - + if ($res) { $array = array(); @@ -153,11 +173,11 @@ public function queryColumn(Query $query) } else return null; } - + public function querySet(Query $query) { $res = $this->query($query); - + if ($res) { $array = array(); @@ -169,12 +189,12 @@ public function querySet(Query $query) } else return null; } - + public function hasSequences() { return true; } - + /** * @throws ObjectNotFoundException * @return DBTable @@ -185,35 +205,37 @@ public function getTableInfo($table) 'time' => DataType::TIME, 'date' => DataType::DATE, 'timestamp' => DataType::TIMESTAMP, - + 'bool' => DataType::BOOLEAN, - + 'int2' => DataType::SMALLINT, 'int4' => DataType::INTEGER, 'int8' => DataType::BIGINT, 'numeric' => DataType::NUMERIC, - + 'float4' => DataType::REAL, 'float8' => DataType::DOUBLE, - + 'varchar' => DataType::VARCHAR, 'bpchar' => DataType::CHAR, 'text' => DataType::TEXT, - + 'bytea' => DataType::BINARY, - + 'ip4' => DataType::IP, 'inet' => DataType::IP, - + 'ip4r' => DataType::IP_RANGE, - + + 'uuid' => DataType::UUID, + // unhandled types, not ours anyway 'tsvector' => null, - + 'ltree' => null, 'hstore' => null, ); - + try { $res = pg_meta_data($this->link, $table); } catch (BaseException $e) { @@ -221,43 +243,43 @@ public function getTableInfo($table) "unknown table '{$table}'" ); } - + $table = new DBTable($table); - + foreach ($res as $name => $info) { - + Assert::isTrue( array_key_exists($info['type'], $types), - + 'unknown type "' .$types[$info['type']] .'" found in column "'.$name.'"' ); - + if (empty($types[$info['type']])) continue; - + $column = new DBColumn( DataType::create($types[$info['type']])-> setNull(!$info['not null']), - + $name ); - + $table->addColumn($column); } - + return $table; } - + private function checkSingle($result) { if (pg_num_rows($result) > 1) throw new TooManyRowsException( 'query returned too many rows (we need only one)' ); - + return $result; } } diff --git a/core/DB/PostgresDialect.class.php b/core/DB/PostgresDialect.class.php index e11cb20713..e87cadda43 100644 --- a/core/DB/PostgresDialect.class.php +++ b/core/DB/PostgresDialect.class.php @@ -20,7 +20,7 @@ final class PostgresDialect extends Dialect { private static $tsConfiguration = 'utf8_russian'; private static $rankFunction = 'rank'; - + /** * @return PostgresDialect **/ @@ -28,36 +28,36 @@ public static function me() { return Singleton::getInstance(__CLASS__); } - + public static function getTsConfiguration() { return self::$tsConfiguration; } - + public static function setTsConfiguration($configuration) { self::$tsConfiguration = $configuration; } - + public static function setRankFunction($rank) { self::$rankFunction = $rank; } - + public static function quoteValue($value) { return "'".pg_escape_string($value)."'"; } - + public static function toCasted($field, $type) { return "{$field}::{$type}"; } - + public static function prepareFullText(array $words, $logic) { $glue = ($logic == DB::FULL_TEXT_AND) ? ' & ' : ' | '; - + return mb_strtolower( implode( @@ -69,111 +69,114 @@ public static function prepareFullText(array $words, $logic) ) ); } - + public function quoteBinary($data) { - return "E'".pg_escape_bytea($data)."'"; + return "'".pg_escape_bytea($data)."'"; // deleted first E in qoutes; it was - "E'..." } - + public function unquoteBinary($data) { return pg_unescape_bytea($data); } - + public function typeToString(DataType $type) { if ($type->getId() == DataType::BINARY) return 'BYTEA'; - + if (defined('POSTGRES_IP4_ENABLED')) { - + if ($type->getId() == DataType::IP) return 'ip4'; - + if ($type->getId() == DataType::IP_RANGE) return 'ip4r'; } - + + if ($type->getId() == DataType::UUID) + return 'UUID'; + return parent::typeToString($type); } - + public function hasTruncate() { return true; } - + public function hasMultipleTruncate() { return true; } - + public function hasReturning() { return true; } - + public function fullTextSearch($field, $words, $logic) { $searchString = self::prepareFullText($words, $logic); $field = $this->fieldToString($field); - + return "({$field} @@ to_tsquery('".self::$tsConfiguration."', ". self::quoteValue($searchString)."))"; } - + public function fullTextRank($field, $words, $logic) { $searchString = self::prepareFullText($words, $logic); $field = $this->fieldToString($field); - + return self::$rankFunction."({$field}, to_tsquery('".self::$tsConfiguration."', ". self::quoteValue($searchString)."))"; } - + public function preAutoincrement(DBColumn $column) { self::checkColumn($column); - + return 'CREATE SEQUENCE "' .$this->makeSequenceName($column).'";'; } - + public function postAutoincrement(DBColumn $column) { self::checkColumn($column); - + return 'default nextval(\'' .$this->makeSequenceName($column).'\')'; } - + public function quoteIpInRange($range, $ip) { $string = ''; - + if ($ip instanceof DialectString) $string .= $ip->toDialectString($this); else $string .= $this->quoteValue($ip); - + $string .= ' <<= '; - + if ($range instanceof DialectString) $string .= $range->toDialectString($this); else $string .= $this->quoteValue($range); - - return $string; + + return $string; } - + protected function makeSequenceName(DBColumn $column) { return $column->getTable()->getName().'_'.$column->getName(); } - + private static function checkColumn(DBColumn $column) { Assert::isTrue( diff --git a/core/Exceptions/MissingModuleException.class.php b/core/Exceptions/MissingModuleException.class.php new file mode 100644 index 0000000000..ae79d922dc --- /dev/null +++ b/core/Exceptions/MissingModuleException.class.php @@ -0,0 +1,18 @@ + + * @date 2011.12.25 + */ +class MissingModuleException extends BaseException {/*_*/} diff --git a/core/Form/Primitive.class.php b/core/Form/Primitive.class.php index beb3d364ad..2e945bb24f 100644 --- a/core/Form/Primitive.class.php +++ b/core/Form/Primitive.class.php @@ -22,10 +22,10 @@ final class Primitive extends StaticFactory public static function spawn($primitive, $name) { Assert::classExists($primitive); - + return new $primitive($name); } - + /** * @return Primitive **/ @@ -33,7 +33,7 @@ public static function alias($name, BasePrimitive $prm) { return new PrimitiveAlias($name, $prm); } - + /** * @return PrimitiveAnyType **/ @@ -41,7 +41,7 @@ public static function anyType($name) { return new PrimitiveAnyType($name); } - + /** * @return PrimitiveInteger **/ @@ -49,7 +49,7 @@ public static function integer($name) { return new PrimitiveInteger($name); } - + /** * @return PrimitiveFloat **/ @@ -57,7 +57,7 @@ public static function float($name) { return new PrimitiveFloat($name); } - + /** * @return PrimitiveIdentifier * @obsoleted by integerIdentifier and scalarIdentifier @@ -66,7 +66,7 @@ public static function identifier($name) { return new PrimitiveIdentifier($name); } - + /** * @return PrimitiveIntegerIdentifier **/ @@ -74,7 +74,7 @@ public static function integerIdentifier($name) { return new PrimitiveIntegerIdentifier($name); } - + /** * @return PrimitiveScalarIdentifier **/ @@ -82,7 +82,7 @@ public static function scalarIdentifier($name) { return new PrimitiveScalarIdentifier($name); } - + /** * @return PrimitivePolymorphicIdentifier **/ @@ -90,7 +90,7 @@ public static function polymorphicIdentifier($name) { return new PrimitivePolymorphicIdentifier($name); } - + /** * @return PrimitiveIdentifierList **/ @@ -98,7 +98,7 @@ public static function identifierlist($name) { return new PrimitiveIdentifierList($name); } - + /** * @return PrimitiveClass **/ @@ -106,7 +106,7 @@ public static function clazz($name) { return new PrimitiveClass($name); } - + /** * @return PrimitiveEnumeration **/ @@ -114,7 +114,7 @@ public static function enumeration($name) { return new PrimitiveEnumeration($name); } - + /** * @return PrimitiveEnumerationByValue **/ @@ -122,7 +122,7 @@ public static function enumerationByValue($name) { return new PrimitiveEnumerationByValue($name); } - + /** * @return PrimitiveEnumerationList **/ @@ -130,7 +130,7 @@ public static function enumerationList($name) { return new PrimitiveEnumerationList($name); } - + /** * @return PrimitiveDate **/ @@ -138,7 +138,7 @@ public static function date($name) { return new PrimitiveDate($name); } - + /** * @return PrimitiveTimestamp **/ @@ -146,7 +146,7 @@ public static function timestamp($name) { return new PrimitiveTimestamp($name); } - + /** * @return PrimitiveTime **/ @@ -154,7 +154,7 @@ public static function time($name) { return new PrimitiveTime($name); } - + /** * @return PrimitiveString **/ @@ -162,7 +162,7 @@ public static function string($name) { return new PrimitiveString($name); } - + /** * @return PrimitiveBinary **/ @@ -170,7 +170,7 @@ public static function binary($name) { return new PrimitiveBinary($name); } - + /** * @return PrimitiveRange **/ @@ -178,7 +178,7 @@ public static function range($name) { return new PrimitiveRange($name); } - + /** * @return PrimitiveDateRange **/ @@ -186,7 +186,7 @@ public static function dateRange($name) { return new PrimitiveDateRange($name); } - + /** * @return PrimitiveTimestampRange **/ @@ -194,7 +194,7 @@ public static function timestampRange($name) { return new PrimitiveTimestampRange($name); } - + /** * @return PrimitiveList **/ @@ -202,7 +202,7 @@ public static function choice($name) { return new PrimitiveList($name); } - + /** * @return PrimitiveArray **/ @@ -210,7 +210,7 @@ public static function set($name) { return new PrimitiveArray($name); } - + /** * @return PrimitiveHstore **/ @@ -218,7 +218,7 @@ public static function hstore($name) { return new PrimitiveHstore($name); } - + /** * @return PrimitiveMultiList **/ @@ -226,7 +226,7 @@ public static function multiChoice($name) { return new PrimitiveMultiList($name); } - + /** * @return PrimitivePlainList **/ @@ -234,7 +234,7 @@ public static function plainChoice($name) { return new PrimitivePlainList($name); } - + /** * @return PrimitiveBoolean **/ @@ -242,7 +242,7 @@ public static function boolean($name) { return new PrimitiveBoolean($name); } - + /** * @return PrimitiveTernary **/ @@ -250,7 +250,7 @@ public static function ternary($name) { return new PrimitiveTernary($name); } - + /** * @return PrimitiveFile **/ @@ -258,7 +258,7 @@ public static function file($name) { return new PrimitiveFile($name); } - + /** * @return PrimitiveImage **/ @@ -266,7 +266,7 @@ public static function image($name) { return new PrimitiveImage($name); } - + /** * @return ExplodedPrimitive **/ @@ -274,7 +274,7 @@ public static function exploded($name) { return new ExplodedPrimitive($name); } - + /** * @return PrimitiveInet **/ @@ -282,7 +282,7 @@ public static function inet($name) { return new PrimitiveInet($name); } - + /** * @return PrimitiveForm **/ @@ -290,7 +290,7 @@ public static function form($name) { return new PrimitiveForm($name); } - + /** * @return PrimitiveFormsList **/ @@ -298,7 +298,7 @@ public static function formsList($name) { return new PrimitiveFormsList($name); } - + /** * @return PrimitiveNoValue **/ @@ -306,7 +306,7 @@ public static function noValue($name) { return new PrimitiveNoValue($name); } - + /** * @return PrimitiveHttpUrl **/ @@ -314,39 +314,39 @@ public static function httpUrl($name) { return new PrimitiveHttpUrl($name); } - + /** * @return BasePrimitive **/ public static function prototyped($class, $propertyName, $name = null) { Assert::isInstance($class, 'Prototyped'); - + $proto = is_string($class) ? call_user_func(array($class, 'proto')) : $class->proto(); - + if (!$name) $name = $propertyName; - + return $proto->getPropertyByName($propertyName)-> makePrimitive($name); } - + /** * @return PrimitiveIdentifier **/ public static function prototypedIdentifier($class, $name = null) { Assert::isInstance($class, 'DAOConnected'); - + $dao = is_string($class) ? call_user_func(array($class, 'dao')) : $class->dao(); - + return self::prototyped($class, $dao->getIdName(), $name); } - + /** * @return PrimitiveIpAddress **/ @@ -354,7 +354,7 @@ public static function ipAddress($name) { return new PrimitiveIpAddress($name); } - + /** * @return PrimitiveIpRange */ @@ -362,5 +362,36 @@ public static function ipRange($name) { return new PrimitiveIpRange($name); } + + /** + * @static + * @param $name + * @return PrimitiveUuidString + **/ + public static function uuid($name) + { + return new PrimitiveUuidString($name); + } + + /** + * @static + * @param $name + * @return PrimitiveUniversalUniqueIdentifier + **/ + public static function uuidIdentifier($name) + { + return new PrimitiveUuidIdentifier($name); + } + + /** + * @static + * @param $name + * @return PrimitiveUniversalUniqueIdentifierList + **/ + public static function uuidIdentifierList($name) + { + return new PrimitiveUuidIdentifierList($name); + } + } ?> \ No newline at end of file diff --git a/core/Form/Primitives/PrimitiveUuidIdentifier.class.php b/core/Form/Primitives/PrimitiveUuidIdentifier.class.php new file mode 100644 index 0000000000..7778a58344 --- /dev/null +++ b/core/Form/Primitives/PrimitiveUuidIdentifier.class.php @@ -0,0 +1,20 @@ +value = array(); + + return $this; + } + + /** + * @return PrimitiveUuidIdentifierList + **/ + public function setValue($value) + { + if ($value) { + Assert::isArray($value); + Assert::isInstance(current($value), $this->className); + } + + $this->value = $value; + + return $this; + } + + public function importValue($value) + { + if ($value instanceof UnifiedContainer) { + if ($value->isLazy()) + return $this->import( + array($this->name => $value->getList()) + ); + elseif ( + $value->getParentObject()->getId() + && ($list = $value->getList()) + ) { + return $this->import( + array($this->name => ArrayUtils::getIdsArray($list)) + ); + } else { + return parent::importValue(null); + } + } + + if (is_array($value)) { + try { + Assert::isUniversalUniqueIdentifier(current($value)); + + return $this->import( + array($this->name => $value) + ); + } catch (WrongArgumentException $e) { + return $this->import( + array($this->name => ArrayUtils::getIdsArray($value)) + ); + } + } + + return parent::importValue($value); + } + + public function import($scope) + { + if (!$this->className) + throw new WrongStateException( + "no class defined for PrimitiveUuidIdentifierList '{$this->name}'" + ); + + if (!BasePrimitive::import($scope)) + return null; + + $this->applyImportFilters($scope[$this->name]); + + if (!is_array($scope[$this->name])) + return false; + + $list = array_unique($scope[$this->name]); + + $values = array(); + + foreach ($list as $id) { + if (!Assert::checkUniversalUniqueIdentifier($id)) + return false; + + $values[] = $id; + } + + $objectList = $this->dao()->getListByIds($values); + + if ( + count($objectList) == count($values) + && !($this->min && count($values) < $this->min) + && !($this->max && count($values) > $this->max) + ) { + $this->value = $objectList; + return true; + } + + return false; + } + + public function exportValue() + { + if (!$this->value) + return null; + + return ArrayUtils::getIdsArray($this->value); + } + +} diff --git a/core/Form/Primitives/PrimitiveUuidString.class.php b/core/Form/Primitives/PrimitiveUuidString.class.php new file mode 100644 index 0000000000..bf3a47e323 --- /dev/null +++ b/core/Form/Primitives/PrimitiveUuidString.class.php @@ -0,0 +1,32 @@ +setAllowedPattern(self::UUID_PATTERN); + } + +} diff --git a/core/OSQL/DataType.class.php b/core/OSQL/DataType.class.php index b299cb0990..6f7bd72739 100644 --- a/core/OSQL/DataType.class.php +++ b/core/OSQL/DataType.class.php @@ -20,66 +20,70 @@ final class DataType extends Enumeration implements DialectString const INTEGER = 0x001002; const BIGINT = 0x001003; const NUMERIC = 0x001704; - + const REAL = 0x001105; const DOUBLE = 0x001106; - + const BOOLEAN = 0x000007; - + const CHAR = 0x000108; const VARCHAR = 0x000109; const TEXT = 0x00000A; - + const DATE = 0x00000B; const TIME = 0x000A0C; const TIMESTAMP = 0x000A0D; const INTERVAL = 0x00000F; - + const BINARY = 0x00000E; - + const IP = 0x000010; const IP_RANGE = 0x000011; - + + const UUID = 0x000005; + const HAVE_SIZE = 0x000100; const HAVE_PRECISION = 0x000200; const HAVE_SCALE = 0x000400; const HAVE_TIMEZONE = 0x000800; const CAN_BE_UNSIGNED = 0x001000; - + private $size = null; private $precision = null; private $scale = null; - + private $null = true; private $timezone = false; private $unsigned = false; - + protected $names = array( self::SMALLINT => 'SMALLINT', self::INTEGER => 'INTEGER', self::BIGINT => 'BIGINT', self::NUMERIC => 'NUMERIC', - + self::REAL => 'FLOAT', self::DOUBLE => 'DOUBLE PRECISION', - + self::BOOLEAN => 'BOOLEAN', - + + self::UUID => 'UUID', + self::CHAR => 'CHARACTER', self::VARCHAR => 'CHARACTER VARYING', self::TEXT => 'TEXT', - + self::DATE => 'DATE', self::TIME => 'TIME', self::TIMESTAMP => 'TIMESTAMP', self::INTERVAL => 'INTERVAL', - + self::BINARY => 'BINARY', - + self::IP => 'IP', self::IP_RANGE => 'IP_RANGE' ); - + /** * @return DataType **/ @@ -87,17 +91,17 @@ public static function create($id) { return new self($id); } - + public static function getAnyId() { return self::BOOLEAN; } - + public function getSize() { return $this->size; } - + /** * @throws WrongArgumentException * @return DataType @@ -106,22 +110,22 @@ public function setSize($size) { Assert::isInteger($size); Assert::isTrue($this->hasSize()); - + $this->size = $size; - + return $this; } - + public function hasSize() { return (bool) ($this->id & self::HAVE_SIZE); } - + public function getPrecision() { return $this->precision; } - + /** * @throws WrongArgumentException * @return DataType @@ -130,22 +134,22 @@ public function setPrecision($precision) { Assert::isInteger($precision); Assert::isTrue(($this->id & self::HAVE_PRECISION) > 0); - + $this->precision = $precision; - + return $this; } - + public function hasPrecision() { return (bool) ($this->id & self::HAVE_PRECISION); } - + public function getScale() { return $this->scale; } - + /** * @throws WrongArgumentException * @return DataType @@ -154,12 +158,12 @@ public function setScale($scale) { Assert::isInteger($scale); Assert::isTrue(($this->id & self::HAVE_SCALE) > 0); - + $this->scale = $scale; - + return $this; } - + /** * @throws WrongArgumentException * @return DataType @@ -167,32 +171,32 @@ public function setScale($scale) public function setTimezoned($zoned = false) { Assert::isTrue(($this->id & self::HAVE_TIMEZONE) > 0); - + $this->timezone = (true === $zoned); - + return $this; } - + public function isTimezoned() { return $this->timezone; } - + /** * @return DataType **/ public function setNull($isNull = false) { $this->null = ($isNull === true); - + return $this; } - + public function isNull() { return $this->null; } - + /** * @throws WrongArgumentException * @return DataType @@ -200,46 +204,46 @@ public function isNull() public function setUnsigned($unsigned = false) { Assert::isTrue(($this->id && self::CAN_BE_UNSIGNED) > 0); - + $this->unsigned = ($unsigned === true); - + return $this; } - + public function isUnsigned() { return $this->unsigned; } - + public function toDialectString(Dialect $dialect) { $out = $dialect->typeToString($this); - + if ($this->unsigned) { $out .= ' UNSIGNED'; } - + if ($this->id & self::HAVE_PRECISION) { if ($this->precision) { - + switch ($this->id) { - + case self::TIME: case self::TIMESTAMP: - + $out .= "({$this->precision})"; break; - + case self::NUMERIC: - + $out .= $this->precision ? "({$this->size}, {$this->precision})" : "({$this->size})"; break; - + default: - + throw new WrongStateException(); } } @@ -248,18 +252,18 @@ public function toDialectString(Dialect $dialect) throw new WrongStateException( "type '{$this->name}' must have size" ); - + $out .= "({$this->size})"; } - + if ($this->id & self::HAVE_TIMEZONE) $out .= $dialect->timeZone($this->timezone); - + $out .= $this->null ? ' NULL' : ' NOT NULL'; - + return $out; } } diff --git a/meta/types/UuidType.class.php b/meta/types/UuidType.class.php new file mode 100644 index 0000000000..205512fa7c --- /dev/null +++ b/meta/types/UuidType.class.php @@ -0,0 +1,31 @@ + getColumnByName('root_id')-> dropReference(); - + return parent::create(); } - + public function testSchema() { return $this->create()->drop(); } - + public function testData() { $this->create(); - + foreach (DBTestPool::me()->getPool() as $connector => $db) { DBPool::me()->setDefault($db); $this->fill(); - + $this->getSome(); // 41! Cache::me()->clean(); $this->getSome(); - + $this->nonIntegerIdentifier(); - + $this->racySave(); $this->binaryTest(); $this->lazyTest(); } - + $this->drop(); } - + public function testBoolean() { $this->create(); - + foreach (DBTestPool::me()->getPool() as $connector => $db) { DBPool::me()->setDefault($db); - + //creating moscow $moscow = TestCity::create()->setName('Moscow'); $moscow = $moscow->dao()->add($moscow); $moscowId = $moscow->getId(); /* @var $moscow TestCity */ - + //now moscow capital $moscow->dao()->merge($moscow->setCapital(true)); TestCity::dao()->dropIdentityMap(); - + Criteria::create(TestCity::dao())-> setSilent(false)-> add(Expression::isTrue('capital'))-> get(); TestCity::dao()->dropIdentityMap(); - + $moscow = Criteria::create(TestCity::dao())-> setSilent(false)-> add(Expression::isNull('large'))-> get(); TestCity::dao()->dropIdentityMap(); - + //now moscow large $moscow = $moscow->dao()->merge($moscow->setLarge(true)); - + TestCity::dao()->dropIdentityMap(); $moscow = TestCity::dao()->getById($moscowId); $this->assertTrue($moscow->getCapital()); $this->assertTrue($moscow->getLarge()); - + Criteria::create(TestCity::dao())-> setSilent(false)-> add(Expression::not(Expression::isFalse('large')))-> get(); TestCity::dao()->dropIdentityMap(); } - + $this->drop(); } - + public function testCriteria() { $this->create(); - + foreach (DBTestPool::me()->getPool() as $connector => $db) { DBPool::me()->setDefault($db); $this->fill(); - + $this->criteriaResult(); - + Cache::me()->clean(); } - + $this->deletedCount(); - + $this->drop(); } - + public function testUnified() { $this->create(); - + foreach (DBTestPool::me()->getPool() as $connector => $db) { DBPool::me()->setDefault($db); $this->fill(); - + $this->unified(); - + Cache::me()->clean(); } - + $this->deletedCount(); - + $this->drop(); } - + public function testCount() { $this->create(); - + foreach (DBTestPool::me()->getPool() as $connector => $db) { DBPool::me()->setDefault($db); - + $this->fill(); - + $count = TestUser::dao()->getTotalCount(); - + $this->assertGreaterThan(1, $count); - + $city = TestCity::create()-> setId(1); - + $newUser = TestUser::create()-> setCity($city)-> @@ -158,40 +158,40 @@ public function testCount() setRegistered( Timestamp::create(time()) ); - + TestUser::dao()->add($newUser); - + $newCount = TestUser::dao()->getTotalCount(); - + $this->assertEquals($count + 1, $newCount); } - + $this->drop(); } - + public function testGetByEmptyId() { $this->create(); - + $this->getByEmptyIdTest(0); $this->getByEmptyIdTest(null); $this->getByEmptyIdTest(''); $this->getByEmptyIdTest('0'); $this->getByEmptyIdTest(false); - + $empty = TestLazy::create(); - + $this->assertNull($empty->getCity()); $this->assertNull($empty->getCityOptional()); $this->assertNull($empty->getEnum()); - + $this->drop(); } - + public function deletedCount() { TestUser::dao()->dropById(1); - + try { TestUser::dao()->dropByIds(array(1, 2)); $this->fail(); @@ -199,17 +199,17 @@ public function deletedCount() // ok } } - + public function fill($assertions = true) { $moscow = TestCity::create()-> setName('Moscow'); - + $piter = TestCity::create()-> setName('Saint-Peterburg'); - + $mysqler = TestUser::create()-> setCity($moscow)-> @@ -224,9 +224,9 @@ public function fill($assertions = true) setRegistered( Timestamp::create(time())->modify('-1 day') ); - + $postgreser = clone $mysqler; - + $postgreser-> setCredentials( Credentials::create()-> @@ -235,23 +235,23 @@ public function fill($assertions = true) )-> setCity($piter)-> setUrl(HttpUrl::create()->parse('http://postgresql.org/')); - + $piter = TestCity::dao()->add($piter); $moscow = TestCity::dao()->add($moscow); - + if ($assertions) { $this->assertEquals($piter->getId(), 1); $this->assertEquals($moscow->getId(), 2); } - + $postgreser = TestUser::dao()->add($postgreser); - + for ($i = 0; $i < 10; $i++) { $encapsulant = TestEncapsulant::dao()->add( TestEncapsulant::create()-> setName($i) ); - + $encapsulant->getCities()-> fetch()-> setList( @@ -259,119 +259,119 @@ public function fill($assertions = true) )-> save(); } - + $mysqler = TestUser::dao()->add($mysqler); - + if ($assertions) { $this->assertEquals($postgreser->getId(), 1); $this->assertEquals($mysqler->getId(), 2); } - + if ($assertions) { // put them in cache now TestUser::dao()->dropIdentityMap(); - + TestUser::dao()->getById(1); TestUser::dao()->getById(2); - + $this->getListByIdsTest(); - + Cache::me()->clean(); - + $this->assertTrue( ($postgreser == TestUser::dao()->getById(1)) ); - + $this->assertTrue( ($mysqler == TestUser::dao()->getById(2)) ); } - + $firstClone = clone $postgreser; $secondClone = clone $mysqler; - + $firstCount = TestUser::dao()->dropById($postgreser->getId()); $secondCount = TestUser::dao()->dropByIds(array($mysqler->getId())); - + if ($assertions) { $this->assertEquals($firstCount, 1); $this->assertEquals($secondCount, 1); - + try { TestUser::dao()->getById(1); $this->fail(); } catch (ObjectNotFoundException $e) { /* pass */ } - + $result = Criteria::create(TestUser::dao())-> add(Expression::eq(1, 2))-> getResult(); - + $this->assertEquals($result->getCount(), 0); $this->assertEquals($result->getList(), array()); } - + TestUser::dao()->import($firstClone); TestUser::dao()->import($secondClone); - + if ($assertions) { // cache multi-get $this->getListByIdsTest(); $this->getListByIdsTest(); } } - + public function criteriaResult() { $queryResult = Criteria::create(TestCity::dao())->getResult(); $this->assertEquals(2, $queryResult->getCount()); } - + public function unified() { $user = TestUser::dao()->getById(1); - + $encapsulant = TestEncapsulant::dao()->getPlainList(); - + $collectionDao = $user->getEncapsulants(); - + $collectionDao->fetch()->setList($encapsulant); - + $collectionDao->save(); - + unset($collectionDao); - + // fetch $encapsulantsList = $user->getEncapsulants()->getList(); - + $piter = TestCity::dao()->getById(1); $moscow = TestCity::dao()->getById(2); - + for ($i = 0; $i < 10; $i++) { $this->assertEquals($encapsulantsList[$i]->getId(), $i + 1); $this->assertEquals($encapsulantsList[$i]->getName(), $i); - + $cityList = $encapsulantsList[$i]->getCities()->getList(); - + $this->assertEquals($cityList[0], $piter); $this->assertEquals($cityList[1], $moscow); } - + unset($encapsulantsList); - + // lazy fetch $encapsulantsList = $user->getEncapsulants(true)->getList(); - + for ($i = 1; $i < 11; $i++) $this->assertEquals($encapsulantsList[$i], $i); - + // count $user->getEncapsulants()->clean(); - + $this->assertEquals($user->getEncapsulants()->getCount(), 10); - + $criteria = Criteria::create(TestEncapsulant::dao())-> add( Expression::in( @@ -379,25 +379,25 @@ public function unified() array($piter->getId(), $moscow->getId()) ) ); - + $user->getEncapsulants()->setCriteria($criteria); - + $this->assertEquals($user->getEncapsulants()->getCount(), 20); - + // distinct count $user->getEncapsulants()->clean(); - + $user->getEncapsulants()->setCriteria( $criteria-> setDistinct(true) ); - + if (DBPool::me()->getLink() instanceof SQLite) // TODO: sqlite does not support such queries yet return null; - + $this->assertEquals($user->getEncapsulants()->getCount(), 10); - + // unified container __clone $dao = $user->getEncapsulants(); $dao->setCriteria(Criteria::create()); // empty criteria @@ -410,45 +410,45 @@ public function unified() ); $this->assertNotEquals($dao, $cloneDao); // they should be different } - + public function testWorkingWithCache() { $this->create(); - + foreach (DBTestPool::me()->getPool() as $connector => $db) { DBPool::me()->setDefault($db); - + $item = TestItem::create()-> setName('testItem1'); - + TestItem::dao()->add($item); - + $encapsulant = TestEncapsulant::create()-> setName('testEncapsulant1'); - + TestEncapsulant::dao()->add($encapsulant); - + $subItem1 = TestSubItem::create()-> setName('testSubItem1')-> setEncapsulant($encapsulant)-> setItem($item); - + $subItem2 = TestSubItem::create()-> setName('testSubItem2')-> setEncapsulant($encapsulant)-> setItem($item); - + TestSubItem::dao()->add($subItem1); TestSubItem::dao()->add($subItem2); - + $items = Criteria::create(TestItem::dao())-> getList(); - + foreach ($items as $item) { foreach ($item->getSubItems()->getList() as $subItem) { $this->assertEquals( @@ -457,22 +457,22 @@ public function testWorkingWithCache() ); } } - + $encapsulant = TestEncapsulant::dao()->getById(1); - + $encapsulant->setName('testEncapsulant1_changed'); - + TestEncapsulant::dao()->save($encapsulant); - + // drop identityMap TestEncapsulant::dao()->dropIdentityMap(); TestSubItem::dao()->dropIdentityMap(); TestItem::dao()->dropIdentityMap(); - + $items = Criteria::create(TestItem::dao())-> getList(); - + foreach ($items as $item) { foreach ($item->getSubItems()->getList() as $subItem) { $this->assertEquals( @@ -481,28 +481,28 @@ public function testWorkingWithCache() ); } } - + // drop identityMap TestEncapsulant::dao()->dropIdentityMap(); TestSubItem::dao()->dropIdentityMap(); TestItem::dao()->dropIdentityMap(); - + $subItem = TestSubItem::dao()->getById(1); - + $this->assertEquals( $subItem->getEncapsulant()->getName(), 'testEncapsulant1_changed' ); - + // drop identityMap TestEncapsulant::dao()->dropIdentityMap(); TestSubItem::dao()->dropIdentityMap(); TestItem::dao()->dropIdentityMap(); - + $subItems = Criteria::create(TestSubItem::dao())-> getList(); - + foreach ($subItems as $subItem) { $this->assertEquals( $subItem->getEncapsulant()->getName(), @@ -510,10 +510,10 @@ public function testWorkingWithCache() ); } } - + $this->drop(); } - + /** * Install hstore * /usr/share/postgresql/contrib # cat hstore.sql | psql -U pgsql -d onphp @@ -521,13 +521,13 @@ public function testWorkingWithCache() public function testHstore() { $this->create(); - + $properties = array( 'age' => '23', 'weight' => 80, 'comment' => null, ); - + $user = TestUser::create()-> setCity( @@ -546,26 +546,26 @@ public function testHstore() Timestamp::create(time())->modify('-1 day') )-> setProperties(Hstore::make($properties)); - + $moscow = TestCity::dao()->add($moscow); - + $user = TestUser::dao()->add($user); - + Cache::me()->clean(); TestUser::dao()->dropIdentityMap(); - + $user = TestUser::dao()->getById('1'); - + $this->assertInstanceOf('Hstore', $user->getProperties()); - + $this->assertEquals( $properties, $user->getProperties()->getList() ); - - + + $form = TestUser::proto()->makeForm(); - + $form->get('properties')-> setFormMapping( array( @@ -574,93 +574,93 @@ public function testHstore() Primitive::string('comment'), ) ); - + $form->import( array('id' => $user->getId()) ); - + $this->assertNotNull($form->getValue('id')); - + $object = $user; - + FormUtils::object2form($object, $form); - + $this->assertInstanceOf('Hstore', $form->getValue('properties')); - + $this->assertEquals( array_filter($properties), $form->getValue('properties')->getList() ); - + $subform = $form->get('properties')->getInnerForm(); - + $this->assertEquals( $subform->getValue('age'), '23' ); - + $this->assertEquals( $subform->getValue('weight'), 80 ); - + $this->assertNull( $subform->getValue('comment') ); - + $user = new TestUser(); - + FormUtils::form2object($form, $user, false); - + $this->assertEquals( $user->getProperties()->getList(), array_filter($properties) ); - + $this->drop(); } - + /** * @see http://lists.shadanakar.org/onphp-dev-ru/0811/0774.html **/ public function testRecursiveContainers() { $this->markTestSkipped('wontfix'); - + $this->create(); - + TestObject::dao()->import( TestObject::create()-> setId(1)-> setName('test object') ); - + TestType::dao()->import( TestType::create()-> setId(1)-> setName('test type') ); - + $type = TestType::dao()->getById(1); - + $type->getObjects()->fetch()->setList( array(TestObject::dao()->getById(1)) )-> save(); - + $object = TestObject::dao()->getById(1); - + TestObject::dao()->save($object->setName('test object modified')); - + $list = $type->getObjects()->getList(); - + $modifiedObject = TestObject::dao()->getById(1); - + $this->assertEquals($list[0], $modifiedObject); - + $this->drop(); } - + public function testRecursionObjects() { $this->create(); @@ -710,30 +710,30 @@ public function nonIntegerIdentifier() { $id = 'non-integer-one'; $binaryData = "\0!bbq!\0"; - + $bin = TestBinaryStuff::create()-> setId($id)-> setData($binaryData); - + try { TestBinaryStuff::dao()->import($bin); } catch (DatabaseException $e) { return $this->fail(); } - + Cache::me()->clean(); - + $prm = Primitive::prototypedIdentifier('TestBinaryStuff', 'id'); - + $this->assertTrue($prm->import(array('id' => $id))); $this->assertSame($prm->getValue()->getId(), $id); - + $binLoaded = TestBinaryStuff::dao()->getById($id); $this->assertEquals($binLoaded, $bin); $this->assertEquals($binLoaded->getData(), $binaryData); $this->assertEquals(TestBinaryStuff::dao()->dropById($id), 1); - + $integerIdPrimitive = Primitive::prototypedIdentifier('TestUser'); try { $integerIdPrimitive->import(array('id' => 'string-instead-of-integer')); @@ -741,17 +741,17 @@ public function nonIntegerIdentifier() return $this->fail(); } } - + public function testIpAddressProperty() { $this->create(); - + $city = TestCity::create()-> setName('Khimki'); - + TestCity::dao()->add($city); - + $userWithIp = TestUser::create()-> setCredentials( @@ -763,13 +763,13 @@ public function testIpAddressProperty() setRegistered(Timestamp::makeNow())-> setCity($city)-> setIp(IpAddress::create('127.0.0.1')); - + TestUser::dao()->add($userWithIp); - + $this->assertTrue($userWithIp->getId() >= 1); - + $this->assertTrue($userWithIp->getIp() instanceof IpAddress); - + $plainIp = DBPool::me()->getByDao(TestUser::dao())-> queryColumn( @@ -777,24 +777,24 @@ public function testIpAddressProperty() from(TestUser::dao()->getTable())-> where(Expression::eq('id', $userWithIp->getId())) ); - + $this->assertEquals($plainIp[0], $userWithIp->getIp()->toString()); - + $count = Criteria::create(TestUser::dao())-> add(Expression::eq('ip', IpAddress::create('127.0.0.1')))-> addProjection(Projection::count('*', 'count'))-> getCustom('count'); - + $this->assertEquals($count, 1); - + $this->drop(); } - + public function testIpRangeProperty() { $this->create(); - + $akado = TestInternetProvider::create()-> setName('Akada')-> @@ -804,21 +804,21 @@ public function testIpRangeProperty() IpAddress::create('192.168.1.42') ) ); - + TestInternetProvider::dao()-> add($akado); - + $plainRange = Criteria::create(TestInternetProvider::dao())-> addProjection(Projection::property('range'))-> add(Expression::eq('name', 'Akada'))-> getCustom(); - + $this->assertEquals( $plainRange['range'], '192.168.1.1-192.168.1.42' ); - + TestInternetProvider::dao()-> add( TestInternetProvider::create()-> @@ -827,28 +827,28 @@ public function testIpRangeProperty() IpRange::create('192.168.2.0/24') ) ); - + $list = Criteria::create(TestInternetProvider::dao())-> addOrder('id')-> getList(); - + $this->assertEquals(count($list), 2); - + $this->drop(); } - + public function testLazy() { $this->create(); - + $parent = TestParentObject::create(); $child = TestChildObject::create()->setParent($parent); - + $parent->dao()->add($parent); - + $child->dao()->add($child); - + $this->assertEquals( $parent->getId(), Criteria::create(TestChildObject::dao())-> @@ -858,10 +858,10 @@ public function testLazy() add(Expression::eq('id', $child->getId()))-> getCustom('parentId') ); - + $this->drop(); } - + protected function getSome() { for ($i = 1; $i < 3; ++$i) { @@ -872,83 +872,83 @@ protected function getSome() == TestUser::dao()->getById($i) ); } - + $this->assertEquals( count(TestUser::dao()->getPlainList()), count(TestCity::dao()->getPlainList()) ); } - + private function racySave() { $lost = TestCity::create()-> setId(424242)-> setName('inexistant city'); - + try { TestCity::dao()->save($lost); - + $this->fail(); } catch (WrongStateException $e) { /* pass */ } } - + private function binaryTest() { $data = null; - + for ($i = 0; $i < 256; ++$i) $data .= chr($i); - + $id = sha1('all sessions are evil'); - + $stuff = TestBinaryStuff::create()-> setId($id)-> setData($data); - + $stuff = $stuff->dao()->import($stuff); - + Cache::me()->clean(); - + $this->assertEquals( TestBinaryStuff::dao()->getById($id)->getData(), $data ); - + TestBinaryStuff::dao()->dropById($id); } - + private function getListByIdsTest() { $first = TestUser::dao()->getById(1); - + TestUser::dao()->dropIdentityMap(); - + $list = TestUser::dao()->getListByIds(array(1, 3, 2, 1, 1, 1)); - + $this->assertEquals(count($list), 5); - + $this->assertEquals($list[0]->getId(), 1); $this->assertEquals($list[1]->getId(), 2); $this->assertEquals($list[2]->getId(), 1); $this->assertEquals($list[3]->getId(), 1); $this->assertEquals($list[4]->getId(), 1); - + $this->assertEquals($list[0], $first); - + $this->assertEquals( array(), TestUser::dao()->getListByIds(array(42, 42, 1738)) ); } - + private function lazyTest() { $city = TestCity::dao()->getById(1); - + $object = TestLazy::dao()->add( TestLazy::create()-> setCity($city)-> @@ -957,18 +957,18 @@ private function lazyTest() new ImageType(ImageType::getAnyId()) ) ); - + Cache::me()->clean(); - + $form = TestLazy::proto()->makeForm(); $form->import( array('id' => $object->getId()) ); - + $this->assertNotNull($form->getValue('id')); - + FormUtils::object2form($object, $form); - + foreach ($object->proto()->getPropertyList() as $name => $property) { if ( $property->getRelationId() == MetaRelation::ONE_TO_ONE @@ -981,7 +981,7 @@ private function lazyTest() } } } - + private function getByEmptyIdTest($id) { try { From 070ef3ea6bf957180550f3ea915cf4696560da5b Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 20 Jan 2012 14:58:22 +0400 Subject: [PATCH 005/418] NoSQL implementation --- core/DB/PgSQL.class.php | 6 +- core/Exceptions/CtppException.class.php | 3 +- .../MissingModuleException.class.php | 3 +- core/Exceptions/NoSQLException.class.php | 18 + .../PrimitiveUuidIdentifier.class.php | 2 +- .../PrimitiveUuidIdentifierList.class.php | 2 +- .../Primitives/PrimitiveUuidString.class.php | 2 +- core/NoSQL/CouchDB.class.php | 475 ++++++++++++++++ core/NoSQL/NoSQL.class.php | 106 ++++ core/NoSQL/NoSQLPool.class.php | 140 +++++ core/NoSQL/NoSqlDAO.class.php | 383 +++++++++++++ core/NoSQL/NoSqlObject.class.php | 65 +++ global.inc.php.tpl | 80 +-- main/DAOs/Workers/TrickyDaoWorker.class.php | 37 ++ main/Flow/CtppView.class.php | 13 +- .../OneToManyNoSqlLinked.class.php | 86 +++ main/Utils/UuidUtils.class.php | 44 ++ meta/builders/AutoClassBuilder.class.php | 52 +- meta/builders/AutoNoSqlDaoBuilder.class.php | 43 ++ meta/builders/BaseBuilder.class.php | 46 +- meta/builders/ContainerClassBuilder.class.php | 35 +- meta/classes/MetaConfiguration.class.php | 528 +++++++++--------- meta/dtd/meta.dtd | 1 + meta/patterns/BasePattern.class.php | 68 ++- meta/patterns/NosqlClassPattern.class.php | 40 ++ meta/types/UuidType.class.php | 2 +- 26 files changed, 1903 insertions(+), 377 deletions(-) create mode 100644 core/Exceptions/NoSQLException.class.php create mode 100644 core/NoSQL/CouchDB.class.php create mode 100644 core/NoSQL/NoSQL.class.php create mode 100644 core/NoSQL/NoSQLPool.class.php create mode 100644 core/NoSQL/NoSqlDAO.class.php create mode 100644 core/NoSQL/NoSqlObject.class.php create mode 100644 main/DAOs/Workers/TrickyDaoWorker.class.php create mode 100644 main/UnifiedContainer/OneToManyNoSqlLinked.class.php create mode 100644 main/Utils/UuidUtils.class.php create mode 100644 meta/builders/AutoNoSqlDaoBuilder.class.php create mode 100644 meta/patterns/NosqlClassPattern.class.php diff --git a/core/DB/PgSQL.class.php b/core/DB/PgSQL.class.php index 3258602247..f9d704c6f0 100644 --- a/core/DB/PgSQL.class.php +++ b/core/DB/PgSQL.class.php @@ -96,11 +96,7 @@ public function obtainSequence($sequence) */ protected function obtainUuid() { - if( !extension_loaded('uuid') ) { - throw new MissingModuleException('UUID module not found!'); - } - - return uuid_create(); + return UuidUtils::generate(); } /** diff --git a/core/Exceptions/CtppException.class.php b/core/Exceptions/CtppException.class.php index d4a9c7bca0..61149478f0 100644 --- a/core/Exceptions/CtppException.class.php +++ b/core/Exceptions/CtppException.class.php @@ -1,6 +1,7 @@ \ No newline at end of file diff --git a/core/Form/Primitives/PrimitiveUuidIdentifier.class.php b/core/Form/Primitives/PrimitiveUuidIdentifier.class.php index 7778a58344..1eaae310f6 100644 --- a/core/Form/Primitives/PrimitiveUuidIdentifier.class.php +++ b/core/Form/Primitives/PrimitiveUuidIdentifier.class.php @@ -1,7 +1,7 @@ 'get', 'post'=>'post', 'put'=>'put', 'delete'=>'delete' ); + + + public function __construct() { + if( !extension_loaded('curl') ) { + throw new MissingModuleException('CouchDB needs CURL module for PHP'); + } + } + + /** + * @param string $dbname + * @param string $id + * @return array + * @throws WrongArgumentException + */ + public function select() { + // checking args + if (func_num_args()!=2) { + throw new WrongArgumentException('Only 2 arguments allowed'); + } + + // parse args + $dbname = func_get_arg(0); + $id = func_get_arg(1); + + // checking dbname + Assert::isString($dbname); + Assert::isNotEmpty($dbname); + // checking id + Assert::isString($id); + Assert::isNotEmpty($id); + + return $this->exec( $this->getUrl($dbname, $id), 'get' ); + } + + /** + * @param string $dbname + * @param array $object + * @return array + * @throws WrongArgumentException + */ + public function insert() { + // checking args + if (func_num_args()!=2) { + throw new WrongArgumentException('Only 2 arguments allowed'); + } + + // parse args + $dbname = func_get_arg(0); + $object = func_get_arg(1); + + // checking dbname + Assert::isString($dbname); + Assert::isNotEmpty($dbname); + // checking object + Assert::isArray($object); + Assert::isNotEmptyArray($object); + + + // remove id + $id = $object['id']; + unset( $object['id'] ); + + $response = $this->exec( $this->getUrl($dbname, $id), 'put', json_encode($object) ); + $object['id'] = $response['id']; + $object['_rev'] = $response['rev']; + return $object; + } + + /** + * @param string $dbname + * @param array $object + * @param string $rev + * @return array + * @throws WrongArgumentException + */ + public function update() { + // checking args + if (func_num_args()!=3) { + throw new WrongArgumentException('Only 3 arguments allowed'); + } + + // parse args + $dbname = func_get_arg(0); + $object = func_get_arg(1); + $rev = func_get_arg(2); + + // checking dbname + Assert::isString($dbname); + Assert::isNotEmpty($dbname); + // checking object + Assert::isArray($object); + Assert::isNotEmptyArray($object); + // checking rev + Assert::isString($rev); + Assert::isNotEmpty($rev); + + // remove id + $id = $object['id']; + unset( $object['id'] ); + // add rev + $object['_rev'] = $rev; + + $response = $this->exec( $this->getUrl($dbname, $id), 'put', json_encode($object) ); + $object['id'] = $response['id']; + $object['_rev'] = $response['rev']; + return $object; + } + + /** + * @param string $dbname + * @param string $id + * @param string $rev + * @return int + * @throws WrongArgumentException + */ + public function delete() { + // checking args + if (func_num_args()!=3) { + throw new WrongArgumentException('Only 3 arguments allowed'); + } + + // parse args + $dbname = func_get_arg(0); + $id = func_get_arg(1); + $rev = func_get_arg(2); + + // checking dbname + Assert::isString($dbname); + Assert::isNotEmpty($dbname); + // checking id + Assert::isScalar($id); + Assert::isNotEmpty($id); + // checking rev + Assert::isString($rev); + Assert::isNotEmpty($rev); + + $response = $this->exec( $this->getUrl($dbname, $id, array('rev'=>$rev)), 'delete' ); + + return $response['ok'] ? 1 : 0; + } + + /** + * @param string $dbname + * @return array + * @throws WrongArgumentException + */ + public function getAllObjects() { + // checking args + if (func_num_args()!=1) { + throw new WrongArgumentException('Only 1 argument allowed'); + } + + // parse args + $dbname = func_get_arg(0); + + // checking dbname + Assert::isString($dbname); + Assert::isNotEmpty($dbname); + + $response = $this->exec( $this->getUrl($dbname, '_all_docs'), 'get' ); + $list = array(); + if( isset($response['total_rows']) && isset($response['rows']) ) { + $list = $response['rows']; + } + + return $list; + } + + /** + * @param string $dbname + * @return int + * @throws WrongArgumentException + */ + public function getTotalCount() { + // checking args + if (func_num_args()!=1) { + throw new WrongArgumentException('Only 1 argument allowed'); + } + + // parse args + $dbname = func_get_arg(0); + + // checking dbname + Assert::isString($dbname); + Assert::isNotEmpty($dbname); + + $response = $this->exec( $this->getUrl($dbname, '_all_docs'), 'post', '{"keys":[]}' ); + $count = 0; + if( isset($response['total_rows']) ) { + $count = $response['total_rows']; + } + + return $count; + } + + /** + * @param string $dbname + * @param string $view + * @param array $params [optional] + * @return array + * @throws WrongArgumentException + */ + public function getCustomList() { + // checking args + if (func_num_args()!=2 && func_num_args()!=3) { + throw new WrongArgumentException('Only 2 or 3 arguments allowed'); + } + + // parse args + $dbname = func_get_arg(0); + $view = func_get_arg(1); + $params = null; + + // checking dbname + Assert::isString($dbname); + Assert::isNotEmpty($dbname); + // checking view + Assert::isString($view); + Assert::isNotEmpty($view); + + // checking params + if( func_num_args()==3 ) { + $params = func_get_arg(2); + // checking params + Assert::isArray($params); + Assert::isNotEmptyArray($params); + } + + //die( $this->getUrl($dbname, $view, $params) ); + $response = $this->exec( $this->getUrl($dbname, $view, $params), 'get' ); + $list = array(); + if( isset($response['total_rows']) && isset($response['rows']) ) { + $list = $response['rows']; + } + + return $list; + } + + /** + * @param string $dbname + * @param string $view + * @param array $params [optional] + * @return mixed + * @throws WrongArgumentException + */ + public function getCustomData() { + // checking args + if (func_num_args()!=2 && func_num_args()!=3) { + throw new WrongArgumentException('Only 2 or 3 arguments allowed'); + } + + // parse args + $dbname = func_get_arg(0); + $view = func_get_arg(1); + $params = null; + + // checking dbname + Assert::isString($dbname); + Assert::isNotEmpty($dbname); + // checking view + Assert::isString($view); + Assert::isNotEmpty($view); + + // checking params + if( func_num_args()==3 ) { + $params = func_get_arg(2); + // checking params + Assert::isArray($params); + Assert::isNotEmptyArray($params); + } + // reduce + $params['reduce'] = 'false'; + + // query + $response = $this->exec( $this->getUrl($dbname, $view, $params), 'get' ); + $result = null; + if( isset($response['rows']) ) { + $result = $response['value']; + } + + return $result; + } + + public function obtainSequence($sequence) { + $normalyzeSequence = mb_strtolower( trim( $sequence ) ); + if( + 'uuid' === $normalyzeSequence || + 'uuid_id' === $normalyzeSequence + ) { + return UuidUtils::generate(); + } else { + $request = $this->makeRequest('_uuids')->setMethod( HttpMethod::get() ); + $response = $this->makeCurlClient()->send( $request ); + $result = json_decode( $response->getBody(), true ); + $this->checkErrors( $result ); + return array_shift( $result ); + + } + } + + /** + * @param string $dbname + * @param string $path + * @return string + */ + protected function getUrl( $dbname, $path=null, array $params=null ) { + Assert::isString($dbname); + + $urlPath = '/'; + if( !empty($dbname) ) { + $urlPath .= $dbname; + if( !empty($path) ) { + $urlPath .= '/'.$path; + } + } + + $urlParams = null; + if( !empty($params) ) { + $strParams = array(); + foreach( $params as $key=>$value ) { + $strParams[] = urlencode($key).'='.urlencode($value); + } + $urlParams = implode('&', $strParams); + unset($strParams); + } + + return + HttpUrl::create() + ->setScheme('http') + ->setAuthority( $this->username.':'.$this->password ) + ->setHost( $this->hostname ) + ->setPort( $this->port ) + ->setPath( $urlPath ) + ->setQuery( $urlParams ) + ->toString(); + } + + /** + * Execeutes CURL request + * @param string $url + * @param string $method + * @param string|null $data + * @return array + * @throws NoSQLException|ObjectNotFoundException + */ + protected function exec( $url, $method, $data=null ) { + if( !in_array($method, $this->_methods) ) { + throw new WrongArgumentException("Wrong menthod '{$method}'!"); + } + + // create resource + $ch = curl_init(); + + // options + $options = array( + CURLOPT_RETURNTRANSFER => true, + CURLINFO_HEADER_OUT => true, + CURLOPT_URL => $url, + CURLOPT_PORT => $this->port, + CURLOPT_USERAGENT => 'onPHP::'.__CLASS__ + ); + + if ( !is_null($this->username) && !is_null($this->password) ) { + $options[CURLOPT_USERPWD] = $this->username . ':' . $this->password; + } + + switch( $method ) { + case $this->_methods['get']: { + $options[CURLOPT_HTTPGET] = true; + } break; + case $this->_methods['post']: { + $options[CURLOPT_CUSTOMREQUEST] = 'POST'; + $options[CURLOPT_POSTFIELDS] = $data; + $options[CURLOPT_HTTPHEADER] = array( 'Content-type: application/json' ); + } break; + case $this->_methods['put']: { + $options[CURLOPT_CUSTOMREQUEST] = 'PUT'; + $options[CURLOPT_POSTFIELDS] = $data; + $options[CURLOPT_HTTPHEADER] = array( 'Content-type: application/json' ); + } break; + case $this->_methods['delete']: { + $options[CURLOPT_CUSTOMREQUEST] = 'DELETE'; + } break; + } + + // set options + curl_setopt_array( $ch, $options ); + + // curl exec + $response = curl_exec( $ch ); + $status = curl_getinfo( $ch, CURLINFO_HTTP_CODE ); + + // checking status + $answer = false; + switch( $status ) { + case 0: { + throw new NoSQLException( 'CouchDB server is asleep' ); + } break; + case 200: + case 201: + case 202: + case 304: { + // decoding answer + $answer = json_decode( $response, true ); + } break; + case 400: { + throw new NoSQLException( 'Bad Request' ); + } break; + case 401: { + throw new NoSQLException( 'Unauthorized' ); + } break; + case 403: { + throw new NoSQLException( 'Forbidden' ); + } break; + case 404: { + $answer = json_decode( $response, true ); + $reason = isset($answer['reason']) ? $answer['reason'] : null; + throw new ObjectNotFoundException( $reason ); + } break; + case 405: { + throw new NoSQLException( 'Resource Not Allowed' ); + } break; + case 406: { + throw new NoSQLException( 'Not Acceptable' ); + } break; + case 409: { + throw new NoSQLException( 'Conflict' ); + } break; + case 412: { + throw new NoSQLException( 'Precondition Failed' ); + } break; + case 415: { + throw new NoSQLException( 'Bad Content Type' ); + } break; + case 401: { + throw new NoSQLException( 'Unauthorized' ); + } break; + case 500: { + throw new NoSQLException( 'CouchDB server error' ); + } break; + default: { + die('NOSQL FATAL!!!'); + } break; + } + + return $answer; + } + +} diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php new file mode 100644 index 0000000000..1ffd3c0f62 --- /dev/null +++ b/core/NoSQL/NoSQL.class.php @@ -0,0 +1,106 @@ + + setUsername($user)-> + setPassword($pass)-> + setHostname($host); + if( !empty($port) ) { + $db->setPort($port); + } + + return $db; + } + + /** + * @param string $name + * @return NoSQL + */ + public function setUsername($name) { + $this->username = $name; + + return $this; + } + + /** + * @param string $password + * @return NoSQL + */ + public function setPassword($password) { + $this->password = $password; + + return $this; + } + + /** + * @param string $host + * @return NoSQL + */ + public function setHostname($host) { + $port = null; + + if (strpos($host, ':') !== false) + list($host, $port) = explode(':', $host, 2); + + $this->hostname = $host; + $this->port = $port; + + return $this; + } + + public function setPort($port) { + $this->port = $port; + + return $this; + } + +} diff --git a/core/NoSQL/NoSQLPool.class.php b/core/NoSQL/NoSQLPool.class.php new file mode 100644 index 0000000000..700557e8ed --- /dev/null +++ b/core/NoSQL/NoSQLPool.class.php @@ -0,0 +1,140 @@ +getLink($dao->getLinkName()); + } + + /** + * @param NoSQL $db + * @return NoSQLPool + */ + public function setDefault(NoSQL $db) + { + $this->default = $db; + + return $this; + } + + /** + * @return NoSQLPool + **/ + public function dropDefault() + { + $this->default = null; + + return $this; + } + + /** + * @param string $name + * @param NoSQL $db + * @return NoSQLPool + * @throws WrongArgumentException + */ + public function addLink($name, NoSQL $db) + { + if (isset($this->pool[$name])) + throw new WrongArgumentException( + "already have '{$name}' link" + ); + + $this->pool[$name] = $db; + + return $this; + } + + /** + * @param string $name + * @return NoSQLPool + * @throws MissingElementException + */ + public function dropLink($name) + { + if (!isset($this->pool[$name])) + throw new MissingElementException( + "link '{$name}' not found" + ); + + unset($this->pool[$name]); + + return $this; + } + + /** + * @param string $name + * @return NoSQL + * @throws MissingElementException + */ + public function getLink($name = null) + { + $link = null; + + // single-NoSQL project + if (!$name) { + if (!$this->default) { + throw new MissingElementException( + 'i have no default link and requested link name is null' + ); + } + + $link = $this->default; + } elseif (isset($this->pool[$name])) { + $link = $this->pool[$name]; + } + // check if found and return + if ($link) { + return $link; + } + + throw new MissingElementException( + "can't find link with '{$name}' name" + ); + } + + /** + * @return NoSQLPool + */ + public function shutdown() + { + $this->default = null; + $this->pool = array(); + + return $this; + } +} +?> \ No newline at end of file diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php new file mode 100644 index 0000000000..bf7face592 --- /dev/null +++ b/core/NoSQL/NoSqlDAO.class.php @@ -0,0 +1,383 @@ +getLink()->select( $this->getTable(), $id )) { + $object = $this->makeNoSqlObject($row); + } + + return $object; + } + + public function getByLogic(LogicalObject $logic, $expires = Cache::DO_NOT_CACHE) { + throw new UnsupportedMethodException( 'Method "getByLogic" is not supported in NoSQL' ); + } + + public function getByQuery(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { + throw new UnsupportedMethodException( 'Method "getByQuery" is not supported in NoSQL' ); + } + + public function getCustom(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { + throw new UnsupportedMethodException( 'Method "getCustom" is not supported in NoSQL' ); + } +//@} + +/// object's list getters +//@{ + /** + * @param array $ids + * @param int $expires + * @return array + */ + public function getListByIds(array $ids, $expires = Cache::EXPIRES_MEDIUM) { + $list = array(); + foreach( $ids as $id ) { + try { + $obj = $this->getById( $id ); + $list[ $id ] = $obj; + } catch(Exception $e) { + // it's ok + } + } + return $list; + } + + public function getListByQuery(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { + throw new UnsupportedMethodException( 'Method "getCustom" is not supported in NoSQL' ); + } + + public function getListByLogic(LogicalObject $logic, $expires = Cache::DO_NOT_CACHE) { + throw new UnsupportedMethodException( 'Method "getCustom" is not supported in NoSQL' ); + } + + /** + * @param int $expires + * @return array + */ + public function getPlainList($expires = Cache::EXPIRES_MEDIUM) { + $list = array(); + $stack = $this->getLink()->getAllObjects( $this->getTable() ); + if( !empty($stack) ) { + foreach( $stack as $row ) { + $object = $this->getById( $row['id'] ); + $list[ $object->getId() ] = $object; + } + } + + return $list; + } + + /** + * @param int $expires + * @return int + */ + public function getTotalCount($expires = Cache::DO_NOT_CACHE) { + return $this->getLink()->getTotalCount( $this->getTable() ); + } +//@} + + +/// custom list getters +//@{ + public function getCustomList(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { + throw new UnsupportedMethodException( 'Method "getCustomList" is not supported in NoSQL' ); + } + + public function getCustomRowList(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { + throw new UnsupportedMethodException( 'Method "getCustomRowList" is not supported in NoSQL' ); + } +//@} + +/// query result getters +//@{ + public function getQueryResult(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { + throw new UnsupportedMethodException( 'Method "getQueryResult" is not supported in NoSQL' ); + } +//@} + +/// some queries +//@{ + public function makeSelectHead() { + throw new UnsupportedMethodException( 'Method "makeSelectHead" is not supported in NoSQL' ); + } + + public function makeTotalCountQuery() { + throw new UnsupportedMethodException( 'Method "makeTotalCountQuery" is not supported in NoSQL' ); + } +//@} + +/// erasers +//@{ + public function drop(Identifiable $object) { + $this->assertNoSqlObject( $object ); + + $link = NoSQLPool::getByDao( $this ); + // delete + return + $link + ->delete( + $this->getTable(), + $object->getId(), + $object->getRev() + ); + } + + public function dropById($id) { + return parent::dropById($id); + } + + public function dropByIds(array $ids) { + return parent::dropByIds($ids); + } +//@} + +/// injects +//@{ + protected function inject( InsertOrUpdateQuery $query, Identifiable $object) { + throw new UnsupportedMethodException( 'Method "inject" is not supported in NoSQL' ); + } + + protected function doInject( InsertOrUpdateQuery $query, Identifiable $object) { + throw new UnsupportedMethodException( 'Method "doInject" is not supported in NoSQL' ); + } +//@} + +/// savers +//@{ + public function take(Identifiable $object) { + return + $object->getId() + ? $this->merge($object, true) + : $this->add($object); + } + + public function add(Identifiable $object) { + $this->assertNoSqlObject( $object ); + + // make sequence + $link = NoSQLPool::getByDao( $this ); + $object->setId( + $link->obtainSequence( + $this->getSequence() + ) + ); + + // insert + $entity = + $link + ->insert( + $this->getTable(), + $object->toArray() + ); + + $object->setId( $entity['id'] ); + if( $link instanceof CouchDB ) { + $object->setRev($entity['_rev']); + } + + return $object; + } + + public function save(Identifiable $object) { + $this->assertNoSqlObject( $object ); + + $link = NoSQLPool::getByDao( $this ); + // insert + $entity = + $link + ->update( + $this->getTable(), + $object->toArray(), + $object->getRev() + ); + + $object->setId( $entity['id'] ); + if( $link instanceof CouchDB ) { + $object->setRev($entity['_rev']); + } + + return $object; + } + + public function import(Identifiable $object) { + $this->assertNoSqlObject( $object ); + + $link = NoSQLPool::getByDao( $this ); + // insert + $entity = + $link + ->insert( + $this->getTable(), + $object->toArray() + ); + + if( $link instanceof CouchDB ) { + $object->setRev($entity['_rev']); + } + + return $object; + } + + public function merge(Identifiable $object, $cacheOnly = true) { + Assert::isNotNull($object->getId()); + + $this->checkObjectType($object); + + try { + $old = Cache::worker($this)->getById($object->getId()); + } catch( Exception $e ) { + return $this->save($object); + } + + return $this->unite($object, $old); + } + + public function unite( Identifiable $object, Identifiable $old ) { + Assert::isNotNull($object->getId()); + + Assert::isTypelessEqual( + $object->getId(), $old->getId(), + 'cannot merge different objects' + ); + + $hasChanges = false; + + foreach ($this->getProtoClass()->getPropertyList() as $property) { + $getter = $property->getGetter(); + + if ($property->getClassName() === null) { + $changed = ($old->$getter() !== $object->$getter()); + } else { + /** + * way to skip pointless update and hack for recursive + * comparsion. + **/ + $changed = + ($old->$getter() !== $object->$getter()) + || ($old->$getter() != $object->$getter()); + } + + if ($changed) { + $hasChanges = true; + } + } + + if( $hasChanges ) { + $object = $this->save( $object ); + } + + return $object; + } +//@} + + +/// object's list getters +//@{ + public function getListByView($view, $key, $criteria=null) { + $params = array(); + + // parse key + switch( get_class($this->getLink()) ) { + case 'CouchDB': { + $params['key'] = $key; + } break; + default: { + throw new WrongStateException( 'Do not know how to work with link type '.get_class($this->getLink()) ); + } break; + } + + // parse criteria + if( !is_null($criteria) && ($criteria instanceof Criteria) ) { + switch( get_class($this->getLink()) ) { + case 'CouchDB': { + if( $criteria->getOffset() ) { + $params['skip'] = $criteria->getOffset(); + } + if( $criteria->getLimit() ) { + $params['limit'] = $criteria->getLimit(); + } + if( !$criteria->getOrder()->getLast()->isAsc() ) { + $params['descending'] = 'true'; + } + } break; + default: { + throw new WrongStateException( 'Do not know how to work with criteria and link type '.get_class($this->getLink()) ); + } break; + } + } + + // query + $list = array(); + $stack = $this->getLink()->getCustomList( $this->getTable(), $view, $params ); + if( !empty($stack) ) { + foreach( $stack as $row ) { + $list[ $row['id'] ] = $this->makeNoSqlObject( $row['value'] ); + } + } + + return $list; + } +//@} + + + /** + * @param $object + * @throws WrongStateException + */ + protected function assertNoSqlObject( $object ) { + if( !($object instanceof NoSqlObject) ) { + throw new WrongStateException('Object must be instance of NoSqlObject'); + } + } + + /** + * @param array $array + * @param null $prefix + * @return Identifiable|Prototyped + */ + public function makeNoSqlObject($array, $prefix = null) { + $object = null; + + if( $this->getLink() instanceof CouchDB ) { + $array['id'] = $array['_id']; + unset( $array['_id'] ); + } + + try { + $object = $this->makeObject( $array, $prefix ); + if( $this->getLink() instanceof CouchDB ) { + $object->setRev($array['_rev']); + } + } catch(Exception $e) { + throw new WrongStateException( 'Can not parse object with id '.$array['id'] ); + } + return $object; + } + + /** + * @return NoSQL + */ + public function getLink() { + return NoSQLPool::me()->getLink( $this->getLinkName() );; + } + +} diff --git a/core/NoSQL/NoSqlObject.class.php b/core/NoSQL/NoSqlObject.class.php new file mode 100644 index 0000000000..729c441033 --- /dev/null +++ b/core/NoSQL/NoSqlObject.class.php @@ -0,0 +1,65 @@ +_rev = $rev; + return $this; + } + + /** + * @return string + */ + public function getRev() { + return $this->_rev; + } + + public function toArray() { + $entity = array(); + /** @var $property LightMetaProperty */ + foreach ($this->proto()->getPropertyList() as $property) { + if( $property->isGenericType() || $property->getType()=='enumeration' ) { + $value = call_user_func(array($this, $property->getGetter())); + if( is_object( $value ) ) { + if( $value instanceof Date ) { + //$value = $value->toStamp(); + $value = $value->toString(); + } + if( $value instanceof Enumeration ) { + $value = $value->getId(); + } + + } + $entity[ $property->getColumnName() ] = $value; + } + } +// $entity[ '_id' ] = $this->id; +// $entity[ '_rev' ] = $this->_rev; + return $entity; + } + +} diff --git a/global.inc.php.tpl b/global.inc.php.tpl index 83196a2734..cf2b7b0f76 100644 --- a/global.inc.php.tpl +++ b/global.inc.php.tpl @@ -10,12 +10,12 @@ ***************************************************************************/ // sample system-wide configuration file - + function error2Exception($code, $string, $file, $line, $context) { throw new BaseException($string, $code); } - + /* void */ function __autoload_failed($classname, $message) { eval( @@ -24,14 +24,14 @@ .'throw new ClassNotFoundException("'.$classname.': '.$message.'");' ); } - + // file extensions define('EXT_CLASS', '.class.php'); define('EXT_TPL', '.tpl.html'); define('EXT_MOD', '.inc.php'); define('EXT_HTML', '.html'); define('EXT_UNIT', '.unit.php'); - + // overridable constant, don't forget for trailing slash // also you may consider using /dev/shm/ for cache purposes if (!defined('ONPHP_TEMP_PATH')) @@ -39,109 +39,111 @@ 'ONPHP_TEMP_PATH', sys_get_temp_dir().DIRECTORY_SEPARATOR.'onPHP'.DIRECTORY_SEPARATOR ); - + if (!defined('ONPHP_CLASS_CACHE')) define('ONPHP_CLASS_CACHE', ONPHP_TEMP_PATH); - + // classes autoload magic if (!defined('ONPHP_CLASS_CACHE_TYPE')) define('ONPHP_CLASS_CACHE_TYPE', 'classPathCache'); - + require dirname(__FILE__).DIRECTORY_SEPARATOR .'misc'.DIRECTORY_SEPARATOR .'Autoloader'.EXT_MOD; - + spl_autoload_register(array('Autoloader', ONPHP_CLASS_CACHE_TYPE), false); - + // system settings error_reporting(E_ALL | E_STRICT); set_error_handler('error2Exception', E_ALL | E_STRICT); ignore_user_abort(true); define('ONPHP_VERSION', '1.0.10.99'); - + if (!defined('ONPHP_IPC_PERMS')) define('ONPHP_IPC_PERMS', 0660); - + // paths define('ONPHP_ROOT_PATH', dirname(__FILE__).DIRECTORY_SEPARATOR); define('ONPHP_CORE_PATH', ONPHP_ROOT_PATH.'core'.DIRECTORY_SEPARATOR); define('ONPHP_MAIN_PATH', ONPHP_ROOT_PATH.'main'.DIRECTORY_SEPARATOR); define('ONPHP_META_PATH', ONPHP_ROOT_PATH.'meta'.DIRECTORY_SEPARATOR); - + if (!defined('ONPHP_META_PATH')) define( 'ONPHP_META_PATH', ONPHP_ROOT_PATH.'meta'.DIRECTORY_SEPARATOR ); - + define('ONPHP_META_CLASSES', ONPHP_META_PATH.'classes'.DIRECTORY_SEPARATOR); - + define( 'ONPHP_INCUBATOR_PATH', ONPHP_ROOT_PATH.'incubator'.DIRECTORY_SEPARATOR ); - + set_include_path( // current path get_include_path().PATH_SEPARATOR - + // core classes .ONPHP_CORE_PATH.'Base' .PATH_SEPARATOR .ONPHP_CORE_PATH.'Cache' .PATH_SEPARATOR - + .ONPHP_CORE_PATH.'DB' .PATH_SEPARATOR .ONPHP_CORE_PATH.'DB'.DIRECTORY_SEPARATOR.'Transaction'.PATH_SEPARATOR - + .ONPHP_CORE_PATH.'Exceptions' .PATH_SEPARATOR - + .ONPHP_CORE_PATH.'Form' .PATH_SEPARATOR .ONPHP_CORE_PATH.'Form'.DIRECTORY_SEPARATOR.'Filters'.PATH_SEPARATOR .ONPHP_CORE_PATH.'Form'.DIRECTORY_SEPARATOR.'Primitives'.PATH_SEPARATOR - + .ONPHP_CORE_PATH.'Logic' .PATH_SEPARATOR .ONPHP_CORE_PATH.'OSQL' .PATH_SEPARATOR - + + .ONPHP_CORE_PATH.'NoSQL' .PATH_SEPARATOR + // main framework .ONPHP_MAIN_PATH.'Base' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Criteria' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Criteria'.DIRECTORY_SEPARATOR.'Projections'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Crypto' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'DAOs' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'DAOs'.DIRECTORY_SEPARATOR.'Handlers'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'DAOs'.DIRECTORY_SEPARATOR.'Workers'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Flow' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'SPL' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Net' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Http'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Mail'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Ip'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Soap'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Math' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Markup' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Markup'.DIRECTORY_SEPARATOR.'Feed'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Markup'.DIRECTORY_SEPARATOR.'Html'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'OQL' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Expressions'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Parsers'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Statements'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'OpenId' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'EntityProto'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'EntityProto'.DIRECTORY_SEPARATOR.'Builders'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'EntityProto'.DIRECTORY_SEPARATOR.'Accessors'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'UnifiedContainer'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Utils' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'TuringTest'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Archivers'.PATH_SEPARATOR @@ -161,23 +163,23 @@ .ONPHP_MAIN_PATH.'Messages'.DIRECTORY_SEPARATOR.'Interface'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Application' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Charts'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Charts'.DIRECTORY_SEPARATOR.'Google'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Monitoring'.PATH_SEPARATOR - + .ONPHP_META_CLASSES.PATH_SEPARATOR - + /* .ONPHP_INCUBATOR_PATH .'classes'.DIRECTORY_SEPARATOR .'Application'.DIRECTORY_SEPARATOR.PATH_SEPARATOR - + .ONPHP_INCUBATOR_PATH .'classes'.DIRECTORY_SEPARATOR .'Application'.DIRECTORY_SEPARATOR .'Markups'.DIRECTORY_SEPARATOR.PATH_SEPARATOR - + .ONPHP_INCUBATOR_PATH .'classes'.DIRECTORY_SEPARATOR .'Application'.DIRECTORY_SEPARATOR @@ -185,7 +187,7 @@ .'Documents'.DIRECTORY_SEPARATOR.PATH_SEPARATOR */ ); - + //NOTE: disable by default //see http://pgfoundry.org/docman/view.php/1000079/117/README.txt //define('POSTGRES_IP4_ENABLED', true); diff --git a/main/DAOs/Workers/TrickyDaoWorker.class.php b/main/DAOs/Workers/TrickyDaoWorker.class.php new file mode 100644 index 0000000000..b1187368c9 --- /dev/null +++ b/main/DAOs/Workers/TrickyDaoWorker.class.php @@ -0,0 +1,37 @@ +isNoSqlDao() ) { + return true; + } + + return parent::uncacheLists(); + } + + /** + * Проверяем является ли текущий DAO реализацией NoSqlDAO + * @return bool + */ + protected function isNoSqlDao() { + return ($this->dao instanceof NoSqlDAO); + } + + + } diff --git a/main/Flow/CtppView.class.php b/main/Flow/CtppView.class.php index 2e9b64fe51..26a7a56697 100644 --- a/main/Flow/CtppView.class.php +++ b/main/Flow/CtppView.class.php @@ -1,10 +1,19 @@ - * @date 2011.12.25 */ class CtppView implements View, Stringable { diff --git a/main/UnifiedContainer/OneToManyNoSqlLinked.class.php b/main/UnifiedContainer/OneToManyNoSqlLinked.class.php new file mode 100644 index 0000000000..d8d06a4425 --- /dev/null +++ b/main/UnifiedContainer/OneToManyNoSqlLinked.class.php @@ -0,0 +1,86 @@ +list, + "that's not an array :-/" + ); + + if (!$this->fetched) { + throw new WrongStateException( + 'do not want to save non-fetched collection' + ); + } + + /** @var $object NoSqlObject */ + foreach($this->list as &$object) { + $object->dao->drop( $object ); + } + + $this->clean(); + + return $this; + } + + public function save() { + Assert::isArray( + $this->list, + "that's not an array :-/" + ); + + if (!$this->fetched) { + throw new WrongStateException( + 'do not want to save non-fetched collection' + ); + } + + /** @var $object NoSqlObject */ + foreach( $this->list as &$object ) { + if( $object->getId() ) { + $object->dao->save( $object ); + } else { + $object->dao->add( $object ); + } + } + + return $this; + } + + /** + * @abstract + * @return array + */ + protected function fetchList() { + $list = $this->dao->getListByView( $this->getViewName(), $this->parent->getId(), $this->worker->getCriteria() ); + if( $this->lazy ) { + $newList = array(); + foreach( $list as $obj ) { + $newList[] = $obj->getId(); + } + } else { + $this->list = $list; + } + + return $this; + } + + protected abstract function getViewName(); + } diff --git a/main/Utils/UuidUtils.class.php b/main/Utils/UuidUtils.class.php new file mode 100644 index 0000000000..4657b43f44 --- /dev/null +++ b/main/Utils/UuidUtils.class.php @@ -0,0 +1,44 @@ +getName()}"; - + $isNamed = false; - + if ($parent = $class->getParent()) $out .= " extends {$parent->getName()}"; elseif ( @@ -30,30 +30,36 @@ public static function build(MetaClass $class) ) { $out .= " extends NamedObject"; $isNamed = true; - } elseif (!$class->getPattern() instanceof ValueObjectPattern) + } elseif ( + $class->getPattern() instanceof NosqlClassPattern + && $class->hasProperty('id') + ) { + $out .= " extends NoSqlObject"; + } elseif (!$class->getPattern() instanceof ValueObjectPattern) { $out .= " extends IdentifiableObject"; - + } + if ($interfaces = $class->getInterfaces()) $out .= ' implements '.implode(', ', $interfaces); - + $out .= "\n{\n"; - + foreach ($class->getProperties() as $property) { if (!self::doPropertyBuild($class, $property, $isNamed)) continue; - + $out .= "protected \${$property->getName()} = " ."{$property->getType()->getDeclaration()};\n"; - + if ($property->getFetchStrategyId() == FetchStrategy::LAZY) { $out .= "protected \${$property->getName()}Id = null;\n"; } } - + $valueObjects = array(); - + foreach ($class->getProperties() as $property) { if ( $property->getType() instanceof ObjectType @@ -65,7 +71,7 @@ public static function build(MetaClass $class) $property->getType()->getClassName(); } } - + if ($valueObjects) { $out .= << $className) { $out .= "\$this->{$propertyName} = new {$className}();\n"; } - + $out .= "}\n"; } - + foreach ($class->getProperties() as $property) { if (!self::doPropertyBuild($class, $property, $isNamed)) continue; - + $out .= $property->toMethods($class); } - + $out .= "}\n"; $out .= self::getHeel(); - + return $out; } - + private static function doPropertyBuild( MetaClass $class, MetaClassProperty $property, @@ -113,19 +119,19 @@ private static function doPropertyBuild( ) ) return true; - + return false; } - + if ($isNamed && $property->getName() == 'name') return false; - + if ( ($property->getName() == 'id') && !$property->getClass()->getParent() ) return false; - + // do not redefine parent's properties if ( $property->getClass()->getParent() @@ -135,7 +141,7 @@ private static function doPropertyBuild( ) ) return false; - + return true; } } diff --git a/meta/builders/AutoNoSqlDaoBuilder.class.php b/meta/builders/AutoNoSqlDaoBuilder.class.php new file mode 100644 index 0000000000..46ab06806e --- /dev/null +++ b/meta/builders/AutoNoSqlDaoBuilder.class.php @@ -0,0 +1,43 @@ +getParent() ) + || + $class->getParent()->getPattern() instanceof InternalClassPattern + ) { + $parentName = 'NoSqlDAO'; + } else { + $parentName = $class->getParent()->getName().'DAO'; + } + + $out = self::getHead(); + + $out .= <<getName()}DAO extends {$parentName} +{ + +EOT; + + $out .= self::buildPointers($class)."\n}\n"; + + return $out.self::getHeel(); + } + +} diff --git a/meta/builders/BaseBuilder.class.php b/meta/builders/BaseBuilder.class.php index 9efc4c85ca..e5cf888aa9 100644 --- a/meta/builders/BaseBuilder.class.php +++ b/meta/builders/BaseBuilder.class.php @@ -18,11 +18,11 @@ public static function build(MetaClass $class) { throw new UnimplementedFeatureException('i am forgotten method'); } - + protected static function buildPointers(MetaClass $class) { $out = null; - + if (!$class->getPattern() instanceof AbstractClassPattern) { if ( $class->getIdentifier()->getColumnName() !== 'id' @@ -35,7 +35,7 @@ public function getIdName() EOT; } - + $out .= <<getName()}'; } +EOT; + + if( + $class->getIdentifier()->getType() instanceof UuidType + ) + { + $out .= <<getTableName()}_id'; } EOT; + } + } elseif ($class->getWithInternalProperties()) { $out .= <<getReferencingClasses()) { $uncachers = array(); foreach ($liaisons as $className) { $uncachers[] = $className.'::dao()->uncacheLists();'; } - + $uncachers = implode("\n", $uncachers); - + $out .= <<getSourceLink()) { $out .= <<'; diff --git a/meta/builders/ContainerClassBuilder.class.php b/meta/builders/ContainerClassBuilder.class.php index eb3243e118..ddb69a7caf 100644 --- a/meta/builders/ContainerClassBuilder.class.php +++ b/meta/builders/ContainerClassBuilder.class.php @@ -18,27 +18,30 @@ public static function build(MetaClass $class) { throw new UnsupportedMethodException(); } - + public static function buildContainer( MetaClass $class, MetaClassProperty $holder ) { $out = self::getHead(); - + $containerName = $class->getName().ucfirst($holder->getName()).'DAO'; - + + $isNoSQL = is_subclass_of($holder->getType()->getClassName(), 'NoSqlObject'); + $parentExtend = $isNoSQL ? 'NoSql' : ''; + $out .= 'final class ' .$containerName .' extends ' - .$holder->getRelation()->toString().'Linked' + .$holder->getRelation()->toString().$parentExtend.'Linked' ."\n{\n"; $className = $class->getName(); $propertyName = strtolower($className[0]).substr($className, 1); - + $remoteColumnName = $holder->getType()->getClass()->getTableName(); - + $out .= <<getName()}/_view/getBy{$class->getName()}Id'; +} + +EOT; + } + + + $out .= "}\n"; $out .= self::getHeel(); - + return $out; } } diff --git a/meta/classes/MetaConfiguration.class.php b/meta/classes/MetaConfiguration.class.php index d00289490b..498ae36f4b 100644 --- a/meta/classes/MetaConfiguration.class.php +++ b/meta/classes/MetaConfiguration.class.php @@ -15,20 +15,20 @@ final class MetaConfiguration extends Singleton implements Instantiatable { private $out = null; - + private $classes = array(); private $sources = array(); - + private $liaisons = array(); private $references = array(); - + private $defaultSource = null; - + private $forcedGeneration = false; private $dryRun = false; - + private $checkEnumerationRefIntegrity = false; - + /** * @return MetaConfiguration **/ @@ -36,7 +36,7 @@ public static function me() { return Singleton::getInstance('MetaConfiguration'); } - + /** * @return MetaOutput **/ @@ -44,54 +44,54 @@ public static function out() { return self::me()->getOutput(); } - + /** * @return MetaConfiguration **/ public function setForcedGeneration($orly) { $this->forcedGeneration = $orly; - + return $this; } - + public function isForcedGeneration() { return $this->forcedGeneration; } - + /** * @return MetaConfiguration **/ public function setDryRun($dry) { $this->dryRun = $dry; - + return $this; } - + public function isDryRun() { return $this->dryRun; } - + /** * @return MetaConfiguration **/ public function setWithEnumerationRefIntegrityCheck($orly) { $this->checkEnumerationRefIntegrity = $orly; - + return $this; } - + /** * @return MetaConfiguration **/ public function load($metafile, $generate = true) { $this->loadXml($metafile, $generate); - + // check sources foreach ($this->classes as $name => $class) { $sourceLink = $class->getSourceLink(); @@ -105,17 +105,17 @@ public function load($metafile, $generate = true) $class->setSourceLink($this->defaultSource); } } - + foreach ($this->liaisons as $class => $parent) { if (isset($this->classes[$parent])) { - + Assert::isFalse( $this->classes[$parent]->getTypeId() == MetaClassType::CLASS_FINAL, - + "'{$parent}' is final, thus can not have childs" ); - + if ( $this->classes[$class]->getPattern() instanceof DictionaryClassPattern @@ -124,7 +124,7 @@ public function load($metafile, $generate = true) 'DictionaryClass pattern does ' .'not support inheritance' ); - + $this->classes[$class]->setParent( $this->classes[$parent] ); @@ -133,11 +133,11 @@ public function load($metafile, $generate = true) "unknown parent class '{$parent}'" ); } - + // search for referencing classes foreach ($this->references as $className => $list) { $class = $this->getClassByName($className); - + if ( ( $class->getPattern() instanceof ValueObjectPattern @@ -149,7 +149,7 @@ public function load($metafile, $generate = true) ) { continue; } - + foreach ($list as $refer) { $remote = $this->getClassByName($refer); if ( @@ -172,12 +172,12 @@ public function load($metafile, $generate = true) } } } - + // final sanity checking foreach ($this->classes as $name => $class) { $this->checkSanity($class); } - + // check for recursion in relations and spooked properties foreach ($this->classes as $name => $class) { foreach ($class->getProperties() as $property) { @@ -206,20 +206,20 @@ public function load($metafile, $generate = true) } } } - + return $this; } - + /** * @return MetaConfiguration **/ public function buildClasses() { $out = $this->getOutput(); - + $out-> infoLine('Building classes:'); - + foreach ($this->classes as $name => $class) { if ( !$class->doBuild() @@ -229,14 +229,14 @@ public function buildClasses() } else { $out->infoLine("\t".$name.':'); } - + $class->dump(); $out->newLine(); } - + return $this; } - + /** * @return MetaConfiguration **/ @@ -247,11 +247,11 @@ public function buildSchema() $out-> newLine()-> infoLine('Building DB schema:'); - + $schema = SchemaBuilder::getHead(); - + $tables = array(); - + foreach ($this->classes as $class) { if ( (!$class->getParent() && !count($class->getProperties())) @@ -259,7 +259,7 @@ public function buildSchema() ) { continue; } - + foreach ($class->getAllProperties() as $property) $tables[ $class->getTableName() @@ -268,21 +268,21 @@ public function buildSchema() $property->getColumnName() ] = $property; } - + foreach ($tables as $name => $propertyList) if ($propertyList) $schema .= SchemaBuilder::buildTable($name, $propertyList); - + foreach ($this->classes as $class) { if (!$class->getPattern()->tableExists()) { continue; } - + $schema .= SchemaBuilder::buildRelations($class); } - + $schema .= '?>'; - + BasePattern::dumpFile( ONPHP_META_AUTO_DIR.'schema.php', Format::indentize($schema) @@ -290,7 +290,7 @@ public function buildSchema() return $this; } - + /** * @return MetaConfiguration **/ @@ -300,82 +300,100 @@ public function buildSchemaChanges() $out-> newLine()-> infoLine('Suggested DB-schema changes: '); - + require ONPHP_META_AUTO_DIR.'schema.php'; - + + /** @var $class MetaClass */ foreach ($this->classes as $class) { if ( $class->getTypeId() == MetaClassType::CLASS_ABSTRACT || $class->getPattern() instanceof EnumerationClassPattern ) continue; - + try { $target = $schema->getTableByName($class->getTableName()); } catch (MissingElementException $e) { // dropped or tableless continue; } - - try { - $db = DBPool::me()->getLink($class->getSourceLink()); - } catch (BaseException $e) { - $out-> - errorLine( - 'Can not connect using source link in \'' - .$class->getName().'\' class, skipping this step.' - ); - - break; - } - - try { - $source = $db->getTableInfo($class->getTableName()); - } catch (UnsupportedMethodException $e) { - $out-> - errorLine( - get_class($db) - .' does not support tables introspection yet.', - - true + + if( $class->getPattern() instanceof NosqlClassPattern ) { + // checking NoSQL-DB + try { + $db = NoSQLPool::me()->getLink($class->getSourceLink()); + } catch (BaseException $e) { + $out-> + errorLine( + 'Can not connect using source link in \'' + .$class->getName().'\' class, skipping this step.' + ); + + break; + } + } else { + // checking SQL-DB + try { + $db = DBPool::me()->getLink($class->getSourceLink()); + } catch (BaseException $e) { + $out-> + errorLine( + 'Can not connect using source link in \'' + .$class->getName().'\' class, skipping this step.' + ); + + break; + } + + try { + $source = $db->getTableInfo($class->getTableName()); + } catch (UnsupportedMethodException $e) { + $out-> + errorLine( + get_class($db) + .' does not support tables introspection yet.', + + true + ); + + break; + } catch (ObjectNotFoundException $e) { + $out->errorLine( + "table '{$class->getTableName()}' not found, skipping." ); - - break; - } catch (ObjectNotFoundException $e) { - $out->errorLine( - "table '{$class->getTableName()}' not found, skipping." + continue; + } + + $diff = DBTable::findDifferences( + $db->getDialect(), + $source, + $target ); - continue; - } - - $diff = DBTable::findDifferences( - $db->getDialect(), - $source, - $target - ); - - if ($diff) { - foreach ($diff as $line) - $out->warningLine($line); - - $out->newLine(); + + if ($diff) { + foreach ($diff as $line) + $out->warningLine($line); + + $out->newLine(); + } } + } - + return $this; } - + /** * @return MetaConfiguration **/ public function buildContainers() { $force = $this->isForcedGeneration(); - + $out = $this->getOutput(); $out-> infoLine('Building containers: '); - + foreach ($this->classes as $class) { foreach ($class->getProperties() as $property) { if ( @@ -387,7 +405,7 @@ public function buildContainers() .$class->getName().ucfirst($property->getName()) .'DAO' .EXT_CLASS; - + if ($force || !file_exists($userFile)) { BasePattern::dumpFile( $userFile, @@ -399,7 +417,7 @@ public function buildContainers() ) ); } - + // check for old-style naming $oldStlye = ONPHP_META_DAO_DIR @@ -408,7 +426,7 @@ public function buildContainers() .$property->getType()->getClassName() .'DAO' .EXT_CLASS; - + if (is_readable($oldStlye)) { $out-> newLine()-> @@ -419,10 +437,10 @@ public function buildContainers() } } } - + return $this; } - + /** * @return MetaConfiguration **/ @@ -432,7 +450,7 @@ public function checkIntegrity() newLine()-> infoLine('Checking sanity of generated files: ')-> newLine(); - + set_include_path( get_include_path().PATH_SEPARATOR .ONPHP_META_BUSINESS_DIR.PATH_SEPARATOR @@ -442,11 +460,11 @@ public function checkIntegrity() .ONPHP_META_AUTO_DAO_DIR.PATH_SEPARATOR .ONPHP_META_AUTO_PROTO_DIR.PATH_SEPARATOR ); - + $out->info("\t"); - + $formErrors = array(); - + foreach ($this->classes as $name => $class) { if ( !( @@ -458,83 +476,83 @@ class_exists($class->getName(), true) ) ) { $out->info($name, true); - + $info = new ReflectionClass($name); - + $this-> checkClassSanity($class, $info); - + if ($info->implementsInterface('Prototyped')) $this->checkClassSanity( $class, new ReflectionClass('Proto'.$name) ); - + if ($info->implementsInterface('DAOConnected')) $this->checkClassSanity( $class, new ReflectionClass($name.'DAO') ); - + foreach ($class->getInterfaces() as $interface) Assert::isTrue( $info->implementsInterface($interface), - + 'class '.$class->getName() .' expected to implement interface '.$interface ); - + // special handling for Enumeration instances if ($class->getPattern() instanceof EnumerationClassPattern) { $object = new $name(call_user_func(array($name, 'getAnyId'))); - + Assert::isTrue( unserialize(serialize($object)) == $object ); - + $out->info(', '); - + if ($this->checkEnumerationRefIntegrity) $this->checkEnumerationReferentialIntegrity( $object, $class->getTableName() ); - + continue; } - + if ($class->getPattern() instanceof AbstractClassPattern) { $out->info(', '); continue; } - + $object = new $name; $proto = $object->proto(); $form = $proto->makeForm(); - + foreach ($class->getProperties() as $name => $property) { Assert::isTrue( $property->toLightProperty($class) == $proto->getPropertyByName($name), - + 'defined property does not match autogenerated one - ' .$class->getName().'::'.$property->getName() ); } - + if (!$object instanceof DAOConnected) { $out->info(', '); continue; } - + $dao = $object->dao(); - + Assert::isEqual( $dao->getIdName(), $class->getIdentifier()->getColumnName(), 'identifier name mismatch in '.$class->getName().' class' ); - + try { DBPool::getByDao($dao); } catch (MissingElementException $e) { @@ -542,14 +560,14 @@ class_exists($class->getName(), true) $out->info(', '); continue; } - + $query = Criteria::create($dao)-> setLimit(1)-> add(Expression::notNull($class->getIdentifier()->getName()))-> addOrder($class->getIdentifier()->getName())-> toSelectQuery(); - + $out->warning( ' (' .$query->getFieldsCount() @@ -557,34 +575,34 @@ class_exists($class->getName(), true) .$query->getTablesCount() .'/' ); - + $clone = clone $object; - + if (serialize($clone) == serialize($object)) $out->info('C', true); else { $out->error('C', true); } - + $out->warning('/'); - + try { $object = $dao->getByQuery($query); $form = $object->proto()->makeForm(); FormUtils::object2form($object, $form); - + if ($errors = $form->getErrors()) { $formErrors[$class->getName()] = $errors; - + $out->error('F', true); } else $out->info('F', true); } catch (ObjectNotFoundException $e) { $out->warning('F'); } - + $out->warning('/'); - + if ( Criteria::create($dao)-> setFetchStrategy(FetchStrategy::cascade())-> @@ -595,33 +613,33 @@ class_exists($class->getName(), true) } else { $out->error('H', true); } - + $out->warning('/'); - + // cloning once again $clone = clone $object; - + FormUtils::object2form($object, $form); FormUtils::form2object($form, $object); - + if ($object != $clone) { $out->error('T', true); } else { $out->info('T', true); } - + $out->warning(')')->info(', '); } } - + $out->infoLine('done.'); - + if ($formErrors) { $out->newLine()->errorLine('Errors found:')->newLine(); - + foreach ($formErrors as $class => $errors) { $out->errorLine("\t".$class.':', true); - + foreach ($errors as $name => $error) { $out->errorLine( "\t\t".$name.' - ' @@ -632,14 +650,14 @@ class_exists($class->getName(), true) ) ); } - + $out->newLine(); } } - + return $this; } - + /** * @return MetaConfiguration **/ @@ -648,13 +666,13 @@ public function checkForStaleFiles($drop = false) $this->getOutput()-> newLine()-> infoLine('Checking for stale files: '); - + return $this-> checkDirectory(ONPHP_META_AUTO_BUSINESS_DIR, 'Auto', null, $drop)-> checkDirectory(ONPHP_META_AUTO_DAO_DIR, 'Auto', 'DAO', $drop)-> checkDirectory(ONPHP_META_AUTO_PROTO_DIR, 'AutoProto', null, $drop); } - + /** * @throws MissingElementException * @return MetaClass @@ -663,27 +681,27 @@ public function getClassByName($name) { if (isset($this->classes[$name])) return $this->classes[$name]; - + throw new MissingElementException( "knows nothing about '{$name}' class" ); } - + public function getClassList() { return $this->classes; } - + /** * @return MetaConfiguration **/ public function setOutput(MetaOutput $out) { $this->out = $out; - + return $this; } - + /** * @return MetaOutput **/ @@ -691,7 +709,7 @@ public function getOutput() { return $this->out; } - + /** * @return MetaConfiguration **/ @@ -700,7 +718,7 @@ private function checkDirectory( ) { $out = $this->getOutput(); - + foreach ( glob($directory.'*.class.php', GLOB_NOSORT) as $filename @@ -710,7 +728,7 @@ private function checkDirectory( basename($filename, $postStrip.EXT_CLASS), strlen($preStrip) ); - + if (!isset($this->classes[$name])) { $out->warning( "\t" @@ -720,7 +738,7 @@ private function checkDirectory( $filename ) ); - + if ($drop) { try { unlink($filename); @@ -733,40 +751,40 @@ private function checkDirectory( } } } - + return $this; } - + /** * @return MetaConfiguration **/ private function addSource(SimpleXMLElement $source) { $name = (string) $source['name']; - + $default = isset($source['default']) && (string) $source['default'] == 'true' ? true : false; - + Assert::isFalse( isset($this->sources[$name]), "duplicate source - '{$name}'" ); - + Assert::isFalse( $default && $this->defaultSource !== null, 'too many default sources' ); - + $this->sources[$name] = $default; - + if ($default) $this->defaultSource = $name; - + return $this; } - + /** * @return MetaClassProperty **/ @@ -776,19 +794,19 @@ private function makeProperty($name, $type, MetaClass $class, $size) strpos($name, '_'), 'naming convention violation spotted' ); - + if (!$name || !$type) throw new WrongArgumentException( 'strange name or type given: "'.$name.'" - "'.$type.'"' ); - + if (is_readable(ONPHP_META_TYPES.$type.'Type'.EXT_CLASS)) $typeClass = $type.'Type'; else $typeClass = 'ObjectType'; - + $property = new MetaClassProperty($name, new $typeClass($type), $class); - + if ($size) $property->setSize($size); else { @@ -803,14 +821,14 @@ private function makeProperty($name, $type, MetaClass $class, $size) !$property->getType() instanceof HttpUrlType ), - + 'size is required for "'.$property->getName().'"' ); } - + return $property; } - + /** * @throws MissingElementException * @return GenerationPattern @@ -818,15 +836,15 @@ private function makeProperty($name, $type, MetaClass $class, $size) private function guessPattern($name) { $class = $name.'Pattern'; - + if (is_readable(ONPHP_META_PATTERNS.$class.EXT_CLASS)) return Singleton::getInstance($class); - + throw new MissingElementException( "unknown pattern '{$name}'" ); } - + /** * @return MetaConfiguration **/ @@ -850,7 +868,7 @@ private function checkSanity(MetaClass $class) .$class->getName().')' ); } - + if ( $class->getType() && $class->getTypeId() @@ -861,7 +879,7 @@ private function checkSanity(MetaClass $class) 'spooked classes must have only identifier: ' .$class->getName() ); - + Assert::isTrue( ($class->getPattern() instanceof SpookedClassPattern || $class->getPattern() instanceof SpookedEnumerationPattern), @@ -869,7 +887,7 @@ private function checkSanity(MetaClass $class) .$class->getName() ); } - + foreach ($class->getProperties() as $property) { if ( !$property->getType()->isGeneric() @@ -883,7 +901,7 @@ private function checkSanity(MetaClass $class) 'optional value object is not supported:' .$property->getName().' @ '.$class->getName() ); - + Assert::isTrue( $property->getRelationId() == MetaRelation::ONE_TO_ONE, 'value objects must have OneToOne relation: ' @@ -903,10 +921,10 @@ private function checkSanity(MetaClass $class) ); } } - + return $this; } - + private function checkRecursion( MetaClassProperty $property, MetaClass $holder, @@ -916,7 +934,7 @@ private function checkRecursion( $property->getRelationId() == MetaRelation::ONE_TO_ONE ); - + if ( $property->getFetchStrategy() && $property->getFetchStrategy()->getId() != FetchStrategy::JOIN @@ -925,12 +943,12 @@ private function checkRecursion( } $remote = $property->getType()->getClass(); - + if (isset($paths[$holder->getName()][$remote->getName()])) return true; else { $paths[$holder->getName()][$remote->getName()] = true; - + foreach ($remote->getProperties() as $remoteProperty) { if ( $remoteProperty->getRelationId() @@ -950,10 +968,10 @@ private function checkRecursion( } } } - + return false; } - + /** * @return MetaConfiguration **/ @@ -962,22 +980,22 @@ private function processIncludes(SimpleXMLElement $xml, $metafile) foreach ($xml->include as $include) { $file = (string) $include['file']; $path = dirname($metafile).'/'.$file; - + Assert::isTrue( is_readable($path), 'can not include '.$file ); - + $this->getOutput()-> infoLine('Including "'.$path.'".')-> newLine(); - + $this->loadXml($path, !((string) $include['generate'] == 'false')); } - + return $this; } - + /** * @return MetaConfiguration **/ @@ -985,59 +1003,59 @@ private function processClasses(SimpleXMLElement $xml, $metafile, $generate) { foreach ($xml->classes[0] as $xmlClass) { $name = (string) $xmlClass['name']; - + Assert::isFalse( isset($this->classes[$name]), 'class name collision found for '.$name ); - + $class = new MetaClass($name); - + if (isset($xmlClass['source'])) $class->setSourceLink((string) $xmlClass['source']); - + if (isset($xmlClass['table'])) $class->setTableName((string) $xmlClass['table']); - + if (isset($xmlClass['type'])) { $type = (string) $xmlClass['type']; - + if ($type == 'spooked') { $this->getOutput()-> warning($class->getName(), true)-> warningLine(': uses obsoleted "spooked" type.')-> newLine(); } - + $class->setType( new MetaClassType( (string) $xmlClass['type'] ) ); } - + // lazy existence checking if (isset($xmlClass['extends'])) $this->liaisons[$class->getName()] = (string) $xmlClass['extends']; - + // populate implemented interfaces foreach ($xmlClass->implement as $xmlImplement) $class->addInterface((string) $xmlImplement['interface']); - + if (isset($xmlClass->properties[0]->identifier)) { - + $id = $xmlClass->properties[0]->identifier; - + if (!isset($id['name'])) $name = 'id'; else $name = (string) $id['name']; - + if (!isset($id['type'])) $type = 'BigInteger'; else $type = (string) $id['type']; - + $property = $this->makeProperty( $name, $type, @@ -1045,7 +1063,7 @@ private function processClasses(SimpleXMLElement $xml, $metafile, $generate) // not casting to int because of Numeric possible size (string) $id['size'] ); - + if (isset($id['column'])) { $property->setColumnName( (string) $id['column'] @@ -1058,23 +1076,23 @@ private function processClasses(SimpleXMLElement $xml, $metafile, $generate) } else { $property->setColumnName($property->getConvertedName()); } - + $property-> setIdentifier(true)-> required(); - + $class->addProperty($property); - + unset($xmlClass->properties[0]->identifier); } - + $class->setPattern( $this->guessPattern((string) $xmlClass->pattern['name']) ); - + if ((string) $xmlClass->pattern['fetch'] == 'cascade') $class->setFetchStrategy(FetchStrategy::cascade()); - + if ($class->getPattern() instanceof InternalClassPattern) { Assert::isTrue( $metafile === ONPHP_META_PATH.'internal.xml', @@ -1093,17 +1111,17 @@ private function processClasses(SimpleXMLElement $xml, $metafile, $generate) ) ); } - + // populate properties foreach ($xmlClass->properties[0] as $xmlProperty) { - + $property = $this->makeProperty( (string) $xmlProperty['name'], (string) $xmlProperty['type'], $class, (string) $xmlProperty['size'] ); - + if (isset($xmlProperty['column'])) { $property->setColumnName( (string) $xmlProperty['column'] @@ -1126,15 +1144,15 @@ private function processClasses(SimpleXMLElement $xml, $metafile, $generate) 'you can not use internal classes directly atm' ); } - + $property->setColumnName($property->getConvertedName().'_id'); } else { $property->setColumnName($property->getConvertedName()); } - + if ((string) $xmlProperty['required'] == 'true') $property->required(); - + if (isset($xmlProperty['identifier'])) { throw new WrongArgumentException( 'obsoleted identifier description found in ' @@ -1142,9 +1160,9 @@ private function processClasses(SimpleXMLElement $xml, $metafile, $generate) .'you must use instead.' ); } - + if (!$property->getType()->isGeneric()) { - + if (!isset($xmlProperty['relation'])) throw new MissingElementException( 'relation should be set for non-generic ' @@ -1158,16 +1176,16 @@ private function processClasses(SimpleXMLElement $xml, $metafile, $generate) (string) $xmlProperty['relation'] ) ); - + if ($fetch = (string) $xmlProperty['fetch']) { Assert::isTrue( $property->getRelationId() == MetaRelation::ONE_TO_ONE, - + 'fetch mode can be specified only for OneToOne relations' ); - + if ($fetch == 'lazy') $property->setFetchStrategy( FetchStrategy::lazy() @@ -1181,7 +1199,7 @@ private function processClasses(SimpleXMLElement $xml, $metafile, $generate) 'strange fetch mode found - '.$fetch ); } - + if ( ( ( @@ -1201,38 +1219,38 @@ private function processClasses(SimpleXMLElement $xml, $metafile, $generate) } } } - + if (isset($xmlProperty['default'])) { // will be correctly autocasted further down the code $property->getType()->setDefault( (string) $xmlProperty['default'] ); } - + $class->addProperty($property); } - + $class->setBuild($generate); - + $this->classes[$class->getName()] = $class; } - + return $this; } - + private function loadXml($metafile, $generate) { $contents = file_get_contents($metafile); - + $contents = str_replace( '"meta.dtd"', '"'.ONPHP_META_PATH.'dtd/meta.dtd"', $contents ); - + $doc = new DOMDocument('1.0'); $doc->loadXML($contents); - + try { $doc->validate(); } catch (BaseException $e) { @@ -1242,28 +1260,28 @@ private function loadXml($metafile, $generate) .$error->line.' in file '.$metafile ); } - + $xml = simplexml_import_dom($doc); - + // populate sources (if any) if (isset($xml->sources[0])) { foreach ($xml->sources[0] as $source) { $this->addSource($source); } } - + if (isset($xml->include['file'])) { $this->processIncludes($xml, $metafile); } - + // otherwise it's an includes-only config if (isset($xml->classes[0])) { return $this->processClasses($xml, $metafile, $generate); } - + return $this; } - + /** * @return MetaConfiguration **/ @@ -1275,7 +1293,7 @@ private function checkClassSanity( switch ($class->getTypeId()) { case null: break; - + case MetaClassType::CLASS_ABSTRACT: Assert::isTrue( $info->isAbstract(), @@ -1286,20 +1304,20 @@ private function checkClassSanity( 'class '.$info->getName().' must use AbstractClassPattern' ); break; - + case MetaClassType::CLASS_FINAL: Assert::isTrue( $info->isFinal(), 'class '.$info->getName().' expected to be final' ); break; - + case MetaClassType::CLASS_SPOOKED: default: Assert::isUnreachable(); break; } - + if ($public = $info->getProperties(ReflectionProperty::IS_PUBLIC)) { Assert::isUnreachable( $class->getName() @@ -1308,58 +1326,58 @@ private function checkClassSanity( .print_r($public, true) ); } - + return $this; } - + private function checkEnumerationReferentialIntegrity( Enumeration $enumeration, $tableName ) { $updateQueries = null; - + $db = DBPool::me()->getLink(); - + $class = get_class($enumeration); - + $ids = array(); - + $list = $enumeration->getObjectList(); - + foreach ($list as $enumerationObject) $ids[$enumerationObject->getId()] = $enumerationObject->getName(); - + $rows = $db->querySet( OSQL::select()->from($tableName)-> multiGet('id', 'name') ); - + echo "\n"; - + foreach ($rows as $row) { if (!isset($ids[$row['id']])) echo "Class '{$class}', strange id: {$row['id']} found. \n"; else { if ($ids[$row['id']] != $row['name']) { echo "Class '{$class}',id: {$row['id']} sync names. \n"; - + $updateQueries .= OSQL::update($tableName)-> set('name', $ids[$row['id']])-> where(Expression::eq('id', $row['id']))-> toDialectString($db->getDialect()) . ";\n"; } - + unset($ids[$row['id']]); } } - + foreach ($ids as $id => $name) echo "Class '{$class}', id: {$id} not present in database. \n"; - + echo $updateQueries; - + return $this; } } diff --git a/meta/dtd/meta.dtd b/meta/dtd/meta.dtd index 35a0b81a57..79666a3691 100644 --- a/meta/dtd/meta.dtd +++ b/meta/dtd/meta.dtd @@ -51,6 +51,7 @@ |SpookedEnumeration |ValueObject |InternalClass + |NosqlClass ) #REQUIRED fetch (lazy|cascade) #IMPLIED > diff --git a/meta/patterns/BasePattern.class.php b/meta/patterns/BasePattern.class.php index 18db66b740..c929363a6a 100644 --- a/meta/patterns/BasePattern.class.php +++ b/meta/patterns/BasePattern.class.php @@ -18,43 +18,43 @@ public function tableExists() { return true; } - + public function daoExists() { return false; } - + public static function dumpFile($path, $content) { $content = trim($content); - + if (is_readable($path)) { $pattern = array( '@\/\*(.*)\*\/@sU', '@[\r\n]@sU' ); - + // strip only header and svn's Id-keyword, don't skip type hints $old = preg_replace($pattern, null, file_get_contents($path), 2); $new = preg_replace($pattern, null, $content, 2); } else { $old = 1; $new = 2; } - + $out = MetaConfiguration::out(); $className = basename($path, EXT_CLASS); - + if ($old !== $new) { $out-> warning("\t\t".$className.' '); - + if (!MetaConfiguration::me()->isDryRun()) { $fp = fopen($path, 'wb'); fwrite($fp, $content); fclose($fp); } - + $out-> log('(')-> remark( @@ -66,12 +66,12 @@ public static function dumpFile($path, $content) infoLine("\t\t".$className.' ', true); } } - + public function build(MetaClass $class) { return $this->fullBuild($class); } - + /** * @return BasePattern **/ @@ -82,7 +82,7 @@ protected function fullBuild(MetaClass $class) buildBusiness($class)-> buildDao($class); } - + /** * @return BasePattern **/ @@ -92,9 +92,9 @@ protected function buildProto(MetaClass $class) ONPHP_META_AUTO_PROTO_DIR.'AutoProto'.$class->getName().EXT_CLASS, Format::indentize(AutoProtoClassBuilder::build($class)) ); - + $userFile = ONPHP_META_PROTO_DIR.'Proto'.$class->getName().EXT_CLASS; - + if ( MetaConfiguration::me()->isForcedGeneration() || !file_exists($userFile) @@ -103,10 +103,10 @@ protected function buildProto(MetaClass $class) $userFile, Format::indentize(ProtoClassBuilder::build($class)) ); - + return $this; } - + /** * @return BasePattern **/ @@ -116,9 +116,9 @@ protected function buildBusiness(MetaClass $class) ONPHP_META_AUTO_BUSINESS_DIR.'Auto'.$class->getName().EXT_CLASS, Format::indentize(AutoClassBuilder::build($class)) ); - + $userFile = ONPHP_META_BUSINESS_DIR.$class->getName().EXT_CLASS; - + if ( MetaConfiguration::me()->isForcedGeneration() || !file_exists($userFile) @@ -127,10 +127,10 @@ protected function buildBusiness(MetaClass $class) $userFile, Format::indentize(BusinessClassBuilder::build($class)) ); - + return $this; } - + /** * @return BasePattern **/ @@ -140,9 +140,33 @@ protected function buildDao(MetaClass $class) ONPHP_META_AUTO_DAO_DIR.'Auto'.$class->getName().'DAO'.EXT_CLASS, Format::indentize(AutoDaoBuilder::build($class)) ); - + + $userFile = ONPHP_META_DAO_DIR.$class->getName().'DAO'.EXT_CLASS; + + if ( + MetaConfiguration::me()->isForcedGeneration() + || !file_exists($userFile) + ) + $this->dumpFile( + $userFile, + Format::indentize(DaoBuilder::build($class)) + ); + + return $this; + } + + /** + * @return BasePattern + **/ + protected function buildNoSqlDao(MetaClass $class) + { + $this->dumpFile( + ONPHP_META_AUTO_DAO_DIR.'Auto'.$class->getName().'DAO'.EXT_CLASS, + Format::indentize(AutoNoSqlDaoBuilder::build($class)) + ); + $userFile = ONPHP_META_DAO_DIR.$class->getName().'DAO'.EXT_CLASS; - + if ( MetaConfiguration::me()->isForcedGeneration() || !file_exists($userFile) @@ -151,7 +175,7 @@ protected function buildDao(MetaClass $class) $userFile, Format::indentize(DaoBuilder::build($class)) ); - + return $this; } } diff --git a/meta/patterns/NosqlClassPattern.class.php b/meta/patterns/NosqlClassPattern.class.php new file mode 100644 index 0000000000..5ee0add3ff --- /dev/null +++ b/meta/patterns/NosqlClassPattern.class.php @@ -0,0 +1,40 @@ + + buildProto($class)-> + buildBusiness($class)-> + buildNoSqlDao($class); + } + +} diff --git a/meta/types/UuidType.class.php b/meta/types/UuidType.class.php index 205512fa7c..d087cadb9a 100644 --- a/meta/types/UuidType.class.php +++ b/meta/types/UuidType.class.php @@ -1,7 +1,7 @@ Date: Mon, 23 Jan 2012 18:14:28 +0400 Subject: [PATCH 006/418] NoSQL full support --- core/NoSQL/NoSQLPool.class.php | 14 +++++++------- core/NoSQL/NoSqlDAO.class.php | 10 +++++----- meta/builders/AutoClassBuilder.class.php | 2 +- meta/patterns/NosqlClassPattern.class.php | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/core/NoSQL/NoSQLPool.class.php b/core/NoSQL/NoSQLPool.class.php index 700557e8ed..fdd5a05085 100644 --- a/core/NoSQL/NoSQLPool.class.php +++ b/core/NoSQL/NoSQLPool.class.php @@ -15,14 +15,14 @@ * * @ingroup NoSQL **/ -final class NoSQLPool extends Singleton implements Instantiatable +final class NoSqlPool extends Singleton implements Instantiatable { private $default = null; private $pool = array(); /** - * @return NoSQLPool + * @return NoSqlPool **/ public static function me() { @@ -41,7 +41,7 @@ public static function getByDao(GenericDAO $dao) /** * @param NoSQL $db - * @return NoSQLPool + * @return NoSqlPool */ public function setDefault(NoSQL $db) { @@ -51,7 +51,7 @@ public function setDefault(NoSQL $db) } /** - * @return NoSQLPool + * @return NoSqlPool **/ public function dropDefault() { @@ -63,7 +63,7 @@ public function dropDefault() /** * @param string $name * @param NoSQL $db - * @return NoSQLPool + * @return NoSqlPool * @throws WrongArgumentException */ public function addLink($name, NoSQL $db) @@ -80,7 +80,7 @@ public function addLink($name, NoSQL $db) /** * @param string $name - * @return NoSQLPool + * @return NoSqlPool * @throws MissingElementException */ public function dropLink($name) @@ -127,7 +127,7 @@ public function getLink($name = null) } /** - * @return NoSQLPool + * @return NoSqlPool */ public function shutdown() { diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index bf7face592..64edb89411 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -130,7 +130,7 @@ public function makeTotalCountQuery() { public function drop(Identifiable $object) { $this->assertNoSqlObject( $object ); - $link = NoSQLPool::getByDao( $this ); + $link = NoSqlPool::getByDao( $this ); // delete return $link @@ -174,7 +174,7 @@ public function add(Identifiable $object) { $this->assertNoSqlObject( $object ); // make sequence - $link = NoSQLPool::getByDao( $this ); + $link = NoSqlPool::getByDao( $this ); $object->setId( $link->obtainSequence( $this->getSequence() @@ -200,7 +200,7 @@ public function add(Identifiable $object) { public function save(Identifiable $object) { $this->assertNoSqlObject( $object ); - $link = NoSQLPool::getByDao( $this ); + $link = NoSqlPool::getByDao( $this ); // insert $entity = $link @@ -221,7 +221,7 @@ public function save(Identifiable $object) { public function import(Identifiable $object) { $this->assertNoSqlObject( $object ); - $link = NoSQLPool::getByDao( $this ); + $link = NoSqlPool::getByDao( $this ); // insert $entity = $link @@ -377,7 +377,7 @@ public function makeNoSqlObject($array, $prefix = null) { * @return NoSQL */ public function getLink() { - return NoSQLPool::me()->getLink( $this->getLinkName() );; + return NoSqlPool::me()->getLink( $this->getLinkName() );; } } diff --git a/meta/builders/AutoClassBuilder.class.php b/meta/builders/AutoClassBuilder.class.php index ecfaae92b8..413fcdcbfc 100644 --- a/meta/builders/AutoClassBuilder.class.php +++ b/meta/builders/AutoClassBuilder.class.php @@ -31,7 +31,7 @@ public static function build(MetaClass $class) $out .= " extends NamedObject"; $isNamed = true; } elseif ( - $class->getPattern() instanceof NosqlClassPattern + $class->getPattern() instanceof NoSqlClassPattern && $class->hasProperty('id') ) { $out .= " extends NoSqlObject"; diff --git a/meta/patterns/NosqlClassPattern.class.php b/meta/patterns/NosqlClassPattern.class.php index 5ee0add3ff..92fe43b6b5 100644 --- a/meta/patterns/NosqlClassPattern.class.php +++ b/meta/patterns/NosqlClassPattern.class.php @@ -13,7 +13,7 @@ /** * @ingroup Patterns **/ -class NosqlClassPattern extends BasePattern { +class NoSqlClassPattern extends BasePattern { public function tableExists() { @@ -27,7 +27,7 @@ public function daoExists() /** * @param MetaClass $class - * @return NosqlClassPattern + * @return NoSqlClassPattern */ protected function fullBuild(MetaClass $class) { From b387bf7c3ec15e0966ae4c458a721656b1e42211 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Mon, 23 Jan 2012 18:14:41 +0400 Subject: [PATCH 007/418] UUID full support --- core/Base/UuidIdentifiable.class.php | 22 +++ .../PrimitiveUuidIdentifierList.class.php | 2 - main/Base/LightMetaProperty.class.php | 149 ++++++++-------- meta/classes/MetaClassProperty.class.php | 160 +++++++++--------- meta/classes/MetaConfiguration.class.php | 139 ++++++++------- 5 files changed, 257 insertions(+), 215 deletions(-) create mode 100644 core/Base/UuidIdentifiable.class.php diff --git a/core/Base/UuidIdentifiable.class.php b/core/Base/UuidIdentifiable.class.php new file mode 100644 index 0000000000..0a21a04a0c --- /dev/null +++ b/core/Base/UuidIdentifiable.class.php @@ -0,0 +1,22 @@ +applyImportFilters($scope[$this->name]); - if (!is_array($scope[$this->name])) return false; diff --git a/main/Base/LightMetaProperty.class.php b/main/Base/LightMetaProperty.class.php index e3a9225c54..50e92ce457 100644 --- a/main/Base/LightMetaProperty.class.php +++ b/main/Base/LightMetaProperty.class.php @@ -18,7 +18,7 @@ class LightMetaProperty implements Stringable { const UNSIGNED_FLAG = 0x1000; - + private static $limits = array( 0x0002 => array( PrimitiveInteger::SIGNED_SMALL_MIN, @@ -45,34 +45,34 @@ class LightMetaProperty implements Stringable null ) ); - + private $name = null; private $columnName = null; - + private $type = null; private $className = null; - + private $size = null; - + private $min = null; private $max = null; - + private $required = false; private $generic = false; private $inner = false; - + /// @see MetaRelation private $relationId = null; - + /// @see FetchStrategy private $strategyId = null; - + private $getter = null; private $setter = null; private $dropper = null; - + private $identifier = null; - + /** * @return LightMetaProperty **/ @@ -80,7 +80,7 @@ public static function create() { return new self; } - + /** * must by in sync with InnerMetaProperty::make() * @@ -93,20 +93,20 @@ public static function fill( ) { $property->name = $name; - + $methodSuffix = ucfirst($name); $property->getter = 'get'.$methodSuffix; $property->setter = 'set'.$methodSuffix; $property->dropper = 'drop'.$methodSuffix; - + if ($columnName) $property->columnName = $columnName; else $property->columnName = $name; - + $property->type = $type; $property->className = $className; - + if ($size) { if ( ($type == 'integer') @@ -121,147 +121,148 @@ public static function fill( } elseif ($type != 'float') { // string $property->max = $size; } - + $property->size = $size; } - + $property->required = $required; $property->generic = $generic; $property->inner = $inner; - + $property->relationId = $relationId; $property->strategyId = $strategyId; - + $property->identifier = $generic && $required && ( ($type == 'identifier') // obsoleted || ($type == 'integerIdentifier') || ($type == 'scalarIdentifier') + || ($type == 'uuidIdentifier') ); - + return $property; } - + public function getName() { return $this->name; } - + public function getColumnName() { return $this->columnName; } - + public function getGetter() { return $this->getter; } - + public function getSetter() { return $this->setter; } - + public function getDropper() { return $this->dropper; } - + /** * @return LightMetaProperty **/ public function setColumnName($name) { $this->columnName = $name; - + return $this; } - + public function getClassName() { return $this->className; } - + public function getMin() { return $this->min; } - + public function getMax() { return $this->max; } - + public function getType() { return $this->type; } - + public function isRequired() { return $this->required; } - + /** * @return LightMetaProperty **/ public function setRequired($yrly) { $this->required = $yrly; - + return $this; } - + public function isGenericType() { return $this->generic; } - + public function isInner() { return $this->inner; } - + public function getRelationId() { return $this->relationId; } - + public function getFetchStrategyId() { return $this->strategyId; } - + /** * @return LightMetaProperty **/ public function setFetchStrategy(FetchStrategy $strategy) { $this->strategyId = $strategy->getId(); - + return $this; } - + /** * @return LightMetaProperty **/ public function dropFetchStrategy() { $this->strategyId = null; - + return $this; } - + public function getContainerName($holderName) { return $holderName.ucfirst($this->getName()).'DAO'; } - + public function isBuildable($array, $prefix = null) { $column = $prefix.$this->columnName; $exists = isset($array[$column]); - + if ( $this->relationId || $this->generic @@ -272,7 +273,7 @@ public function isBuildable($array, $prefix = null) && !$this->generic ) return false; - + if ($this->required) { Assert::isTrue( $exists, @@ -282,10 +283,10 @@ public function isBuildable($array, $prefix = null) return false; } } - + return true; } - + /** * @return BasePrimitive **/ @@ -296,22 +297,22 @@ public function makePrimitive($name) array('Primitive', $this->type), $name ); - + if (null !== ($min = $this->getMin())) $prm->setMin($min); - + if (null !== ($max = $this->getMax())) $prm->setMax($max); - + if ($prm instanceof IdentifiablePrimitive) $prm->of($this->className); - + if ($this->required) $prm->required(); - + return $prm; } - + public function fillMapping(array $mapping) { if ( @@ -326,10 +327,10 @@ public function fillMapping(array $mapping) ) { $mapping[$this->name] = $this->columnName; } - + return $mapping; } - + /** * @return Form **/ @@ -339,7 +340,7 @@ public function fillForm(Form $form, $prefix = null) $this->makePrimitive($prefix.$this->name) ); } - + /** * @return InsertOrUpdateQuery **/ @@ -369,29 +370,29 @@ public function fillQuery( } $value = $object->{$getter}(); - + if ($this->type == 'binary') { $query->set($this->columnName, new DBBinary($value)); } else { $query->lazySet($this->columnName, $value); } } - + return $query; } - + public function toValue(ProtoDAO $dao = null, $array, $prefix = null) { $raw = $array[$prefix.$this->columnName]; - + if ($this->type == 'binary') { return DBPool::getByDao($dao)->getDialect()->unquoteBinary($raw); } - + if ($this->className == 'HttpUrl') { return HttpUrl::create()->parse($raw); } - + if ( !$this->identifier && $this->generic @@ -404,20 +405,20 @@ public function toValue(ProtoDAO $dao = null, $array, $prefix = null) ) { // BOVM: prevents segfault on >=php-5.2.5 Assert::classExists($this->className); - + if (!is_subclass_of($this->className, 'Enumeration')) { $remoteDao = call_user_func(array($this->className, 'dao')); - + $joinPrefix = $remoteDao->getJoinPrefix( $this->columnName, $prefix ); - + $joined = ( ($this->strategyId == FetchStrategy::JOIN) || isset($array[$joinPrefix.$remoteDao->getIdName()]) ); - + if ($joined) { return $remoteDao->makeObject($array, $joinPrefix); } else { @@ -425,28 +426,28 @@ public function toValue(ProtoDAO $dao = null, $array, $prefix = null) // by AbstractProtoClass::fetchEncapsulants $object = new $this->className; $object->setId($raw); - + return $object; } } else { return new $this->className($raw); } } - + // veeeeery "special" handling, by tradition. // MySQL returns 0/1, others - t/f if ($this->type == 'boolean') { return (bool) strtr($raw, array('f' => null)); } - + return $raw; } - + public function isIdentifier() { return $this->identifier; } - + final public function toString() { return @@ -503,7 +504,7 @@ final public function toString() ) .')'; } - + public function isFormless() { // NOTE: enum here formless types diff --git a/meta/classes/MetaClassProperty.class.php b/meta/classes/MetaClassProperty.class.php index dbac6fe23b..e908083568 100644 --- a/meta/classes/MetaClassProperty.class.php +++ b/meta/classes/MetaClassProperty.class.php @@ -15,20 +15,20 @@ class MetaClassProperty { private $class = null; - + private $name = null; private $columnName = null; - + private $type = null; private $size = null; - + private $required = false; private $identifier = false; - + private $relation = null; - + private $strategy = null; - + public function __construct( $name, BasePropertyType $type, @@ -36,12 +36,12 @@ public function __construct( ) { $this->name = $name; - + $this->type = $type; - + $this->class = $class; } - + public function equals(MetaClassProperty $property) { return ( @@ -54,7 +54,7 @@ public function equals(MetaClassProperty $property) && ($property->isIdentifier() == $this->isIdentifier()) ); } - + /** * @return MetaClass **/ @@ -62,37 +62,37 @@ public function getClass() { return $this->class; } - + public function getName() { return $this->name; } - + /** * @return MetaClassProperty **/ public function setName($name) { $this->name = $name; - + return $this; } - + public function getColumnName() { return $this->columnName; } - + /** * @return MetaClassProperty **/ public function setColumnName($name) { $this->columnName = $name; - + return $this; } - + /** * @return MetaClassProperty **/ @@ -102,7 +102,7 @@ public function getConvertedName() preg_replace(':([A-Z]):', '_\1', $this->name) ); } - + /** * @return BasePropertyType **/ @@ -110,12 +110,12 @@ public function getType() { return $this->type; } - + public function getSize() { return $this->size; } - + /** * @throws WrongArgumentException * @return MetaClassProperty @@ -125,16 +125,16 @@ public function setSize($size) if ($this->type instanceof NumericType) { if (strpos($size, ',') !== false) { list($size, $precision) = explode(',', $size, 2); - + $this->type->setPrecision($precision); } } - + Assert::isInteger( $size, 'only integers allowed in size parameter' ); - + if ($this->type->isMeasurable()) { $this->size = $size; } else @@ -143,55 +143,55 @@ public function setSize($size) .$this->getName().'::'.get_class($this->type) ."' type" ); - + return $this; } - + public function isRequired() { return $this->required; } - + public function isOptional() { return !$this->required; } - + /** * @return MetaClassProperty **/ public function required() { $this->required = true; - + return $this; } - + /** * @return MetaClassProperty **/ public function optional() { $this->required = false; - + return $this; } - + public function isIdentifier() { return $this->identifier; } - + /** * @return MetaClassProperty **/ public function setIdentifier($really = false) { $this->identifier = ($really === true); - + return $this; } - + /** * @return MetaRelation **/ @@ -199,35 +199,35 @@ public function getRelation() { return $this->relation; } - + public function getRelationId() { if ($this->relation) return $this->relation->getId(); - + return null; } - + /** * @return MetaClassProperty **/ public function setRelation(MetaRelation $relation) { $this->relation = $relation; - + return $this; } - + /** * @return MetaClassProperty **/ public function setFetchStrategy(FetchStrategy $strategy) { $this->strategy = $strategy; - + return $this; } - + /** * @return FetchStrategy **/ @@ -235,7 +235,7 @@ public function getFetchStrategy() { return $this->strategy; } - + public function getFetchStrategyId() { if ($this->strategy) @@ -247,10 +247,10 @@ public function getFetchStrategyId() && (!$this->getType()->isGeneric()) ) return $this->getClass()->getFetchStrategyId(); - + return null; } - + public function toMethods( MetaClass $class, MetaClassProperty $holder = null @@ -258,7 +258,7 @@ public function toMethods( { return $this->type->toMethods($class, $this, $holder); } - + public function getRelationColumnName() { if ($this->type instanceof ObjectType && !$this->type->isGeneric()) { @@ -274,10 +274,10 @@ public function getRelationColumnName() return $out; } else $columnName = $this->getColumnName(); - + return $columnName; } - + public function toColumn() { if ( @@ -294,40 +294,46 @@ public function toColumn() ) ) { $columns = array(); - + $prefix = $this->getType() instanceof InternalType ? $this->getColumnName().'_' : null; - + $remote = $this->getType()->getClass(); - + foreach ($remote->getAllProperties() as $property) { $columns[] = $property->buildColumn( $prefix.$property->getRelationColumnName() ); } - + return $columns; } - + return $this->buildColumn($this->getRelationColumnName()); } - + public function toLightProperty(MetaClass $holder) { $className = null; - + if ( ($this->getRelationId() == MetaRelation::ONE_TO_MANY) || ($this->getRelationId() == MetaRelation::MANY_TO_MANY) ) { // collections $primitiveName = 'identifierList'; + if( is_subclass_of($this->getType()->getClassName(), 'UuidIdentifiable') ) { + $primitiveName = 'uuidIdentifierList'; + } } elseif ($this->isIdentifier()) { if ($this->getType() instanceof IntegerType) { $primitiveName = 'integerIdentifier'; $className = $holder->getName(); + } elseif ($this->getType() instanceof UuidType) { + $primitiveName = 'uuidIdentifier'; + $className = $holder->getName(); } elseif ($this->getType() instanceof StringType) { $primitiveName = 'scalarIdentifier'; $className = $holder->getName(); @@ -348,27 +354,29 @@ public function toLightProperty(MetaClass $holder) ) { if ($identifier->getType() instanceof IntegerType) { $primitiveName = 'integerIdentifier'; + } elseif ($identifier->getType() instanceof UuidType) { + $primitiveName = 'uuidIdentifier'; } elseif ($identifier->getType() instanceof StringType) { $primitiveName = 'scalarIdentifier'; } else $primitiveName = $this->getType()->getPrimitiveName(); - } else + } else $primitiveName = $this->getType()->getPrimitiveName(); } else $primitiveName = $this->getType()->getPrimitiveName(); - + $inner = false; - + if ($this->getType() instanceof ObjectType) { $className = $this->getType()->getClassName(); - + if (!$this->getType()->isGeneric()) { $class = $this->getType()->getClass(); $pattern = $class->getPattern(); - + if ($pattern instanceof InternalClassPattern) $className = $holder->getName(); - + if ( ( ($pattern instanceof InternalClassPattern) @@ -381,13 +389,13 @@ public function toLightProperty(MetaClass $holder) } } } - + $propertyClassName = ( $inner ? 'InnerMetaProperty' : 'LightMetaProperty' ); - + if ( ($this->getType() instanceof IntegerType) ) { @@ -404,7 +412,7 @@ public function toLightProperty(MetaClass $holder) } else { $size = null; } - + return call_user_func_array( array($propertyClassName, 'fill'), @@ -430,14 +438,14 @@ private function buildColumn($columnName) { if (is_array($columnName)) { $out = array(); - + foreach ($columnName as $name) { $out[] = $this->buildColumn($name); } - + return $out; } - + $column = <<size) { $column .= << setSize({$this->size}) EOT; } - + if ($this->type instanceof NumericType) { $column .= << setPrecision({$this->type->getPrecision()}) EOT; } - + $column .= << setPrimaryKey(true) EOT; - + if ($this->getType() instanceof IntegerType) { $column .= << @@ -484,10 +492,10 @@ private function buildColumn($columnName) EOT; } } - + if ($this->type->hasDefault()) { $default = $this->type->getDefault(); - + if ($this->type instanceof BooleanType) { if ($default) $default = 'true'; @@ -496,21 +504,21 @@ private function buildColumn($columnName) } elseif ($this->type instanceof StringType) { $default = "'{$default}'"; } - + $column .= << setDefault({$default}) EOT; } - + $column .= <<getPattern() instanceof NosqlClassPattern ) { + if( $class->getPattern() instanceof NoSqlClassPattern ) { // checking NoSQL-DB try { - $db = NoSQLPool::me()->getLink($class->getSourceLink()); + $db = NoSqlPool::me()->getLink($class->getSourceLink()); } catch (BaseException $e) { $out-> errorLine( @@ -553,82 +553,95 @@ class_exists($class->getName(), true) 'identifier name mismatch in '.$class->getName().' class' ); - try { - DBPool::getByDao($dao); - } catch (MissingElementException $e) { - // skipping - $out->info(', '); - continue; - } + if( $class->getPattern() instanceof NoSqlClassPattern ) { + try { + NoSqlPool::getByDao($dao); + } catch (MissingElementException $e) { + // skipping + $out->info(', '); + continue; + } - $query = - Criteria::create($dao)-> - setLimit(1)-> - add(Expression::notNull($class->getIdentifier()->getName()))-> - addOrder($class->getIdentifier()->getName())-> - toSelectQuery(); + $out->info(', '); + } else { + try { + DBPool::getByDao($dao); + } catch (MissingElementException $e) { + // skipping + $out->info(', '); + continue; + } - $out->warning( - ' (' - .$query->getFieldsCount() - .'/' - .$query->getTablesCount() - .'/' - ); + $query = + Criteria::create($dao)-> + setLimit(1)-> + add(Expression::notNull($class->getIdentifier()->getName()))-> + addOrder($class->getIdentifier()->getName())-> + toSelectQuery(); + + $out->warning( + ' (' + .$query->getFieldsCount() + .'/' + .$query->getTablesCount() + .'/' + ); - $clone = clone $object; + $clone = clone $object; - if (serialize($clone) == serialize($object)) - $out->info('C', true); - else { - $out->error('C', true); - } + if (serialize($clone) == serialize($object)) + $out->info('C', true); + else { + $out->error('C', true); + } - $out->warning('/'); + $out->warning('/'); - try { - $object = $dao->getByQuery($query); - $form = $object->proto()->makeForm(); - FormUtils::object2form($object, $form); + try { + $object = $dao->getByQuery($query); + $form = $object->proto()->makeForm(); + FormUtils::object2form($object, $form); + + if ($errors = $form->getErrors()) { + $formErrors[$class->getName()] = $errors; + + $out->error('F', true); + } else + $out->info('F', true); + } catch (ObjectNotFoundException $e) { + $out->warning('F'); + } - if ($errors = $form->getErrors()) { - $formErrors[$class->getName()] = $errors; + $out->warning('/'); - $out->error('F', true); - } else - $out->info('F', true); - } catch (ObjectNotFoundException $e) { - $out->warning('F'); - } + if ( + Criteria::create($dao)-> + setFetchStrategy(FetchStrategy::cascade())-> + toSelectQuery() + == $dao->makeSelectHead() + ) { + $out->info('H', true); + } else { + $out->error('H', true); + } - $out->warning('/'); + $out->warning('/'); - if ( - Criteria::create($dao)-> - setFetchStrategy(FetchStrategy::cascade())-> - toSelectQuery() - == $dao->makeSelectHead() - ) { - $out->info('H', true); - } else { - $out->error('H', true); - } - - $out->warning('/'); + // cloning once again + $clone = clone $object; - // cloning once again - $clone = clone $object; + FormUtils::object2form($object, $form); + FormUtils::form2object($form, $object); - FormUtils::object2form($object, $form); - FormUtils::form2object($form, $object); + if ($object != $clone) { + $out->error('T', true); + } else { + $out->info('T', true); + } - if ($object != $clone) { - $out->error('T', true); - } else { - $out->info('T', true); + $out->warning(')')->info(', '); } - $out->warning(')')->info(', '); } } From 3683174b53acfe8924b4d289dffcd74385f068d0 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 26 Jan 2012 00:38:13 +0400 Subject: [PATCH 008/418] Date & Timestamp method "toFormatString" --- core/Base/Date.class.php | 94 +++++++++++++++++++---------------- core/Base/Timestamp.class.php | 56 ++++++++++++--------- 2 files changed, 83 insertions(+), 67 deletions(-) diff --git a/core/Base/Date.class.php b/core/Base/Date.class.php index b8614b3f0d..4ae9b83d34 100644 --- a/core/Base/Date.class.php +++ b/core/Base/Date.class.php @@ -13,9 +13,9 @@ /** * Date's container and utilities. - * + * * @see DateRange - * + * * @ingroup Base **/ class Date implements Stringable, DialectString @@ -27,14 +27,14 @@ class Date implements Stringable, DialectString const WEEKDAY_FRIDAY = 5; const WEEKDAY_SATURDAY = 6; const WEEKDAY_SUNDAY = 0; // because strftime('%w') is 0 on Sunday - + protected $string = null; protected $int = null; - + protected $year = null; protected $month = null; protected $day = null; - + /** * @return Date **/ @@ -42,12 +42,12 @@ public static function create($date) { return new self($date); } - + public static function today($delimiter = '-') { return date("Y{$delimiter}m{$delimiter}d"); } - + /** * @return Date **/ @@ -55,7 +55,7 @@ public static function makeToday() { return new self(self::today()); } - + /** * @return Date * @see http://www.faqs.org/rfcs/rfc3339.html @@ -70,7 +70,7 @@ public static function makeFromWeek($weekNumber, $year = null) ($weekNumber > 0) && ($weekNumber <= self::getWeekCountInYear($year)) ); - + $date = new self( date( @@ -80,7 +80,7 @@ public static function makeFromWeek($weekNumber, $year = null) ) ) ); - + $days = ( ( @@ -89,10 +89,10 @@ public static function makeFromWeek($weekNumber, $year = null) ) * 7 ) + 1 - $date->getWeekDay(); - + return $date->modify("+{$days} day"); } - + public static function dayDifference(Date $left, Date $right) { return @@ -107,7 +107,7 @@ public static function dayDifference(Date $left, Date $right) $left->getYear() ); } - + public static function compare(Date $left, Date $right) { if ($left->int == $right->int) @@ -127,13 +127,13 @@ public function __construct($date) $this->string = date($this->getFormat(), $date); } elseif ($date && is_string($date)) $this->stringImport($date); - + if ($this->string === null) { throw new WrongArgumentException( "strange input given - '{$date}'" ); } - + $this->import($this->string); $this->buildInteger(); } @@ -147,12 +147,12 @@ public function __wakeup() { $this->import(date($this->getFormat(), $this->int)); } - + public function toStamp() { return $this->int; } - + public function toDate($delimiter = '-') { return @@ -162,7 +162,7 @@ public function toDate($delimiter = '-') .$delimiter .$this->day; } - + public function getYear() { return $this->year; @@ -177,7 +177,7 @@ public function getDay() { return $this->day; } - + public function getWeek() { return date('W', $this->int); @@ -187,20 +187,20 @@ public function getWeekDay() { return strftime('%w', $this->int); } - + /** * @return Date **/ public function spawn($modification = null) { $child = new $this($this->string); - + if ($modification) return $child->modify($modification); - + return $child; } - + /** * @throws WrongArgumentException * @return Date @@ -209,12 +209,12 @@ public function modify($string) { try { $time = strtotime($string, $this->int); - + if ($time === false) throw new WrongArgumentException( "modification yielded false '{$string}'" ); - + $this->int = $time; $this->string = date($this->getFormat(), $time); $this->import($this->string); @@ -223,10 +223,10 @@ public function modify($string) "wrong time string '{$string}'" ); } - + return $this; } - + public function getDayStartStamp() { return @@ -237,7 +237,7 @@ public function getDayStartStamp() $this->year ); } - + public function getDayEndStamp() { return @@ -248,7 +248,7 @@ public function getDayEndStamp() $this->year ); } - + /** * @return Date **/ @@ -258,7 +258,7 @@ public function getFirstDayOfWeek($weekStart = Date::WEEKDAY_MONDAY) '-'.((7 + $this->getWeekDay() - $weekStart) % 7).' days' ); } - + /** * @return Date **/ @@ -268,18 +268,18 @@ public function getLastDayOfWeek($weekStart = Date::WEEKDAY_MONDAY) '+'.((13 - $this->getWeekDay() + $weekStart) % 7).' days' ); } - + public function toString() { return $this->string; } - + public function toDialectString(Dialect $dialect) { // there are no known differences yet return $dialect->quoteValue($this->toString()); } - + /** * ISO 8601 date string **/ @@ -287,7 +287,15 @@ public function toIsoString() { return $this->toString(); } - + + /** + * @param string $format + * @return string + */ + public function toFormatString($format = 'd.m.Y') { + return date($format, $this->int); + } + /** * @return Timestamp **/ @@ -295,22 +303,22 @@ public function toTimestamp() { return Timestamp::create($this->toStamp()); } - + protected static function getFormat() { return 'Y-m-d'; } - + /* void */ protected function import($string) { list($this->year, $this->month, $this->day) = explode('-', $string, 3); - + if (!$this->month || !$this->day) throw new WrongArgumentException( 'month and day must not be zero' ); - + $this->string = sprintf( '%04d-%02d-%02d', @@ -318,25 +326,25 @@ protected static function getFormat() $this->month, $this->day ); - + list($this->year, $this->month, $this->day) = explode('-', $this->string, 3); } - + /* void */ protected function stringImport($string) { $matches = array(); - + if ( preg_match('/^(\d{1,4})-(\d{1,2})-(\d{1,2})$/', $string, $matches) ) { if (checkdate($matches[2], $matches[3], $matches[1])) $this->string = $string; - + } elseif (($stamp = strtotime($string)) !== false) $this->string = date($this->getFormat(), $stamp); } - + /* void */ protected function buildInteger() { $this->int = diff --git a/core/Base/Timestamp.class.php b/core/Base/Timestamp.class.php index f097d3db2a..ae42014a71 100644 --- a/core/Base/Timestamp.class.php +++ b/core/Base/Timestamp.class.php @@ -23,7 +23,7 @@ class Timestamp extends Date private $hour = null; private $minute = null; private $second = null; - + /** * @return Timestamp **/ @@ -31,12 +31,12 @@ public static function create($timestamp) { return new self($timestamp); } - + public static function now() { return date(self::getFormat()); } - + /** * @return Timestamp **/ @@ -44,7 +44,7 @@ public static function makeNow() { return new self(time()); } - + /** * @return Timestamp **/ @@ -52,7 +52,7 @@ public static function makeToday() { return new self(self::today()); } - + public function toTime($timeDelimiter = ':', $secondDelimiter = '.') { return @@ -62,7 +62,7 @@ public function toTime($timeDelimiter = ':', $secondDelimiter = '.') .$secondDelimiter .$this->second; } - + public function toDateTime( $dateDelimiter = '-', $timeDelimiter = ':', @@ -73,27 +73,27 @@ public function toDateTime( $this->toDate($dateDelimiter).' ' .$this->toTime($timeDelimiter, $secondDelimiter); } - + public function getHour() { return $this->hour; } - + public function getMinute() { return $this->minute; } - + public function getSecond() { return $this->second; } - + public function equals(Timestamp $timestamp) { return ($this->toDateTime() === $timestamp->toDateTime()); } - + public function getDayStartStamp() { if (!$this->hour && !$this->minute && !$this->second) @@ -106,7 +106,7 @@ public function getHourStartStamp() { if (!$this->minute && !$this->second) return $this->int; - + return mktime( $this->hour, @@ -117,7 +117,7 @@ public function getHourStartStamp() $this->year ); } - + /** * ISO 8601 time string **/ @@ -128,7 +128,15 @@ public function toIsoString($convertToUtc = true) else return date('Y-m-d\TH:i:sO', $this->int); } - + + /** + * @param string $format + * @return string + */ + public function toFormatString($format = 'd.m.Y H:i:s') { + return date($format, $this->int); + } + /** * @return Timestamp **/ @@ -136,19 +144,19 @@ public function toTimestamp() { return $this; } - + protected static function getFormat() { return 'Y-m-d H:i:s'; } - + /* void */ protected function import($string) { list($date, $time) = explode(' ', $string, 2); - + list($this->hour, $this->minute, $this->second) = explode(':', $time, 3); - + $time = sprintf( '%02d:%02d:%02d', @@ -156,19 +164,19 @@ protected static function getFormat() $this->minute, $this->second ); - + list($this->hour, $this->minute, $this->second) = explode(':', $time, 3); - + parent::import($date); - + $this->string .= ' '.$time; } - + /* void */ protected function stringImport($string) { $matches = array(); - + if ( preg_match( '/^(\d{1,4})-(\d{1,2})-(\d{1,2})\s\d{1,2}:\d{1,2}:\d{1,2}$/', @@ -190,7 +198,7 @@ protected static function getFormat() } elseif (($stamp = strtotime($string)) !== false) $this->string = date($this->getFormat(), $stamp); } - + /* void */ protected function buildInteger() { $this->int = From 2692cc5d3e8db5d2469137b07e53afad4207725a Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 26 Jan 2012 00:38:27 +0400 Subject: [PATCH 009/418] default value fix --- core/OSQL/DBColumn.class.php | 74 ++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/core/OSQL/DBColumn.class.php b/core/OSQL/DBColumn.class.php index a7a5e9c863..428d7b40be 100644 --- a/core/OSQL/DBColumn.class.php +++ b/core/OSQL/DBColumn.class.php @@ -16,18 +16,18 @@ final class DBColumn implements SQLTableName { private $type = null; private $name = null; - + private $table = null; private $default = null; - + private $reference = null; private $onUpdate = null; private $onDelete = null; - + private $primary = null; - + private $sequenced = null; - + /** * @return DBColumn **/ @@ -35,13 +35,13 @@ public static function create(DataType $type, $name) { return new self($type, $name); } - + public function __construct(DataType $type, $name) { $this->type = $type; $this->name = $name; } - + /** * @return DataType **/ @@ -49,22 +49,22 @@ public function getType() { return $this->type; } - + /** * @return DBColumn **/ public function setTable(DBTable $table) { $this->table = $table; - + return $this; } - + public function getName() { return $this->name; } - + /** * @return DBTable **/ @@ -72,37 +72,37 @@ public function getTable() { return $this->table; } - + public function isPrimaryKey() { return $this->primary; } - + /** * @return DBColumn **/ public function setPrimaryKey($primary = false) { $this->primary = true === $primary; - + return $this; } - + /** * @return DBColumn **/ public function setDefault($default) { $this->default = $default; - + return $this; } - + public function getDefault() { return $this->default; } - + /** * @throws WrongArgumentException * @return DBColumn @@ -123,14 +123,14 @@ public function setReference( || $onUpdate instanceof ForeignChangeAction ) ); - + $this->reference = $column; $this->onDelete = $onDelete; $this->onUpdate = $onUpdate; - + return $this; } - + /** * @return DBColumn **/ @@ -139,64 +139,64 @@ public function dropReference() $this->reference = null; $this->onDelete = null; $this->onUpdate = null; - + return $this; } - + public function hasReference() { return ($this->reference !== null); } - + /** * @return DBColumn **/ public function setAutoincrement($auto = false) { $this->sequenced = (true === $auto); - + return $this; } - + public function isAutoincrement() { return $this->sequenced; } - + public function toDialectString(Dialect $dialect) { $out = $dialect->quoteField($this->name).' ' .$this->type->toDialectString($dialect); - + if (null !== $this->default) { - + if ($this->type->getId() == DataType::BOOLEAN) $default = $this->default ? $dialect->literalToString(Dialect::LITERAL_TRUE) : $dialect->literalToString(Dialect::LITERAL_FALSE); else - $default = $dialect->valueToString($default); - + $default = $dialect->valueToString($this->default); + $out .= ' DEFAULT '.($default); } - + if ($this->reference) { - + $table = $this->reference->getTable()->getName(); $column = $this->reference->getName(); - + $out .= " REFERENCES {$dialect->quoteTable($table)}" ."({$dialect->quoteField($column)})"; - + if ($this->onDelete) $out .= ' ON DELETE '.$this->onDelete->toString(); - + if ($this->onUpdate) $out .= ' ON UPDATE '.$this->onUpdate->toString(); } - + return $out; } } From 8f6c15665f5944c267604d88912af1294a5d0162 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 26 Jan 2012 11:22:33 +0400 Subject: [PATCH 010/418] merge with onphp-framework master branch --- core/Base/Date.class.php | 17 ++++--- core/Cache/CachePeer.class.php | 2 +- core/Cache/WatermarkedPeer.class.php | 21 ++++++-- core/DB/Dialect.class.php | 21 ++++---- doc/ChangeLog | 9 ++++ global.inc.php.tpl | 4 ++ .../View}/CleanRedirectView.class.php | 0 main/{Flow => UI/View}/CtppView.class.php | 0 main/{Flow => UI/View}/DebugPhpView.class.php | 0 main/{Flow => UI/View}/EmptyGifView.class.php | 0 main/{Flow => UI/View}/EmptyView.class.php | 0 .../{Flow => UI/View}/HttpErrorView.class.php | 0 main/{Flow => UI/View}/JsonView.class.php | 0 .../MultiPrefixPhpViewResolver.class.php | 0 main/{Flow => UI/View}/PartViewer.class.php | 0 .../View}/PhpViewResolver.class.php | 0 .../View}/RedirectToView.class.php | 0 main/{Flow => UI/View}/RedirectView.class.php | 0 .../{Flow => UI/View}/SimplePhpView.class.php | 0 main/{Flow => UI/View}/View.class.php | 0 main/{Flow => UI/View}/ViewResolver.class.php | 0 test/core/LogicTest.class.php | 8 +++ test/core/WatermarkedPeerTest.class.php | 50 +++++++++++++++++++ 23 files changed, 110 insertions(+), 22 deletions(-) rename main/{Flow => UI/View}/CleanRedirectView.class.php (100%) rename main/{Flow => UI/View}/CtppView.class.php (100%) rename main/{Flow => UI/View}/DebugPhpView.class.php (100%) rename main/{Flow => UI/View}/EmptyGifView.class.php (100%) rename main/{Flow => UI/View}/EmptyView.class.php (100%) rename main/{Flow => UI/View}/HttpErrorView.class.php (100%) rename main/{Flow => UI/View}/JsonView.class.php (100%) rename main/{Flow => UI/View}/MultiPrefixPhpViewResolver.class.php (100%) rename main/{Flow => UI/View}/PartViewer.class.php (100%) rename main/{Flow => UI/View}/PhpViewResolver.class.php (100%) rename main/{Flow => UI/View}/RedirectToView.class.php (100%) rename main/{Flow => UI/View}/RedirectView.class.php (100%) rename main/{Flow => UI/View}/SimplePhpView.class.php (100%) rename main/{Flow => UI/View}/View.class.php (100%) rename main/{Flow => UI/View}/ViewResolver.class.php (100%) create mode 100644 test/core/WatermarkedPeerTest.class.php diff --git a/core/Base/Date.class.php b/core/Base/Date.class.php index 4ae9b83d34..a5f021233f 100644 --- a/core/Base/Date.class.php +++ b/core/Base/Date.class.php @@ -274,6 +274,15 @@ public function toString() return $this->string; } + /** + * @param string $format + * @return string + */ + public function toFormatString($format) + { + return date($format, $this->toStamp()); + } + public function toDialectString(Dialect $dialect) { // there are no known differences yet @@ -288,14 +297,6 @@ public function toIsoString() return $this->toString(); } - /** - * @param string $format - * @return string - */ - public function toFormatString($format = 'd.m.Y') { - return date($format, $this->int); - } - /** * @return Timestamp **/ diff --git a/core/Cache/CachePeer.class.php b/core/Cache/CachePeer.class.php index 1fe10efe2c..35ea662b27 100644 --- a/core/Cache/CachePeer.class.php +++ b/core/Cache/CachePeer.class.php @@ -150,7 +150,7 @@ public function getList($indexes) foreach ($indexes as $key) if (null !== ($value = $this->get($key))) - $out[] = $value; + $out[$key] = $value; return $out; } diff --git a/core/Cache/WatermarkedPeer.class.php b/core/Cache/WatermarkedPeer.class.php index c696b68e9a..3319db692d 100644 --- a/core/Cache/WatermarkedPeer.class.php +++ b/core/Cache/WatermarkedPeer.class.php @@ -110,10 +110,23 @@ public function decrement($key, $value) public function getList($indexes) { - foreach ($indexes as &$index) - $index = $this->getActualWatermark().$index; - - return $this->peer->getList($indexes); + $peerIndexMap = array(); + foreach ($indexes as $index) + $peerIndexMap[$this->getActualWatermark().$index] = $index; + + $peerIndexes = array_keys($peerIndexMap); + $peerResult = $this->peer->getList($peerIndexes); + + $result = array(); + if (!empty($peerResult)) { + foreach ($peerResult as $key => $value) { + $result[$peerIndexMap[$key]] = $value; + } + } else { + $result = $peerResult; + } + + return $result; } public function get($key) diff --git a/core/DB/Dialect.class.php b/core/DB/Dialect.class.php index 0281371292..efff76504f 100644 --- a/core/DB/Dialect.class.php +++ b/core/DB/Dialect.class.php @@ -103,17 +103,20 @@ public function toValueString($expression) private function toNeededString($expression, $method) { + if (null === $expression) + throw new WrongArgumentException( + 'not null expression expected' + ); + $string = null; - if (null !== $expression) { - if ($expression instanceof DialectString) { - if ($expression instanceof Query) - $string .= '('.$expression->toDialectString($this).')'; - else - $string .= $expression->toDialectString($this); - } else { - $string .= $this->$method($expression); - } + if ($expression instanceof DialectString) { + if ($expression instanceof Query) + $string .= '('.$expression->toDialectString($this).')'; + else + $string .= $expression->toDialectString($this); + } else { + $string .= $this->$method($expression); } return $string; diff --git a/doc/ChangeLog b/doc/ChangeLog index 5407f828ee..3cef93b6e4 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,12 @@ +2012-01-13 Alexander A. Zaytsev + + * core/Base/Date.class.php: toFormatString method added. + +2012-01-11 Evgeny V. Kokovikhin + + * core/DB/Dialect.class.php: throw exception for null values. Thanks to + Nikita V. Konstantinov. + 2011-11-21 Alexey S. Denisov, Evgeny V. Kokovikhin * meta/types/ObjectType.class.php, test/misc/DAOTest.class.php: changed logic diff --git a/global.inc.php.tpl b/global.inc.php.tpl index cf2b7b0f76..590bc1d8d0 100644 --- a/global.inc.php.tpl +++ b/global.inc.php.tpl @@ -68,6 +68,7 @@ define('ONPHP_CORE_PATH', ONPHP_ROOT_PATH.'core'.DIRECTORY_SEPARATOR); define('ONPHP_MAIN_PATH', ONPHP_ROOT_PATH.'main'.DIRECTORY_SEPARATOR); define('ONPHP_META_PATH', ONPHP_ROOT_PATH.'meta'.DIRECTORY_SEPARATOR); + define('ONPHP_UI_PATH', ONPHP_ROOT_PATH.'UI'.DIRECTORY_SEPARATOR); if (!defined('ONPHP_META_PATH')) define( @@ -144,6 +145,9 @@ .ONPHP_MAIN_PATH.'UnifiedContainer'.PATH_SEPARATOR + .ONPHP_MAIN_PATH.'UI'.PATH_SEPARATOR + .ONPHP_MAIN_PATH.'UI'.DIRECTORY_SEPARATOR.'View'.PATH_SEPARATOR + .ONPHP_MAIN_PATH.'Utils' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'TuringTest'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Archivers'.PATH_SEPARATOR diff --git a/main/Flow/CleanRedirectView.class.php b/main/UI/View/CleanRedirectView.class.php similarity index 100% rename from main/Flow/CleanRedirectView.class.php rename to main/UI/View/CleanRedirectView.class.php diff --git a/main/Flow/CtppView.class.php b/main/UI/View/CtppView.class.php similarity index 100% rename from main/Flow/CtppView.class.php rename to main/UI/View/CtppView.class.php diff --git a/main/Flow/DebugPhpView.class.php b/main/UI/View/DebugPhpView.class.php similarity index 100% rename from main/Flow/DebugPhpView.class.php rename to main/UI/View/DebugPhpView.class.php diff --git a/main/Flow/EmptyGifView.class.php b/main/UI/View/EmptyGifView.class.php similarity index 100% rename from main/Flow/EmptyGifView.class.php rename to main/UI/View/EmptyGifView.class.php diff --git a/main/Flow/EmptyView.class.php b/main/UI/View/EmptyView.class.php similarity index 100% rename from main/Flow/EmptyView.class.php rename to main/UI/View/EmptyView.class.php diff --git a/main/Flow/HttpErrorView.class.php b/main/UI/View/HttpErrorView.class.php similarity index 100% rename from main/Flow/HttpErrorView.class.php rename to main/UI/View/HttpErrorView.class.php diff --git a/main/Flow/JsonView.class.php b/main/UI/View/JsonView.class.php similarity index 100% rename from main/Flow/JsonView.class.php rename to main/UI/View/JsonView.class.php diff --git a/main/Flow/MultiPrefixPhpViewResolver.class.php b/main/UI/View/MultiPrefixPhpViewResolver.class.php similarity index 100% rename from main/Flow/MultiPrefixPhpViewResolver.class.php rename to main/UI/View/MultiPrefixPhpViewResolver.class.php diff --git a/main/Flow/PartViewer.class.php b/main/UI/View/PartViewer.class.php similarity index 100% rename from main/Flow/PartViewer.class.php rename to main/UI/View/PartViewer.class.php diff --git a/main/Flow/PhpViewResolver.class.php b/main/UI/View/PhpViewResolver.class.php similarity index 100% rename from main/Flow/PhpViewResolver.class.php rename to main/UI/View/PhpViewResolver.class.php diff --git a/main/Flow/RedirectToView.class.php b/main/UI/View/RedirectToView.class.php similarity index 100% rename from main/Flow/RedirectToView.class.php rename to main/UI/View/RedirectToView.class.php diff --git a/main/Flow/RedirectView.class.php b/main/UI/View/RedirectView.class.php similarity index 100% rename from main/Flow/RedirectView.class.php rename to main/UI/View/RedirectView.class.php diff --git a/main/Flow/SimplePhpView.class.php b/main/UI/View/SimplePhpView.class.php similarity index 100% rename from main/Flow/SimplePhpView.class.php rename to main/UI/View/SimplePhpView.class.php diff --git a/main/Flow/View.class.php b/main/UI/View/View.class.php similarity index 100% rename from main/Flow/View.class.php rename to main/UI/View/View.class.php diff --git a/main/Flow/ViewResolver.class.php b/main/UI/View/ViewResolver.class.php similarity index 100% rename from main/Flow/ViewResolver.class.php rename to main/UI/View/ViewResolver.class.php diff --git a/test/core/LogicTest.class.php b/test/core/LogicTest.class.php index bfaa3834e7..83b20e5c4c 100644 --- a/test/core/LogicTest.class.php +++ b/test/core/LogicTest.class.php @@ -210,6 +210,14 @@ public function testBaseSqlGeneration() '(- a)', Expression::minus('a')->toDialectString($dialect) ); + + try { + Expression::eq('id', null)->toDialectString($dialect); + + $this->fail(); + } catch (WrongArgumentException $e) { + //it's Ok + } } public function testPgGeneration() diff --git a/test/core/WatermarkedPeerTest.class.php b/test/core/WatermarkedPeerTest.class.php new file mode 100644 index 0000000000..4d9e8eb0a8 --- /dev/null +++ b/test/core/WatermarkedPeerTest.class.php @@ -0,0 +1,50 @@ +clean(); + + $cache->set('a', 'a', Cache::EXPIRES_MEDIUM); + $cache->set('b', 2, Cache::EXPIRES_MEDIUM); + $cache->set('c', 42.28, Cache::EXPIRES_MEDIUM); + + $this->assertEquals($cache->get('a'), 'a'); + $this->assertEquals($cache->get('b'), 2); + $this->assertEquals($cache->get('c'), 42.28); + + $list = $cache->getList(array('a', 'b', 'c')); + + $this->assertEquals(count($list), 3); + + $this->assertEquals($list['a'], 'a'); + $this->assertEquals($list['b'], 2); + $this->assertEquals($list['c'], 42.28); + + $list = $cache->getList(array('a')); + + $this->assertEquals(count($list), 1); + + $this->assertEquals($list['a'], 'a'); + + $list = $cache->getList(array('a', 'b', 'c', 'd')); + + $this->assertEquals(count($list), 3); + + $this->assertEquals($list['a'], 'a'); + $this->assertEquals($list['b'], 2); + $this->assertEquals($list['c'], 42.28); + + $list = $cache->getList(array('d')); + + $this->assertEquals(count($list), 0); + + $cache->clean(); + } + } +?> \ No newline at end of file From 26ef817cf632ed1741241eed76354a96af851093 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 26 Jan 2012 11:45:27 +0400 Subject: [PATCH 011/418] fixing conflicts --- core/Base/Date.class.php | 6 +----- core/DB/Dialect.class.php | 3 --- global.inc.php.tpl | 4 +--- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/core/Base/Date.class.php b/core/Base/Date.class.php index a5f021233f..1758e25af3 100644 --- a/core/Base/Date.class.php +++ b/core/Base/Date.class.php @@ -274,10 +274,6 @@ public function toString() return $this->string; } - /** - * @param string $format - * @return string - */ public function toFormatString($format) { return date($format, $this->toStamp()); @@ -357,4 +353,4 @@ protected static function getFormat() ); } } -?> +?> \ No newline at end of file diff --git a/core/DB/Dialect.class.php b/core/DB/Dialect.class.php index efff76504f..ed9f56abb1 100644 --- a/core/DB/Dialect.class.php +++ b/core/DB/Dialect.class.php @@ -85,9 +85,6 @@ public function typeToString(DataType $type) if ($type->getId() == DataType::IP_RANGE) return 'varchar(41)'; - if ($type->getId() == DataType::UUID) - return 'varchar(36)'; - return $type->getName(); } diff --git a/global.inc.php.tpl b/global.inc.php.tpl index 590bc1d8d0..b4f34c81cd 100644 --- a/global.inc.php.tpl +++ b/global.inc.php.tpl @@ -103,8 +103,6 @@ .ONPHP_CORE_PATH.'Logic' .PATH_SEPARATOR .ONPHP_CORE_PATH.'OSQL' .PATH_SEPARATOR - .ONPHP_CORE_PATH.'NoSQL' .PATH_SEPARATOR - // main framework .ONPHP_MAIN_PATH.'Base' .PATH_SEPARATOR @@ -195,4 +193,4 @@ //NOTE: disable by default //see http://pgfoundry.org/docman/view.php/1000079/117/README.txt //define('POSTGRES_IP4_ENABLED', true); -?> +?> \ No newline at end of file From d170622c0d9c08fc211f433bb81ab6d9ac4aeea7 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 26 Jan 2012 11:48:21 +0400 Subject: [PATCH 012/418] fixing confilcts --- core/Base/Date.class.php | 90 +++++++++++++++++++-------------------- core/DB/Dialect.class.php | 52 +++++++++++----------- global.inc.php.tpl | 80 +++++++++++++++++----------------- 3 files changed, 111 insertions(+), 111 deletions(-) diff --git a/core/Base/Date.class.php b/core/Base/Date.class.php index 1758e25af3..af60ef8678 100644 --- a/core/Base/Date.class.php +++ b/core/Base/Date.class.php @@ -13,9 +13,9 @@ /** * Date's container and utilities. - * + * * @see DateRange - * + * * @ingroup Base **/ class Date implements Stringable, DialectString @@ -27,14 +27,14 @@ class Date implements Stringable, DialectString const WEEKDAY_FRIDAY = 5; const WEEKDAY_SATURDAY = 6; const WEEKDAY_SUNDAY = 0; // because strftime('%w') is 0 on Sunday - + protected $string = null; protected $int = null; - + protected $year = null; protected $month = null; protected $day = null; - + /** * @return Date **/ @@ -42,12 +42,12 @@ public static function create($date) { return new self($date); } - + public static function today($delimiter = '-') { return date("Y{$delimiter}m{$delimiter}d"); } - + /** * @return Date **/ @@ -55,7 +55,7 @@ public static function makeToday() { return new self(self::today()); } - + /** * @return Date * @see http://www.faqs.org/rfcs/rfc3339.html @@ -70,7 +70,7 @@ public static function makeFromWeek($weekNumber, $year = null) ($weekNumber > 0) && ($weekNumber <= self::getWeekCountInYear($year)) ); - + $date = new self( date( @@ -80,7 +80,7 @@ public static function makeFromWeek($weekNumber, $year = null) ) ) ); - + $days = ( ( @@ -89,10 +89,10 @@ public static function makeFromWeek($weekNumber, $year = null) ) * 7 ) + 1 - $date->getWeekDay(); - + return $date->modify("+{$days} day"); } - + public static function dayDifference(Date $left, Date $right) { return @@ -107,7 +107,7 @@ public static function dayDifference(Date $left, Date $right) $left->getYear() ); } - + public static function compare(Date $left, Date $right) { if ($left->int == $right->int) @@ -127,13 +127,13 @@ public function __construct($date) $this->string = date($this->getFormat(), $date); } elseif ($date && is_string($date)) $this->stringImport($date); - + if ($this->string === null) { throw new WrongArgumentException( "strange input given - '{$date}'" ); } - + $this->import($this->string); $this->buildInteger(); } @@ -147,12 +147,12 @@ public function __wakeup() { $this->import(date($this->getFormat(), $this->int)); } - + public function toStamp() { return $this->int; } - + public function toDate($delimiter = '-') { return @@ -162,7 +162,7 @@ public function toDate($delimiter = '-') .$delimiter .$this->day; } - + public function getYear() { return $this->year; @@ -177,7 +177,7 @@ public function getDay() { return $this->day; } - + public function getWeek() { return date('W', $this->int); @@ -187,20 +187,20 @@ public function getWeekDay() { return strftime('%w', $this->int); } - + /** * @return Date **/ public function spawn($modification = null) { $child = new $this($this->string); - + if ($modification) return $child->modify($modification); - + return $child; } - + /** * @throws WrongArgumentException * @return Date @@ -209,12 +209,12 @@ public function modify($string) { try { $time = strtotime($string, $this->int); - + if ($time === false) throw new WrongArgumentException( "modification yielded false '{$string}'" ); - + $this->int = $time; $this->string = date($this->getFormat(), $time); $this->import($this->string); @@ -223,10 +223,10 @@ public function modify($string) "wrong time string '{$string}'" ); } - + return $this; } - + public function getDayStartStamp() { return @@ -237,7 +237,7 @@ public function getDayStartStamp() $this->year ); } - + public function getDayEndStamp() { return @@ -248,7 +248,7 @@ public function getDayEndStamp() $this->year ); } - + /** * @return Date **/ @@ -258,7 +258,7 @@ public function getFirstDayOfWeek($weekStart = Date::WEEKDAY_MONDAY) '-'.((7 + $this->getWeekDay() - $weekStart) % 7).' days' ); } - + /** * @return Date **/ @@ -268,23 +268,23 @@ public function getLastDayOfWeek($weekStart = Date::WEEKDAY_MONDAY) '+'.((13 - $this->getWeekDay() + $weekStart) % 7).' days' ); } - + public function toString() { return $this->string; } - + public function toFormatString($format) { return date($format, $this->toStamp()); } - + public function toDialectString(Dialect $dialect) { // there are no known differences yet return $dialect->quoteValue($this->toString()); } - + /** * ISO 8601 date string **/ @@ -292,7 +292,7 @@ public function toIsoString() { return $this->toString(); } - + /** * @return Timestamp **/ @@ -300,22 +300,22 @@ public function toTimestamp() { return Timestamp::create($this->toStamp()); } - + protected static function getFormat() { return 'Y-m-d'; } - + /* void */ protected function import($string) { list($this->year, $this->month, $this->day) = explode('-', $string, 3); - + if (!$this->month || !$this->day) throw new WrongArgumentException( 'month and day must not be zero' ); - + $this->string = sprintf( '%04d-%02d-%02d', @@ -323,25 +323,25 @@ protected static function getFormat() $this->month, $this->day ); - + list($this->year, $this->month, $this->day) = explode('-', $this->string, 3); } - + /* void */ protected function stringImport($string) { $matches = array(); - + if ( preg_match('/^(\d{1,4})-(\d{1,2})-(\d{1,2})$/', $string, $matches) ) { if (checkdate($matches[2], $matches[3], $matches[1])) $this->string = $string; - + } elseif (($stamp = strtotime($string)) !== false) $this->string = date($this->getFormat(), $stamp); } - + /* void */ protected function buildInteger() { $this->int = @@ -353,4 +353,4 @@ protected static function getFormat() ); } } -?> \ No newline at end of file +?> diff --git a/core/DB/Dialect.class.php b/core/DB/Dialect.class.php index ed9f56abb1..1323e24b9f 100644 --- a/core/DB/Dialect.class.php +++ b/core/DB/Dialect.class.php @@ -22,25 +22,25 @@ abstract class /* ANSI's */ Dialect const LITERAL_NULL = 'NULL'; const LITERAL_TRUE = 'TRUE'; const LITERAL_FALSE = 'FALSE'; - + abstract public function preAutoincrement(DBColumn $column); abstract public function postAutoincrement(DBColumn $column); - + abstract public function hasTruncate(); abstract public function hasMultipleTruncate(); abstract public function hasReturning(); - + /** must be implemented too: - + public static function quoteValue($value); **/ - + public static function quoteField($field) { return self::quoteTable($field); } - + public static function quoteTable($table) { return '"'.$table.'"'; @@ -50,7 +50,7 @@ public static function toCasted($field, $type) { return "CAST ({$field} AS {$type})"; } - + public static function timeZone($exist = false) { return @@ -58,7 +58,7 @@ public static function timeZone($exist = false) ? ' WITH TIME ZONE' : ' WITHOUT TIME ZONE'; } - + public static function dropTableMode($cascade = false) { return @@ -66,47 +66,47 @@ public static function dropTableMode($cascade = false) ? ' CASCADE' : ' RESTRICT'; } - + public function quoteBinary($data) { return $this->quoteValue($data); } - + public function unquoteBinary($data) { return $data; } - + public function typeToString(DataType $type) { if ($type->getId() == DataType::IP) return 'varchar(19)'; - + if ($type->getId() == DataType::IP_RANGE) return 'varchar(41)'; - + return $type->getName(); } - + public function toFieldString($expression) { return $this->toNeededString($expression, 'quoteField'); } - + public function toValueString($expression) { return $this->toNeededString($expression, 'quoteValue'); } - + private function toNeededString($expression, $method) { if (null === $expression) throw new WrongArgumentException( 'not null expression expected' ); - + $string = null; - + if ($expression instanceof DialectString) { if ($expression instanceof Query) $string .= '('.$expression->toDialectString($this).')'; @@ -115,10 +115,10 @@ private function toNeededString($expression, $method) } else { $string .= $this->$method($expression); } - + return $string; } - + public function fieldToString($field) { return @@ -126,7 +126,7 @@ public function fieldToString($field) ? $field->toDialectString($this) : $this->quoteField($field); } - + public function valueToString($value) { return @@ -134,27 +134,27 @@ public function valueToString($value) ? $value->toDialectString($this) : $this->quoteValue($value); } - + public function logicToString($logic) { return $logic; } - + public function literalToString($literal) { return $literal; } - + public function fullTextSearch($field, $words, $logic) { throw new UnimplementedFeatureException(); } - + public function fullTextRank($field, $words, $logic) { throw new UnimplementedFeatureException(); } - + public function quoteIpInRange($range, $ip) { throw new UnimplementedFeatureException(); diff --git a/global.inc.php.tpl b/global.inc.php.tpl index b4f34c81cd..7ad77d44a9 100644 --- a/global.inc.php.tpl +++ b/global.inc.php.tpl @@ -10,12 +10,12 @@ ***************************************************************************/ // sample system-wide configuration file - + function error2Exception($code, $string, $file, $line, $context) { throw new BaseException($string, $code); } - + /* void */ function __autoload_failed($classname, $message) { eval( @@ -24,14 +24,14 @@ .'throw new ClassNotFoundException("'.$classname.': '.$message.'");' ); } - + // file extensions define('EXT_CLASS', '.class.php'); define('EXT_TPL', '.tpl.html'); define('EXT_MOD', '.inc.php'); define('EXT_HTML', '.html'); define('EXT_UNIT', '.unit.php'); - + // overridable constant, don't forget for trailing slash // also you may consider using /dev/shm/ for cache purposes if (!defined('ONPHP_TEMP_PATH')) @@ -39,113 +39,113 @@ 'ONPHP_TEMP_PATH', sys_get_temp_dir().DIRECTORY_SEPARATOR.'onPHP'.DIRECTORY_SEPARATOR ); - + if (!defined('ONPHP_CLASS_CACHE')) define('ONPHP_CLASS_CACHE', ONPHP_TEMP_PATH); - + // classes autoload magic if (!defined('ONPHP_CLASS_CACHE_TYPE')) define('ONPHP_CLASS_CACHE_TYPE', 'classPathCache'); - + require dirname(__FILE__).DIRECTORY_SEPARATOR .'misc'.DIRECTORY_SEPARATOR .'Autoloader'.EXT_MOD; - + spl_autoload_register(array('Autoloader', ONPHP_CLASS_CACHE_TYPE), false); - + // system settings error_reporting(E_ALL | E_STRICT); set_error_handler('error2Exception', E_ALL | E_STRICT); ignore_user_abort(true); define('ONPHP_VERSION', '1.0.10.99'); - + if (!defined('ONPHP_IPC_PERMS')) define('ONPHP_IPC_PERMS', 0660); - + // paths define('ONPHP_ROOT_PATH', dirname(__FILE__).DIRECTORY_SEPARATOR); define('ONPHP_CORE_PATH', ONPHP_ROOT_PATH.'core'.DIRECTORY_SEPARATOR); define('ONPHP_MAIN_PATH', ONPHP_ROOT_PATH.'main'.DIRECTORY_SEPARATOR); define('ONPHP_META_PATH', ONPHP_ROOT_PATH.'meta'.DIRECTORY_SEPARATOR); define('ONPHP_UI_PATH', ONPHP_ROOT_PATH.'UI'.DIRECTORY_SEPARATOR); - + if (!defined('ONPHP_META_PATH')) define( 'ONPHP_META_PATH', ONPHP_ROOT_PATH.'meta'.DIRECTORY_SEPARATOR ); - + define('ONPHP_META_CLASSES', ONPHP_META_PATH.'classes'.DIRECTORY_SEPARATOR); - + define( 'ONPHP_INCUBATOR_PATH', ONPHP_ROOT_PATH.'incubator'.DIRECTORY_SEPARATOR ); - + set_include_path( // current path get_include_path().PATH_SEPARATOR - + // core classes .ONPHP_CORE_PATH.'Base' .PATH_SEPARATOR .ONPHP_CORE_PATH.'Cache' .PATH_SEPARATOR - + .ONPHP_CORE_PATH.'DB' .PATH_SEPARATOR .ONPHP_CORE_PATH.'DB'.DIRECTORY_SEPARATOR.'Transaction'.PATH_SEPARATOR - + .ONPHP_CORE_PATH.'Exceptions' .PATH_SEPARATOR - + .ONPHP_CORE_PATH.'Form' .PATH_SEPARATOR .ONPHP_CORE_PATH.'Form'.DIRECTORY_SEPARATOR.'Filters'.PATH_SEPARATOR .ONPHP_CORE_PATH.'Form'.DIRECTORY_SEPARATOR.'Primitives'.PATH_SEPARATOR - + .ONPHP_CORE_PATH.'Logic' .PATH_SEPARATOR .ONPHP_CORE_PATH.'OSQL' .PATH_SEPARATOR - + // main framework .ONPHP_MAIN_PATH.'Base' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Criteria' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Criteria'.DIRECTORY_SEPARATOR.'Projections'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Crypto' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'DAOs' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'DAOs'.DIRECTORY_SEPARATOR.'Handlers'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'DAOs'.DIRECTORY_SEPARATOR.'Workers'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Flow' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'SPL' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Net' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Http'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Mail'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Ip'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Soap'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Math' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Markup' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Markup'.DIRECTORY_SEPARATOR.'Feed'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Markup'.DIRECTORY_SEPARATOR.'Html'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'OQL' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Expressions'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Parsers'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Statements'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'OpenId' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'EntityProto'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'EntityProto'.DIRECTORY_SEPARATOR.'Builders'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'EntityProto'.DIRECTORY_SEPARATOR.'Accessors'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'UnifiedContainer'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'UI'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'UI'.DIRECTORY_SEPARATOR.'View'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Utils' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'TuringTest'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Archivers'.PATH_SEPARATOR @@ -165,23 +165,23 @@ .ONPHP_MAIN_PATH.'Messages'.DIRECTORY_SEPARATOR.'Interface'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Application' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Charts'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Charts'.DIRECTORY_SEPARATOR.'Google'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Monitoring'.PATH_SEPARATOR - + .ONPHP_META_CLASSES.PATH_SEPARATOR - + /* .ONPHP_INCUBATOR_PATH .'classes'.DIRECTORY_SEPARATOR .'Application'.DIRECTORY_SEPARATOR.PATH_SEPARATOR - + .ONPHP_INCUBATOR_PATH .'classes'.DIRECTORY_SEPARATOR .'Application'.DIRECTORY_SEPARATOR .'Markups'.DIRECTORY_SEPARATOR.PATH_SEPARATOR - + .ONPHP_INCUBATOR_PATH .'classes'.DIRECTORY_SEPARATOR .'Application'.DIRECTORY_SEPARATOR @@ -189,8 +189,8 @@ .'Documents'.DIRECTORY_SEPARATOR.PATH_SEPARATOR */ ); - + //NOTE: disable by default //see http://pgfoundry.org/docman/view.php/1000079/117/README.txt //define('POSTGRES_IP4_ENABLED', true); -?> \ No newline at end of file +?> From 54eb1ac421c66fe43b52d49e4106d078f885a0fb Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 26 Jan 2012 11:56:02 +0400 Subject: [PATCH 013/418] complete merge --- core/Base/Timestamp.class.php | 56 ++++++++++++++------------------ core/DB/Dialect.class.php | 3 ++ doc/patches/core_DB_Dialect.diff | 10 ++++++ doc/patches/global-inc.diff | 9 +++++ global.inc.php.tpl | 2 ++ 5 files changed, 48 insertions(+), 32 deletions(-) create mode 100644 doc/patches/core_DB_Dialect.diff create mode 100644 doc/patches/global-inc.diff diff --git a/core/Base/Timestamp.class.php b/core/Base/Timestamp.class.php index ae42014a71..f097d3db2a 100644 --- a/core/Base/Timestamp.class.php +++ b/core/Base/Timestamp.class.php @@ -23,7 +23,7 @@ class Timestamp extends Date private $hour = null; private $minute = null; private $second = null; - + /** * @return Timestamp **/ @@ -31,12 +31,12 @@ public static function create($timestamp) { return new self($timestamp); } - + public static function now() { return date(self::getFormat()); } - + /** * @return Timestamp **/ @@ -44,7 +44,7 @@ public static function makeNow() { return new self(time()); } - + /** * @return Timestamp **/ @@ -52,7 +52,7 @@ public static function makeToday() { return new self(self::today()); } - + public function toTime($timeDelimiter = ':', $secondDelimiter = '.') { return @@ -62,7 +62,7 @@ public function toTime($timeDelimiter = ':', $secondDelimiter = '.') .$secondDelimiter .$this->second; } - + public function toDateTime( $dateDelimiter = '-', $timeDelimiter = ':', @@ -73,27 +73,27 @@ public function toDateTime( $this->toDate($dateDelimiter).' ' .$this->toTime($timeDelimiter, $secondDelimiter); } - + public function getHour() { return $this->hour; } - + public function getMinute() { return $this->minute; } - + public function getSecond() { return $this->second; } - + public function equals(Timestamp $timestamp) { return ($this->toDateTime() === $timestamp->toDateTime()); } - + public function getDayStartStamp() { if (!$this->hour && !$this->minute && !$this->second) @@ -106,7 +106,7 @@ public function getHourStartStamp() { if (!$this->minute && !$this->second) return $this->int; - + return mktime( $this->hour, @@ -117,7 +117,7 @@ public function getHourStartStamp() $this->year ); } - + /** * ISO 8601 time string **/ @@ -128,15 +128,7 @@ public function toIsoString($convertToUtc = true) else return date('Y-m-d\TH:i:sO', $this->int); } - - /** - * @param string $format - * @return string - */ - public function toFormatString($format = 'd.m.Y H:i:s') { - return date($format, $this->int); - } - + /** * @return Timestamp **/ @@ -144,19 +136,19 @@ public function toTimestamp() { return $this; } - + protected static function getFormat() { return 'Y-m-d H:i:s'; } - + /* void */ protected function import($string) { list($date, $time) = explode(' ', $string, 2); - + list($this->hour, $this->minute, $this->second) = explode(':', $time, 3); - + $time = sprintf( '%02d:%02d:%02d', @@ -164,19 +156,19 @@ protected static function getFormat() $this->minute, $this->second ); - + list($this->hour, $this->minute, $this->second) = explode(':', $time, 3); - + parent::import($date); - + $this->string .= ' '.$time; } - + /* void */ protected function stringImport($string) { $matches = array(); - + if ( preg_match( '/^(\d{1,4})-(\d{1,2})-(\d{1,2})\s\d{1,2}:\d{1,2}:\d{1,2}$/', @@ -198,7 +190,7 @@ protected static function getFormat() } elseif (($stamp = strtotime($string)) !== false) $this->string = date($this->getFormat(), $stamp); } - + /* void */ protected function buildInteger() { $this->int = diff --git a/core/DB/Dialect.class.php b/core/DB/Dialect.class.php index 1323e24b9f..e0a29dc310 100644 --- a/core/DB/Dialect.class.php +++ b/core/DB/Dialect.class.php @@ -85,6 +85,9 @@ public function typeToString(DataType $type) if ($type->getId() == DataType::IP_RANGE) return 'varchar(41)'; + if ($type->getId() == DataType::UUID) + return 'varchar(36)'; + return $type->getName(); } diff --git a/doc/patches/core_DB_Dialect.diff b/doc/patches/core_DB_Dialect.diff new file mode 100644 index 0000000000..a1b3fc6c36 --- /dev/null +++ b/doc/patches/core_DB_Dialect.diff @@ -0,0 +1,10 @@ +@@ -85,6 +85,9 @@ + if ($type->getId() == DataType::IP_RANGE) + return 'varchar(41)'; + ++ if ($type->getId() == DataType::UUID) ++ return 'varchar(36)'; ++ + return $type->getName(); + } + diff --git a/doc/patches/global-inc.diff b/doc/patches/global-inc.diff new file mode 100644 index 0000000000..b5ed717817 --- /dev/null +++ b/doc/patches/global-inc.diff @@ -0,0 +1,9 @@ +@@ -103,6 +103,8 @@ + .ONPHP_CORE_PATH.'Logic' .PATH_SEPARATOR + .ONPHP_CORE_PATH.'OSQL' .PATH_SEPARATOR + ++ .ONPHP_CORE_PATH.'NoSQL' .PATH_SEPARATOR ++ + // main framework + .ONPHP_MAIN_PATH.'Base' .PATH_SEPARATOR + diff --git a/global.inc.php.tpl b/global.inc.php.tpl index 7ad77d44a9..ea4343c5e2 100644 --- a/global.inc.php.tpl +++ b/global.inc.php.tpl @@ -103,6 +103,8 @@ .ONPHP_CORE_PATH.'Logic' .PATH_SEPARATOR .ONPHP_CORE_PATH.'OSQL' .PATH_SEPARATOR + .ONPHP_CORE_PATH.'NoSQL' .PATH_SEPARATOR + // main framework .ONPHP_MAIN_PATH.'Base' .PATH_SEPARATOR From 99ce1b088c344a3d0419dfdaec60fbc86bfeb39e Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 15 Feb 2012 13:45:56 +0400 Subject: [PATCH 014/418] common fixes --- core/NoSQL/NoSqlDAO.class.php | 2 ++ core/NoSQL/NoSqlObject.class.php | 19 +++++++++++-------- main/Utils/AMQP/AMQPExchangeType.class.php | 4 ++++ main/Utils/UuidUtils.class.php | 4 ++++ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 64edb89411..7d5d968d4c 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -193,6 +193,8 @@ public function add(Identifiable $object) { if( $link instanceof CouchDB ) { $object->setRev($entity['_rev']); } + // проверка добалвения + //$object = $this->getById( $entity['id'] ); return $object; } diff --git a/core/NoSQL/NoSqlObject.class.php b/core/NoSQL/NoSqlObject.class.php index 729c441033..adb1fd11b9 100644 --- a/core/NoSQL/NoSqlObject.class.php +++ b/core/NoSQL/NoSqlObject.class.php @@ -42,19 +42,22 @@ public function toArray() { $entity = array(); /** @var $property LightMetaProperty */ foreach ($this->proto()->getPropertyList() as $property) { - if( $property->isGenericType() || $property->getType()=='enumeration' ) { + // обрабатываем базовые типы + if( $property->isGenericType() ) { $value = call_user_func(array($this, $property->getGetter())); - if( is_object( $value ) ) { - if( $value instanceof Date ) { + if( is_object( $value )&& $value instanceof Date ) { //$value = $value->toStamp(); $value = $value->toString(); - } - if( $value instanceof Enumeration ) { - $value = $value->getId(); - } - } $entity[ $property->getColumnName() ] = $value; + + } // обрабатываем перечисления + elseif( $property->getType()=='enumeration' ) { + $value = call_user_func(array($this, $property->getGetter())); + $entity[ $property->getColumnName() ] = $value = $value->getId(); + } // обрабатываем связи 1к1 + elseif( $property->getType()=='identifier' && $property->getRelationId()==1 ) { + $entity[ $property->getColumnName() ] = call_user_func(array($this, $property->getGetter().'Id')); } } // $entity[ '_id' ] = $this->id; diff --git a/main/Utils/AMQP/AMQPExchangeType.class.php b/main/Utils/AMQP/AMQPExchangeType.class.php index 14410b4f6c..f701db5932 100644 --- a/main/Utils/AMQP/AMQPExchangeType.class.php +++ b/main/Utils/AMQP/AMQPExchangeType.class.php @@ -23,6 +23,10 @@ final class AMQPExchangeType extends Enumeration self::HEADER => "header" ); + public static function create($id) { + return new self($id); + } + public function getDefault() { return self::DIRECT; diff --git a/main/Utils/UuidUtils.class.php b/main/Utils/UuidUtils.class.php index 4657b43f44..6fb79f8e25 100644 --- a/main/Utils/UuidUtils.class.php +++ b/main/Utils/UuidUtils.class.php @@ -39,6 +39,10 @@ public static function assert( $uuid ) { Assert::isUniversalUniqueIdentifier( $uuid ); } + public static function parseHash( $hash ) { + return preg_replace( '/([a-z0-9]{8})([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{12})/iu', '$1-$2-$3-$4-$5', strtolower($hash) ); + } + } From ed20f57ae27caa48e018a88e8ec4e1c502df17d7 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 17 Feb 2012 19:04:42 +0400 Subject: [PATCH 015/418] uuid fix --- main/Utils/UuidUtils.class.php | 2 +- meta/types/UuidType.class.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/main/Utils/UuidUtils.class.php b/main/Utils/UuidUtils.class.php index 6fb79f8e25..0093f66cc3 100644 --- a/main/Utils/UuidUtils.class.php +++ b/main/Utils/UuidUtils.class.php @@ -40,7 +40,7 @@ public static function assert( $uuid ) { } public static function parseHash( $hash ) { - return preg_replace( '/([a-z0-9]{8})([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{12})/iu', '$1-$2-$3-$4-$5', strtolower($hash) ); + return preg_replace( '/([a-f0-9]{8})([a-f0-9]{4})([a-f0-9]{4})([a-f0-9]{4})([a-f0-9]{12})/iu', '$1-$2-$3-$4-$5', strtolower($hash) ); } diff --git a/meta/types/UuidType.class.php b/meta/types/UuidType.class.php index d087cadb9a..b064c3595c 100644 --- a/meta/types/UuidType.class.php +++ b/meta/types/UuidType.class.php @@ -17,7 +17,7 @@ public function getPrimitiveName() { } public function getDeclaration() { - return null; + return 'null'; } public function toColumnType() { From 1d84feae0208e9a7932fb28a8f0a25f18126e6b6 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 17 Feb 2012 20:09:55 +0400 Subject: [PATCH 016/418] AutoDao building fix --- meta/builders/BaseBuilder.class.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meta/builders/BaseBuilder.class.php b/meta/builders/BaseBuilder.class.php index e5cf888aa9..9916d1db8c 100644 --- a/meta/builders/BaseBuilder.class.php +++ b/meta/builders/BaseBuilder.class.php @@ -46,6 +46,8 @@ public function getObjectName() { return '{$class->getName()}'; } + + EOT; From 33af1bf408f3c83da20dd5ce61d74196feef7e47 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Sat, 18 Feb 2012 00:35:57 +0400 Subject: [PATCH 017/418] ManyToMany generation fix --- meta/builders/ContainerClassBuilder.class.php | 14 ++- meta/builders/SchemaBuilder.class.php | 112 +++++++++++++----- 2 files changed, 95 insertions(+), 31 deletions(-) diff --git a/meta/builders/ContainerClassBuilder.class.php b/meta/builders/ContainerClassBuilder.class.php index ddb69a7caf..3d4c75541d 100644 --- a/meta/builders/ContainerClassBuilder.class.php +++ b/meta/builders/ContainerClassBuilder.class.php @@ -63,13 +63,25 @@ public static function create({$className} \${$propertyName}, \$lazy = false) EOT; if ($holder->getRelation()->getId() == MetaRelation::MANY_TO_MANY) { - $out .= <<getTableName(), $remoteColumnName)>=0 ) { + $out .= <<getTableName()}'; +} +EOT; + } else { + $out .= <<getTableName()}_{$remoteColumnName}'; } +EOT; + } + +$out .= <<getRelation() @@ -32,31 +34,31 @@ public static function buildTable($tableName, array $propertyList) ) { continue; } - + $column = $property->toColumn(); - + if (is_array($column)) $columns = array_merge($columns, $column); else $columns[] = $property->toColumn(); } - + $out .= implode("->\n", $columns); - + return $out."\n);\n\n"; } - + public static function buildRelations(MetaClass $class) { $out = null; - + $knownJunctions = array(); - + foreach ($class->getAllProperties() as $property) { if ($relation = $property->getRelation()) { - + $foreignClass = $property->getType()->getClass(); - + if ( $relation->getId() == MetaRelation::ONE_TO_MANY // nothing to build, it's in the same table @@ -69,32 +71,41 @@ public static function buildRelations(MetaClass $class) } elseif ( $relation->getId() == MetaRelation::MANY_TO_MANY ) { - $tableName = - $class->getTableName() - .'_' - .$foreignClass->getTableName(); - - if (isset($knownJunctions[$tableName])) + if( strcmp($class->getTableName(), $foreignClass->getTableName())>=0 ) { + $tableName = + $foreignClass->getTableName() + .'_' + .$class->getTableName(); + } else { + $tableName = + $class->getTableName() + .'_' + .$foreignClass->getTableName(); + } + + if (isset($knownJunctions[$tableName]) || isset(self::$knownTables[$tableName])) continue; // collision prevention - else + else { $knownJunctions[$tableName] = true; - + self::$knownTables[$tableName] = true; + } + $foreignPropery = clone $foreignClass->getIdentifier(); - + $name = $class->getName(); $name = strtolower($name[0]).substr($name, 1); $name .= 'Id'; - + $foreignPropery-> setName($name)-> setColumnName($foreignPropery->getConvertedName())-> // we don't need primary key here setIdentifier(false); - + // we don't want any garbage in such tables $property = clone $property; $property->required(); - + // prevent name collisions if ( $property->getRelationColumnName() @@ -105,7 +116,7 @@ public static function buildRelations(MetaClass $class) .$property->getConvertedName().'_id' ); } - + $out .= << addTable( @@ -117,13 +128,54 @@ public static function buildRelations(MetaClass $class) EOT; + + $sourceColumn = $property->getRelationColumnName(); + $targetTable = $foreignClass->getTableName(); + $targetColumn = $foreignClass->getIdentifier()->getColumnName(); + + $out .= << {$targetTable}.{$targetColumn} +\$schema-> + getTableByName('{$tableName}')-> + getColumnByName('{$sourceColumn}')-> + setReference( + \$schema-> + getTableByName('{$targetTable}')-> + getColumnByName('{$targetColumn}'), + ForeignChangeAction::cascade(), + ForeignChangeAction::cascade() + ); + + +EOT; + + $sourceColumn = $foreignPropery->getRelationColumnName(); + $targetTable = $class->getTableName(); + $targetColumn = $class->getIdentifier()->getColumnName(); + + $out .= << {$targetTable}.{$targetColumn} +\$schema-> + getTableByName('{$tableName}')-> + getColumnByName('{$sourceColumn}')-> + setReference( + \$schema-> + getTableByName('{$targetTable}')-> + getColumnByName('{$targetColumn}'), + ForeignChangeAction::cascade(), + ForeignChangeAction::cascade() + ); + + +EOT; + } else { $sourceTable = $class->getTableName(); $sourceColumn = $property->getRelationColumnName(); - + $targetTable = $foreignClass->getTableName(); $targetColumn = $foreignClass->getIdentifier()->getColumnName(); - + $out .= << {$targetTable}.{$targetColumn} \$schema-> @@ -139,20 +191,20 @@ public static function buildRelations(MetaClass $class) EOT; - + } } } - + return $out; } - + public static function getHead() { $out = parent::getHead(); - + $out .= "\$schema = new DBSchema();\n\n"; - + return $out; } } From 286d9d698dbe0033ba167e094ea351f88b59c0f0 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Sat, 18 Feb 2012 00:58:11 +0400 Subject: [PATCH 018/418] ManyToMany generation fix --- meta/builders/ContainerClassBuilder.class.php | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/meta/builders/ContainerClassBuilder.class.php b/meta/builders/ContainerClassBuilder.class.php index 3d4c75541d..ea9289146d 100644 --- a/meta/builders/ContainerClassBuilder.class.php +++ b/meta/builders/ContainerClassBuilder.class.php @@ -63,25 +63,17 @@ public static function create({$className} \${$propertyName}, \$lazy = false) EOT; if ($holder->getRelation()->getId() == MetaRelation::MANY_TO_MANY) { + $helper_table_name = $class->getTableName().'_'.$remoteColumnName; if( strcmp($class->getTableName(), $remoteColumnName)>=0 ) { + $helper_table_name = $remoteColumnName.'_'.$class->getTableName(); + } $out .= <<getTableName()}'; -} -EOT; - } else { - $out .= <<getTableName()}_{$remoteColumnName}'; + return '{$helper_table_name}'; } -EOT; - } - -$out .= << Date: Mon, 20 Feb 2012 18:16:07 +0400 Subject: [PATCH 019/418] Primitive for ReCaptcha --- core/Form/Primitive.class.php | 13 +- .../Primitives/PrimitiveReCaptcha.class.php | 191 ++++++++++++++++++ 2 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 core/Form/Primitives/PrimitiveReCaptcha.class.php diff --git a/core/Form/Primitive.class.php b/core/Form/Primitive.class.php index 2e945bb24f..41bfd8df25 100644 --- a/core/Form/Primitive.class.php +++ b/core/Form/Primitive.class.php @@ -376,7 +376,7 @@ public static function uuid($name) /** * @static * @param $name - * @return PrimitiveUniversalUniqueIdentifier + * @return PrimitiveUuidIdentifier **/ public static function uuidIdentifier($name) { @@ -386,12 +386,21 @@ public static function uuidIdentifier($name) /** * @static * @param $name - * @return PrimitiveUniversalUniqueIdentifierList + * @return PrimitiveUuidIdentifierList **/ public static function uuidIdentifierList($name) { return new PrimitiveUuidIdentifierList($name); } + /** + * @static + * @return PrimitiveReCaptcha + **/ + public static function reCaptcha() + { + return new PrimitiveReCaptcha(); + } + } ?> \ No newline at end of file diff --git a/core/Form/Primitives/PrimitiveReCaptcha.class.php b/core/Form/Primitives/PrimitiveReCaptcha.class.php new file mode 100644 index 0000000000..ae61f7257d --- /dev/null +++ b/core/Form/Primitives/PrimitiveReCaptcha.class.php @@ -0,0 +1,191 @@ + + * @date 2012.02.20 + */ +class PrimitiveReCaptcha extends BasePrimitive { + + CONST + RECAPTCHA_API_SERVER = 'http://www.google.com/recaptcha/api', + RECAPTCHA_API_SECURE_SERVER = 'https://www.google.com/recaptcha/api', + RECAPTCHA_VERIFY_SERVER = 'www.google.com', + + RECAPTCHA_RESPONSE_FIELD = 'recaptcha_response_field', + RECAPTCHA_CHALLENGE_FIELD = 'recaptcha_challenge_field' + ; + + protected $reCaptchaPrivateKey = null; + + public function __construct() { + $this->name = self::RECAPTCHA_RESPONSE_FIELD; + } + + /** + * @param string $key + * @return PrimitiveReCaptcha + */ + public function setReCaptchaPrivateKey( $key ) { + $this->reCaptchaPrivateKey = $key; + return $this; + } + + public function import($scope) { + if (!BasePrimitive::import($scope)) + return null; + + if (!is_scalar($scope[$this->name])) + return false; + + $this->value = (string) $scope[$this->name]; + + if ( + is_string($this->value) + // zero is quite special value here + && !empty($this->value) + && self::recaptcha_check_answer( + $this->reCaptchaPrivateKey, + $_SERVER["REMOTE_ADDR"], + $_POST[self::RECAPTCHA_CHALLENGE_FIELD], + $this->value + ) + ) { + return true; + } else { + $this->value = null; + } + + return false; + } + + /** + * Encodes the given data into a query string format + * @param $data - array of string elements to be encoded + * @return string - encoded request + */ + protected static function _recaptcha_qsencode ($data) { + $req = ""; + foreach ( $data as $key => $value ) { + $req .= $key . '=' . urlencode( stripslashes($value) ) . '&'; + } + + // Cut the last '&' + $req=substr($req,0,strlen($req)-1); + return $req; + } + + /** + * Submits an HTTP POST to a reCAPTCHA server + * @param string $host + * @param string $path + * @param array $data + * @param int port + * @return array response + */ + protected static function _recaptcha_http_post($host, $path, $data, $port = 80) { + $req = self::_recaptcha_qsencode ($data); + + $http_request = "POST $path HTTP/1.0\r\n"; + $http_request .= "Host: $host\r\n"; + $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n"; + $http_request .= "Content-Length: " . strlen($req) . "\r\n"; + $http_request .= "User-Agent: reCAPTCHA/PHP\r\n"; + $http_request .= "\r\n"; + $http_request .= $req; + + $response = ''; + if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) { + die ('Could not open socket'); + } + + fwrite($fs, $http_request); + + while ( !feof($fs) ) { + $response .= fgets($fs, 1160); // One TCP-IP packet + } + fclose($fs); + $response = explode("\r\n\r\n", $response, 2); + + return $response; + } + + /** + * Gets the challenge HTML (javascript and non-javascript version). + * This is called from the browser, and the resulting reCAPTCHA HTML widget + * is embedded within the HTML form it was called from. + * @param string $pubkey A public key for reCAPTCHA + * @param string $error The error given by reCAPTCHA (optional, default is null) + * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false) + + * @return string - The HTML to be embedded in the user's form. + */ + public static function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false) { + if ($pubkey == null || $pubkey == '') { + die ("To use reCAPTCHA you must get an API key from https://www.google.com/recaptcha/admin/create"); + } + + if ($use_ssl) { + $server = self::RECAPTCHA_API_SECURE_SERVER; + } else { + $server = self::RECAPTCHA_API_SERVER; + } + + $errorpart = ""; + if ($error) { + $errorpart = "&error=" . $error; + } + return ''; + } + + /** + * Calls an HTTP POST function to verify if the user's guess was correct + * @param string $privkey + * @param string $remoteip + * @param string $challenge + * @param string $response + * @param array $extra_params an array of extra variables to post to the server + * @return boolean + */ + protected static function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array()) { + + if ($privkey == null || $privkey == '') { + die ("To use reCAPTCHA you must get an API key from https://www.google.com/recaptcha/admin/create"); + } + + if ($remoteip == null || $remoteip == '') { + die ("For security reasons, you must pass the remote ip to reCAPTCHA"); + } + + //discard spam submissions + if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) { + return false; + } + + $response = + self::_recaptcha_http_post ( + self::RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify", + array ( + 'privatekey' => $privkey, + 'remoteip' => $remoteip, + 'challenge' => $challenge, + 'response' => $response + ) + $extra_params + ); + + $answers = explode ("\n", $response [1]); + + return (trim ($answers [0]) == 'true'); + } + +// protected static function _recaptcha_aes_pad($val) { +// $block_size = 16; +// $numpad = $block_size - (strlen ($val) % $block_size); +// return str_pad($val, strlen ($val) + $numpad, chr($numpad)); +// } + + + + + +} From c0bd0f9c4a349851a742362227f186b5d655d81c Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Mon, 20 Feb 2012 20:10:27 +0400 Subject: [PATCH 020/418] Primitive ReCaptcha fix --- .../Primitives/PrimitiveReCaptcha.class.php | 99 ++++++++----------- 1 file changed, 39 insertions(+), 60 deletions(-) diff --git a/core/Form/Primitives/PrimitiveReCaptcha.class.php b/core/Form/Primitives/PrimitiveReCaptcha.class.php index ae61f7257d..3a9798f68a 100644 --- a/core/Form/Primitives/PrimitiveReCaptcha.class.php +++ b/core/Form/Primitives/PrimitiveReCaptcha.class.php @@ -59,22 +59,6 @@ public function import($scope) { return false; } - /** - * Encodes the given data into a query string format - * @param $data - array of string elements to be encoded - * @return string - encoded request - */ - protected static function _recaptcha_qsencode ($data) { - $req = ""; - foreach ( $data as $key => $value ) { - $req .= $key . '=' . urlencode( stripslashes($value) ) . '&'; - } - - // Cut the last '&' - $req=substr($req,0,strlen($req)-1); - return $req; - } - /** * Submits an HTTP POST to a reCAPTCHA server * @param string $host @@ -84,30 +68,39 @@ protected static function _recaptcha_qsencode ($data) { * @return array response */ protected static function _recaptcha_http_post($host, $path, $data, $port = 80) { - $req = self::_recaptcha_qsencode ($data); - - $http_request = "POST $path HTTP/1.0\r\n"; - $http_request .= "Host: $host\r\n"; - $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n"; - $http_request .= "Content-Length: " . strlen($req) . "\r\n"; - $http_request .= "User-Agent: reCAPTCHA/PHP\r\n"; - $http_request .= "\r\n"; - $http_request .= $req; - - $response = ''; - if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) { - die ('Could not open socket'); + $req = ""; + foreach ( $data as $key => $value ) { + $req .= $key . '=' . urlencode( stripslashes($value) ) . '&'; } + // Cut the last '&' + $req=substr($req,0,strlen($req)-1); - fwrite($fs, $http_request); + $options = array( + CURLOPT_URL => 'http://'.$host.':'.$port.$path, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_USERAGENT => 'reCAPTCHA/PHP', + CURLOPT_HTTPHEADER => array('Content-Type: application/x-www-form-urlencoded', 'Content-Length: '.strlen($req)), + CURLOPT_POSTFIELDS => $req, + CURLOPT_TIMEOUT => 3, + ); - while ( !feof($fs) ) { - $response .= fgets($fs, 1160); // One TCP-IP packet + // переменная под результат + $result = false; + + // делаем запрос + $handler = curl_init(); + curl_setopt_array($handler, $options); + $response = curl_exec($handler); + if( curl_errno($handler)==0 && curl_getinfo($handler, CURLINFO_HTTP_CODE)==200 ) { + $response = explode("\n", $response); + if( isset($response[0]) && trim($response[0])=='true' ) { + $result = true; + } } - fclose($fs); - $response = explode("\r\n\r\n", $response, 2); + curl_close($handler); - return $response; + return $result; } /** @@ -120,7 +113,7 @@ protected static function _recaptcha_http_post($host, $path, $data, $port = 80) * @return string - The HTML to be embedded in the user's form. */ - public static function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false) { + public static function getHtmlCode ($pubkey, $error = null, $use_ssl = false) { if ($pubkey == null || $pubkey == '') { die ("To use reCAPTCHA you must get an API key from https://www.google.com/recaptcha/admin/create"); } @@ -162,30 +155,16 @@ protected static function recaptcha_check_answer ($privkey, $remoteip, $challeng return false; } - $response = - self::_recaptcha_http_post ( - self::RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify", - array ( - 'privatekey' => $privkey, - 'remoteip' => $remoteip, - 'challenge' => $challenge, - 'response' => $response - ) + $extra_params - ); - - $answers = explode ("\n", $response [1]); - - return (trim ($answers [0]) == 'true'); + return + self::_recaptcha_http_post ( + self::RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify", + array ( + 'privatekey' => $privkey, + 'remoteip' => $remoteip, + 'challenge' => $challenge, + 'response' => $response + ) + $extra_params + ); } -// protected static function _recaptcha_aes_pad($val) { -// $block_size = 16; -// $numpad = $block_size - (strlen ($val) % $block_size); -// return str_pad($val, strlen ($val) + $numpad, chr($numpad)); -// } - - - - - } From cf51dc75af1aab84e6c02423d94e85a0ffca91e8 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 22 Feb 2012 17:59:19 +0400 Subject: [PATCH 021/418] AutoDAO builder fix --- meta/builders/BaseBuilder.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/meta/builders/BaseBuilder.class.php b/meta/builders/BaseBuilder.class.php index 9916d1db8c..c5e6627c0b 100644 --- a/meta/builders/BaseBuilder.class.php +++ b/meta/builders/BaseBuilder.class.php @@ -79,7 +79,9 @@ public function getSequence() if ($liaisons = $class->getReferencingClasses()) { $uncachers = array(); foreach ($liaisons as $className) { - $uncachers[] = $className.'::dao()->uncacheLists();'; + if( method_exists($className,'dao') ) { + $uncachers[] = $className.'::dao()->uncacheLists();'; + } } $uncachers = implode("\n", $uncachers); From a6e8f417098f6b75771d68d8579e4c65b918bae0 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 6 Mar 2012 14:20:10 +0400 Subject: [PATCH 022/418] Meta realtions fix --- main/Base/AbstractProtoClass.class.php | 154 +++++++++++------------ meta/classes/MetaClassProperty.class.php | 12 ++ 2 files changed, 89 insertions(+), 77 deletions(-) diff --git a/main/Base/AbstractProtoClass.class.php b/main/Base/AbstractProtoClass.class.php index ebd9169266..63d8a8852c 100644 --- a/main/Base/AbstractProtoClass.class.php +++ b/main/Base/AbstractProtoClass.class.php @@ -17,9 +17,9 @@ abstract class AbstractProtoClass extends Singleton private $depth = 0; private $storage = array(); private $skipList = array(); - + abstract protected function makePropertyList(); - + /** * @return AbstractProtoClass **/ @@ -27,10 +27,10 @@ public function beginPrefetch() { $this->storage[++$this->depth] = array(); $this->skipList[$this->depth] = array(); - + return $this; } - + /** * @return AbstractProtoClass **/ @@ -42,45 +42,45 @@ public function skipObjectPrefetching(Identifiable $object) else ++$this->skipList[$this->depth][$object->getId()]; } - + return $this; } - + public function endPrefetch(array $objectList) { if (!$this->depth) throw new WrongStateException('prefetch mode is already off'); - + foreach ($this->storage[$this->depth] as $setter => $innerList) { Assert::isEqual( count($objectList), count($innerList) + array_sum($this->skipList[$this->depth]) ); - + $ids = array(); - + foreach ($innerList as $inner) if ($inner) $ids[] = $inner->getId(); - + // finding first available inner object foreach ($innerList as $inner) if ($inner) break; - + if (!$inner) continue; - + // put yet unmapped objects into dao's identityMap $inner->dao()->getListByIds($ids); - + $skippedMap = $this->skipList[$this->depth]; - + $i = $j = 0; - + foreach ($objectList as $object) { $objectId = $object->getId(); - + if (isset($skippedMap[$objectId])) { if ($skippedMap[$objectId] == 1) unset($skippedMap[$objectId]); @@ -89,7 +89,7 @@ public function endPrefetch(array $objectList) ++$j; continue; } - + if ($innerList[$i]) { try { // avoid dao "caching" here @@ -106,50 +106,50 @@ public function endPrefetch(array $objectList) ); } } - + ++$i; } - + Assert::isEqual( $i, count($objectList) - $j ); } - + unset($this->skipList[$this->depth], $this->storage[$this->depth--]); - + return $objectList; } - + public static function makeOnlyObject($className, $array, $prefix = null) { return self::assemblyObject(new $className, $array, $prefix); } - + public static function completeObject(Prototyped $object) { return self::fetchEncapsulants($object); } - + final public function getPropertyList() { static $lists = array(); - + $className = get_class($this); - + if (!isset($lists[$className])) { $lists[$className] = $this->makePropertyList(); } - + return $lists[$className]; } - + final public function getExpandedPropertyList($prefix = null) { static $lists = array(); - + $className = get_class($this); - + if (!isset($lists[$className])) { foreach ($this->makePropertyList() as $property) { if ($property instanceof InnerMetaProperty) { @@ -170,10 +170,10 @@ final public function getExpandedPropertyList($prefix = null) } } } - + return $lists[$className]; } - + /** * @return LightMetaProperty * @throws MissingElementException @@ -182,31 +182,31 @@ public function getPropertyByName($name) { if ($property = $this->safePropertyGet($name)) return $property; - + throw new MissingElementException( "unknown property requested by name '{$name}'" ); } - + public function isPropertyExists($name) { return $this->safePropertyGet($name) !== null; } - + /** * @return Form **/ public function makeForm($prefix = null) { $form = Form::create(); - + foreach ($this->getPropertyList() as $property) { $property->fillForm($form, $prefix); } - + return $form; } - + /** * @return InsertOrUpdateQuery **/ @@ -217,16 +217,16 @@ public function fillQuery( foreach ($this->getPropertyList() as $property) { $property->fillQuery($query, $object); } - + return $query; } - + public function getMapping() { static $mappings = array(); - + $className = get_class($this); - + if (!isset($mappings[$className])) { $mapping = array(); foreach ($this->getPropertyList() as $property) { @@ -234,10 +234,10 @@ public function getMapping() } $mappings[$className] = $mapping; } - + return $mappings[$className]; } - + public function importPrimitive( $path, Form $form, @@ -253,7 +253,7 @@ public function importPrimitive( } else { $property = $this->getPropertyByName($path); $getter = $property->getGetter(); - + if ( !$property->isFormless() && ($property->getFetchStrategyId() == FetchStrategy::LAZY) @@ -261,17 +261,17 @@ public function importPrimitive( ) { return $object; } - + $value = $object->$getter(); - + if (!$ignoreNull || ($value !== null)) { $form->importValue($prm->getName(), $value); } } - + return $object; } - + public function exportPrimitive( $path, BasePrimitive $prm, @@ -287,16 +287,16 @@ public function exportPrimitive( $property = $this->getPropertyByName($path); $setter = $property->getSetter(); $value = $prm->getValue(); - + if ( !$ignoreNull || ($value !== null) ) { if ($property->isIdentifier()) { $value = $value->getId(); } - + $dropper = $property->getDropper(); - + if ( ($value === null) && method_exists($object, $dropper) @@ -309,7 +309,7 @@ public function exportPrimitive( ) ) { $object->$dropper(); - + return $object; } elseif ( ( @@ -322,24 +322,24 @@ public function exportPrimitive( ) { if ($value === null) $value = array(); - + $getter = $property->getGetter(); $object->$getter()->setList($value); - + return $object; } - + $object->$setter($value); } } - + return $object; } - + private static function fetchEncapsulants(Prototyped $object) { $proto = $object->proto(); - + foreach ($proto->getPropertyList() as $property) { if ( $property->getRelationId() == MetaRelation::ONE_TO_ONE @@ -347,7 +347,7 @@ private static function fetchEncapsulants(Prototyped $object) ) { $getter = $property->getGetter(); $setter = $property->getSetter(); - + if (($inner = $object->$getter()) instanceof DAOConnected) { if ($proto->depth) $proto->storage[$proto->depth][$setter][] = $inner; @@ -365,10 +365,10 @@ private static function fetchEncapsulants(Prototyped $object) $proto->storage[$proto->depth][$setter][] = null; } } - + return $object; } - + private static function assemblyObject( Prototyped $object, $array, $prefix = null ) @@ -377,12 +377,12 @@ private static function assemblyObject( $dao = $object->dao(); else $dao = null; - + $proto = $object->proto(); - + foreach ($proto->getPropertyList() as $property) { $setter = $property->getSetter(); - + if ($property instanceof InnerMetaProperty) { $object->$setter( $property->toValue($dao, $array, $prefix) @@ -394,21 +394,21 @@ private static function assemblyObject( == FetchStrategy::LAZY ) { $columnName = $prefix.$property->getColumnName(); - + $object-> {$setter.'Id'}($array[$columnName]); - + continue; } } - + $object->$setter($property->toValue($dao, $array, $prefix)); } } - + return $object; } - + private function forwardPrimitive( $path, Form $form = null, @@ -418,13 +418,13 @@ private function forwardPrimitive( ) { list($propertyName, $path) = explode(':', $path, 2); - + $property = $this->getPropertyByName($propertyName); - + Assert::isTrue($property instanceof InnerMetaProperty); - + $getter = $property->getGetter(); - + if ($form) return $property->getProto()->importPrimitive( $path, $form, $prm, $object->$getter(), $ignoreNull @@ -434,14 +434,14 @@ private function forwardPrimitive( $path, $prm, $object->$getter(), $ignoreNull ); } - + private function safePropertyGet($name) { $list = $this->getPropertyList(); - + if (isset($list[$name])) return $list[$name]; - + return null; } } diff --git a/meta/classes/MetaClassProperty.class.php b/meta/classes/MetaClassProperty.class.php index e908083568..cc95901431 100644 --- a/meta/classes/MetaClassProperty.class.php +++ b/meta/classes/MetaClassProperty.class.php @@ -360,6 +360,18 @@ public function toLightProperty(MetaClass $holder) $primitiveName = 'scalarIdentifier'; } else $primitiveName = $this->getType()->getPrimitiveName(); + } elseif ( + $this->getType() instanceof ObjectType + && ($identifier = $this->getType()->getClass()->getIdentifier()) + ) { + if ($identifier->getType() instanceof IntegerType) { + $primitiveName = 'integerIdentifier'; + } elseif ($identifier->getType() instanceof UuidType) { + $primitiveName = 'uuidIdentifier'; + } elseif ($identifier->getType() instanceof StringType) { + $primitiveName = 'scalarIdentifier'; + } else + $primitiveName = $this->getType()->getPrimitiveName(); } else $primitiveName = $this->getType()->getPrimitiveName(); } else From 80e80f606349d063f4211435dbeeb8cdfb19b5d0 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 6 Mar 2012 14:20:23 +0400 Subject: [PATCH 023/418] NoSQL multikey fix --- core/NoSQL/NoSqlDAO.class.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 7d5d968d4c..2f23f4f5b3 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -12,6 +12,8 @@ abstract class NoSqlDAO extends StorableDAO { + const COUCHDB_VIEW_PREFIX = '_design/data/_view/'; + /// single object getters //@{ /** @@ -294,12 +296,29 @@ public function unite( Identifiable $object, Identifiable $old ) { /// object's list getters //@{ - public function getListByView($view, $key, $criteria=null) { + public function getListByView($view, array $keys, $criteria=null) { $params = array(); // parse key switch( get_class($this->getLink()) ) { case 'CouchDB': { + // собираем правильное имя вьюшки + $view = self::COUCHDB_VIEW_PREFIX.$view; + // проверяем что в массиве ключей есть хоть один + if( count($keys)<1 ) { + throw new WrongArgumentException( '$keys must be an array with one or more values' ); + } + // собираем ключи + $key = ''; + if( count($keys)==1 ) { + $key = array_shift($keys); + } else { + foreach($keys as &$val) { + $val = '"'.$val.'"'; + } + $key = '['.implode(',', $keys).']'; + } + $params['key'] = $key; } break; default: { @@ -379,7 +398,7 @@ public function makeNoSqlObject($array, $prefix = null) { * @return NoSQL */ public function getLink() { - return NoSqlPool::me()->getLink( $this->getLinkName() );; + return NoSqlPool::me()->getLink( $this->getLinkName() ); } } From e2c817196919e546b823765de473ce68def33beb Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 6 Mar 2012 14:20:50 +0400 Subject: [PATCH 024/418] Enum function for static creation of child objects --- core/Base/Enumeration.class.php | 44 +++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/core/Base/Enumeration.class.php b/core/Base/Enumeration.class.php index b838c83a36..5a93b49a15 100644 --- a/core/Base/Enumeration.class.php +++ b/core/Base/Enumeration.class.php @@ -11,39 +11,39 @@ /** * Parent of all enumeration classes. - * + * * @see AccessMode for example - * + * * @ingroup Base * @ingroup Module **/ abstract class Enumeration extends NamedObject implements Serializable { protected $names = array(/* override me */); - + final public function __construct($id) { $this->setId($id); } - + /// prevent's serialization of names' array //@{ public function serialize() { return (string) $this->id; } - + public function unserialize($serialized) { $this->setId($serialized); } //@} - + public static function getList(Enumeration $enum) { return $enum->getObjectList(); } - + /** * must return any existent ID * 1 should be ok for most enumerations @@ -52,18 +52,18 @@ public static function getAnyId() { return 1; } - + /// parent's getId() is too complex in our case public function getId() { return $this->id; } - + public function getObjectList() { $list = array(); $names = $this->getNameList(); - + foreach (array_keys($names) as $id) $list[] = new $this($id); @@ -74,12 +74,12 @@ public function toString() { return $this->name; } - + public function getNameList() { return $this->names; } - + /** * @return Enumeration **/ @@ -94,8 +94,26 @@ public function setId($id) throw new MissingElementException( 'knows nothing about such id == '.$id ); - + return $this; } + + /** + * @static + * @return array + */ + public static function makeObjectList() { + $enum = new static( static::getAnyId() ); + return $enum->getObjectList(); + } + + /** + * @static + * @return array + */ + public static function makeNameList() { + $enum = new static( static::getAnyId() ); + return $enum->getNameList(); + } } ?> \ No newline at end of file From 9fcbcd2a9662b774305f14175aec0524991a4f5d Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 6 Mar 2012 19:05:20 +0400 Subject: [PATCH 025/418] nosql pool fix --- core/NoSQL/NoSQLPool.class.php | 140 --------------------------------- 1 file changed, 140 deletions(-) delete mode 100644 core/NoSQL/NoSQLPool.class.php diff --git a/core/NoSQL/NoSQLPool.class.php b/core/NoSQL/NoSQLPool.class.php deleted file mode 100644 index fdd5a05085..0000000000 --- a/core/NoSQL/NoSQLPool.class.php +++ /dev/null @@ -1,140 +0,0 @@ -getLink($dao->getLinkName()); - } - - /** - * @param NoSQL $db - * @return NoSqlPool - */ - public function setDefault(NoSQL $db) - { - $this->default = $db; - - return $this; - } - - /** - * @return NoSqlPool - **/ - public function dropDefault() - { - $this->default = null; - - return $this; - } - - /** - * @param string $name - * @param NoSQL $db - * @return NoSqlPool - * @throws WrongArgumentException - */ - public function addLink($name, NoSQL $db) - { - if (isset($this->pool[$name])) - throw new WrongArgumentException( - "already have '{$name}' link" - ); - - $this->pool[$name] = $db; - - return $this; - } - - /** - * @param string $name - * @return NoSqlPool - * @throws MissingElementException - */ - public function dropLink($name) - { - if (!isset($this->pool[$name])) - throw new MissingElementException( - "link '{$name}' not found" - ); - - unset($this->pool[$name]); - - return $this; - } - - /** - * @param string $name - * @return NoSQL - * @throws MissingElementException - */ - public function getLink($name = null) - { - $link = null; - - // single-NoSQL project - if (!$name) { - if (!$this->default) { - throw new MissingElementException( - 'i have no default link and requested link name is null' - ); - } - - $link = $this->default; - } elseif (isset($this->pool[$name])) { - $link = $this->pool[$name]; - } - // check if found and return - if ($link) { - return $link; - } - - throw new MissingElementException( - "can't find link with '{$name}' name" - ); - } - - /** - * @return NoSqlPool - */ - public function shutdown() - { - $this->default = null; - $this->pool = array(); - - return $this; - } -} -?> \ No newline at end of file From 3f5417c657e27b94d08dd31868b65715fc4542b6 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 6 Mar 2012 19:06:09 +0400 Subject: [PATCH 026/418] nosql pool fix --- core/NoSQL/NoSqlPool.class.php | 140 +++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 core/NoSQL/NoSqlPool.class.php diff --git a/core/NoSQL/NoSqlPool.class.php b/core/NoSQL/NoSqlPool.class.php new file mode 100644 index 0000000000..fdd5a05085 --- /dev/null +++ b/core/NoSQL/NoSqlPool.class.php @@ -0,0 +1,140 @@ +getLink($dao->getLinkName()); + } + + /** + * @param NoSQL $db + * @return NoSqlPool + */ + public function setDefault(NoSQL $db) + { + $this->default = $db; + + return $this; + } + + /** + * @return NoSqlPool + **/ + public function dropDefault() + { + $this->default = null; + + return $this; + } + + /** + * @param string $name + * @param NoSQL $db + * @return NoSqlPool + * @throws WrongArgumentException + */ + public function addLink($name, NoSQL $db) + { + if (isset($this->pool[$name])) + throw new WrongArgumentException( + "already have '{$name}' link" + ); + + $this->pool[$name] = $db; + + return $this; + } + + /** + * @param string $name + * @return NoSqlPool + * @throws MissingElementException + */ + public function dropLink($name) + { + if (!isset($this->pool[$name])) + throw new MissingElementException( + "link '{$name}' not found" + ); + + unset($this->pool[$name]); + + return $this; + } + + /** + * @param string $name + * @return NoSQL + * @throws MissingElementException + */ + public function getLink($name = null) + { + $link = null; + + // single-NoSQL project + if (!$name) { + if (!$this->default) { + throw new MissingElementException( + 'i have no default link and requested link name is null' + ); + } + + $link = $this->default; + } elseif (isset($this->pool[$name])) { + $link = $this->pool[$name]; + } + // check if found and return + if ($link) { + return $link; + } + + throw new MissingElementException( + "can't find link with '{$name}' name" + ); + } + + /** + * @return NoSqlPool + */ + public function shutdown() + { + $this->default = null; + $this->pool = array(); + + return $this; + } +} +?> \ No newline at end of file From 79cdfdab99a8097254d6717fc582be2c6024d95b Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 6 Mar 2012 23:25:27 +0400 Subject: [PATCH 027/418] Primitive Uuidentifier fix --- core/Form/Primitives/PrimitiveUuidIdentifier.class.php | 7 +++++++ core/Form/Primitives/PrimitiveUuidIdentifierList.class.php | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/core/Form/Primitives/PrimitiveUuidIdentifier.class.php b/core/Form/Primitives/PrimitiveUuidIdentifier.class.php index 1eaae310f6..e6c0d21f26 100644 --- a/core/Form/Primitives/PrimitiveUuidIdentifier.class.php +++ b/core/Form/Primitives/PrimitiveUuidIdentifier.class.php @@ -12,6 +12,13 @@ class PrimitiveUuidIdentifier extends PrimitiveIdentifier { + protected $scalar = true; + + public function setScalar($orly = false) + { + throw new WrongStateException(); + } + public function getTypeName() { return 'Uuid'; diff --git a/core/Form/Primitives/PrimitiveUuidIdentifierList.class.php b/core/Form/Primitives/PrimitiveUuidIdentifierList.class.php index 4957a3c5c4..9a8ff9ee35 100644 --- a/core/Form/Primitives/PrimitiveUuidIdentifierList.class.php +++ b/core/Form/Primitives/PrimitiveUuidIdentifierList.class.php @@ -12,8 +12,15 @@ class PrimitiveUuidIdentifierList extends PrimitiveIdentifier { + protected $scalar = true; + protected $value = array(); + public function setScalar($orly = false) + { + throw new WrongStateException(); + } + public function getTypeName() { return 'Uuid'; From 4faf4354083d767778cfe66d11f862846cac0fee Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 7 Mar 2012 13:23:47 +0400 Subject: [PATCH 028/418] Primitive Rule --- core/Form/Primitive.class.php | 9 ++++ core/Form/Primitives/PrimitiveRule.class.php | 48 ++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 core/Form/Primitives/PrimitiveRule.class.php diff --git a/core/Form/Primitive.class.php b/core/Form/Primitive.class.php index 41bfd8df25..80526283b9 100644 --- a/core/Form/Primitive.class.php +++ b/core/Form/Primitive.class.php @@ -402,5 +402,14 @@ public static function reCaptcha() return new PrimitiveReCaptcha(); } + /** + * @return PrimitiveRule + **/ + public static function rule($name) + { + return new PrimitiveRule($name); + } + + } ?> \ No newline at end of file diff --git a/core/Form/Primitives/PrimitiveRule.class.php b/core/Form/Primitives/PrimitiveRule.class.php new file mode 100644 index 0000000000..77d43fae74 --- /dev/null +++ b/core/Form/Primitives/PrimitiveRule.class.php @@ -0,0 +1,48 @@ +form = $form; + + return $this; + } + + /** + * @return PrimitiveRule + **/ + public function setExpression(LogicalObject $exp) + { + $this->expression = $exp; + + return $this; + } + + public function import(array $scope) + { + Assert::isNotNull($this->form); + Assert::isNotNull($this->expression); + + return $this->expression->toBoolean($this->form); + } + } +?> \ No newline at end of file From 2beee40191501c1ba1f477ae0ccf5227ff812079 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 7 Mar 2012 13:25:40 +0400 Subject: [PATCH 029/418] MappedFormField --- core/Form/MappedFormField.class.php | 156 ++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 core/Form/MappedFormField.class.php diff --git a/core/Form/MappedFormField.class.php b/core/Form/MappedFormField.class.php new file mode 100644 index 0000000000..636e01b206 --- /dev/null +++ b/core/Form/MappedFormField.class.php @@ -0,0 +1,156 @@ +map = $value; + + return $this; + } + + /** + * @return string + */ + public function getMap() + { + return $this->map; + } + + /** + * @param bool $isSilent + * @return MappedFormField + */ + public function setSilent($isSilent) + { + $this->isSilent = $isSilent; + return $this; + } + + /** + * @return bool + */ + public function getIsSilent() + { + return $this->isSilent; + } + + /** + * @return array + */ + protected function makeMapChain() + { + Assert::isNotNull( + $this->getMap(), + __METHOD__.': '. + _('you must be set "method"!') + ); + + $chain = array(); + $map = $this->getMap(); + $delimiter = '.'; + + if( mb_strstr($map, $delimiter) !== FALSE ) + { + $chain = explode($delimiter, $map); + } else { + $chain[] = $map; + } + + return $chain; + } + + public function toValue(Form $form) + { + $object = parent::toValue($form); + + if( $object === null ) + return null; + + + Assert::isInstance( + $object, + 'Prototyped', + __METHOD__.': '. + _('value must be instance of Prototyped!') + ); + + $result = $object; + $mapChain = $this->makeMapChain(); + foreach ( $mapChain as $propertyName ) + { + if( + !is_object( $result ) + ) { + if( $this->isSilent ) { + return NULL; + } else { + throw new WrongArgumentException( + __METHOD__.': '. + _('previous property not is a object type!') + ); + } + } + + if( + is_object($result) && + !($result instanceof Prototyped) + ) { + if( $this->isSilent ) { + return NULL; + } else { + throw new WrongArgumentException( + __METHOD__.': '. + _('result must be instance of Prototyped!') + ); + } + } + + + $property = $result->proto()->getPropertyByName( $propertyName ); + $result = call_user_func( + array( + $result, + $property->getGetter() + ) + ); + + } + + return $result; + } + + } From 92f7076b73de74e2c2bde784d6d09fcbeb1d23da Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 7 Mar 2012 13:35:22 +0400 Subject: [PATCH 030/418] FormField is not longer final --- core/Form/FormField.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/Form/FormField.class.php b/core/Form/FormField.class.php index f472d2c6ce..97e59eb865 100644 --- a/core/Form/FormField.class.php +++ b/core/Form/FormField.class.php @@ -11,20 +11,20 @@ /** * Atom for using in LogicalExpression. - * + * * @see DBField - * + * * @ingroup Form **/ - final class FormField + class FormField { private $primitiveName = null; - + public function __construct($name) { $this->primitiveName = $name; } - + /** * @return FormField **/ @@ -37,7 +37,7 @@ public function getName() { return $this->primitiveName; } - + public function toValue(Form $form) { return $form->getValue($this->primitiveName); From dd0c71f5a7936d16101e47173a94a2aeff55af21 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 7 Mar 2012 13:57:22 +0400 Subject: [PATCH 031/418] PrimitiveRule fix --- core/Form/Primitives/PrimitiveRule.class.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/Form/Primitives/PrimitiveRule.class.php b/core/Form/Primitives/PrimitiveRule.class.php index 77d43fae74..131c2910d1 100644 --- a/core/Form/Primitives/PrimitiveRule.class.php +++ b/core/Form/Primitives/PrimitiveRule.class.php @@ -16,32 +16,32 @@ final class PrimitiveRule extends BasePrimitive { private $form = null; private $expression = null; - + /** * @return PrimitiveRule **/ public function setForm(Form $form) { $this->form = $form; - + return $this; } - + /** * @return PrimitiveRule **/ public function setExpression(LogicalObject $exp) { $this->expression = $exp; - + return $this; } - - public function import(array $scope) + + public function import($scope) { Assert::isNotNull($this->form); Assert::isNotNull($this->expression); - + return $this->expression->toBoolean($this->form); } } From 150a41fbdbc314acefa2a2c03582faf6bed64647 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 7 Mar 2012 15:34:55 +0400 Subject: [PATCH 032/418] PrimitiveRule and MappedFormField fix --- core/Form/Form.class.php | 170 ++++++++++--------- core/Form/Primitives/PrimitiveRule.class.php | 3 + core/Logic/BinaryExpression.class.php | 38 ++--- 3 files changed, 108 insertions(+), 103 deletions(-) diff --git a/core/Form/Form.class.php b/core/Form/Form.class.php index b4c9077823..9b380deb53 100644 --- a/core/Form/Form.class.php +++ b/core/Form/Form.class.php @@ -11,25 +11,25 @@ /** * Complete Form class. - * + * * @ingroup Form * @ingroup Module - * + * * @see http://onphp.org/examples.Form.en.html **/ final class Form extends RegulatedForm { const WRONG = 0x0001; const MISSING = 0x0002; - + private $errors = array(); private $labels = array(); private $describedLabels = array(); - + private $proto = null; - + private $importFiltering = true; - + /** * @return Form **/ @@ -37,18 +37,18 @@ public static function create() { return new self; } - + public function getErrors() { return array_merge($this->errors, $this->violated); } - + public function hasError($name) { return array_key_exists($name, $this->errors) || array_key_exists($name, $this->violated); } - + public function getError($name) { if (array_key_exists($name, $this->errors)) { @@ -58,11 +58,11 @@ public function getError($name) } return null; } - + public function getInnerErrors() { $result = $this->getErrors(); - + foreach ($this->primitives as $name => $prm) { if ( ( @@ -78,10 +78,10 @@ public function getInnerErrors() } } } - + return $result; } - + /** * @return Form **/ @@ -89,30 +89,30 @@ public function dropAllErrors() { $this->errors = array(); $this->violated = array(); - + return $this; } - + /** * @return Form **/ public function enableImportFiltering() { $this->importFiltering = true; - + return $this; } - + /** * @return Form **/ public function disableImportFiltering() { $this->importFiltering = false; - + return $this; } - + /** * primitive marking **/ @@ -124,10 +124,10 @@ public function markMissing($primitiveName) { return $this->markCustom($primitiveName, Form::MISSING); } - + /** * rule or primitive - * + * * @return Form **/ public function markWrong($name) @@ -140,10 +140,10 @@ public function markWrong($name) throw new MissingElementException( $name.' does not match known primitives or rules' ); - + return $this; } - + /** * @return Form **/ @@ -157,40 +157,40 @@ public function markGood($primitiveName) throw new MissingElementException( $primitiveName.' does not match known primitives or rules' ); - + return $this; } - + /** * Set's custom error mark for primitive. - * + * * @return Form **/ public function markCustom($primitiveName, $customMark) { Assert::isInteger($customMark); - + $this->errors[$this->get($primitiveName)->getName()] = $customMark; - + return $this; } //@} - + /** * Returns plain list of error's labels **/ public function getTextualErrors() { $list = array(); - + foreach (array_keys($this->labels) as $name) { if ($label = $this->getTextualErrorFor($name)) $list[] = $label; } - + return $list; } - + public function getTextualErrorFor($name) { if ( @@ -210,7 +210,7 @@ public function getTextualErrorFor($name) else return null; } - + public function getErrorDescriptionFor($name) { if ( @@ -230,13 +230,13 @@ public function getErrorDescriptionFor($name) else return null; } - + /** * @return Form **/ public function addErrorDescription($name, $errorType, $description) { - + if ( !isset($this->rules[$name]) && !$this->get($name)->getName() @@ -244,12 +244,12 @@ public function addErrorDescription($name, $errorType, $description) throw new MissingElementException( "knows nothing about '{$name}'" ); - + $this->describedLabels[$name][$errorType] = $description; - + return $this; } - + /** * @return Form **/ @@ -257,7 +257,7 @@ public function addWrongLabel($primitiveName, $label) { return $this->addErrorLabel($primitiveName, Form::WRONG, $label); } - + /** * @return Form **/ @@ -265,7 +265,7 @@ public function addMissingLabel($primitiveName, $label) { return $this->addErrorLabel($primitiveName, Form::MISSING, $label); } - + /** * @return Form **/ @@ -273,17 +273,17 @@ public function addCustomLabel($primitiveName, $customMark, $label) { return $this->addErrorLabel($primitiveName, $customMark, $label); } - + public function getWrongLabel($primitiveName) { return $this->getErrorLabel($primitiveName, Form::WRONG); } - + public function getMissingLabel($primitiveName) { return $this->getErrorLabel($primitiveName, Form::MISSING); } - + /** * @return Form **/ @@ -291,10 +291,10 @@ public function import($scope) { foreach ($this->primitives as $prm) $this->importPrimitive($scope, $prm); - + return $this; } - + /** * @return Form **/ @@ -304,10 +304,10 @@ public function importMore($scope) if (!$prm->isImported()) $this->importPrimitive($scope, $prm); } - + return $this; } - + /** * @return Form **/ @@ -315,67 +315,69 @@ public function importOne($primitiveName, $scope) { return $this->importPrimitive($scope, $this->get($primitiveName)); } - + /** * @return Form **/ public function importValue($primitiveName, $value) { $prm = $this->get($primitiveName); - + return $this->checkImportResult($prm, $prm->importValue($value)); } - + /** * @return Form **/ public function importOneMore($primitiveName, $scope) { $prm = $this->get($primitiveName); - + if (!$prm->isImported()) return $this->importPrimitive($scope, $prm); - + return $this; } - + public function exportValue($primitiveName) { return $this->get($primitiveName)->exportValue(); } - + public function export() { $result = array(); - + foreach ($this->primitives as $name => $prm) { if ($prm->isImported()) $result[$name] = $prm->exportValue(); } - + return $result; } - + public function toFormValue($value) { - if ($value instanceof FormField) + if( $value instanceof MappedFormField ) + return $value->toValue($this); + elseif ($value instanceof FormField) return $this->getValue($value->getName()); elseif ($value instanceof LogicalObject) return $value->toBoolean($this); else return $value; } - + /** * @return Form **/ public function setProto(EntityProto $proto) { $this->proto = $proto; - + return $this; } - + /** * @return EntityProto **/ @@ -383,7 +385,7 @@ public function getProto() { return $this->proto; } - + /** * @return Form **/ @@ -391,20 +393,20 @@ private function importPrimitive($scope, BasePrimitive $prm) { if (!$this->importFiltering) { if ($prm instanceof FiltrablePrimitive) { - + $chain = $prm->getImportFilter(); - + $prm->dropImportFilters(); - + $result = $this->checkImportResult( $prm, $prm->import($scope) ); - + $prm->setImportFilter($chain); - + return $result; - + } elseif ($prm instanceof PrimitiveForm) { return $this->checkImportResult( $prm, @@ -412,10 +414,10 @@ private function importPrimitive($scope, BasePrimitive $prm) ); } } - + return $this->checkImportResult($prm, $prm->import($scope)); } - + /** * @return Form **/ @@ -426,30 +428,30 @@ private function checkImportResult(BasePrimitive $prm, $result) && $result !== null ) $this->markGood($prm->getInner()->getName()); - + $name = $prm->getName(); - + if (null === $result) { if ($prm->isRequired()) $this->errors[$name] = self::MISSING; - + } elseif (true === $result) { unset($this->errors[$name]); - + } elseif ($error = $prm->getCustomError()) { - + $this->errors[$name] = $error; - + } else $this->errors[$name] = self::WRONG; - + return $this; } - + /** * Assigns specific label for given primitive and error type. * One more example of horrible documentation style. - * + * * @param $name string primitive or rule name * @param $errorType enum Form::(WRONG|MISSING) * @param $label string YDFB WTF is this :-) (c) /. @@ -465,20 +467,20 @@ private function addErrorLabel($name, $errorType, $label) throw new MissingElementException( "knows nothing about '{$name}'" ); - + $this->labels[$name][$errorType] = $label; - + return $this; } - + private function getErrorLabel($name, $errorType) { // checks for primitive's existence $this->get($name); - + if (isset($this->labels[$name][$errorType])) return $this->labels[$name][$errorType]; - + return null; } } diff --git a/core/Form/Primitives/PrimitiveRule.class.php b/core/Form/Primitives/PrimitiveRule.class.php index 131c2910d1..9d5bbdfbcc 100644 --- a/core/Form/Primitives/PrimitiveRule.class.php +++ b/core/Form/Primitives/PrimitiveRule.class.php @@ -14,7 +14,10 @@ **/ final class PrimitiveRule extends BasePrimitive { + /** @var Form */ private $form = null; + + /** @var BinaryExpression */ private $expression = null; /** diff --git a/core/Logic/BinaryExpression.class.php b/core/Logic/BinaryExpression.class.php index 921ea21a9e..a779b5ace6 100644 --- a/core/Logic/BinaryExpression.class.php +++ b/core/Logic/BinaryExpression.class.php @@ -16,7 +16,7 @@ final class BinaryExpression implements LogicalObject, MappableObject { const EQUALS = '='; const NOT_EQUALS = '!='; - + const EXPRESSION_AND = 'AND'; const EXPRESSION_OR = 'OR'; @@ -33,39 +33,39 @@ final class BinaryExpression implements LogicalObject, MappableObject const SIMILAR_TO = 'SIMILAR TO'; const NOT_SIMILAR_TO = 'NOT SIMILAR TO'; - + const ADD = '+'; const SUBSTRACT = '-'; const MULTIPLY = '*'; const DIVIDE = '/'; const MOD = '%'; - + private $left = null; private $right = null; private $logic = null; - + public function __construct($left, $right, $logic) { $this->left = $left; $this->right = $right; $this->logic = $logic; } - + public function getLeft() { return $this->left; } - + public function getRight() { return $this->right; } - + public function getLogic() { return $this->logic; } - + public function toDialectString(Dialect $dialect) { return @@ -75,7 +75,7 @@ public function toDialectString(Dialect $dialect) .$dialect->toValueString($this->right) .')'; } - + /** * @return BinaryExpression **/ @@ -87,16 +87,16 @@ public function toMapped(ProtoDAO $dao, JoinCapableQuery $query) $this->logic ); } - + public function toBoolean(Form $form) { $left = $form->toFormValue($this->left); $right = $form->toFormValue($this->right); - + $both = (null !== $left) && (null !== $right); - + switch ($this->logic) { case self::EQUALS: return $both && ($left == $right); @@ -118,25 +118,25 @@ public function toBoolean(Form $form) case self::EXPRESSION_AND: return $both && ($left && $right); - + case self::EXPRESSION_OR: return $both && ($left || $right); - + case self::ADD: return $both && ($left + $right); - + case self::SUBSTRACT: return $both && ($left - $right); - + case self::MULTIPLY: return $both && ($left * $right); - + case self::DIVIDE: return $both && $right && ($left / $right); - + case self::MOD: return $both && $right && ($left % $right); - + default: throw new UnsupportedMethodException( "'{$this->logic}' doesn't supported yet" From d80b33277b61aeafa11fc3a38d0eb8ebce297f35 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Sat, 10 Mar 2012 11:12:29 +0400 Subject: [PATCH 033/418] CouchDB fix --- core/NoSQL/CouchDB.class.php | 40 ++++++++++--------- meta/builders/ContainerClassBuilder.class.php | 2 +- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/core/NoSQL/CouchDB.class.php b/core/NoSQL/CouchDB.class.php index 85f7f43fa4..531c837ee2 100644 --- a/core/NoSQL/CouchDB.class.php +++ b/core/NoSQL/CouchDB.class.php @@ -19,11 +19,18 @@ **/ class CouchDB extends NoSQL { + // methods + const + GET = 1, + POST = 2, + PUT = 3, + DELETE = 4; + // credentials protected $port = 5984; // quering - protected $_methods = array( 'get'=>'get', 'post'=>'post', 'put'=>'put', 'delete'=>'delete' ); + protected $_methods = array( self::GET=>self::GET, self::POST=>self::POST, self::PUT=>self::PUT, self::DELETE=>self::DELETE ); public function __construct() { @@ -55,7 +62,7 @@ public function select() { Assert::isString($id); Assert::isNotEmpty($id); - return $this->exec( $this->getUrl($dbname, $id), 'get' ); + return $this->exec( $this->getUrl($dbname, $id), self::GET ); } /** @@ -86,7 +93,7 @@ public function insert() { $id = $object['id']; unset( $object['id'] ); - $response = $this->exec( $this->getUrl($dbname, $id), 'put', json_encode($object) ); + $response = $this->exec( $this->getUrl($dbname, $id), self::PUT, json_encode($object) ); $object['id'] = $response['id']; $object['_rev'] = $response['rev']; return $object; @@ -126,7 +133,7 @@ public function update() { // add rev $object['_rev'] = $rev; - $response = $this->exec( $this->getUrl($dbname, $id), 'put', json_encode($object) ); + $response = $this->exec( $this->getUrl($dbname, $id), self::PUT, json_encode($object) ); $object['id'] = $response['id']; $object['_rev'] = $response['rev']; return $object; @@ -160,7 +167,7 @@ public function delete() { Assert::isString($rev); Assert::isNotEmpty($rev); - $response = $this->exec( $this->getUrl($dbname, $id, array('rev'=>$rev)), 'delete' ); + $response = $this->exec( $this->getUrl($dbname, $id, array('rev'=>$rev)), self::DELETE ); return $response['ok'] ? 1 : 0; } @@ -183,7 +190,7 @@ public function getAllObjects() { Assert::isString($dbname); Assert::isNotEmpty($dbname); - $response = $this->exec( $this->getUrl($dbname, '_all_docs'), 'get' ); + $response = $this->exec( $this->getUrl($dbname, '_all_docs'), self::GET ); $list = array(); if( isset($response['total_rows']) && isset($response['rows']) ) { $list = $response['rows']; @@ -210,7 +217,7 @@ public function getTotalCount() { Assert::isString($dbname); Assert::isNotEmpty($dbname); - $response = $this->exec( $this->getUrl($dbname, '_all_docs'), 'post', '{"keys":[]}' ); + $response = $this->exec( $this->getUrl($dbname, '_all_docs'), self::POST, '{"keys":[]}' ); $count = 0; if( isset($response['total_rows']) ) { $count = $response['total_rows']; @@ -253,7 +260,7 @@ public function getCustomList() { } //die( $this->getUrl($dbname, $view, $params) ); - $response = $this->exec( $this->getUrl($dbname, $view, $params), 'get' ); + $response = $this->exec( $this->getUrl($dbname, $view, $params), self::GET ); $list = array(); if( isset($response['total_rows']) && isset($response['rows']) ) { $list = $response['rows']; @@ -298,7 +305,7 @@ public function getCustomData() { $params['reduce'] = 'false'; // query - $response = $this->exec( $this->getUrl($dbname, $view, $params), 'get' ); + $response = $this->exec( $this->getUrl($dbname, $view, $params), self::GET ); $result = null; if( isset($response['rows']) ) { $result = $response['value']; @@ -315,11 +322,8 @@ public function obtainSequence($sequence) { ) { return UuidUtils::generate(); } else { - $request = $this->makeRequest('_uuids')->setMethod( HttpMethod::get() ); - $response = $this->makeCurlClient()->send( $request ); - $result = json_decode( $response->getBody(), true ); - $this->checkErrors( $result ); - return array_shift( $result ); + $response = $this->exec( $this->getUrl('_uuids'), self::GET ); + return array_shift( $response ); } } @@ -391,20 +395,20 @@ protected function exec( $url, $method, $data=null ) { } switch( $method ) { - case $this->_methods['get']: { + case self::GET: { $options[CURLOPT_HTTPGET] = true; } break; - case $this->_methods['post']: { + case self::POST: { $options[CURLOPT_CUSTOMREQUEST] = 'POST'; $options[CURLOPT_POSTFIELDS] = $data; $options[CURLOPT_HTTPHEADER] = array( 'Content-type: application/json' ); } break; - case $this->_methods['put']: { + case self::PUT: { $options[CURLOPT_CUSTOMREQUEST] = 'PUT'; $options[CURLOPT_POSTFIELDS] = $data; $options[CURLOPT_HTTPHEADER] = array( 'Content-type: application/json' ); } break; - case $this->_methods['delete']: { + case self::DELETE: { $options[CURLOPT_CUSTOMREQUEST] = 'DELETE'; } break; } diff --git a/meta/builders/ContainerClassBuilder.class.php b/meta/builders/ContainerClassBuilder.class.php index ea9289146d..72cce62502 100644 --- a/meta/builders/ContainerClassBuilder.class.php +++ b/meta/builders/ContainerClassBuilder.class.php @@ -96,7 +96,7 @@ public function getParentIdField() protected function getViewName() { - return '_design/{$holder->getName()}/_view/getBy{$class->getName()}Id'; + return '_design/data/_view/getBy{$class->getName()}Id'; } EOT; From 243e3b5b0c1839d70b3bf4fb4f2f4e55305f2194 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Mon, 12 Mar 2012 14:34:27 +0400 Subject: [PATCH 034/418] NoSQL fix --- core/NoSQL/CouchDB.class.php | 4 ++-- core/NoSQL/NoSqlDAO.class.php | 2 +- core/NoSQL/NoSqlObject.class.php | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/core/NoSQL/CouchDB.class.php b/core/NoSQL/CouchDB.class.php index 531c837ee2..b6e7c04de5 100644 --- a/core/NoSQL/CouchDB.class.php +++ b/core/NoSQL/CouchDB.class.php @@ -62,7 +62,7 @@ public function select() { Assert::isString($id); Assert::isNotEmpty($id); - return $this->exec( $this->getUrl($dbname, $id), self::GET ); + return $this->exec( $this->getUrl($dbname, $id), self::GET ); } /** @@ -340,7 +340,7 @@ protected function getUrl( $dbname, $path=null, array $params=null ) { if( !empty($dbname) ) { $urlPath .= $dbname; if( !empty($path) ) { - $urlPath .= '/'.$path; + $urlPath .= '/'.urlencode($path); } } diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 2f23f4f5b3..5286d6b19c 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -379,7 +379,7 @@ public function makeNoSqlObject($array, $prefix = null) { $object = null; if( $this->getLink() instanceof CouchDB ) { - $array['id'] = $array['_id']; + $array['id'] = urldecode($array['_id']); unset( $array['_id'] ); } diff --git a/core/NoSQL/NoSqlObject.class.php b/core/NoSQL/NoSqlObject.class.php index adb1fd11b9..4b7aac527a 100644 --- a/core/NoSQL/NoSqlObject.class.php +++ b/core/NoSQL/NoSqlObject.class.php @@ -22,6 +22,8 @@ class NoSqlObject extends IdentifiableObject { */ protected $_rev = null; + protected $identifiers = array('identifier', 'integerIdentifier', 'scalarIdentifier', 'uuidIdentifier'); + /** * @param $rev * @return NoSqlObject @@ -56,7 +58,7 @@ public function toArray() { $value = call_user_func(array($this, $property->getGetter())); $entity[ $property->getColumnName() ] = $value = $value->getId(); } // обрабатываем связи 1к1 - elseif( $property->getType()=='identifier' && $property->getRelationId()==1 ) { + elseif( in_array($property->getType(), $this->identifiers) && $property->getRelationId()==1 ) { $entity[ $property->getColumnName() ] = call_user_func(array($this, $property->getGetter().'Id')); } } From c791bb32936983fae0e0e08ef93c1e4b2b5bb735 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Mon, 12 Mar 2012 17:05:14 +0400 Subject: [PATCH 035/418] NoSqlObject to JSON fix --- core/NoSQL/NoSqlObject.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/NoSQL/NoSqlObject.class.php b/core/NoSQL/NoSqlObject.class.php index 4b7aac527a..b098bdcba6 100644 --- a/core/NoSQL/NoSqlObject.class.php +++ b/core/NoSQL/NoSqlObject.class.php @@ -48,8 +48,8 @@ public function toArray() { if( $property->isGenericType() ) { $value = call_user_func(array($this, $property->getGetter())); if( is_object( $value )&& $value instanceof Date ) { - //$value = $value->toStamp(); - $value = $value->toString(); + $value = $value->toStamp(); + //$value = $value->toString(); } $entity[ $property->getColumnName() ] = $value; From 189188c6542106df69e0ff1aaf7b338460bd9070 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 13 Mar 2012 12:36:18 +0400 Subject: [PATCH 036/418] urlencode for couchdb fix --- core/NoSQL/CouchDB.class.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/NoSQL/CouchDB.class.php b/core/NoSQL/CouchDB.class.php index b6e7c04de5..26ba3fd783 100644 --- a/core/NoSQL/CouchDB.class.php +++ b/core/NoSQL/CouchDB.class.php @@ -90,7 +90,7 @@ public function insert() { // remove id - $id = $object['id']; + $id = urlencode($object['id']); unset( $object['id'] ); $response = $this->exec( $this->getUrl($dbname, $id), self::PUT, json_encode($object) ); @@ -128,7 +128,7 @@ public function update() { Assert::isNotEmpty($rev); // remove id - $id = $object['id']; + $id = urlencode($object['id']); unset( $object['id'] ); // add rev $object['_rev'] = $rev; @@ -154,7 +154,7 @@ public function delete() { // parse args $dbname = func_get_arg(0); - $id = func_get_arg(1); + $id = urlencode(func_get_arg(1)); $rev = func_get_arg(2); // checking dbname @@ -340,7 +340,7 @@ protected function getUrl( $dbname, $path=null, array $params=null ) { if( !empty($dbname) ) { $urlPath .= $dbname; if( !empty($path) ) { - $urlPath .= '/'.urlencode($path); + $urlPath .= '/'.$path; } } @@ -385,6 +385,7 @@ protected function exec( $url, $method, $data=null ) { $options = array( CURLOPT_RETURNTRANSFER => true, CURLINFO_HEADER_OUT => true, + //CURLOPT_FOLLOWLOCATION => true, CURLOPT_URL => $url, CURLOPT_PORT => $this->port, CURLOPT_USERAGENT => 'onPHP::'.__CLASS__ @@ -466,10 +467,10 @@ protected function exec( $url, $method, $data=null ) { throw new NoSQLException( 'Unauthorized' ); } break; case 500: { - throw new NoSQLException( 'CouchDB server error' ); + throw new NoSQLException( 'CouchDB server error: '.var_export($response, true) ); } break; default: { - die('NOSQL FATAL!!!'); + throw new NoSQLException( 'CouchDB fatal error. Code: '.$status.' Info:'.var_export($response, true) ); } break; } From 97e925f38c376020030f8c670dcb1d7a764b35de Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 13 Mar 2012 16:37:32 +0400 Subject: [PATCH 037/418] Another NoSQL fix --- core/NoSQL/CouchDB.class.php | 2 +- core/NoSQL/NoSqlDAO.class.php | 24 +++++++++++-------- meta/builders/ContainerClassBuilder.class.php | 7 +++++- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/core/NoSQL/CouchDB.class.php b/core/NoSQL/CouchDB.class.php index 26ba3fd783..722bbff624 100644 --- a/core/NoSQL/CouchDB.class.php +++ b/core/NoSQL/CouchDB.class.php @@ -449,7 +449,7 @@ protected function exec( $url, $method, $data=null ) { throw new ObjectNotFoundException( $reason ); } break; case 405: { - throw new NoSQLException( 'Resource Not Allowed' ); + throw new NoSQLException( 'Resource Not Allowed, url: '.$url ); } break; case 406: { throw new NoSQLException( 'Not Acceptable' ); diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 5286d6b19c..aa15080fb4 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -296,7 +296,7 @@ public function unite( Identifiable $object, Identifiable $old ) { /// object's list getters //@{ - public function getListByView($view, array $keys, $criteria=null) { + public function getListByView($view, $keys, $criteria=null) { $params = array(); // parse key @@ -304,19 +304,23 @@ public function getListByView($view, array $keys, $criteria=null) { case 'CouchDB': { // собираем правильное имя вьюшки $view = self::COUCHDB_VIEW_PREFIX.$view; - // проверяем что в массиве ключей есть хоть один - if( count($keys)<1 ) { - throw new WrongArgumentException( '$keys must be an array with one or more values' ); - } // собираем ключи $key = ''; - if( count($keys)==1 ) { - $key = array_shift($keys); + if( !is_array($keys) ) { + $key = $keys; } else { - foreach($keys as &$val) { - $val = '"'.$val.'"'; + // проверяем что в массиве ключей есть хоть один + if( count($keys)<1 ) { + throw new WrongArgumentException( '$keys must be an array with one or more values' ); + } + if( count($keys)==1 ) { + $key = array_shift($keys); + } else { + foreach($keys as &$val) { + $val = '"'.$val.'"'; + } + $key = '['.implode(',', $keys).']'; } - $key = '['.implode(',', $keys).']'; } $params['key'] = $key; diff --git a/meta/builders/ContainerClassBuilder.class.php b/meta/builders/ContainerClassBuilder.class.php index 72cce62502..e44a9ad5f3 100644 --- a/meta/builders/ContainerClassBuilder.class.php +++ b/meta/builders/ContainerClassBuilder.class.php @@ -94,9 +94,14 @@ public function getParentIdField() if ($isNoSQL) { $out .= <<getName()}Id'; + return 'getBy{$class->getName()}Id'; } EOT; From 60dda3de7b7edc662a767ccde898f552bf6a25b7 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 13 Mar 2012 20:28:29 +0400 Subject: [PATCH 038/418] PgSQL profiler --- core/DB/PgSQL.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/core/DB/PgSQL.class.php b/core/DB/PgSQL.class.php index f9d704c6f0..109cb69441 100644 --- a/core/DB/PgSQL.class.php +++ b/core/DB/PgSQL.class.php @@ -115,6 +115,7 @@ public function setDbEncoding() public function queryRaw($queryString) { + if( defined('DB_PROFILE_LOG') ) { file_put_contents(DB_PROFILE_LOG, $queryString."\n", FILE_APPEND); } try { return pg_query($this->link, $queryString); } catch (BaseException $e) { From 41a3b54fc199e9d117f16f705969cf825e2be49f Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 14 Mar 2012 14:15:16 +0400 Subject: [PATCH 039/418] Enum fix --- core/Base/Enumeration.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/Base/Enumeration.class.php b/core/Base/Enumeration.class.php index 5a93b49a15..e52fc90ffa 100644 --- a/core/Base/Enumeration.class.php +++ b/core/Base/Enumeration.class.php @@ -65,7 +65,7 @@ public function getObjectList() $names = $this->getNameList(); foreach (array_keys($names) as $id) - $list[] = new $this($id); + $list[$id] = new $this($id); return $list; } From 06365ce69a07f3970789c30b47cf693146c64223 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 16 Mar 2012 14:10:27 +0400 Subject: [PATCH 040/418] NoSQL CouchDB fix --- core/NoSQL/CouchDB.class.php | 4 +++- core/NoSQL/NoSqlDAO.class.php | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/core/NoSQL/CouchDB.class.php b/core/NoSQL/CouchDB.class.php index 722bbff624..ca9d9a1e87 100644 --- a/core/NoSQL/CouchDB.class.php +++ b/core/NoSQL/CouchDB.class.php @@ -59,7 +59,7 @@ public function select() { Assert::isString($dbname); Assert::isNotEmpty($dbname); // checking id - Assert::isString($id); + Assert::isScalar($id); Assert::isNotEmpty($id); return $this->exec( $this->getUrl($dbname, $id), self::GET ); @@ -473,6 +473,8 @@ protected function exec( $url, $method, $data=null ) { throw new NoSQLException( 'CouchDB fatal error. Code: '.$status.' Info:'.var_export($response, true) ); } break; } + // closing + curl_close($ch); return $answer; } diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index aa15080fb4..0615181dd8 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -317,12 +317,15 @@ public function getListByView($view, $keys, $criteria=null) { $key = array_shift($keys); } else { foreach($keys as &$val) { - $val = '"'.$val.'"'; + if( is_null($val) ) { + $val = 'null'; + } else { + $val = '"'.$val.'"'; + } } $key = '['.implode(',', $keys).']'; } } - $params['key'] = $key; } break; default: { From 6abbfb46ca0c18b93a1cb58293dd5c7da82fd1e8 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 16 Mar 2012 14:10:43 +0400 Subject: [PATCH 041/418] NoSQL Riak files --- core/NoSQL/Riak/RiakBucket.class.php | 312 +++++++ core/NoSQL/Riak/RiakClient.class.php | 195 +++++ core/NoSQL/Riak/RiakLink.class.php | 120 +++ core/NoSQL/Riak/RiakLinkPhase.class.php | 30 + core/NoSQL/Riak/RiakMapReduce.class.php | 274 +++++++ core/NoSQL/Riak/RiakMapReducePhase.class.php | 50 ++ core/NoSQL/Riak/RiakObject.class.php | 815 +++++++++++++++++++ core/NoSQL/Riak/RiakStringIO.class.php | 19 + core/NoSQL/Riak/RiakUtils.class.php | 189 +++++ global.inc.php.tpl | 81 +- 10 files changed, 2045 insertions(+), 40 deletions(-) create mode 100644 core/NoSQL/Riak/RiakBucket.class.php create mode 100644 core/NoSQL/Riak/RiakClient.class.php create mode 100644 core/NoSQL/Riak/RiakLink.class.php create mode 100644 core/NoSQL/Riak/RiakLinkPhase.class.php create mode 100644 core/NoSQL/Riak/RiakMapReduce.class.php create mode 100644 core/NoSQL/Riak/RiakMapReducePhase.class.php create mode 100644 core/NoSQL/Riak/RiakObject.class.php create mode 100644 core/NoSQL/Riak/RiakStringIO.class.php create mode 100644 core/NoSQL/Riak/RiakUtils.class.php diff --git a/core/NoSQL/Riak/RiakBucket.class.php b/core/NoSQL/Riak/RiakBucket.class.php new file mode 100644 index 0000000000..9119400051 --- /dev/null +++ b/core/NoSQL/Riak/RiakBucket.class.php @@ -0,0 +1,312 @@ +client = $client; + $this->name = $name; + $this->r = NULL; + $this->w = NULL; + $this->dw = NULL; + } + + /** + * Get the bucket name. + */ + function getName() { + return $this->name; + } + + /** + * Get the R-value for this bucket, if it is set, otherwise return + * the R-value for the client. + * @return integer + */ + function getR($r=NULL) { + if ($r != NULL) return $r; + if ($this->r != NULL) return $this->r; + return $this->client->getR(); + } + + /** + * Set the R-value for this bucket. get(...) and getBinary(...) + * operations that do not specify an R-value will use this value. + * @param integer $r - The new R-value. + * @return $this + */ + function setR($r) { + $this->r = $r; + return $this; + } + + /** + * Get the W-value for this bucket, if it is set, otherwise return + * the W-value for the client. + * @return integer + */ + function getW($w) { + if ($w != NULL) return $w; + if ($this->w != NULL) return $this->w; + return $this->client->getW(); + } + + /** + * Set the W-value for this bucket. See setR(...) for more information. + * @param integer $w - The new W-value. + * @return $this + */ + function setW($w) { + $this->w = $w; + return $this; + } + + /** + * Get the DW-value for this bucket, if it is set, otherwise return + * the DW-value for the client. + * @return integer + */ + function getDW($dw) { + if ($dw != NULL) return $dw; + if ($this->dw != NULL) return $this->dw; + return $this->client->getDW(); + } + + /** + * Set the DW-value for this bucket. See setR(...) for more information. + * @param integer $dw - The new DW-value + * @return $this + */ + function setDW($dw) { + $this->dw = $dw; + return $this; + } + + /** + * Create a new Riak object that will be stored as JSON. + * @param string $key - Name of the key. + * @param object $data - The data to store. (default NULL) + * @return RiakObject + */ + function newObject($key, $data=NULL) { + $obj = new RiakObject($this->client, $this, $key); + $obj->setData($data); + $obj->setContentType('text/json'); + $obj->jsonize = TRUE; + return $obj; + } + + /** + * Create a new Riak object that will be stored as plain text/binary. + * @param string $key - Name of the key. + * @param object $data - The data to store. + * @param string $content_type - The content type of the object. (default 'text/json') + * @return RiakObject + */ + function newBinary($key, $data, $content_type='text/json') { + $obj = new RiakObject($this->client, $this, $key); + $obj->setData($data); + $obj->setContentType($content_type); + $obj->jsonize = FALSE; + return $obj; + } + + /** + * Retrieve a JSON-encoded object from Riak. + * @param string $key - Name of the key. + * @param int $r - R-Value of the request (defaults to bucket's R) + * @return RiakObject + */ + function get($key, $r=NULL) { + $obj = new RiakObject($this->client, $this, $key); + $obj->jsonize = TRUE; + $r = $this->getR($r); + return $obj->reload($r); + } + + /** + * Retrieve a binary/string object from Riak. + * @param string $key - Name of the key. + * @param int $r - R-Value of the request (defaults to bucket's R) + * @return RiakObject + */ + function getBinary($key, $r=NULL) { + $obj = new RiakObject($this->client, $this, $key); + $obj->jsonize = FALSE; + $r = $this->getR($r); + return $obj->reload($r); + } + + /** + * Set the N-value for this bucket, which is the number of replicas + * that will be written of each object in the bucket. Set this once + * before you write any data to the bucket, and never change it + * again, otherwise unpredictable things could happen. This should + * only be used if you know what you are doing. + * @param integer $nval - The new N-Val. + */ + function setNVal($nval) { + return $this->setProperty("n_val", $nval); + } + + /** + * Retrieve the N-value for this bucket. + * @return integer + */ + function getNVal() { + return $this->getProperty("n_val"); + } + + /** + * If set to true, then writes with conflicting data will be stored + * and returned to the client. This situation can be detected by + * calling hasSiblings() and getSiblings(). This should only be used + * if you know what you are doing. + * @param boolean $bool - True to store and return conflicting writes. + */ + function setAllowMultiples($bool) { + return $this->setProperty("allow_mult", $bool); + } + + /** + * Retrieve the 'allow multiples' setting. + * @return Boolean + */ + function getAllowMultiples() { + return "true" == $this->getProperty("allow_mult"); + } + + /** + * Set a bucket property. This should only be used if you know what + * you are doing. + * @param string $key - Property to set. + * @param mixed $value - Property value. + */ + function setProperty($key, $value) { + return $this->setProperties(array($key=>$value)); + } + + /** + * Retrieve a bucket property. + * @param string $key - The property to retrieve. + * @return mixed + */ + function getProperty($key) { + $props = $this->getProperties(); + if (array_key_exists($key, $props)) { + return $props[$key]; + } else { + return NULL; + } + } + + /** + * Set multiple bucket properties in one call. This should only be + * used if you know what you are doing. + * @param array $props - An associative array of $key=>$value. + */ + function setProperties($props) { + # Construct the URL, Headers, and Content... + $url = RiakUtils::buildRestPath($this->client, $this); + $headers = array('Content-Type: application/json'); + $content = json_encode(array("props"=>$props)); + + # Run the request... + $response = RiakUtils::httpRequest('PUT', $url, $headers, $content); + + # Handle the response... + if ($response == NULL) { + throw Exception("Error setting bucket properties."); + } + + # Check the response value... + $status = $response[0]['http_code']; + if ($status != 204) { + throw Exception("Error setting bucket properties."); + } + } + + /** + * Retrieve an associative array of all bucket properties. + * @return Array + */ + function getProperties() { + # Run the request... + $params = array('props' => 'true', 'keys' => 'false'); + $url = RiakUtils::buildRestPath($this->client, $this, NULL, NULL, $params); + $response = RiakUtils::httpRequest('GET', $url); + + # Use a RiakObject to interpret the response, we are just interested in the value. + $obj = new RiakObject($this->client, $this, NULL); + $obj->populate($response, array(200)); + if (!$obj->exists()) { + throw Exception("Error getting bucket properties."); + } + + $props = $obj->getData(); + $props = $props["props"]; + + return $props; + } + + /** + * Retrieve an array of all keys in this bucket. + * Note: this operation is pretty slow. + * @return Array + */ + function getKeys() { + $params = array('props'=>'false','keys'=>'true'); + $url = RiakUtils::buildRestPath($this->client, $this, NULL, NULL, $params); + $response = RiakUtils::httpRequest('GET', $url); + + # Use a RiakObject to interpret the response, we are just interested in the value. + $obj = new RiakObject($this->client, $this, NULL); + $obj->populate($response, array(200)); + if (!$obj->exists()) { + throw Exception("Error getting bucket properties."); + } + $keys = $obj->getData(); + return array_map("urldecode",$keys["keys"]); + } + + /** + * Search a secondary index + * @author Eric Stevens + * @param string $indexName - The name of the index to search + * @param string $indexType - The type of index ('int' or 'bin') + * @param string|int $startOrExact + * @param string|int optional $end + * @param bool $dedupe - whether to eliminate duplicate entries if any + * @return array of RiakLinks + */ + function indexSearch($indexName, $indexType, $startOrExact, $end=NULL, $dedupe=false) { + $url = RiakUtils::buildIndexPath($this->client, $this, "{$indexName}_{$indexType}", $startOrExact, $end, NULL); + $response = RiakUtils::httpRequest('GET', $url); + + $obj = new RiakObject($this->client, $this, NULL); + $obj->populate($response, array(200)); + if (!$obj->exists()) { + throw Exception("Error searching index."); + } + $data = $obj->getData(); + $keys = array_map("urldecode",$data["keys"]); + + $seenKeys = array(); + foreach($keys as $id=>&$key) { + if ($dedupe) { + if (isset($seenKeys[$key])) { + unset($keys[$id]); + continue; + } + $seenKeys[$key] = true; + } + $key = new RiakLink($this->name, $key); + $key->client = $this->client; + } + return $keys; + } + +} diff --git a/core/NoSQL/Riak/RiakClient.class.php b/core/NoSQL/Riak/RiakClient.class.php new file mode 100644 index 0000000000..dcdb3249f2 --- /dev/null +++ b/core/NoSQL/Riak/RiakClient.class.php @@ -0,0 +1,195 @@ +host = $host; + $this->port = $port; + $this->prefix = $prefix; + $this->mapred_prefix = $mapred_prefix; + $this->indexPrefix='buckets'; + $this->clientid = 'php_' . base_convert(mt_rand(), 10, 36); + $this->r = 2; + $this->w = 2; + $this->dw = 2; + } + + /** + * Get the R-value setting for this RiakClient. (default 2) + * @return integer + */ + function getR() { + return $this->r; + } + + /** + * Set the R-value for this RiakClient. This value will be used + * for any calls to get(...) or getBinary(...) where where 1) no + * R-value is specified in the method call and 2) no R-value has + * been set in the RiakBucket. + * @param integer $r - The R value. + * @return $this + */ + function setR($r) { + $this->r = $r; + return $this; + } + + /** + * Get the W-value setting for this RiakClient. (default 2) + * @return integer + */ + function getW() { + return $this->w; + } + + /** + * Set the W-value for this RiakClient. See setR(...) for a + * description of how these values are used. + * @param integer $w - The W value. + * @return $this + */ + function setW($w) { + $this->w = $w; + return $this; + } + + /** + * Get the DW-value for this ClientOBject. (default 2) + * @return integer + */ + function getDW() { + return $this->dw; + } + + /** + * Set the DW-value for this RiakClient. See setR(...) for a + * description of how these values are used. + * @param integer $dw - The DW value. + * @return $this + */ + function setDW($dw) { + $this->dw = $dw; + return $this; + } + + /** + * Get the clientID for this RiakClient. + * @return string + */ + function getClientID() { + return $this->clientid; + } + + /** + * Set the clientID for this RiakClient. Should not be called + * unless you know what you are doing. + * @param string $clientID - The new clientID. + * @return $this + */ + function setClientID($clientid) { + $this->clientid = $clientid; + return $this; + } + + /** + * Get the bucket by the specified name. Since buckets always exist, + * this will always return a RiakBucket. + * @return RiakBucket + */ + function bucket($name) { + return new RiakBucket($this, $name); + } + + /** + * Get all buckets. + * @return array() of RiakBucket objects + */ + function buckets() { + $url = RiakUtils::buildRestPath($this); + $response = RiakUtils::httpRequest('GET', $url.'?buckets=true'); + $response_obj = json_decode($response[1]); + $buckets = array(); + foreach($response_obj->buckets as $name) { + $buckets[] = $this->bucket($name); + } + return $buckets; + } + + /** + * Check if the Riak server for this RiakClient is alive. + * @return boolean + */ + function isAlive() { + $url = 'http://' . $this->host . ':' . $this->port . '/ping'; + $response = RiakUtils::httpRequest('GET', $url); + return ($response != NULL) && ($response[1] == 'OK'); + } + + + # MAP/REDUCE/LINK FUNCTIONS + + /** + * Start assembling a Map/Reduce operation. + * @see RiakMapReduce::add() + * @return RiakMapReduce + */ + function add($params) { + $mr = new RiakMapReduce($this); + $args = func_get_args(); + return call_user_func_array(array(&$mr, "add"), $args); + } + + /** + * Start assembling a Map/Reduce operation. This command will + * return an error unless executed against a Riak Search cluster. + * @see RiakMapReduce::search() + * @return RiakMapReduce + */ + function search($params) { + $mr = new RiakMapReduce($this); + $args = func_get_args(); + return call_user_func_array(array(&$mr, "search"), $args); + } + + /** + * Start assembling a Map/Reduce operation. + * @see RiakMapReduce::link() + */ + function link($params) { + $mr = new RiakMapReduce($this); + $args = func_get_args(); + return call_user_func_array(array(&$mr, "link"), $args); + } + + /** + * Start assembling a Map/Reduce operation. + * @see RiakMapReduce::map() + */ + function map($params) { + $mr = new RiakMapReduce($this); + $args = func_get_args(); + return call_user_func_array(array(&$mr, "map"), $args); + } + + /** + * Start assembling a Map/Reduce operation. + * @see RiakMapReduce::reduce() + */ + function reduce($params) { + $mr = new RiakMapReduce($this); + $args = func_get_args(); + return call_user_func_array(array(&$mr, "reduce"), $args); + } +} diff --git a/core/NoSQL/Riak/RiakLink.class.php b/core/NoSQL/Riak/RiakLink.class.php new file mode 100644 index 0000000000..80c2f493f1 --- /dev/null +++ b/core/NoSQL/Riak/RiakLink.class.php @@ -0,0 +1,120 @@ +bucket = $bucket; + $this->key = $key; + $this->tag = $tag; + $this->client = NULL; + } + + /** + * Retrieve the RiakObject to which this link points. + * @param integer $r - The R-value to use. + * @return RiakObject + */ + function get($r=NULL) { + return $this->client->bucket($this->bucket)->get($this->key, $r); + } + + /** + * Retrieve the RiakObject to which this link points, as a binary. + * @param integer $r - The R-value to use. + * @return RiakObject + */ + function getBinary($r=NULL) { + return $this->client->bucket($this->bucket)->getBinary($this->key, $r); + } + + /** + * Get the bucket name of this link. + * @return string + */ + function getBucket() { + return $this->bucket; + } + + /** + * Set the bucket name of this link. + * @param string $name - The bucket name. + * @return $this + */ + function setBucket($name) { + $this->bucket = $bucket; + return $this; + } + + /** + * Get the key of this link. + * @return string + */ + function getKey() { + return $this->key; + } + + /** + * Set the key of this link. + * @param string $key - The key. + * @return $this + */ + function setKey($key) { + $this->key = $key; + return $this; + } + + /** + * Get the tag of this link. + * @return string + */ + function getTag() { + if ($this->tag == null) + return $this->bucket; + else + return $this->tag; + } + + /** + * Set the tag of this link. + * @param string $tag - The tag. + * @return $this + */ + function setTag($tag) { + $this->tag = $tag; + return $this; + } + + /** + * Convert this RiakLink object to a link header string. Used internally. + */ + function toLinkHeader($client) { + $link = "prefix . "/" . + urlencode($this->bucket) . "/" . + urlencode($this->key) . ">; riaktag=\"" . + urlencode($this->getTag()) . "\""; + return $link; + } + + /** + * Return true if the links are equal. + * @param RiakLink $link - A RiakLink object. + * @return boolean + */ + function isEqual($link) { + $is_equal = + ($this->bucket == $link->bucket) && + ($this->key == $link->key) && + ($this->getTag() == $link->getTag()); + return $is_equal; + } +} diff --git a/core/NoSQL/Riak/RiakLinkPhase.class.php b/core/NoSQL/Riak/RiakLinkPhase.class.php new file mode 100644 index 0000000000..7590eb96f1 --- /dev/null +++ b/core/NoSQL/Riak/RiakLinkPhase.class.php @@ -0,0 +1,30 @@ +bucket = $bucket; + $this->tag = $tag; + $this->keep = $keep; + } + + /** + * Convert the RiakLinkPhase to an associative array. Used + * internally. + */ + function to_array() { + $stepdef = array("bucket"=>$this->bucket, + "tag"=>$this->tag, + "keep"=>$this->keep); + return array("link"=>$stepdef); + } +} diff --git a/core/NoSQL/Riak/RiakMapReduce.class.php b/core/NoSQL/Riak/RiakMapReduce.class.php new file mode 100644 index 0000000000..f1553e905d --- /dev/null +++ b/core/NoSQL/Riak/RiakMapReduce.class.php @@ -0,0 +1,274 @@ +client = $client; + $this->phases = array(); + $this->inputs = array(); + $this->input_mode = NULL; + $this->key_filters = array(); + } + + /** + * Add inputs to a map/reduce operation. This method takes three + * different forms, depending on the provided inputs. You can + * specify either a RiakObject, a string bucket name, or a bucket, + * key, and additional arg. + * @param mixed $arg1 - RiakObject or Bucket + * @param mixed $arg2 - Key or blank + * @param mixed $arg3 - Arg or blank + * @return RiakMapReduce + */ + function add($arg1, $arg2=NULL, $arg3=NULL) { + if (func_num_args() == 1) { + if ($arg1 instanceof RiakObject) + return $this->add_object($arg1); + else + return $this->add_bucket($arg1); + } + return $this->add_bucket_key_data($arg1, (string) $arg2, $arg3); + } + + /** + * Private. + */ + private function add_object($obj) { + return $this->add_bucket_key_data($obj->bucket->name, $obj->key, NULL); + } + + /** + * Private. + */ + private function add_bucket_key_data($bucket, $key, $data) { + if ($this->input_mode == "bucket") + throw new Exception("Already added a bucket, can't add an object."); + $this->inputs[] = array($bucket, $key, $data); + return $this; + } + + /** + * Private. + * @return $this + */ + private function add_bucket($bucket) { + $this->input_mode = "bucket"; + $this->inputs = $bucket; + return $this; + } + + /** + * Begin a map/reduce operation using a Search. This command will + * return an error unless executed against a Riak Search cluster. + * @param string $bucket - The Bucket to search. @param string + * query - The Query to execute. (Lucene syntax.) @return + * RiakMapReduce + */ + function search($bucket, $query) { + $this->inputs = array("module"=>"riak_search", "function"=>"mapred_search", "arg"=>array($bucket, $query)); + return $this; + } + + /** + * Add a link phase to the map/reduce operation. + * @param string $bucket - Bucket name (default '_', which means all + * buckets) + * @param string $tag - Tag (default '_', which means all buckets) + * @param boolean $keep - Flag whether to keep results from this + * stage in the map/reduce. (default FALSE, unless this is the last + * step in the phase) + * @return $this + */ + function link($bucket='_', $tag='_', $keep=FALSE) { + $this->phases[] = new RiakLinkPhase($bucket, $tag, $keep); + return $this; + } + + /** + * Add a map phase to the map/reduce operation. + * @param mixed $function - Either a named Javascript function (ie: + * "Riak.mapValues"), or an anonymous javascript function (ie: + * "function(...) { ... }" or an array ["erlang_module", + * "function"]. + * @param array() $options - An optional associative array + * containing "language", "keep" flag, and/or "arg". + * @return $this + */ + function map($function, $options=array()) { + $language = is_array($function) ? "erlang" : "javascript"; + $this->phases[] = new RiakMapReducePhase("map", + $function, + RiakUtils::get_value("language", $options, $language), + RiakUtils::get_value("keep", $options, FALSE), + RiakUtils::get_value("arg", $options, NULL)); + return $this; + } + + /** + * Add a reduce phase to the map/reduce operation. + * @param mixed $function - Either a named Javascript function (ie: + * "Riak.mapValues"), or an anonymous javascript function (ie: + * "function(...) { ... }" or an array ["erlang_module", + * "function"]. + * @param array() $options - An optional associative array + * containing "language", "keep" flag, and/or "arg". + * @return $this + */ + function reduce($function, $options=array()) { + $language = is_array($function) ? "erlang" : "javascript"; + $this->phases[] = new RiakMapReducePhase("reduce", + $function, + RiakUtils::get_value("language", $options, $language), + RiakUtils::get_value("keep", $options, FALSE), + RiakUtils::get_value("arg", $options, NULL)); + return $this; + } + + /** + * Add a key filter to the map/reduce operation. If there are already + * existing filters, an "and" condition will be used to combine them. + * Alias for key_filter_and + * @param array $filter - a key filter (ie: + * ->key_filter( + * array("tokenize", "-", 2), + * array("between", "20110601", "20110630") + * ) + * @return $this + */ + function key_filter(array $filter /*. ,$filter .*/) { + $args = func_get_args(); + array_unshift($args, 'and'); + return call_user_func_array(array($this, 'key_filter_operator'), $args); + } + + /** + * Add a key filter to the map/reduce operation. If there are already + * existing filters, an "and" condition will be used to combine them. + * @param array $filter - a key filter (ie: + * ->key_filter( + * array("tokenize", "-", 2), + * array("between", "20110601", "20110630") + * ) + * @return $this + */ + function key_filter_and(array $filter) { + $args = func_get_args(); + array_unshift($args, 'and'); + return call_user_func_array(array($this, 'key_filter_operator'), $args); + } + + /** + * Adds a key filter to the map/reduce operation. If there are already + * existing filters, an "or" condition will be used to combine with the + * existing filters. + * @param array $filter + * @return $this + */ + function key_filter_or(array $filter /*. ,$filter .*/) { + $args = func_get_args(); + array_unshift($args, 'or'); + return call_user_func_array(array($this, 'key_filter_operator'), $args); + } + + /** + * Adds a key filter to the map/reduce operation. If there are already + * existing filters, the provided conditional operator will be used + * to combine with the existing filters. + * @param string $operator - Operator (usually "and" or "or") + * @param array $filter + * @return $this + */ + function key_filter_operator($operator, $filter /*. ,$filter .*/) { + $filters = func_get_args(); + array_shift($filters); + if ($this->input_mode != 'bucket') + throw new Exception("Key filters can only be used in bucket mode"); + + if (count($this->key_filters) > 0) { + $this->key_filters = array(array( + $operator, + $this->key_filters, + $filters + )); + } else { + $this->key_filters = $filters; + } + return $this; + } + + /** + * Run the map/reduce operation. Returns an array of results, or an + * array of RiakLink objects if the last phase is a link phase. + * @param integer $timeout - Timeout in seconds. + * @return array() + */ + function run($timeout=NULL) { + $num_phases = count($this->phases); + + $linkResultsFlag = FALSE; + + # If there are no phases, then just echo the inputs back to the user. + if ($num_phases == 0) { + $this->reduce(array("riak_kv_mapreduce", "reduce_identity")); + $num_phases = 1; + $linkResultsFlag = TRUE; + } + + # Convert all phases to associative arrays. Also, + # if none of the phases are accumulating, then set the last one to + # accumulate. + $keep_flag = FALSE; + $query = array(); + for ($i = 0; $i < $num_phases; $i++) { + $phase = $this->phases[$i]; + if ($i == ($num_phases - 1) && !$keep_flag) + $phase->keep = TRUE; + if ($phase->keep) $keep_flag = TRUE; + $query[] = $phase->to_array(); + } + + # Add key filters if applicable + if ($this->input_mode == 'bucket' && count($this->key_filters) > 0) { + $this->inputs = array( + 'bucket' => $this->inputs, + 'key_filters' => $this->key_filters + ); + } + + # Construct the job, optionally set the timeout... + $job = array("inputs"=>$this->inputs, "query"=>$query); + if ($timeout != NULL) $job["timeout"] = $timeout; + $content = json_encode($job); + + # Do the request... + $url = "http://" . $this->client->host . ":" . $this->client->port . "/" . $this->client->mapred_prefix; + $response = RiakUtils::httpRequest('POST', $url, array(), $content); + $result = json_decode($response[1]); + + # If the last phase is NOT a link phase, then return the result. + $linkResultsFlag |= (end($this->phases) instanceof RiakLinkPhase); + + # If we don't need to link results, then just return. + if (!$linkResultsFlag) return $result; + + # Otherwise, if the last phase IS a link phase, then convert the + # results to RiakLink objects. + $a = array(); + foreach ($result as $r) { + $tag = isset($r[2]) ? $r[2] : null; + $link = new RiakLink($r[0], $r[1], $tag); + $link->client = $this->client; + $a[] = $link; + } + return $a; + } +} diff --git a/core/NoSQL/Riak/RiakMapReducePhase.class.php b/core/NoSQL/Riak/RiakMapReducePhase.class.php new file mode 100644 index 0000000000..5db9a70958 --- /dev/null +++ b/core/NoSQL/Riak/RiakMapReducePhase.class.php @@ -0,0 +1,50 @@ +type = $type; + $this->language = $language; + $this->function = $function; + $this->keep = $keep; + $this->arg = $arg; + } + + /** + * Convert the RiakMapReducePhase to an associative array. Used + * internally. + */ + function to_array() { + $stepdef = array("keep"=>$this->keep, + "language"=>$this->language, + "arg"=>$this->arg); + + if ($this->language == "javascript" && is_array($this->function)) { + $stepdef["bucket"] = $this->function[0]; + $stepdef["key"] = $this->function[1]; + } else if ($this->language == "javascript" && is_string($this->function)) { + if (strpos($this->function, "{") == FALSE) + $stepdef["name"] = $this->function; + else + $stepdef["source"] = $this->function; + } else if ($this->language == "erlang" && is_array($this->function)) { + $stepdef["module"] = $this->function[0]; + $stepdef["function"] = $this->function[1]; + } + + return array(($this->type)=>$stepdef); + } +} diff --git a/core/NoSQL/Riak/RiakObject.class.php b/core/NoSQL/Riak/RiakObject.class.php new file mode 100644 index 0000000000..7472d26aef --- /dev/null +++ b/core/NoSQL/Riak/RiakObject.class.php @@ -0,0 +1,815 @@ +client = $client; + $this->bucket = $bucket; + $this->key = $key; + $this->jsonize = TRUE; + $this->headers = array(); + $this->links = array(); + $this->siblings = NULL; + $this->exists = FALSE; + } + + /** + * Get the bucket of this object. + * @return RiakBucket + */ + function getBucket() { + return $this->bucket; + } + + /** + * Get the key of this object. + * @return string + */ + function getKey() { + return $this->key; + } + + /** + * Get the data stored in this object. Will return a associative + * array, unless the object was constructed with newBinary(...) or + * getBinary(...), in which case this will return a string. + * @return array or string + */ + function getData() { + return $this->data; + } + + /** + * Set the data stored in this object. This data will be + * JSON encoded unless the object was constructed with + * newBinary(...) or getBinary(...). + * @param mixed $data - The data to store. + * @return $data + */ + function setData($data) { + $this->data = $data; + return $this->data; + } + + /** + * Get the HTTP status from the last operation on this object. + * @return integer + */ + function status() { + return $this->headers['http_code']; + } + + /** + * Return true if the object exists, false otherwise. Allows you to + * detect a get(...) or getBinary(...) operation where the object is missing. + * @return boolean + */ + function exists() { + return $this->exists; + } + + /** + * Get the content type of this object. This is either text/json, or + * the provided content type if the object was created via newBinary(...). + * @return string + */ + function getContentType() { + return $this->headers['content-type']; + } + + /** + * Set the content type of this object. + * @param string $content_type - The new content type. + * @return $this + */ + function setContentType($content_type) { + $this->headers['content-type'] = $content_type; + return $this; + } + + /** + * Add a link to a RiakObject. + * @param mixed $obj - Either a RiakObject or a RiakLink object. + * @param string $tag - Optional link tag. (default is bucket name, + * ignored if $obj is a RiakLink object.) + * @return RiakObject + */ + function addLink($obj, $tag=NULL) { + if ($obj instanceof RiakLink) + $newlink = $obj; + else + $newlink = new RiakLink($obj->bucket->name, $obj->key, $tag); + + $this->removeLink($newlink); + $this->links[] = $newlink; + + return $this; + } + + /** + * Remove a link to a RiakObject. + * @param mixed $obj - Either a RiakObject or a RiakLink object. + * @param string $tag - + * @param mixed $obj - Either a RiakObject or a RiakLink object. + * @param string $tag - Optional link tag. (default is bucket name, + * ignored if $obj is a RiakLink object.) + * @return $this + */ + function removeLink($obj, $tag=NULL) { + if ($obj instanceof RiakLink) + $oldlink = $obj; + else + $oldlink = new RiakLink($obj->bucket->name, $obj->key, $tag); + + $a = array(); + foreach ($this->links as $link) { + if (!$link->isEqual($oldlink)) + $a[] = $link; + } + + $this->links = $a; + return $this; + } + + /** + * Return an array of RiakLink objects. + * @return array() + */ + function getLinks() { + # Set the clients before returning... + foreach ($this->links as $link) { + $link->client = $this->client; + } + return $this->links; + } + + /** @section Indexes */ + + /** + * Adds a secondary index to the object + * This will create the index if it does not exist, or will + * append an additional value if the index already exists and + * does not contain the provided value. + * @param string $indexName + * @param string $indexType - Must be one of 'int' or 'bin' - the + * only two index types supported by Riak + * @param string|int optional $explicitValue - If provided, uses this + * value explicitly. If not provided, this will search the object's + * data for a field with the name $indexName, and use that value. + * @return $this + */ + function addIndex($indexName, $indexType=null, $explicitValue = null) { + if ($explicitValue === null) { + $this->addAutoIndex($indexName, $indexType); + return; + } + + if ($indexType !== null) { + $index = strtolower("{$indexName}_{$indexType}"); + } else { + $index = strtolower($indexName); + } + if (!isset($this->indexes[$index])) $this->indexes[$index] = array(); + + if (false === array_search($explicitValue, $this->indexes[$index])) { + $this->indexes[$index][] = $explicitValue; + } + return $this; + } + + /** + * Sets a given index to a specific value or set of values + * @param string $indexName + * @param string $indexType - must be 'bin' or 'int' + * @param array|string|int $values + * @return $this + */ + function setIndex($indexName, $indexType=null, $values) { + if ($indexType !== null) { + $index = strtolower("{$indexName}_{$indexType}"); + } else { + $index = strtolower($indexName); + } + + $this->indexes[$index] = $values; + + return $this; + } + + /** + * Gets the current values for the identified index + * Note, the NULL value has special meaning - when the object is + * ->store()d, this value will be replaced with the current value + * the value of the field matching $indexName from the object's data + * @param string $indexName + * @param string $indexType + */ + function getIndex($indexName, $indexType=null) { + if ($indexType !== null) { + $index = strtolower("{$indexName}_{$indexType}"); + } else { + $index = strtolower($indexName); + } + if (!isset($this->indexes[$index])) return array(); + + return $this->indexes[$index]; + } + + /** + * Removes a specific value from a given index + * @param string $indexName + * @param string $indexType - must be 'bin' or 'int' + * @param string|int optional $explicitValue + * @return $this + */ + function removeIndex($indexName, $indexType=null, $explicitValue = null) { + if ($explicitValue === null) { + $this->removeAutoIndex($indexName, $indexType); + return; + } + if ($indexType !== null) { + $index = strtolower("{$indexName}_{$indexType}"); + } else { + $index = strtolower($indexName); + } + + if (!isset($this->indexes[$index])) return; + + if (false !== ($position = array_search($explicitValue, $this->indexes[$index]))) { + unset($this->indexes[$index][$position]); + } + + return $this; + } + + /** + * Bulk index removal + * If $indexName and $indexType are provided, all values for the + * identified index are removed. + * If just $indexName is provided, all values for all types of + * the identified index are removed + * If neither is provided, all indexes are removed from the object + * + * Note that this function will NOT affect auto indexes + * + * @param string optional $indexName + * @param string optional $indexType + * + * @return $this + */ + function removeAllIndexes($indexName=null, $indexType=null) { + if ($indexName === null) { + $this->indexes = array(); + } else if ($indexType === null) { + $indexName = strtolower($indexName); + unset($this->indexes["{$indexName}_int"]); + unset($this->indexes["{$indexName}_bin"]); + } else { + unset($this->indexes[strtolower("{$indexName}_{$indexType}")]); + } + + return $this; + } + + /** @section Auto Indexes */ + + /** + * Adds an automatic secondary index to the object + * The value of an automatic secondary index is determined at + * time of ->store() by looking for an $fieldName key + * in the object's data. + * + * @param string $fieldName + * @param string $indexType Must be one of 'int' or 'bin' + * + * @return $this + */ + function addAutoIndex($fieldName, $indexType=null) { + if ($indexType !== null) { + $index = strtolower("{$fieldName}_{$indexType}"); + } else { + $index = strtolower($fieldName); + } + $this->autoIndexes[$index] = $fieldName; + + return $this; + } + + /** + * Returns whether the object has a given auto index + * @param string $fieldName + * @param string $indexType - must be one of 'int' or 'bin' + * + * @return boolean + */ + function hasAutoIndex($fieldName, $indexType=null) { + if ($indexType !== null) { + $index = strtolower("{$fieldName}_{$indexType}"); + } else { + $index = strtolower($fieldName); + } + return isset($this->autoIndexes[$index]); + } + + /** + * Removes a given auto index from the object + * + * @param string $fieldName + * @param string $indexType + * + * @return $this + */ + function removeAutoIndex($fieldName, $indexType=null) { + if ($indexType !== null) { + $index = strtolower("{$fieldName}_{$indexType}"); + } else { + $index = strtolower($fieldName); + } + unset($this->autoIndexes[$index]); + return $this; + } + + /** + * Removes all auto indexes + * If $fieldName is not provided, all auto indexes on the + * object are stripped, otherwise just indexes on the given field + * are stripped. + * If $indexType is not provided, all types of index for the + * given field are stripped, otherwise just a given type is stripped. + * + * @param string $fieldName + * @param string $indexType + * + * @return $this + */ + function removeAllAutoIndexes($fieldName = null, $indexType = null) { + if ($fieldName === null) { + $this->autoIndexes = array(); + } else if ($indexType === null) { + $fieldName = strtolower($fieldName); + unset($this->autoIndexes["{$fieldName}_bin"]); + unset($this->autoIndexes["{$fieldName}_int"]); + } else { + unset($this->autoIndexes[strtolower("{$fieldName}_{$indexType}")]); + } + } + + /** @section Meta Data */ + + /** + * Gets a given metadata value + * Returns null if no metadata value with the given name exists + * + * @param string $metaName + * + * @return string|null + */ + function getMeta($metaName) { + $metaName = strtolower($metaName); + if (isset($this->meta[$metaName])) return $this->meta[$metaName]; + return null; + } + + /** + * Sets a given metadata value, overwriting an existing + * value with the same name if it exists. + * @param string $metaName + * @param string $value + * @return $this + */ + function setMeta($metaName, $value) { + $this->meta[strtolower($metaName)] = $value; + return $this; + } + + /** + * Removes a given metadata value + * @param string $metaName + * @return $this + */ + function removeMeta($metaName) { + unset ($this->meta[strtolower($metaName)]); + return $this; + } + + /** + * Gets all metadata values + * @return array=string + */ + function getAllMeta() { + return $this->meta; + } + + /** + * Strips all metadata values + * @return $this; + */ + function removeAllMeta() { + $this->meta = array(); + return $this; + } + + /** + * Store the object in Riak. When this operation completes, the + * object could contain new metadata and possibly new data if Riak + * contains a newer version of the object according to the object's + * vector clock. + * @param integer $w - W-value, wait for this many partitions to respond + * before returning to client. + * @param integer $dw - DW-value, wait for this many partitions to + * confirm the write before returning to client. + * @return $this + */ + function store($w=NULL, $dw=NULL) { + # Use defaults if not specified... + $w = $this->bucket->getW($w); + $dw = $this->bucket->getDW($w); + + # Construct the URL... + $params = array('returnbody' => 'true', 'w' => $w, 'dw' => $dw); + $url = RiakUtils::buildRestPath($this->client, $this->bucket, $this->key, NULL, $params); + + # Construct the headers... + $headers = array('Accept: text/plain, */*; q=0.5', + 'Content-Type: ' . $this->getContentType(), + 'X-Riak-ClientId: ' . $this->client->getClientID()); + + # Add the vclock if it exists... + if ($this->vclock() != NULL) { + $headers[] = 'X-Riak-Vclock: ' . $this->vclock(); + } + + # Add the Links... + foreach ($this->links as $link) { + $headers[] = 'Link: ' . $link->toLinkHeader($this->client); + } + + # Add the auto indexes... + $collisions = array(); + foreach($this->autoIndexes as $index=>$fieldName) { + $value = null; + // look up the value + if (isset($this->data[$fieldName])) { + $value = $this->data[$fieldName]; + $headers[] = "x-riak-index-$index: ".urlencode($value); + + // look for value collisions with normal indexes + if (isset($this->indexes[$index])) { + if (false !== array_search($value, $this->indexes[$index])) { + $collisions[$index] = $value; + } + } + } + } + count($this->autoIndexes) > 0 + ? $this->meta['x-rc-autoindex'] = json_encode($this->autoIndexes) + : $this->meta['x-rc-autoindex'] = null; + count($collisions) > 0 + ? $this->meta['x-rc-autoindexcollision'] = json_encode($collisions) + : $this->meta['x-rc-autoindexcollision'] = null; + + # Add the indexes + foreach ($this->indexes as $index=>$values) { + $headers[] = "x-riak-index-$index: " . join(', ', array_map('urlencode', $values)); + } + + + # Add the metadata... + foreach($this->meta as $metaName=>$metaValue) { + if ($metaValue !== null) $headers[] = "X-Riak-Meta-$metaName: $metaValue"; + } + + if ($this->jsonize) { + $content = json_encode($this->getData()); + } else { + $content = $this->getData(); + } + + $method = $this->key ? 'PUT' : 'POST'; + + # Run the operation. + $response = RiakUtils::httpRequest($method, $url, $headers, $content); + $this->populate($response, array(200, 201, 300)); + return $this; + } + + /** + * Reload the object from Riak. When this operation completes, the + * object could contain new metadata and a new value, if the object + * was updated in Riak since it was last retrieved. + * @param integer $r - R-Value, wait for this many partitions to respond + * before returning to client. + * @return $this + */ + function reload($r=NULL) { + # Do the request... + $r = $this->bucket->getR($r); + $params = array('r' => $r); + $url = RiakUtils::buildRestPath($this->client, $this->bucket, $this->key, NULL, $params); + $response = RiakUtils::httpRequest('GET', $url); + $this->populate($response, array(200, 300, 404)); + + # If there are siblings, load the data for the first one by default... + if ($this->hasSiblings()) { + $obj = $this->getSibling(0); + $this->setData($obj->getData()); + } + + return $this; + } + + /** + * Delete this object from Riak. + * @param integer $dw - DW-value. Wait until this many partitions have + * deleted the object before responding. + * @return $this + */ + function delete($dw=NULL) { + # Use defaults if not specified... + $dw = $this->bucket->getDW($dw); + + # Construct the URL... + $params = array('dw' => $dw); + $url = RiakUtils::buildRestPath($this->client, $this->bucket, $this->key, NULL, $params); + + # Run the operation... + $response = RiakUtils::httpRequest('DELETE', $url); + $this->populate($response, array(204, 404)); + + return $this; + } + + + /** + * Reset this object. + * @return $this + */ + private function clear() { + $this->headers = array(); + $this->links = array(); + $this->data = NULL; + $this->exists = FALSE; + $this->siblings = NULL; + $this->indexes = array(); + $this->autoIndexes = array(); + $this->meta = array(); + return $this; + } + + /** + * Get the vclock of this object. + * @return string + */ + private function vclock() { + if (array_key_exists('x-riak-vclock', $this->headers)) { + return $this->headers['x-riak-vclock']; + } else { + return NULL; + } + } + + /** + * Given the output of RiakUtils::httpRequest and a list of + * statuses, populate the object. Only for use by the Riak client + * library. + * @return $this + */ + function populate($response, $expected_statuses) { + $this->clear(); + + # If no response given, then return. + if ($response == NULL) { + return $this; + } + + # Update the object... + $this->headers = $response[0]; + $this->data = $response[1]; + $status = $this->status(); + + # Check if the server is down (status==0) + if ($status == 0) { + $m = 'Could not contact Riak Server: http://' . $this->client->host . ':' . $this->client->port . '!'; + throw new Exception($m); + } + + # Verify that we got one of the expected statuses. Otherwise, throw an exception. + if (!in_array($status, $expected_statuses)) { + $m = 'Expected status ' . implode(' or ', $expected_statuses) . ', received ' . $status . ' with body: ' . $this->data; + throw new Exception($m); + } + + # If 404 (Not Found), then clear the object. + if ($status == 404) { + $this->clear(); + return $this; + } + + # If we are here, then the object exists... + $this->exists = TRUE; + + # Parse the link header... + if (array_key_exists("link", $this->headers)) { + $this->populateLinks($this->headers["link"]); + } + + # Parse the index and metadata headers + $this->indexes = array(); + $this->autoIndexes = array(); + $this->meta = array(); + foreach($this->headers as $key=>$val) { + if (preg_match('~^x-riak-([^-]+)-(.+)$~', $key, $matches)) { + switch($matches[1]) { + case 'index': + $index = substr($matches[2], 0, strrpos($matches[2], '_')); + $type = substr($matches[2], strlen($index)+1); + $this->setIndex($index, $type, array_map('urldecode', explode(', ', $val))); + break; + case 'meta': + $this->meta[$matches[2]] = $val; + break; + } + } + } + + # If 300 (Siblings), then load the first sibling, and + # store the rest. + if ($status == 300) { + $siblings = explode("\n", trim($this->data)); + array_shift($siblings); # Get rid of 'Siblings:' string. + $this->siblings = $siblings; + $this->exists = TRUE; + return $this; + } + + if ($status == 201) { + $path_parts = explode('/', $this->headers['location']); + $this->key = array_pop($path_parts); + } + + # Possibly json_decode... + if (($status == 200 || $status == 201) && $this->jsonize) { + $this->data = json_decode($this->data, true); + } + + # Look for auto indexes and deindex explicit values if appropriate + if (isset($this->meta['x-rc-autoindex'])) { + # dereference the autoindexes + $this->autoIndexes = json_decode($this->meta['x-rc-autoindex'], true); + $collisions = isset($this->meta['x-rc-autoindexcollision']) ? json_decode($this->meta['x-rc-autoindexcollision'], true) : array(); + + foreach($this->autoIndexes as $index=>$fieldName) { + $value = null; + if (isset($this->data[$fieldName])) { + $value = $this->data[$fieldName]; + if (isset($collisions[$index]) && $collisions[$index] === $value) { + // Don't strip this value, it's an explicit index. + } else { + if ($value !== null) $this->removeIndex($index, null, $value); + } + } + + if (!isset($collisions[$index])) { + // Do not delete this value if + } + } + } + + return $this; + } + + /** + * Private. + * @return $this + */ + private function populateLinks($linkHeaders) { + $linkHeaders = explode(",", trim($linkHeaders)); + foreach ($linkHeaders as $linkHeader) { + $linkHeader = trim($linkHeader); + $matches = array(); + $result = preg_match("/\<\/([^\/]+)\/([^\/]+)\/([^\/]+)\>; ?riaktag=\"([^\"]+)\"/", $linkHeader, $matches); + if ($result == 1) { + $this->links[] = new RiakLink(urldecode($matches[2]), urldecode($matches[3]), urldecode($matches[4])); + } + } + + return $this; + } + + /** + * Return true if this object has siblings. + * @return boolean + */ + function hasSiblings() { + return ($this->getSiblingCount() > 0); + } + + /** + * Get the number of siblings that this object contains. + * @return integer + */ + function getSiblingCount() { + return count($this->siblings); + } + + /** + * Retrieve a sibling by sibling number. + * @param integer $i - Sibling number. + * @param integer $r - R-Value. Wait until this many partitions + * have responded before returning to client. + * @return RiakObject. + */ + function getSibling($i, $r=NULL) { + # Use defaults if not specified. + $r = $this->bucket->getR($r); + + # Run the request... + $vtag = $this->siblings[$i]; + $params = array('r' => $r, 'vtag' => $vtag); + $url = RiakUtils::buildRestPath($this->client, $this->bucket, $this->key, NULL, $params); + $response = RiakUtils::httpRequest('GET', $url); + + # Respond with a new object... + $obj = new RiakObject($this->client, $this->bucket, $this->key); + $obj->jsonize = $this->jsonize; + $obj->populate($response, array(200)); + return $obj; + } + + /** + * Retrieve an array of siblings. + * @param integer $r - R-Value. Wait until this many partitions have + * responded before returning to client. + * @return array of RiakObject + */ + function getSiblings($r=NULL) { + $a = array(); + for ($i = 0; $i<$this->getSiblingCount(); $i++) { + $a[] = $this->getSibling($i, $r); + } + return $a; + } + + /** + * Start assembling a Map/Reduce operation. + * @see RiakMapReduce::add() + * @return RiakMapReduce + */ + function add($params) { + $mr = new RiakMapReduce($this->client); + $mr->add($this->bucket->name, $this->key); + $args = func_get_args(); + return call_user_func_array(array(&$mr, "add"), $args); + } + + /** + * Start assembling a Map/Reduce operation. + * @see RiakMapReduce::link() + * @return RiakMapReduce + */ + function link($params) { + $mr = new RiakMapReduce($this->client); + $mr->add($this->bucket->name, $this->key); + $args = func_get_args(); + return call_user_func_array(array(&$mr, "link"), $args); + } + + /** + * Start assembling a Map/Reduce operation. + * @see RiakMapReduce::map() + * @return RiakMapReduce + */ + function map($params) { + $mr = new RiakMapReduce($this->client); + $mr->add($this->bucket->name, $this->key); + $args = func_get_args(); + return call_user_func_array(array(&$mr, "map"), $args); + } + + /** + * Start assembling a Map/Reduce operation. + * @see RiakMapReduce::reduce() + * @return RiakMapReduce + */ + function reduce($params) { + $mr = new RiakMapReduce($this->client); + $mr->add($this->bucket->name, $this->key); + $args = func_get_args(); + return call_user_func_array(array(&$mr, "reduce"), $args); + } +} diff --git a/core/NoSQL/Riak/RiakStringIO.class.php b/core/NoSQL/Riak/RiakStringIO.class.php new file mode 100644 index 0000000000..0a53ddfaf5 --- /dev/null +++ b/core/NoSQL/Riak/RiakStringIO.class.php @@ -0,0 +1,19 @@ +contents = ''; + } + + function write($ch, $data) { + $this->contents .= $data; + return strlen($data); + } + + function contents() { + return $this->contents; + } +} diff --git a/core/NoSQL/Riak/RiakUtils.class.php b/core/NoSQL/Riak/RiakUtils.class.php new file mode 100644 index 0000000000..10c0c389ee --- /dev/null +++ b/core/NoSQL/Riak/RiakUtils.class.php @@ -0,0 +1,189 @@ +host . ':' . $client->port; + $path.= '/' . $client->prefix; + + # Add '.../bucket' + if (!is_null($bucket) && $bucket instanceof RiakBucket) { + $path .= '/' . urlencode($bucket->name); + } + + # Add '.../key' + if (!is_null($key)) { + $path .= '/' . urlencode($key); + } + + # Add '.../bucket,tag,acc/bucket,tag,acc' + if (!is_null($spec)) { + $s = ''; + foreach($spec as $el) { + if ($s != '') $s .= '/'; + $s .= urlencode($el[0]) . ',' . urlencode($el[1]) . ',' . $el[2] . '/'; + } + $path .= '/' . $s; + } + + # Add query parameters. + if (!is_null($params)) { + $s = ''; + foreach ($params as $key => $value) { + if ($s != '') $s .= '&'; + $s .= urlencode($key) . '=' . urlencode($value); + } + + $path .= '?' . $s; + } + + return $path; + } + + /** + * Given a RiakClient, RiakBucket, Key, LinkSpec, and Params, + * construct and return a URL for searching secondary indexes. + * @author Eric Stevens + * @param RiakClient $client + * @param RiakBucket $bucket + * @param string $index - Index Name & type (eg, "indexName_bin") + * @param string|int $start - Starting value or exact match if no ending value + * @param string|int $end - Ending value for range search + * @param array $params - Any extra query parameters to pass on the URL + * @return string URL + */ + public static function buildIndexPath(RiakClient $client, RiakBucket $bucket, $index, $start, $end=NULL, array $params=NULL) { + # Build 'http://hostname:port/prefix/bucket' + $path = array('http:/',$client->host.':'.$client->port,$client->indexPrefix); + + # Add '.../bucket' + $path[] = urlencode($bucket->name); + + # Add '.../index' + $path[] = 'index'; + + # Add '.../index_type' + $path[] = urlencode($index); + + # Add .../(start|exact) + $path[] = urlencode($start); + + if (!is_null($end)) { + $path[] = urlencode($end); + } + + // faster than repeated string concatenations + $path = join('/', $path); + + # Add query parameters. + if (!is_null($params)) { + // Most users will have the http PECL extension + if (func_exists('http_build_query')) { + $path .= '?' . http_build_query($params, '', '&'); + } else { + // In case they don't have the http PECL extension + $s = array(); + foreach ($params as $key => $value) { + $s[] = urlencode($key) . '=' . urlencode($value); + } + + $path .= '?' . join('&', $s); + } + } + + return $path; + } + + /** + * Given a Method, URL, Headers, and Body, perform and HTTP request, + * and return an array of arity 2 containing an associative array of + * response headers and the response body. + */ + public static function httpRequest($method, $url, $request_headers = array(), $obj = '') { + # Set up curl + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers); + + if ($method == 'GET') { + curl_setopt($ch, CURLOPT_HTTPGET, 1); + } else if ($method == 'POST') { + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $obj); + } else if ($method == 'PUT') { + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); + curl_setopt($ch, CURLOPT_POSTFIELDS, $obj); + } else if ($method == 'DELETE') { + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); + } + + # Capture the response headers... + $response_headers_io = new RiakStringIO(); + curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(&$response_headers_io, 'write')); + + # Capture the response body... + $response_body_io = new RiakStringIO(); + curl_setopt($ch, CURLOPT_WRITEFUNCTION, array(&$response_body_io, 'write')); + + try { + # Run the request. + curl_exec($ch); + $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + # Get the headers... + $parsed_headers = RiakUtils::parseHttpHeaders($response_headers_io->contents()); + $response_headers = array("http_code"=>$http_code); + foreach ($parsed_headers as $key=>$value) { + $response_headers[strtolower($key)] = $value; + } + + # Get the body... + $response_body = $response_body_io->contents(); + + # Return a new RiakResponse object. + return array($response_headers, $response_body); + } catch (Exception $e) { + curl_close($ch); + error_log('Error: ' . $e->getMessage()); + return NULL; + } + } + + /** + * Parse an HTTP Header string into an asssociative array of + * response headers. + */ + static function parseHttpHeaders($headers) { + $retVal = array(); + $fields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ', $headers)); + foreach( $fields as $field ) { + if( preg_match('/([^:]+): (.+)/m', $field, $match) ) { + $match[1] = preg_replace('/(?<=^|[\x09\x20\x2D])./e', 'strtoupper("\0")', strtolower(trim($match[1]))); + if( isset($retVal[$match[1]]) ) { + $retVal[$match[1]] = array($retVal[$match[1]], $match[2]); + } else { + $retVal[$match[1]] = trim($match[2]); + } + } + } + return $retVal; + } +} diff --git a/global.inc.php.tpl b/global.inc.php.tpl index ea4343c5e2..cd81b559d6 100644 --- a/global.inc.php.tpl +++ b/global.inc.php.tpl @@ -10,12 +10,12 @@ ***************************************************************************/ // sample system-wide configuration file - + function error2Exception($code, $string, $file, $line, $context) { throw new BaseException($string, $code); } - + /* void */ function __autoload_failed($classname, $message) { eval( @@ -24,14 +24,14 @@ .'throw new ClassNotFoundException("'.$classname.': '.$message.'");' ); } - + // file extensions define('EXT_CLASS', '.class.php'); define('EXT_TPL', '.tpl.html'); define('EXT_MOD', '.inc.php'); define('EXT_HTML', '.html'); define('EXT_UNIT', '.unit.php'); - + // overridable constant, don't forget for trailing slash // also you may consider using /dev/shm/ for cache purposes if (!defined('ONPHP_TEMP_PATH')) @@ -39,115 +39,116 @@ 'ONPHP_TEMP_PATH', sys_get_temp_dir().DIRECTORY_SEPARATOR.'onPHP'.DIRECTORY_SEPARATOR ); - + if (!defined('ONPHP_CLASS_CACHE')) define('ONPHP_CLASS_CACHE', ONPHP_TEMP_PATH); - + // classes autoload magic if (!defined('ONPHP_CLASS_CACHE_TYPE')) define('ONPHP_CLASS_CACHE_TYPE', 'classPathCache'); - + require dirname(__FILE__).DIRECTORY_SEPARATOR .'misc'.DIRECTORY_SEPARATOR .'Autoloader'.EXT_MOD; - + spl_autoload_register(array('Autoloader', ONPHP_CLASS_CACHE_TYPE), false); - + // system settings error_reporting(E_ALL | E_STRICT); set_error_handler('error2Exception', E_ALL | E_STRICT); ignore_user_abort(true); define('ONPHP_VERSION', '1.0.10.99'); - + if (!defined('ONPHP_IPC_PERMS')) define('ONPHP_IPC_PERMS', 0660); - + // paths define('ONPHP_ROOT_PATH', dirname(__FILE__).DIRECTORY_SEPARATOR); define('ONPHP_CORE_PATH', ONPHP_ROOT_PATH.'core'.DIRECTORY_SEPARATOR); define('ONPHP_MAIN_PATH', ONPHP_ROOT_PATH.'main'.DIRECTORY_SEPARATOR); define('ONPHP_META_PATH', ONPHP_ROOT_PATH.'meta'.DIRECTORY_SEPARATOR); define('ONPHP_UI_PATH', ONPHP_ROOT_PATH.'UI'.DIRECTORY_SEPARATOR); - + if (!defined('ONPHP_META_PATH')) define( 'ONPHP_META_PATH', ONPHP_ROOT_PATH.'meta'.DIRECTORY_SEPARATOR ); - + define('ONPHP_META_CLASSES', ONPHP_META_PATH.'classes'.DIRECTORY_SEPARATOR); - + define( 'ONPHP_INCUBATOR_PATH', ONPHP_ROOT_PATH.'incubator'.DIRECTORY_SEPARATOR ); - + set_include_path( // current path get_include_path().PATH_SEPARATOR - + // core classes .ONPHP_CORE_PATH.'Base' .PATH_SEPARATOR .ONPHP_CORE_PATH.'Cache' .PATH_SEPARATOR - + .ONPHP_CORE_PATH.'DB' .PATH_SEPARATOR .ONPHP_CORE_PATH.'DB'.DIRECTORY_SEPARATOR.'Transaction'.PATH_SEPARATOR - + .ONPHP_CORE_PATH.'Exceptions' .PATH_SEPARATOR - + .ONPHP_CORE_PATH.'Form' .PATH_SEPARATOR .ONPHP_CORE_PATH.'Form'.DIRECTORY_SEPARATOR.'Filters'.PATH_SEPARATOR .ONPHP_CORE_PATH.'Form'.DIRECTORY_SEPARATOR.'Primitives'.PATH_SEPARATOR - + .ONPHP_CORE_PATH.'Logic' .PATH_SEPARATOR .ONPHP_CORE_PATH.'OSQL' .PATH_SEPARATOR - + .ONPHP_CORE_PATH.'NoSQL' .PATH_SEPARATOR - + .ONPHP_CORE_PATH.'NoSQL'.DIRECTORY_SEPARATOR.'Riak'.PATH_SEPARATOR + // main framework .ONPHP_MAIN_PATH.'Base' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Criteria' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Criteria'.DIRECTORY_SEPARATOR.'Projections'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Crypto' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'DAOs' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'DAOs'.DIRECTORY_SEPARATOR.'Handlers'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'DAOs'.DIRECTORY_SEPARATOR.'Workers'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Flow' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'SPL' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Net' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Http'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Mail'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Ip'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Net'.DIRECTORY_SEPARATOR.'Soap'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Math' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Markup' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Markup'.DIRECTORY_SEPARATOR.'Feed'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Markup'.DIRECTORY_SEPARATOR.'Html'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'OQL' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Expressions'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Parsers'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'OQL'.DIRECTORY_SEPARATOR.'Statements'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'OpenId' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'EntityProto'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'EntityProto'.DIRECTORY_SEPARATOR.'Builders'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'EntityProto'.DIRECTORY_SEPARATOR.'Accessors'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'UnifiedContainer'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'UI'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'UI'.DIRECTORY_SEPARATOR.'View'.PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Utils' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'TuringTest'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Archivers'.PATH_SEPARATOR @@ -167,23 +168,23 @@ .ONPHP_MAIN_PATH.'Messages'.DIRECTORY_SEPARATOR.'Interface'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Application' .PATH_SEPARATOR - + .ONPHP_MAIN_PATH.'Charts'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Charts'.DIRECTORY_SEPARATOR.'Google'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Monitoring'.PATH_SEPARATOR - + .ONPHP_META_CLASSES.PATH_SEPARATOR - + /* .ONPHP_INCUBATOR_PATH .'classes'.DIRECTORY_SEPARATOR .'Application'.DIRECTORY_SEPARATOR.PATH_SEPARATOR - + .ONPHP_INCUBATOR_PATH .'classes'.DIRECTORY_SEPARATOR .'Application'.DIRECTORY_SEPARATOR .'Markups'.DIRECTORY_SEPARATOR.PATH_SEPARATOR - + .ONPHP_INCUBATOR_PATH .'classes'.DIRECTORY_SEPARATOR .'Application'.DIRECTORY_SEPARATOR @@ -191,7 +192,7 @@ .'Documents'.DIRECTORY_SEPARATOR.PATH_SEPARATOR */ ); - + //NOTE: disable by default //see http://pgfoundry.org/docman/view.php/1000079/117/README.txt //define('POSTGRES_IP4_ENABLED', true); From bc8ac70565a35a2893a8fab47d2f4b3f8f2b2b61 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Sat, 17 Mar 2012 14:02:21 +0400 Subject: [PATCH 042/418] NoSQL numeric->int --- core/NoSQL/NoSqlObject.class.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/NoSQL/NoSqlObject.class.php b/core/NoSQL/NoSqlObject.class.php index b098bdcba6..fcfb2a3766 100644 --- a/core/NoSQL/NoSqlObject.class.php +++ b/core/NoSQL/NoSqlObject.class.php @@ -51,15 +51,16 @@ public function toArray() { $value = $value->toStamp(); //$value = $value->toString(); } - $entity[ $property->getColumnName() ] = $value; + $entity[ $property->getColumnName() ] = is_numeric($value) ? (int)$value : $value; } // обрабатываем перечисления elseif( $property->getType()=='enumeration' ) { $value = call_user_func(array($this, $property->getGetter())); - $entity[ $property->getColumnName() ] = $value = $value->getId(); + $entity[ $property->getColumnName() ] = (int)$value->getId(); } // обрабатываем связи 1к1 elseif( in_array($property->getType(), $this->identifiers) && $property->getRelationId()==1 ) { - $entity[ $property->getColumnName() ] = call_user_func(array($this, $property->getGetter().'Id')); + $value = call_user_func(array($this, $property->getGetter().'Id')); + $entity[ $property->getColumnName() ] = is_numeric($value) ? (int)$value : $value; } } // $entity[ '_id' ] = $this->id; From 7c596809a8b6d2c8a1b0a9c2b60ab080950f7c7d Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 20 Mar 2012 19:28:05 +0400 Subject: [PATCH 043/418] ExtendedPhpView --- main/UI/View/ExtendedPhpView.class.php | 79 ++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 main/UI/View/ExtendedPhpView.class.php diff --git a/main/UI/View/ExtendedPhpView.class.php b/main/UI/View/ExtendedPhpView.class.php new file mode 100644 index 0000000000..15ca6d7b8a --- /dev/null +++ b/main/UI/View/ExtendedPhpView.class.php @@ -0,0 +1,79 @@ + + * @date 2012.03.20 + */ +class ExtendedPhpView extends SimplePhpView { + + protected + /** + * @var PartViewer + */ + $partViewer = null, + /** + * вьюшка, которую выпаолним до основной + * @var string + */ + $preView = null, + /** + * вьюшка, которую выполним после основной + * @var string + */ + $postView = null; + + /** + * @param string $preView + * @return ExtendedPhpView + */ + public function setPreView($preView) { + $this->preView = $preView; + return $this; + } + + /** + * @param string $postView + * @return ExtendedPhpView + */ + public function setPostView($postView) { + $this->postView = $postView; + return $this; + } + + /** + * @param Model $model + * @return ExtendedPhpView + */ + public function render(/* Model */ $model = null) + { + Assert::isTrue($model === null || $model instanceof Model); + + if ($model) + extract($model->getList()); + + $this->partViewer = $partViewer = new PartViewer($this->partViewResolver, $model); + + $this->preRender(); + + include $this->templatePath; + + $this->postRender(); + + return $this; + } + + protected function preRender() { + if( !is_null($this->preView) ) { + $this->partViewer->view($this->preView); + } + return $this; + } + + protected function postRender() { + if( !is_null($this->postView) ) { + $this->partViewer->view($this->postView); + } + return $this; + } + +} From dd42ed7b8958b9dc4160909bf64032de100783b4 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 20 Mar 2012 19:36:55 +0400 Subject: [PATCH 044/418] NoSqlDAO fix --- core/NoSQL/NoSqlDAO.class.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 0615181dd8..ca4dde0ee6 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -319,6 +319,8 @@ public function getListByView($view, $keys, $criteria=null) { foreach($keys as &$val) { if( is_null($val) ) { $val = 'null'; + } elseif(is_numeric($val)) { + $val = $val; } else { $val = '"'.$val.'"'; } From ee59f818f147d6b3ea38005c2bedd9fc18686095 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 20 Mar 2012 19:37:25 +0400 Subject: [PATCH 045/418] NoSqlDAO fix --- core/NoSQL/NoSqlDAO.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index ca4dde0ee6..bdf8b71b24 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -320,7 +320,7 @@ public function getListByView($view, $keys, $criteria=null) { if( is_null($val) ) { $val = 'null'; } elseif(is_numeric($val)) { - $val = $val; + //$val = $val; } else { $val = '"'.$val.'"'; } From 65f1eeb7674b402628ad6c01ea4469042217814e Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 22 Mar 2012 19:58:20 +0400 Subject: [PATCH 046/418] delete riak --- core/NoSQL/Riak/RiakBucket.class.php | 312 ------- core/NoSQL/Riak/RiakClient.class.php | 195 ----- core/NoSQL/Riak/RiakLink.class.php | 120 --- core/NoSQL/Riak/RiakLinkPhase.class.php | 30 - core/NoSQL/Riak/RiakMapReduce.class.php | 274 ------- core/NoSQL/Riak/RiakMapReducePhase.class.php | 50 -- core/NoSQL/Riak/RiakObject.class.php | 815 ------------------- core/NoSQL/Riak/RiakStringIO.class.php | 19 - core/NoSQL/Riak/RiakUtils.class.php | 189 ----- 9 files changed, 2004 deletions(-) delete mode 100644 core/NoSQL/Riak/RiakBucket.class.php delete mode 100644 core/NoSQL/Riak/RiakClient.class.php delete mode 100644 core/NoSQL/Riak/RiakLink.class.php delete mode 100644 core/NoSQL/Riak/RiakLinkPhase.class.php delete mode 100644 core/NoSQL/Riak/RiakMapReduce.class.php delete mode 100644 core/NoSQL/Riak/RiakMapReducePhase.class.php delete mode 100644 core/NoSQL/Riak/RiakObject.class.php delete mode 100644 core/NoSQL/Riak/RiakStringIO.class.php delete mode 100644 core/NoSQL/Riak/RiakUtils.class.php diff --git a/core/NoSQL/Riak/RiakBucket.class.php b/core/NoSQL/Riak/RiakBucket.class.php deleted file mode 100644 index 9119400051..0000000000 --- a/core/NoSQL/Riak/RiakBucket.class.php +++ /dev/null @@ -1,312 +0,0 @@ -client = $client; - $this->name = $name; - $this->r = NULL; - $this->w = NULL; - $this->dw = NULL; - } - - /** - * Get the bucket name. - */ - function getName() { - return $this->name; - } - - /** - * Get the R-value for this bucket, if it is set, otherwise return - * the R-value for the client. - * @return integer - */ - function getR($r=NULL) { - if ($r != NULL) return $r; - if ($this->r != NULL) return $this->r; - return $this->client->getR(); - } - - /** - * Set the R-value for this bucket. get(...) and getBinary(...) - * operations that do not specify an R-value will use this value. - * @param integer $r - The new R-value. - * @return $this - */ - function setR($r) { - $this->r = $r; - return $this; - } - - /** - * Get the W-value for this bucket, if it is set, otherwise return - * the W-value for the client. - * @return integer - */ - function getW($w) { - if ($w != NULL) return $w; - if ($this->w != NULL) return $this->w; - return $this->client->getW(); - } - - /** - * Set the W-value for this bucket. See setR(...) for more information. - * @param integer $w - The new W-value. - * @return $this - */ - function setW($w) { - $this->w = $w; - return $this; - } - - /** - * Get the DW-value for this bucket, if it is set, otherwise return - * the DW-value for the client. - * @return integer - */ - function getDW($dw) { - if ($dw != NULL) return $dw; - if ($this->dw != NULL) return $this->dw; - return $this->client->getDW(); - } - - /** - * Set the DW-value for this bucket. See setR(...) for more information. - * @param integer $dw - The new DW-value - * @return $this - */ - function setDW($dw) { - $this->dw = $dw; - return $this; - } - - /** - * Create a new Riak object that will be stored as JSON. - * @param string $key - Name of the key. - * @param object $data - The data to store. (default NULL) - * @return RiakObject - */ - function newObject($key, $data=NULL) { - $obj = new RiakObject($this->client, $this, $key); - $obj->setData($data); - $obj->setContentType('text/json'); - $obj->jsonize = TRUE; - return $obj; - } - - /** - * Create a new Riak object that will be stored as plain text/binary. - * @param string $key - Name of the key. - * @param object $data - The data to store. - * @param string $content_type - The content type of the object. (default 'text/json') - * @return RiakObject - */ - function newBinary($key, $data, $content_type='text/json') { - $obj = new RiakObject($this->client, $this, $key); - $obj->setData($data); - $obj->setContentType($content_type); - $obj->jsonize = FALSE; - return $obj; - } - - /** - * Retrieve a JSON-encoded object from Riak. - * @param string $key - Name of the key. - * @param int $r - R-Value of the request (defaults to bucket's R) - * @return RiakObject - */ - function get($key, $r=NULL) { - $obj = new RiakObject($this->client, $this, $key); - $obj->jsonize = TRUE; - $r = $this->getR($r); - return $obj->reload($r); - } - - /** - * Retrieve a binary/string object from Riak. - * @param string $key - Name of the key. - * @param int $r - R-Value of the request (defaults to bucket's R) - * @return RiakObject - */ - function getBinary($key, $r=NULL) { - $obj = new RiakObject($this->client, $this, $key); - $obj->jsonize = FALSE; - $r = $this->getR($r); - return $obj->reload($r); - } - - /** - * Set the N-value for this bucket, which is the number of replicas - * that will be written of each object in the bucket. Set this once - * before you write any data to the bucket, and never change it - * again, otherwise unpredictable things could happen. This should - * only be used if you know what you are doing. - * @param integer $nval - The new N-Val. - */ - function setNVal($nval) { - return $this->setProperty("n_val", $nval); - } - - /** - * Retrieve the N-value for this bucket. - * @return integer - */ - function getNVal() { - return $this->getProperty("n_val"); - } - - /** - * If set to true, then writes with conflicting data will be stored - * and returned to the client. This situation can be detected by - * calling hasSiblings() and getSiblings(). This should only be used - * if you know what you are doing. - * @param boolean $bool - True to store and return conflicting writes. - */ - function setAllowMultiples($bool) { - return $this->setProperty("allow_mult", $bool); - } - - /** - * Retrieve the 'allow multiples' setting. - * @return Boolean - */ - function getAllowMultiples() { - return "true" == $this->getProperty("allow_mult"); - } - - /** - * Set a bucket property. This should only be used if you know what - * you are doing. - * @param string $key - Property to set. - * @param mixed $value - Property value. - */ - function setProperty($key, $value) { - return $this->setProperties(array($key=>$value)); - } - - /** - * Retrieve a bucket property. - * @param string $key - The property to retrieve. - * @return mixed - */ - function getProperty($key) { - $props = $this->getProperties(); - if (array_key_exists($key, $props)) { - return $props[$key]; - } else { - return NULL; - } - } - - /** - * Set multiple bucket properties in one call. This should only be - * used if you know what you are doing. - * @param array $props - An associative array of $key=>$value. - */ - function setProperties($props) { - # Construct the URL, Headers, and Content... - $url = RiakUtils::buildRestPath($this->client, $this); - $headers = array('Content-Type: application/json'); - $content = json_encode(array("props"=>$props)); - - # Run the request... - $response = RiakUtils::httpRequest('PUT', $url, $headers, $content); - - # Handle the response... - if ($response == NULL) { - throw Exception("Error setting bucket properties."); - } - - # Check the response value... - $status = $response[0]['http_code']; - if ($status != 204) { - throw Exception("Error setting bucket properties."); - } - } - - /** - * Retrieve an associative array of all bucket properties. - * @return Array - */ - function getProperties() { - # Run the request... - $params = array('props' => 'true', 'keys' => 'false'); - $url = RiakUtils::buildRestPath($this->client, $this, NULL, NULL, $params); - $response = RiakUtils::httpRequest('GET', $url); - - # Use a RiakObject to interpret the response, we are just interested in the value. - $obj = new RiakObject($this->client, $this, NULL); - $obj->populate($response, array(200)); - if (!$obj->exists()) { - throw Exception("Error getting bucket properties."); - } - - $props = $obj->getData(); - $props = $props["props"]; - - return $props; - } - - /** - * Retrieve an array of all keys in this bucket. - * Note: this operation is pretty slow. - * @return Array - */ - function getKeys() { - $params = array('props'=>'false','keys'=>'true'); - $url = RiakUtils::buildRestPath($this->client, $this, NULL, NULL, $params); - $response = RiakUtils::httpRequest('GET', $url); - - # Use a RiakObject to interpret the response, we are just interested in the value. - $obj = new RiakObject($this->client, $this, NULL); - $obj->populate($response, array(200)); - if (!$obj->exists()) { - throw Exception("Error getting bucket properties."); - } - $keys = $obj->getData(); - return array_map("urldecode",$keys["keys"]); - } - - /** - * Search a secondary index - * @author Eric Stevens - * @param string $indexName - The name of the index to search - * @param string $indexType - The type of index ('int' or 'bin') - * @param string|int $startOrExact - * @param string|int optional $end - * @param bool $dedupe - whether to eliminate duplicate entries if any - * @return array of RiakLinks - */ - function indexSearch($indexName, $indexType, $startOrExact, $end=NULL, $dedupe=false) { - $url = RiakUtils::buildIndexPath($this->client, $this, "{$indexName}_{$indexType}", $startOrExact, $end, NULL); - $response = RiakUtils::httpRequest('GET', $url); - - $obj = new RiakObject($this->client, $this, NULL); - $obj->populate($response, array(200)); - if (!$obj->exists()) { - throw Exception("Error searching index."); - } - $data = $obj->getData(); - $keys = array_map("urldecode",$data["keys"]); - - $seenKeys = array(); - foreach($keys as $id=>&$key) { - if ($dedupe) { - if (isset($seenKeys[$key])) { - unset($keys[$id]); - continue; - } - $seenKeys[$key] = true; - } - $key = new RiakLink($this->name, $key); - $key->client = $this->client; - } - return $keys; - } - -} diff --git a/core/NoSQL/Riak/RiakClient.class.php b/core/NoSQL/Riak/RiakClient.class.php deleted file mode 100644 index dcdb3249f2..0000000000 --- a/core/NoSQL/Riak/RiakClient.class.php +++ /dev/null @@ -1,195 +0,0 @@ -host = $host; - $this->port = $port; - $this->prefix = $prefix; - $this->mapred_prefix = $mapred_prefix; - $this->indexPrefix='buckets'; - $this->clientid = 'php_' . base_convert(mt_rand(), 10, 36); - $this->r = 2; - $this->w = 2; - $this->dw = 2; - } - - /** - * Get the R-value setting for this RiakClient. (default 2) - * @return integer - */ - function getR() { - return $this->r; - } - - /** - * Set the R-value for this RiakClient. This value will be used - * for any calls to get(...) or getBinary(...) where where 1) no - * R-value is specified in the method call and 2) no R-value has - * been set in the RiakBucket. - * @param integer $r - The R value. - * @return $this - */ - function setR($r) { - $this->r = $r; - return $this; - } - - /** - * Get the W-value setting for this RiakClient. (default 2) - * @return integer - */ - function getW() { - return $this->w; - } - - /** - * Set the W-value for this RiakClient. See setR(...) for a - * description of how these values are used. - * @param integer $w - The W value. - * @return $this - */ - function setW($w) { - $this->w = $w; - return $this; - } - - /** - * Get the DW-value for this ClientOBject. (default 2) - * @return integer - */ - function getDW() { - return $this->dw; - } - - /** - * Set the DW-value for this RiakClient. See setR(...) for a - * description of how these values are used. - * @param integer $dw - The DW value. - * @return $this - */ - function setDW($dw) { - $this->dw = $dw; - return $this; - } - - /** - * Get the clientID for this RiakClient. - * @return string - */ - function getClientID() { - return $this->clientid; - } - - /** - * Set the clientID for this RiakClient. Should not be called - * unless you know what you are doing. - * @param string $clientID - The new clientID. - * @return $this - */ - function setClientID($clientid) { - $this->clientid = $clientid; - return $this; - } - - /** - * Get the bucket by the specified name. Since buckets always exist, - * this will always return a RiakBucket. - * @return RiakBucket - */ - function bucket($name) { - return new RiakBucket($this, $name); - } - - /** - * Get all buckets. - * @return array() of RiakBucket objects - */ - function buckets() { - $url = RiakUtils::buildRestPath($this); - $response = RiakUtils::httpRequest('GET', $url.'?buckets=true'); - $response_obj = json_decode($response[1]); - $buckets = array(); - foreach($response_obj->buckets as $name) { - $buckets[] = $this->bucket($name); - } - return $buckets; - } - - /** - * Check if the Riak server for this RiakClient is alive. - * @return boolean - */ - function isAlive() { - $url = 'http://' . $this->host . ':' . $this->port . '/ping'; - $response = RiakUtils::httpRequest('GET', $url); - return ($response != NULL) && ($response[1] == 'OK'); - } - - - # MAP/REDUCE/LINK FUNCTIONS - - /** - * Start assembling a Map/Reduce operation. - * @see RiakMapReduce::add() - * @return RiakMapReduce - */ - function add($params) { - $mr = new RiakMapReduce($this); - $args = func_get_args(); - return call_user_func_array(array(&$mr, "add"), $args); - } - - /** - * Start assembling a Map/Reduce operation. This command will - * return an error unless executed against a Riak Search cluster. - * @see RiakMapReduce::search() - * @return RiakMapReduce - */ - function search($params) { - $mr = new RiakMapReduce($this); - $args = func_get_args(); - return call_user_func_array(array(&$mr, "search"), $args); - } - - /** - * Start assembling a Map/Reduce operation. - * @see RiakMapReduce::link() - */ - function link($params) { - $mr = new RiakMapReduce($this); - $args = func_get_args(); - return call_user_func_array(array(&$mr, "link"), $args); - } - - /** - * Start assembling a Map/Reduce operation. - * @see RiakMapReduce::map() - */ - function map($params) { - $mr = new RiakMapReduce($this); - $args = func_get_args(); - return call_user_func_array(array(&$mr, "map"), $args); - } - - /** - * Start assembling a Map/Reduce operation. - * @see RiakMapReduce::reduce() - */ - function reduce($params) { - $mr = new RiakMapReduce($this); - $args = func_get_args(); - return call_user_func_array(array(&$mr, "reduce"), $args); - } -} diff --git a/core/NoSQL/Riak/RiakLink.class.php b/core/NoSQL/Riak/RiakLink.class.php deleted file mode 100644 index 80c2f493f1..0000000000 --- a/core/NoSQL/Riak/RiakLink.class.php +++ /dev/null @@ -1,120 +0,0 @@ -bucket = $bucket; - $this->key = $key; - $this->tag = $tag; - $this->client = NULL; - } - - /** - * Retrieve the RiakObject to which this link points. - * @param integer $r - The R-value to use. - * @return RiakObject - */ - function get($r=NULL) { - return $this->client->bucket($this->bucket)->get($this->key, $r); - } - - /** - * Retrieve the RiakObject to which this link points, as a binary. - * @param integer $r - The R-value to use. - * @return RiakObject - */ - function getBinary($r=NULL) { - return $this->client->bucket($this->bucket)->getBinary($this->key, $r); - } - - /** - * Get the bucket name of this link. - * @return string - */ - function getBucket() { - return $this->bucket; - } - - /** - * Set the bucket name of this link. - * @param string $name - The bucket name. - * @return $this - */ - function setBucket($name) { - $this->bucket = $bucket; - return $this; - } - - /** - * Get the key of this link. - * @return string - */ - function getKey() { - return $this->key; - } - - /** - * Set the key of this link. - * @param string $key - The key. - * @return $this - */ - function setKey($key) { - $this->key = $key; - return $this; - } - - /** - * Get the tag of this link. - * @return string - */ - function getTag() { - if ($this->tag == null) - return $this->bucket; - else - return $this->tag; - } - - /** - * Set the tag of this link. - * @param string $tag - The tag. - * @return $this - */ - function setTag($tag) { - $this->tag = $tag; - return $this; - } - - /** - * Convert this RiakLink object to a link header string. Used internally. - */ - function toLinkHeader($client) { - $link = "prefix . "/" . - urlencode($this->bucket) . "/" . - urlencode($this->key) . ">; riaktag=\"" . - urlencode($this->getTag()) . "\""; - return $link; - } - - /** - * Return true if the links are equal. - * @param RiakLink $link - A RiakLink object. - * @return boolean - */ - function isEqual($link) { - $is_equal = - ($this->bucket == $link->bucket) && - ($this->key == $link->key) && - ($this->getTag() == $link->getTag()); - return $is_equal; - } -} diff --git a/core/NoSQL/Riak/RiakLinkPhase.class.php b/core/NoSQL/Riak/RiakLinkPhase.class.php deleted file mode 100644 index 7590eb96f1..0000000000 --- a/core/NoSQL/Riak/RiakLinkPhase.class.php +++ /dev/null @@ -1,30 +0,0 @@ -bucket = $bucket; - $this->tag = $tag; - $this->keep = $keep; - } - - /** - * Convert the RiakLinkPhase to an associative array. Used - * internally. - */ - function to_array() { - $stepdef = array("bucket"=>$this->bucket, - "tag"=>$this->tag, - "keep"=>$this->keep); - return array("link"=>$stepdef); - } -} diff --git a/core/NoSQL/Riak/RiakMapReduce.class.php b/core/NoSQL/Riak/RiakMapReduce.class.php deleted file mode 100644 index f1553e905d..0000000000 --- a/core/NoSQL/Riak/RiakMapReduce.class.php +++ /dev/null @@ -1,274 +0,0 @@ -client = $client; - $this->phases = array(); - $this->inputs = array(); - $this->input_mode = NULL; - $this->key_filters = array(); - } - - /** - * Add inputs to a map/reduce operation. This method takes three - * different forms, depending on the provided inputs. You can - * specify either a RiakObject, a string bucket name, or a bucket, - * key, and additional arg. - * @param mixed $arg1 - RiakObject or Bucket - * @param mixed $arg2 - Key or blank - * @param mixed $arg3 - Arg or blank - * @return RiakMapReduce - */ - function add($arg1, $arg2=NULL, $arg3=NULL) { - if (func_num_args() == 1) { - if ($arg1 instanceof RiakObject) - return $this->add_object($arg1); - else - return $this->add_bucket($arg1); - } - return $this->add_bucket_key_data($arg1, (string) $arg2, $arg3); - } - - /** - * Private. - */ - private function add_object($obj) { - return $this->add_bucket_key_data($obj->bucket->name, $obj->key, NULL); - } - - /** - * Private. - */ - private function add_bucket_key_data($bucket, $key, $data) { - if ($this->input_mode == "bucket") - throw new Exception("Already added a bucket, can't add an object."); - $this->inputs[] = array($bucket, $key, $data); - return $this; - } - - /** - * Private. - * @return $this - */ - private function add_bucket($bucket) { - $this->input_mode = "bucket"; - $this->inputs = $bucket; - return $this; - } - - /** - * Begin a map/reduce operation using a Search. This command will - * return an error unless executed against a Riak Search cluster. - * @param string $bucket - The Bucket to search. @param string - * query - The Query to execute. (Lucene syntax.) @return - * RiakMapReduce - */ - function search($bucket, $query) { - $this->inputs = array("module"=>"riak_search", "function"=>"mapred_search", "arg"=>array($bucket, $query)); - return $this; - } - - /** - * Add a link phase to the map/reduce operation. - * @param string $bucket - Bucket name (default '_', which means all - * buckets) - * @param string $tag - Tag (default '_', which means all buckets) - * @param boolean $keep - Flag whether to keep results from this - * stage in the map/reduce. (default FALSE, unless this is the last - * step in the phase) - * @return $this - */ - function link($bucket='_', $tag='_', $keep=FALSE) { - $this->phases[] = new RiakLinkPhase($bucket, $tag, $keep); - return $this; - } - - /** - * Add a map phase to the map/reduce operation. - * @param mixed $function - Either a named Javascript function (ie: - * "Riak.mapValues"), or an anonymous javascript function (ie: - * "function(...) { ... }" or an array ["erlang_module", - * "function"]. - * @param array() $options - An optional associative array - * containing "language", "keep" flag, and/or "arg". - * @return $this - */ - function map($function, $options=array()) { - $language = is_array($function) ? "erlang" : "javascript"; - $this->phases[] = new RiakMapReducePhase("map", - $function, - RiakUtils::get_value("language", $options, $language), - RiakUtils::get_value("keep", $options, FALSE), - RiakUtils::get_value("arg", $options, NULL)); - return $this; - } - - /** - * Add a reduce phase to the map/reduce operation. - * @param mixed $function - Either a named Javascript function (ie: - * "Riak.mapValues"), or an anonymous javascript function (ie: - * "function(...) { ... }" or an array ["erlang_module", - * "function"]. - * @param array() $options - An optional associative array - * containing "language", "keep" flag, and/or "arg". - * @return $this - */ - function reduce($function, $options=array()) { - $language = is_array($function) ? "erlang" : "javascript"; - $this->phases[] = new RiakMapReducePhase("reduce", - $function, - RiakUtils::get_value("language", $options, $language), - RiakUtils::get_value("keep", $options, FALSE), - RiakUtils::get_value("arg", $options, NULL)); - return $this; - } - - /** - * Add a key filter to the map/reduce operation. If there are already - * existing filters, an "and" condition will be used to combine them. - * Alias for key_filter_and - * @param array $filter - a key filter (ie: - * ->key_filter( - * array("tokenize", "-", 2), - * array("between", "20110601", "20110630") - * ) - * @return $this - */ - function key_filter(array $filter /*. ,$filter .*/) { - $args = func_get_args(); - array_unshift($args, 'and'); - return call_user_func_array(array($this, 'key_filter_operator'), $args); - } - - /** - * Add a key filter to the map/reduce operation. If there are already - * existing filters, an "and" condition will be used to combine them. - * @param array $filter - a key filter (ie: - * ->key_filter( - * array("tokenize", "-", 2), - * array("between", "20110601", "20110630") - * ) - * @return $this - */ - function key_filter_and(array $filter) { - $args = func_get_args(); - array_unshift($args, 'and'); - return call_user_func_array(array($this, 'key_filter_operator'), $args); - } - - /** - * Adds a key filter to the map/reduce operation. If there are already - * existing filters, an "or" condition will be used to combine with the - * existing filters. - * @param array $filter - * @return $this - */ - function key_filter_or(array $filter /*. ,$filter .*/) { - $args = func_get_args(); - array_unshift($args, 'or'); - return call_user_func_array(array($this, 'key_filter_operator'), $args); - } - - /** - * Adds a key filter to the map/reduce operation. If there are already - * existing filters, the provided conditional operator will be used - * to combine with the existing filters. - * @param string $operator - Operator (usually "and" or "or") - * @param array $filter - * @return $this - */ - function key_filter_operator($operator, $filter /*. ,$filter .*/) { - $filters = func_get_args(); - array_shift($filters); - if ($this->input_mode != 'bucket') - throw new Exception("Key filters can only be used in bucket mode"); - - if (count($this->key_filters) > 0) { - $this->key_filters = array(array( - $operator, - $this->key_filters, - $filters - )); - } else { - $this->key_filters = $filters; - } - return $this; - } - - /** - * Run the map/reduce operation. Returns an array of results, or an - * array of RiakLink objects if the last phase is a link phase. - * @param integer $timeout - Timeout in seconds. - * @return array() - */ - function run($timeout=NULL) { - $num_phases = count($this->phases); - - $linkResultsFlag = FALSE; - - # If there are no phases, then just echo the inputs back to the user. - if ($num_phases == 0) { - $this->reduce(array("riak_kv_mapreduce", "reduce_identity")); - $num_phases = 1; - $linkResultsFlag = TRUE; - } - - # Convert all phases to associative arrays. Also, - # if none of the phases are accumulating, then set the last one to - # accumulate. - $keep_flag = FALSE; - $query = array(); - for ($i = 0; $i < $num_phases; $i++) { - $phase = $this->phases[$i]; - if ($i == ($num_phases - 1) && !$keep_flag) - $phase->keep = TRUE; - if ($phase->keep) $keep_flag = TRUE; - $query[] = $phase->to_array(); - } - - # Add key filters if applicable - if ($this->input_mode == 'bucket' && count($this->key_filters) > 0) { - $this->inputs = array( - 'bucket' => $this->inputs, - 'key_filters' => $this->key_filters - ); - } - - # Construct the job, optionally set the timeout... - $job = array("inputs"=>$this->inputs, "query"=>$query); - if ($timeout != NULL) $job["timeout"] = $timeout; - $content = json_encode($job); - - # Do the request... - $url = "http://" . $this->client->host . ":" . $this->client->port . "/" . $this->client->mapred_prefix; - $response = RiakUtils::httpRequest('POST', $url, array(), $content); - $result = json_decode($response[1]); - - # If the last phase is NOT a link phase, then return the result. - $linkResultsFlag |= (end($this->phases) instanceof RiakLinkPhase); - - # If we don't need to link results, then just return. - if (!$linkResultsFlag) return $result; - - # Otherwise, if the last phase IS a link phase, then convert the - # results to RiakLink objects. - $a = array(); - foreach ($result as $r) { - $tag = isset($r[2]) ? $r[2] : null; - $link = new RiakLink($r[0], $r[1], $tag); - $link->client = $this->client; - $a[] = $link; - } - return $a; - } -} diff --git a/core/NoSQL/Riak/RiakMapReducePhase.class.php b/core/NoSQL/Riak/RiakMapReducePhase.class.php deleted file mode 100644 index 5db9a70958..0000000000 --- a/core/NoSQL/Riak/RiakMapReducePhase.class.php +++ /dev/null @@ -1,50 +0,0 @@ -type = $type; - $this->language = $language; - $this->function = $function; - $this->keep = $keep; - $this->arg = $arg; - } - - /** - * Convert the RiakMapReducePhase to an associative array. Used - * internally. - */ - function to_array() { - $stepdef = array("keep"=>$this->keep, - "language"=>$this->language, - "arg"=>$this->arg); - - if ($this->language == "javascript" && is_array($this->function)) { - $stepdef["bucket"] = $this->function[0]; - $stepdef["key"] = $this->function[1]; - } else if ($this->language == "javascript" && is_string($this->function)) { - if (strpos($this->function, "{") == FALSE) - $stepdef["name"] = $this->function; - else - $stepdef["source"] = $this->function; - } else if ($this->language == "erlang" && is_array($this->function)) { - $stepdef["module"] = $this->function[0]; - $stepdef["function"] = $this->function[1]; - } - - return array(($this->type)=>$stepdef); - } -} diff --git a/core/NoSQL/Riak/RiakObject.class.php b/core/NoSQL/Riak/RiakObject.class.php deleted file mode 100644 index 7472d26aef..0000000000 --- a/core/NoSQL/Riak/RiakObject.class.php +++ /dev/null @@ -1,815 +0,0 @@ -client = $client; - $this->bucket = $bucket; - $this->key = $key; - $this->jsonize = TRUE; - $this->headers = array(); - $this->links = array(); - $this->siblings = NULL; - $this->exists = FALSE; - } - - /** - * Get the bucket of this object. - * @return RiakBucket - */ - function getBucket() { - return $this->bucket; - } - - /** - * Get the key of this object. - * @return string - */ - function getKey() { - return $this->key; - } - - /** - * Get the data stored in this object. Will return a associative - * array, unless the object was constructed with newBinary(...) or - * getBinary(...), in which case this will return a string. - * @return array or string - */ - function getData() { - return $this->data; - } - - /** - * Set the data stored in this object. This data will be - * JSON encoded unless the object was constructed with - * newBinary(...) or getBinary(...). - * @param mixed $data - The data to store. - * @return $data - */ - function setData($data) { - $this->data = $data; - return $this->data; - } - - /** - * Get the HTTP status from the last operation on this object. - * @return integer - */ - function status() { - return $this->headers['http_code']; - } - - /** - * Return true if the object exists, false otherwise. Allows you to - * detect a get(...) or getBinary(...) operation where the object is missing. - * @return boolean - */ - function exists() { - return $this->exists; - } - - /** - * Get the content type of this object. This is either text/json, or - * the provided content type if the object was created via newBinary(...). - * @return string - */ - function getContentType() { - return $this->headers['content-type']; - } - - /** - * Set the content type of this object. - * @param string $content_type - The new content type. - * @return $this - */ - function setContentType($content_type) { - $this->headers['content-type'] = $content_type; - return $this; - } - - /** - * Add a link to a RiakObject. - * @param mixed $obj - Either a RiakObject or a RiakLink object. - * @param string $tag - Optional link tag. (default is bucket name, - * ignored if $obj is a RiakLink object.) - * @return RiakObject - */ - function addLink($obj, $tag=NULL) { - if ($obj instanceof RiakLink) - $newlink = $obj; - else - $newlink = new RiakLink($obj->bucket->name, $obj->key, $tag); - - $this->removeLink($newlink); - $this->links[] = $newlink; - - return $this; - } - - /** - * Remove a link to a RiakObject. - * @param mixed $obj - Either a RiakObject or a RiakLink object. - * @param string $tag - - * @param mixed $obj - Either a RiakObject or a RiakLink object. - * @param string $tag - Optional link tag. (default is bucket name, - * ignored if $obj is a RiakLink object.) - * @return $this - */ - function removeLink($obj, $tag=NULL) { - if ($obj instanceof RiakLink) - $oldlink = $obj; - else - $oldlink = new RiakLink($obj->bucket->name, $obj->key, $tag); - - $a = array(); - foreach ($this->links as $link) { - if (!$link->isEqual($oldlink)) - $a[] = $link; - } - - $this->links = $a; - return $this; - } - - /** - * Return an array of RiakLink objects. - * @return array() - */ - function getLinks() { - # Set the clients before returning... - foreach ($this->links as $link) { - $link->client = $this->client; - } - return $this->links; - } - - /** @section Indexes */ - - /** - * Adds a secondary index to the object - * This will create the index if it does not exist, or will - * append an additional value if the index already exists and - * does not contain the provided value. - * @param string $indexName - * @param string $indexType - Must be one of 'int' or 'bin' - the - * only two index types supported by Riak - * @param string|int optional $explicitValue - If provided, uses this - * value explicitly. If not provided, this will search the object's - * data for a field with the name $indexName, and use that value. - * @return $this - */ - function addIndex($indexName, $indexType=null, $explicitValue = null) { - if ($explicitValue === null) { - $this->addAutoIndex($indexName, $indexType); - return; - } - - if ($indexType !== null) { - $index = strtolower("{$indexName}_{$indexType}"); - } else { - $index = strtolower($indexName); - } - if (!isset($this->indexes[$index])) $this->indexes[$index] = array(); - - if (false === array_search($explicitValue, $this->indexes[$index])) { - $this->indexes[$index][] = $explicitValue; - } - return $this; - } - - /** - * Sets a given index to a specific value or set of values - * @param string $indexName - * @param string $indexType - must be 'bin' or 'int' - * @param array|string|int $values - * @return $this - */ - function setIndex($indexName, $indexType=null, $values) { - if ($indexType !== null) { - $index = strtolower("{$indexName}_{$indexType}"); - } else { - $index = strtolower($indexName); - } - - $this->indexes[$index] = $values; - - return $this; - } - - /** - * Gets the current values for the identified index - * Note, the NULL value has special meaning - when the object is - * ->store()d, this value will be replaced with the current value - * the value of the field matching $indexName from the object's data - * @param string $indexName - * @param string $indexType - */ - function getIndex($indexName, $indexType=null) { - if ($indexType !== null) { - $index = strtolower("{$indexName}_{$indexType}"); - } else { - $index = strtolower($indexName); - } - if (!isset($this->indexes[$index])) return array(); - - return $this->indexes[$index]; - } - - /** - * Removes a specific value from a given index - * @param string $indexName - * @param string $indexType - must be 'bin' or 'int' - * @param string|int optional $explicitValue - * @return $this - */ - function removeIndex($indexName, $indexType=null, $explicitValue = null) { - if ($explicitValue === null) { - $this->removeAutoIndex($indexName, $indexType); - return; - } - if ($indexType !== null) { - $index = strtolower("{$indexName}_{$indexType}"); - } else { - $index = strtolower($indexName); - } - - if (!isset($this->indexes[$index])) return; - - if (false !== ($position = array_search($explicitValue, $this->indexes[$index]))) { - unset($this->indexes[$index][$position]); - } - - return $this; - } - - /** - * Bulk index removal - * If $indexName and $indexType are provided, all values for the - * identified index are removed. - * If just $indexName is provided, all values for all types of - * the identified index are removed - * If neither is provided, all indexes are removed from the object - * - * Note that this function will NOT affect auto indexes - * - * @param string optional $indexName - * @param string optional $indexType - * - * @return $this - */ - function removeAllIndexes($indexName=null, $indexType=null) { - if ($indexName === null) { - $this->indexes = array(); - } else if ($indexType === null) { - $indexName = strtolower($indexName); - unset($this->indexes["{$indexName}_int"]); - unset($this->indexes["{$indexName}_bin"]); - } else { - unset($this->indexes[strtolower("{$indexName}_{$indexType}")]); - } - - return $this; - } - - /** @section Auto Indexes */ - - /** - * Adds an automatic secondary index to the object - * The value of an automatic secondary index is determined at - * time of ->store() by looking for an $fieldName key - * in the object's data. - * - * @param string $fieldName - * @param string $indexType Must be one of 'int' or 'bin' - * - * @return $this - */ - function addAutoIndex($fieldName, $indexType=null) { - if ($indexType !== null) { - $index = strtolower("{$fieldName}_{$indexType}"); - } else { - $index = strtolower($fieldName); - } - $this->autoIndexes[$index] = $fieldName; - - return $this; - } - - /** - * Returns whether the object has a given auto index - * @param string $fieldName - * @param string $indexType - must be one of 'int' or 'bin' - * - * @return boolean - */ - function hasAutoIndex($fieldName, $indexType=null) { - if ($indexType !== null) { - $index = strtolower("{$fieldName}_{$indexType}"); - } else { - $index = strtolower($fieldName); - } - return isset($this->autoIndexes[$index]); - } - - /** - * Removes a given auto index from the object - * - * @param string $fieldName - * @param string $indexType - * - * @return $this - */ - function removeAutoIndex($fieldName, $indexType=null) { - if ($indexType !== null) { - $index = strtolower("{$fieldName}_{$indexType}"); - } else { - $index = strtolower($fieldName); - } - unset($this->autoIndexes[$index]); - return $this; - } - - /** - * Removes all auto indexes - * If $fieldName is not provided, all auto indexes on the - * object are stripped, otherwise just indexes on the given field - * are stripped. - * If $indexType is not provided, all types of index for the - * given field are stripped, otherwise just a given type is stripped. - * - * @param string $fieldName - * @param string $indexType - * - * @return $this - */ - function removeAllAutoIndexes($fieldName = null, $indexType = null) { - if ($fieldName === null) { - $this->autoIndexes = array(); - } else if ($indexType === null) { - $fieldName = strtolower($fieldName); - unset($this->autoIndexes["{$fieldName}_bin"]); - unset($this->autoIndexes["{$fieldName}_int"]); - } else { - unset($this->autoIndexes[strtolower("{$fieldName}_{$indexType}")]); - } - } - - /** @section Meta Data */ - - /** - * Gets a given metadata value - * Returns null if no metadata value with the given name exists - * - * @param string $metaName - * - * @return string|null - */ - function getMeta($metaName) { - $metaName = strtolower($metaName); - if (isset($this->meta[$metaName])) return $this->meta[$metaName]; - return null; - } - - /** - * Sets a given metadata value, overwriting an existing - * value with the same name if it exists. - * @param string $metaName - * @param string $value - * @return $this - */ - function setMeta($metaName, $value) { - $this->meta[strtolower($metaName)] = $value; - return $this; - } - - /** - * Removes a given metadata value - * @param string $metaName - * @return $this - */ - function removeMeta($metaName) { - unset ($this->meta[strtolower($metaName)]); - return $this; - } - - /** - * Gets all metadata values - * @return array=string - */ - function getAllMeta() { - return $this->meta; - } - - /** - * Strips all metadata values - * @return $this; - */ - function removeAllMeta() { - $this->meta = array(); - return $this; - } - - /** - * Store the object in Riak. When this operation completes, the - * object could contain new metadata and possibly new data if Riak - * contains a newer version of the object according to the object's - * vector clock. - * @param integer $w - W-value, wait for this many partitions to respond - * before returning to client. - * @param integer $dw - DW-value, wait for this many partitions to - * confirm the write before returning to client. - * @return $this - */ - function store($w=NULL, $dw=NULL) { - # Use defaults if not specified... - $w = $this->bucket->getW($w); - $dw = $this->bucket->getDW($w); - - # Construct the URL... - $params = array('returnbody' => 'true', 'w' => $w, 'dw' => $dw); - $url = RiakUtils::buildRestPath($this->client, $this->bucket, $this->key, NULL, $params); - - # Construct the headers... - $headers = array('Accept: text/plain, */*; q=0.5', - 'Content-Type: ' . $this->getContentType(), - 'X-Riak-ClientId: ' . $this->client->getClientID()); - - # Add the vclock if it exists... - if ($this->vclock() != NULL) { - $headers[] = 'X-Riak-Vclock: ' . $this->vclock(); - } - - # Add the Links... - foreach ($this->links as $link) { - $headers[] = 'Link: ' . $link->toLinkHeader($this->client); - } - - # Add the auto indexes... - $collisions = array(); - foreach($this->autoIndexes as $index=>$fieldName) { - $value = null; - // look up the value - if (isset($this->data[$fieldName])) { - $value = $this->data[$fieldName]; - $headers[] = "x-riak-index-$index: ".urlencode($value); - - // look for value collisions with normal indexes - if (isset($this->indexes[$index])) { - if (false !== array_search($value, $this->indexes[$index])) { - $collisions[$index] = $value; - } - } - } - } - count($this->autoIndexes) > 0 - ? $this->meta['x-rc-autoindex'] = json_encode($this->autoIndexes) - : $this->meta['x-rc-autoindex'] = null; - count($collisions) > 0 - ? $this->meta['x-rc-autoindexcollision'] = json_encode($collisions) - : $this->meta['x-rc-autoindexcollision'] = null; - - # Add the indexes - foreach ($this->indexes as $index=>$values) { - $headers[] = "x-riak-index-$index: " . join(', ', array_map('urlencode', $values)); - } - - - # Add the metadata... - foreach($this->meta as $metaName=>$metaValue) { - if ($metaValue !== null) $headers[] = "X-Riak-Meta-$metaName: $metaValue"; - } - - if ($this->jsonize) { - $content = json_encode($this->getData()); - } else { - $content = $this->getData(); - } - - $method = $this->key ? 'PUT' : 'POST'; - - # Run the operation. - $response = RiakUtils::httpRequest($method, $url, $headers, $content); - $this->populate($response, array(200, 201, 300)); - return $this; - } - - /** - * Reload the object from Riak. When this operation completes, the - * object could contain new metadata and a new value, if the object - * was updated in Riak since it was last retrieved. - * @param integer $r - R-Value, wait for this many partitions to respond - * before returning to client. - * @return $this - */ - function reload($r=NULL) { - # Do the request... - $r = $this->bucket->getR($r); - $params = array('r' => $r); - $url = RiakUtils::buildRestPath($this->client, $this->bucket, $this->key, NULL, $params); - $response = RiakUtils::httpRequest('GET', $url); - $this->populate($response, array(200, 300, 404)); - - # If there are siblings, load the data for the first one by default... - if ($this->hasSiblings()) { - $obj = $this->getSibling(0); - $this->setData($obj->getData()); - } - - return $this; - } - - /** - * Delete this object from Riak. - * @param integer $dw - DW-value. Wait until this many partitions have - * deleted the object before responding. - * @return $this - */ - function delete($dw=NULL) { - # Use defaults if not specified... - $dw = $this->bucket->getDW($dw); - - # Construct the URL... - $params = array('dw' => $dw); - $url = RiakUtils::buildRestPath($this->client, $this->bucket, $this->key, NULL, $params); - - # Run the operation... - $response = RiakUtils::httpRequest('DELETE', $url); - $this->populate($response, array(204, 404)); - - return $this; - } - - - /** - * Reset this object. - * @return $this - */ - private function clear() { - $this->headers = array(); - $this->links = array(); - $this->data = NULL; - $this->exists = FALSE; - $this->siblings = NULL; - $this->indexes = array(); - $this->autoIndexes = array(); - $this->meta = array(); - return $this; - } - - /** - * Get the vclock of this object. - * @return string - */ - private function vclock() { - if (array_key_exists('x-riak-vclock', $this->headers)) { - return $this->headers['x-riak-vclock']; - } else { - return NULL; - } - } - - /** - * Given the output of RiakUtils::httpRequest and a list of - * statuses, populate the object. Only for use by the Riak client - * library. - * @return $this - */ - function populate($response, $expected_statuses) { - $this->clear(); - - # If no response given, then return. - if ($response == NULL) { - return $this; - } - - # Update the object... - $this->headers = $response[0]; - $this->data = $response[1]; - $status = $this->status(); - - # Check if the server is down (status==0) - if ($status == 0) { - $m = 'Could not contact Riak Server: http://' . $this->client->host . ':' . $this->client->port . '!'; - throw new Exception($m); - } - - # Verify that we got one of the expected statuses. Otherwise, throw an exception. - if (!in_array($status, $expected_statuses)) { - $m = 'Expected status ' . implode(' or ', $expected_statuses) . ', received ' . $status . ' with body: ' . $this->data; - throw new Exception($m); - } - - # If 404 (Not Found), then clear the object. - if ($status == 404) { - $this->clear(); - return $this; - } - - # If we are here, then the object exists... - $this->exists = TRUE; - - # Parse the link header... - if (array_key_exists("link", $this->headers)) { - $this->populateLinks($this->headers["link"]); - } - - # Parse the index and metadata headers - $this->indexes = array(); - $this->autoIndexes = array(); - $this->meta = array(); - foreach($this->headers as $key=>$val) { - if (preg_match('~^x-riak-([^-]+)-(.+)$~', $key, $matches)) { - switch($matches[1]) { - case 'index': - $index = substr($matches[2], 0, strrpos($matches[2], '_')); - $type = substr($matches[2], strlen($index)+1); - $this->setIndex($index, $type, array_map('urldecode', explode(', ', $val))); - break; - case 'meta': - $this->meta[$matches[2]] = $val; - break; - } - } - } - - # If 300 (Siblings), then load the first sibling, and - # store the rest. - if ($status == 300) { - $siblings = explode("\n", trim($this->data)); - array_shift($siblings); # Get rid of 'Siblings:' string. - $this->siblings = $siblings; - $this->exists = TRUE; - return $this; - } - - if ($status == 201) { - $path_parts = explode('/', $this->headers['location']); - $this->key = array_pop($path_parts); - } - - # Possibly json_decode... - if (($status == 200 || $status == 201) && $this->jsonize) { - $this->data = json_decode($this->data, true); - } - - # Look for auto indexes and deindex explicit values if appropriate - if (isset($this->meta['x-rc-autoindex'])) { - # dereference the autoindexes - $this->autoIndexes = json_decode($this->meta['x-rc-autoindex'], true); - $collisions = isset($this->meta['x-rc-autoindexcollision']) ? json_decode($this->meta['x-rc-autoindexcollision'], true) : array(); - - foreach($this->autoIndexes as $index=>$fieldName) { - $value = null; - if (isset($this->data[$fieldName])) { - $value = $this->data[$fieldName]; - if (isset($collisions[$index]) && $collisions[$index] === $value) { - // Don't strip this value, it's an explicit index. - } else { - if ($value !== null) $this->removeIndex($index, null, $value); - } - } - - if (!isset($collisions[$index])) { - // Do not delete this value if - } - } - } - - return $this; - } - - /** - * Private. - * @return $this - */ - private function populateLinks($linkHeaders) { - $linkHeaders = explode(",", trim($linkHeaders)); - foreach ($linkHeaders as $linkHeader) { - $linkHeader = trim($linkHeader); - $matches = array(); - $result = preg_match("/\<\/([^\/]+)\/([^\/]+)\/([^\/]+)\>; ?riaktag=\"([^\"]+)\"/", $linkHeader, $matches); - if ($result == 1) { - $this->links[] = new RiakLink(urldecode($matches[2]), urldecode($matches[3]), urldecode($matches[4])); - } - } - - return $this; - } - - /** - * Return true if this object has siblings. - * @return boolean - */ - function hasSiblings() { - return ($this->getSiblingCount() > 0); - } - - /** - * Get the number of siblings that this object contains. - * @return integer - */ - function getSiblingCount() { - return count($this->siblings); - } - - /** - * Retrieve a sibling by sibling number. - * @param integer $i - Sibling number. - * @param integer $r - R-Value. Wait until this many partitions - * have responded before returning to client. - * @return RiakObject. - */ - function getSibling($i, $r=NULL) { - # Use defaults if not specified. - $r = $this->bucket->getR($r); - - # Run the request... - $vtag = $this->siblings[$i]; - $params = array('r' => $r, 'vtag' => $vtag); - $url = RiakUtils::buildRestPath($this->client, $this->bucket, $this->key, NULL, $params); - $response = RiakUtils::httpRequest('GET', $url); - - # Respond with a new object... - $obj = new RiakObject($this->client, $this->bucket, $this->key); - $obj->jsonize = $this->jsonize; - $obj->populate($response, array(200)); - return $obj; - } - - /** - * Retrieve an array of siblings. - * @param integer $r - R-Value. Wait until this many partitions have - * responded before returning to client. - * @return array of RiakObject - */ - function getSiblings($r=NULL) { - $a = array(); - for ($i = 0; $i<$this->getSiblingCount(); $i++) { - $a[] = $this->getSibling($i, $r); - } - return $a; - } - - /** - * Start assembling a Map/Reduce operation. - * @see RiakMapReduce::add() - * @return RiakMapReduce - */ - function add($params) { - $mr = new RiakMapReduce($this->client); - $mr->add($this->bucket->name, $this->key); - $args = func_get_args(); - return call_user_func_array(array(&$mr, "add"), $args); - } - - /** - * Start assembling a Map/Reduce operation. - * @see RiakMapReduce::link() - * @return RiakMapReduce - */ - function link($params) { - $mr = new RiakMapReduce($this->client); - $mr->add($this->bucket->name, $this->key); - $args = func_get_args(); - return call_user_func_array(array(&$mr, "link"), $args); - } - - /** - * Start assembling a Map/Reduce operation. - * @see RiakMapReduce::map() - * @return RiakMapReduce - */ - function map($params) { - $mr = new RiakMapReduce($this->client); - $mr->add($this->bucket->name, $this->key); - $args = func_get_args(); - return call_user_func_array(array(&$mr, "map"), $args); - } - - /** - * Start assembling a Map/Reduce operation. - * @see RiakMapReduce::reduce() - * @return RiakMapReduce - */ - function reduce($params) { - $mr = new RiakMapReduce($this->client); - $mr->add($this->bucket->name, $this->key); - $args = func_get_args(); - return call_user_func_array(array(&$mr, "reduce"), $args); - } -} diff --git a/core/NoSQL/Riak/RiakStringIO.class.php b/core/NoSQL/Riak/RiakStringIO.class.php deleted file mode 100644 index 0a53ddfaf5..0000000000 --- a/core/NoSQL/Riak/RiakStringIO.class.php +++ /dev/null @@ -1,19 +0,0 @@ -contents = ''; - } - - function write($ch, $data) { - $this->contents .= $data; - return strlen($data); - } - - function contents() { - return $this->contents; - } -} diff --git a/core/NoSQL/Riak/RiakUtils.class.php b/core/NoSQL/Riak/RiakUtils.class.php deleted file mode 100644 index 10c0c389ee..0000000000 --- a/core/NoSQL/Riak/RiakUtils.class.php +++ /dev/null @@ -1,189 +0,0 @@ -host . ':' . $client->port; - $path.= '/' . $client->prefix; - - # Add '.../bucket' - if (!is_null($bucket) && $bucket instanceof RiakBucket) { - $path .= '/' . urlencode($bucket->name); - } - - # Add '.../key' - if (!is_null($key)) { - $path .= '/' . urlencode($key); - } - - # Add '.../bucket,tag,acc/bucket,tag,acc' - if (!is_null($spec)) { - $s = ''; - foreach($spec as $el) { - if ($s != '') $s .= '/'; - $s .= urlencode($el[0]) . ',' . urlencode($el[1]) . ',' . $el[2] . '/'; - } - $path .= '/' . $s; - } - - # Add query parameters. - if (!is_null($params)) { - $s = ''; - foreach ($params as $key => $value) { - if ($s != '') $s .= '&'; - $s .= urlencode($key) . '=' . urlencode($value); - } - - $path .= '?' . $s; - } - - return $path; - } - - /** - * Given a RiakClient, RiakBucket, Key, LinkSpec, and Params, - * construct and return a URL for searching secondary indexes. - * @author Eric Stevens - * @param RiakClient $client - * @param RiakBucket $bucket - * @param string $index - Index Name & type (eg, "indexName_bin") - * @param string|int $start - Starting value or exact match if no ending value - * @param string|int $end - Ending value for range search - * @param array $params - Any extra query parameters to pass on the URL - * @return string URL - */ - public static function buildIndexPath(RiakClient $client, RiakBucket $bucket, $index, $start, $end=NULL, array $params=NULL) { - # Build 'http://hostname:port/prefix/bucket' - $path = array('http:/',$client->host.':'.$client->port,$client->indexPrefix); - - # Add '.../bucket' - $path[] = urlencode($bucket->name); - - # Add '.../index' - $path[] = 'index'; - - # Add '.../index_type' - $path[] = urlencode($index); - - # Add .../(start|exact) - $path[] = urlencode($start); - - if (!is_null($end)) { - $path[] = urlencode($end); - } - - // faster than repeated string concatenations - $path = join('/', $path); - - # Add query parameters. - if (!is_null($params)) { - // Most users will have the http PECL extension - if (func_exists('http_build_query')) { - $path .= '?' . http_build_query($params, '', '&'); - } else { - // In case they don't have the http PECL extension - $s = array(); - foreach ($params as $key => $value) { - $s[] = urlencode($key) . '=' . urlencode($value); - } - - $path .= '?' . join('&', $s); - } - } - - return $path; - } - - /** - * Given a Method, URL, Headers, and Body, perform and HTTP request, - * and return an array of arity 2 containing an associative array of - * response headers and the response body. - */ - public static function httpRequest($method, $url, $request_headers = array(), $obj = '') { - # Set up curl - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers); - - if ($method == 'GET') { - curl_setopt($ch, CURLOPT_HTTPGET, 1); - } else if ($method == 'POST') { - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $obj); - } else if ($method == 'PUT') { - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); - curl_setopt($ch, CURLOPT_POSTFIELDS, $obj); - } else if ($method == 'DELETE') { - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); - } - - # Capture the response headers... - $response_headers_io = new RiakStringIO(); - curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(&$response_headers_io, 'write')); - - # Capture the response body... - $response_body_io = new RiakStringIO(); - curl_setopt($ch, CURLOPT_WRITEFUNCTION, array(&$response_body_io, 'write')); - - try { - # Run the request. - curl_exec($ch); - $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - curl_close($ch); - - # Get the headers... - $parsed_headers = RiakUtils::parseHttpHeaders($response_headers_io->contents()); - $response_headers = array("http_code"=>$http_code); - foreach ($parsed_headers as $key=>$value) { - $response_headers[strtolower($key)] = $value; - } - - # Get the body... - $response_body = $response_body_io->contents(); - - # Return a new RiakResponse object. - return array($response_headers, $response_body); - } catch (Exception $e) { - curl_close($ch); - error_log('Error: ' . $e->getMessage()); - return NULL; - } - } - - /** - * Parse an HTTP Header string into an asssociative array of - * response headers. - */ - static function parseHttpHeaders($headers) { - $retVal = array(); - $fields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ', $headers)); - foreach( $fields as $field ) { - if( preg_match('/([^:]+): (.+)/m', $field, $match) ) { - $match[1] = preg_replace('/(?<=^|[\x09\x20\x2D])./e', 'strtoupper("\0")', strtolower(trim($match[1]))); - if( isset($retVal[$match[1]]) ) { - $retVal[$match[1]] = array($retVal[$match[1]], $match[2]); - } else { - $retVal[$match[1]] = trim($match[2]); - } - } - } - return $retVal; - } -} From e44b3c726ddd307633f9590f8ddfe6c7e91e97cf Mon Sep 17 00:00:00 2001 From: "m.klkvsk" Date: Tue, 27 Mar 2012 13:35:18 +0400 Subject: [PATCH 047/418] fix for single string key --- core/NoSQL/NoSqlDAO.class.php | 45 ++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index bdf8b71b24..b938de2046 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -304,30 +304,31 @@ public function getListByView($view, $keys, $criteria=null) { case 'CouchDB': { // собираем правильное имя вьюшки $view = self::COUCHDB_VIEW_PREFIX.$view; - // собираем ключи - $key = ''; + // приводим к массиву даже если ключ один if( !is_array($keys) ) { - $key = $keys; - } else { - // проверяем что в массиве ключей есть хоть один - if( count($keys)<1 ) { - throw new WrongArgumentException( '$keys must be an array with one or more values' ); - } - if( count($keys)==1 ) { - $key = array_shift($keys); - } else { - foreach($keys as &$val) { - if( is_null($val) ) { - $val = 'null'; - } elseif(is_numeric($val)) { - //$val = $val; - } else { - $val = '"'.$val.'"'; - } - } - $key = '['.implode(',', $keys).']'; - } + $keys = array($keys); } + // проверяем что в массиве ключей есть хоть один + if( count($keys)<1 ) { + throw new WrongArgumentException( '$keys must be an array with one or more values' ); + } + // проверяем типы + foreach($keys as &$val) { + if( is_null($val) ) { + $val = 'null'; + } elseif(is_numeric($val)) { + //$val = $val; + } else { + $val = '"'.$val.'"'; + } + } + // сериализуем + if( count($keys)==1 ) { + $key = array_shift($keys); + } else { + $key = '['.implode(',', $keys).']'; + } + $params['key'] = $key; } break; default: { From ad714b2bef49cb478c723573a7108b3e1ee2bdca Mon Sep 17 00:00:00 2001 From: "m.klkvsk" Date: Tue, 27 Mar 2012 13:50:57 +0400 Subject: [PATCH 048/418] fix for getAllObjects to get full doc --- core/NoSQL/CouchDB.class.php | 8 +++++--- core/NoSQL/NoSqlDAO.class.php | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/core/NoSQL/CouchDB.class.php b/core/NoSQL/CouchDB.class.php index ca9d9a1e87..5099db3317 100644 --- a/core/NoSQL/CouchDB.class.php +++ b/core/NoSQL/CouchDB.class.php @@ -190,10 +190,12 @@ public function getAllObjects() { Assert::isString($dbname); Assert::isNotEmpty($dbname); - $response = $this->exec( $this->getUrl($dbname, '_all_docs'), self::GET ); + $response = $this->exec( $this->getUrl($dbname, '_all_docs', array('include_docs' => 'true')), self::GET ); $list = array(); if( isset($response['total_rows']) && isset($response['rows']) ) { - $list = $response['rows']; + foreach ($response['rows'] as $row) { + $list[] = $row['doc']; + } } return $list; @@ -259,7 +261,7 @@ public function getCustomList() { Assert::isNotEmptyArray($params); } - //die( $this->getUrl($dbname, $view, $params) ); + //die( $this->getUrl($dbname, $view, $params) ); $response = $this->exec( $this->getUrl($dbname, $view, $params), self::GET ); $list = array(); if( isset($response['total_rows']) && isset($response['rows']) ) { diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index b938de2046..afdf427218 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -80,7 +80,7 @@ public function getPlainList($expires = Cache::EXPIRES_MEDIUM) { $stack = $this->getLink()->getAllObjects( $this->getTable() ); if( !empty($stack) ) { foreach( $stack as $row ) { - $object = $this->getById( $row['id'] ); + $object = $this->makeNoSqlObject($row); $list[ $object->getId() ] = $object; } } From 85c54424f2512a2c576e8a84e2080852c7468741 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 27 Mar 2012 16:44:37 +0400 Subject: [PATCH 049/418] nosql fix --- core/NoSQL/NoSQL.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php index 1ffd3c0f62..405d44f593 100644 --- a/core/NoSQL/NoSQL.class.php +++ b/core/NoSQL/NoSQL.class.php @@ -48,6 +48,7 @@ abstract public function getCustomData(); * @return NoSQL */ public static function spawn( $connector, $user, $pass, $host, $port=null ) { + Assert::classExists($connector); $db = new $connector; $db-> From 2c56f484c8634af2e94f3e40cabc0a76152e18c2 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 3 Apr 2012 20:25:54 +0400 Subject: [PATCH 050/418] mongo --- core/Logic/NoSQLExpression.class.php | 200 ++++++++ core/NoSQL/CouchDB.class.php | 484 ------------------ core/NoSQL/MongoBase.class.php | 312 +++++++++++ core/NoSQL/NoSQL.class.php | 97 ++-- core/NoSQL/NoSqlDAO.class.php | 212 +++----- core/NoSQL/NoSqlObject.class.php | 26 +- core/NoSQL/NoSqlPool.class.php | 4 + global.inc.php.tpl | 1 + .../OneToManyNoSqlLinked.class.php | 31 +- meta/builders/ContainerClassBuilder.class.php | 18 - 10 files changed, 651 insertions(+), 734 deletions(-) create mode 100644 core/Logic/NoSQLExpression.class.php delete mode 100644 core/NoSQL/CouchDB.class.php create mode 100644 core/NoSQL/MongoBase.class.php diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php new file mode 100644 index 0000000000..4a518f970f --- /dev/null +++ b/core/Logic/NoSQLExpression.class.php @@ -0,0 +1,200 @@ + + * @author Alex Gorbylev + * @date 2012.03.30 + */ +final class NoSQLExpression implements LogicalObject, MappableObject { + + const C_TYPE = 1; + const C_FIELD = 2; + const C_VALUE = 3; + + const EXP_EQ = 1001; + const EXP_NOTEQ = 1002; + const EXP_GT = 1003; + const EXP_GTE = 1004; + const EXP_LT = 1005; + const EXP_LTE = 1006; + + /** + * true = объединять условия по И + * false = разделять условия по ИЛИ + * @var bool + */ + protected $unite = null; + + protected $conditions = array(); + +// public static function create($unite = true) { +// return new self($unite); +// } + + /** + * Создает условие типа И + * @static + * @return NoSQLExpression + */ + public static function createAnd() { + return new self(true); + } + + /** + * Создает условие типа ИЛИ + * @static + * @return NoSQLExpression + */ + public static function createOr() { + return new self(false); + } + + public function __construct($unite = true) { + $this->unite = (bool)$unite; + } + +/// condition setters +//@{ + public function addEq($field, $value) { + $this->conditions[] = array( + self::C_TYPE => self::EXP_EQ, + self::C_FIELD => (string)$field, + self::C_VALUE => Assert::checkInteger($value) ? (int)$value : $value, + ); + return $this; + } + + public function addNotEq($field, $value) { + $this->conditions[] = array( + self::C_TYPE => self::EXP_EQ, + self::C_FIELD => (string)$field, + self::C_VALUE => Assert::checkInteger($value) ? (int)$value : $value, + ); + return $this; + } + + public function addGt($field, $value) { + Assert::isInteger($value); + $this->conditions[] = array( + self::C_TYPE => self::EXP_GT, + self::C_FIELD => (string)$field, + self::C_VALUE => (int)$value, + ); + return $this; + } + + public function addGte($field, $value) { + Assert::isInteger($value); + $this->conditions[] = array( + self::C_TYPE => self::EXP_GTE, + self::C_FIELD => (string)$field, + self::C_VALUE => (int)$value, + ); + return $this; + } + + public function addLt($field, $value) { + Assert::isInteger($value); + $this->conditions[] = array( + self::C_TYPE => self::EXP_LT, + self::C_FIELD => (string)$field, + self::C_VALUE => (int)$value, + ); + return $this; + } + + public function addLte($field, $value) { + Assert::isInteger($value); + $this->conditions[] = array( + self::C_TYPE => self::EXP_LTE, + self::C_FIELD => (string)$field, + self::C_VALUE => (int)$value, + ); + return $this; + } +//@} + +/// helper functions +//@{ +//@} + +/// condition setters +//@{ + public function toMongoQuery() { + if( empty($this->conditions) ) { + throw new WrongStateException('Sorry, query conditions are empty!'); + } + // make query + $query = array(); + foreach($this->conditions as $condition) { + switch($condition[self::C_TYPE]) { + case self::EXP_EQ: { + if( $this->unite ) { + $query[ $condition[self::C_FIELD] ] = $condition[self::C_VALUE]; + } else { + $query[] = array( $condition[self::C_FIELD] => $condition[self::C_VALUE] ); + } + + } break; + case self::EXP_NOTEQ: { + if( $this->unite ) { + $query[ $condition[self::C_FIELD] ] = array('$ne' => $condition[self::C_VALUE]); + } else { + $query[] = array( $condition[self::C_FIELD] => array('$ne' => $condition[self::C_VALUE]) ); + } + } break; + case self::EXP_GT: { + if( $this->unite ) { + $query[ $condition[self::C_FIELD] ] = array('$gt' => $condition[self::C_VALUE]); + } else { + $query[] = array( $condition[self::C_FIELD] => array('$gt' => $condition[self::C_VALUE]) ); + } + } break; + case self::EXP_GTE: { + if( $this->unite ) { + $query[ $condition[self::C_FIELD] ] = array('$gte' => $condition[self::C_VALUE]); + } else { + $query[] = array( $condition[self::C_FIELD] => array('$gte' => $condition[self::C_VALUE]) ); + } + } break; + case self::EXP_LT: { + if( $this->unite ) { + $query[ $condition[self::C_FIELD] ] = array('$lt' => $condition[self::C_VALUE]); + } else { + $query[] = array( $condition[self::C_FIELD] => array('$lt' => $condition[self::C_VALUE]) ); + } + } break; + case self::EXP_LTE: { + if( $this->unite ) { + $query[ $condition[self::C_FIELD] ] = array('$lte' => $condition[self::C_VALUE]); + } else { + $query[] = array( $condition[self::C_FIELD] => array('$lte' => $condition[self::C_VALUE]) ); + } + } break; + default: { + throw new WrongStateException( 'Sorry, I do not know how to work with you condition with ' ); + } break; + } + } + if( !$this->unite ) { + $query = array('$or' => $query); + } + return $query; + } +//@} + +/// parent object function implenetation +//@{ + public function toDialectString(Dialect $dialect) { + throw new UnsupportedMethodException('NoSQLExpression does not support method "toDialectStringg"'); + } + + public function toBoolean(Form $form) { + throw new UnsupportedMethodException('NoSQLExpression does not support method "toBoolean"'); + } + + public function toMapped(ProtoDAO $dao, JoinCapableQuery $query) { + throw new UnsupportedMethodException('NoSQLExpression does not support method "toMapped"'); + } +//@} + +} diff --git a/core/NoSQL/CouchDB.class.php b/core/NoSQL/CouchDB.class.php deleted file mode 100644 index 5099db3317..0000000000 --- a/core/NoSQL/CouchDB.class.php +++ /dev/null @@ -1,484 +0,0 @@ -self::GET, self::POST=>self::POST, self::PUT=>self::PUT, self::DELETE=>self::DELETE ); - - - public function __construct() { - if( !extension_loaded('curl') ) { - throw new MissingModuleException('CouchDB needs CURL module for PHP'); - } - } - - /** - * @param string $dbname - * @param string $id - * @return array - * @throws WrongArgumentException - */ - public function select() { - // checking args - if (func_num_args()!=2) { - throw new WrongArgumentException('Only 2 arguments allowed'); - } - - // parse args - $dbname = func_get_arg(0); - $id = func_get_arg(1); - - // checking dbname - Assert::isString($dbname); - Assert::isNotEmpty($dbname); - // checking id - Assert::isScalar($id); - Assert::isNotEmpty($id); - - return $this->exec( $this->getUrl($dbname, $id), self::GET ); - } - - /** - * @param string $dbname - * @param array $object - * @return array - * @throws WrongArgumentException - */ - public function insert() { - // checking args - if (func_num_args()!=2) { - throw new WrongArgumentException('Only 2 arguments allowed'); - } - - // parse args - $dbname = func_get_arg(0); - $object = func_get_arg(1); - - // checking dbname - Assert::isString($dbname); - Assert::isNotEmpty($dbname); - // checking object - Assert::isArray($object); - Assert::isNotEmptyArray($object); - - - // remove id - $id = urlencode($object['id']); - unset( $object['id'] ); - - $response = $this->exec( $this->getUrl($dbname, $id), self::PUT, json_encode($object) ); - $object['id'] = $response['id']; - $object['_rev'] = $response['rev']; - return $object; - } - - /** - * @param string $dbname - * @param array $object - * @param string $rev - * @return array - * @throws WrongArgumentException - */ - public function update() { - // checking args - if (func_num_args()!=3) { - throw new WrongArgumentException('Only 3 arguments allowed'); - } - - // parse args - $dbname = func_get_arg(0); - $object = func_get_arg(1); - $rev = func_get_arg(2); - - // checking dbname - Assert::isString($dbname); - Assert::isNotEmpty($dbname); - // checking object - Assert::isArray($object); - Assert::isNotEmptyArray($object); - // checking rev - Assert::isString($rev); - Assert::isNotEmpty($rev); - - // remove id - $id = urlencode($object['id']); - unset( $object['id'] ); - // add rev - $object['_rev'] = $rev; - - $response = $this->exec( $this->getUrl($dbname, $id), self::PUT, json_encode($object) ); - $object['id'] = $response['id']; - $object['_rev'] = $response['rev']; - return $object; - } - - /** - * @param string $dbname - * @param string $id - * @param string $rev - * @return int - * @throws WrongArgumentException - */ - public function delete() { - // checking args - if (func_num_args()!=3) { - throw new WrongArgumentException('Only 3 arguments allowed'); - } - - // parse args - $dbname = func_get_arg(0); - $id = urlencode(func_get_arg(1)); - $rev = func_get_arg(2); - - // checking dbname - Assert::isString($dbname); - Assert::isNotEmpty($dbname); - // checking id - Assert::isScalar($id); - Assert::isNotEmpty($id); - // checking rev - Assert::isString($rev); - Assert::isNotEmpty($rev); - - $response = $this->exec( $this->getUrl($dbname, $id, array('rev'=>$rev)), self::DELETE ); - - return $response['ok'] ? 1 : 0; - } - - /** - * @param string $dbname - * @return array - * @throws WrongArgumentException - */ - public function getAllObjects() { - // checking args - if (func_num_args()!=1) { - throw new WrongArgumentException('Only 1 argument allowed'); - } - - // parse args - $dbname = func_get_arg(0); - - // checking dbname - Assert::isString($dbname); - Assert::isNotEmpty($dbname); - - $response = $this->exec( $this->getUrl($dbname, '_all_docs', array('include_docs' => 'true')), self::GET ); - $list = array(); - if( isset($response['total_rows']) && isset($response['rows']) ) { - foreach ($response['rows'] as $row) { - $list[] = $row['doc']; - } - } - - return $list; - } - - /** - * @param string $dbname - * @return int - * @throws WrongArgumentException - */ - public function getTotalCount() { - // checking args - if (func_num_args()!=1) { - throw new WrongArgumentException('Only 1 argument allowed'); - } - - // parse args - $dbname = func_get_arg(0); - - // checking dbname - Assert::isString($dbname); - Assert::isNotEmpty($dbname); - - $response = $this->exec( $this->getUrl($dbname, '_all_docs'), self::POST, '{"keys":[]}' ); - $count = 0; - if( isset($response['total_rows']) ) { - $count = $response['total_rows']; - } - - return $count; - } - - /** - * @param string $dbname - * @param string $view - * @param array $params [optional] - * @return array - * @throws WrongArgumentException - */ - public function getCustomList() { - // checking args - if (func_num_args()!=2 && func_num_args()!=3) { - throw new WrongArgumentException('Only 2 or 3 arguments allowed'); - } - - // parse args - $dbname = func_get_arg(0); - $view = func_get_arg(1); - $params = null; - - // checking dbname - Assert::isString($dbname); - Assert::isNotEmpty($dbname); - // checking view - Assert::isString($view); - Assert::isNotEmpty($view); - - // checking params - if( func_num_args()==3 ) { - $params = func_get_arg(2); - // checking params - Assert::isArray($params); - Assert::isNotEmptyArray($params); - } - - //die( $this->getUrl($dbname, $view, $params) ); - $response = $this->exec( $this->getUrl($dbname, $view, $params), self::GET ); - $list = array(); - if( isset($response['total_rows']) && isset($response['rows']) ) { - $list = $response['rows']; - } - - return $list; - } - - /** - * @param string $dbname - * @param string $view - * @param array $params [optional] - * @return mixed - * @throws WrongArgumentException - */ - public function getCustomData() { - // checking args - if (func_num_args()!=2 && func_num_args()!=3) { - throw new WrongArgumentException('Only 2 or 3 arguments allowed'); - } - - // parse args - $dbname = func_get_arg(0); - $view = func_get_arg(1); - $params = null; - - // checking dbname - Assert::isString($dbname); - Assert::isNotEmpty($dbname); - // checking view - Assert::isString($view); - Assert::isNotEmpty($view); - - // checking params - if( func_num_args()==3 ) { - $params = func_get_arg(2); - // checking params - Assert::isArray($params); - Assert::isNotEmptyArray($params); - } - // reduce - $params['reduce'] = 'false'; - - // query - $response = $this->exec( $this->getUrl($dbname, $view, $params), self::GET ); - $result = null; - if( isset($response['rows']) ) { - $result = $response['value']; - } - - return $result; - } - - public function obtainSequence($sequence) { - $normalyzeSequence = mb_strtolower( trim( $sequence ) ); - if( - 'uuid' === $normalyzeSequence || - 'uuid_id' === $normalyzeSequence - ) { - return UuidUtils::generate(); - } else { - $response = $this->exec( $this->getUrl('_uuids'), self::GET ); - return array_shift( $response ); - - } - } - - /** - * @param string $dbname - * @param string $path - * @return string - */ - protected function getUrl( $dbname, $path=null, array $params=null ) { - Assert::isString($dbname); - - $urlPath = '/'; - if( !empty($dbname) ) { - $urlPath .= $dbname; - if( !empty($path) ) { - $urlPath .= '/'.$path; - } - } - - $urlParams = null; - if( !empty($params) ) { - $strParams = array(); - foreach( $params as $key=>$value ) { - $strParams[] = urlencode($key).'='.urlencode($value); - } - $urlParams = implode('&', $strParams); - unset($strParams); - } - - return - HttpUrl::create() - ->setScheme('http') - ->setAuthority( $this->username.':'.$this->password ) - ->setHost( $this->hostname ) - ->setPort( $this->port ) - ->setPath( $urlPath ) - ->setQuery( $urlParams ) - ->toString(); - } - - /** - * Execeutes CURL request - * @param string $url - * @param string $method - * @param string|null $data - * @return array - * @throws NoSQLException|ObjectNotFoundException - */ - protected function exec( $url, $method, $data=null ) { - if( !in_array($method, $this->_methods) ) { - throw new WrongArgumentException("Wrong menthod '{$method}'!"); - } - - // create resource - $ch = curl_init(); - - // options - $options = array( - CURLOPT_RETURNTRANSFER => true, - CURLINFO_HEADER_OUT => true, - //CURLOPT_FOLLOWLOCATION => true, - CURLOPT_URL => $url, - CURLOPT_PORT => $this->port, - CURLOPT_USERAGENT => 'onPHP::'.__CLASS__ - ); - - if ( !is_null($this->username) && !is_null($this->password) ) { - $options[CURLOPT_USERPWD] = $this->username . ':' . $this->password; - } - - switch( $method ) { - case self::GET: { - $options[CURLOPT_HTTPGET] = true; - } break; - case self::POST: { - $options[CURLOPT_CUSTOMREQUEST] = 'POST'; - $options[CURLOPT_POSTFIELDS] = $data; - $options[CURLOPT_HTTPHEADER] = array( 'Content-type: application/json' ); - } break; - case self::PUT: { - $options[CURLOPT_CUSTOMREQUEST] = 'PUT'; - $options[CURLOPT_POSTFIELDS] = $data; - $options[CURLOPT_HTTPHEADER] = array( 'Content-type: application/json' ); - } break; - case self::DELETE: { - $options[CURLOPT_CUSTOMREQUEST] = 'DELETE'; - } break; - } - - // set options - curl_setopt_array( $ch, $options ); - - // curl exec - $response = curl_exec( $ch ); - $status = curl_getinfo( $ch, CURLINFO_HTTP_CODE ); - - // checking status - $answer = false; - switch( $status ) { - case 0: { - throw new NoSQLException( 'CouchDB server is asleep' ); - } break; - case 200: - case 201: - case 202: - case 304: { - // decoding answer - $answer = json_decode( $response, true ); - } break; - case 400: { - throw new NoSQLException( 'Bad Request' ); - } break; - case 401: { - throw new NoSQLException( 'Unauthorized' ); - } break; - case 403: { - throw new NoSQLException( 'Forbidden' ); - } break; - case 404: { - $answer = json_decode( $response, true ); - $reason = isset($answer['reason']) ? $answer['reason'] : null; - throw new ObjectNotFoundException( $reason ); - } break; - case 405: { - throw new NoSQLException( 'Resource Not Allowed, url: '.$url ); - } break; - case 406: { - throw new NoSQLException( 'Not Acceptable' ); - } break; - case 409: { - throw new NoSQLException( 'Conflict' ); - } break; - case 412: { - throw new NoSQLException( 'Precondition Failed' ); - } break; - case 415: { - throw new NoSQLException( 'Bad Content Type' ); - } break; - case 401: { - throw new NoSQLException( 'Unauthorized' ); - } break; - case 500: { - throw new NoSQLException( 'CouchDB server error: '.var_export($response, true) ); - } break; - default: { - throw new NoSQLException( 'CouchDB fatal error. Code: '.$status.' Info:'.var_export($response, true) ); - } break; - } - // closing - curl_close($ch); - - return $answer; - } - -} diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php new file mode 100644 index 0000000000..cb8e374927 --- /dev/null +++ b/core/NoSQL/MongoBase.class.php @@ -0,0 +1,312 @@ + + * @date 2012.03.27 + */ +class MongoBase extends NoSQL { + + /** + * @var Mongo + */ + protected $link = null; + + /** + * @var MongoDB + */ + protected $db = null; + + /** + * @return MongoDB + * @throws NoSQLException + */ + public function connect() { + $conn = + 'mongodb://' + .($this->username && $this->password ? "{$this->username}:{$this->password}@" : null) + .$this->hostname + .($this->port ? ":{$this->port}" : null); + + $options = array("connect" => true); + + if ($this->persistent) { + $options['persist'] = $this->hostname.'-'.$this->basename; + } + try { + $this->link = new Mongo($conn, $options); + $this->db = $this->link->selectDB($this->basename); + } catch(MongoConnectionException $e) { + throw new NoSQLException( + 'can not connect to MongoBase server: '.$e->getMessage() + ); + } catch(InvalidArgumentException $e) { + throw new NoSQLException( + 'can not select DB in MongoBase: '.$e->getMessage() + ); + } + + return $this; + } + + /** + * @return MongoDB + */ + public function disconnect() { + if( $this->isConnected() ) { + $this->link->close(); + } + $this->link = null; + $this->db = null; + + return $this; + } + + /** + * @return bool + */ + public function isConnected() { + return ($this->link instanceof Mongo && $this->link->connected); + } + + /** + * @param string $sequence + * @return MongoId + */ + public function obtainSequence($sequence) { + return new MongoId(mb_strtolower(trim($sequence))); + } + + public function selectOne($table, $key) { + $row = + $this + ->db + ->selectCollection($table) + ->findOne( array('_id' => new MongoId($key)) ); + if( is_null($row) ) { + throw new ObjectNotFoundException( 'Object with id "'.$key.'" in table "'.$table.'" not found!' ); + } + // return clean row + return $this->decodeId($row); + } + + public function selectList($table, array $keys) { + // quering + $cursor = + $this + ->db + ->selectCollection($table) + ->find( array('$or' => $this->makeIdList($keys)) ); + // recieving objects + $rows = array(); + foreach ($cursor as $row) { + $rows[] = $this->decodeId($row); + } + // return result + return $rows; + } + + public function insert($table, array $row) { + $row = $this->encodeId($row); + // save + $result = + $this + ->db + ->selectCollection($table) + ->insert($row); + // checking result + if( !$result ) { + throw new NoSQLException('Could not insert object: '.var_export($row, true)); + } + // return clean row + return $this->decodeId($row); + } + + public function update($table, array $row) { + $row = $this->encodeId($row); + $id = $row['_id']; + unset($row['_id']); + + $result = + $this + ->db + ->selectCollection($table) + ->update(array('_id' => $id), $row); + // checking result + if( !$result ) { + throw new NoSQLException('Could not update object: '.var_export($row, true)); + } + $row['_id'] = $id; + // return clean row + return $this->decodeId($row); + } + + public function deleteOne($table, $key) { + return + $this + ->db + ->selectCollection($table) + ->remove( array('_id' => $this->makeId($key)), array('justOne' => true) ); + } + + public function deleteList($table, array $keys) { + return + $this + ->db + ->selectCollection($table) + ->remove( array('$or' => $this->makeIdList($keys)) ); + } + + public function getPlainList($table) { + // quering + $cursor = + $this + ->db + ->selectCollection($table) + ->find(); + // recieving objects + $rows = array(); + foreach ($cursor as $row) { + $rows[] = $this->decodeId($row); + } + // return result + return $rows; + } + + public function getTotalCount($table) { + return + $this + ->db + ->selectCollection($table) + ->find() + ->count(); + } + + public function getListByField($table, $field, $value, Criteria $criteria = null) { + // quering + $cursor = + $this + ->db + ->selectCollection($table) + ->find( array($field => $value) ); + // criteria + if( !is_null($criteria) ) { + if( $limit = $criteria->getLimit() ) { + $cursor->limit( $limit ); + } + if( $offset = $criteria->getOffset() ) { + $cursor->skip( $offset ); + } + if( $order = $criteria->getOrder()->getLast() ) { + $cursor->sort( array($order->getFieldName() => $order->isAsc()?1:-1) ); + } + } + + // recieving objects + $rows = array(); + foreach ($cursor as $row) { + $rows[] = $this->decodeId($row); + } + // return result + return $rows; + } + + public function getIdListByField($table, $field, $value, Criteria $criteria = null) { + // quering + $cursor = + $this + ->db + ->selectCollection($table) + ->find( array($field => $value), array('_id') ); + // criteria + if( !is_null($criteria) ) { + if( $criteria->getLimit() ) { + $cursor->limit( $criteria->getLimit() ); + } + if( $criteria->getOffset() ) { + $cursor->skip( $criteria->getOffset() ); + } + if( $criteria->getOrder() ) { + /** @var $order OrderBy */ + $order = $criteria->getOrder()->getLast(); + $cursor->sort( array($order->getFieldName() => $order->isAsc()?1:-1) ); + } + } + + // recieving objects + $rows = array(); + foreach ($cursor as $row) { + $rows[] = $this->decodeId($row); + } + // return result + return $rows; + } + + public function find($table, $query) { + // quering + $cursor = + $this + ->db + ->selectCollection($table) + ->find( $query ); + // recieving objects + $rows = array(); + foreach ($cursor as $row) { + $rows[] = $this->decodeId($row); + } + // return result + return $rows; + } + +/// helper functions +//@{ + /** + * Encode ID to MongoId + * @param array $row + * @return array + */ + protected function encodeId(array $row) { + $row['_id'] = $this->makeId($row['id']); + unset($row['id']); + return $row; + } + + /** + * Decode ID from MongoId to string + * @param array $row + * @return array + */ + protected function decodeId(array $row) { + $row['id'] = (string)$row['_id']; + unset($row['_id']); + return $row; + } + + protected function makeId($key) { + return ($key instanceof MongoId) ? $key : new MongoId($key); + } + + protected function makeIdList(array $keys) { + $fields = array(); + foreach( $keys as $key ) { + $fields[] = array( '_id'=>$this->makeId($key) ); + } + return $fields; + } + +// protected function prepareQuery($terms, $unite) { +// $query = array(); +// foreach( $terms as $key=>$value ) { +// $query[$key] = $value; +// } +// // query type check +// if( !$unite ) { +// $query = array('$or'=>$query ); +// } +// return $query; +// } +//@} +} diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php index 405d44f593..de59751916 100644 --- a/core/NoSQL/NoSQL.class.php +++ b/core/NoSQL/NoSQL.class.php @@ -15,93 +15,62 @@ * * @ingroup NoSQL **/ -abstract class NoSQL { +abstract class NoSQL extends DB { + + protected $link = null; // credentials protected $username = null; protected $password = null; protected $hostname = null; protected $port = null; + protected $basename = null; + protected $encoding = null; // queries - abstract public function select(); - abstract public function insert(); - abstract public function update(); - abstract public function delete(); + abstract public function selectOne($table, $key); + abstract public function selectList($table, array $keys); + abstract public function insert($table, array $row); + abstract public function update($table, array $row); + abstract public function deleteOne($table, $key); + abstract public function deleteList($table, array $keys); // full table queries - abstract public function getAllObjects(); - abstract public function getTotalCount(); + abstract public function getPlainList($table); + abstract public function getTotalCount($table); // custom queries - abstract public function getCustomList(); - abstract public function getCustomData(); - - /** - * Shortcut - * @static - * @param string $connector - * @param string $user - * @param string $pass - * @param string $host - * @param string $port - * @return NoSQL - */ - public static function spawn( $connector, $user, $pass, $host, $port=null ) { - Assert::classExists($connector); - $db = new $connector; - - $db-> - setUsername($user)-> - setPassword($pass)-> - setHostname($host); - if( !empty($port) ) { - $db->setPort($port); - } + abstract public function getListByField($table, $field, $value, Criteria $criteria = null); + abstract public function getIdListByField($table, $field, $value, Criteria $criteria = null); + abstract public function find($table, $query); +// abstract public function count($table, $query); - return $db; + public function getTableInfo($table) { + throw new UnsupportedMethodException('Can not execute getTableInfo in NoSQL'); } - /** - * @param string $name - * @return NoSQL - */ - public function setUsername($name) { - $this->username = $name; - - return $this; + public function queryRaw($queryString) { + throw new UnsupportedMethodException('Can not execute queryRaw in NoSQL'); } - /** - * @param string $password - * @return NoSQL - */ - public function setPassword($password) { - $this->password = $password; - - return $this; + public function queryRow(Query $query) { + throw new UnsupportedMethodException('Can not execute queryRow in NoSQL'); } - /** - * @param string $host - * @return NoSQL - */ - public function setHostname($host) { - $port = null; - - if (strpos($host, ':') !== false) - list($host, $port) = explode(':', $host, 2); - - $this->hostname = $host; - $this->port = $port; + public function querySet(Query $query) { + throw new UnsupportedMethodException('Can not execute querySet in NoSQL'); + } - return $this; + public function queryColumn(Query $query) { + throw new UnsupportedMethodException('Can not execute queryColumn in NoSQL'); } - public function setPort($port) { - $this->port = $port; + public function queryCount(Query $query) { + throw new UnsupportedMethodException('Can not execute queryCount in NoSQL'); + } - return $this; + public function setDbEncoding() { + throw new UnsupportedMethodException('Can not set encoding in NoSQL'); } } diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index afdf427218..308a1790ee 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -12,8 +12,6 @@ abstract class NoSqlDAO extends StorableDAO { - const COUCHDB_VIEW_PREFIX = '_design/data/_view/'; - /// single object getters //@{ /** @@ -23,23 +21,39 @@ abstract class NoSqlDAO extends StorableDAO { */ public function getById($id, $expires = Cache::EXPIRES_MEDIUM) { $object = null; - if ($row = $this->getLink()->select( $this->getTable(), $id )) { + if ($row = $this->getLink()->selectOne( $this->getTable(), $id )) { $object = $this->makeNoSqlObject($row); + } else { + throw new ObjectNotFoundException( 'Object with id '.$id.' does not exist' ); } - return $object; } public function getByLogic(LogicalObject $logic, $expires = Cache::DO_NOT_CACHE) { - throw new UnsupportedMethodException( 'Method "getByLogic" is not supported in NoSQL' ); + if( !($logic instanceof NoSQLExpression) ) { + throw new WrongArgumentException( '$logic should be instance of NoSQLExpression' ); + } + // quering for different NoSQL types + $rows = array(); + if( $this->getLink() instanceof MongoBase ) { + $rows = $this->getLink()->find($this->getTable(), $logic->toMongoQuery()); + } else { + throw new UnimplementedFeatureException( 'Method "getByLogic" is not implemented now for your NoSQL DB' ); + } + // processing list + $list = array(); + foreach($rows as $row) { + $list[] = $this->makeNoSqlObject($row); + } + return $list; } public function getByQuery(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { - throw new UnsupportedMethodException( 'Method "getByQuery" is not supported in NoSQL' ); + throw new UnsupportedMethodException( 'Can not execute "getByQuery" in NoSQL' ); } public function getCustom(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { - throw new UnsupportedMethodException( 'Method "getCustom" is not supported in NoSQL' ); + throw new UnsupportedMethodException( 'Can not execute "getCustom" in NoSQL' ); } //@} @@ -52,23 +66,19 @@ public function getCustom(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { */ public function getListByIds(array $ids, $expires = Cache::EXPIRES_MEDIUM) { $list = array(); - foreach( $ids as $id ) { - try { - $obj = $this->getById( $id ); - $list[ $id ] = $obj; - } catch(Exception $e) { - // it's ok - } + $rows = $this->getLink()->selectList( $this->getTable(), $ids ); + foreach($rows as $row) { + $list[] = $this->makeNoSqlObject($row); } return $list; } public function getListByQuery(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { - throw new UnsupportedMethodException( 'Method "getCustom" is not supported in NoSQL' ); + throw new UnsupportedMethodException( 'Can not execute "getListByQuery" in NoSQL' ); } public function getListByLogic(LogicalObject $logic, $expires = Cache::DO_NOT_CACHE) { - throw new UnsupportedMethodException( 'Method "getCustom" is not supported in NoSQL' ); + throw new UnimplementedFeatureException( 'Method "getListByLogic" is not implemented now' ); } /** @@ -77,12 +87,10 @@ public function getListByLogic(LogicalObject $logic, $expires = Cache::DO_NOT_CA */ public function getPlainList($expires = Cache::EXPIRES_MEDIUM) { $list = array(); - $stack = $this->getLink()->getAllObjects( $this->getTable() ); - if( !empty($stack) ) { - foreach( $stack as $row ) { - $object = $this->makeNoSqlObject($row); - $list[ $object->getId() ] = $object; - } + $stack = $this->getLink()->getPlainList( $this->getTable() ); + foreach( $stack as $row ) { + $object = $this->makeNoSqlObject($row); + $list[ $object->getId() ] = $object; } return $list; @@ -101,18 +109,18 @@ public function getTotalCount($expires = Cache::DO_NOT_CACHE) { /// custom list getters //@{ public function getCustomList(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { - throw new UnsupportedMethodException( 'Method "getCustomList" is not supported in NoSQL' ); + throw new UnsupportedMethodException( 'Can not execute "getCustomList" in NoSQL' ); } public function getCustomRowList(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { - throw new UnsupportedMethodException( 'Method "getCustomRowList" is not supported in NoSQL' ); + throw new UnsupportedMethodException( 'Can not execute "getCustomRowList" in NoSQL' ); } //@} /// query result getters //@{ public function getQueryResult(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { - throw new UnsupportedMethodException( 'Method "getQueryResult" is not supported in NoSQL' ); + throw new UnsupportedMethodException( 'Can not execute "getQueryResult" in NoSQL' ); } //@} @@ -131,24 +139,17 @@ public function makeTotalCountQuery() { //@{ public function drop(Identifiable $object) { $this->assertNoSqlObject( $object ); - - $link = NoSqlPool::getByDao( $this ); - // delete - return - $link - ->delete( - $this->getTable(), - $object->getId(), - $object->getRev() - ); + return $this->dropById( $object->getId() ); } public function dropById($id) { - return parent::dropById($id); + $link = NoSqlPool::getByDao( $this ); + return $link->deleteOne($this->getTable(), $id); } public function dropByIds(array $ids) { - return parent::dropByIds($ids); + $link = NoSqlPool::getByDao( $this ); + return $link->deleteList($this->getTable(), $ids); } //@} @@ -192,10 +193,7 @@ public function add(Identifiable $object) { ); $object->setId( $entity['id'] ); - if( $link instanceof CouchDB ) { - $object->setRev($entity['_rev']); - } - // проверка добалвения + // проверка добавления //$object = $this->getById( $entity['id'] ); return $object; @@ -205,19 +203,14 @@ public function save(Identifiable $object) { $this->assertNoSqlObject( $object ); $link = NoSqlPool::getByDao( $this ); - // insert + // save $entity = $link ->update( $this->getTable(), - $object->toArray(), - $object->getRev() + $object->toArray() ); - $object->setId( $entity['id'] ); - if( $link instanceof CouchDB ) { - $object->setRev($entity['_rev']); - } return $object; } @@ -233,10 +226,9 @@ public function import(Identifiable $object) { $this->getTable(), $object->toArray() ); - - if( $link instanceof CouchDB ) { - $object->setRev($entity['_rev']); - } + $object->setId( $entity['id'] ); + // проверка сохранения + //$object = $this->getById( $entity['id'] ); return $object; } @@ -247,7 +239,7 @@ public function merge(Identifiable $object, $cacheOnly = true) { $this->checkObjectType($object); try { - $old = Cache::worker($this)->getById($object->getId()); + $old = $this->getById($object->getId()); } catch( Exception $e ) { return $this->save($object); } @@ -294,81 +286,50 @@ public function unite( Identifiable $object, Identifiable $old ) { //@} -/// object's list getters +/// object's list getters by foreign_key //@{ - public function getListByView($view, $keys, $criteria=null) { - $params = array(); - - // parse key - switch( get_class($this->getLink()) ) { - case 'CouchDB': { - // собираем правильное имя вьюшки - $view = self::COUCHDB_VIEW_PREFIX.$view; - // приводим к массиву даже если ключ один - if( !is_array($keys) ) { - $keys = array($keys); - } - // проверяем что в массиве ключей есть хоть один - if( count($keys)<1 ) { - throw new WrongArgumentException( '$keys must be an array with one or more values' ); - } - // проверяем типы - foreach($keys as &$val) { - if( is_null($val) ) { - $val = 'null'; - } elseif(is_numeric($val)) { - //$val = $val; - } else { - $val = '"'.$val.'"'; - } - } - // сериализуем - if( count($keys)==1 ) { - $key = array_shift($keys); - } else { - $key = '['.implode(',', $keys).']'; - } - - $params['key'] = $key; - } break; - default: { - throw new WrongStateException( 'Do not know how to work with link type '.get_class($this->getLink()) ); - } break; + public function getOneByField($field, $value, Criteria $criteria = null) { + if( is_null($criteria) ) { + $criteria = Criteria::create(); } - - // parse criteria - if( !is_null($criteria) && ($criteria instanceof Criteria) ) { - switch( get_class($this->getLink()) ) { - case 'CouchDB': { - if( $criteria->getOffset() ) { - $params['skip'] = $criteria->getOffset(); - } - if( $criteria->getLimit() ) { - $params['limit'] = $criteria->getLimit(); - } - if( !$criteria->getOrder()->getLast()->isAsc() ) { - $params['descending'] = 'true'; - } - } break; - default: { - throw new WrongStateException( 'Do not know how to work with criteria and link type '.get_class($this->getLink()) ); - } break; - } + $criteria->setLimit(1); + // get object + $list = $this->getListByField( $field, $value, $criteria ); + if( empty($list) ) { + throw new ObjectNotFoundException(); } + return array_shift($list); + } - // query + public function getListByField($field, $value, Criteria $criteria = null) { $list = array(); - $stack = $this->getLink()->getCustomList( $this->getTable(), $view, $params ); - if( !empty($stack) ) { - foreach( $stack as $row ) { - $list[ $row['id'] ] = $this->makeNoSqlObject( $row['value'] ); - } + $rows = $this->getLink()->getListByField( $this->getTable(), $field, $value, $criteria ); + foreach($rows as $row) { + $list[] = $this->makeNoSqlObject($row); } + return $list; + } + public function getIdListByField($field, $value, Criteria $criteria = null) { + $list = array(); + $rows = $this->getLink()->getIdListByField( $this->getTable(), $field, $value, $criteria ); + foreach($rows as $row) { + $list[] = $row['id']; + } return $list; } //@} +/// object finder +//@{ +// public function find($table, $options) { +// +// } +// +// public function findByCriteria($table, Criteria $criteria) { +// throw new UnimplementedFeatureException( 'Method "getByLogic" is not implemented now' ); +// } +//@} /** * @param $object @@ -381,25 +342,16 @@ protected function assertNoSqlObject( $object ) { } /** - * @param array $array + * @param array $row * @param null $prefix * @return Identifiable|Prototyped */ - public function makeNoSqlObject($array, $prefix = null) { + public function makeNoSqlObject($row, $prefix = null) { $object = null; - - if( $this->getLink() instanceof CouchDB ) { - $array['id'] = urldecode($array['_id']); - unset( $array['_id'] ); - } - try { - $object = $this->makeObject( $array, $prefix ); - if( $this->getLink() instanceof CouchDB ) { - $object->setRev($array['_rev']); - } + $object = $this->makeObject( $row, $prefix ); } catch(Exception $e) { - throw new WrongStateException( 'Can not parse object with id '.$array['id'] ); + throw new WrongStateException( 'Can not make object with id '.$row['id'].'. Dump: '.var_export($row, true) ); } return $object; } diff --git a/core/NoSQL/NoSqlObject.class.php b/core/NoSQL/NoSqlObject.class.php index fcfb2a3766..538db52747 100644 --- a/core/NoSQL/NoSqlObject.class.php +++ b/core/NoSQL/NoSqlObject.class.php @@ -17,28 +17,7 @@ **/ class NoSqlObject extends IdentifiableObject { - /** - * @var string - */ - protected $_rev = null; - - protected $identifiers = array('identifier', 'integerIdentifier', 'scalarIdentifier', 'uuidIdentifier'); - - /** - * @param $rev - * @return NoSqlObject - */ - public function setRev($rev) { - $this->_rev = $rev; - return $this; - } - - /** - * @return string - */ - public function getRev() { - return $this->_rev; - } + protected static $identifiers = array('identifier', 'integerIdentifier', 'scalarIdentifier', 'uuidIdentifier'); public function toArray() { $entity = array(); @@ -58,13 +37,12 @@ public function toArray() { $value = call_user_func(array($this, $property->getGetter())); $entity[ $property->getColumnName() ] = (int)$value->getId(); } // обрабатываем связи 1к1 - elseif( in_array($property->getType(), $this->identifiers) && $property->getRelationId()==1 ) { + elseif( in_array($property->getType(), self::$identifiers) && $property->getRelationId()==1 ) { $value = call_user_func(array($this, $property->getGetter().'Id')); $entity[ $property->getColumnName() ] = is_numeric($value) ? (int)$value : $value; } } // $entity[ '_id' ] = $this->id; -// $entity[ '_rev' ] = $this->_rev; return $entity; } diff --git a/core/NoSQL/NoSqlPool.class.php b/core/NoSQL/NoSqlPool.class.php index fdd5a05085..4d7c64fd63 100644 --- a/core/NoSQL/NoSqlPool.class.php +++ b/core/NoSQL/NoSqlPool.class.php @@ -102,6 +102,7 @@ public function dropLink($name) */ public function getLink($name = null) { + /** @var $link NoSQL */ $link = null; // single-NoSQL project @@ -118,6 +119,9 @@ public function getLink($name = null) } // check if found and return if ($link) { + if (!$link->isConnected()) + $link->connect(); + return $link; } diff --git a/global.inc.php.tpl b/global.inc.php.tpl index cd81b559d6..42af288aae 100644 --- a/global.inc.php.tpl +++ b/global.inc.php.tpl @@ -69,6 +69,7 @@ define('ONPHP_MAIN_PATH', ONPHP_ROOT_PATH.'main'.DIRECTORY_SEPARATOR); define('ONPHP_META_PATH', ONPHP_ROOT_PATH.'meta'.DIRECTORY_SEPARATOR); define('ONPHP_UI_PATH', ONPHP_ROOT_PATH.'UI'.DIRECTORY_SEPARATOR); + define('ONPHP_LIB_PATH', ONPHP_ROOT_PATH.'lib'.DIRECTORY_SEPARATOR); if (!defined('ONPHP_META_PATH')) define( diff --git a/main/UnifiedContainer/OneToManyNoSqlLinked.class.php b/main/UnifiedContainer/OneToManyNoSqlLinked.class.php index d8d06a4425..c873e2d7fe 100644 --- a/main/UnifiedContainer/OneToManyNoSqlLinked.class.php +++ b/main/UnifiedContainer/OneToManyNoSqlLinked.class.php @@ -30,10 +30,16 @@ public function dropList() { ); } - /** @var $object NoSqlObject */ - foreach($this->list as &$object) { - $object->dao->drop( $object ); + $idList = array(); + if( current($this->list) instanceof NoSqlObject ) { + /** @var $object NoSqlObject */ + foreach($this->list as &$object) { + $idList[] = $object->getId(); + } + } else { + $idList = $this->list; } + $this->dao->dropByIds($idList); $this->clean(); @@ -54,10 +60,12 @@ public function save() { /** @var $object NoSqlObject */ foreach( $this->list as &$object ) { - if( $object->getId() ) { - $object->dao->save( $object ); - } else { - $object->dao->add( $object ); + if( $object instanceof NoSqlObject ) { + if( $object->getId() ) { + $object->dao->save( $object ); + } else { + $object->dao->add( $object ); + } } } @@ -69,18 +77,13 @@ public function save() { * @return array */ protected function fetchList() { - $list = $this->dao->getListByView( $this->getViewName(), $this->parent->getId(), $this->worker->getCriteria() ); if( $this->lazy ) { - $newList = array(); - foreach( $list as $obj ) { - $newList[] = $obj->getId(); - } + $this->list = $this->dao->getIdListByField( $this->getParentIdField(), $this->parent->getId(), $this->worker->getCriteria() ); } else { - $this->list = $list; + $this->list = $this->dao->getListByField( $this->getParentIdField(), $this->parent->getId(), $this->worker->getCriteria() ); } return $this; } - protected abstract function getViewName(); } diff --git a/meta/builders/ContainerClassBuilder.class.php b/meta/builders/ContainerClassBuilder.class.php index e44a9ad5f3..ce9da8d5e1 100644 --- a/meta/builders/ContainerClassBuilder.class.php +++ b/meta/builders/ContainerClassBuilder.class.php @@ -91,24 +91,6 @@ public function getParentIdField() EOT; - if ($isNoSQL) { - $out .= <<getName()}Id'; -} - -EOT; - } - - - $out .= "}\n"; $out .= self::getHeel(); From c158e2e3b7a31bafa4b5062cb3836219d628565d Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 5 Apr 2012 15:26:02 +0400 Subject: [PATCH 051/418] one_to_many fix --- core/NoSQL/MongoBase.class.php | 6 ++++++ core/NoSQL/NoSqlDAO.class.php | 10 +++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index cb8e374927..799c3db7cd 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -186,6 +186,9 @@ public function getTotalCount($table) { } public function getListByField($table, $field, $value, Criteria $criteria = null) { + if( Assert::checkInteger($value) ) { + $value = (int)$value; + } // quering $cursor = $this @@ -215,6 +218,9 @@ public function getListByField($table, $field, $value, Criteria $criteria = null } public function getIdListByField($table, $field, $value, Criteria $criteria = null) { + if( Assert::checkInteger($value) ) { + $value = (int)$value; + } // quering $cursor = $this diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 308a1790ee..1172bfef79 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -178,11 +178,11 @@ public function add(Identifiable $object) { // make sequence $link = NoSqlPool::getByDao( $this ); - $object->setId( - $link->obtainSequence( - $this->getSequence() - ) - ); +// $object->setId( +// $link->obtainSequence( +// $this->getSequence() +// ) +// ); // insert $entity = From 669c92b439cf3fc60de598049f12fb7e45ddf177 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 6 Apr 2012 14:37:19 +0400 Subject: [PATCH 052/418] Mongo remake --- core/NoSQL/MongoBase.class.php | 147 +++++++++++++++++++-------------- core/NoSQL/NoSQL.class.php | 1 + core/NoSQL/NoSqlDAO.class.php | 36 ++++---- 3 files changed, 104 insertions(+), 80 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 799c3db7cd..3a27e0f6fa 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -10,6 +10,12 @@ */ class MongoBase extends NoSQL { + const C_TABLE = 1001; + const C_QUERY = 1002; + const C_ORDER = 1003; + const C_LIMIT = 1004; + const C_SKIP = 1005; + /** * @var Mongo */ @@ -189,75 +195,57 @@ public function getListByField($table, $field, $value, Criteria $criteria = null if( Assert::checkInteger($value) ) { $value = (int)$value; } - // quering - $cursor = - $this - ->db - ->selectCollection($table) - ->find( array($field => $value) ); - // criteria - if( !is_null($criteria) ) { - if( $limit = $criteria->getLimit() ) { - $cursor->limit( $limit ); - } - if( $offset = $criteria->getOffset() ) { - $cursor->skip( $offset ); - } - if( $order = $criteria->getOrder()->getLast() ) { - $cursor->sort( array($order->getFieldName() => $order->isAsc()?1:-1) ); - } - } + $options = $this->parseCriteria($criteria); - // recieving objects - $rows = array(); - foreach ($cursor as $row) { - $rows[] = $this->decodeId($row); - } - // return result - return $rows; + return + $this->mongoFind($table, array($field => $value), array(), $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); } public function getIdListByField($table, $field, $value, Criteria $criteria = null) { if( Assert::checkInteger($value) ) { $value = (int)$value; } - // quering - $cursor = - $this - ->db - ->selectCollection($table) - ->find( array($field => $value), array('_id') ); - // criteria - if( !is_null($criteria) ) { - if( $criteria->getLimit() ) { - $cursor->limit( $criteria->getLimit() ); - } - if( $criteria->getOffset() ) { - $cursor->skip( $criteria->getOffset() ); - } - if( $criteria->getOrder() ) { - /** @var $order OrderBy */ - $order = $criteria->getOrder()->getLast(); - $cursor->sort( array($order->getFieldName() => $order->isAsc()?1:-1) ); - } - } + $options = $this->parseCriteria($criteria); - // recieving objects - $rows = array(); - foreach ($cursor as $row) { - $rows[] = $this->decodeId($row); - } - // return result - return $rows; + return + $this->mongoFind($table, array($field => $value), array('_id'), $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); } public function find($table, $query) { + return + $this->mongoFind($table, $query); + } + + public function findByCriteria(Criteria $criteria) { + $options = $this->parseCriteria($criteria); + + if( !isset($options[self::C_TABLE]) ) { + throw new NoSQLException('Can not find without table!'); + } + if( !isset($options[self::C_QUERY]) ) { + throw new NoSQLException('Can not find without query!'); + } + + return + $this->mongoFind($options[self::C_TABLE], $options[self::C_QUERY], array(), $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); + } + + protected function mongoFind($table, array $query, array $fields=array(), array $order=null, $limit=null, $skip=null) { // quering $cursor = $this ->db ->selectCollection($table) - ->find( $query ); + ->find( $query, $fields ); + if( !is_null($order) ) { + $cursor->sort( $order ); + } + if( !is_null($limit) ) { + $cursor->limit( $limit ); + } + if( !is_null($skip) ) { + $cursor->skip( $skip ); + } // recieving objects $rows = array(); foreach ($cursor as $row) { @@ -303,16 +291,47 @@ protected function makeIdList(array $keys) { return $fields; } -// protected function prepareQuery($terms, $unite) { -// $query = array(); -// foreach( $terms as $key=>$value ) { -// $query[$key] = $value; -// } -// // query type check -// if( !$unite ) { -// $query = array('$or'=>$query ); -// } -// return $query; -// } + /** + * Разбираем критерию на параметры запроса к монго + * @param Criteria $criteria + * @return array + */ + protected function parseCriteria(Criteria $criteria) { + $result = array(); + // парсим табличку + if( $criteria->getDao() ) { + $result[self::C_TABLE] = $criteria->getDao()->getTable(); + } + // парсим запросы + if( $criteria->getLogic()->getLogic() ) { + $expression = array_shift($criteria->getLogic()->getLogic()); + if( $expression instanceof NoSQLExpression ) { + $result[self::C_QUERY] = $expression->toMongoQuery(); + } + } + // парсим сортировку + if( $criteria->getOrder() ) { + /** @var $order OrderBy */ + $order = $criteria->getOrder()->getLast(); + $result[self::C_ORDER] = array($order->getFieldName() => $order->isAsc()?1:-1); + } else { + $result[self::C_ORDER] = null; + } + // парсим лимит + if( $criteria->getLimit() ) { + $result[self::C_LIMIT] = $criteria->getLimit(); + } else { + $result[self::C_LIMIT] = null; + } + // парсим сдвиг + if( $criteria->getOffset() ) { + $result[self::C_SKIP] = $criteria->getOffset(); + } else { + $result[self::C_SKIP] = null; + } + // отдаем результат + return $result; + } + //@} } diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php index de59751916..7a17fbc412 100644 --- a/core/NoSQL/NoSQL.class.php +++ b/core/NoSQL/NoSQL.class.php @@ -43,6 +43,7 @@ abstract public function getTotalCount($table); abstract public function getListByField($table, $field, $value, Criteria $criteria = null); abstract public function getIdListByField($table, $field, $value, Criteria $criteria = null); abstract public function find($table, $query); + abstract public function findByCriteria(Criteria $criteria); // abstract public function count($table, $query); public function getTableInfo($table) { diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 1172bfef79..39e64f091e 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -41,11 +41,11 @@ public function getByLogic(LogicalObject $logic, $expires = Cache::DO_NOT_CACHE) throw new UnimplementedFeatureException( 'Method "getByLogic" is not implemented now for your NoSQL DB' ); } // processing list - $list = array(); - foreach($rows as $row) { - $list[] = $this->makeNoSqlObject($row); + if( count($rows)==0 ) { + throw new ObjectNotFoundException('Can not find object for your query'); + } else { + return $this->makeNoSqlObject( array_shift($rows) ); } - return $list; } public function getByQuery(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { @@ -78,7 +78,22 @@ public function getListByQuery(SelectQuery $query, $expires = Cache::DO_NOT_CACH } public function getListByLogic(LogicalObject $logic, $expires = Cache::DO_NOT_CACHE) { - throw new UnimplementedFeatureException( 'Method "getListByLogic" is not implemented now' ); + if( !($logic instanceof NoSQLExpression) ) { + throw new WrongArgumentException( '$logic should be instance of NoSQLExpression' ); + } + // quering for different NoSQL types + $rows = array(); + if( $this->getLink() instanceof MongoBase ) { + $rows = $this->getLink()->find($this->getTable(), $logic->toMongoQuery()); + } else { + throw new UnimplementedFeatureException( 'Method "getByLogic" is not implemented now for your NoSQL DB' ); + } + // processing list + $list = array(); + foreach($rows as $row) { + $list[] = $this->makeNoSqlObject($row); + } + return $list; } /** @@ -320,17 +335,6 @@ public function getIdListByField($field, $value, Criteria $criteria = null) { } //@} -/// object finder -//@{ -// public function find($table, $options) { -// -// } -// -// public function findByCriteria($table, Criteria $criteria) { -// throw new UnimplementedFeatureException( 'Method "getByLogic" is not implemented now' ); -// } -//@} - /** * @param $object * @throws WrongStateException From 541d56a776c1b98c9159c370bdb2c9b11c5a6d5f Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 6 Apr 2012 16:06:38 +0400 Subject: [PATCH 053/418] mongo + criteria --- core/NoSQL/MongoBase.class.php | 9 +- core/NoSQL/NoSqlDAO.class.php | 42 ++++++ main/Criteria/Criteria.class.php | 232 ++++++++++++++++--------------- 3 files changed, 168 insertions(+), 115 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 3a27e0f6fa..d606a55926 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -304,7 +304,8 @@ protected function parseCriteria(Criteria $criteria) { } // парсим запросы if( $criteria->getLogic()->getLogic() ) { - $expression = array_shift($criteria->getLogic()->getLogic()); + $logic = $criteria->getLogic()->getChain(); + $expression = array_shift($logic); if( $expression instanceof NoSQLExpression ) { $result[self::C_QUERY] = $expression->toMongoQuery(); } @@ -313,7 +314,11 @@ protected function parseCriteria(Criteria $criteria) { if( $criteria->getOrder() ) { /** @var $order OrderBy */ $order = $criteria->getOrder()->getLast(); - $result[self::C_ORDER] = array($order->getFieldName() => $order->isAsc()?1:-1); + if( $order instanceof OrderBy ) { + $result[self::C_ORDER] = array($order->getFieldName() => $order->isAsc()?1:-1); + } else { + $result[self::C_ORDER] = null; + } } else { $result[self::C_ORDER] = null; } diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 39e64f091e..ee4597a710 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -29,6 +29,12 @@ public function getById($id, $expires = Cache::EXPIRES_MEDIUM) { return $object; } + /** + * @param LogicalObject $logic + * @param int $expires + * @return Identifiable|Prototyped + * @throws ObjectNotFoundException|UnimplementedFeatureException|WrongArgumentException + */ public function getByLogic(LogicalObject $logic, $expires = Cache::DO_NOT_CACHE) { if( !($logic instanceof NoSQLExpression) ) { throw new WrongArgumentException( '$logic should be instance of NoSQLExpression' ); @@ -48,10 +54,20 @@ public function getByLogic(LogicalObject $logic, $expires = Cache::DO_NOT_CACHE) } } + /** + * @param SelectQuery $query + * @param int $expires + * @throws UnsupportedMethodException + */ public function getByQuery(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { throw new UnsupportedMethodException( 'Can not execute "getByQuery" in NoSQL' ); } + /** + * @param SelectQuery $query + * @param int $expires + * @throws UnsupportedMethodException + */ public function getCustom(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { throw new UnsupportedMethodException( 'Can not execute "getCustom" in NoSQL' ); } @@ -73,10 +89,21 @@ public function getListByIds(array $ids, $expires = Cache::EXPIRES_MEDIUM) { return $list; } + /** + * @param SelectQuery $query + * @param int $expires + * @throws UnsupportedMethodException + */ public function getListByQuery(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { throw new UnsupportedMethodException( 'Can not execute "getListByQuery" in NoSQL' ); } + /** + * @param LogicalObject $logic + * @param int $expires + * @return array + * @throws UnimplementedFeatureException|WrongArgumentException + */ public function getListByLogic(LogicalObject $logic, $expires = Cache::DO_NOT_CACHE) { if( !($logic instanceof NoSQLExpression) ) { throw new WrongArgumentException( '$logic should be instance of NoSQLExpression' ); @@ -96,6 +123,21 @@ public function getListByLogic(LogicalObject $logic, $expires = Cache::DO_NOT_CA return $list; } + /** + * @param Criteria $criteria + * @param int $expires + * @return array + */ + public function getListByCriteria(Criteria $criteria, $expires = Cache::DO_NOT_CACHE) { + $list = array(); + $stack = $this->getLink()->findByCriteria($criteria); + foreach( $stack as $row ) { + $object = $this->makeNoSqlObject($row); + $list[ $object->getId() ] = $object; + } + return $list; + } + /** * @param int $expires * @return array diff --git a/main/Criteria/Criteria.class.php b/main/Criteria/Criteria.class.php index 08e97142ab..b2da79d0c0 100644 --- a/main/Criteria/Criteria.class.php +++ b/main/Criteria/Criteria.class.php @@ -11,7 +11,7 @@ /** * @see http://www.hibernate.org/hib_docs/v3/reference/en/html/querycriteria.html - * + * * @ingroup Criteria **/ final class Criteria extends QueryIdentification @@ -22,17 +22,17 @@ final class Criteria extends QueryIdentification private $order = null; private $strategy = null; private $projection = null; - + private $distinct = false; - + private $limit = null; private $offset = null; - + private $collections = array(); - + // dao-like behaviour: will throw ObjectNotFoundException when 'false' private $silent = true; - + /** * @return Criteria **/ @@ -40,19 +40,19 @@ public static function create(/* ProtoDAO */ $dao = null) { return new self($dao); } - + public function __construct(/* ProtoDAO */ $dao = null) { if ($dao) Assert::isTrue($dao instanceof ProtoDAO); - + $this->dao = $dao; $this->logic = Expression::andBlock(); $this->order = new OrderChain(); $this->strategy = FetchStrategy::join(); $this->projection = Projection::chain(); } - + public function __clone() { $this->logic = clone $this->logic; @@ -60,25 +60,25 @@ public function __clone() $this->strategy = clone $this->strategy; $this->projection = clone $this->projection; } - + public function __sleep() { $this->daoClass = $this->getDao() ? get_class($this->dao) : null; - + $vars = get_object_vars($this); unset($vars['dao']); return array_keys($vars); } - + public function __wakeup() { if ($this->daoClass) $this->dao = Singleton::getInstance($this->daoClass); } - + /** * @return ProtoDAO **/ @@ -86,25 +86,29 @@ public function getDao() { return $this->dao; } - + /** * @return Criteria **/ public function setDao(ProtoDAO $dao) { $this->dao = $dao; - + return $this; } - + + /** + * @return ProtoDAO + * @throws WrongStateException + */ public function checkAndGetDao() { if (!$this->dao) throw new WrongStateException('You forgot to set dao'); - + return $this->dao; } - + /** * @return LogicalChain **/ @@ -112,17 +116,17 @@ public function getLogic() { return $this->logic; } - + /** * @return Criteria **/ public function add(LogicalObject $logic) { $this->logic->expAnd($logic); - + return $this; } - + /** * @return OrderChain **/ @@ -130,7 +134,7 @@ public function getOrder() { return $this->order; } - + /** * @return Criteria **/ @@ -138,12 +142,12 @@ public function addOrder(/* MapableObject */ $order) { if (!$order instanceof MappableObject) $order = new OrderBy($order); - + $this->order->add($order); - + return $this; } - + /** * @return Criteria **/ @@ -151,52 +155,52 @@ public function prependOrder(/* MapableObject */ $order) { if (!$order instanceof MappableObject) $order = new OrderBy($order); - + $this->order->prepend($order); - + return $this; } - + /** * @return Criteria **/ public function dropOrder() { $this->order = new OrderChain(); - + return $this; } - + public function getLimit() { return $this->limit; } - + /** * @return Criteria **/ public function setLimit($limit) { $this->limit = $limit; - + return $this; } - + public function getOffset() { return $this->offset; } - + /** * @return Criteria **/ public function setOffset($offset) { $this->offset = $offset; - + return $this; } - + /** * @return FetchStrategy **/ @@ -204,17 +208,17 @@ public function getFetchStrategy() { return $this->strategy; } - + /** * @return Criteria **/ public function setFetchStrategy(FetchStrategy $strategy) { $this->strategy = $strategy; - + return $this; } - + /** * @return Criteria **/ @@ -224,10 +228,10 @@ public function setProjection(ObjectProjection $chain) $this->projection = $chain; else $this->projection = Projection::chain()->add($chain); - + return $this; } - + /** * @return Criteria **/ @@ -238,10 +242,10 @@ public function addProjection(ObjectProjection $projection) || !$projection->isEmpty() ) $this->projection->add($projection); - + return $this; } - + /** * @return ProjectionChain **/ @@ -249,49 +253,49 @@ public function getProjection() { return $this->projection; } - + /** * @return Criteria **/ public function dropProjection() { $this->projection = Projection::chain(); - + return $this; } - + /** * @return Criteria **/ public function setDistinct($orly = true) { $this->distinct = ($orly === true); - + return $this; } - + public function isDistinct() { return $this->distinct; } - + public function isSilent() { return $this->silent; } - + /** * @return Criteria **/ public function setSilent($silent) { Assert::isBoolean($silent); - + $this->silent = $silent; - + return $this; } - + /** * @return Criteria **/ @@ -306,7 +310,7 @@ public function fetchCollection( ($criteria === null) || ($criteria instanceof Criteria) ); - + $this->collections[$path]['lazy'] = $lazy; $this->collections[$path]['criteria'] = $criteria; $this->collections[$path]['propertyPath'] @@ -314,56 +318,58 @@ public function fetchCollection( $this->checkAndGetDao()->getObjectName(), $path ); - + return $this; } - + public function get() { try { - $list = array( - $this->checkAndGetDao()-> - getByQuery($this->toSelectQuery()) - ); + $dao = $this->checkAndGetDao(); + $list = + $dao instanceof NoSqlDAO + ? $dao->getListByCriteria($this) + : $dao->getListByQuery($this->toSelectQuery()); } catch (ObjectNotFoundException $e) { if (!$this->isSilent()) throw $e; - + return null; } - + if (!$this->collections || !$list) return reset($list); - + $list = $this->checkAndGetDao()-> fetchCollections($this->collections, $list); - + return reset($list); } - + public function getList() { try { + $dao = $this->checkAndGetDao(); $list = - $this->checkAndGetDao()-> - getListByQuery($this->toSelectQuery()); - + $dao instanceof NoSqlDAO + ? $dao->getListByCriteria($this) + : $dao->getListByQuery($this->toSelectQuery()); } catch (ObjectNotFoundException $e) { if (!$this->isSilent()) throw $e; - + return array(); } - + if (!$this->collections || !$list) return $list; - + return $this->checkAndGetDao()-> fetchCollections($this->collections, $list); } - + /** * @return QueryResult **/ @@ -372,10 +378,10 @@ public function getResult() $result = $this->checkAndGetDao()-> getQueryResult($this->toSelectQuery()); - + if (!$this->collections || !$result->getCount()) return $result; - + return $result->setList( $this->checkAndGetDao()->fetchCollections( $this->collections, @@ -383,61 +389,61 @@ public function getResult() ) ); } - + public function getCustom($index = null) { try { $result = $this->checkAndGetDao()->getCustom($this->toSelectQuery()); - + if ($index) { if (array_key_exists($index, $result)) return $result[$index]; - + throw new MissingElementException( 'No such key: "'.$index.'" in result set.' ); } - + return $result; } catch (ObjectNotFoundException $e) { if (!$this->isSilent()) throw $e; - + return null; } } - + public function getCustomList() { try { return $this->checkAndGetDao()-> getCustomList($this->toSelectQuery()); - + } catch (ObjectNotFoundException $e) { if (!$this->isSilent()) throw $e; - + return array(); } } - + public function getPropertyList() { try { return $this->checkAndGetDao()-> getCustomRowList($this->toSelectQuery()); - + } catch (ObjectNotFoundException $e) { if (!$this->isSilent()) throw $e; - + return array(); } } - + public function toString() { return $this->toDialectString( @@ -446,12 +452,12 @@ public function toString() : ImaginaryDialect::me() ); } - + public function toDialectString(Dialect $dialect) { return $this->toSelectQuery()->toDialectString($dialect); } - + /** * @return SelectQuery **/ @@ -466,13 +472,13 @@ public function toSelectQuery() ); } else $query = $this->checkAndGetDao()->makeSelectHead(); - + if ($this->distinct) $query->distinct(); - + return $this->fillSelectQuery($query); } - + /** * @return SelectQuery **/ @@ -480,23 +486,23 @@ public function fillSelectQuery(SelectQuery $query) { $query-> limit($this->limit, $this->offset); - + if ($this->distinct) $query->distinct(); - + if ($this->logic->getSize()) { $query-> andWhere( $this->logic->toMapped($this->checkAndGetDao(), $query) ); } - + if ($this->order) { $query->setOrderChain( $this->order->toMapped($this->checkAndGetDao(), $query) ); } - + if ( $this->projection->isEmpty() && ( @@ -510,22 +516,22 @@ public function fillSelectQuery(SelectQuery $query) true ); } - + return $query; } - + /** * @return Criteria **/ public function dropProjectionByType(/* array */ $dropTypes) { Assert::isInstance($this->projection, 'ProjectionChain'); - + $this->projection->dropByType($dropTypes); - + return $this; } - + private function joinProperties( SelectQuery $query, ProtoDAO $parentDao, @@ -535,7 +541,7 @@ private function joinProperties( ) { $proto = call_user_func(array($parentDao->getObjectName(), 'proto')); - + foreach ($proto->getPropertyList() as $property) { if ( ($property instanceof LightMetaProperty) @@ -566,7 +572,7 @@ private function joinProperties( $proto = call_user_func( array($property->getClassName(), 'proto') ); - + foreach ($proto->getPropertyList() as $innerProperty) $query->get( new DBField( @@ -574,25 +580,25 @@ private function joinProperties( $parentTable ) ); - + continue; } - + $propertyDao = call_user_func( array($property->getClassName(), 'dao') ); - + // add's custom dao's injection possibility if (!$propertyDao instanceof ProtoDAO) continue; - + $tableAlias = $propertyDao->getJoinName( $property->getColumnName(), $prefix ); - + $fields = $propertyDao->getFields(); - + if (!$query->hasJoinedTable($tableAlias)) { $logic = Expression::eq( @@ -600,19 +606,19 @@ private function joinProperties( $property->getColumnName(), $parentTable ), - + DBField::create( $propertyDao->getIdName(), $tableAlias ) ); - + if ($property->isRequired() && $parentRequired) $query->join($propertyDao->getTable(), $logic, $tableAlias); else $query->leftJoin($propertyDao->getTable(), $logic, $tableAlias); } - + foreach ($fields as $field) { $query->get( new DBField($field, $tableAlias), @@ -620,7 +626,7 @@ private function joinProperties( .$field ); } - + $this->joinProperties( $query, $propertyDao, @@ -631,7 +637,7 @@ private function joinProperties( } } } - + /** * @return AbstractProtoClass **/ From 21c05b93ff8ee2702d941535162e7c86aeade6b3 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 6 Apr 2012 19:05:30 +0400 Subject: [PATCH 054/418] mongo fix --- core/NoSQL/MongoBase.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index d606a55926..0f228ba1b0 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -296,14 +296,14 @@ protected function makeIdList(array $keys) { * @param Criteria $criteria * @return array */ - protected function parseCriteria(Criteria $criteria) { + protected function parseCriteria(Criteria $criteria=null) { $result = array(); // парсим табличку - if( $criteria->getDao() ) { + if( !is_null($criteria) && $criteria->getDao() ) { $result[self::C_TABLE] = $criteria->getDao()->getTable(); } // парсим запросы - if( $criteria->getLogic()->getLogic() ) { + if( !is_null($criteria) && $criteria->getLogic()->getLogic() ) { $logic = $criteria->getLogic()->getChain(); $expression = array_shift($logic); if( $expression instanceof NoSQLExpression ) { @@ -311,7 +311,7 @@ protected function parseCriteria(Criteria $criteria) { } } // парсим сортировку - if( $criteria->getOrder() ) { + if( !is_null($criteria) && $criteria->getOrder() ) { /** @var $order OrderBy */ $order = $criteria->getOrder()->getLast(); if( $order instanceof OrderBy ) { @@ -323,13 +323,13 @@ protected function parseCriteria(Criteria $criteria) { $result[self::C_ORDER] = null; } // парсим лимит - if( $criteria->getLimit() ) { + if( !is_null($criteria) && $criteria->getLimit() ) { $result[self::C_LIMIT] = $criteria->getLimit(); } else { $result[self::C_LIMIT] = null; } // парсим сдвиг - if( $criteria->getOffset() ) { + if( !is_null($criteria) && $criteria->getOffset() ) { $result[self::C_SKIP] = $criteria->getOffset(); } else { $result[self::C_SKIP] = null; From ac5a6ed0589a581aa6aa7350d8c8214c1c4f3c97 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Mon, 9 Apr 2012 00:09:54 +0400 Subject: [PATCH 055/418] NoSQL map/reduce --- core/NoSQL/MongoBase.class.php | 49 ++++++++++++++++++++++++++++++++++ core/NoSQL/NoSQL.class.php | 3 ++- core/NoSQL/NoSqlDAO.class.php | 7 +++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 0f228ba1b0..5e998562c1 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -255,6 +255,55 @@ protected function mongoFind($table, array $query, array $fields=array(), array return $rows; } + /** + * @param string $table + * @param string $map + * @param string $reduce + * @param Criteria $criteria + * @return array + */ + public function mapReduce($table, $map, $reduce, Criteria $criteria=null) { + $options = $this->parseCriteria($criteria); + + $command = array( + 'mapreduce' => $table, + 'map' => new MongoCode($map), + 'reduce' => new MongoCode($reduce), + 'out' => array('inline' => 1) + ); + // обрабатываем критерию + if( !is_null($options[self::C_QUERY]) ) { + $command['query'] = $options[self::C_QUERY]; + } + if( !is_null($options[self::C_QUERY]) ) { + $command['sort'] = $options[self::C_ORDER]; + } + if( !is_null($options[self::C_LIMIT]) ) { + $command['limit'] = $options[self::C_LIMIT]; + } + + $result = $this->db->command($command); + // обрабатываем результаты + $list = array(); + if( is_array($result) && isset($result['ok']) && $result['ok']==1 ) { + foreach( $result['results'] as $row ) { + // prepare id + $row['id'] = $row['_id']; + unset($row['_id']); + // prepare values + foreach($row['value'] as $key=>$value) { + $row[$key] = is_bool($value) ? (int)$value : $value; + } + unset($row['value']); + + $list[ $row['id'] ] = $row; + } + } else { + throw new NoSQLException('Error during map/reduce running'); + } + return $list; + } + /// helper functions //@{ /** diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php index 7a17fbc412..3408cdec6d 100644 --- a/core/NoSQL/NoSQL.class.php +++ b/core/NoSQL/NoSQL.class.php @@ -44,7 +44,8 @@ abstract public function getListByField($table, $field, $value, Criteria $criter abstract public function getIdListByField($table, $field, $value, Criteria $criteria = null); abstract public function find($table, $query); abstract public function findByCriteria(Criteria $criteria); -// abstract public function count($table, $query); + + abstract public function mapReduce($table, $map, $reduce, Criteria $criteria=null); public function getTableInfo($table) { throw new UnsupportedMethodException('Can not execute getTableInfo in NoSQL'); diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index ee4597a710..fb0ccdf201 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -377,6 +377,13 @@ public function getIdListByField($field, $value, Criteria $criteria = null) { } //@} +/// map/reduce +//@{ + public function mapReduce($map, $reduce, Criteria $criteria=null) { + return $this->getLink()->mapReduce( $this->getTable(), $map, $reduce, $criteria ); + } +//@} + /** * @param $object * @throws WrongStateException From 03364c4209303379c7d9f876c16ddf0c1ae40b3a Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Mon, 9 Apr 2012 11:43:57 +0400 Subject: [PATCH 056/418] small fix --- core/NoSQL/MongoBase.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 5e998562c1..8dc4e0779c 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -275,7 +275,7 @@ public function mapReduce($table, $map, $reduce, Criteria $criteria=null) { if( !is_null($options[self::C_QUERY]) ) { $command['query'] = $options[self::C_QUERY]; } - if( !is_null($options[self::C_QUERY]) ) { + if( !is_null($options[self::C_ORDER]) ) { $command['sort'] = $options[self::C_ORDER]; } if( !is_null($options[self::C_LIMIT]) ) { From 3d6f6b52b52ea0c2e5b39beca212f6a841fc8d4a Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Mon, 9 Apr 2012 17:53:47 +0400 Subject: [PATCH 057/418] NoSQLExpression update --- core/Logic/NoSQLExpression.class.php | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index 4a518f970f..a00b2d4230 100644 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -10,12 +10,17 @@ final class NoSQLExpression implements LogicalObject, MappableObject { const C_FIELD = 2; const C_VALUE = 3; + const V_LEFT = 101; + const V_RIGHT = 102; + const EXP_EQ = 1001; const EXP_NOTEQ = 1002; const EXP_GT = 1003; const EXP_GTE = 1004; const EXP_LT = 1005; const EXP_LTE = 1006; + const EXP_BTW_STR = 1006; + const EXP_BTW_SFT = 1006; /** * true = объединять условия по И @@ -111,6 +116,28 @@ public function addLte($field, $value) { ); return $this; } + + public function addBetweenStrict($field, $left, $right) { + Assert::isInteger($left); + Assert::isInteger($right); + $this->conditions[] = array( + self::C_TYPE => self::EXP_BTW_STR, + self::C_FIELD => (string)$field, + self::C_VALUE => array( self::V_LEFT=>$left, self::V_RIGHT=>$right ), + ); + return $this; + } + + public function addBetweenSoft($field, $left, $right) { + Assert::isInteger($left); + Assert::isInteger($right); + $this->conditions[] = array( + self::C_TYPE => self::EXP_BTW_SFT, + self::C_FIELD => (string)$field, + self::C_VALUE => array( self::V_LEFT=>$left, self::V_RIGHT=>$right ), + ); + return $this; + } //@} /// helper functions @@ -170,6 +197,20 @@ public function toMongoQuery() { $query[] = array( $condition[self::C_FIELD] => array('$lte' => $condition[self::C_VALUE]) ); } } break; + case self::EXP_BTW_STR: { + if( $this->unite ) { + $query[ $condition[self::C_FIELD] ] = array('$gt' => $condition[self::C_VALUE][self::V_LEFT], '$lt' => $condition[self::C_VALUE][self::V_RIGHT]); + } else { + $query[] = array( $condition[self::C_FIELD] => array('$gt' => $condition[self::C_VALUE][self::V_LEFT], '$lt' => $condition[self::C_VALUE][self::V_RIGHT]) ); + } + } break; + case self::EXP_BTW_SFT: { + if( $this->unite ) { + $query[ $condition[self::C_FIELD] ] = array('$gte' => $condition[self::C_VALUE][self::V_LEFT], '$lte' => $condition[self::C_VALUE][self::V_RIGHT]); + } else { + $query[] = array( $condition[self::C_FIELD] => array('$gte' => $condition[self::C_VALUE][self::V_LEFT], '$lte' => $condition[self::C_VALUE][self::V_RIGHT]) ); + } + } break; default: { throw new WrongStateException( 'Sorry, I do not know how to work with you condition with ' ); } break; From 100a00303b46110c5581f9c28eae34ac9cd0bcb3 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Mon, 9 Apr 2012 18:03:01 +0400 Subject: [PATCH 058/418] fix --- core/Logic/NoSQLExpression.class.php | 4 ++-- core/NoSQL/MongoBase.class.php | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index a00b2d4230..567bd6af10 100644 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -19,8 +19,8 @@ final class NoSQLExpression implements LogicalObject, MappableObject { const EXP_GTE = 1004; const EXP_LT = 1005; const EXP_LTE = 1006; - const EXP_BTW_STR = 1006; - const EXP_BTW_SFT = 1006; + const EXP_BTW_STR = 1007; + const EXP_BTW_SFT = 1008; /** * true = объединять условия по И diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 8dc4e0779c..c5e7f3b6e0 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -264,6 +264,8 @@ protected function mongoFind($table, array $query, array $fields=array(), array */ public function mapReduce($table, $map, $reduce, Criteria $criteria=null) { $options = $this->parseCriteria($criteria); + var_dump($options[self::C_QUERY]); + die(); $command = array( 'mapreduce' => $table, From 9d1628c5fb7db5d2f2a016bc9fd316c112472b19 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Mon, 9 Apr 2012 18:03:33 +0400 Subject: [PATCH 059/418] fix --- core/NoSQL/MongoBase.class.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index c5e7f3b6e0..8dc4e0779c 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -264,8 +264,6 @@ protected function mongoFind($table, array $query, array $fields=array(), array */ public function mapReduce($table, $map, $reduce, Criteria $criteria=null) { $options = $this->parseCriteria($criteria); - var_dump($options[self::C_QUERY]); - die(); $command = array( 'mapreduce' => $table, From b2f82ad7dd2aec909e46085e5937fd968c48dc5d Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Mon, 9 Apr 2012 23:29:56 +0400 Subject: [PATCH 060/418] Mongo fix --- core/NoSQL/MongoBase.class.php | 5 +++-- core/NoSQL/NoSqlDAO.class.php | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 8dc4e0779c..a15797f654 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -105,7 +105,7 @@ public function selectList($table, array $keys) { $this ->db ->selectCollection($table) - ->find( array('$or' => $this->makeIdList($keys)) ); + ->find( array('_id' => array('$in'=>$this->makeIdList($keys)) ) ); // recieving objects $rows = array(); foreach ($cursor as $row) { @@ -335,7 +335,8 @@ protected function makeId($key) { protected function makeIdList(array $keys) { $fields = array(); foreach( $keys as $key ) { - $fields[] = array( '_id'=>$this->makeId($key) ); + //$fields[] = array( '_id'=>$this->makeId($key) ); + $fields[] = $this->makeId($key); } return $fields; } diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index fb0ccdf201..d1a8438276 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -129,6 +129,8 @@ public function getListByLogic(LogicalObject $logic, $expires = Cache::DO_NOT_CA * @return array */ public function getListByCriteria(Criteria $criteria, $expires = Cache::DO_NOT_CACHE) { + $criteria->setDao( $this ); + // getting list $list = array(); $stack = $this->getLink()->findByCriteria($criteria); foreach( $stack as $row ) { From f4ac163c4624400019d41b8de17ba93938c09577 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 10 Apr 2012 20:54:27 +0400 Subject: [PATCH 061/418] NoSQLObject->toArray fix --- core/NoSQL/NoSqlObject.class.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/core/NoSQL/NoSqlObject.class.php b/core/NoSQL/NoSqlObject.class.php index 538db52747..bbf7b32a80 100644 --- a/core/NoSQL/NoSqlObject.class.php +++ b/core/NoSQL/NoSqlObject.class.php @@ -30,12 +30,17 @@ public function toArray() { $value = $value->toStamp(); //$value = $value->toString(); } - $entity[ $property->getColumnName() ] = is_numeric($value) ? (int)$value : $value; - + if( Assert::checkInteger($value) ) { + $entity[ $property->getColumnName() ] = (int)$value; + } elseif( Assert::checkFloat($value) ) { + $entity[ $property->getColumnName() ] = (float)$value; + } else { + $entity[ $property->getColumnName() ] = $value; + } } // обрабатываем перечисления elseif( $property->getType()=='enumeration' ) { $value = call_user_func(array($this, $property->getGetter())); - $entity[ $property->getColumnName() ] = (int)$value->getId(); + $entity[ $property->getColumnName() ] = is_null($value) ? null : (int)$value->getId(); } // обрабатываем связи 1к1 elseif( in_array($property->getType(), self::$identifiers) && $property->getRelationId()==1 ) { $value = call_user_func(array($this, $property->getGetter().'Id')); From ff673e0de49007deee324e64aa5e9bb2e2e0ec40 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 11 Apr 2012 14:08:43 +0400 Subject: [PATCH 062/418] Mongo count for one-to-many --- core/NoSQL/MongoBase.class.php | 45 ++++++++++++++++--- core/NoSQL/NoSQL.class.php | 1 + core/NoSQL/NoSqlDAO.class.php | 4 ++ .../OneToManyNoSqlLinked.class.php | 9 ++++ 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index a15797f654..27561b9643 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -191,6 +191,16 @@ public function getTotalCount($table) { ->count(); } + public function getCountByField($table, $field, $value, Criteria $criteria = null) { + if( Assert::checkInteger($value) ) { + $value = (int)$value; + } + $options = $this->parseCriteria($criteria); + + return + $this->mongoCount($table, array($field => $value), array('_id'), $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); + } + public function getListByField($table, $field, $value, Criteria $criteria = null) { if( Assert::checkInteger($value) ) { $value = (int)$value; @@ -232,6 +242,33 @@ public function findByCriteria(Criteria $criteria) { protected function mongoFind($table, array $query, array $fields=array(), array $order=null, $limit=null, $skip=null) { // quering + $cursor = $this->mongoMakeCursor($table, $query, $fields, $order, $limit, $skip); + // recieving objects + $rows = array(); + foreach ($cursor as $row) { + $rows[] = $this->decodeId($row); + } + // return result + return $rows; + } + + protected function mongoCount($table, array $query, array $fields=array(), array $order=null, $limit=null, $skip=null) { + // quering + $cursor = $this->mongoMakeCursor($table, $query, $fields, $order, $limit, $skip); + // return result + return $cursor->count(); + } + + /** + * @param $table + * @param array $query + * @param array $fields + * @param array $order + * @param int $limit + * @param int $skip + * @return MongoCursor + */ + protected function mongoMakeCursor($table, array $query, array $fields=array(), array $order=null, $limit=null, $skip=null) { $cursor = $this ->db @@ -246,13 +283,7 @@ protected function mongoFind($table, array $query, array $fields=array(), array if( !is_null($skip) ) { $cursor->skip( $skip ); } - // recieving objects - $rows = array(); - foreach ($cursor as $row) { - $rows[] = $this->decodeId($row); - } - // return result - return $rows; + return $cursor; } /** diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php index 3408cdec6d..a1f8adf6ca 100644 --- a/core/NoSQL/NoSQL.class.php +++ b/core/NoSQL/NoSQL.class.php @@ -40,6 +40,7 @@ abstract public function getPlainList($table); abstract public function getTotalCount($table); // custom queries + abstract public function getCountByField($table, $field, $value, Criteria $criteria = null); abstract public function getListByField($table, $field, $value, Criteria $criteria = null); abstract public function getIdListByField($table, $field, $value, Criteria $criteria = null); abstract public function find($table, $query); diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index d1a8438276..49b3ddb97e 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -377,6 +377,10 @@ public function getIdListByField($field, $value, Criteria $criteria = null) { } return $list; } + + public function getCountByField($field, $value, Criteria $criteria = null) { + return $this->getLink()->getCountByField( $this->getTable(), $field, $value, $criteria ); + } //@} /// map/reduce diff --git a/main/UnifiedContainer/OneToManyNoSqlLinked.class.php b/main/UnifiedContainer/OneToManyNoSqlLinked.class.php index c873e2d7fe..d5ee0c97ac 100644 --- a/main/UnifiedContainer/OneToManyNoSqlLinked.class.php +++ b/main/UnifiedContainer/OneToManyNoSqlLinked.class.php @@ -86,4 +86,13 @@ protected function fetchList() { return $this; } + public function getCount() + { + if (!$this->isFetched() && $this->parent->getId()) { + return $this->dao->getCountByField( $this->getParentIdField(), $this->parent->getId(), $this->worker->getCriteria() ); + } + + return count($this->list); + } + } From df1a89f2f3cca72ee466c0adc27c4e23a7759a6d Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 11 Apr 2012 14:18:40 +0400 Subject: [PATCH 063/418] fix --- core/NoSQL/MongoBase.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 27561b9643..1917978cc4 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -232,9 +232,9 @@ public function findByCriteria(Criteria $criteria) { if( !isset($options[self::C_TABLE]) ) { throw new NoSQLException('Can not find without table!'); } - if( !isset($options[self::C_QUERY]) ) { - throw new NoSQLException('Can not find without query!'); - } +// if( !isset($options[self::C_QUERY]) ) { +// throw new NoSQLException('Can not find without query!'); +// } return $this->mongoFind($options[self::C_TABLE], $options[self::C_QUERY], array(), $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); From b22b1dc3e9e1d26f5580146077125c633b52f968 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 11 Apr 2012 15:31:00 +0400 Subject: [PATCH 064/418] mongo criteria fix --- core/NoSQL/MongoBase.class.php | 9 +++++++++ core/NoSQL/NoSQL.class.php | 1 + 2 files changed, 10 insertions(+) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 1917978cc4..613760cb93 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -131,6 +131,9 @@ public function insert($table, array $row) { return $this->decodeId($row); } + public function batchInsert($table, array $rows) { + } + public function update($table, array $row) { $row = $this->encodeId($row); $id = $row['_id']; @@ -382,6 +385,8 @@ protected function parseCriteria(Criteria $criteria=null) { // парсим табличку if( !is_null($criteria) && $criteria->getDao() ) { $result[self::C_TABLE] = $criteria->getDao()->getTable(); + } else { + $result[self::C_TABLE] = null; } // парсим запросы if( !is_null($criteria) && $criteria->getLogic()->getLogic() ) { @@ -389,7 +394,11 @@ protected function parseCriteria(Criteria $criteria=null) { $expression = array_shift($logic); if( $expression instanceof NoSQLExpression ) { $result[self::C_QUERY] = $expression->toMongoQuery(); + } else { + $result[self::C_QUERY] = array(); } + } else { + $result[self::C_QUERY] = array(); } // парсим сортировку if( !is_null($criteria) && $criteria->getOrder() ) { diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php index a1f8adf6ca..dea3bb8cb1 100644 --- a/core/NoSQL/NoSQL.class.php +++ b/core/NoSQL/NoSQL.class.php @@ -31,6 +31,7 @@ abstract class NoSQL extends DB { abstract public function selectOne($table, $key); abstract public function selectList($table, array $keys); abstract public function insert($table, array $row); + abstract public function batchInsert($table, array $rows); abstract public function update($table, array $row); abstract public function deleteOne($table, $key); abstract public function deleteList($table, array $keys); From 2735ba474254219e5bc121ed9e55844d6d8ff275 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 11 Apr 2012 15:32:29 +0400 Subject: [PATCH 065/418] fix --- core/NoSQL/NoSqlDAO.class.php | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 49b3ddb97e..2df912813e 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -258,6 +258,46 @@ public function add(Identifiable $object) { return $object; } + /** + * @param NoSqlObject[] $objectList + * @return AbstractAmqpObject|mixed|null + */ + public function multiAdd(array $objectList) { + $rows = array(); + foreach( $objectList as $object ) { + $this->assertNoSqlObject( $object ); + // преобразуем объект в массив для nosql + $rows[] = $object->toArray(); + } + + if( !empty($rows) ) { + $link = NoSqlPool::getByDao( $this ); + + } + + // make sequence + +// $object->setId( +// $link->obtainSequence( +// $this->getSequence() +// ) +// ); + + // insert + $entity = + $link + ->insert( + $this->getTable(), + $object->toArray() + ); + + $object->setId( $entity['id'] ); + // проверка добавления + //$object = $this->getById( $entity['id'] ); + + return $object; + } + public function save(Identifiable $object) { $this->assertNoSqlObject( $object ); From b242b5c590a38ce8b79d423a0abde07acb2df0be Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 11 Apr 2012 16:02:59 +0400 Subject: [PATCH 066/418] nosql batch insert --- core/NoSQL/MongoBase.class.php | 5 ++++- core/NoSQL/NoSqlDAO.class.php | 40 ++++++++++++++++------------------ 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 613760cb93..237892f684 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -116,7 +116,9 @@ public function selectList($table, array $keys) { } public function insert($table, array $row) { - $row = $this->encodeId($row); + if( isset($row['id']) ) { + $row = $this->encodeId($row); + } // save $result = $this @@ -132,6 +134,7 @@ public function insert($table, array $row) { } public function batchInsert($table, array $rows) { + throw new UnimplementedFeatureException('Unfortunately method "batchInsert" is not implemented yet :('); } public function update($table, array $row) { diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 2df912813e..4034581b42 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -264,6 +264,7 @@ public function add(Identifiable $object) { */ public function multiAdd(array $objectList) { $rows = array(); + $objectList = array_values($objectList); foreach( $objectList as $object ) { $this->assertNoSqlObject( $object ); // преобразуем объект в массив для nosql @@ -272,30 +273,27 @@ public function multiAdd(array $objectList) { if( !empty($rows) ) { $link = NoSqlPool::getByDao( $this ); - + // insert + $entityList = + $link + ->batchInsert( + $this->getTable(), + $rows + ); + foreach($entityList as $key=>$entity) { + $object = $objectList[$key]; + $object->setId($entity['id']); + } } - // make sequence - -// $object->setId( -// $link->obtainSequence( -// $this->getSequence() -// ) -// ); - - // insert - $entity = - $link - ->insert( - $this->getTable(), - $object->toArray() - ); - - $object->setId( $entity['id'] ); - // проверка добавления - //$object = $this->getById( $entity['id'] ); + // проверяем наличие ИДешек + foreach($objectList as &$object) { + if(!$object->getId()) { + unset($object); + } + } - return $object; + return $objectList; } public function save(Identifiable $object) { From dac8b597e14fad5aec40611bdbea42bde291e4b8 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 11 Apr 2012 17:49:44 +0400 Subject: [PATCH 067/418] mongo fix --- core/NoSQL/MongoBase.class.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 237892f684..b29ab94daf 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -116,9 +116,7 @@ public function selectList($table, array $keys) { } public function insert($table, array $row) { - if( isset($row['id']) ) { - $row = $this->encodeId($row); - } + $row = $this->encodeId($row); // save $result = $this @@ -349,7 +347,9 @@ public function mapReduce($table, $map, $reduce, Criteria $criteria=null) { * @return array */ protected function encodeId(array $row) { - $row['_id'] = $this->makeId($row['id']); + if( isset($row['id']) ) { + $row['_id'] = $this->makeId($row['id']); + } unset($row['id']); return $row; } From eb98a300725362e2ad64082b20412795600b0a61 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Mon, 16 Apr 2012 23:19:27 +0400 Subject: [PATCH 068/418] permission fix --- .gitignore | 0 core/Base/Aliased.class.php | 0 core/Base/Assert.class.php | 0 core/Base/Date.class.php | 0 core/Base/Enumeration.class.php | 0 core/Base/Identifiable.class.php | 0 core/Base/IdentifiableObject.class.php | 0 core/Base/Identifier.class.php | 0 core/Base/Instantiatable.class.php | 0 core/Base/IntervalUnit.class.php | 0 core/Base/Named.class.php | 0 core/Base/NamedObject.class.php | 0 core/Base/PriorityQueue.class.php | 0 core/Base/Prototyped.class.php | 0 core/Base/Session.class.php | 0 core/Base/Singleton.class.php | 0 core/Base/StaticFactory.class.php | 0 core/Base/Stringable.class.php | 0 core/Base/Ternary.class.php | 0 core/Base/Time.class.php | 0 core/Base/Timestamp.class.php | 0 core/Cache/AggregateCache.class.php | 0 core/Cache/BaseAggregateCache.class.php | 0 core/Cache/BaseLocker.class.php | 0 core/Cache/Cache.class.php | 0 core/Cache/CachePeer.class.php | 0 core/Cache/CyclicAggregateCache.class.php | 0 core/Cache/DebugCachePeer.class.php | 0 core/Cache/DirectoryLocker.class.php | 0 core/Cache/FileLocker.class.php | 0 core/Cache/Memcached.class.php | 0 core/Cache/MemcachedLocker.class.php | 0 core/Cache/PeclMemcached.class.php | 0 core/Cache/ReadOnlyPeer.class.php | 0 core/Cache/RubberFileSystem.class.php | 0 core/Cache/RuntimeMemory.class.php | 0 core/Cache/SelectivePeer.class.php | 0 core/Cache/SemaphorePool.class.php | 0 core/Cache/SharedMemory.class.php | 0 core/Cache/SimpleAggregateCache.class.php | 0 core/Cache/SystemFiveLocker.class.php | 0 core/Cache/WatermarkedPeer.class.php | 0 core/Cache/eAcceleratorLocker.class.php | 0 core/DB/DB.class.php | 0 core/DB/DBPool.class.php | 0 core/DB/Dialect.class.php | 0 core/DB/ImaginaryDialect.class.php | 0 core/DB/LiteDialect.class.php | 0 core/DB/MyDialect.class.php | 0 core/DB/MyImprovedDialect.class.php | 0 core/DB/MySQL.class.php | 0 core/DB/MySQLim.class.php | 0 core/DB/PgSQL.class.php | 0 core/DB/PostgresDialect.class.php | 0 core/DB/PostgresError.class.php | 0 core/DB/Queue.class.php | 0 core/DB/SQLite.class.php | 0 core/DB/Sequenceless.class.php | 0 core/DB/Transaction/AccessMode.class.php | 0 core/DB/Transaction/BaseTransaction.class.php | 0 core/DB/Transaction/DBTransaction.class.php | 0 core/DB/Transaction/FakeTransaction.class.php | 0 core/DB/Transaction/IsolationLevel.class.php | 0 core/DB/Transaction/Transaction.class.php | 0 core/DB/Transaction/TransactionQueue.class.php | 0 core/Exceptions/BadRequestException.class.php | 0 core/Exceptions/BaseException.class.php | 0 core/Exceptions/BusinessLogicException.class.php | 0 .../CachedObjectNotFoundException.class.php | 0 core/Exceptions/ClassNotFoundException.class.php | 0 core/Exceptions/DatabaseException.class.php | 0 core/Exceptions/DuplicateObjectException.class.php | 0 core/Exceptions/FileNotFoundException.class.php | 0 core/Exceptions/IOException.class.php | 0 core/Exceptions/IOTimedOutException.class.php | 0 core/Exceptions/MissingElementException.class.php | 0 core/Exceptions/NetworkException.class.php | 0 core/Exceptions/ObjectNotFoundException.class.php | 0 core/Exceptions/PostgresDatabaseException.class.php | 0 core/Exceptions/SecurityException.class.php | 0 core/Exceptions/SoapFault.class.php | 0 core/Exceptions/SyntaxErrorException.class.php | 0 core/Exceptions/TooManyRowsException.class.php | 0 .../UnimplementedFeatureException.class.php | 0 .../Exceptions/UnsupportedMethodException.class.php | 0 core/Exceptions/WrongArgumentException.class.php | 0 core/Exceptions/WrongStateException.class.php | 0 core/Form/Filter.class.php | 0 core/Form/Filters/BaseFilter.class.php | 0 core/Form/Filters/CallbackFilter.class.php | 0 .../Form/Filters/CompressWhitespaceFilter.class.php | 0 core/Form/Filters/CropFilter.class.php | 0 core/Form/Filters/DateRangeDisplayFilter.class.php | 0 core/Form/Filters/FilterChain.class.php | 0 core/Form/Filters/Filtrator.class.php | 0 core/Form/Filters/HashFilter.class.php | 0 core/Form/Filters/HtmlSpecialCharsFilter.class.php | 0 core/Form/Filters/JsonDecoderFilter.class.php | 0 core/Form/Filters/JsonEncoderFilter.class.php | 0 core/Form/Filters/LowerCaseFilter.class.php | 0 core/Form/Filters/NewLinesToBreaks.class.php | 0 core/Form/Filters/NormalizeUrlFilter.class.php | 0 core/Form/Filters/PCREFilter.class.php | 0 core/Form/Filters/Paragraphizer.class.php | 0 core/Form/Filters/RemoveNewlineFilter.class.php | 0 core/Form/Filters/RussianTypograph.class.php | 0 core/Form/Filters/SafeUtf8Filter.class.php | 0 core/Form/Filters/StringReplaceFilter.class.php | 0 core/Form/Filters/StripTagsFilter.class.php | 0 core/Form/Filters/TrimFilter.class.php | 0 core/Form/Filters/UnTypographizer.class.php | 0 core/Form/Filters/UnixToUnixDecode.class.php | 0 core/Form/Filters/UnixToUnixEncode.class.php | 0 core/Form/Filters/UnserializeFilter.class.php | 0 core/Form/Filters/UpperCaseFilter.class.php | 0 core/Form/Filters/UrlDecodeFilter.class.php | 0 core/Form/Filters/UrlEncodeFilter.class.php | 0 core/Form/Filters/Utf16ConverterFilter.class.php | 0 core/Form/Filters/WordSplitterFilter.class.php | 0 core/Form/Form.class.php | 0 core/Form/FormField.class.php | 0 core/Form/FormUtils.class.php | 0 core/Form/MappedForm.class.php | 0 core/Form/PlainForm.class.php | 0 core/Form/Primitive.class.php | 0 core/Form/Primitives/BaseObjectPrimitive.class.php | 0 core/Form/Primitives/BasePrimitive.class.php | 0 core/Form/Primitives/ComplexPrimitive.class.php | 0 core/Form/Primitives/DateRangeList.class.php | 0 core/Form/Primitives/ExplodedPrimitive.class.php | 0 core/Form/Primitives/FiltrablePrimitive.class.php | 0 .../Form/Primitives/IdentifiablePrimitive.class.php | 0 core/Form/Primitives/ListedPrimitive.class.php | 0 core/Form/Primitives/PrimitiveAlias.class.php | 0 core/Form/Primitives/PrimitiveAnyType.class.php | 0 core/Form/Primitives/PrimitiveArray.class.php | 0 core/Form/Primitives/PrimitiveBinary.class.php | 0 core/Form/Primitives/PrimitiveBoolean.class.php | 0 core/Form/Primitives/PrimitiveClass.class.php | 0 core/Form/Primitives/PrimitiveDate.class.php | 0 core/Form/Primitives/PrimitiveDateRange.class.php | 0 core/Form/Primitives/PrimitiveEnumeration.class.php | 0 .../PrimitiveEnumerationByValue.class.php | 0 .../Primitives/PrimitiveEnumerationList.class.php | 0 core/Form/Primitives/PrimitiveFile.class.php | 0 core/Form/Primitives/PrimitiveFloat.class.php | 0 core/Form/Primitives/PrimitiveForm.class.php | 0 core/Form/Primitives/PrimitiveFormsList.class.php | 0 core/Form/Primitives/PrimitiveHstore.class.php | 0 core/Form/Primitives/PrimitiveHttpUrl.class.php | 0 core/Form/Primitives/PrimitiveIdentifier.class.php | 0 .../Primitives/PrimitiveIdentifierList.class.php | 0 core/Form/Primitives/PrimitiveImage.class.php | 0 core/Form/Primitives/PrimitiveInet.class.php | 0 core/Form/Primitives/PrimitiveInteger.class.php | 0 .../Primitives/PrimitiveIntegerIdentifier.class.php | 0 core/Form/Primitives/PrimitiveIpAddress.class.php | 0 core/Form/Primitives/PrimitiveIpRange.class.php | 0 core/Form/Primitives/PrimitiveList.class.php | 0 core/Form/Primitives/PrimitiveMultiList.class.php | 0 core/Form/Primitives/PrimitiveNoValue.class.php | 0 core/Form/Primitives/PrimitiveNumber.class.php | 0 core/Form/Primitives/PrimitivePlainList.class.php | 0 .../PrimitivePolymorphicIdentifier.class.php | 0 core/Form/Primitives/PrimitiveRange.class.php | 0 .../Primitives/PrimitiveScalarIdentifier.class.php | 0 core/Form/Primitives/PrimitiveString.class.php | 0 core/Form/Primitives/PrimitiveTernary.class.php | 0 core/Form/Primitives/PrimitiveTime.class.php | 0 core/Form/Primitives/PrimitiveTimestamp.class.php | 0 .../Primitives/PrimitiveTimestampRange.class.php | 0 core/Form/Primitives/RangedPrimitive.class.php | 0 core/Form/Primitives/TimeList.class.php | 0 core/Form/RegulatedForm.class.php | 0 core/Logic/BinaryExpression.class.php | 0 core/Logic/CallbackLogicalObject.class.php | 0 core/Logic/EqualsLowerExpression.class.php | 0 core/Logic/Expression.class.php | 0 core/Logic/HstoreExpression.class.php | 0 core/Logic/InExpression.class.php | 0 core/Logic/Ip4ContainsExpression.class.php | 0 core/Logic/LTreeExpression.class.php | 0 core/Logic/LogicalBetween.class.php | 0 core/Logic/LogicalChain.class.php | 0 core/Logic/LogicalObject.class.php | 0 core/Logic/MappableObject.class.php | 0 core/Logic/PostfixUnaryExpression.class.php | 0 core/Logic/PrefixUnaryExpression.class.php | 0 core/OSQL/Castable.class.php | 0 core/OSQL/CombineQuery.class.php | 0 core/OSQL/CreateTableQuery.class.php | 0 core/OSQL/DBBinary.class.php | 0 core/OSQL/DBColumn.class.php | 0 core/OSQL/DBField.class.php | 0 core/OSQL/DBRaw.class.php | 0 core/OSQL/DBSchema.class.php | 0 core/OSQL/DBTable.class.php | 0 core/OSQL/DBValue.class.php | 0 core/OSQL/DataType.class.php | 0 core/OSQL/DatePart.class.php | 0 core/OSQL/DeleteQuery.class.php | 0 core/OSQL/DialectString.class.php | 0 core/OSQL/DropTableQuery.class.php | 0 core/OSQL/ExtractPart.class.php | 0 core/OSQL/FieldGroup.class.php | 0 core/OSQL/FieldTable.class.php | 0 core/OSQL/ForeignChangeAction.class.php | 0 core/OSQL/FromTable.class.php | 0 core/OSQL/FullText.class.php | 0 core/OSQL/FullTextRank.class.php | 0 core/OSQL/FullTextSearch.class.php | 0 core/OSQL/GroupBy.class.php | 0 core/OSQL/InsertOrUpdateQuery.class.php | 0 core/OSQL/InsertQuery.class.php | 0 core/OSQL/JoinCapableQuery.class.php | 0 core/OSQL/Joiner.class.php | 0 core/OSQL/OSQL.class.php | 0 core/OSQL/OrderBy.class.php | 0 core/OSQL/OrderChain.class.php | 0 core/OSQL/Query.class.php | 0 core/OSQL/QueryChain.class.php | 0 core/OSQL/QueryCombination.class.php | 0 core/OSQL/QueryIdentification.class.php | 0 core/OSQL/QueryResult.class.php | 0 core/OSQL/QuerySkeleton.class.php | 0 core/OSQL/SQLArray.class.php | 0 core/OSQL/SQLBaseJoin.class.php | 0 core/OSQL/SQLChain.class.php | 0 core/OSQL/SQLFunction.class.php | 0 core/OSQL/SQLJoin.class.php | 0 core/OSQL/SQLLeftJoin.class.php | 0 core/OSQL/SQLRightJoin.class.php | 0 core/OSQL/SQLTableName.class.php | 0 core/OSQL/SelectField.class.php | 0 core/OSQL/SelectQuery.class.php | 0 core/OSQL/TimeIntervalsGenerator.class.php | 0 core/OSQL/TruncateQuery.class.php | 0 core/OSQL/UpdateQuery.class.php | 0 doc/AUTHORS | 0 doc/ChangeLog | 0 doc/CodingStyle | 0 doc/Doxyfile | 0 doc/FAQ | 0 doc/FEATURES | 0 doc/LICENSE | 0 doc/OQL-BNF | 0 doc/README | 0 doc/ROUTERS | 0 doc/THANKS | 0 doc/TODO | 0 doc/examples/cacheSettings.php | 0 doc/examples/index.php | 0 doc/examples/singleton.php | 0 doc/examples/union.php | 0 doc/onphp.doxy.php | 0 doc/parts/doxyHead.html | 0 doc/parts/doxyHeel.html | 0 doc/project.skel/config.inc.php.tpl | 0 doc/project.skel/config.xml | 0 doc/project.skel/db/schema.sql | 0 .../src/admin/controllers/login.class.php | 0 .../src/admin/controllers/main.class.php | 0 doc/project.skel/src/admin/htdocs/index.php | 0 doc/project.skel/src/admin/templates/login.tpl.html | 0 doc/project.skel/src/admin/templates/main.tpl.html | 0 .../Auto/Business/AutoAdministrator.class.php | 0 .../Auto/DAOs/AutoAdministratorDAO.class.php | 0 .../Auto/Proto/AutoProtoAdministrator.class.php | 0 doc/project.skel/src/classes/Auto/schema.php | 0 .../src/classes/Business/Administrator.class.php | 0 .../src/classes/DAOs/AdministratorDAO.class.php | 0 .../src/classes/Flow/AuthorizationFilter.class.php | 0 .../src/classes/Proto/ProtoAdministrator.class.php | 0 .../src/user/controllers/main.class.php | 0 doc/project.skel/src/user/htdocs/index.php | 0 doc/project.skel/src/user/templates/main.tpl.html | 0 global.inc.php.tpl | 0 main/Application/ApplicationUrl.class.php | 0 main/Application/ScopeNavigationSchema.class.php | 0 main/Application/SimpleApplicationUrl.class.php | 0 main/Base/AbstractCollection.class.php | 0 main/Base/AbstractProtoClass.class.php | 0 main/Base/BaseRange.class.php | 0 main/Base/CalendarDay.class.php | 0 main/Base/CalendarMonthWeekly.class.php | 0 main/Base/CalendarWeek.class.php | 0 main/Base/CallChain.class.php | 0 main/Base/Collection.class.php | 0 main/Base/CollectionItem.class.php | 0 main/Base/Comparator.class.php | 0 main/Base/DateObjectComparator.class.php | 0 main/Base/DateRange.class.php | 0 main/Base/FloatRange.class.php | 0 main/Base/Hstore.class.php | 0 main/Base/IdentifiableTree.class.php | 0 main/Base/ImageType.class.php | 0 main/Base/ImmutableObjectComparator.class.php | 0 main/Base/InnerMetaProperty.class.php | 0 main/Base/IntegerSet.class.php | 0 main/Base/IsoCurrency.class.php | 0 main/Base/LightMetaProperty.class.php | 0 main/Base/NamedTree.class.php | 0 main/Base/Range.class.php | 0 main/Base/RequestType.class.php | 0 main/Base/SerializedObjectComparator.class.php | 0 main/Base/SingleRange.class.php | 0 main/Base/StandardComparator.class.php | 0 main/Base/TempDirectory.class.php | 0 main/Base/TempFile.class.php | 0 main/Base/TimestampRange.class.php | 0 main/Base/TransparentFile.class.php | 0 main/Charts/Google/BaseGoogleChartData.class.php | 0 .../Google/BaseGoogleChartDataEncoding.class.php | 0 .../Google/BaseGoogleChartLabelStyleType.class.php | 0 .../Google/BaseGoogleChartParameter.class.php | 0 main/Charts/Google/BaseGoogleChartStyle.class.php | 0 main/Charts/Google/ChartLabelStyle.class.php | 0 main/Charts/Google/ChartLineStyle.class.php | 0 main/Charts/Google/GoogleChart.class.php | 0 main/Charts/Google/GoogleChartAxis.class.php | 0 .../Google/GoogleChartAxisCollection.class.php | 0 main/Charts/Google/GoogleChartAxisLabel.class.php | 0 main/Charts/Google/GoogleChartAxisType.class.php | 0 main/Charts/Google/GoogleChartColor.class.php | 0 main/Charts/Google/GoogleChartData.class.php | 0 .../Charts/Google/GoogleChartDataEncoding.class.php | 0 main/Charts/Google/GoogleChartDataRange.class.php | 0 main/Charts/Google/GoogleChartDataScaling.class.php | 0 main/Charts/Google/GoogleChartDataSet.class.php | 0 .../Google/GoogleChartDataSimpleEncoding.class.php | 0 .../Google/GoogleChartDataTextEncoding.class.php | 0 main/Charts/Google/GoogleChartGrid.class.php | 0 main/Charts/Google/GoogleChartLabel.class.php | 0 main/Charts/Google/GoogleChartLabelStyle.class.php | 0 .../GoogleChartLabelStyleNumberType.class.php | 0 main/Charts/Google/GoogleChartLegend.class.php | 0 .../Google/GoogleChartLegendPositionType.class.php | 0 main/Charts/Google/GoogleChartLine.class.php | 0 main/Charts/Google/GoogleChartLineStyle.class.php | 0 main/Charts/Google/GoogleChartPiece.class.php | 0 main/Charts/Google/GoogleChartSize.class.php | 0 main/Charts/Google/GoogleChartSolidFill.class.php | 0 .../Google/GoogleChartSolidFillCollection.class.php | 0 .../Google/GoogleChartSolidFillType.class.php | 0 main/Charts/Google/GoogleChartTitle.class.php | 0 main/Charts/Google/GoogleChartType.class.php | 0 main/Charts/Google/GoogleGridedLineChart.class.php | 0 main/Charts/Google/GoogleLineChart.class.php | 0 .../Google/GoogleNormalizedLineChart.class.php | 0 main/Charts/Google/GooglePieChart.class.php | 0 main/Charts/Google/LabelStyleType.class.php | 0 main/Criteria/Criteria.class.php | 0 main/Criteria/FetchStrategy.class.php | 0 main/Criteria/Projection.class.php | 0 .../Projections/AggregateProjection.class.php | 0 .../Projections/AverageNumberProjection.class.php | 0 main/Criteria/Projections/BaseProjection.class.php | 0 main/Criteria/Projections/ClassProjection.class.php | 0 main/Criteria/Projections/CountProjection.class.php | 0 .../Projections/DistinctCountProjection.class.php | 0 .../Projections/GroupByClassProjection.class.php | 0 .../Projections/GroupByPropertyProjection.class.php | 0 .../Criteria/Projections/HavingProjection.class.php | 0 .../Projections/MappableObjectProjection.class.php | 0 .../Projections/MaximalNumberProjection.class.php | 0 .../Projections/MinimalNumberProjection.class.php | 0 .../Criteria/Projections/ObjectProjection.class.php | 0 main/Criteria/Projections/ProjectionChain.class.php | 0 .../Projections/PropertyProjection.class.php | 0 .../Projections/RowCountProjection.class.php | 0 main/Criteria/Projections/SumProjection.class.php | 0 main/Criteria/PropertyPath.class.php | 0 main/Crypto/Base62Utils.class.php | 0 main/Crypto/Crypter.class.php | 0 main/Crypto/CryptoFunctions.class.php | 0 main/Crypto/DiffieHellmanKeyPair.class.php | 0 main/Crypto/DiffieHellmanParameters.class.php | 0 main/Crypto/KeyPair.class.php | 0 main/DAOs/BaseDAO.class.php | 0 main/DAOs/DAOConnected.class.php | 0 main/DAOs/FullTextDAO.class.php | 0 main/DAOs/GenericDAO.class.php | 0 main/DAOs/Handlers/ApcSegmentHandler.class.php | 0 main/DAOs/Handlers/CacheSegmentHandler.class.php | 0 .../Handlers/FileSystemSegmentHandler.class.php | 0 main/DAOs/Handlers/MessageSegmentHandler.class.php | 0 .../DAOs/Handlers/OptimizerSegmentHandler.class.php | 0 main/DAOs/Handlers/SegmentHandler.class.php | 0 .../Handlers/SharedMemorySegmentHandler.class.php | 0 main/DAOs/Handlers/XCacheSegmentHandler.class.php | 0 .../Handlers/eAcceleratorSegmentHandler.class.php | 0 main/DAOs/ProtoDAO.class.php | 0 main/DAOs/StorableDAO.class.php | 0 main/DAOs/Workers/BaseDaoWorker.class.php | 0 main/DAOs/Workers/CacheDaoWorker.class.php | 0 main/DAOs/Workers/CommonDaoWorker.class.php | 0 main/DAOs/Workers/CustomDataScopedWorker.class.php | 0 main/DAOs/Workers/DalayedDropDaoWorker.class.php | 0 main/DAOs/Workers/NullDaoWorker.class.php | 0 main/DAOs/Workers/SmartDaoWorker.class.php | 0 main/DAOs/Workers/TransparentDaoWorker.class.php | 0 main/DAOs/Workers/VoodooDaoWorker.class.php | 0 main/EntityProto/Accessors/DTOGetter.class.php | 0 main/EntityProto/Accessors/DTOSetter.class.php | 0 .../EntityProto/Accessors/DirectoryGetter.class.php | 0 .../Accessors/DirectoryMutator.class.php | 0 .../EntityProto/Accessors/DirectorySetter.class.php | 0 main/EntityProto/Accessors/FormExporter.class.php | 0 main/EntityProto/Accessors/FormGetter.class.php | 0 .../Accessors/FormHardenedSetter.class.php | 0 main/EntityProto/Accessors/FormImporter.class.php | 0 main/EntityProto/Accessors/FormMutator.class.php | 0 main/EntityProto/Accessors/FormSetter.class.php | 0 main/EntityProto/Accessors/ObjectGetter.class.php | 0 main/EntityProto/Accessors/ObjectSetter.class.php | 0 main/EntityProto/Accessors/ScopeGetter.class.php | 0 main/EntityProto/Accessors/ScopeSetter.class.php | 0 main/EntityProto/Builders/DTOBuilder.class.php | 0 .../Builders/DTOToFormImporter.class.php | 0 .../Builders/DTOToScopeConverter.class.php | 0 .../EntityProto/Builders/DirectoryBuilder.class.php | 0 .../Builders/DirectoryToObjectBinder.class.php | 0 main/EntityProto/Builders/FormBuilder.class.php | 0 .../Builders/FormToObjectConverter.class.php | 0 .../Builders/FormToScopeExporter.class.php | 0 main/EntityProto/Builders/ObjectBuilder.class.php | 0 .../Builders/ObjectToDTOConverter.class.php | 0 .../Builders/ObjectToDirectoryBinder.class.php | 0 .../Builders/ObjectToFormConverter.class.php | 0 .../Builders/ObjectToFormSetter.class.php | 0 .../Builders/ObjectToObjectCast.class.php | 0 .../Builders/ScopeToFormImporter.class.php | 0 main/EntityProto/DirectoryContext.class.php | 0 main/EntityProto/EntityProto.class.php | 0 main/EntityProto/PrototypedBuilder.class.php | 0 main/EntityProto/PrototypedEntity.class.php | 0 main/EntityProto/PrototypedGetter.class.php | 0 main/EntityProto/PrototypedMethodCaller.class.php | 0 main/EntityProto/PrototypedSetter.class.php | 0 main/Flow/AddCommand.class.php | 0 main/Flow/BaseEditor.class.php | 0 main/Flow/CarefulCommand.class.php | 0 main/Flow/CarefulDatabaseRunner.class.php | 0 main/Flow/CommandChain.class.php | 0 main/Flow/Controller.class.php | 0 main/Flow/ControllersCollection.class.php | 0 main/Flow/DecoratorController.class.php | 0 main/Flow/DropCommand.class.php | 0 main/Flow/EditCommand.class.php | 0 main/Flow/EditorCommand.class.php | 0 main/Flow/EditorController.class.php | 0 main/Flow/ForbiddenCommand.class.php | 0 main/Flow/HandlerMapping.class.php | 0 main/Flow/HttpRequest.class.php | 0 main/Flow/ImportCommand.class.php | 0 main/Flow/MakeCommand.class.php | 0 main/Flow/MethodMappedController.class.php | 0 main/Flow/Model.class.php | 0 main/Flow/ModelAndView.class.php | 0 main/Flow/MonolithicController.class.php | 0 main/Flow/NullController.class.php | 0 main/Flow/PrototypedEditor.class.php | 0 main/Flow/ProxyController.class.php | 0 main/Flow/SaveCommand.class.php | 0 main/Flow/TakeCommand.class.php | 0 main/Markup/Csv.class.php | 0 main/Markup/Feed/AtomChannelWorker.class.php | 0 main/Markup/Feed/AtomFeedFormat.class.php | 0 main/Markup/Feed/AtomItemWorker.class.php | 0 main/Markup/Feed/FeedChannel.class.php | 0 main/Markup/Feed/FeedChannelWorker.class.php | 0 main/Markup/Feed/FeedFormat.class.php | 0 main/Markup/Feed/FeedItem.class.php | 0 main/Markup/Feed/FeedItemContent.class.php | 0 main/Markup/Feed/FeedItemContentType.class.php | 0 main/Markup/Feed/FeedItemWorker.class.php | 0 main/Markup/Feed/FeedReader.class.php | 0 main/Markup/Feed/RssChannelWorker.class.php | 0 main/Markup/Feed/RssFeedFormat.class.php | 0 main/Markup/Feed/RssItemWorker.class.php | 0 main/Markup/Feed/YandexRssFeedFormat.class.php | 0 main/Markup/Feed/YandexRssFeedItem.class.php | 0 main/Markup/Feed/YandexRssItemWorker.class.php | 0 main/Markup/Html/Cdata.class.php | 0 main/Markup/Html/HtmlAssembler.class.php | 0 main/Markup/Html/HtmlTokenizer.class.php | 0 main/Markup/Html/SgmlEndTag.class.php | 0 main/Markup/Html/SgmlIgnoredTag.class.php | 0 main/Markup/Html/SgmlOpenTag.class.php | 0 main/Markup/Html/SgmlTag.class.php | 0 main/Markup/Html/SgmlToken.class.php | 0 main/Math/BigInteger.class.php | 0 main/Math/BigNumberFactory.class.php | 0 main/Math/FileRandomSource.class.php | 0 main/Math/GmpBigInteger.class.php | 0 main/Math/GmpBigIntegerFactory.class.php | 0 main/Math/MathUtils.class.php | 0 main/Math/MtRandomSource.class.php | 0 main/Math/RandomSource.class.php | 0 main/Math/TupleFunctor.class.php | 0 main/Messages/Interface/Message.class.php | 0 main/Messages/Interface/MessageQueue.class.php | 0 .../Interface/MessageQueueBrowser.class.php | 0 .../Interface/MessageQueueReceiver.class.php | 0 .../Messages/Interface/MessageQueueSender.class.php | 0 main/Messages/TextFileQueue.class.php | 0 main/Messages/TextFileQueueBrowser.class.php | 0 main/Messages/TextFileReceiver.class.php | 0 main/Messages/TextFileSender.class.php | 0 main/Messages/TextMessage.class.php | 0 main/Monitoring/PinbaClient.class.php | 0 main/Monitoring/PinbedMemcached.class.php | 0 main/Monitoring/PinbedPeclMemcached.class.php | 0 main/Monitoring/PinbedPgSQL.class.php | 0 main/Net/GenericUri.class.php | 0 main/Net/Http/Cookie.class.php | 0 main/Net/Http/CookieCollection.class.php | 0 main/Net/Http/CurlHttpClient.class.php | 0 main/Net/Http/CurlHttpResponse.class.php | 0 main/Net/Http/HeaderParser.class.php | 0 main/Net/Http/HeaderUtils.class.php | 0 main/Net/Http/HttpClient.class.php | 0 main/Net/Http/HttpMethod.class.php | 0 main/Net/Http/HttpResponse.class.php | 0 main/Net/Http/HttpStatus.class.php | 0 main/Net/HttpUrl.class.php | 0 main/Net/Ip/IpAddress.class.php | 0 main/Net/Ip/IpNetwork.class.php | 0 main/Net/Ip/IpRange.class.php | 0 main/Net/Ip/IpUtils.class.php | 0 main/Net/Mail/Mail.class.php | 0 main/Net/Mail/MailAddress.class.php | 0 main/Net/Mail/MailBuilder.class.php | 0 main/Net/Mail/MailEncoding.class.php | 0 main/Net/Mail/MailException.class.php | 0 main/Net/Mail/MailNotSentException.class.php | 0 main/Net/Mail/MimeMail.class.php | 0 main/Net/Mail/MimePart.class.php | 0 main/Net/Soap/DTOClass.class.php | 0 main/Net/Soap/DTOMessage.class.php | 0 main/Net/Soap/PrototypedSoapClient.class.php | 0 main/Net/Url.class.php | 0 main/Net/Urn.class.php | 0 main/OQL/Expressions/OqlInExpression.class.php | 0 main/OQL/Expressions/OqlOrderByExpression.class.php | 0 .../Expressions/OqlPrefixMinusExpression.class.php | 0 main/OQL/Expressions/OqlQueryExpression.class.php | 0 main/OQL/Expressions/OqlQueryParameter.class.php | 0 main/OQL/OQL.class.php | 0 main/OQL/Parsers/OqlGroupByParser.class.php | 0 main/OQL/Parsers/OqlHavingParser.class.php | 0 main/OQL/Parsers/OqlOrderByParser.class.php | 0 main/OQL/Parsers/OqlParser.class.php | 0 main/OQL/Parsers/OqlSelectParser.class.php | 0 .../OQL/Parsers/OqlSelectPropertiesParser.class.php | 0 main/OQL/Parsers/OqlToken.class.php | 0 main/OQL/Parsers/OqlTokenizer.class.php | 0 main/OQL/Parsers/OqlWhereParser.class.php | 0 main/OQL/Statements/OqlHavingClause.class.php | 0 main/OQL/Statements/OqlOrderByClause.class.php | 0 main/OQL/Statements/OqlProjectionClause.class.php | 0 main/OQL/Statements/OqlQuery.class.php | 0 main/OQL/Statements/OqlQueryClause.class.php | 0 .../Statements/OqlQueryExpressionClause.class.php | 0 main/OQL/Statements/OqlQueryListedClause.class.php | 0 .../Statements/OqlSelectPropertiesClause.class.php | 0 main/OQL/Statements/OqlSelectQuery.class.php | 0 main/OQL/Statements/OqlWhereClause.class.php | 0 main/OpenId/OpenIdConsumer.class.php | 0 main/OpenId/OpenIdConsumerAssociation.class.php | 0 .../OpenIdConsumerAssociationManager.class.php | 0 main/OpenId/OpenIdConsumerCancel.class.php | 0 main/OpenId/OpenIdConsumerFail.class.php | 0 main/OpenId/OpenIdConsumerPositive.class.php | 0 main/OpenId/OpenIdConsumerResult.class.php | 0 main/OpenId/OpenIdConsumerSetupRequired.class.php | 0 main/OpenId/OpenIdCredentials.class.php | 0 main/OpenId/OpenIdException.class.php | 0 main/OpenId/OpenIdExtension.class.php | 0 .../OpenIdExtensionAttributeExchange.class.php | 0 main/OpenId/OpenIdExtensionSreg.class.php | 0 main/SPL/AbstractList.class.php | 0 main/SPL/IndexedList.class.php | 0 main/SPL/PlainList.class.php | 0 main/SPL/SimplifiedArrayAccess.class.php | 0 main/UI/View/CleanRedirectView.class.php | 0 main/UI/View/DebugPhpView.class.php | 0 main/UI/View/EmptyGifView.class.php | 0 main/UI/View/EmptyView.class.php | 0 main/UI/View/HttpErrorView.class.php | 0 main/UI/View/JsonView.class.php | 0 main/UI/View/MultiPrefixPhpViewResolver.class.php | 0 main/UI/View/PartViewer.class.php | 0 main/UI/View/PhpViewResolver.class.php | 0 main/UI/View/RedirectToView.class.php | 0 main/UI/View/RedirectView.class.php | 0 main/UI/View/SimplePhpView.class.php | 0 main/UI/View/View.class.php | 0 main/UI/View/ViewResolver.class.php | 0 main/UnifiedContainer/ManyToManyLinked.class.php | 0 .../UnifiedContainer/ManyToManyLinkedFull.class.php | 0 .../UnifiedContainer/ManyToManyLinkedLazy.class.php | 0 .../ManyToManyLinkedWorker.class.php | 0 main/UnifiedContainer/OneToManyLinked.class.php | 0 main/UnifiedContainer/OneToManyLinkedFull.class.php | 0 main/UnifiedContainer/OneToManyLinkedLazy.class.php | 0 .../OneToManyLinkedWorker.class.php | 0 main/UnifiedContainer/UnifiedContainer.class.php | 0 .../UnifiedContainerWorker.class.php | 0 main/Utils/AMQP/AMQP.class.php | 0 main/Utils/AMQP/AMQPBaseChannel.class.php | 0 main/Utils/AMQP/AMQPBaseConfig.class.php | 0 main/Utils/AMQP/AMQPBaseMessage.class.php | 0 main/Utils/AMQP/AMQPBitmaskResolver.class.php | 0 main/Utils/AMQP/AMQPChannelInterface.class.php | 0 main/Utils/AMQP/AMQPConsumer.class.php | 0 main/Utils/AMQP/AMQPCredentials.class.php | 0 main/Utils/AMQP/AMQPDefaultConsumer.class.php | 0 main/Utils/AMQP/AMQPExchangeConfig.class.php | 0 main/Utils/AMQP/AMQPExchangeType.class.php | 0 main/Utils/AMQP/AMQPIncomingMessage.class.php | 0 main/Utils/AMQP/AMQPOutgoingMessage.class.php | 0 main/Utils/AMQP/AMQPPool.class.php | 0 main/Utils/AMQP/AMQPQueueConfig.class.php | 0 main/Utils/AMQP/AMQPQueueConsumer.class.php | 0 .../AMQPServerConnectionException.class.php | 0 .../AMQP/Exceptions/AMQPServerException.class.php | 0 main/Utils/AMQP/Pecl/AMQPPecl.class.php | 0 main/Utils/AMQP/Pecl/AMQPPeclBaseBitmask.class.php | 0 main/Utils/AMQP/Pecl/AMQPPeclChannel.class.php | 0 .../AMQP/Pecl/AMQPPeclExchangeBitmask.class.php | 0 .../Pecl/AMQPPeclOutgoingMessageBitmask.class.php | 0 main/Utils/AMQP/Pecl/AMQPPeclQueueBitmask.class.php | 0 main/Utils/Archivers/ArchiverException.class.php | 0 main/Utils/Archivers/FileArchive.class.php | 0 main/Utils/Archivers/InfoZipArchive.class.php | 0 main/Utils/Archivers/TarArchive.class.php | 0 main/Utils/ArrayUtils.class.php | 0 main/Utils/ClassUtils.class.php | 0 main/Utils/CommandLine/ArgumentParser.class.php | 0 .../CommandLine/FormToArgumentsConverter.class.php | 0 main/Utils/CommonDoctypeDeclaration.class.php | 0 main/Utils/ContentTypeHeader.class.php | 0 main/Utils/CustomizableDaoSynchronizer.class.php | 0 main/Utils/CyrillicPairs.class.php | 0 main/Utils/DaoIterator.class.php | 0 main/Utils/DaoMoveHelper.class.php | 0 main/Utils/DaoSynchronizer.class.php | 0 main/Utils/DaoUtils.class.php | 0 main/Utils/DateUtils.class.php | 0 main/Utils/DebugUtils.class.php | 0 main/Utils/DoctypeDeclaration.class.php | 0 main/Utils/FileUtils.class.php | 0 main/Utils/FullTextUtils.class.php | 0 main/Utils/IO/BufferedInputStream.class.php | 0 main/Utils/IO/BufferedReader.class.php | 0 main/Utils/IO/FileInputStream.class.php | 0 main/Utils/IO/FileOutputStream.class.php | 0 main/Utils/IO/FileReader.class.php | 0 main/Utils/IO/InputStream.class.php | 0 main/Utils/IO/OutputStream.class.php | 0 main/Utils/IO/Reader.class.php | 0 main/Utils/IO/Socket.class.php | 0 main/Utils/IO/SocketInputStream.class.php | 0 main/Utils/IO/SocketOutputStream.class.php | 0 main/Utils/IO/StringInputStream.class.php | 0 main/Utils/IO/StringReader.class.php | 0 main/Utils/Logging/BaseLogger.class.php | 0 main/Utils/Logging/LogLevel.class.php | 0 main/Utils/Logging/LogRecord.class.php | 0 main/Utils/Logging/StreamLogger.class.php | 0 main/Utils/LogicUtils.class.php | 0 main/Utils/Mobile/MobileRequestDetector.class.php | 0 main/Utils/Mobile/MobileUtils.class.php | 0 main/Utils/Routers/Router.class.php | 0 main/Utils/Routers/RouterBaseRule.class.php | 0 main/Utils/Routers/RouterChainRule.class.php | 0 main/Utils/Routers/RouterException.class.php | 0 main/Utils/Routers/RouterHostnameRule.class.php | 0 main/Utils/Routers/RouterRegexpRule.class.php | 0 main/Utils/Routers/RouterRewrite.class.php | 0 main/Utils/Routers/RouterRule.class.php | 0 main/Utils/Routers/RouterStaticRule.class.php | 0 main/Utils/Routers/RouterTransparentRule.class.php | 0 main/Utils/Routers/RouterUrlHelper.class.php | 0 main/Utils/RussianTextUtils.class.php | 0 main/Utils/SortHelper.class.php | 0 main/Utils/SynchronizableObject.class.php | 0 main/Utils/TextUtils.class.php | 0 main/Utils/TidyValidator.class.php | 0 main/Utils/TuringTest/BackgroundDrawer.class.php | 0 .../Utils/TuringTest/CellBackgroundDrawer.class.php | 0 .../TuringTest/CircleBackgroundDrawer.class.php | 0 main/Utils/TuringTest/CodeGenerator.class.php | 0 main/Utils/TuringTest/Color.class.php | 0 main/Utils/TuringTest/ColorArray.class.php | 0 main/Utils/TuringTest/CurvedStringDrawer.class.php | 0 main/Utils/TuringTest/Drawer.class.php | 0 main/Utils/TuringTest/ErrorDrawer.class.php | 0 .../Utils/TuringTest/InclinedStringDrawer.class.php | 0 main/Utils/TuringTest/LinearStringDrawer.class.php | 0 .../RandomLinesBackgroundDrawer.class.php | 0 main/Utils/TuringTest/TextDrawer.class.php | 0 main/Utils/TuringTest/TuringImage.class.php | 0 .../TuringTest/WavesBackgroundDrawer.class.php | 0 main/Utils/TypesUtils.class.php | 0 main/Utils/WebMoneyUtils.class.php | 0 main/Utils/XmlRpcClient.class.php | 0 meta/builders/AutoClassBuilder.class.php | 0 meta/builders/AutoDaoBuilder.class.php | 0 meta/builders/AutoProtoClassBuilder.class.php | 0 meta/builders/BaseBuilder.class.php | 0 meta/builders/BusinessClassBuilder.class.php | 0 meta/builders/ContainerClassBuilder.class.php | 0 meta/builders/DaoBuilder.class.php | 0 meta/builders/DictionaryDaoBuilder.class.php | 0 meta/builders/EnumerationClassBuilder.class.php | 0 meta/builders/OnceBuilder.class.php | 0 meta/builders/ProtoClassBuilder.class.php | 0 meta/builders/SchemaBuilder.class.php | 0 meta/classes/ColoredTextOutput.class.php | 0 meta/classes/ConsoleMode.class.php | 0 meta/classes/Format.class.php | 0 meta/classes/MetaClass.class.php | 0 meta/classes/MetaClassProperty.class.php | 0 meta/classes/MetaClassType.class.php | 0 meta/classes/MetaConfiguration.class.php | 0 meta/classes/MetaOutput.class.php | 0 meta/classes/MetaRelation.class.php | 0 meta/classes/TextOutput.class.php | 0 meta/dtd/meta.dtd | 0 meta/internal.xml | 0 meta/patterns/AbstractClassPattern.class.php | 0 meta/patterns/BasePattern.class.php | 0 meta/patterns/DictionaryClassPattern.class.php | 0 meta/patterns/EnumerationClassPattern.class.php | 0 meta/patterns/GenerationPattern.class.php | 0 meta/patterns/InternalClassPattern.class.php | 0 meta/patterns/SpookedClassPattern.class.php | 0 meta/patterns/SpookedEnumerationPattern.class.php | 0 meta/patterns/StraightMappingPattern.class.php | 0 meta/patterns/ValueObjectPattern.class.php | 0 meta/types/BasePropertyType.class.php | 0 meta/types/BigIntegerType.class.php | 0 meta/types/BinaryType.class.php | 0 meta/types/BooleanType.class.php | 0 meta/types/DateRangeType.class.php | 0 meta/types/DateType.class.php | 0 meta/types/DoubleType.class.php | 0 meta/types/FixedLengthStringType.class.php | 0 meta/types/FloatType.class.php | 0 meta/types/HstoreType.class.php | 0 meta/types/HttpUrlType.class.php | 0 meta/types/InetType.class.php | 0 meta/types/IntegerType.class.php | 0 meta/types/InternalType.class.php | 0 meta/types/IpAddressType.class.php | 0 meta/types/IpRangeType.class.php | 0 meta/types/NumericType.class.php | 0 meta/types/ObjectType.class.php | 0 meta/types/RangeType.class.php | 0 meta/types/SmallIntegerType.class.php | 0 meta/types/StringType.class.php | 0 meta/types/TimeType.class.php | 0 meta/types/TimestampRangeType.class.php | 0 meta/types/TimestampType.class.php | 0 meta/types/UnsignedBigIntegerType.class.php | 0 meta/types/UnsignedIntegerType.class.php | 0 meta/types/UnsignedSmallIntegerType.class.php | 0 misc/Autoloader.inc.php | 0 misc/BaseException.inc.php | 0 test/AllTests.php | 0 test/config.inc.php.tpl | 0 test/core/AggregateCacheTest.class.php | 0 test/core/AssertTest.class.php | 0 test/core/BaseCachesTest.class.php | 0 test/core/CalendarDayTest.class.php | 0 test/core/DateRangeTest.class.php | 0 test/core/DateTest.class.php | 0 test/core/DeleteQueryTest.class.php | 0 test/core/FiltersTest.class.php | 0 test/core/FormPrimitivesDateTest.class.php | 0 test/core/FormTest.class.php | 0 test/core/IntervalUnitTest.class.php | 0 test/core/Ip4ContainsExpressionTest.class.php | 0 test/core/LockerTest.class.php | 0 test/core/LogicTest.class.php | 0 test/core/PrimitiveAliasTest.class.php | 0 test/core/PrimitiveClassTest.class.php | 0 test/core/PrimitiveDateRangeTest.class.php | 0 test/core/PrimitiveEnumerationTest.class.php | 0 test/core/PrimitiveHstoreTest.class.php | 0 test/core/PrimitiveIdentifierTest.class.php | 0 test/core/PrimitiveInetTest.class.php | 0 test/core/PrimitiveIpTest.class.php | 0 test/core/PrimitiveNumberTest.class.php | 0 test/core/PrimitiveStringTest.class.php | 0 test/core/PrimitiveTimeTest.class.php | 0 test/core/PrimitiveTimestampTest.class.php | 0 test/core/SingletonTest.class.php | 0 test/core/TimestampTest.class.php | 0 test/core/TruncateQueryTest.class.php | 0 test/core/UnionTest.class.php | 0 test/main/Base62UtilsTest.class.php | 0 test/main/ClassUtilsTest.class.php | 0 test/main/ComparatorTest.class.php | 0 test/main/CriteriaTest.class.php | 0 test/main/CrypterTest.class.php | 0 test/main/CryptoTest.class.php | 0 test/main/CsvTest.class.php | 0 test/main/DateUtilsTest.class.php | 0 test/main/EntityProtoConvertersTest.class.php | 0 test/main/EnumerationTest.class.php | 0 test/main/FeedReaderTest.class.php | 0 test/main/FloatRangeTest.class.php | 0 test/main/GenericUriTest.class.php | 0 test/main/GoogleChartTest.class.php | 0 test/main/HeaderParserTest.class.php | 0 test/main/HttpUtilsTest.class.php | 0 test/main/Ip/IpAddressTest.class.php | 0 test/main/Ip/IpBaseRangeTest.class.php | 0 test/main/Ip/IpNetworkTest.class.php | 0 test/main/Ip/IpUtilsTest.class.php | 0 test/main/JsonViewTest.class.php | 0 test/main/MathTest.class.php | 0 test/main/MathUtilsTest.class.php | 0 test/main/MessagesTest.class.php | 0 test/main/MimeMailTest.class.php | 0 test/main/Net/CookieTest.class.php | 0 test/main/Net/MailTest.class.php | 0 test/main/OpenIdTest.class.php | 0 test/main/OqlSelectClauseTest.class.php | 0 test/main/OqlSelectTest.class.php | 0 test/main/OqlTokenizerTest.class.php | 0 test/main/OsqlDeleteTest.class.php | 0 test/main/OsqlInsertTest.class.php | 0 test/main/OsqlReturningTest.class.php | 0 test/main/OsqlSelectTest.class.php | 0 test/main/PostgresDialectTest.class.php | 0 test/main/RangeTest.class.php | 0 test/main/TextUtilsTest.class.php | 0 test/main/Utils/AMQP/AMQPPeclTest.class.php | 0 test/main/Utils/ArrayUtilsTest.class.php | 0 test/main/Utils/FileUtilsTest.class.php | 0 .../main/Utils/Routers/RouterBaseRuleTest.class.php | 0 .../Utils/Routers/RouterChainRuleTest.class.php | 0 .../Utils/Routers/RouterHostnameRuleTest.class.php | 0 .../Utils/Routers/RouterRegexpRuleTest.class.php | 0 test/main/Utils/Routers/RouterRewriteTest.class.php | 0 .../Utils/Routers/RouterStaticRuleTest.class.php | 0 .../Routers/RouterTransparentRuleTest.class.php | 0 test/main/Utils/SocketTest.class.php | 0 test/main/Utils/TypesUtilsTest.class.php | 0 test/main/Utils/WebMoneyUtilsTest.class.php | 0 test/main/ViewTest.class.php | 0 test/main/data/directory/contents | 0 test/main/data/directory/inner/textField | 0 test/main/data/directory/textField | 0 test/main/data/feedReader/atom_v1_0.xml | 0 test/main/data/feedReader/news.xml | 0 test/main/data/feedReader/yandex_rss.xml | 0 test/main/data/mimeMail/encodedBody.txt | 0 test/main/data/mimeMail/headers.txt | 0 test/main/data/mimeMail/message.html | 0 test/main/data/mimeMail/picture.jpg | Bin test/main/data/unicode/utf16.txt | Bin test/main/data/unicode/utf16be.txt | Bin test/main/data/unicode/utf16le.txt | Bin test/main/data/unicode/utf8.txt | 0 test/main/data/urls/.._.._.._.._g.dump | 0 test/main/data/urls/.dump | 0 test/main/data/urls/parser.dump | 0 test/main/data/views/testPartView.tpl.html | 0 test/main/data/views/testView.tpl.html | 0 test/main/data/views/testViewToString.tpl.html | 0 test/meta/config.inc.php | 0 test/meta/config.meta.xml | 0 test/misc/DAOTest.class.php | 0 test/misc/DBTestPool.class.php | 0 test/misc/ServerVarUtils.class.php | 0 test/misc/TestCase.class.php | 0 test/misc/TestTables.class.php | 0 882 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 core/Base/Aliased.class.php mode change 100644 => 100755 core/Base/Assert.class.php mode change 100644 => 100755 core/Base/Date.class.php mode change 100644 => 100755 core/Base/Enumeration.class.php mode change 100644 => 100755 core/Base/Identifiable.class.php mode change 100644 => 100755 core/Base/IdentifiableObject.class.php mode change 100644 => 100755 core/Base/Identifier.class.php mode change 100644 => 100755 core/Base/Instantiatable.class.php mode change 100644 => 100755 core/Base/IntervalUnit.class.php mode change 100644 => 100755 core/Base/Named.class.php mode change 100644 => 100755 core/Base/NamedObject.class.php mode change 100644 => 100755 core/Base/PriorityQueue.class.php mode change 100644 => 100755 core/Base/Prototyped.class.php mode change 100644 => 100755 core/Base/Session.class.php mode change 100644 => 100755 core/Base/Singleton.class.php mode change 100644 => 100755 core/Base/StaticFactory.class.php mode change 100644 => 100755 core/Base/Stringable.class.php mode change 100644 => 100755 core/Base/Ternary.class.php mode change 100644 => 100755 core/Base/Time.class.php mode change 100644 => 100755 core/Base/Timestamp.class.php mode change 100644 => 100755 core/Cache/AggregateCache.class.php mode change 100644 => 100755 core/Cache/BaseAggregateCache.class.php mode change 100644 => 100755 core/Cache/BaseLocker.class.php mode change 100644 => 100755 core/Cache/Cache.class.php mode change 100644 => 100755 core/Cache/CachePeer.class.php mode change 100644 => 100755 core/Cache/CyclicAggregateCache.class.php mode change 100644 => 100755 core/Cache/DebugCachePeer.class.php mode change 100644 => 100755 core/Cache/DirectoryLocker.class.php mode change 100644 => 100755 core/Cache/FileLocker.class.php mode change 100644 => 100755 core/Cache/Memcached.class.php mode change 100644 => 100755 core/Cache/MemcachedLocker.class.php mode change 100644 => 100755 core/Cache/PeclMemcached.class.php mode change 100644 => 100755 core/Cache/ReadOnlyPeer.class.php mode change 100644 => 100755 core/Cache/RubberFileSystem.class.php mode change 100644 => 100755 core/Cache/RuntimeMemory.class.php mode change 100644 => 100755 core/Cache/SelectivePeer.class.php mode change 100644 => 100755 core/Cache/SemaphorePool.class.php mode change 100644 => 100755 core/Cache/SharedMemory.class.php mode change 100644 => 100755 core/Cache/SimpleAggregateCache.class.php mode change 100644 => 100755 core/Cache/SystemFiveLocker.class.php mode change 100644 => 100755 core/Cache/WatermarkedPeer.class.php mode change 100644 => 100755 core/Cache/eAcceleratorLocker.class.php mode change 100644 => 100755 core/DB/DB.class.php mode change 100644 => 100755 core/DB/DBPool.class.php mode change 100644 => 100755 core/DB/Dialect.class.php mode change 100644 => 100755 core/DB/ImaginaryDialect.class.php mode change 100644 => 100755 core/DB/LiteDialect.class.php mode change 100644 => 100755 core/DB/MyDialect.class.php mode change 100644 => 100755 core/DB/MyImprovedDialect.class.php mode change 100644 => 100755 core/DB/MySQL.class.php mode change 100644 => 100755 core/DB/MySQLim.class.php mode change 100644 => 100755 core/DB/PgSQL.class.php mode change 100644 => 100755 core/DB/PostgresDialect.class.php mode change 100644 => 100755 core/DB/PostgresError.class.php mode change 100644 => 100755 core/DB/Queue.class.php mode change 100644 => 100755 core/DB/SQLite.class.php mode change 100644 => 100755 core/DB/Sequenceless.class.php mode change 100644 => 100755 core/DB/Transaction/AccessMode.class.php mode change 100644 => 100755 core/DB/Transaction/BaseTransaction.class.php mode change 100644 => 100755 core/DB/Transaction/DBTransaction.class.php mode change 100644 => 100755 core/DB/Transaction/FakeTransaction.class.php mode change 100644 => 100755 core/DB/Transaction/IsolationLevel.class.php mode change 100644 => 100755 core/DB/Transaction/Transaction.class.php mode change 100644 => 100755 core/DB/Transaction/TransactionQueue.class.php mode change 100644 => 100755 core/Exceptions/BadRequestException.class.php mode change 100644 => 100755 core/Exceptions/BaseException.class.php mode change 100644 => 100755 core/Exceptions/BusinessLogicException.class.php mode change 100644 => 100755 core/Exceptions/CachedObjectNotFoundException.class.php mode change 100644 => 100755 core/Exceptions/ClassNotFoundException.class.php mode change 100644 => 100755 core/Exceptions/DatabaseException.class.php mode change 100644 => 100755 core/Exceptions/DuplicateObjectException.class.php mode change 100644 => 100755 core/Exceptions/FileNotFoundException.class.php mode change 100644 => 100755 core/Exceptions/IOException.class.php mode change 100644 => 100755 core/Exceptions/IOTimedOutException.class.php mode change 100644 => 100755 core/Exceptions/MissingElementException.class.php mode change 100644 => 100755 core/Exceptions/NetworkException.class.php mode change 100644 => 100755 core/Exceptions/ObjectNotFoundException.class.php mode change 100644 => 100755 core/Exceptions/PostgresDatabaseException.class.php mode change 100644 => 100755 core/Exceptions/SecurityException.class.php mode change 100644 => 100755 core/Exceptions/SoapFault.class.php mode change 100644 => 100755 core/Exceptions/SyntaxErrorException.class.php mode change 100644 => 100755 core/Exceptions/TooManyRowsException.class.php mode change 100644 => 100755 core/Exceptions/UnimplementedFeatureException.class.php mode change 100644 => 100755 core/Exceptions/UnsupportedMethodException.class.php mode change 100644 => 100755 core/Exceptions/WrongArgumentException.class.php mode change 100644 => 100755 core/Exceptions/WrongStateException.class.php mode change 100644 => 100755 core/Form/Filter.class.php mode change 100644 => 100755 core/Form/Filters/BaseFilter.class.php mode change 100644 => 100755 core/Form/Filters/CallbackFilter.class.php mode change 100644 => 100755 core/Form/Filters/CompressWhitespaceFilter.class.php mode change 100644 => 100755 core/Form/Filters/CropFilter.class.php mode change 100644 => 100755 core/Form/Filters/DateRangeDisplayFilter.class.php mode change 100644 => 100755 core/Form/Filters/FilterChain.class.php mode change 100644 => 100755 core/Form/Filters/Filtrator.class.php mode change 100644 => 100755 core/Form/Filters/HashFilter.class.php mode change 100644 => 100755 core/Form/Filters/HtmlSpecialCharsFilter.class.php mode change 100644 => 100755 core/Form/Filters/JsonDecoderFilter.class.php mode change 100644 => 100755 core/Form/Filters/JsonEncoderFilter.class.php mode change 100644 => 100755 core/Form/Filters/LowerCaseFilter.class.php mode change 100644 => 100755 core/Form/Filters/NewLinesToBreaks.class.php mode change 100644 => 100755 core/Form/Filters/NormalizeUrlFilter.class.php mode change 100644 => 100755 core/Form/Filters/PCREFilter.class.php mode change 100644 => 100755 core/Form/Filters/Paragraphizer.class.php mode change 100644 => 100755 core/Form/Filters/RemoveNewlineFilter.class.php mode change 100644 => 100755 core/Form/Filters/RussianTypograph.class.php mode change 100644 => 100755 core/Form/Filters/SafeUtf8Filter.class.php mode change 100644 => 100755 core/Form/Filters/StringReplaceFilter.class.php mode change 100644 => 100755 core/Form/Filters/StripTagsFilter.class.php mode change 100644 => 100755 core/Form/Filters/TrimFilter.class.php mode change 100644 => 100755 core/Form/Filters/UnTypographizer.class.php mode change 100644 => 100755 core/Form/Filters/UnixToUnixDecode.class.php mode change 100644 => 100755 core/Form/Filters/UnixToUnixEncode.class.php mode change 100644 => 100755 core/Form/Filters/UnserializeFilter.class.php mode change 100644 => 100755 core/Form/Filters/UpperCaseFilter.class.php mode change 100644 => 100755 core/Form/Filters/UrlDecodeFilter.class.php mode change 100644 => 100755 core/Form/Filters/UrlEncodeFilter.class.php mode change 100644 => 100755 core/Form/Filters/Utf16ConverterFilter.class.php mode change 100644 => 100755 core/Form/Filters/WordSplitterFilter.class.php mode change 100644 => 100755 core/Form/Form.class.php mode change 100644 => 100755 core/Form/FormField.class.php mode change 100644 => 100755 core/Form/FormUtils.class.php mode change 100644 => 100755 core/Form/MappedForm.class.php mode change 100644 => 100755 core/Form/PlainForm.class.php mode change 100644 => 100755 core/Form/Primitive.class.php mode change 100644 => 100755 core/Form/Primitives/BaseObjectPrimitive.class.php mode change 100644 => 100755 core/Form/Primitives/BasePrimitive.class.php mode change 100644 => 100755 core/Form/Primitives/ComplexPrimitive.class.php mode change 100644 => 100755 core/Form/Primitives/DateRangeList.class.php mode change 100644 => 100755 core/Form/Primitives/ExplodedPrimitive.class.php mode change 100644 => 100755 core/Form/Primitives/FiltrablePrimitive.class.php mode change 100644 => 100755 core/Form/Primitives/IdentifiablePrimitive.class.php mode change 100644 => 100755 core/Form/Primitives/ListedPrimitive.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveAlias.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveAnyType.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveArray.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveBinary.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveBoolean.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveClass.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveDate.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveDateRange.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveEnumeration.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveEnumerationByValue.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveEnumerationList.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveFile.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveFloat.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveForm.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveFormsList.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveHstore.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveHttpUrl.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveIdentifier.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveIdentifierList.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveImage.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveInet.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveInteger.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveIntegerIdentifier.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveIpAddress.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveIpRange.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveList.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveMultiList.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveNoValue.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveNumber.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitivePlainList.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitivePolymorphicIdentifier.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveRange.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveScalarIdentifier.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveString.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveTernary.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveTime.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveTimestamp.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveTimestampRange.class.php mode change 100644 => 100755 core/Form/Primitives/RangedPrimitive.class.php mode change 100644 => 100755 core/Form/Primitives/TimeList.class.php mode change 100644 => 100755 core/Form/RegulatedForm.class.php mode change 100644 => 100755 core/Logic/BinaryExpression.class.php mode change 100644 => 100755 core/Logic/CallbackLogicalObject.class.php mode change 100644 => 100755 core/Logic/EqualsLowerExpression.class.php mode change 100644 => 100755 core/Logic/Expression.class.php mode change 100644 => 100755 core/Logic/HstoreExpression.class.php mode change 100644 => 100755 core/Logic/InExpression.class.php mode change 100644 => 100755 core/Logic/Ip4ContainsExpression.class.php mode change 100644 => 100755 core/Logic/LTreeExpression.class.php mode change 100644 => 100755 core/Logic/LogicalBetween.class.php mode change 100644 => 100755 core/Logic/LogicalChain.class.php mode change 100644 => 100755 core/Logic/LogicalObject.class.php mode change 100644 => 100755 core/Logic/MappableObject.class.php mode change 100644 => 100755 core/Logic/PostfixUnaryExpression.class.php mode change 100644 => 100755 core/Logic/PrefixUnaryExpression.class.php mode change 100644 => 100755 core/OSQL/Castable.class.php mode change 100644 => 100755 core/OSQL/CombineQuery.class.php mode change 100644 => 100755 core/OSQL/CreateTableQuery.class.php mode change 100644 => 100755 core/OSQL/DBBinary.class.php mode change 100644 => 100755 core/OSQL/DBColumn.class.php mode change 100644 => 100755 core/OSQL/DBField.class.php mode change 100644 => 100755 core/OSQL/DBRaw.class.php mode change 100644 => 100755 core/OSQL/DBSchema.class.php mode change 100644 => 100755 core/OSQL/DBTable.class.php mode change 100644 => 100755 core/OSQL/DBValue.class.php mode change 100644 => 100755 core/OSQL/DataType.class.php mode change 100644 => 100755 core/OSQL/DatePart.class.php mode change 100644 => 100755 core/OSQL/DeleteQuery.class.php mode change 100644 => 100755 core/OSQL/DialectString.class.php mode change 100644 => 100755 core/OSQL/DropTableQuery.class.php mode change 100644 => 100755 core/OSQL/ExtractPart.class.php mode change 100644 => 100755 core/OSQL/FieldGroup.class.php mode change 100644 => 100755 core/OSQL/FieldTable.class.php mode change 100644 => 100755 core/OSQL/ForeignChangeAction.class.php mode change 100644 => 100755 core/OSQL/FromTable.class.php mode change 100644 => 100755 core/OSQL/FullText.class.php mode change 100644 => 100755 core/OSQL/FullTextRank.class.php mode change 100644 => 100755 core/OSQL/FullTextSearch.class.php mode change 100644 => 100755 core/OSQL/GroupBy.class.php mode change 100644 => 100755 core/OSQL/InsertOrUpdateQuery.class.php mode change 100644 => 100755 core/OSQL/InsertQuery.class.php mode change 100644 => 100755 core/OSQL/JoinCapableQuery.class.php mode change 100644 => 100755 core/OSQL/Joiner.class.php mode change 100644 => 100755 core/OSQL/OSQL.class.php mode change 100644 => 100755 core/OSQL/OrderBy.class.php mode change 100644 => 100755 core/OSQL/OrderChain.class.php mode change 100644 => 100755 core/OSQL/Query.class.php mode change 100644 => 100755 core/OSQL/QueryChain.class.php mode change 100644 => 100755 core/OSQL/QueryCombination.class.php mode change 100644 => 100755 core/OSQL/QueryIdentification.class.php mode change 100644 => 100755 core/OSQL/QueryResult.class.php mode change 100644 => 100755 core/OSQL/QuerySkeleton.class.php mode change 100644 => 100755 core/OSQL/SQLArray.class.php mode change 100644 => 100755 core/OSQL/SQLBaseJoin.class.php mode change 100644 => 100755 core/OSQL/SQLChain.class.php mode change 100644 => 100755 core/OSQL/SQLFunction.class.php mode change 100644 => 100755 core/OSQL/SQLJoin.class.php mode change 100644 => 100755 core/OSQL/SQLLeftJoin.class.php mode change 100644 => 100755 core/OSQL/SQLRightJoin.class.php mode change 100644 => 100755 core/OSQL/SQLTableName.class.php mode change 100644 => 100755 core/OSQL/SelectField.class.php mode change 100644 => 100755 core/OSQL/SelectQuery.class.php mode change 100644 => 100755 core/OSQL/TimeIntervalsGenerator.class.php mode change 100644 => 100755 core/OSQL/TruncateQuery.class.php mode change 100644 => 100755 core/OSQL/UpdateQuery.class.php mode change 100644 => 100755 doc/AUTHORS mode change 100644 => 100755 doc/ChangeLog mode change 100644 => 100755 doc/CodingStyle mode change 100644 => 100755 doc/Doxyfile mode change 100644 => 100755 doc/FAQ mode change 100644 => 100755 doc/FEATURES mode change 100644 => 100755 doc/LICENSE mode change 100644 => 100755 doc/OQL-BNF mode change 100644 => 100755 doc/README mode change 100644 => 100755 doc/ROUTERS mode change 100644 => 100755 doc/THANKS mode change 100644 => 100755 doc/TODO mode change 100644 => 100755 doc/examples/cacheSettings.php mode change 100644 => 100755 doc/examples/index.php mode change 100644 => 100755 doc/examples/singleton.php mode change 100644 => 100755 doc/examples/union.php mode change 100644 => 100755 doc/onphp.doxy.php mode change 100644 => 100755 doc/parts/doxyHead.html mode change 100644 => 100755 doc/parts/doxyHeel.html mode change 100644 => 100755 doc/project.skel/config.inc.php.tpl mode change 100644 => 100755 doc/project.skel/config.xml mode change 100644 => 100755 doc/project.skel/db/schema.sql mode change 100644 => 100755 doc/project.skel/src/admin/controllers/login.class.php mode change 100644 => 100755 doc/project.skel/src/admin/controllers/main.class.php mode change 100644 => 100755 doc/project.skel/src/admin/htdocs/index.php mode change 100644 => 100755 doc/project.skel/src/admin/templates/login.tpl.html mode change 100644 => 100755 doc/project.skel/src/admin/templates/main.tpl.html mode change 100644 => 100755 doc/project.skel/src/classes/Auto/Business/AutoAdministrator.class.php mode change 100644 => 100755 doc/project.skel/src/classes/Auto/DAOs/AutoAdministratorDAO.class.php mode change 100644 => 100755 doc/project.skel/src/classes/Auto/Proto/AutoProtoAdministrator.class.php mode change 100644 => 100755 doc/project.skel/src/classes/Auto/schema.php mode change 100644 => 100755 doc/project.skel/src/classes/Business/Administrator.class.php mode change 100644 => 100755 doc/project.skel/src/classes/DAOs/AdministratorDAO.class.php mode change 100644 => 100755 doc/project.skel/src/classes/Flow/AuthorizationFilter.class.php mode change 100644 => 100755 doc/project.skel/src/classes/Proto/ProtoAdministrator.class.php mode change 100644 => 100755 doc/project.skel/src/user/controllers/main.class.php mode change 100644 => 100755 doc/project.skel/src/user/htdocs/index.php mode change 100644 => 100755 doc/project.skel/src/user/templates/main.tpl.html mode change 100644 => 100755 global.inc.php.tpl mode change 100644 => 100755 main/Application/ApplicationUrl.class.php mode change 100644 => 100755 main/Application/ScopeNavigationSchema.class.php mode change 100644 => 100755 main/Application/SimpleApplicationUrl.class.php mode change 100644 => 100755 main/Base/AbstractCollection.class.php mode change 100644 => 100755 main/Base/AbstractProtoClass.class.php mode change 100644 => 100755 main/Base/BaseRange.class.php mode change 100644 => 100755 main/Base/CalendarDay.class.php mode change 100644 => 100755 main/Base/CalendarMonthWeekly.class.php mode change 100644 => 100755 main/Base/CalendarWeek.class.php mode change 100644 => 100755 main/Base/CallChain.class.php mode change 100644 => 100755 main/Base/Collection.class.php mode change 100644 => 100755 main/Base/CollectionItem.class.php mode change 100644 => 100755 main/Base/Comparator.class.php mode change 100644 => 100755 main/Base/DateObjectComparator.class.php mode change 100644 => 100755 main/Base/DateRange.class.php mode change 100644 => 100755 main/Base/FloatRange.class.php mode change 100644 => 100755 main/Base/Hstore.class.php mode change 100644 => 100755 main/Base/IdentifiableTree.class.php mode change 100644 => 100755 main/Base/ImageType.class.php mode change 100644 => 100755 main/Base/ImmutableObjectComparator.class.php mode change 100644 => 100755 main/Base/InnerMetaProperty.class.php mode change 100644 => 100755 main/Base/IntegerSet.class.php mode change 100644 => 100755 main/Base/IsoCurrency.class.php mode change 100644 => 100755 main/Base/LightMetaProperty.class.php mode change 100644 => 100755 main/Base/NamedTree.class.php mode change 100644 => 100755 main/Base/Range.class.php mode change 100644 => 100755 main/Base/RequestType.class.php mode change 100644 => 100755 main/Base/SerializedObjectComparator.class.php mode change 100644 => 100755 main/Base/SingleRange.class.php mode change 100644 => 100755 main/Base/StandardComparator.class.php mode change 100644 => 100755 main/Base/TempDirectory.class.php mode change 100644 => 100755 main/Base/TempFile.class.php mode change 100644 => 100755 main/Base/TimestampRange.class.php mode change 100644 => 100755 main/Base/TransparentFile.class.php mode change 100644 => 100755 main/Charts/Google/BaseGoogleChartData.class.php mode change 100644 => 100755 main/Charts/Google/BaseGoogleChartDataEncoding.class.php mode change 100644 => 100755 main/Charts/Google/BaseGoogleChartLabelStyleType.class.php mode change 100644 => 100755 main/Charts/Google/BaseGoogleChartParameter.class.php mode change 100644 => 100755 main/Charts/Google/BaseGoogleChartStyle.class.php mode change 100644 => 100755 main/Charts/Google/ChartLabelStyle.class.php mode change 100644 => 100755 main/Charts/Google/ChartLineStyle.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChart.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartAxis.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartAxisCollection.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartAxisLabel.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartAxisType.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartColor.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartData.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartDataEncoding.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartDataRange.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartDataScaling.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartDataSet.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartDataSimpleEncoding.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartDataTextEncoding.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartGrid.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartLabel.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartLabelStyle.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartLabelStyleNumberType.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartLegend.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartLegendPositionType.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartLine.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartLineStyle.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartPiece.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartSize.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartSolidFill.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartSolidFillCollection.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartSolidFillType.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartTitle.class.php mode change 100644 => 100755 main/Charts/Google/GoogleChartType.class.php mode change 100644 => 100755 main/Charts/Google/GoogleGridedLineChart.class.php mode change 100644 => 100755 main/Charts/Google/GoogleLineChart.class.php mode change 100644 => 100755 main/Charts/Google/GoogleNormalizedLineChart.class.php mode change 100644 => 100755 main/Charts/Google/GooglePieChart.class.php mode change 100644 => 100755 main/Charts/Google/LabelStyleType.class.php mode change 100644 => 100755 main/Criteria/Criteria.class.php mode change 100644 => 100755 main/Criteria/FetchStrategy.class.php mode change 100644 => 100755 main/Criteria/Projection.class.php mode change 100644 => 100755 main/Criteria/Projections/AggregateProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/AverageNumberProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/BaseProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/ClassProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/CountProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/DistinctCountProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/GroupByClassProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/GroupByPropertyProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/HavingProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/MappableObjectProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/MaximalNumberProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/MinimalNumberProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/ObjectProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/ProjectionChain.class.php mode change 100644 => 100755 main/Criteria/Projections/PropertyProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/RowCountProjection.class.php mode change 100644 => 100755 main/Criteria/Projections/SumProjection.class.php mode change 100644 => 100755 main/Criteria/PropertyPath.class.php mode change 100644 => 100755 main/Crypto/Base62Utils.class.php mode change 100644 => 100755 main/Crypto/Crypter.class.php mode change 100644 => 100755 main/Crypto/CryptoFunctions.class.php mode change 100644 => 100755 main/Crypto/DiffieHellmanKeyPair.class.php mode change 100644 => 100755 main/Crypto/DiffieHellmanParameters.class.php mode change 100644 => 100755 main/Crypto/KeyPair.class.php mode change 100644 => 100755 main/DAOs/BaseDAO.class.php mode change 100644 => 100755 main/DAOs/DAOConnected.class.php mode change 100644 => 100755 main/DAOs/FullTextDAO.class.php mode change 100644 => 100755 main/DAOs/GenericDAO.class.php mode change 100644 => 100755 main/DAOs/Handlers/ApcSegmentHandler.class.php mode change 100644 => 100755 main/DAOs/Handlers/CacheSegmentHandler.class.php mode change 100644 => 100755 main/DAOs/Handlers/FileSystemSegmentHandler.class.php mode change 100644 => 100755 main/DAOs/Handlers/MessageSegmentHandler.class.php mode change 100644 => 100755 main/DAOs/Handlers/OptimizerSegmentHandler.class.php mode change 100644 => 100755 main/DAOs/Handlers/SegmentHandler.class.php mode change 100644 => 100755 main/DAOs/Handlers/SharedMemorySegmentHandler.class.php mode change 100644 => 100755 main/DAOs/Handlers/XCacheSegmentHandler.class.php mode change 100644 => 100755 main/DAOs/Handlers/eAcceleratorSegmentHandler.class.php mode change 100644 => 100755 main/DAOs/ProtoDAO.class.php mode change 100644 => 100755 main/DAOs/StorableDAO.class.php mode change 100644 => 100755 main/DAOs/Workers/BaseDaoWorker.class.php mode change 100644 => 100755 main/DAOs/Workers/CacheDaoWorker.class.php mode change 100644 => 100755 main/DAOs/Workers/CommonDaoWorker.class.php mode change 100644 => 100755 main/DAOs/Workers/CustomDataScopedWorker.class.php mode change 100644 => 100755 main/DAOs/Workers/DalayedDropDaoWorker.class.php mode change 100644 => 100755 main/DAOs/Workers/NullDaoWorker.class.php mode change 100644 => 100755 main/DAOs/Workers/SmartDaoWorker.class.php mode change 100644 => 100755 main/DAOs/Workers/TransparentDaoWorker.class.php mode change 100644 => 100755 main/DAOs/Workers/VoodooDaoWorker.class.php mode change 100644 => 100755 main/EntityProto/Accessors/DTOGetter.class.php mode change 100644 => 100755 main/EntityProto/Accessors/DTOSetter.class.php mode change 100644 => 100755 main/EntityProto/Accessors/DirectoryGetter.class.php mode change 100644 => 100755 main/EntityProto/Accessors/DirectoryMutator.class.php mode change 100644 => 100755 main/EntityProto/Accessors/DirectorySetter.class.php mode change 100644 => 100755 main/EntityProto/Accessors/FormExporter.class.php mode change 100644 => 100755 main/EntityProto/Accessors/FormGetter.class.php mode change 100644 => 100755 main/EntityProto/Accessors/FormHardenedSetter.class.php mode change 100644 => 100755 main/EntityProto/Accessors/FormImporter.class.php mode change 100644 => 100755 main/EntityProto/Accessors/FormMutator.class.php mode change 100644 => 100755 main/EntityProto/Accessors/FormSetter.class.php mode change 100644 => 100755 main/EntityProto/Accessors/ObjectGetter.class.php mode change 100644 => 100755 main/EntityProto/Accessors/ObjectSetter.class.php mode change 100644 => 100755 main/EntityProto/Accessors/ScopeGetter.class.php mode change 100644 => 100755 main/EntityProto/Accessors/ScopeSetter.class.php mode change 100644 => 100755 main/EntityProto/Builders/DTOBuilder.class.php mode change 100644 => 100755 main/EntityProto/Builders/DTOToFormImporter.class.php mode change 100644 => 100755 main/EntityProto/Builders/DTOToScopeConverter.class.php mode change 100644 => 100755 main/EntityProto/Builders/DirectoryBuilder.class.php mode change 100644 => 100755 main/EntityProto/Builders/DirectoryToObjectBinder.class.php mode change 100644 => 100755 main/EntityProto/Builders/FormBuilder.class.php mode change 100644 => 100755 main/EntityProto/Builders/FormToObjectConverter.class.php mode change 100644 => 100755 main/EntityProto/Builders/FormToScopeExporter.class.php mode change 100644 => 100755 main/EntityProto/Builders/ObjectBuilder.class.php mode change 100644 => 100755 main/EntityProto/Builders/ObjectToDTOConverter.class.php mode change 100644 => 100755 main/EntityProto/Builders/ObjectToDirectoryBinder.class.php mode change 100644 => 100755 main/EntityProto/Builders/ObjectToFormConverter.class.php mode change 100644 => 100755 main/EntityProto/Builders/ObjectToFormSetter.class.php mode change 100644 => 100755 main/EntityProto/Builders/ObjectToObjectCast.class.php mode change 100644 => 100755 main/EntityProto/Builders/ScopeToFormImporter.class.php mode change 100644 => 100755 main/EntityProto/DirectoryContext.class.php mode change 100644 => 100755 main/EntityProto/EntityProto.class.php mode change 100644 => 100755 main/EntityProto/PrototypedBuilder.class.php mode change 100644 => 100755 main/EntityProto/PrototypedEntity.class.php mode change 100644 => 100755 main/EntityProto/PrototypedGetter.class.php mode change 100644 => 100755 main/EntityProto/PrototypedMethodCaller.class.php mode change 100644 => 100755 main/EntityProto/PrototypedSetter.class.php mode change 100644 => 100755 main/Flow/AddCommand.class.php mode change 100644 => 100755 main/Flow/BaseEditor.class.php mode change 100644 => 100755 main/Flow/CarefulCommand.class.php mode change 100644 => 100755 main/Flow/CarefulDatabaseRunner.class.php mode change 100644 => 100755 main/Flow/CommandChain.class.php mode change 100644 => 100755 main/Flow/Controller.class.php mode change 100644 => 100755 main/Flow/ControllersCollection.class.php mode change 100644 => 100755 main/Flow/DecoratorController.class.php mode change 100644 => 100755 main/Flow/DropCommand.class.php mode change 100644 => 100755 main/Flow/EditCommand.class.php mode change 100644 => 100755 main/Flow/EditorCommand.class.php mode change 100644 => 100755 main/Flow/EditorController.class.php mode change 100644 => 100755 main/Flow/ForbiddenCommand.class.php mode change 100644 => 100755 main/Flow/HandlerMapping.class.php mode change 100644 => 100755 main/Flow/HttpRequest.class.php mode change 100644 => 100755 main/Flow/ImportCommand.class.php mode change 100644 => 100755 main/Flow/MakeCommand.class.php mode change 100644 => 100755 main/Flow/MethodMappedController.class.php mode change 100644 => 100755 main/Flow/Model.class.php mode change 100644 => 100755 main/Flow/ModelAndView.class.php mode change 100644 => 100755 main/Flow/MonolithicController.class.php mode change 100644 => 100755 main/Flow/NullController.class.php mode change 100644 => 100755 main/Flow/PrototypedEditor.class.php mode change 100644 => 100755 main/Flow/ProxyController.class.php mode change 100644 => 100755 main/Flow/SaveCommand.class.php mode change 100644 => 100755 main/Flow/TakeCommand.class.php mode change 100644 => 100755 main/Markup/Csv.class.php mode change 100644 => 100755 main/Markup/Feed/AtomChannelWorker.class.php mode change 100644 => 100755 main/Markup/Feed/AtomFeedFormat.class.php mode change 100644 => 100755 main/Markup/Feed/AtomItemWorker.class.php mode change 100644 => 100755 main/Markup/Feed/FeedChannel.class.php mode change 100644 => 100755 main/Markup/Feed/FeedChannelWorker.class.php mode change 100644 => 100755 main/Markup/Feed/FeedFormat.class.php mode change 100644 => 100755 main/Markup/Feed/FeedItem.class.php mode change 100644 => 100755 main/Markup/Feed/FeedItemContent.class.php mode change 100644 => 100755 main/Markup/Feed/FeedItemContentType.class.php mode change 100644 => 100755 main/Markup/Feed/FeedItemWorker.class.php mode change 100644 => 100755 main/Markup/Feed/FeedReader.class.php mode change 100644 => 100755 main/Markup/Feed/RssChannelWorker.class.php mode change 100644 => 100755 main/Markup/Feed/RssFeedFormat.class.php mode change 100644 => 100755 main/Markup/Feed/RssItemWorker.class.php mode change 100644 => 100755 main/Markup/Feed/YandexRssFeedFormat.class.php mode change 100644 => 100755 main/Markup/Feed/YandexRssFeedItem.class.php mode change 100644 => 100755 main/Markup/Feed/YandexRssItemWorker.class.php mode change 100644 => 100755 main/Markup/Html/Cdata.class.php mode change 100644 => 100755 main/Markup/Html/HtmlAssembler.class.php mode change 100644 => 100755 main/Markup/Html/HtmlTokenizer.class.php mode change 100644 => 100755 main/Markup/Html/SgmlEndTag.class.php mode change 100644 => 100755 main/Markup/Html/SgmlIgnoredTag.class.php mode change 100644 => 100755 main/Markup/Html/SgmlOpenTag.class.php mode change 100644 => 100755 main/Markup/Html/SgmlTag.class.php mode change 100644 => 100755 main/Markup/Html/SgmlToken.class.php mode change 100644 => 100755 main/Math/BigInteger.class.php mode change 100644 => 100755 main/Math/BigNumberFactory.class.php mode change 100644 => 100755 main/Math/FileRandomSource.class.php mode change 100644 => 100755 main/Math/GmpBigInteger.class.php mode change 100644 => 100755 main/Math/GmpBigIntegerFactory.class.php mode change 100644 => 100755 main/Math/MathUtils.class.php mode change 100644 => 100755 main/Math/MtRandomSource.class.php mode change 100644 => 100755 main/Math/RandomSource.class.php mode change 100644 => 100755 main/Math/TupleFunctor.class.php mode change 100644 => 100755 main/Messages/Interface/Message.class.php mode change 100644 => 100755 main/Messages/Interface/MessageQueue.class.php mode change 100644 => 100755 main/Messages/Interface/MessageQueueBrowser.class.php mode change 100644 => 100755 main/Messages/Interface/MessageQueueReceiver.class.php mode change 100644 => 100755 main/Messages/Interface/MessageQueueSender.class.php mode change 100644 => 100755 main/Messages/TextFileQueue.class.php mode change 100644 => 100755 main/Messages/TextFileQueueBrowser.class.php mode change 100644 => 100755 main/Messages/TextFileReceiver.class.php mode change 100644 => 100755 main/Messages/TextFileSender.class.php mode change 100644 => 100755 main/Messages/TextMessage.class.php mode change 100644 => 100755 main/Monitoring/PinbaClient.class.php mode change 100644 => 100755 main/Monitoring/PinbedMemcached.class.php mode change 100644 => 100755 main/Monitoring/PinbedPeclMemcached.class.php mode change 100644 => 100755 main/Monitoring/PinbedPgSQL.class.php mode change 100644 => 100755 main/Net/GenericUri.class.php mode change 100644 => 100755 main/Net/Http/Cookie.class.php mode change 100644 => 100755 main/Net/Http/CookieCollection.class.php mode change 100644 => 100755 main/Net/Http/CurlHttpClient.class.php mode change 100644 => 100755 main/Net/Http/CurlHttpResponse.class.php mode change 100644 => 100755 main/Net/Http/HeaderParser.class.php mode change 100644 => 100755 main/Net/Http/HeaderUtils.class.php mode change 100644 => 100755 main/Net/Http/HttpClient.class.php mode change 100644 => 100755 main/Net/Http/HttpMethod.class.php mode change 100644 => 100755 main/Net/Http/HttpResponse.class.php mode change 100644 => 100755 main/Net/Http/HttpStatus.class.php mode change 100644 => 100755 main/Net/HttpUrl.class.php mode change 100644 => 100755 main/Net/Ip/IpAddress.class.php mode change 100644 => 100755 main/Net/Ip/IpNetwork.class.php mode change 100644 => 100755 main/Net/Ip/IpRange.class.php mode change 100644 => 100755 main/Net/Ip/IpUtils.class.php mode change 100644 => 100755 main/Net/Mail/Mail.class.php mode change 100644 => 100755 main/Net/Mail/MailAddress.class.php mode change 100644 => 100755 main/Net/Mail/MailBuilder.class.php mode change 100644 => 100755 main/Net/Mail/MailEncoding.class.php mode change 100644 => 100755 main/Net/Mail/MailException.class.php mode change 100644 => 100755 main/Net/Mail/MailNotSentException.class.php mode change 100644 => 100755 main/Net/Mail/MimeMail.class.php mode change 100644 => 100755 main/Net/Mail/MimePart.class.php mode change 100644 => 100755 main/Net/Soap/DTOClass.class.php mode change 100644 => 100755 main/Net/Soap/DTOMessage.class.php mode change 100644 => 100755 main/Net/Soap/PrototypedSoapClient.class.php mode change 100644 => 100755 main/Net/Url.class.php mode change 100644 => 100755 main/Net/Urn.class.php mode change 100644 => 100755 main/OQL/Expressions/OqlInExpression.class.php mode change 100644 => 100755 main/OQL/Expressions/OqlOrderByExpression.class.php mode change 100644 => 100755 main/OQL/Expressions/OqlPrefixMinusExpression.class.php mode change 100644 => 100755 main/OQL/Expressions/OqlQueryExpression.class.php mode change 100644 => 100755 main/OQL/Expressions/OqlQueryParameter.class.php mode change 100644 => 100755 main/OQL/OQL.class.php mode change 100644 => 100755 main/OQL/Parsers/OqlGroupByParser.class.php mode change 100644 => 100755 main/OQL/Parsers/OqlHavingParser.class.php mode change 100644 => 100755 main/OQL/Parsers/OqlOrderByParser.class.php mode change 100644 => 100755 main/OQL/Parsers/OqlParser.class.php mode change 100644 => 100755 main/OQL/Parsers/OqlSelectParser.class.php mode change 100644 => 100755 main/OQL/Parsers/OqlSelectPropertiesParser.class.php mode change 100644 => 100755 main/OQL/Parsers/OqlToken.class.php mode change 100644 => 100755 main/OQL/Parsers/OqlTokenizer.class.php mode change 100644 => 100755 main/OQL/Parsers/OqlWhereParser.class.php mode change 100644 => 100755 main/OQL/Statements/OqlHavingClause.class.php mode change 100644 => 100755 main/OQL/Statements/OqlOrderByClause.class.php mode change 100644 => 100755 main/OQL/Statements/OqlProjectionClause.class.php mode change 100644 => 100755 main/OQL/Statements/OqlQuery.class.php mode change 100644 => 100755 main/OQL/Statements/OqlQueryClause.class.php mode change 100644 => 100755 main/OQL/Statements/OqlQueryExpressionClause.class.php mode change 100644 => 100755 main/OQL/Statements/OqlQueryListedClause.class.php mode change 100644 => 100755 main/OQL/Statements/OqlSelectPropertiesClause.class.php mode change 100644 => 100755 main/OQL/Statements/OqlSelectQuery.class.php mode change 100644 => 100755 main/OQL/Statements/OqlWhereClause.class.php mode change 100644 => 100755 main/OpenId/OpenIdConsumer.class.php mode change 100644 => 100755 main/OpenId/OpenIdConsumerAssociation.class.php mode change 100644 => 100755 main/OpenId/OpenIdConsumerAssociationManager.class.php mode change 100644 => 100755 main/OpenId/OpenIdConsumerCancel.class.php mode change 100644 => 100755 main/OpenId/OpenIdConsumerFail.class.php mode change 100644 => 100755 main/OpenId/OpenIdConsumerPositive.class.php mode change 100644 => 100755 main/OpenId/OpenIdConsumerResult.class.php mode change 100644 => 100755 main/OpenId/OpenIdConsumerSetupRequired.class.php mode change 100644 => 100755 main/OpenId/OpenIdCredentials.class.php mode change 100644 => 100755 main/OpenId/OpenIdException.class.php mode change 100644 => 100755 main/OpenId/OpenIdExtension.class.php mode change 100644 => 100755 main/OpenId/OpenIdExtensionAttributeExchange.class.php mode change 100644 => 100755 main/OpenId/OpenIdExtensionSreg.class.php mode change 100644 => 100755 main/SPL/AbstractList.class.php mode change 100644 => 100755 main/SPL/IndexedList.class.php mode change 100644 => 100755 main/SPL/PlainList.class.php mode change 100644 => 100755 main/SPL/SimplifiedArrayAccess.class.php mode change 100644 => 100755 main/UI/View/CleanRedirectView.class.php mode change 100644 => 100755 main/UI/View/DebugPhpView.class.php mode change 100644 => 100755 main/UI/View/EmptyGifView.class.php mode change 100644 => 100755 main/UI/View/EmptyView.class.php mode change 100644 => 100755 main/UI/View/HttpErrorView.class.php mode change 100644 => 100755 main/UI/View/JsonView.class.php mode change 100644 => 100755 main/UI/View/MultiPrefixPhpViewResolver.class.php mode change 100644 => 100755 main/UI/View/PartViewer.class.php mode change 100644 => 100755 main/UI/View/PhpViewResolver.class.php mode change 100644 => 100755 main/UI/View/RedirectToView.class.php mode change 100644 => 100755 main/UI/View/RedirectView.class.php mode change 100644 => 100755 main/UI/View/SimplePhpView.class.php mode change 100644 => 100755 main/UI/View/View.class.php mode change 100644 => 100755 main/UI/View/ViewResolver.class.php mode change 100644 => 100755 main/UnifiedContainer/ManyToManyLinked.class.php mode change 100644 => 100755 main/UnifiedContainer/ManyToManyLinkedFull.class.php mode change 100644 => 100755 main/UnifiedContainer/ManyToManyLinkedLazy.class.php mode change 100644 => 100755 main/UnifiedContainer/ManyToManyLinkedWorker.class.php mode change 100644 => 100755 main/UnifiedContainer/OneToManyLinked.class.php mode change 100644 => 100755 main/UnifiedContainer/OneToManyLinkedFull.class.php mode change 100644 => 100755 main/UnifiedContainer/OneToManyLinkedLazy.class.php mode change 100644 => 100755 main/UnifiedContainer/OneToManyLinkedWorker.class.php mode change 100644 => 100755 main/UnifiedContainer/UnifiedContainer.class.php mode change 100644 => 100755 main/UnifiedContainer/UnifiedContainerWorker.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQP.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPBaseChannel.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPBaseConfig.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPBaseMessage.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPBitmaskResolver.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPChannelInterface.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPConsumer.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPCredentials.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPDefaultConsumer.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPExchangeConfig.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPExchangeType.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPIncomingMessage.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPOutgoingMessage.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPPool.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPQueueConfig.class.php mode change 100644 => 100755 main/Utils/AMQP/AMQPQueueConsumer.class.php mode change 100644 => 100755 main/Utils/AMQP/Exceptions/AMQPServerConnectionException.class.php mode change 100644 => 100755 main/Utils/AMQP/Exceptions/AMQPServerException.class.php mode change 100644 => 100755 main/Utils/AMQP/Pecl/AMQPPecl.class.php mode change 100644 => 100755 main/Utils/AMQP/Pecl/AMQPPeclBaseBitmask.class.php mode change 100644 => 100755 main/Utils/AMQP/Pecl/AMQPPeclChannel.class.php mode change 100644 => 100755 main/Utils/AMQP/Pecl/AMQPPeclExchangeBitmask.class.php mode change 100644 => 100755 main/Utils/AMQP/Pecl/AMQPPeclOutgoingMessageBitmask.class.php mode change 100644 => 100755 main/Utils/AMQP/Pecl/AMQPPeclQueueBitmask.class.php mode change 100644 => 100755 main/Utils/Archivers/ArchiverException.class.php mode change 100644 => 100755 main/Utils/Archivers/FileArchive.class.php mode change 100644 => 100755 main/Utils/Archivers/InfoZipArchive.class.php mode change 100644 => 100755 main/Utils/Archivers/TarArchive.class.php mode change 100644 => 100755 main/Utils/ArrayUtils.class.php mode change 100644 => 100755 main/Utils/ClassUtils.class.php mode change 100644 => 100755 main/Utils/CommandLine/ArgumentParser.class.php mode change 100644 => 100755 main/Utils/CommandLine/FormToArgumentsConverter.class.php mode change 100644 => 100755 main/Utils/CommonDoctypeDeclaration.class.php mode change 100644 => 100755 main/Utils/ContentTypeHeader.class.php mode change 100644 => 100755 main/Utils/CustomizableDaoSynchronizer.class.php mode change 100644 => 100755 main/Utils/CyrillicPairs.class.php mode change 100644 => 100755 main/Utils/DaoIterator.class.php mode change 100644 => 100755 main/Utils/DaoMoveHelper.class.php mode change 100644 => 100755 main/Utils/DaoSynchronizer.class.php mode change 100644 => 100755 main/Utils/DaoUtils.class.php mode change 100644 => 100755 main/Utils/DateUtils.class.php mode change 100644 => 100755 main/Utils/DebugUtils.class.php mode change 100644 => 100755 main/Utils/DoctypeDeclaration.class.php mode change 100644 => 100755 main/Utils/FileUtils.class.php mode change 100644 => 100755 main/Utils/FullTextUtils.class.php mode change 100644 => 100755 main/Utils/IO/BufferedInputStream.class.php mode change 100644 => 100755 main/Utils/IO/BufferedReader.class.php mode change 100644 => 100755 main/Utils/IO/FileInputStream.class.php mode change 100644 => 100755 main/Utils/IO/FileOutputStream.class.php mode change 100644 => 100755 main/Utils/IO/FileReader.class.php mode change 100644 => 100755 main/Utils/IO/InputStream.class.php mode change 100644 => 100755 main/Utils/IO/OutputStream.class.php mode change 100644 => 100755 main/Utils/IO/Reader.class.php mode change 100644 => 100755 main/Utils/IO/Socket.class.php mode change 100644 => 100755 main/Utils/IO/SocketInputStream.class.php mode change 100644 => 100755 main/Utils/IO/SocketOutputStream.class.php mode change 100644 => 100755 main/Utils/IO/StringInputStream.class.php mode change 100644 => 100755 main/Utils/IO/StringReader.class.php mode change 100644 => 100755 main/Utils/Logging/BaseLogger.class.php mode change 100644 => 100755 main/Utils/Logging/LogLevel.class.php mode change 100644 => 100755 main/Utils/Logging/LogRecord.class.php mode change 100644 => 100755 main/Utils/Logging/StreamLogger.class.php mode change 100644 => 100755 main/Utils/LogicUtils.class.php mode change 100644 => 100755 main/Utils/Mobile/MobileRequestDetector.class.php mode change 100644 => 100755 main/Utils/Mobile/MobileUtils.class.php mode change 100644 => 100755 main/Utils/Routers/Router.class.php mode change 100644 => 100755 main/Utils/Routers/RouterBaseRule.class.php mode change 100644 => 100755 main/Utils/Routers/RouterChainRule.class.php mode change 100644 => 100755 main/Utils/Routers/RouterException.class.php mode change 100644 => 100755 main/Utils/Routers/RouterHostnameRule.class.php mode change 100644 => 100755 main/Utils/Routers/RouterRegexpRule.class.php mode change 100644 => 100755 main/Utils/Routers/RouterRewrite.class.php mode change 100644 => 100755 main/Utils/Routers/RouterRule.class.php mode change 100644 => 100755 main/Utils/Routers/RouterStaticRule.class.php mode change 100644 => 100755 main/Utils/Routers/RouterTransparentRule.class.php mode change 100644 => 100755 main/Utils/Routers/RouterUrlHelper.class.php mode change 100644 => 100755 main/Utils/RussianTextUtils.class.php mode change 100644 => 100755 main/Utils/SortHelper.class.php mode change 100644 => 100755 main/Utils/SynchronizableObject.class.php mode change 100644 => 100755 main/Utils/TextUtils.class.php mode change 100644 => 100755 main/Utils/TidyValidator.class.php mode change 100644 => 100755 main/Utils/TuringTest/BackgroundDrawer.class.php mode change 100644 => 100755 main/Utils/TuringTest/CellBackgroundDrawer.class.php mode change 100644 => 100755 main/Utils/TuringTest/CircleBackgroundDrawer.class.php mode change 100644 => 100755 main/Utils/TuringTest/CodeGenerator.class.php mode change 100644 => 100755 main/Utils/TuringTest/Color.class.php mode change 100644 => 100755 main/Utils/TuringTest/ColorArray.class.php mode change 100644 => 100755 main/Utils/TuringTest/CurvedStringDrawer.class.php mode change 100644 => 100755 main/Utils/TuringTest/Drawer.class.php mode change 100644 => 100755 main/Utils/TuringTest/ErrorDrawer.class.php mode change 100644 => 100755 main/Utils/TuringTest/InclinedStringDrawer.class.php mode change 100644 => 100755 main/Utils/TuringTest/LinearStringDrawer.class.php mode change 100644 => 100755 main/Utils/TuringTest/RandomLinesBackgroundDrawer.class.php mode change 100644 => 100755 main/Utils/TuringTest/TextDrawer.class.php mode change 100644 => 100755 main/Utils/TuringTest/TuringImage.class.php mode change 100644 => 100755 main/Utils/TuringTest/WavesBackgroundDrawer.class.php mode change 100644 => 100755 main/Utils/TypesUtils.class.php mode change 100644 => 100755 main/Utils/WebMoneyUtils.class.php mode change 100644 => 100755 main/Utils/XmlRpcClient.class.php mode change 100644 => 100755 meta/builders/AutoClassBuilder.class.php mode change 100644 => 100755 meta/builders/AutoDaoBuilder.class.php mode change 100644 => 100755 meta/builders/AutoProtoClassBuilder.class.php mode change 100644 => 100755 meta/builders/BaseBuilder.class.php mode change 100644 => 100755 meta/builders/BusinessClassBuilder.class.php mode change 100644 => 100755 meta/builders/ContainerClassBuilder.class.php mode change 100644 => 100755 meta/builders/DaoBuilder.class.php mode change 100644 => 100755 meta/builders/DictionaryDaoBuilder.class.php mode change 100644 => 100755 meta/builders/EnumerationClassBuilder.class.php mode change 100644 => 100755 meta/builders/OnceBuilder.class.php mode change 100644 => 100755 meta/builders/ProtoClassBuilder.class.php mode change 100644 => 100755 meta/builders/SchemaBuilder.class.php mode change 100644 => 100755 meta/classes/ColoredTextOutput.class.php mode change 100644 => 100755 meta/classes/ConsoleMode.class.php mode change 100644 => 100755 meta/classes/Format.class.php mode change 100644 => 100755 meta/classes/MetaClass.class.php mode change 100644 => 100755 meta/classes/MetaClassProperty.class.php mode change 100644 => 100755 meta/classes/MetaClassType.class.php mode change 100644 => 100755 meta/classes/MetaConfiguration.class.php mode change 100644 => 100755 meta/classes/MetaOutput.class.php mode change 100644 => 100755 meta/classes/MetaRelation.class.php mode change 100644 => 100755 meta/classes/TextOutput.class.php mode change 100644 => 100755 meta/dtd/meta.dtd mode change 100644 => 100755 meta/internal.xml mode change 100644 => 100755 meta/patterns/AbstractClassPattern.class.php mode change 100644 => 100755 meta/patterns/BasePattern.class.php mode change 100644 => 100755 meta/patterns/DictionaryClassPattern.class.php mode change 100644 => 100755 meta/patterns/EnumerationClassPattern.class.php mode change 100644 => 100755 meta/patterns/GenerationPattern.class.php mode change 100644 => 100755 meta/patterns/InternalClassPattern.class.php mode change 100644 => 100755 meta/patterns/SpookedClassPattern.class.php mode change 100644 => 100755 meta/patterns/SpookedEnumerationPattern.class.php mode change 100644 => 100755 meta/patterns/StraightMappingPattern.class.php mode change 100644 => 100755 meta/patterns/ValueObjectPattern.class.php mode change 100644 => 100755 meta/types/BasePropertyType.class.php mode change 100644 => 100755 meta/types/BigIntegerType.class.php mode change 100644 => 100755 meta/types/BinaryType.class.php mode change 100644 => 100755 meta/types/BooleanType.class.php mode change 100644 => 100755 meta/types/DateRangeType.class.php mode change 100644 => 100755 meta/types/DateType.class.php mode change 100644 => 100755 meta/types/DoubleType.class.php mode change 100644 => 100755 meta/types/FixedLengthStringType.class.php mode change 100644 => 100755 meta/types/FloatType.class.php mode change 100644 => 100755 meta/types/HstoreType.class.php mode change 100644 => 100755 meta/types/HttpUrlType.class.php mode change 100644 => 100755 meta/types/InetType.class.php mode change 100644 => 100755 meta/types/IntegerType.class.php mode change 100644 => 100755 meta/types/InternalType.class.php mode change 100644 => 100755 meta/types/IpAddressType.class.php mode change 100644 => 100755 meta/types/IpRangeType.class.php mode change 100644 => 100755 meta/types/NumericType.class.php mode change 100644 => 100755 meta/types/ObjectType.class.php mode change 100644 => 100755 meta/types/RangeType.class.php mode change 100644 => 100755 meta/types/SmallIntegerType.class.php mode change 100644 => 100755 meta/types/StringType.class.php mode change 100644 => 100755 meta/types/TimeType.class.php mode change 100644 => 100755 meta/types/TimestampRangeType.class.php mode change 100644 => 100755 meta/types/TimestampType.class.php mode change 100644 => 100755 meta/types/UnsignedBigIntegerType.class.php mode change 100644 => 100755 meta/types/UnsignedIntegerType.class.php mode change 100644 => 100755 meta/types/UnsignedSmallIntegerType.class.php mode change 100644 => 100755 misc/Autoloader.inc.php mode change 100644 => 100755 misc/BaseException.inc.php mode change 100644 => 100755 test/AllTests.php mode change 100644 => 100755 test/config.inc.php.tpl mode change 100644 => 100755 test/core/AggregateCacheTest.class.php mode change 100644 => 100755 test/core/AssertTest.class.php mode change 100644 => 100755 test/core/BaseCachesTest.class.php mode change 100644 => 100755 test/core/CalendarDayTest.class.php mode change 100644 => 100755 test/core/DateRangeTest.class.php mode change 100644 => 100755 test/core/DateTest.class.php mode change 100644 => 100755 test/core/DeleteQueryTest.class.php mode change 100644 => 100755 test/core/FiltersTest.class.php mode change 100644 => 100755 test/core/FormPrimitivesDateTest.class.php mode change 100644 => 100755 test/core/FormTest.class.php mode change 100644 => 100755 test/core/IntervalUnitTest.class.php mode change 100644 => 100755 test/core/Ip4ContainsExpressionTest.class.php mode change 100644 => 100755 test/core/LockerTest.class.php mode change 100644 => 100755 test/core/LogicTest.class.php mode change 100644 => 100755 test/core/PrimitiveAliasTest.class.php mode change 100644 => 100755 test/core/PrimitiveClassTest.class.php mode change 100644 => 100755 test/core/PrimitiveDateRangeTest.class.php mode change 100644 => 100755 test/core/PrimitiveEnumerationTest.class.php mode change 100644 => 100755 test/core/PrimitiveHstoreTest.class.php mode change 100644 => 100755 test/core/PrimitiveIdentifierTest.class.php mode change 100644 => 100755 test/core/PrimitiveInetTest.class.php mode change 100644 => 100755 test/core/PrimitiveIpTest.class.php mode change 100644 => 100755 test/core/PrimitiveNumberTest.class.php mode change 100644 => 100755 test/core/PrimitiveStringTest.class.php mode change 100644 => 100755 test/core/PrimitiveTimeTest.class.php mode change 100644 => 100755 test/core/PrimitiveTimestampTest.class.php mode change 100644 => 100755 test/core/SingletonTest.class.php mode change 100644 => 100755 test/core/TimestampTest.class.php mode change 100644 => 100755 test/core/TruncateQueryTest.class.php mode change 100644 => 100755 test/core/UnionTest.class.php mode change 100644 => 100755 test/main/Base62UtilsTest.class.php mode change 100644 => 100755 test/main/ClassUtilsTest.class.php mode change 100644 => 100755 test/main/ComparatorTest.class.php mode change 100644 => 100755 test/main/CriteriaTest.class.php mode change 100644 => 100755 test/main/CrypterTest.class.php mode change 100644 => 100755 test/main/CryptoTest.class.php mode change 100644 => 100755 test/main/CsvTest.class.php mode change 100644 => 100755 test/main/DateUtilsTest.class.php mode change 100644 => 100755 test/main/EntityProtoConvertersTest.class.php mode change 100644 => 100755 test/main/EnumerationTest.class.php mode change 100644 => 100755 test/main/FeedReaderTest.class.php mode change 100644 => 100755 test/main/FloatRangeTest.class.php mode change 100644 => 100755 test/main/GenericUriTest.class.php mode change 100644 => 100755 test/main/GoogleChartTest.class.php mode change 100644 => 100755 test/main/HeaderParserTest.class.php mode change 100644 => 100755 test/main/HttpUtilsTest.class.php mode change 100644 => 100755 test/main/Ip/IpAddressTest.class.php mode change 100644 => 100755 test/main/Ip/IpBaseRangeTest.class.php mode change 100644 => 100755 test/main/Ip/IpNetworkTest.class.php mode change 100644 => 100755 test/main/Ip/IpUtilsTest.class.php mode change 100644 => 100755 test/main/JsonViewTest.class.php mode change 100644 => 100755 test/main/MathTest.class.php mode change 100644 => 100755 test/main/MathUtilsTest.class.php mode change 100644 => 100755 test/main/MessagesTest.class.php mode change 100644 => 100755 test/main/MimeMailTest.class.php mode change 100644 => 100755 test/main/Net/CookieTest.class.php mode change 100644 => 100755 test/main/Net/MailTest.class.php mode change 100644 => 100755 test/main/OpenIdTest.class.php mode change 100644 => 100755 test/main/OqlSelectClauseTest.class.php mode change 100644 => 100755 test/main/OqlSelectTest.class.php mode change 100644 => 100755 test/main/OqlTokenizerTest.class.php mode change 100644 => 100755 test/main/OsqlDeleteTest.class.php mode change 100644 => 100755 test/main/OsqlInsertTest.class.php mode change 100644 => 100755 test/main/OsqlReturningTest.class.php mode change 100644 => 100755 test/main/OsqlSelectTest.class.php mode change 100644 => 100755 test/main/PostgresDialectTest.class.php mode change 100644 => 100755 test/main/RangeTest.class.php mode change 100644 => 100755 test/main/TextUtilsTest.class.php mode change 100644 => 100755 test/main/Utils/AMQP/AMQPPeclTest.class.php mode change 100644 => 100755 test/main/Utils/ArrayUtilsTest.class.php mode change 100644 => 100755 test/main/Utils/FileUtilsTest.class.php mode change 100644 => 100755 test/main/Utils/Routers/RouterBaseRuleTest.class.php mode change 100644 => 100755 test/main/Utils/Routers/RouterChainRuleTest.class.php mode change 100644 => 100755 test/main/Utils/Routers/RouterHostnameRuleTest.class.php mode change 100644 => 100755 test/main/Utils/Routers/RouterRegexpRuleTest.class.php mode change 100644 => 100755 test/main/Utils/Routers/RouterRewriteTest.class.php mode change 100644 => 100755 test/main/Utils/Routers/RouterStaticRuleTest.class.php mode change 100644 => 100755 test/main/Utils/Routers/RouterTransparentRuleTest.class.php mode change 100644 => 100755 test/main/Utils/SocketTest.class.php mode change 100644 => 100755 test/main/Utils/TypesUtilsTest.class.php mode change 100644 => 100755 test/main/Utils/WebMoneyUtilsTest.class.php mode change 100644 => 100755 test/main/ViewTest.class.php mode change 100644 => 100755 test/main/data/directory/contents mode change 100644 => 100755 test/main/data/directory/inner/textField mode change 100644 => 100755 test/main/data/directory/textField mode change 100644 => 100755 test/main/data/feedReader/atom_v1_0.xml mode change 100644 => 100755 test/main/data/feedReader/news.xml mode change 100644 => 100755 test/main/data/feedReader/yandex_rss.xml mode change 100644 => 100755 test/main/data/mimeMail/encodedBody.txt mode change 100644 => 100755 test/main/data/mimeMail/headers.txt mode change 100644 => 100755 test/main/data/mimeMail/message.html mode change 100644 => 100755 test/main/data/mimeMail/picture.jpg mode change 100644 => 100755 test/main/data/unicode/utf16.txt mode change 100644 => 100755 test/main/data/unicode/utf16be.txt mode change 100644 => 100755 test/main/data/unicode/utf16le.txt mode change 100644 => 100755 test/main/data/unicode/utf8.txt mode change 100644 => 100755 test/main/data/urls/.._.._.._.._g.dump mode change 100644 => 100755 test/main/data/urls/.dump mode change 100644 => 100755 test/main/data/urls/parser.dump mode change 100644 => 100755 test/main/data/views/testPartView.tpl.html mode change 100644 => 100755 test/main/data/views/testView.tpl.html mode change 100644 => 100755 test/main/data/views/testViewToString.tpl.html mode change 100644 => 100755 test/meta/config.inc.php mode change 100644 => 100755 test/meta/config.meta.xml mode change 100644 => 100755 test/misc/DAOTest.class.php mode change 100644 => 100755 test/misc/DBTestPool.class.php mode change 100644 => 100755 test/misc/ServerVarUtils.class.php mode change 100644 => 100755 test/misc/TestCase.class.php mode change 100644 => 100755 test/misc/TestTables.class.php diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/core/Base/Aliased.class.php b/core/Base/Aliased.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Assert.class.php b/core/Base/Assert.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Date.class.php b/core/Base/Date.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Enumeration.class.php b/core/Base/Enumeration.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Identifiable.class.php b/core/Base/Identifiable.class.php old mode 100644 new mode 100755 diff --git a/core/Base/IdentifiableObject.class.php b/core/Base/IdentifiableObject.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Identifier.class.php b/core/Base/Identifier.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Instantiatable.class.php b/core/Base/Instantiatable.class.php old mode 100644 new mode 100755 diff --git a/core/Base/IntervalUnit.class.php b/core/Base/IntervalUnit.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Named.class.php b/core/Base/Named.class.php old mode 100644 new mode 100755 diff --git a/core/Base/NamedObject.class.php b/core/Base/NamedObject.class.php old mode 100644 new mode 100755 diff --git a/core/Base/PriorityQueue.class.php b/core/Base/PriorityQueue.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Prototyped.class.php b/core/Base/Prototyped.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Session.class.php b/core/Base/Session.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Singleton.class.php b/core/Base/Singleton.class.php old mode 100644 new mode 100755 diff --git a/core/Base/StaticFactory.class.php b/core/Base/StaticFactory.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Stringable.class.php b/core/Base/Stringable.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Ternary.class.php b/core/Base/Ternary.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Time.class.php b/core/Base/Time.class.php old mode 100644 new mode 100755 diff --git a/core/Base/Timestamp.class.php b/core/Base/Timestamp.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/AggregateCache.class.php b/core/Cache/AggregateCache.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/BaseAggregateCache.class.php b/core/Cache/BaseAggregateCache.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/BaseLocker.class.php b/core/Cache/BaseLocker.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/Cache.class.php b/core/Cache/Cache.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/CachePeer.class.php b/core/Cache/CachePeer.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/CyclicAggregateCache.class.php b/core/Cache/CyclicAggregateCache.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/DebugCachePeer.class.php b/core/Cache/DebugCachePeer.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/DirectoryLocker.class.php b/core/Cache/DirectoryLocker.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/FileLocker.class.php b/core/Cache/FileLocker.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/Memcached.class.php b/core/Cache/Memcached.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/MemcachedLocker.class.php b/core/Cache/MemcachedLocker.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/PeclMemcached.class.php b/core/Cache/PeclMemcached.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/ReadOnlyPeer.class.php b/core/Cache/ReadOnlyPeer.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/RubberFileSystem.class.php b/core/Cache/RubberFileSystem.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/RuntimeMemory.class.php b/core/Cache/RuntimeMemory.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/SelectivePeer.class.php b/core/Cache/SelectivePeer.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/SemaphorePool.class.php b/core/Cache/SemaphorePool.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/SharedMemory.class.php b/core/Cache/SharedMemory.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/SimpleAggregateCache.class.php b/core/Cache/SimpleAggregateCache.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/SystemFiveLocker.class.php b/core/Cache/SystemFiveLocker.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/WatermarkedPeer.class.php b/core/Cache/WatermarkedPeer.class.php old mode 100644 new mode 100755 diff --git a/core/Cache/eAcceleratorLocker.class.php b/core/Cache/eAcceleratorLocker.class.php old mode 100644 new mode 100755 diff --git a/core/DB/DB.class.php b/core/DB/DB.class.php old mode 100644 new mode 100755 diff --git a/core/DB/DBPool.class.php b/core/DB/DBPool.class.php old mode 100644 new mode 100755 diff --git a/core/DB/Dialect.class.php b/core/DB/Dialect.class.php old mode 100644 new mode 100755 diff --git a/core/DB/ImaginaryDialect.class.php b/core/DB/ImaginaryDialect.class.php old mode 100644 new mode 100755 diff --git a/core/DB/LiteDialect.class.php b/core/DB/LiteDialect.class.php old mode 100644 new mode 100755 diff --git a/core/DB/MyDialect.class.php b/core/DB/MyDialect.class.php old mode 100644 new mode 100755 diff --git a/core/DB/MyImprovedDialect.class.php b/core/DB/MyImprovedDialect.class.php old mode 100644 new mode 100755 diff --git a/core/DB/MySQL.class.php b/core/DB/MySQL.class.php old mode 100644 new mode 100755 diff --git a/core/DB/MySQLim.class.php b/core/DB/MySQLim.class.php old mode 100644 new mode 100755 diff --git a/core/DB/PgSQL.class.php b/core/DB/PgSQL.class.php old mode 100644 new mode 100755 diff --git a/core/DB/PostgresDialect.class.php b/core/DB/PostgresDialect.class.php old mode 100644 new mode 100755 diff --git a/core/DB/PostgresError.class.php b/core/DB/PostgresError.class.php old mode 100644 new mode 100755 diff --git a/core/DB/Queue.class.php b/core/DB/Queue.class.php old mode 100644 new mode 100755 diff --git a/core/DB/SQLite.class.php b/core/DB/SQLite.class.php old mode 100644 new mode 100755 diff --git a/core/DB/Sequenceless.class.php b/core/DB/Sequenceless.class.php old mode 100644 new mode 100755 diff --git a/core/DB/Transaction/AccessMode.class.php b/core/DB/Transaction/AccessMode.class.php old mode 100644 new mode 100755 diff --git a/core/DB/Transaction/BaseTransaction.class.php b/core/DB/Transaction/BaseTransaction.class.php old mode 100644 new mode 100755 diff --git a/core/DB/Transaction/DBTransaction.class.php b/core/DB/Transaction/DBTransaction.class.php old mode 100644 new mode 100755 diff --git a/core/DB/Transaction/FakeTransaction.class.php b/core/DB/Transaction/FakeTransaction.class.php old mode 100644 new mode 100755 diff --git a/core/DB/Transaction/IsolationLevel.class.php b/core/DB/Transaction/IsolationLevel.class.php old mode 100644 new mode 100755 diff --git a/core/DB/Transaction/Transaction.class.php b/core/DB/Transaction/Transaction.class.php old mode 100644 new mode 100755 diff --git a/core/DB/Transaction/TransactionQueue.class.php b/core/DB/Transaction/TransactionQueue.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/BadRequestException.class.php b/core/Exceptions/BadRequestException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/BaseException.class.php b/core/Exceptions/BaseException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/BusinessLogicException.class.php b/core/Exceptions/BusinessLogicException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/CachedObjectNotFoundException.class.php b/core/Exceptions/CachedObjectNotFoundException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/ClassNotFoundException.class.php b/core/Exceptions/ClassNotFoundException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/DatabaseException.class.php b/core/Exceptions/DatabaseException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/DuplicateObjectException.class.php b/core/Exceptions/DuplicateObjectException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/FileNotFoundException.class.php b/core/Exceptions/FileNotFoundException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/IOException.class.php b/core/Exceptions/IOException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/IOTimedOutException.class.php b/core/Exceptions/IOTimedOutException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/MissingElementException.class.php b/core/Exceptions/MissingElementException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/NetworkException.class.php b/core/Exceptions/NetworkException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/ObjectNotFoundException.class.php b/core/Exceptions/ObjectNotFoundException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/PostgresDatabaseException.class.php b/core/Exceptions/PostgresDatabaseException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/SecurityException.class.php b/core/Exceptions/SecurityException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/SoapFault.class.php b/core/Exceptions/SoapFault.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/SyntaxErrorException.class.php b/core/Exceptions/SyntaxErrorException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/TooManyRowsException.class.php b/core/Exceptions/TooManyRowsException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/UnimplementedFeatureException.class.php b/core/Exceptions/UnimplementedFeatureException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/UnsupportedMethodException.class.php b/core/Exceptions/UnsupportedMethodException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/WrongArgumentException.class.php b/core/Exceptions/WrongArgumentException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/WrongStateException.class.php b/core/Exceptions/WrongStateException.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filter.class.php b/core/Form/Filter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/BaseFilter.class.php b/core/Form/Filters/BaseFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/CallbackFilter.class.php b/core/Form/Filters/CallbackFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/CompressWhitespaceFilter.class.php b/core/Form/Filters/CompressWhitespaceFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/CropFilter.class.php b/core/Form/Filters/CropFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/DateRangeDisplayFilter.class.php b/core/Form/Filters/DateRangeDisplayFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/FilterChain.class.php b/core/Form/Filters/FilterChain.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/Filtrator.class.php b/core/Form/Filters/Filtrator.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/HashFilter.class.php b/core/Form/Filters/HashFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/HtmlSpecialCharsFilter.class.php b/core/Form/Filters/HtmlSpecialCharsFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/JsonDecoderFilter.class.php b/core/Form/Filters/JsonDecoderFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/JsonEncoderFilter.class.php b/core/Form/Filters/JsonEncoderFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/LowerCaseFilter.class.php b/core/Form/Filters/LowerCaseFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/NewLinesToBreaks.class.php b/core/Form/Filters/NewLinesToBreaks.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/NormalizeUrlFilter.class.php b/core/Form/Filters/NormalizeUrlFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/PCREFilter.class.php b/core/Form/Filters/PCREFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/Paragraphizer.class.php b/core/Form/Filters/Paragraphizer.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/RemoveNewlineFilter.class.php b/core/Form/Filters/RemoveNewlineFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/RussianTypograph.class.php b/core/Form/Filters/RussianTypograph.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/SafeUtf8Filter.class.php b/core/Form/Filters/SafeUtf8Filter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/StringReplaceFilter.class.php b/core/Form/Filters/StringReplaceFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/StripTagsFilter.class.php b/core/Form/Filters/StripTagsFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/TrimFilter.class.php b/core/Form/Filters/TrimFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/UnTypographizer.class.php b/core/Form/Filters/UnTypographizer.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/UnixToUnixDecode.class.php b/core/Form/Filters/UnixToUnixDecode.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/UnixToUnixEncode.class.php b/core/Form/Filters/UnixToUnixEncode.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/UnserializeFilter.class.php b/core/Form/Filters/UnserializeFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/UpperCaseFilter.class.php b/core/Form/Filters/UpperCaseFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/UrlDecodeFilter.class.php b/core/Form/Filters/UrlDecodeFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/UrlEncodeFilter.class.php b/core/Form/Filters/UrlEncodeFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/Utf16ConverterFilter.class.php b/core/Form/Filters/Utf16ConverterFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Filters/WordSplitterFilter.class.php b/core/Form/Filters/WordSplitterFilter.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Form.class.php b/core/Form/Form.class.php old mode 100644 new mode 100755 diff --git a/core/Form/FormField.class.php b/core/Form/FormField.class.php old mode 100644 new mode 100755 diff --git a/core/Form/FormUtils.class.php b/core/Form/FormUtils.class.php old mode 100644 new mode 100755 diff --git a/core/Form/MappedForm.class.php b/core/Form/MappedForm.class.php old mode 100644 new mode 100755 diff --git a/core/Form/PlainForm.class.php b/core/Form/PlainForm.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitive.class.php b/core/Form/Primitive.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/BaseObjectPrimitive.class.php b/core/Form/Primitives/BaseObjectPrimitive.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/BasePrimitive.class.php b/core/Form/Primitives/BasePrimitive.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/ComplexPrimitive.class.php b/core/Form/Primitives/ComplexPrimitive.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/DateRangeList.class.php b/core/Form/Primitives/DateRangeList.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/ExplodedPrimitive.class.php b/core/Form/Primitives/ExplodedPrimitive.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/FiltrablePrimitive.class.php b/core/Form/Primitives/FiltrablePrimitive.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/IdentifiablePrimitive.class.php b/core/Form/Primitives/IdentifiablePrimitive.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/ListedPrimitive.class.php b/core/Form/Primitives/ListedPrimitive.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveAlias.class.php b/core/Form/Primitives/PrimitiveAlias.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveAnyType.class.php b/core/Form/Primitives/PrimitiveAnyType.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveArray.class.php b/core/Form/Primitives/PrimitiveArray.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveBinary.class.php b/core/Form/Primitives/PrimitiveBinary.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveBoolean.class.php b/core/Form/Primitives/PrimitiveBoolean.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveClass.class.php b/core/Form/Primitives/PrimitiveClass.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveDate.class.php b/core/Form/Primitives/PrimitiveDate.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveDateRange.class.php b/core/Form/Primitives/PrimitiveDateRange.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveEnumeration.class.php b/core/Form/Primitives/PrimitiveEnumeration.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveEnumerationByValue.class.php b/core/Form/Primitives/PrimitiveEnumerationByValue.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveEnumerationList.class.php b/core/Form/Primitives/PrimitiveEnumerationList.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveFile.class.php b/core/Form/Primitives/PrimitiveFile.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveFloat.class.php b/core/Form/Primitives/PrimitiveFloat.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveForm.class.php b/core/Form/Primitives/PrimitiveForm.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveFormsList.class.php b/core/Form/Primitives/PrimitiveFormsList.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveHstore.class.php b/core/Form/Primitives/PrimitiveHstore.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveHttpUrl.class.php b/core/Form/Primitives/PrimitiveHttpUrl.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveIdentifier.class.php b/core/Form/Primitives/PrimitiveIdentifier.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveIdentifierList.class.php b/core/Form/Primitives/PrimitiveIdentifierList.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveImage.class.php b/core/Form/Primitives/PrimitiveImage.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveInet.class.php b/core/Form/Primitives/PrimitiveInet.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveInteger.class.php b/core/Form/Primitives/PrimitiveInteger.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveIntegerIdentifier.class.php b/core/Form/Primitives/PrimitiveIntegerIdentifier.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveIpAddress.class.php b/core/Form/Primitives/PrimitiveIpAddress.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveIpRange.class.php b/core/Form/Primitives/PrimitiveIpRange.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveList.class.php b/core/Form/Primitives/PrimitiveList.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveMultiList.class.php b/core/Form/Primitives/PrimitiveMultiList.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveNoValue.class.php b/core/Form/Primitives/PrimitiveNoValue.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveNumber.class.php b/core/Form/Primitives/PrimitiveNumber.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitivePlainList.class.php b/core/Form/Primitives/PrimitivePlainList.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitivePolymorphicIdentifier.class.php b/core/Form/Primitives/PrimitivePolymorphicIdentifier.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveRange.class.php b/core/Form/Primitives/PrimitiveRange.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveScalarIdentifier.class.php b/core/Form/Primitives/PrimitiveScalarIdentifier.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveString.class.php b/core/Form/Primitives/PrimitiveString.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveTernary.class.php b/core/Form/Primitives/PrimitiveTernary.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveTime.class.php b/core/Form/Primitives/PrimitiveTime.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveTimestamp.class.php b/core/Form/Primitives/PrimitiveTimestamp.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveTimestampRange.class.php b/core/Form/Primitives/PrimitiveTimestampRange.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/RangedPrimitive.class.php b/core/Form/Primitives/RangedPrimitive.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/TimeList.class.php b/core/Form/Primitives/TimeList.class.php old mode 100644 new mode 100755 diff --git a/core/Form/RegulatedForm.class.php b/core/Form/RegulatedForm.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/BinaryExpression.class.php b/core/Logic/BinaryExpression.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/CallbackLogicalObject.class.php b/core/Logic/CallbackLogicalObject.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/EqualsLowerExpression.class.php b/core/Logic/EqualsLowerExpression.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/Expression.class.php b/core/Logic/Expression.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/HstoreExpression.class.php b/core/Logic/HstoreExpression.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/InExpression.class.php b/core/Logic/InExpression.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/Ip4ContainsExpression.class.php b/core/Logic/Ip4ContainsExpression.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/LTreeExpression.class.php b/core/Logic/LTreeExpression.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/LogicalBetween.class.php b/core/Logic/LogicalBetween.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/LogicalChain.class.php b/core/Logic/LogicalChain.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/LogicalObject.class.php b/core/Logic/LogicalObject.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/MappableObject.class.php b/core/Logic/MappableObject.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/PostfixUnaryExpression.class.php b/core/Logic/PostfixUnaryExpression.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/PrefixUnaryExpression.class.php b/core/Logic/PrefixUnaryExpression.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/Castable.class.php b/core/OSQL/Castable.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/CombineQuery.class.php b/core/OSQL/CombineQuery.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/CreateTableQuery.class.php b/core/OSQL/CreateTableQuery.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/DBBinary.class.php b/core/OSQL/DBBinary.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/DBColumn.class.php b/core/OSQL/DBColumn.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/DBField.class.php b/core/OSQL/DBField.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/DBRaw.class.php b/core/OSQL/DBRaw.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/DBSchema.class.php b/core/OSQL/DBSchema.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/DBTable.class.php b/core/OSQL/DBTable.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/DBValue.class.php b/core/OSQL/DBValue.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/DataType.class.php b/core/OSQL/DataType.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/DatePart.class.php b/core/OSQL/DatePart.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/DeleteQuery.class.php b/core/OSQL/DeleteQuery.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/DialectString.class.php b/core/OSQL/DialectString.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/DropTableQuery.class.php b/core/OSQL/DropTableQuery.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/ExtractPart.class.php b/core/OSQL/ExtractPart.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/FieldGroup.class.php b/core/OSQL/FieldGroup.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/FieldTable.class.php b/core/OSQL/FieldTable.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/ForeignChangeAction.class.php b/core/OSQL/ForeignChangeAction.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/FromTable.class.php b/core/OSQL/FromTable.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/FullText.class.php b/core/OSQL/FullText.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/FullTextRank.class.php b/core/OSQL/FullTextRank.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/FullTextSearch.class.php b/core/OSQL/FullTextSearch.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/GroupBy.class.php b/core/OSQL/GroupBy.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/InsertOrUpdateQuery.class.php b/core/OSQL/InsertOrUpdateQuery.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/InsertQuery.class.php b/core/OSQL/InsertQuery.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/JoinCapableQuery.class.php b/core/OSQL/JoinCapableQuery.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/Joiner.class.php b/core/OSQL/Joiner.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/OSQL.class.php b/core/OSQL/OSQL.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/OrderBy.class.php b/core/OSQL/OrderBy.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/OrderChain.class.php b/core/OSQL/OrderChain.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/Query.class.php b/core/OSQL/Query.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/QueryChain.class.php b/core/OSQL/QueryChain.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/QueryCombination.class.php b/core/OSQL/QueryCombination.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/QueryIdentification.class.php b/core/OSQL/QueryIdentification.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/QueryResult.class.php b/core/OSQL/QueryResult.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/QuerySkeleton.class.php b/core/OSQL/QuerySkeleton.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/SQLArray.class.php b/core/OSQL/SQLArray.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/SQLBaseJoin.class.php b/core/OSQL/SQLBaseJoin.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/SQLChain.class.php b/core/OSQL/SQLChain.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/SQLFunction.class.php b/core/OSQL/SQLFunction.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/SQLJoin.class.php b/core/OSQL/SQLJoin.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/SQLLeftJoin.class.php b/core/OSQL/SQLLeftJoin.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/SQLRightJoin.class.php b/core/OSQL/SQLRightJoin.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/SQLTableName.class.php b/core/OSQL/SQLTableName.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/SelectField.class.php b/core/OSQL/SelectField.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/SelectQuery.class.php b/core/OSQL/SelectQuery.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/TimeIntervalsGenerator.class.php b/core/OSQL/TimeIntervalsGenerator.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/TruncateQuery.class.php b/core/OSQL/TruncateQuery.class.php old mode 100644 new mode 100755 diff --git a/core/OSQL/UpdateQuery.class.php b/core/OSQL/UpdateQuery.class.php old mode 100644 new mode 100755 diff --git a/doc/AUTHORS b/doc/AUTHORS old mode 100644 new mode 100755 diff --git a/doc/ChangeLog b/doc/ChangeLog old mode 100644 new mode 100755 diff --git a/doc/CodingStyle b/doc/CodingStyle old mode 100644 new mode 100755 diff --git a/doc/Doxyfile b/doc/Doxyfile old mode 100644 new mode 100755 diff --git a/doc/FAQ b/doc/FAQ old mode 100644 new mode 100755 diff --git a/doc/FEATURES b/doc/FEATURES old mode 100644 new mode 100755 diff --git a/doc/LICENSE b/doc/LICENSE old mode 100644 new mode 100755 diff --git a/doc/OQL-BNF b/doc/OQL-BNF old mode 100644 new mode 100755 diff --git a/doc/README b/doc/README old mode 100644 new mode 100755 diff --git a/doc/ROUTERS b/doc/ROUTERS old mode 100644 new mode 100755 diff --git a/doc/THANKS b/doc/THANKS old mode 100644 new mode 100755 diff --git a/doc/TODO b/doc/TODO old mode 100644 new mode 100755 diff --git a/doc/examples/cacheSettings.php b/doc/examples/cacheSettings.php old mode 100644 new mode 100755 diff --git a/doc/examples/index.php b/doc/examples/index.php old mode 100644 new mode 100755 diff --git a/doc/examples/singleton.php b/doc/examples/singleton.php old mode 100644 new mode 100755 diff --git a/doc/examples/union.php b/doc/examples/union.php old mode 100644 new mode 100755 diff --git a/doc/onphp.doxy.php b/doc/onphp.doxy.php old mode 100644 new mode 100755 diff --git a/doc/parts/doxyHead.html b/doc/parts/doxyHead.html old mode 100644 new mode 100755 diff --git a/doc/parts/doxyHeel.html b/doc/parts/doxyHeel.html old mode 100644 new mode 100755 diff --git a/doc/project.skel/config.inc.php.tpl b/doc/project.skel/config.inc.php.tpl old mode 100644 new mode 100755 diff --git a/doc/project.skel/config.xml b/doc/project.skel/config.xml old mode 100644 new mode 100755 diff --git a/doc/project.skel/db/schema.sql b/doc/project.skel/db/schema.sql old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/admin/controllers/login.class.php b/doc/project.skel/src/admin/controllers/login.class.php old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/admin/controllers/main.class.php b/doc/project.skel/src/admin/controllers/main.class.php old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/admin/htdocs/index.php b/doc/project.skel/src/admin/htdocs/index.php old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/admin/templates/login.tpl.html b/doc/project.skel/src/admin/templates/login.tpl.html old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/admin/templates/main.tpl.html b/doc/project.skel/src/admin/templates/main.tpl.html old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/classes/Auto/Business/AutoAdministrator.class.php b/doc/project.skel/src/classes/Auto/Business/AutoAdministrator.class.php old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/classes/Auto/DAOs/AutoAdministratorDAO.class.php b/doc/project.skel/src/classes/Auto/DAOs/AutoAdministratorDAO.class.php old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/classes/Auto/Proto/AutoProtoAdministrator.class.php b/doc/project.skel/src/classes/Auto/Proto/AutoProtoAdministrator.class.php old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/classes/Auto/schema.php b/doc/project.skel/src/classes/Auto/schema.php old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/classes/Business/Administrator.class.php b/doc/project.skel/src/classes/Business/Administrator.class.php old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/classes/DAOs/AdministratorDAO.class.php b/doc/project.skel/src/classes/DAOs/AdministratorDAO.class.php old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/classes/Flow/AuthorizationFilter.class.php b/doc/project.skel/src/classes/Flow/AuthorizationFilter.class.php old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/classes/Proto/ProtoAdministrator.class.php b/doc/project.skel/src/classes/Proto/ProtoAdministrator.class.php old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/user/controllers/main.class.php b/doc/project.skel/src/user/controllers/main.class.php old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/user/htdocs/index.php b/doc/project.skel/src/user/htdocs/index.php old mode 100644 new mode 100755 diff --git a/doc/project.skel/src/user/templates/main.tpl.html b/doc/project.skel/src/user/templates/main.tpl.html old mode 100644 new mode 100755 diff --git a/global.inc.php.tpl b/global.inc.php.tpl old mode 100644 new mode 100755 diff --git a/main/Application/ApplicationUrl.class.php b/main/Application/ApplicationUrl.class.php old mode 100644 new mode 100755 diff --git a/main/Application/ScopeNavigationSchema.class.php b/main/Application/ScopeNavigationSchema.class.php old mode 100644 new mode 100755 diff --git a/main/Application/SimpleApplicationUrl.class.php b/main/Application/SimpleApplicationUrl.class.php old mode 100644 new mode 100755 diff --git a/main/Base/AbstractCollection.class.php b/main/Base/AbstractCollection.class.php old mode 100644 new mode 100755 diff --git a/main/Base/AbstractProtoClass.class.php b/main/Base/AbstractProtoClass.class.php old mode 100644 new mode 100755 diff --git a/main/Base/BaseRange.class.php b/main/Base/BaseRange.class.php old mode 100644 new mode 100755 diff --git a/main/Base/CalendarDay.class.php b/main/Base/CalendarDay.class.php old mode 100644 new mode 100755 diff --git a/main/Base/CalendarMonthWeekly.class.php b/main/Base/CalendarMonthWeekly.class.php old mode 100644 new mode 100755 diff --git a/main/Base/CalendarWeek.class.php b/main/Base/CalendarWeek.class.php old mode 100644 new mode 100755 diff --git a/main/Base/CallChain.class.php b/main/Base/CallChain.class.php old mode 100644 new mode 100755 diff --git a/main/Base/Collection.class.php b/main/Base/Collection.class.php old mode 100644 new mode 100755 diff --git a/main/Base/CollectionItem.class.php b/main/Base/CollectionItem.class.php old mode 100644 new mode 100755 diff --git a/main/Base/Comparator.class.php b/main/Base/Comparator.class.php old mode 100644 new mode 100755 diff --git a/main/Base/DateObjectComparator.class.php b/main/Base/DateObjectComparator.class.php old mode 100644 new mode 100755 diff --git a/main/Base/DateRange.class.php b/main/Base/DateRange.class.php old mode 100644 new mode 100755 diff --git a/main/Base/FloatRange.class.php b/main/Base/FloatRange.class.php old mode 100644 new mode 100755 diff --git a/main/Base/Hstore.class.php b/main/Base/Hstore.class.php old mode 100644 new mode 100755 diff --git a/main/Base/IdentifiableTree.class.php b/main/Base/IdentifiableTree.class.php old mode 100644 new mode 100755 diff --git a/main/Base/ImageType.class.php b/main/Base/ImageType.class.php old mode 100644 new mode 100755 diff --git a/main/Base/ImmutableObjectComparator.class.php b/main/Base/ImmutableObjectComparator.class.php old mode 100644 new mode 100755 diff --git a/main/Base/InnerMetaProperty.class.php b/main/Base/InnerMetaProperty.class.php old mode 100644 new mode 100755 diff --git a/main/Base/IntegerSet.class.php b/main/Base/IntegerSet.class.php old mode 100644 new mode 100755 diff --git a/main/Base/IsoCurrency.class.php b/main/Base/IsoCurrency.class.php old mode 100644 new mode 100755 diff --git a/main/Base/LightMetaProperty.class.php b/main/Base/LightMetaProperty.class.php old mode 100644 new mode 100755 diff --git a/main/Base/NamedTree.class.php b/main/Base/NamedTree.class.php old mode 100644 new mode 100755 diff --git a/main/Base/Range.class.php b/main/Base/Range.class.php old mode 100644 new mode 100755 diff --git a/main/Base/RequestType.class.php b/main/Base/RequestType.class.php old mode 100644 new mode 100755 diff --git a/main/Base/SerializedObjectComparator.class.php b/main/Base/SerializedObjectComparator.class.php old mode 100644 new mode 100755 diff --git a/main/Base/SingleRange.class.php b/main/Base/SingleRange.class.php old mode 100644 new mode 100755 diff --git a/main/Base/StandardComparator.class.php b/main/Base/StandardComparator.class.php old mode 100644 new mode 100755 diff --git a/main/Base/TempDirectory.class.php b/main/Base/TempDirectory.class.php old mode 100644 new mode 100755 diff --git a/main/Base/TempFile.class.php b/main/Base/TempFile.class.php old mode 100644 new mode 100755 diff --git a/main/Base/TimestampRange.class.php b/main/Base/TimestampRange.class.php old mode 100644 new mode 100755 diff --git a/main/Base/TransparentFile.class.php b/main/Base/TransparentFile.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/BaseGoogleChartData.class.php b/main/Charts/Google/BaseGoogleChartData.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/BaseGoogleChartDataEncoding.class.php b/main/Charts/Google/BaseGoogleChartDataEncoding.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/BaseGoogleChartLabelStyleType.class.php b/main/Charts/Google/BaseGoogleChartLabelStyleType.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/BaseGoogleChartParameter.class.php b/main/Charts/Google/BaseGoogleChartParameter.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/BaseGoogleChartStyle.class.php b/main/Charts/Google/BaseGoogleChartStyle.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/ChartLabelStyle.class.php b/main/Charts/Google/ChartLabelStyle.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/ChartLineStyle.class.php b/main/Charts/Google/ChartLineStyle.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChart.class.php b/main/Charts/Google/GoogleChart.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartAxis.class.php b/main/Charts/Google/GoogleChartAxis.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartAxisCollection.class.php b/main/Charts/Google/GoogleChartAxisCollection.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartAxisLabel.class.php b/main/Charts/Google/GoogleChartAxisLabel.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartAxisType.class.php b/main/Charts/Google/GoogleChartAxisType.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartColor.class.php b/main/Charts/Google/GoogleChartColor.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartData.class.php b/main/Charts/Google/GoogleChartData.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartDataEncoding.class.php b/main/Charts/Google/GoogleChartDataEncoding.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartDataRange.class.php b/main/Charts/Google/GoogleChartDataRange.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartDataScaling.class.php b/main/Charts/Google/GoogleChartDataScaling.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartDataSet.class.php b/main/Charts/Google/GoogleChartDataSet.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartDataSimpleEncoding.class.php b/main/Charts/Google/GoogleChartDataSimpleEncoding.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartDataTextEncoding.class.php b/main/Charts/Google/GoogleChartDataTextEncoding.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartGrid.class.php b/main/Charts/Google/GoogleChartGrid.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartLabel.class.php b/main/Charts/Google/GoogleChartLabel.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartLabelStyle.class.php b/main/Charts/Google/GoogleChartLabelStyle.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartLabelStyleNumberType.class.php b/main/Charts/Google/GoogleChartLabelStyleNumberType.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartLegend.class.php b/main/Charts/Google/GoogleChartLegend.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartLegendPositionType.class.php b/main/Charts/Google/GoogleChartLegendPositionType.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartLine.class.php b/main/Charts/Google/GoogleChartLine.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartLineStyle.class.php b/main/Charts/Google/GoogleChartLineStyle.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartPiece.class.php b/main/Charts/Google/GoogleChartPiece.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartSize.class.php b/main/Charts/Google/GoogleChartSize.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartSolidFill.class.php b/main/Charts/Google/GoogleChartSolidFill.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartSolidFillCollection.class.php b/main/Charts/Google/GoogleChartSolidFillCollection.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartSolidFillType.class.php b/main/Charts/Google/GoogleChartSolidFillType.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartTitle.class.php b/main/Charts/Google/GoogleChartTitle.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleChartType.class.php b/main/Charts/Google/GoogleChartType.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleGridedLineChart.class.php b/main/Charts/Google/GoogleGridedLineChart.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleLineChart.class.php b/main/Charts/Google/GoogleLineChart.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GoogleNormalizedLineChart.class.php b/main/Charts/Google/GoogleNormalizedLineChart.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/GooglePieChart.class.php b/main/Charts/Google/GooglePieChart.class.php old mode 100644 new mode 100755 diff --git a/main/Charts/Google/LabelStyleType.class.php b/main/Charts/Google/LabelStyleType.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Criteria.class.php b/main/Criteria/Criteria.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/FetchStrategy.class.php b/main/Criteria/FetchStrategy.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projection.class.php b/main/Criteria/Projection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/AggregateProjection.class.php b/main/Criteria/Projections/AggregateProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/AverageNumberProjection.class.php b/main/Criteria/Projections/AverageNumberProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/BaseProjection.class.php b/main/Criteria/Projections/BaseProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/ClassProjection.class.php b/main/Criteria/Projections/ClassProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/CountProjection.class.php b/main/Criteria/Projections/CountProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/DistinctCountProjection.class.php b/main/Criteria/Projections/DistinctCountProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/GroupByClassProjection.class.php b/main/Criteria/Projections/GroupByClassProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/GroupByPropertyProjection.class.php b/main/Criteria/Projections/GroupByPropertyProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/HavingProjection.class.php b/main/Criteria/Projections/HavingProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/MappableObjectProjection.class.php b/main/Criteria/Projections/MappableObjectProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/MaximalNumberProjection.class.php b/main/Criteria/Projections/MaximalNumberProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/MinimalNumberProjection.class.php b/main/Criteria/Projections/MinimalNumberProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/ObjectProjection.class.php b/main/Criteria/Projections/ObjectProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/ProjectionChain.class.php b/main/Criteria/Projections/ProjectionChain.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/PropertyProjection.class.php b/main/Criteria/Projections/PropertyProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/RowCountProjection.class.php b/main/Criteria/Projections/RowCountProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/Projections/SumProjection.class.php b/main/Criteria/Projections/SumProjection.class.php old mode 100644 new mode 100755 diff --git a/main/Criteria/PropertyPath.class.php b/main/Criteria/PropertyPath.class.php old mode 100644 new mode 100755 diff --git a/main/Crypto/Base62Utils.class.php b/main/Crypto/Base62Utils.class.php old mode 100644 new mode 100755 diff --git a/main/Crypto/Crypter.class.php b/main/Crypto/Crypter.class.php old mode 100644 new mode 100755 diff --git a/main/Crypto/CryptoFunctions.class.php b/main/Crypto/CryptoFunctions.class.php old mode 100644 new mode 100755 diff --git a/main/Crypto/DiffieHellmanKeyPair.class.php b/main/Crypto/DiffieHellmanKeyPair.class.php old mode 100644 new mode 100755 diff --git a/main/Crypto/DiffieHellmanParameters.class.php b/main/Crypto/DiffieHellmanParameters.class.php old mode 100644 new mode 100755 diff --git a/main/Crypto/KeyPair.class.php b/main/Crypto/KeyPair.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/BaseDAO.class.php b/main/DAOs/BaseDAO.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/DAOConnected.class.php b/main/DAOs/DAOConnected.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/FullTextDAO.class.php b/main/DAOs/FullTextDAO.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/GenericDAO.class.php b/main/DAOs/GenericDAO.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Handlers/ApcSegmentHandler.class.php b/main/DAOs/Handlers/ApcSegmentHandler.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Handlers/CacheSegmentHandler.class.php b/main/DAOs/Handlers/CacheSegmentHandler.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Handlers/FileSystemSegmentHandler.class.php b/main/DAOs/Handlers/FileSystemSegmentHandler.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Handlers/MessageSegmentHandler.class.php b/main/DAOs/Handlers/MessageSegmentHandler.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Handlers/OptimizerSegmentHandler.class.php b/main/DAOs/Handlers/OptimizerSegmentHandler.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Handlers/SegmentHandler.class.php b/main/DAOs/Handlers/SegmentHandler.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Handlers/SharedMemorySegmentHandler.class.php b/main/DAOs/Handlers/SharedMemorySegmentHandler.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Handlers/XCacheSegmentHandler.class.php b/main/DAOs/Handlers/XCacheSegmentHandler.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Handlers/eAcceleratorSegmentHandler.class.php b/main/DAOs/Handlers/eAcceleratorSegmentHandler.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/ProtoDAO.class.php b/main/DAOs/ProtoDAO.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/StorableDAO.class.php b/main/DAOs/StorableDAO.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Workers/BaseDaoWorker.class.php b/main/DAOs/Workers/BaseDaoWorker.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Workers/CacheDaoWorker.class.php b/main/DAOs/Workers/CacheDaoWorker.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Workers/CommonDaoWorker.class.php b/main/DAOs/Workers/CommonDaoWorker.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Workers/CustomDataScopedWorker.class.php b/main/DAOs/Workers/CustomDataScopedWorker.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Workers/DalayedDropDaoWorker.class.php b/main/DAOs/Workers/DalayedDropDaoWorker.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Workers/NullDaoWorker.class.php b/main/DAOs/Workers/NullDaoWorker.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Workers/SmartDaoWorker.class.php b/main/DAOs/Workers/SmartDaoWorker.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Workers/TransparentDaoWorker.class.php b/main/DAOs/Workers/TransparentDaoWorker.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Workers/VoodooDaoWorker.class.php b/main/DAOs/Workers/VoodooDaoWorker.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/DTOGetter.class.php b/main/EntityProto/Accessors/DTOGetter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/DTOSetter.class.php b/main/EntityProto/Accessors/DTOSetter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/DirectoryGetter.class.php b/main/EntityProto/Accessors/DirectoryGetter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/DirectoryMutator.class.php b/main/EntityProto/Accessors/DirectoryMutator.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/DirectorySetter.class.php b/main/EntityProto/Accessors/DirectorySetter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/FormExporter.class.php b/main/EntityProto/Accessors/FormExporter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/FormGetter.class.php b/main/EntityProto/Accessors/FormGetter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/FormHardenedSetter.class.php b/main/EntityProto/Accessors/FormHardenedSetter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/FormImporter.class.php b/main/EntityProto/Accessors/FormImporter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/FormMutator.class.php b/main/EntityProto/Accessors/FormMutator.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/FormSetter.class.php b/main/EntityProto/Accessors/FormSetter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/ObjectGetter.class.php b/main/EntityProto/Accessors/ObjectGetter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/ObjectSetter.class.php b/main/EntityProto/Accessors/ObjectSetter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/ScopeGetter.class.php b/main/EntityProto/Accessors/ScopeGetter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Accessors/ScopeSetter.class.php b/main/EntityProto/Accessors/ScopeSetter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/DTOBuilder.class.php b/main/EntityProto/Builders/DTOBuilder.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/DTOToFormImporter.class.php b/main/EntityProto/Builders/DTOToFormImporter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/DTOToScopeConverter.class.php b/main/EntityProto/Builders/DTOToScopeConverter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/DirectoryBuilder.class.php b/main/EntityProto/Builders/DirectoryBuilder.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/DirectoryToObjectBinder.class.php b/main/EntityProto/Builders/DirectoryToObjectBinder.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/FormBuilder.class.php b/main/EntityProto/Builders/FormBuilder.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/FormToObjectConverter.class.php b/main/EntityProto/Builders/FormToObjectConverter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/FormToScopeExporter.class.php b/main/EntityProto/Builders/FormToScopeExporter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/ObjectBuilder.class.php b/main/EntityProto/Builders/ObjectBuilder.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/ObjectToDTOConverter.class.php b/main/EntityProto/Builders/ObjectToDTOConverter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/ObjectToDirectoryBinder.class.php b/main/EntityProto/Builders/ObjectToDirectoryBinder.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/ObjectToFormConverter.class.php b/main/EntityProto/Builders/ObjectToFormConverter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/ObjectToFormSetter.class.php b/main/EntityProto/Builders/ObjectToFormSetter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/ObjectToObjectCast.class.php b/main/EntityProto/Builders/ObjectToObjectCast.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/Builders/ScopeToFormImporter.class.php b/main/EntityProto/Builders/ScopeToFormImporter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/DirectoryContext.class.php b/main/EntityProto/DirectoryContext.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/EntityProto.class.php b/main/EntityProto/EntityProto.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/PrototypedBuilder.class.php b/main/EntityProto/PrototypedBuilder.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/PrototypedEntity.class.php b/main/EntityProto/PrototypedEntity.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/PrototypedGetter.class.php b/main/EntityProto/PrototypedGetter.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/PrototypedMethodCaller.class.php b/main/EntityProto/PrototypedMethodCaller.class.php old mode 100644 new mode 100755 diff --git a/main/EntityProto/PrototypedSetter.class.php b/main/EntityProto/PrototypedSetter.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/AddCommand.class.php b/main/Flow/AddCommand.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/BaseEditor.class.php b/main/Flow/BaseEditor.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/CarefulCommand.class.php b/main/Flow/CarefulCommand.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/CarefulDatabaseRunner.class.php b/main/Flow/CarefulDatabaseRunner.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/CommandChain.class.php b/main/Flow/CommandChain.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/Controller.class.php b/main/Flow/Controller.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/ControllersCollection.class.php b/main/Flow/ControllersCollection.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/DecoratorController.class.php b/main/Flow/DecoratorController.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/DropCommand.class.php b/main/Flow/DropCommand.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/EditCommand.class.php b/main/Flow/EditCommand.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/EditorCommand.class.php b/main/Flow/EditorCommand.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/EditorController.class.php b/main/Flow/EditorController.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/ForbiddenCommand.class.php b/main/Flow/ForbiddenCommand.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/HandlerMapping.class.php b/main/Flow/HandlerMapping.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/HttpRequest.class.php b/main/Flow/HttpRequest.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/ImportCommand.class.php b/main/Flow/ImportCommand.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/MakeCommand.class.php b/main/Flow/MakeCommand.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/MethodMappedController.class.php b/main/Flow/MethodMappedController.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/Model.class.php b/main/Flow/Model.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/ModelAndView.class.php b/main/Flow/ModelAndView.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/MonolithicController.class.php b/main/Flow/MonolithicController.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/NullController.class.php b/main/Flow/NullController.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/PrototypedEditor.class.php b/main/Flow/PrototypedEditor.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/ProxyController.class.php b/main/Flow/ProxyController.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/SaveCommand.class.php b/main/Flow/SaveCommand.class.php old mode 100644 new mode 100755 diff --git a/main/Flow/TakeCommand.class.php b/main/Flow/TakeCommand.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Csv.class.php b/main/Markup/Csv.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/AtomChannelWorker.class.php b/main/Markup/Feed/AtomChannelWorker.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/AtomFeedFormat.class.php b/main/Markup/Feed/AtomFeedFormat.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/AtomItemWorker.class.php b/main/Markup/Feed/AtomItemWorker.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/FeedChannel.class.php b/main/Markup/Feed/FeedChannel.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/FeedChannelWorker.class.php b/main/Markup/Feed/FeedChannelWorker.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/FeedFormat.class.php b/main/Markup/Feed/FeedFormat.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/FeedItem.class.php b/main/Markup/Feed/FeedItem.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/FeedItemContent.class.php b/main/Markup/Feed/FeedItemContent.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/FeedItemContentType.class.php b/main/Markup/Feed/FeedItemContentType.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/FeedItemWorker.class.php b/main/Markup/Feed/FeedItemWorker.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/FeedReader.class.php b/main/Markup/Feed/FeedReader.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/RssChannelWorker.class.php b/main/Markup/Feed/RssChannelWorker.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/RssFeedFormat.class.php b/main/Markup/Feed/RssFeedFormat.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/RssItemWorker.class.php b/main/Markup/Feed/RssItemWorker.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/YandexRssFeedFormat.class.php b/main/Markup/Feed/YandexRssFeedFormat.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/YandexRssFeedItem.class.php b/main/Markup/Feed/YandexRssFeedItem.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Feed/YandexRssItemWorker.class.php b/main/Markup/Feed/YandexRssItemWorker.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Html/Cdata.class.php b/main/Markup/Html/Cdata.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Html/HtmlAssembler.class.php b/main/Markup/Html/HtmlAssembler.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Html/HtmlTokenizer.class.php b/main/Markup/Html/HtmlTokenizer.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Html/SgmlEndTag.class.php b/main/Markup/Html/SgmlEndTag.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Html/SgmlIgnoredTag.class.php b/main/Markup/Html/SgmlIgnoredTag.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Html/SgmlOpenTag.class.php b/main/Markup/Html/SgmlOpenTag.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Html/SgmlTag.class.php b/main/Markup/Html/SgmlTag.class.php old mode 100644 new mode 100755 diff --git a/main/Markup/Html/SgmlToken.class.php b/main/Markup/Html/SgmlToken.class.php old mode 100644 new mode 100755 diff --git a/main/Math/BigInteger.class.php b/main/Math/BigInteger.class.php old mode 100644 new mode 100755 diff --git a/main/Math/BigNumberFactory.class.php b/main/Math/BigNumberFactory.class.php old mode 100644 new mode 100755 diff --git a/main/Math/FileRandomSource.class.php b/main/Math/FileRandomSource.class.php old mode 100644 new mode 100755 diff --git a/main/Math/GmpBigInteger.class.php b/main/Math/GmpBigInteger.class.php old mode 100644 new mode 100755 diff --git a/main/Math/GmpBigIntegerFactory.class.php b/main/Math/GmpBigIntegerFactory.class.php old mode 100644 new mode 100755 diff --git a/main/Math/MathUtils.class.php b/main/Math/MathUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Math/MtRandomSource.class.php b/main/Math/MtRandomSource.class.php old mode 100644 new mode 100755 diff --git a/main/Math/RandomSource.class.php b/main/Math/RandomSource.class.php old mode 100644 new mode 100755 diff --git a/main/Math/TupleFunctor.class.php b/main/Math/TupleFunctor.class.php old mode 100644 new mode 100755 diff --git a/main/Messages/Interface/Message.class.php b/main/Messages/Interface/Message.class.php old mode 100644 new mode 100755 diff --git a/main/Messages/Interface/MessageQueue.class.php b/main/Messages/Interface/MessageQueue.class.php old mode 100644 new mode 100755 diff --git a/main/Messages/Interface/MessageQueueBrowser.class.php b/main/Messages/Interface/MessageQueueBrowser.class.php old mode 100644 new mode 100755 diff --git a/main/Messages/Interface/MessageQueueReceiver.class.php b/main/Messages/Interface/MessageQueueReceiver.class.php old mode 100644 new mode 100755 diff --git a/main/Messages/Interface/MessageQueueSender.class.php b/main/Messages/Interface/MessageQueueSender.class.php old mode 100644 new mode 100755 diff --git a/main/Messages/TextFileQueue.class.php b/main/Messages/TextFileQueue.class.php old mode 100644 new mode 100755 diff --git a/main/Messages/TextFileQueueBrowser.class.php b/main/Messages/TextFileQueueBrowser.class.php old mode 100644 new mode 100755 diff --git a/main/Messages/TextFileReceiver.class.php b/main/Messages/TextFileReceiver.class.php old mode 100644 new mode 100755 diff --git a/main/Messages/TextFileSender.class.php b/main/Messages/TextFileSender.class.php old mode 100644 new mode 100755 diff --git a/main/Messages/TextMessage.class.php b/main/Messages/TextMessage.class.php old mode 100644 new mode 100755 diff --git a/main/Monitoring/PinbaClient.class.php b/main/Monitoring/PinbaClient.class.php old mode 100644 new mode 100755 diff --git a/main/Monitoring/PinbedMemcached.class.php b/main/Monitoring/PinbedMemcached.class.php old mode 100644 new mode 100755 diff --git a/main/Monitoring/PinbedPeclMemcached.class.php b/main/Monitoring/PinbedPeclMemcached.class.php old mode 100644 new mode 100755 diff --git a/main/Monitoring/PinbedPgSQL.class.php b/main/Monitoring/PinbedPgSQL.class.php old mode 100644 new mode 100755 diff --git a/main/Net/GenericUri.class.php b/main/Net/GenericUri.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Http/Cookie.class.php b/main/Net/Http/Cookie.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Http/CookieCollection.class.php b/main/Net/Http/CookieCollection.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Http/CurlHttpClient.class.php b/main/Net/Http/CurlHttpClient.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Http/CurlHttpResponse.class.php b/main/Net/Http/CurlHttpResponse.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Http/HeaderParser.class.php b/main/Net/Http/HeaderParser.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Http/HeaderUtils.class.php b/main/Net/Http/HeaderUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Http/HttpClient.class.php b/main/Net/Http/HttpClient.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Http/HttpMethod.class.php b/main/Net/Http/HttpMethod.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Http/HttpResponse.class.php b/main/Net/Http/HttpResponse.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Http/HttpStatus.class.php b/main/Net/Http/HttpStatus.class.php old mode 100644 new mode 100755 diff --git a/main/Net/HttpUrl.class.php b/main/Net/HttpUrl.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Ip/IpAddress.class.php b/main/Net/Ip/IpAddress.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Ip/IpNetwork.class.php b/main/Net/Ip/IpNetwork.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Ip/IpRange.class.php b/main/Net/Ip/IpRange.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Ip/IpUtils.class.php b/main/Net/Ip/IpUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Mail/Mail.class.php b/main/Net/Mail/Mail.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Mail/MailAddress.class.php b/main/Net/Mail/MailAddress.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Mail/MailBuilder.class.php b/main/Net/Mail/MailBuilder.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Mail/MailEncoding.class.php b/main/Net/Mail/MailEncoding.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Mail/MailException.class.php b/main/Net/Mail/MailException.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Mail/MailNotSentException.class.php b/main/Net/Mail/MailNotSentException.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Mail/MimeMail.class.php b/main/Net/Mail/MimeMail.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Mail/MimePart.class.php b/main/Net/Mail/MimePart.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Soap/DTOClass.class.php b/main/Net/Soap/DTOClass.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Soap/DTOMessage.class.php b/main/Net/Soap/DTOMessage.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Soap/PrototypedSoapClient.class.php b/main/Net/Soap/PrototypedSoapClient.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Url.class.php b/main/Net/Url.class.php old mode 100644 new mode 100755 diff --git a/main/Net/Urn.class.php b/main/Net/Urn.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Expressions/OqlInExpression.class.php b/main/OQL/Expressions/OqlInExpression.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Expressions/OqlOrderByExpression.class.php b/main/OQL/Expressions/OqlOrderByExpression.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Expressions/OqlPrefixMinusExpression.class.php b/main/OQL/Expressions/OqlPrefixMinusExpression.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Expressions/OqlQueryExpression.class.php b/main/OQL/Expressions/OqlQueryExpression.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Expressions/OqlQueryParameter.class.php b/main/OQL/Expressions/OqlQueryParameter.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/OQL.class.php b/main/OQL/OQL.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Parsers/OqlGroupByParser.class.php b/main/OQL/Parsers/OqlGroupByParser.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Parsers/OqlHavingParser.class.php b/main/OQL/Parsers/OqlHavingParser.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Parsers/OqlOrderByParser.class.php b/main/OQL/Parsers/OqlOrderByParser.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Parsers/OqlParser.class.php b/main/OQL/Parsers/OqlParser.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Parsers/OqlSelectParser.class.php b/main/OQL/Parsers/OqlSelectParser.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Parsers/OqlSelectPropertiesParser.class.php b/main/OQL/Parsers/OqlSelectPropertiesParser.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Parsers/OqlToken.class.php b/main/OQL/Parsers/OqlToken.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Parsers/OqlTokenizer.class.php b/main/OQL/Parsers/OqlTokenizer.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Parsers/OqlWhereParser.class.php b/main/OQL/Parsers/OqlWhereParser.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Statements/OqlHavingClause.class.php b/main/OQL/Statements/OqlHavingClause.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Statements/OqlOrderByClause.class.php b/main/OQL/Statements/OqlOrderByClause.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Statements/OqlProjectionClause.class.php b/main/OQL/Statements/OqlProjectionClause.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Statements/OqlQuery.class.php b/main/OQL/Statements/OqlQuery.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Statements/OqlQueryClause.class.php b/main/OQL/Statements/OqlQueryClause.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Statements/OqlQueryExpressionClause.class.php b/main/OQL/Statements/OqlQueryExpressionClause.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Statements/OqlQueryListedClause.class.php b/main/OQL/Statements/OqlQueryListedClause.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Statements/OqlSelectPropertiesClause.class.php b/main/OQL/Statements/OqlSelectPropertiesClause.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Statements/OqlSelectQuery.class.php b/main/OQL/Statements/OqlSelectQuery.class.php old mode 100644 new mode 100755 diff --git a/main/OQL/Statements/OqlWhereClause.class.php b/main/OQL/Statements/OqlWhereClause.class.php old mode 100644 new mode 100755 diff --git a/main/OpenId/OpenIdConsumer.class.php b/main/OpenId/OpenIdConsumer.class.php old mode 100644 new mode 100755 diff --git a/main/OpenId/OpenIdConsumerAssociation.class.php b/main/OpenId/OpenIdConsumerAssociation.class.php old mode 100644 new mode 100755 diff --git a/main/OpenId/OpenIdConsumerAssociationManager.class.php b/main/OpenId/OpenIdConsumerAssociationManager.class.php old mode 100644 new mode 100755 diff --git a/main/OpenId/OpenIdConsumerCancel.class.php b/main/OpenId/OpenIdConsumerCancel.class.php old mode 100644 new mode 100755 diff --git a/main/OpenId/OpenIdConsumerFail.class.php b/main/OpenId/OpenIdConsumerFail.class.php old mode 100644 new mode 100755 diff --git a/main/OpenId/OpenIdConsumerPositive.class.php b/main/OpenId/OpenIdConsumerPositive.class.php old mode 100644 new mode 100755 diff --git a/main/OpenId/OpenIdConsumerResult.class.php b/main/OpenId/OpenIdConsumerResult.class.php old mode 100644 new mode 100755 diff --git a/main/OpenId/OpenIdConsumerSetupRequired.class.php b/main/OpenId/OpenIdConsumerSetupRequired.class.php old mode 100644 new mode 100755 diff --git a/main/OpenId/OpenIdCredentials.class.php b/main/OpenId/OpenIdCredentials.class.php old mode 100644 new mode 100755 diff --git a/main/OpenId/OpenIdException.class.php b/main/OpenId/OpenIdException.class.php old mode 100644 new mode 100755 diff --git a/main/OpenId/OpenIdExtension.class.php b/main/OpenId/OpenIdExtension.class.php old mode 100644 new mode 100755 diff --git a/main/OpenId/OpenIdExtensionAttributeExchange.class.php b/main/OpenId/OpenIdExtensionAttributeExchange.class.php old mode 100644 new mode 100755 diff --git a/main/OpenId/OpenIdExtensionSreg.class.php b/main/OpenId/OpenIdExtensionSreg.class.php old mode 100644 new mode 100755 diff --git a/main/SPL/AbstractList.class.php b/main/SPL/AbstractList.class.php old mode 100644 new mode 100755 diff --git a/main/SPL/IndexedList.class.php b/main/SPL/IndexedList.class.php old mode 100644 new mode 100755 diff --git a/main/SPL/PlainList.class.php b/main/SPL/PlainList.class.php old mode 100644 new mode 100755 diff --git a/main/SPL/SimplifiedArrayAccess.class.php b/main/SPL/SimplifiedArrayAccess.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/CleanRedirectView.class.php b/main/UI/View/CleanRedirectView.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/DebugPhpView.class.php b/main/UI/View/DebugPhpView.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/EmptyGifView.class.php b/main/UI/View/EmptyGifView.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/EmptyView.class.php b/main/UI/View/EmptyView.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/HttpErrorView.class.php b/main/UI/View/HttpErrorView.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/JsonView.class.php b/main/UI/View/JsonView.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/MultiPrefixPhpViewResolver.class.php b/main/UI/View/MultiPrefixPhpViewResolver.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/PartViewer.class.php b/main/UI/View/PartViewer.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/PhpViewResolver.class.php b/main/UI/View/PhpViewResolver.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/RedirectToView.class.php b/main/UI/View/RedirectToView.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/RedirectView.class.php b/main/UI/View/RedirectView.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/SimplePhpView.class.php b/main/UI/View/SimplePhpView.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/View.class.php b/main/UI/View/View.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/ViewResolver.class.php b/main/UI/View/ViewResolver.class.php old mode 100644 new mode 100755 diff --git a/main/UnifiedContainer/ManyToManyLinked.class.php b/main/UnifiedContainer/ManyToManyLinked.class.php old mode 100644 new mode 100755 diff --git a/main/UnifiedContainer/ManyToManyLinkedFull.class.php b/main/UnifiedContainer/ManyToManyLinkedFull.class.php old mode 100644 new mode 100755 diff --git a/main/UnifiedContainer/ManyToManyLinkedLazy.class.php b/main/UnifiedContainer/ManyToManyLinkedLazy.class.php old mode 100644 new mode 100755 diff --git a/main/UnifiedContainer/ManyToManyLinkedWorker.class.php b/main/UnifiedContainer/ManyToManyLinkedWorker.class.php old mode 100644 new mode 100755 diff --git a/main/UnifiedContainer/OneToManyLinked.class.php b/main/UnifiedContainer/OneToManyLinked.class.php old mode 100644 new mode 100755 diff --git a/main/UnifiedContainer/OneToManyLinkedFull.class.php b/main/UnifiedContainer/OneToManyLinkedFull.class.php old mode 100644 new mode 100755 diff --git a/main/UnifiedContainer/OneToManyLinkedLazy.class.php b/main/UnifiedContainer/OneToManyLinkedLazy.class.php old mode 100644 new mode 100755 diff --git a/main/UnifiedContainer/OneToManyLinkedWorker.class.php b/main/UnifiedContainer/OneToManyLinkedWorker.class.php old mode 100644 new mode 100755 diff --git a/main/UnifiedContainer/UnifiedContainer.class.php b/main/UnifiedContainer/UnifiedContainer.class.php old mode 100644 new mode 100755 diff --git a/main/UnifiedContainer/UnifiedContainerWorker.class.php b/main/UnifiedContainer/UnifiedContainerWorker.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQP.class.php b/main/Utils/AMQP/AMQP.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPBaseChannel.class.php b/main/Utils/AMQP/AMQPBaseChannel.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPBaseConfig.class.php b/main/Utils/AMQP/AMQPBaseConfig.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPBaseMessage.class.php b/main/Utils/AMQP/AMQPBaseMessage.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPBitmaskResolver.class.php b/main/Utils/AMQP/AMQPBitmaskResolver.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPChannelInterface.class.php b/main/Utils/AMQP/AMQPChannelInterface.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPConsumer.class.php b/main/Utils/AMQP/AMQPConsumer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPCredentials.class.php b/main/Utils/AMQP/AMQPCredentials.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPDefaultConsumer.class.php b/main/Utils/AMQP/AMQPDefaultConsumer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPExchangeConfig.class.php b/main/Utils/AMQP/AMQPExchangeConfig.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPExchangeType.class.php b/main/Utils/AMQP/AMQPExchangeType.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPIncomingMessage.class.php b/main/Utils/AMQP/AMQPIncomingMessage.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPOutgoingMessage.class.php b/main/Utils/AMQP/AMQPOutgoingMessage.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPPool.class.php b/main/Utils/AMQP/AMQPPool.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPQueueConfig.class.php b/main/Utils/AMQP/AMQPQueueConfig.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/AMQPQueueConsumer.class.php b/main/Utils/AMQP/AMQPQueueConsumer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/Exceptions/AMQPServerConnectionException.class.php b/main/Utils/AMQP/Exceptions/AMQPServerConnectionException.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/Exceptions/AMQPServerException.class.php b/main/Utils/AMQP/Exceptions/AMQPServerException.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/Pecl/AMQPPecl.class.php b/main/Utils/AMQP/Pecl/AMQPPecl.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/Pecl/AMQPPeclBaseBitmask.class.php b/main/Utils/AMQP/Pecl/AMQPPeclBaseBitmask.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/Pecl/AMQPPeclChannel.class.php b/main/Utils/AMQP/Pecl/AMQPPeclChannel.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/Pecl/AMQPPeclExchangeBitmask.class.php b/main/Utils/AMQP/Pecl/AMQPPeclExchangeBitmask.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/Pecl/AMQPPeclOutgoingMessageBitmask.class.php b/main/Utils/AMQP/Pecl/AMQPPeclOutgoingMessageBitmask.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/AMQP/Pecl/AMQPPeclQueueBitmask.class.php b/main/Utils/AMQP/Pecl/AMQPPeclQueueBitmask.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Archivers/ArchiverException.class.php b/main/Utils/Archivers/ArchiverException.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Archivers/FileArchive.class.php b/main/Utils/Archivers/FileArchive.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Archivers/InfoZipArchive.class.php b/main/Utils/Archivers/InfoZipArchive.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Archivers/TarArchive.class.php b/main/Utils/Archivers/TarArchive.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/ArrayUtils.class.php b/main/Utils/ArrayUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/ClassUtils.class.php b/main/Utils/ClassUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/CommandLine/ArgumentParser.class.php b/main/Utils/CommandLine/ArgumentParser.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/CommandLine/FormToArgumentsConverter.class.php b/main/Utils/CommandLine/FormToArgumentsConverter.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/CommonDoctypeDeclaration.class.php b/main/Utils/CommonDoctypeDeclaration.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/ContentTypeHeader.class.php b/main/Utils/ContentTypeHeader.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/CustomizableDaoSynchronizer.class.php b/main/Utils/CustomizableDaoSynchronizer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/CyrillicPairs.class.php b/main/Utils/CyrillicPairs.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/DaoIterator.class.php b/main/Utils/DaoIterator.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/DaoMoveHelper.class.php b/main/Utils/DaoMoveHelper.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/DaoSynchronizer.class.php b/main/Utils/DaoSynchronizer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/DaoUtils.class.php b/main/Utils/DaoUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/DateUtils.class.php b/main/Utils/DateUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/DebugUtils.class.php b/main/Utils/DebugUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/DoctypeDeclaration.class.php b/main/Utils/DoctypeDeclaration.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/FileUtils.class.php b/main/Utils/FileUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/FullTextUtils.class.php b/main/Utils/FullTextUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/IO/BufferedInputStream.class.php b/main/Utils/IO/BufferedInputStream.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/IO/BufferedReader.class.php b/main/Utils/IO/BufferedReader.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/IO/FileInputStream.class.php b/main/Utils/IO/FileInputStream.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/IO/FileOutputStream.class.php b/main/Utils/IO/FileOutputStream.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/IO/FileReader.class.php b/main/Utils/IO/FileReader.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/IO/InputStream.class.php b/main/Utils/IO/InputStream.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/IO/OutputStream.class.php b/main/Utils/IO/OutputStream.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/IO/Reader.class.php b/main/Utils/IO/Reader.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/IO/Socket.class.php b/main/Utils/IO/Socket.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/IO/SocketInputStream.class.php b/main/Utils/IO/SocketInputStream.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/IO/SocketOutputStream.class.php b/main/Utils/IO/SocketOutputStream.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/IO/StringInputStream.class.php b/main/Utils/IO/StringInputStream.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/IO/StringReader.class.php b/main/Utils/IO/StringReader.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Logging/BaseLogger.class.php b/main/Utils/Logging/BaseLogger.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Logging/LogLevel.class.php b/main/Utils/Logging/LogLevel.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Logging/LogRecord.class.php b/main/Utils/Logging/LogRecord.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Logging/StreamLogger.class.php b/main/Utils/Logging/StreamLogger.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/LogicUtils.class.php b/main/Utils/LogicUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Mobile/MobileRequestDetector.class.php b/main/Utils/Mobile/MobileRequestDetector.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Mobile/MobileUtils.class.php b/main/Utils/Mobile/MobileUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Routers/Router.class.php b/main/Utils/Routers/Router.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Routers/RouterBaseRule.class.php b/main/Utils/Routers/RouterBaseRule.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Routers/RouterChainRule.class.php b/main/Utils/Routers/RouterChainRule.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Routers/RouterException.class.php b/main/Utils/Routers/RouterException.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Routers/RouterHostnameRule.class.php b/main/Utils/Routers/RouterHostnameRule.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Routers/RouterRegexpRule.class.php b/main/Utils/Routers/RouterRegexpRule.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Routers/RouterRewrite.class.php b/main/Utils/Routers/RouterRewrite.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Routers/RouterRule.class.php b/main/Utils/Routers/RouterRule.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Routers/RouterStaticRule.class.php b/main/Utils/Routers/RouterStaticRule.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Routers/RouterTransparentRule.class.php b/main/Utils/Routers/RouterTransparentRule.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/Routers/RouterUrlHelper.class.php b/main/Utils/Routers/RouterUrlHelper.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/RussianTextUtils.class.php b/main/Utils/RussianTextUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/SortHelper.class.php b/main/Utils/SortHelper.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/SynchronizableObject.class.php b/main/Utils/SynchronizableObject.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TextUtils.class.php b/main/Utils/TextUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TidyValidator.class.php b/main/Utils/TidyValidator.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/BackgroundDrawer.class.php b/main/Utils/TuringTest/BackgroundDrawer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/CellBackgroundDrawer.class.php b/main/Utils/TuringTest/CellBackgroundDrawer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/CircleBackgroundDrawer.class.php b/main/Utils/TuringTest/CircleBackgroundDrawer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/CodeGenerator.class.php b/main/Utils/TuringTest/CodeGenerator.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/Color.class.php b/main/Utils/TuringTest/Color.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/ColorArray.class.php b/main/Utils/TuringTest/ColorArray.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/CurvedStringDrawer.class.php b/main/Utils/TuringTest/CurvedStringDrawer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/Drawer.class.php b/main/Utils/TuringTest/Drawer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/ErrorDrawer.class.php b/main/Utils/TuringTest/ErrorDrawer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/InclinedStringDrawer.class.php b/main/Utils/TuringTest/InclinedStringDrawer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/LinearStringDrawer.class.php b/main/Utils/TuringTest/LinearStringDrawer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/RandomLinesBackgroundDrawer.class.php b/main/Utils/TuringTest/RandomLinesBackgroundDrawer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/TextDrawer.class.php b/main/Utils/TuringTest/TextDrawer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/TuringImage.class.php b/main/Utils/TuringTest/TuringImage.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TuringTest/WavesBackgroundDrawer.class.php b/main/Utils/TuringTest/WavesBackgroundDrawer.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/TypesUtils.class.php b/main/Utils/TypesUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/WebMoneyUtils.class.php b/main/Utils/WebMoneyUtils.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/XmlRpcClient.class.php b/main/Utils/XmlRpcClient.class.php old mode 100644 new mode 100755 diff --git a/meta/builders/AutoClassBuilder.class.php b/meta/builders/AutoClassBuilder.class.php old mode 100644 new mode 100755 diff --git a/meta/builders/AutoDaoBuilder.class.php b/meta/builders/AutoDaoBuilder.class.php old mode 100644 new mode 100755 diff --git a/meta/builders/AutoProtoClassBuilder.class.php b/meta/builders/AutoProtoClassBuilder.class.php old mode 100644 new mode 100755 diff --git a/meta/builders/BaseBuilder.class.php b/meta/builders/BaseBuilder.class.php old mode 100644 new mode 100755 diff --git a/meta/builders/BusinessClassBuilder.class.php b/meta/builders/BusinessClassBuilder.class.php old mode 100644 new mode 100755 diff --git a/meta/builders/ContainerClassBuilder.class.php b/meta/builders/ContainerClassBuilder.class.php old mode 100644 new mode 100755 diff --git a/meta/builders/DaoBuilder.class.php b/meta/builders/DaoBuilder.class.php old mode 100644 new mode 100755 diff --git a/meta/builders/DictionaryDaoBuilder.class.php b/meta/builders/DictionaryDaoBuilder.class.php old mode 100644 new mode 100755 diff --git a/meta/builders/EnumerationClassBuilder.class.php b/meta/builders/EnumerationClassBuilder.class.php old mode 100644 new mode 100755 diff --git a/meta/builders/OnceBuilder.class.php b/meta/builders/OnceBuilder.class.php old mode 100644 new mode 100755 diff --git a/meta/builders/ProtoClassBuilder.class.php b/meta/builders/ProtoClassBuilder.class.php old mode 100644 new mode 100755 diff --git a/meta/builders/SchemaBuilder.class.php b/meta/builders/SchemaBuilder.class.php old mode 100644 new mode 100755 diff --git a/meta/classes/ColoredTextOutput.class.php b/meta/classes/ColoredTextOutput.class.php old mode 100644 new mode 100755 diff --git a/meta/classes/ConsoleMode.class.php b/meta/classes/ConsoleMode.class.php old mode 100644 new mode 100755 diff --git a/meta/classes/Format.class.php b/meta/classes/Format.class.php old mode 100644 new mode 100755 diff --git a/meta/classes/MetaClass.class.php b/meta/classes/MetaClass.class.php old mode 100644 new mode 100755 diff --git a/meta/classes/MetaClassProperty.class.php b/meta/classes/MetaClassProperty.class.php old mode 100644 new mode 100755 diff --git a/meta/classes/MetaClassType.class.php b/meta/classes/MetaClassType.class.php old mode 100644 new mode 100755 diff --git a/meta/classes/MetaConfiguration.class.php b/meta/classes/MetaConfiguration.class.php old mode 100644 new mode 100755 diff --git a/meta/classes/MetaOutput.class.php b/meta/classes/MetaOutput.class.php old mode 100644 new mode 100755 diff --git a/meta/classes/MetaRelation.class.php b/meta/classes/MetaRelation.class.php old mode 100644 new mode 100755 diff --git a/meta/classes/TextOutput.class.php b/meta/classes/TextOutput.class.php old mode 100644 new mode 100755 diff --git a/meta/dtd/meta.dtd b/meta/dtd/meta.dtd old mode 100644 new mode 100755 diff --git a/meta/internal.xml b/meta/internal.xml old mode 100644 new mode 100755 diff --git a/meta/patterns/AbstractClassPattern.class.php b/meta/patterns/AbstractClassPattern.class.php old mode 100644 new mode 100755 diff --git a/meta/patterns/BasePattern.class.php b/meta/patterns/BasePattern.class.php old mode 100644 new mode 100755 diff --git a/meta/patterns/DictionaryClassPattern.class.php b/meta/patterns/DictionaryClassPattern.class.php old mode 100644 new mode 100755 diff --git a/meta/patterns/EnumerationClassPattern.class.php b/meta/patterns/EnumerationClassPattern.class.php old mode 100644 new mode 100755 diff --git a/meta/patterns/GenerationPattern.class.php b/meta/patterns/GenerationPattern.class.php old mode 100644 new mode 100755 diff --git a/meta/patterns/InternalClassPattern.class.php b/meta/patterns/InternalClassPattern.class.php old mode 100644 new mode 100755 diff --git a/meta/patterns/SpookedClassPattern.class.php b/meta/patterns/SpookedClassPattern.class.php old mode 100644 new mode 100755 diff --git a/meta/patterns/SpookedEnumerationPattern.class.php b/meta/patterns/SpookedEnumerationPattern.class.php old mode 100644 new mode 100755 diff --git a/meta/patterns/StraightMappingPattern.class.php b/meta/patterns/StraightMappingPattern.class.php old mode 100644 new mode 100755 diff --git a/meta/patterns/ValueObjectPattern.class.php b/meta/patterns/ValueObjectPattern.class.php old mode 100644 new mode 100755 diff --git a/meta/types/BasePropertyType.class.php b/meta/types/BasePropertyType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/BigIntegerType.class.php b/meta/types/BigIntegerType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/BinaryType.class.php b/meta/types/BinaryType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/BooleanType.class.php b/meta/types/BooleanType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/DateRangeType.class.php b/meta/types/DateRangeType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/DateType.class.php b/meta/types/DateType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/DoubleType.class.php b/meta/types/DoubleType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/FixedLengthStringType.class.php b/meta/types/FixedLengthStringType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/FloatType.class.php b/meta/types/FloatType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/HstoreType.class.php b/meta/types/HstoreType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/HttpUrlType.class.php b/meta/types/HttpUrlType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/InetType.class.php b/meta/types/InetType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/IntegerType.class.php b/meta/types/IntegerType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/InternalType.class.php b/meta/types/InternalType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/IpAddressType.class.php b/meta/types/IpAddressType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/IpRangeType.class.php b/meta/types/IpRangeType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/NumericType.class.php b/meta/types/NumericType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/ObjectType.class.php b/meta/types/ObjectType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/RangeType.class.php b/meta/types/RangeType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/SmallIntegerType.class.php b/meta/types/SmallIntegerType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/StringType.class.php b/meta/types/StringType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/TimeType.class.php b/meta/types/TimeType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/TimestampRangeType.class.php b/meta/types/TimestampRangeType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/TimestampType.class.php b/meta/types/TimestampType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/UnsignedBigIntegerType.class.php b/meta/types/UnsignedBigIntegerType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/UnsignedIntegerType.class.php b/meta/types/UnsignedIntegerType.class.php old mode 100644 new mode 100755 diff --git a/meta/types/UnsignedSmallIntegerType.class.php b/meta/types/UnsignedSmallIntegerType.class.php old mode 100644 new mode 100755 diff --git a/misc/Autoloader.inc.php b/misc/Autoloader.inc.php old mode 100644 new mode 100755 diff --git a/misc/BaseException.inc.php b/misc/BaseException.inc.php old mode 100644 new mode 100755 diff --git a/test/AllTests.php b/test/AllTests.php old mode 100644 new mode 100755 diff --git a/test/config.inc.php.tpl b/test/config.inc.php.tpl old mode 100644 new mode 100755 diff --git a/test/core/AggregateCacheTest.class.php b/test/core/AggregateCacheTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/AssertTest.class.php b/test/core/AssertTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/BaseCachesTest.class.php b/test/core/BaseCachesTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/CalendarDayTest.class.php b/test/core/CalendarDayTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/DateRangeTest.class.php b/test/core/DateRangeTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/DateTest.class.php b/test/core/DateTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/DeleteQueryTest.class.php b/test/core/DeleteQueryTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/FiltersTest.class.php b/test/core/FiltersTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/FormPrimitivesDateTest.class.php b/test/core/FormPrimitivesDateTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/FormTest.class.php b/test/core/FormTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/IntervalUnitTest.class.php b/test/core/IntervalUnitTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/Ip4ContainsExpressionTest.class.php b/test/core/Ip4ContainsExpressionTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/LockerTest.class.php b/test/core/LockerTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/LogicTest.class.php b/test/core/LogicTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/PrimitiveAliasTest.class.php b/test/core/PrimitiveAliasTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/PrimitiveClassTest.class.php b/test/core/PrimitiveClassTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/PrimitiveDateRangeTest.class.php b/test/core/PrimitiveDateRangeTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/PrimitiveEnumerationTest.class.php b/test/core/PrimitiveEnumerationTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/PrimitiveHstoreTest.class.php b/test/core/PrimitiveHstoreTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/PrimitiveIdentifierTest.class.php b/test/core/PrimitiveIdentifierTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/PrimitiveInetTest.class.php b/test/core/PrimitiveInetTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/PrimitiveIpTest.class.php b/test/core/PrimitiveIpTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/PrimitiveNumberTest.class.php b/test/core/PrimitiveNumberTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/PrimitiveStringTest.class.php b/test/core/PrimitiveStringTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/PrimitiveTimeTest.class.php b/test/core/PrimitiveTimeTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/PrimitiveTimestampTest.class.php b/test/core/PrimitiveTimestampTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/SingletonTest.class.php b/test/core/SingletonTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/TimestampTest.class.php b/test/core/TimestampTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/TruncateQueryTest.class.php b/test/core/TruncateQueryTest.class.php old mode 100644 new mode 100755 diff --git a/test/core/UnionTest.class.php b/test/core/UnionTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Base62UtilsTest.class.php b/test/main/Base62UtilsTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/ClassUtilsTest.class.php b/test/main/ClassUtilsTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/ComparatorTest.class.php b/test/main/ComparatorTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/CriteriaTest.class.php b/test/main/CriteriaTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/CrypterTest.class.php b/test/main/CrypterTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/CryptoTest.class.php b/test/main/CryptoTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/CsvTest.class.php b/test/main/CsvTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/DateUtilsTest.class.php b/test/main/DateUtilsTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/EntityProtoConvertersTest.class.php b/test/main/EntityProtoConvertersTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/EnumerationTest.class.php b/test/main/EnumerationTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/FeedReaderTest.class.php b/test/main/FeedReaderTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/FloatRangeTest.class.php b/test/main/FloatRangeTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/GenericUriTest.class.php b/test/main/GenericUriTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/GoogleChartTest.class.php b/test/main/GoogleChartTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/HeaderParserTest.class.php b/test/main/HeaderParserTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/HttpUtilsTest.class.php b/test/main/HttpUtilsTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Ip/IpAddressTest.class.php b/test/main/Ip/IpAddressTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Ip/IpBaseRangeTest.class.php b/test/main/Ip/IpBaseRangeTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Ip/IpNetworkTest.class.php b/test/main/Ip/IpNetworkTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Ip/IpUtilsTest.class.php b/test/main/Ip/IpUtilsTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/JsonViewTest.class.php b/test/main/JsonViewTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/MathTest.class.php b/test/main/MathTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/MathUtilsTest.class.php b/test/main/MathUtilsTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/MessagesTest.class.php b/test/main/MessagesTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/MimeMailTest.class.php b/test/main/MimeMailTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Net/CookieTest.class.php b/test/main/Net/CookieTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Net/MailTest.class.php b/test/main/Net/MailTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/OpenIdTest.class.php b/test/main/OpenIdTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/OqlSelectClauseTest.class.php b/test/main/OqlSelectClauseTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/OqlSelectTest.class.php b/test/main/OqlSelectTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/OqlTokenizerTest.class.php b/test/main/OqlTokenizerTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/OsqlDeleteTest.class.php b/test/main/OsqlDeleteTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/OsqlInsertTest.class.php b/test/main/OsqlInsertTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/OsqlReturningTest.class.php b/test/main/OsqlReturningTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/OsqlSelectTest.class.php b/test/main/OsqlSelectTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/PostgresDialectTest.class.php b/test/main/PostgresDialectTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/RangeTest.class.php b/test/main/RangeTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/TextUtilsTest.class.php b/test/main/TextUtilsTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Utils/AMQP/AMQPPeclTest.class.php b/test/main/Utils/AMQP/AMQPPeclTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Utils/ArrayUtilsTest.class.php b/test/main/Utils/ArrayUtilsTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Utils/FileUtilsTest.class.php b/test/main/Utils/FileUtilsTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Utils/Routers/RouterBaseRuleTest.class.php b/test/main/Utils/Routers/RouterBaseRuleTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Utils/Routers/RouterChainRuleTest.class.php b/test/main/Utils/Routers/RouterChainRuleTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Utils/Routers/RouterHostnameRuleTest.class.php b/test/main/Utils/Routers/RouterHostnameRuleTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Utils/Routers/RouterRegexpRuleTest.class.php b/test/main/Utils/Routers/RouterRegexpRuleTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Utils/Routers/RouterRewriteTest.class.php b/test/main/Utils/Routers/RouterRewriteTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Utils/Routers/RouterStaticRuleTest.class.php b/test/main/Utils/Routers/RouterStaticRuleTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Utils/Routers/RouterTransparentRuleTest.class.php b/test/main/Utils/Routers/RouterTransparentRuleTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Utils/SocketTest.class.php b/test/main/Utils/SocketTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Utils/TypesUtilsTest.class.php b/test/main/Utils/TypesUtilsTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/Utils/WebMoneyUtilsTest.class.php b/test/main/Utils/WebMoneyUtilsTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/ViewTest.class.php b/test/main/ViewTest.class.php old mode 100644 new mode 100755 diff --git a/test/main/data/directory/contents b/test/main/data/directory/contents old mode 100644 new mode 100755 diff --git a/test/main/data/directory/inner/textField b/test/main/data/directory/inner/textField old mode 100644 new mode 100755 diff --git a/test/main/data/directory/textField b/test/main/data/directory/textField old mode 100644 new mode 100755 diff --git a/test/main/data/feedReader/atom_v1_0.xml b/test/main/data/feedReader/atom_v1_0.xml old mode 100644 new mode 100755 diff --git a/test/main/data/feedReader/news.xml b/test/main/data/feedReader/news.xml old mode 100644 new mode 100755 diff --git a/test/main/data/feedReader/yandex_rss.xml b/test/main/data/feedReader/yandex_rss.xml old mode 100644 new mode 100755 diff --git a/test/main/data/mimeMail/encodedBody.txt b/test/main/data/mimeMail/encodedBody.txt old mode 100644 new mode 100755 diff --git a/test/main/data/mimeMail/headers.txt b/test/main/data/mimeMail/headers.txt old mode 100644 new mode 100755 diff --git a/test/main/data/mimeMail/message.html b/test/main/data/mimeMail/message.html old mode 100644 new mode 100755 diff --git a/test/main/data/mimeMail/picture.jpg b/test/main/data/mimeMail/picture.jpg old mode 100644 new mode 100755 diff --git a/test/main/data/unicode/utf16.txt b/test/main/data/unicode/utf16.txt old mode 100644 new mode 100755 diff --git a/test/main/data/unicode/utf16be.txt b/test/main/data/unicode/utf16be.txt old mode 100644 new mode 100755 diff --git a/test/main/data/unicode/utf16le.txt b/test/main/data/unicode/utf16le.txt old mode 100644 new mode 100755 diff --git a/test/main/data/unicode/utf8.txt b/test/main/data/unicode/utf8.txt old mode 100644 new mode 100755 diff --git a/test/main/data/urls/.._.._.._.._g.dump b/test/main/data/urls/.._.._.._.._g.dump old mode 100644 new mode 100755 diff --git a/test/main/data/urls/.dump b/test/main/data/urls/.dump old mode 100644 new mode 100755 diff --git a/test/main/data/urls/parser.dump b/test/main/data/urls/parser.dump old mode 100644 new mode 100755 diff --git a/test/main/data/views/testPartView.tpl.html b/test/main/data/views/testPartView.tpl.html old mode 100644 new mode 100755 diff --git a/test/main/data/views/testView.tpl.html b/test/main/data/views/testView.tpl.html old mode 100644 new mode 100755 diff --git a/test/main/data/views/testViewToString.tpl.html b/test/main/data/views/testViewToString.tpl.html old mode 100644 new mode 100755 diff --git a/test/meta/config.inc.php b/test/meta/config.inc.php old mode 100644 new mode 100755 diff --git a/test/meta/config.meta.xml b/test/meta/config.meta.xml old mode 100644 new mode 100755 diff --git a/test/misc/DAOTest.class.php b/test/misc/DAOTest.class.php old mode 100644 new mode 100755 diff --git a/test/misc/DBTestPool.class.php b/test/misc/DBTestPool.class.php old mode 100644 new mode 100755 diff --git a/test/misc/ServerVarUtils.class.php b/test/misc/ServerVarUtils.class.php old mode 100644 new mode 100755 diff --git a/test/misc/TestCase.class.php b/test/misc/TestCase.class.php old mode 100644 new mode 100755 diff --git a/test/misc/TestTables.class.php b/test/misc/TestTables.class.php old mode 100644 new mode 100755 From 08d61d300dfac71be2cb14cac688f46fbf8ca581 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Mon, 16 Apr 2012 23:59:15 +0400 Subject: [PATCH 069/418] global config fix --- global.inc.php.tpl | 1 - 1 file changed, 1 deletion(-) diff --git a/global.inc.php.tpl b/global.inc.php.tpl index 42af288aae..336f45415e 100755 --- a/global.inc.php.tpl +++ b/global.inc.php.tpl @@ -105,7 +105,6 @@ .ONPHP_CORE_PATH.'OSQL' .PATH_SEPARATOR .ONPHP_CORE_PATH.'NoSQL' .PATH_SEPARATOR - .ONPHP_CORE_PATH.'NoSQL'.DIRECTORY_SEPARATOR.'Riak'.PATH_SEPARATOR // main framework .ONPHP_MAIN_PATH.'Base' .PATH_SEPARATOR From 5e9bac506715acc1d4f17136798af80e3639b64f Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 23 Apr 2012 17:09:55 +0400 Subject: [PATCH 070/418] notEq fix --- core/Logic/NoSQLExpression.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index 567bd6af10..c8dd11a847 100644 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -70,7 +70,7 @@ public function addEq($field, $value) { public function addNotEq($field, $value) { $this->conditions[] = array( - self::C_TYPE => self::EXP_EQ, + self::C_TYPE => self::EXP_NOTEQ, self::C_FIELD => (string)$field, self::C_VALUE => Assert::checkInteger($value) ? (int)$value : $value, ); From b33251db9d0b1adfcdd25b164085b272964c44c4 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 23 Apr 2012 17:50:00 +0400 Subject: [PATCH 071/418] mapReduce without query fix --- core/NoSQL/MongoBase.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index b29ab94daf..5a901d4010 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -307,13 +307,13 @@ public function mapReduce($table, $map, $reduce, Criteria $criteria=null) { 'out' => array('inline' => 1) ); // обрабатываем критерию - if( !is_null($options[self::C_QUERY]) ) { + if( !empty($options[self::C_QUERY]) ) { $command['query'] = $options[self::C_QUERY]; } - if( !is_null($options[self::C_ORDER]) ) { + if( !empty($options[self::C_ORDER]) ) { $command['sort'] = $options[self::C_ORDER]; } - if( !is_null($options[self::C_LIMIT]) ) { + if( !empty($options[self::C_LIMIT]) ) { $command['limit'] = $options[self::C_LIMIT]; } From 4026d9bbe9c4e1c038fe7c769d924e2d313c936c Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Sun, 29 Apr 2012 13:17:45 +0400 Subject: [PATCH 072/418] mongo count by criteria --- core/NoSQL/MongoBase.class.php | 14 ++++++++++++++ core/NoSQL/NoSQL.class.php | 1 + core/NoSQL/NoSqlDAO.class.php | 10 ++++++++++ 3 files changed, 25 insertions(+) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 5a901d4010..eb836c014c 100644 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -244,6 +244,20 @@ public function findByCriteria(Criteria $criteria) { $this->mongoFind($options[self::C_TABLE], $options[self::C_QUERY], array(), $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); } + public function countByCriteria(Criteria $criteria) { + $options = $this->parseCriteria($criteria); + + if( !isset($options[self::C_TABLE]) ) { + throw new NoSQLException('Can not find without table!'); + } +// if( !isset($options[self::C_QUERY]) ) { +// throw new NoSQLException('Can not find without query!'); +// } + + return + $this->mongoCount($options[self::C_TABLE], $options[self::C_QUERY], array(), $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); + } + protected function mongoFind($table, array $query, array $fields=array(), array $order=null, $limit=null, $skip=null) { // quering $cursor = $this->mongoMakeCursor($table, $query, $fields, $order, $limit, $skip); diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php index dea3bb8cb1..21d70513c1 100644 --- a/core/NoSQL/NoSQL.class.php +++ b/core/NoSQL/NoSQL.class.php @@ -46,6 +46,7 @@ abstract public function getListByField($table, $field, $value, Criteria $criter abstract public function getIdListByField($table, $field, $value, Criteria $criteria = null); abstract public function find($table, $query); abstract public function findByCriteria(Criteria $criteria); + abstract public function countByCriteria(Criteria $criteria); abstract public function mapReduce($table, $map, $reduce, Criteria $criteria=null); diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 4034581b42..c699ac4375 100644 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -140,6 +140,16 @@ public function getListByCriteria(Criteria $criteria, $expires = Cache::DO_NOT_C return $list; } + /** + * @param Criteria $criteria + * @param int $expires + * @return int + */ + public function getCountByCriteria(Criteria $criteria, $expires = Cache::DO_NOT_CACHE) { + $criteria->setDao( $this ); + return $this->getLink()->countByCriteria($criteria); + } + /** * @param int $expires * @return array From 2c9ca0dde2bafac86edc9540f0ff1f50dcf3d0c7 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Tue, 1 May 2012 19:34:27 +0400 Subject: [PATCH 073/418] FirePHP lib --- lib/FirePHP/FirePHP.class.php | 1788 +++++++++++++++++++++++++++++++++ 1 file changed, 1788 insertions(+) create mode 100644 lib/FirePHP/FirePHP.class.php diff --git a/lib/FirePHP/FirePHP.class.php b/lib/FirePHP/FirePHP.class.php new file mode 100644 index 0000000000..74d1c2d73e --- /dev/null +++ b/lib/FirePHP/FirePHP.class.php @@ -0,0 +1,1788 @@ + + * @license http://www.opensource.org/licenses/bsd-license.php + * @package FirePHPCore + */ + +/** + * @see http://code.google.com/p/firephp/issues/detail?id=112 + */ +if (!defined('E_STRICT')) { + define('E_STRICT', 2048); +} +if (!defined('E_RECOVERABLE_ERROR')) { + define('E_RECOVERABLE_ERROR', 4096); +} +if (!defined('E_DEPRECATED')) { + define('E_DEPRECATED', 8192); +} +if (!defined('E_USER_DEPRECATED')) { + define('E_USER_DEPRECATED', 16384); +} + +/** + * Sends the given data to the FirePHP Firefox Extension. + * The data can be displayed in the Firebug Console or in the + * "Server" request tab. + * + * For more information see: http://www.firephp.org/ + * + * @copyright Copyright (C) 2007-2009 Christoph Dorn + * @author Christoph Dorn + * @license http://www.opensource.org/licenses/bsd-license.php + * @package FirePHPCore + */ +class FirePHP { + + /** + * FirePHP version + * + * @var string + */ + const VERSION = '0.3'; // @pinf replace '0.3' with '%%package.version%%' + + /** + * Firebug LOG level + * + * Logs a message to firebug console. + * + * @var string + */ + const LOG = 'LOG'; + + /** + * Firebug INFO level + * + * Logs a message to firebug console and displays an info icon before the message. + * + * @var string + */ + const INFO = 'INFO'; + + /** + * Firebug WARN level + * + * Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise. + * + * @var string + */ + const WARN = 'WARN'; + + /** + * Firebug ERROR level + * + * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count. + * + * @var string + */ + const ERROR = 'ERROR'; + + /** + * Dumps a variable to firebug's server panel + * + * @var string + */ + const DUMP = 'DUMP'; + + /** + * Displays a stack trace in firebug console + * + * @var string + */ + const TRACE = 'TRACE'; + + /** + * Displays an exception in firebug console + * + * Increments the firebug error count. + * + * @var string + */ + const EXCEPTION = 'EXCEPTION'; + + /** + * Displays an table in firebug console + * + * @var string + */ + const TABLE = 'TABLE'; + + /** + * Starts a group in firebug console + * + * @var string + */ + const GROUP_START = 'GROUP_START'; + + /** + * Ends a group in firebug console + * + * @var string + */ + const GROUP_END = 'GROUP_END'; + + /** + * Singleton instance of FirePHP + * + * @var FirePHP + */ + protected static $instance = null; + + /** + * Flag whether we are logging from within the exception handler + * + * @var boolean + */ + protected $inExceptionHandler = false; + + /** + * Flag whether to throw PHP errors that have been converted to ErrorExceptions + * + * @var boolean + */ + protected $throwErrorExceptions = true; + + /** + * Flag whether to convert PHP assertion errors to Exceptions + * + * @var boolean + */ + protected $convertAssertionErrorsToExceptions = true; + + /** + * Flag whether to throw PHP assertion errors that have been converted to Exceptions + * + * @var boolean + */ + protected $throwAssertionExceptions = false; + + /** + * Wildfire protocol message index + * + * @var int + */ + protected $messageIndex = 1; + + /** + * Options for the library + * + * @var array + */ + protected $options = array('maxDepth' => 10, + 'maxObjectDepth' => 5, + 'maxArrayDepth' => 5, + 'useNativeJsonEncode' => true, + 'includeLineNumbers' => true); + + /** + * Filters used to exclude object members when encoding + * + * @var array + */ + protected $objectFilters = array( + 'firephp' => array('objectStack', 'instance', 'json_objectStack'), + 'firephp_test_class' => array('objectStack', 'instance', 'json_objectStack') + ); + + /** + * A stack of objects used to detect recursion during object encoding + * + * @var object + */ + protected $objectStack = array(); + + /** + * Flag to enable/disable logging + * + * @var boolean + */ + protected $enabled = true; + + /** + * The insight console to log to if applicable + * + * @var object + */ + protected $logToInsightConsole = null; + + /** + * When the object gets serialized only include specific object members. + * + * @return array + */ + public function __sleep() + { + return array('options','objectFilters','enabled'); + } + + public static function me() { + return self::getInstance(true); + } + + /** + * Gets singleton instance of FirePHP + * + * @param boolean $AutoCreate + * @return FirePHP + */ + public static function getInstance($AutoCreate = false) + { + if ($AutoCreate===true && !self::$instance) { + self::init(); + } + return self::$instance; + } + + /** + * Creates FirePHP object and stores it for singleton access + * + * @return FirePHP + */ + public static function init() + { + return self::setInstance(new self()); + } + + /** + * Set the instance of the FirePHP singleton + * + * @param FirePHP $instance The FirePHP object instance + * @return FirePHP + */ + public static function setInstance($instance) + { + return self::$instance = $instance; + } + + /** + * Set an Insight console to direct all logging calls to + * + * @param object $console The console object to log to + * @return void + */ + public function setLogToInsightConsole($console) + { + if(is_string($console)) { + if(get_class($this)!='FirePHP_Insight' && !is_subclass_of($this, 'FirePHP_Insight')) { + throw new Exception('FirePHP instance not an instance or subclass of FirePHP_Insight!'); + } + $this->logToInsightConsole = $this->to('request')->console($console); + } else { + $this->logToInsightConsole = $console; + } + } + + /** + * Enable and disable logging to Firebug + * + * @param boolean $Enabled TRUE to enable, FALSE to disable + * @return void + */ + public function setEnabled($Enabled) + { + $this->enabled = $Enabled; + } + + /** + * Check if logging is enabled + * + * @return boolean TRUE if enabled + */ + public function getEnabled() + { + return $this->enabled; + } + + /** + * Specify a filter to be used when encoding an object + * + * Filters are used to exclude object members. + * + * @param string $Class The class name of the object + * @param array $Filter An array of members to exclude + * @return void + */ + public function setObjectFilter($Class, $Filter) + { + $this->objectFilters[strtolower($Class)] = $Filter; + } + + /** + * Set some options for the library + * + * Options: + * - maxDepth: The maximum depth to traverse (default: 10) + * - maxObjectDepth: The maximum depth to traverse objects (default: 5) + * - maxArrayDepth: The maximum depth to traverse arrays (default: 5) + * - useNativeJsonEncode: If true will use json_encode() (default: true) + * - includeLineNumbers: If true will include line numbers and filenames (default: true) + * + * @param array $Options The options to be set + * @return void + */ + public function setOptions($Options) + { + $this->options = array_merge($this->options,$Options); + } + + /** + * Get options from the library + * + * @return array The currently set options + */ + public function getOptions() + { + return $this->options; + } + + /** + * Set an option for the library + * + * @param string $Name + * @param mixed $Value + * @throws Exception + * @return void + */ + public function setOption($Name, $Value) + { + if (!isset($this->options[$Name])) { + throw $this->newException('Unknown option: ' . $Name); + } + $this->options[$Name] = $Value; + } + + /** + * Get an option from the library + * + * @param string $Name + * @throws Exception + * @return mixed + */ + public function getOption($Name) + { + if (!isset($this->options[$Name])) { + throw $this->newException('Unknown option: ' . $Name); + } + return $this->options[$Name]; + } + + /** + * Register FirePHP as your error handler + * + * Will throw exceptions for each php error. + * + * @return mixed Returns a string containing the previously defined error handler (if any) + */ + public function registerErrorHandler($throwErrorExceptions = false) + { + //NOTE: The following errors will not be caught by this error handler: + // E_ERROR, E_PARSE, E_CORE_ERROR, + // E_CORE_WARNING, E_COMPILE_ERROR, + // E_COMPILE_WARNING, E_STRICT + + $this->throwErrorExceptions = $throwErrorExceptions; + + return set_error_handler(array($this,'errorHandler')); + } + + /** + * FirePHP's error handler + * + * Throws exception for each php error that will occur. + * + * @param int $errno + * @param string $errstr + * @param string $errfile + * @param int $errline + * @param array $errcontext + */ + public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) + { + // Don't throw exception if error reporting is switched off + if (error_reporting() == 0) { + return; + } + // Only throw exceptions for errors we are asking for + if (error_reporting() & $errno) { + + $exception = new ErrorException($errstr, 0, $errno, $errfile, $errline); + if ($this->throwErrorExceptions) { + throw $exception; + } else { + $this->fb($exception); + } + } + } + + /** + * Register FirePHP as your exception handler + * + * @return mixed Returns the name of the previously defined exception handler, + * or NULL on error. + * If no previous handler was defined, NULL is also returned. + */ + public function registerExceptionHandler() + { + return set_exception_handler(array($this,'exceptionHandler')); + } + + /** + * FirePHP's exception handler + * + * Logs all exceptions to your firebug console and then stops the script. + * + * @param Exception $Exception + * @throws Exception + */ + function exceptionHandler($Exception) + { + + $this->inExceptionHandler = true; + + header('HTTP/1.1 500 Internal Server Error'); + + try { + $this->fb($Exception); + } catch (Exception $e) { + echo 'We had an exception: ' . $e; + } + $this->inExceptionHandler = false; + } + + /** + * Register FirePHP driver as your assert callback + * + * @param boolean $convertAssertionErrorsToExceptions + * @param boolean $throwAssertionExceptions + * @return mixed Returns the original setting or FALSE on errors + */ + public function registerAssertionHandler($convertAssertionErrorsToExceptions = true, $throwAssertionExceptions = false) + { + $this->convertAssertionErrorsToExceptions = $convertAssertionErrorsToExceptions; + $this->throwAssertionExceptions = $throwAssertionExceptions; + + if ($throwAssertionExceptions && !$convertAssertionErrorsToExceptions) { + throw $this->newException('Cannot throw assertion exceptions as assertion errors are not being converted to exceptions!'); + } + + return assert_options(ASSERT_CALLBACK, array($this, 'assertionHandler')); + } + + /** + * FirePHP's assertion handler + * + * Logs all assertions to your firebug console and then stops the script. + * + * @param string $file File source of assertion + * @param int $line Line source of assertion + * @param mixed $code Assertion code + */ + public function assertionHandler($file, $line, $code) + { + if ($this->convertAssertionErrorsToExceptions) { + + $exception = new ErrorException('Assertion Failed - Code[ '.$code.' ]', 0, null, $file, $line); + + if ($this->throwAssertionExceptions) { + throw $exception; + } else { + $this->fb($exception); + } + + } else { + $this->fb($code, 'Assertion Failed', FirePHP::ERROR, array('File'=>$file,'Line'=>$line)); + } + } + + /** + * Start a group for following messages. + * + * Options: + * Collapsed: [true|false] + * Color: [#RRGGBB|ColorName] + * + * @param string $Name + * @param array $Options OPTIONAL Instructions on how to log the group + * @return true + * @throws Exception + */ + public function group($Name, $Options = null) + { + + if (!$Name) { + throw $this->newException('You must specify a label for the group!'); + } + + if ($Options) { + if (!is_array($Options)) { + throw $this->newException('Options must be defined as an array!'); + } + if (array_key_exists('Collapsed', $Options)) { + $Options['Collapsed'] = ($Options['Collapsed'])?'true':'false'; + } + } + + return $this->fb(null, $Name, FirePHP::GROUP_START, $Options); + } + + /** + * Ends a group you have started before + * + * @return true + * @throws Exception + */ + public function groupEnd() + { + return $this->fb(null, null, FirePHP::GROUP_END); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::LOG + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function log($Object, $Label = null, $Options = array()) + { + return $this->fb($Object, $Label, FirePHP::LOG, $Options); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::INFO + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function info($Object, $Label = null, $Options = array()) + { + return $this->fb($Object, $Label, FirePHP::INFO, $Options); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::WARN + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function warn($Object, $Label = null, $Options = array()) + { + return $this->fb($Object, $Label, FirePHP::WARN, $Options); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::ERROR + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function error($Object, $Label = null, $Options = array()) + { + return $this->fb($Object, $Label, FirePHP::ERROR, $Options); + } + + /** + * Dumps key and variable to firebug server panel + * + * @see FirePHP::DUMP + * @param string $Key + * @param mixed $Variable + * @return true + * @throws Exception + */ + public function dump($Key, $Variable, $Options = array()) + { + if (!is_string($Key)) { + throw $this->newException('Key passed to dump() is not a string'); + } + if (strlen($Key)>100) { + throw $this->newException('Key passed to dump() is longer than 100 characters'); + } + if (!preg_match_all('/^[a-zA-Z0-9-_\.:]*$/', $Key, $m)) { + throw $this->newException('Key passed to dump() contains invalid characters [a-zA-Z0-9-_\.:]'); + } + return $this->fb($Variable, $Key, FirePHP::DUMP, $Options); + } + + /** + * Log a trace in the firebug console + * + * @see FirePHP::TRACE + * @param string $Label + * @return true + * @throws Exception + */ + public function trace($Label) + { + return $this->fb($Label, FirePHP::TRACE); + } + + /** + * Log a table in the firebug console + * + * @see FirePHP::TABLE + * @param string $Label + * @param string $Table + * @return true + * @throws Exception + */ + public function table($Label, $Table, $Options = array()) + { + return $this->fb($Table, $Label, FirePHP::TABLE, $Options); + } + + /** + * Insight API wrapper + * + * @see Insight_Helper::to() + */ + public static function to() + { + $instance = self::getInstance(); + if (!method_exists($instance, "_to")) { + throw new Exception("FirePHP::to() implementation not loaded"); + } + $args = func_get_args(); + return call_user_func_array(array($instance, '_to'), $args); + } + + /** + * Insight API wrapper + * + * @see Insight_Helper::plugin() + */ + public static function plugin() + { + $instance = self::getInstance(); + if (!method_exists($instance, "_plugin")) { + throw new Exception("FirePHP::plugin() implementation not loaded"); + } + $args = func_get_args(); + return call_user_func_array(array($instance, '_plugin'), $args); + } + + /** + * Check if FirePHP is installed on client + * + * @return boolean + */ + public function detectClientExtension() + { + // Check if FirePHP is installed on client via User-Agent header + if (@preg_match_all('/\sFirePHP\/([\.\d]*)\s?/si',$this->getUserAgent(),$m) && + version_compare($m[1][0],'0.0.6','>=')) { + return true; + } else + // Check if FirePHP is installed on client via X-FirePHP-Version header + if (@preg_match_all('/^([\.\d]*)$/si',$this->getRequestHeader("X-FirePHP-Version"),$m) && + version_compare($m[1][0],'0.0.6','>=')) { + return true; + } + return false; + } + + /** + * Log varible to Firebug + * + * @see http://www.firephp.org/Wiki/Reference/Fb + * @param mixed $Object The variable to be logged + * @return true Return TRUE if message was added to headers, FALSE otherwise + * @throws Exception + */ + public function fb($Object) + { + if($this instanceof FirePHP_Insight && method_exists($this, '_logUpgradeClientMessage')) { + if(!FirePHP_Insight::$upgradeClientMessageLogged) { // avoid infinite recursion as _logUpgradeClientMessage() logs a message + $this->_logUpgradeClientMessage(); + } + } + + static $insightGroupStack = array(); + + if (!$this->getEnabled()) { + return false; + } + + if ($this->headersSent($filename, $linenum)) { + // If we are logging from within the exception handler we cannot throw another exception + if ($this->inExceptionHandler) { + // Simply echo the error out to the page + echo '
FirePHP ERROR: Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.
'; + } else { + throw $this->newException('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.'); + } + } + + $Type = null; + $Label = null; + $Options = array(); + + if (func_num_args()==1) { + } else + if (func_num_args()==2) { + switch(func_get_arg(1)) { + case self::LOG: + case self::INFO: + case self::WARN: + case self::ERROR: + case self::DUMP: + case self::TRACE: + case self::EXCEPTION: + case self::TABLE: + case self::GROUP_START: + case self::GROUP_END: + $Type = func_get_arg(1); + break; + default: + $Label = func_get_arg(1); + break; + } + } else + if (func_num_args()==3) { + $Type = func_get_arg(2); + $Label = func_get_arg(1); + } else + if (func_num_args()==4) { + $Type = func_get_arg(2); + $Label = func_get_arg(1); + $Options = func_get_arg(3); + } else { + throw $this->newException('Wrong number of arguments to fb() function!'); + } + + if($this->logToInsightConsole!==null && (get_class($this)=='FirePHP_Insight' || is_subclass_of($this, 'FirePHP_Insight'))) { + $msg = $this->logToInsightConsole; + if ($Object instanceof Exception) { + $Type = self::EXCEPTION; + } + if($Label && $Type!=self::TABLE && $Type!=self::GROUP_START) { + $msg = $msg->label($Label); + } + switch($Type) { + case self::DUMP: + case self::LOG: + return $msg->log($Object); + case self::INFO: + return $msg->info($Object); + case self::WARN: + return $msg->warn($Object); + case self::ERROR: + return $msg->error($Object); + case self::TRACE: + return $msg->trace($Object); + case self::EXCEPTION: + return $this->plugin('engine')->handleException($Object, $msg); + case self::TABLE: + if (isset($Object[0]) && !is_string($Object[0]) && $Label) { + $Object = array($Label, $Object); + } + return $msg->table($Object[0], array_slice($Object[1],1), $Object[1][0]); + case self::GROUP_START: + $insightGroupStack[] = $msg->group(md5($Label))->open(); + return $msg->log($Label); + case self::GROUP_END: + if(count($insightGroupStack)==0) { + throw new Error('Too many groupEnd() as opposed to group() calls!'); + } + $group = array_pop($insightGroupStack); + return $group->close(); + default: + return $msg->log($Object); + } + } + + if (!$this->detectClientExtension()) { + return false; + } + + $meta = array(); + $skipFinalObjectEncode = false; + + if ($Object instanceof Exception) { + + $meta['file'] = $this->_escapeTraceFile($Object->getFile()); + $meta['line'] = $Object->getLine(); + + $trace = $Object->getTrace(); + if ($Object instanceof ErrorException + && isset($trace[0]['function']) + && $trace[0]['function']=='errorHandler' + && isset($trace[0]['class']) + && $trace[0]['class']=='FirePHP') { + + $severity = false; + switch($Object->getSeverity()) { + case E_WARNING: $severity = 'E_WARNING'; break; + case E_NOTICE: $severity = 'E_NOTICE'; break; + case E_USER_ERROR: $severity = 'E_USER_ERROR'; break; + case E_USER_WARNING: $severity = 'E_USER_WARNING'; break; + case E_USER_NOTICE: $severity = 'E_USER_NOTICE'; break; + case E_STRICT: $severity = 'E_STRICT'; break; + case E_RECOVERABLE_ERROR: $severity = 'E_RECOVERABLE_ERROR'; break; + case E_DEPRECATED: $severity = 'E_DEPRECATED'; break; + case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break; + } + + $Object = array('Class'=>get_class($Object), + 'Message'=>$severity.': '.$Object->getMessage(), + 'File'=>$this->_escapeTraceFile($Object->getFile()), + 'Line'=>$Object->getLine(), + 'Type'=>'trigger', + 'Trace'=>$this->_escapeTrace(array_splice($trace,2))); + $skipFinalObjectEncode = true; + } else { + $Object = array('Class'=>get_class($Object), + 'Message'=>$Object->getMessage(), + 'File'=>$this->_escapeTraceFile($Object->getFile()), + 'Line'=>$Object->getLine(), + 'Type'=>'throw', + 'Trace'=>$this->_escapeTrace($trace)); + $skipFinalObjectEncode = true; + } + $Type = self::EXCEPTION; + + } else + if ($Type==self::TRACE) { + + $trace = debug_backtrace(); + if (!$trace) return false; + for( $i=0 ; $i_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' + || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { + /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ + } else + if (isset($trace[$i]['class']) + && isset($trace[$i+1]['file']) + && $trace[$i]['class']=='FirePHP' + && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip fb() */ + } else + if ($trace[$i]['function']=='fb' + || $trace[$i]['function']=='trace' + || $trace[$i]['function']=='send') { + + $Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'', + 'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'', + 'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'', + 'Message'=>$trace[$i]['args'][0], + 'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'', + 'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'', + 'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'', + 'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1))); + + $skipFinalObjectEncode = true; + $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; + $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; + break; + } + } + + } else + if ($Type==self::TABLE) { + + if (isset($Object[0]) && is_string($Object[0])) { + $Object[1] = $this->encodeTable($Object[1]); + } else { + $Object = $this->encodeTable($Object); + } + + $skipFinalObjectEncode = true; + + } else + if ($Type==self::GROUP_START) { + + if (!$Label) { + throw $this->newException('You must specify a label for the group!'); + } + + } else { + if ($Type===null) { + $Type = self::LOG; + } + } + + if ($this->options['includeLineNumbers']) { + if (!isset($meta['file']) || !isset($meta['line'])) { + + $trace = debug_backtrace(); + for( $i=0 ; $trace && $i_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' + || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { + /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ + } else + if (isset($trace[$i]['class']) + && isset($trace[$i+1]['file']) + && $trace[$i]['class']=='FirePHP' + && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip fb() */ + } else + if (isset($trace[$i]['file']) + && substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip FB::fb() */ + } else { + $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; + $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; + break; + } + } + } + } else { + unset($meta['file']); + unset($meta['line']); + } + + $this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2'); + $this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION); + + $structure_index = 1; + if ($Type==self::DUMP) { + $structure_index = 2; + $this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1'); + } else { + $this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'); + } + + if ($Type==self::DUMP) { + $msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}'; + } else { + $msg_meta = $Options; + $msg_meta['Type'] = $Type; + if ($Label!==null) { + $msg_meta['Label'] = $Label; + } + if (isset($meta['file']) && !isset($msg_meta['File'])) { + $msg_meta['File'] = $meta['file']; + } + if (isset($meta['line']) && !isset($msg_meta['Line'])) { + $msg_meta['Line'] = $meta['line']; + } + $msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']'; + } + + $parts = explode("\n",chunk_split($msg, 5000, "\n")); + + for( $i=0 ; $i2) { + // Message needs to be split into multiple parts + $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, + (($i==0)?strlen($msg):'') + . '|' . $part . '|' + . (($isetHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, + strlen($part) . '|' . $part . '|'); + } + + $this->messageIndex++; + + if ($this->messageIndex > 99999) { + throw $this->newException('Maximum number (99,999) of messages reached!'); + } + } + } + + $this->setHeader('X-Wf-1-Index',$this->messageIndex-1); + + return true; + } + + /** + * Standardizes path for windows systems. + * + * @param string $Path + * @return string + */ + protected function _standardizePath($Path) + { + return preg_replace('/\\\\+/','/',$Path); + } + + /** + * Escape trace path for windows systems + * + * @param array $Trace + * @return array + */ + protected function _escapeTrace($Trace) + { + if (!$Trace) return $Trace; + for( $i=0 ; $i_escapeTraceFile($Trace[$i]['file']); + } + if (isset($Trace[$i]['args'])) { + $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']); + } + } + return $Trace; + } + + /** + * Escape file information of trace for windows systems + * + * @param string $File + * @return string + */ + protected function _escapeTraceFile($File) + { + /* Check if we have a windows filepath */ + if (strpos($File,'\\')) { + /* First strip down to single \ */ + + $file = preg_replace('/\\\\+/','\\',$File); + + return $file; + } + return $File; + } + + /** + * Check if headers have already been sent + * + * @param string $Filename + * @param integer $Linenum + */ + protected function headersSent(&$Filename, &$Linenum) + { + return headers_sent($Filename, $Linenum); + } + + /** + * Send header + * + * @param string $Name + * @param string $Value + */ + protected function setHeader($Name, $Value) + { + return header($Name.': '.$Value); + } + + /** + * Get user agent + * + * @return string|false + */ + protected function getUserAgent() + { + if (!isset($_SERVER['HTTP_USER_AGENT'])) return false; + return $_SERVER['HTTP_USER_AGENT']; + } + + /** + * Get all request headers + * + * @return array + */ + public static function getAllRequestHeaders() { + static $_cached_headers = false; + if($_cached_headers!==false) { + return $_cached_headers; + } + $headers = array(); + if(function_exists('getallheaders')) { + foreach( getallheaders() as $name => $value ) { + $headers[strtolower($name)] = $value; + } + } else { + foreach($_SERVER as $name => $value) { + if(substr($name, 0, 5) == 'HTTP_') { + $headers[strtolower(str_replace(' ', '-', str_replace('_', ' ', substr($name, 5))))] = $value; + } + } + } + return $_cached_headers = $headers; + } + + /** + * Get a request header + * + * @return string|false + */ + protected function getRequestHeader($Name) + { + $headers = self::getAllRequestHeaders(); + if (isset($headers[strtolower($Name)])) { + return $headers[strtolower($Name)]; + } + return false; + } + + /** + * Returns a new exception + * + * @param string $Message + * @return Exception + */ + protected function newException($Message) + { + return new Exception($Message); + } + + /** + * Encode an object into a JSON string + * + * Uses PHP's jeson_encode() if available + * + * @param object $Object The object to be encoded + * @return string The JSON string + */ + public function jsonEncode($Object, $skipObjectEncode = false) + { + if (!$skipObjectEncode) { + $Object = $this->encodeObject($Object); + } + + if (function_exists('json_encode') + && $this->options['useNativeJsonEncode']!=false) { + + return json_encode($Object); + } else { + return $this->json_encode($Object); + } + } + + /** + * Encodes a table by encoding each row and column with encodeObject() + * + * @param array $Table The table to be encoded + * @return array + */ + protected function encodeTable($Table) + { + + if (!$Table) return $Table; + + $new_table = array(); + foreach($Table as $row) { + + if (is_array($row)) { + $new_row = array(); + + foreach($row as $item) { + $new_row[] = $this->encodeObject($item); + } + + $new_table[] = $new_row; + } + } + + return $new_table; + } + + /** + * Encodes an object including members with + * protected and private visibility + * + * @param Object $Object The object to be encoded + * @param int $Depth The current traversal depth + * @return array All members of the object + */ + protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1, $MaxDepth = 1) + { + if ($MaxDepth > $this->options['maxDepth']) { + return '** Max Depth ('.$this->options['maxDepth'].') **'; + } + + $return = array(); + + if (is_resource($Object)) { + + return '** '.(string)$Object.' **'; + + } else + if (is_object($Object)) { + + if ($ObjectDepth > $this->options['maxObjectDepth']) { + return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **'; + } + + foreach ($this->objectStack as $refVal) { + if ($refVal === $Object) { + return '** Recursion ('.get_class($Object).') **'; + } + } + array_push($this->objectStack, $Object); + + $return['__className'] = $class = get_class($Object); + $class_lower = strtolower($class); + + $reflectionClass = new ReflectionClass($class); + $properties = array(); + foreach( $reflectionClass->getProperties() as $property) { + $properties[$property->getName()] = $property; + } + + $members = (array)$Object; + + foreach( $properties as $plain_name => $property ) { + + $name = $raw_name = $plain_name; + if ($property->isStatic()) { + $name = 'static:'.$name; + } + if ($property->isPublic()) { + $name = 'public:'.$name; + } else + if ($property->isPrivate()) { + $name = 'private:'.$name; + $raw_name = "\0".$class."\0".$raw_name; + } else + if ($property->isProtected()) { + $name = 'protected:'.$name; + $raw_name = "\0".'*'."\0".$raw_name; + } + + if (!(isset($this->objectFilters[$class_lower]) + && is_array($this->objectFilters[$class_lower]) + && in_array($plain_name,$this->objectFilters[$class_lower]))) { + + if (array_key_exists($raw_name,$members) + && !$property->isStatic()) { + + $return[$name] = $this->encodeObject($members[$raw_name], $ObjectDepth + 1, 1, $MaxDepth + 1); + + } else { + if (method_exists($property,'setAccessible')) { + $property->setAccessible(true); + $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1, $MaxDepth + 1); + } else + if ($property->isPublic()) { + $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1, $MaxDepth + 1); + } else { + $return[$name] = '** Need PHP 5.3 to get value **'; + } + } + } else { + $return[$name] = '** Excluded by Filter **'; + } + } + + // Include all members that are not defined in the class + // but exist in the object + foreach( $members as $raw_name => $value ) { + + $name = $raw_name; + + if ($name{0} == "\0") { + $parts = explode("\0", $name); + $name = $parts[2]; + } + + $plain_name = $name; + + if (!isset($properties[$name])) { + $name = 'undeclared:'.$name; + + if (!(isset($this->objectFilters[$class_lower]) + && is_array($this->objectFilters[$class_lower]) + && in_array($plain_name,$this->objectFilters[$class_lower]))) { + + $return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1, $MaxDepth + 1); + } else { + $return[$name] = '** Excluded by Filter **'; + } + } + } + + array_pop($this->objectStack); + + } elseif (is_array($Object)) { + + if ($ArrayDepth > $this->options['maxArrayDepth']) { + return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **'; + } + + foreach ($Object as $key => $val) { + + // Encoding the $GLOBALS PHP array causes an infinite loop + // if the recursion is not reset here as it contains + // a reference to itself. This is the only way I have come up + // with to stop infinite recursion in this case. + if ($key=='GLOBALS' + && is_array($val) + && array_key_exists('GLOBALS',$val)) { + $val['GLOBALS'] = '** Recursion (GLOBALS) **'; + } + + $return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1, $MaxDepth + 1); + } + } else { + if (self::is_utf8($Object)) { + return $Object; + } else { + return utf8_encode($Object); + } + } + return $return; + } + + /** + * Returns true if $string is valid UTF-8 and false otherwise. + * + * @param mixed $str String to be tested + * @return boolean + */ + protected static function is_utf8($str) + { + if(function_exists('mb_detect_encoding')) { + return (mb_detect_encoding($str) == 'UTF-8'); + } + $c=0; $b=0; + $bits=0; + $len=strlen($str); + for($i=0; $i<$len; $i++){ + $c=ord($str[$i]); + if ($c > 128){ + if (($c >= 254)) return false; + elseif ($c >= 252) $bits=6; + elseif ($c >= 248) $bits=5; + elseif ($c >= 240) $bits=4; + elseif ($c >= 224) $bits=3; + elseif ($c >= 192) $bits=2; + else return false; + if (($i+$bits) > $len) return false; + while($bits > 1){ + $i++; + $b=ord($str[$i]); + if ($b < 128 || $b > 191) return false; + $bits--; + } + } + } + return true; + } + + /** + * Converts to and from JSON format. + * + * JSON (JavaScript Object Notation) is a lightweight data-interchange + * format. It is easy for humans to read and write. It is easy for machines + * to parse and generate. It is based on a subset of the JavaScript + * Programming Language, Standard ECMA-262 3rd Edition - December 1999. + * This feature can also be found in Python. JSON is a text format that is + * completely language independent but uses conventions that are familiar + * to programmers of the C-family of languages, including C, C++, C#, Java, + * JavaScript, Perl, TCL, and many others. These properties make JSON an + * ideal data-interchange language. + * + * This package provides a simple encoder and decoder for JSON notation. It + * is intended for use with client-side Javascript applications that make + * use of HTTPRequest to perform server communication functions - data can + * be encoded into JSON notation for use in a client-side javascript, or + * decoded from incoming Javascript requests. JSON format is native to + * Javascript, and can be directly eval()'ed with no further parsing + * overhead + * + * All strings should be in ASCII or UTF-8 format! + * + * LICENSE: Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: Redistributions of source code must retain the + * above copyright notice, this list of conditions and the following + * disclaimer. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * @category + * @package Services_JSON + * @author Michal Migurski + * @author Matt Knapp + * @author Brett Stimmerman + * @author Christoph Dorn + * @copyright 2005 Michal Migurski + * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $ + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 + */ + + + /** + * Keep a list of objects as we descend into the array so we can detect recursion. + */ + private $json_objectStack = array(); + + + /** + * convert a string from one UTF-8 char to one UTF-16 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf8 UTF-8 character + * @return string UTF-16 character + * @access private + */ + private function json_utf82utf16($utf8) + { + // oh please oh please oh please oh please oh please + if (function_exists('mb_convert_encoding')) { + return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); + } + + switch(strlen($utf8)) { + case 1: + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return $utf8; + + case 2: + // return a UTF-16 character from a 2-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x07 & (ord($utf8{0}) >> 2)) + . chr((0xC0 & (ord($utf8{0}) << 6)) + | (0x3F & ord($utf8{1}))); + + case 3: + // return a UTF-16 character from a 3-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr((0xF0 & (ord($utf8{0}) << 4)) + | (0x0F & (ord($utf8{1}) >> 2))) + . chr((0xC0 & (ord($utf8{1}) << 6)) + | (0x7F & ord($utf8{2}))); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * encodes an arbitrary variable into JSON format + * + * @param mixed $var any number, boolean, string, array, or object to be encoded. + * see argument 1 to Services_JSON() above for array-parsing behavior. + * if var is a strng, note that encode() always expects it + * to be in ASCII or UTF-8 format! + * + * @return mixed JSON string representation of input var or an error if a problem occurs + * @access public + */ + private function json_encode($var) + { + + if (is_object($var)) { + if (in_array($var,$this->json_objectStack)) { + return '"** Recursion **"'; + } + } + + switch (gettype($var)) { + case 'boolean': + return $var ? 'true' : 'false'; + + case 'NULL': + return 'null'; + + case 'integer': + return (int) $var; + + case 'double': + case 'float': + return (float) $var; + + case 'string': + // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT + $ascii = ''; + $strlen_var = strlen($var); + + /* + * Iterate over every character in the string, + * escaping with a slash or encoding to UTF-8 where necessary + */ + for ($c = 0; $c < $strlen_var; ++$c) { + + $ord_var_c = ord($var{$c}); + + switch (true) { + case $ord_var_c == 0x08: + $ascii .= '\b'; + break; + case $ord_var_c == 0x09: + $ascii .= '\t'; + break; + case $ord_var_c == 0x0A: + $ascii .= '\n'; + break; + case $ord_var_c == 0x0C: + $ascii .= '\f'; + break; + case $ord_var_c == 0x0D: + $ascii .= '\r'; + break; + + case $ord_var_c == 0x22: + case $ord_var_c == 0x2F: + case $ord_var_c == 0x5C: + // double quote, slash, slosh + $ascii .= '\\'.$var{$c}; + break; + + case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): + // characters U-00000000 - U-0000007F (same as ASCII) + $ascii .= $var{$c}; + break; + + case (($ord_var_c & 0xE0) == 0xC0): + // characters U-00000080 - U-000007FF, mask 110XXXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($var{$c + 1})); + $c += 1; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF0) == 0xE0): + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2})); + $c += 2; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF8) == 0xF0): + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3})); + $c += 3; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFC) == 0xF8): + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4})); + $c += 4; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFE) == 0xFC): + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4}), + ord($var{$c + 5})); + $c += 5; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + } + } + + return '"'.$ascii.'"'; + + case 'array': + /* + * As per JSON spec if any array key is not an integer + * we must treat the the whole array as an object. We + * also try to catch a sparsely populated associative + * array with numeric keys here because some JS engines + * will create an array with empty indexes up to + * max_index which can cause memory issues and because + * the keys, which may be relevant, will be remapped + * otherwise. + * + * As per the ECMA and JSON specification an object may + * have any string as a property. Unfortunately due to + * a hole in the ECMA specification if the key is a + * ECMA reserved word or starts with a digit the + * parameter is only accessible using ECMAScript's + * bracket notation. + */ + + // treat as a JSON object + if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { + + $this->json_objectStack[] = $var; + + $properties = array_map(array($this, 'json_name_value'), + array_keys($var), + array_values($var)); + + array_pop($this->json_objectStack); + + foreach($properties as $property) { + if ($property instanceof Exception) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + } + + $this->json_objectStack[] = $var; + + // treat it like a regular array + $elements = array_map(array($this, 'json_encode'), $var); + + array_pop($this->json_objectStack); + + foreach($elements as $element) { + if ($element instanceof Exception) { + return $element; + } + } + + return '[' . join(',', $elements) . ']'; + + case 'object': + $vars = self::encodeObject($var); + + $this->json_objectStack[] = $var; + + $properties = array_map(array($this, 'json_name_value'), + array_keys($vars), + array_values($vars)); + + array_pop($this->json_objectStack); + + foreach($properties as $property) { + if ($property instanceof Exception) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + + default: + return null; + } + } + + /** + * array-walking function for use in generating JSON-formatted name-value pairs + * + * @param string $name name of key to use + * @param mixed $value reference to an array element to be encoded + * + * @return string JSON-formatted name-value pair, like '"name":value' + * @access private + */ + private function json_name_value($name, $value) + { + // Encoding the $GLOBALS PHP array causes an infinite loop + // if the recursion is not reset here as it contains + // a reference to itself. This is the only way I have come up + // with to stop infinite recursion in this case. + if ($name=='GLOBALS' + && is_array($value) + && array_key_exists('GLOBALS',$value)) { + $value['GLOBALS'] = '** Recursion **'; + } + + $encoded_value = $this->json_encode($value); + + if ($encoded_value instanceof Exception) { + return $encoded_value; + } + + return $this->json_encode(strval($name)) . ':' . $encoded_value; + } + + /** + * @deprecated + */ + public function setProcessorUrl($URL) + { + trigger_error("The FirePHP::setProcessorUrl() method is no longer supported", E_USER_DEPRECATED); + } + + /** + * @deprecated + */ + public function setRendererUrl($URL) + { + trigger_error("The FirePHP::setRendererUrl() method is no longer supported", E_USER_DEPRECATED); + } +} From 5480df78ee13e85a9199475f85101ea09fef0f2b Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Tue, 1 May 2012 19:50:01 +0400 Subject: [PATCH 074/418] fix --- core/Base/UuidIdentifiable.class.php | 0 core/Exceptions/CtppException.class.php | 0 core/Exceptions/MissingModuleException.class.php | 0 core/Exceptions/NoSQLException.class.php | 0 core/Form/MappedFormField.class.php | 0 core/Form/Primitives/PrimitiveReCaptcha.class.php | 0 core/Form/Primitives/PrimitiveRule.class.php | 0 core/Form/Primitives/PrimitiveUuidIdentifier.class.php | 0 core/Form/Primitives/PrimitiveUuidIdentifierList.class.php | 0 core/Form/Primitives/PrimitiveUuidString.class.php | 0 core/Logic/NoSQLExpression.class.php | 0 core/NoSQL/MongoBase.class.php | 0 core/NoSQL/NoSQL.class.php | 0 core/NoSQL/NoSqlDAO.class.php | 0 core/NoSQL/NoSqlObject.class.php | 0 core/NoSQL/NoSqlPool.class.php | 0 doc/patches/core_DB_Dialect.diff | 0 doc/patches/global-inc.diff | 0 lib/FirePHP/FirePHP.class.php | 0 main/DAOs/Workers/TrickyDaoWorker.class.php | 0 main/UI/View/CtppView.class.php | 0 main/UI/View/ExtendedPhpView.class.php | 0 main/UnifiedContainer/OneToManyNoSqlLinked.class.php | 0 main/Utils/UuidUtils.class.php | 0 meta/builders/AutoNoSqlDaoBuilder.class.php | 0 meta/patterns/NosqlClassPattern.class.php | 0 meta/types/UuidType.class.php | 0 27 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 core/Base/UuidIdentifiable.class.php mode change 100644 => 100755 core/Exceptions/CtppException.class.php mode change 100644 => 100755 core/Exceptions/MissingModuleException.class.php mode change 100644 => 100755 core/Exceptions/NoSQLException.class.php mode change 100644 => 100755 core/Form/MappedFormField.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveReCaptcha.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveRule.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveUuidIdentifier.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveUuidIdentifierList.class.php mode change 100644 => 100755 core/Form/Primitives/PrimitiveUuidString.class.php mode change 100644 => 100755 core/Logic/NoSQLExpression.class.php mode change 100644 => 100755 core/NoSQL/MongoBase.class.php mode change 100644 => 100755 core/NoSQL/NoSQL.class.php mode change 100644 => 100755 core/NoSQL/NoSqlDAO.class.php mode change 100644 => 100755 core/NoSQL/NoSqlObject.class.php mode change 100644 => 100755 core/NoSQL/NoSqlPool.class.php mode change 100644 => 100755 doc/patches/core_DB_Dialect.diff mode change 100644 => 100755 doc/patches/global-inc.diff mode change 100644 => 100755 lib/FirePHP/FirePHP.class.php mode change 100644 => 100755 main/DAOs/Workers/TrickyDaoWorker.class.php mode change 100644 => 100755 main/UI/View/CtppView.class.php mode change 100644 => 100755 main/UI/View/ExtendedPhpView.class.php mode change 100644 => 100755 main/UnifiedContainer/OneToManyNoSqlLinked.class.php mode change 100644 => 100755 main/Utils/UuidUtils.class.php mode change 100644 => 100755 meta/builders/AutoNoSqlDaoBuilder.class.php mode change 100644 => 100755 meta/patterns/NosqlClassPattern.class.php mode change 100644 => 100755 meta/types/UuidType.class.php diff --git a/core/Base/UuidIdentifiable.class.php b/core/Base/UuidIdentifiable.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/CtppException.class.php b/core/Exceptions/CtppException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/MissingModuleException.class.php b/core/Exceptions/MissingModuleException.class.php old mode 100644 new mode 100755 diff --git a/core/Exceptions/NoSQLException.class.php b/core/Exceptions/NoSQLException.class.php old mode 100644 new mode 100755 diff --git a/core/Form/MappedFormField.class.php b/core/Form/MappedFormField.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveReCaptcha.class.php b/core/Form/Primitives/PrimitiveReCaptcha.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveRule.class.php b/core/Form/Primitives/PrimitiveRule.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveUuidIdentifier.class.php b/core/Form/Primitives/PrimitiveUuidIdentifier.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveUuidIdentifierList.class.php b/core/Form/Primitives/PrimitiveUuidIdentifierList.class.php old mode 100644 new mode 100755 diff --git a/core/Form/Primitives/PrimitiveUuidString.class.php b/core/Form/Primitives/PrimitiveUuidString.class.php old mode 100644 new mode 100755 diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php old mode 100644 new mode 100755 diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php old mode 100644 new mode 100755 diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php old mode 100644 new mode 100755 diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php old mode 100644 new mode 100755 diff --git a/core/NoSQL/NoSqlObject.class.php b/core/NoSQL/NoSqlObject.class.php old mode 100644 new mode 100755 diff --git a/core/NoSQL/NoSqlPool.class.php b/core/NoSQL/NoSqlPool.class.php old mode 100644 new mode 100755 diff --git a/doc/patches/core_DB_Dialect.diff b/doc/patches/core_DB_Dialect.diff old mode 100644 new mode 100755 diff --git a/doc/patches/global-inc.diff b/doc/patches/global-inc.diff old mode 100644 new mode 100755 diff --git a/lib/FirePHP/FirePHP.class.php b/lib/FirePHP/FirePHP.class.php old mode 100644 new mode 100755 diff --git a/main/DAOs/Workers/TrickyDaoWorker.class.php b/main/DAOs/Workers/TrickyDaoWorker.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/CtppView.class.php b/main/UI/View/CtppView.class.php old mode 100644 new mode 100755 diff --git a/main/UI/View/ExtendedPhpView.class.php b/main/UI/View/ExtendedPhpView.class.php old mode 100644 new mode 100755 diff --git a/main/UnifiedContainer/OneToManyNoSqlLinked.class.php b/main/UnifiedContainer/OneToManyNoSqlLinked.class.php old mode 100644 new mode 100755 diff --git a/main/Utils/UuidUtils.class.php b/main/Utils/UuidUtils.class.php old mode 100644 new mode 100755 diff --git a/meta/builders/AutoNoSqlDaoBuilder.class.php b/meta/builders/AutoNoSqlDaoBuilder.class.php old mode 100644 new mode 100755 diff --git a/meta/patterns/NosqlClassPattern.class.php b/meta/patterns/NosqlClassPattern.class.php old mode 100644 new mode 100755 diff --git a/meta/types/UuidType.class.php b/meta/types/UuidType.class.php old mode 100644 new mode 100755 From 98a24aa26fb3093c2362b092c4566702fd0832aa Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Tue, 1 May 2012 20:29:00 +0400 Subject: [PATCH 075/418] debug --- main/DAOs/GenericDAO.class.php | 149 +++++++++++++++++---------------- 1 file changed, 75 insertions(+), 74 deletions(-) diff --git a/main/DAOs/GenericDAO.class.php b/main/DAOs/GenericDAO.class.php index ab0cd44dd5..c6366efa51 100755 --- a/main/DAOs/GenericDAO.class.php +++ b/main/DAOs/GenericDAO.class.php @@ -11,16 +11,16 @@ /** * Basis of all DAO's. - * + * * @ingroup DAOs **/ abstract class GenericDAO extends Singleton implements BaseDAO { private $identityMap = array(); - + abstract public function getTable(); abstract public function getObjectName(); - + public function makeObject($array, $prefix = null) { if ( @@ -33,18 +33,19 @@ public function makeObject($array, $prefix = null) $this->getProtoClass()->skipObjectPrefetching( $this->identityMap[$array[$idName]] ); - + return $this->identityMap[$array[$idName]]; } - + return $this->completeObject( $this->makeOnlyObject($array, $prefix) ); } - + public function makeOnlyObject($array, $prefix = null) { + FirePHP::me()->log($array); // adding incomplete object to identity map // solves case with circular-dependent objects return $this->addObjectToMap( @@ -53,7 +54,7 @@ public function makeOnlyObject($array, $prefix = null) ) ); } - + public function completeObject(Identifiable $object) { return $this->getProtoClass()->completeObject( @@ -62,82 +63,82 @@ public function completeObject(Identifiable $object) $this->addObjectToMap($object) ); } - + /** * Returns link name which is used to get actual DB-link from DBPool, * returning null by default for single-source projects. - * + * * @see DBPool **/ public function getLinkName() { return null; } - + public function getIdName() { return 'id'; } - + public function getSequence() { return $this->getTable().'_id'; } - + /** * @return AbstractProtoClass **/ public function getProtoClass() { static $protos = array(); - + if (!isset($protos[$className = $this->getObjectName()])) $protos[$className] = call_user_func(array($className, 'proto')); - + return $protos[$className]; } - + public function getMapping() { return $this->getProtoClass()->getMapping(); } - + public function getFields() { static $fields = array(); - + $className = $this->getObjectName(); - + if (!isset($fields[$className])) { $fields[$className] = array_values($this->getMapping()); } - + return $fields[$className]; } - + /** * @return SelectQuery **/ public function makeSelectHead() { static $selectHead = array(); - + if (!isset($selectHead[$className = $this->getObjectName()])) { $table = $this->getTable(); - + $object = OSQL::select()-> from($table); - + foreach ($this->getFields() as $field) $object->get(new DBField($field, $table)); - + $selectHead[$className] = $object; } - + return clone $selectHead[$className]; } - + /** * @return SelectQuery **/ @@ -150,22 +151,22 @@ public function makeTotalCountQuery() )-> from($this->getTable()); } - + /// boring delegates //@{ public function getById($id, $expires = Cache::EXPIRES_MEDIUM) { Assert::isScalar($id); Assert::isNotEmpty($id); - + if (isset($this->identityMap[$id])) return $this->identityMap[$id]; - + return $this->addObjectToMap( Cache::worker($this)->getById($id, $expires) ); } - + public function getByLogic( LogicalObject $logic, $expires = Cache::DO_NOT_CACHE ) @@ -174,7 +175,7 @@ public function getByLogic( Cache::worker($this)->getByLogic($logic, $expires) ); } - + public function getByQuery( SelectQuery $query, $expires = Cache::DO_NOT_CACHE ) @@ -183,20 +184,20 @@ public function getByQuery( Cache::worker($this)->getByQuery($query, $expires) ); } - + public function getCustom( SelectQuery $query, $expires = Cache::DO_NOT_CACHE ) { return Cache::worker($this)->getCustom($query, $expires); } - + public function getListByIds( array $ids, $expires = Cache::EXPIRES_MEDIUM ) { $mapped = $remain = array(); - + foreach ($ids as $id) { if (isset($this->identityMap[$id])) { $mapped[] = $this->identityMap[$id]; @@ -204,18 +205,18 @@ public function getListByIds( $remain[] = $id; } } - + if ($remain) { $list = $this->addObjectListToMap( Cache::worker($this)->getListByIds($remain, $expires) ); - + $mapped = array_merge($mapped, $list); } - + return ArrayUtils::regularizeList($ids, $mapped); } - + public function getListByQuery( SelectQuery $query, $expires = Cache::DO_NOT_CACHE ) @@ -224,7 +225,7 @@ public function getListByQuery( Cache::worker($this)->getListByQuery($query, $expires) ); } - + public function getListByLogic( LogicalObject $logic, $expires = Cache::DO_NOT_CACHE ) @@ -233,102 +234,102 @@ public function getListByLogic( Cache::worker($this)->getListByLogic($logic, $expires) ); } - + public function getPlainList($expires = Cache::EXPIRES_MEDIUM) { return $this->addObjectListToMap( Cache::worker($this)->getPlainList($expires) ); } - + public function getTotalCount($expires = Cache::DO_NOT_CACHE) { return Cache::worker($this)->getTotalCount($expires); } - + public function getCustomList( SelectQuery $query, $expires = Cache::DO_NOT_CACHE ) { return Cache::worker($this)->getCustomList($query, $expires); } - + public function getCustomRowList( SelectQuery $query, $expires = Cache::DO_NOT_CACHE ) { return Cache::worker($this)->getCustomRowList($query, $expires); } - + public function getQueryResult( SelectQuery $query, $expires = Cache::DO_NOT_CACHE ) { return Cache::worker($this)->getQueryResult($query, $expires); } - + public function drop(Identifiable $object) { $this->checkObjectType($object); - + return $this->dropById($object->getId()); } - + public function dropById($id) { unset($this->identityMap[$id]); - + $count = Cache::worker($this)->dropById($id); - + if (1 != $count) throw new WrongStateException('no object were dropped'); - + return $count; } - + public function dropByIds(array $ids) { foreach ($ids as $id) unset($this->identityMap[$id]); - + $count = Cache::worker($this)->dropByIds($ids); - + if ($count != count($ids)) throw new WrongStateException('not all objects were dropped'); - + return $count; } - + public function uncacheById($id) { unset($this->identityMap[$id]); - + return Cache::worker($this)->uncacheById($id); } - + public function uncacheByIds($ids) { foreach ($ids as $id) unset($this->identityMap[$id]); - + return Cache::worker($this)->uncacheByIds($ids); } - + public function uncacheLists() { $this->dropIdentityMap(); - + return Cache::worker($this)->uncacheLists(); } //@} - + /** * @return GenericDAO **/ public function dropIdentityMap() { $this->identityMap = array(); - + return $this; } @@ -338,14 +339,14 @@ public function dropObjectIdentityMapById($id) return $this; } - + protected function inject( InsertOrUpdateQuery $query, Identifiable $object ) { $this->checkObjectType($object); - + return $this->doInject( $this->setQueryFields( $query->setTable($this->getTable()), $object @@ -353,19 +354,19 @@ protected function inject( $object ); } - + protected function doInject( InsertOrUpdateQuery $query, Identifiable $object ) { $db = DBPool::getByDao($this); - + if (!$db->isQueueActive()) { $count = $db->queryCount($query); - + $this->uncacheById($object->getId()); - + if ($count !== 1) throw new WrongStateException( $count.' rows affected: racy or insane inject happened: ' @@ -373,14 +374,14 @@ protected function doInject( ); } else { $db->queryNull($query); - + $this->uncacheById($object->getId()); } - + // clean out Identifier, if any return $this->addObjectToMap($object->setId($object->getId())); } - + /* void */ protected function checkObjectType(Identifiable $object) { Assert::isSame( @@ -389,17 +390,17 @@ protected function doInject( 'strange object given, i can not inject it' ); } - + private function addObjectToMap(Identifiable $object) { return $this->identityMap[$object->getId()] = $object; } - + private function addObjectListToMap($list) { foreach ($list as $object) $this->identityMap[$object->getId()] = $object; - + return $list; } } From dfb72d41c7353b397a884ed1846eebe8d99491ae Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Tue, 1 May 2012 20:37:54 +0400 Subject: [PATCH 076/418] debug mongo --- main/Base/AbstractProtoClass.class.php | 2 ++ main/DAOs/GenericDAO.class.php | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/main/Base/AbstractProtoClass.class.php b/main/Base/AbstractProtoClass.class.php index 63d8a8852c..22f8571636 100755 --- a/main/Base/AbstractProtoClass.class.php +++ b/main/Base/AbstractProtoClass.class.php @@ -373,6 +373,8 @@ private static function assemblyObject( Prototyped $object, $array, $prefix = null ) { + FirePHP::me()->log($array); + die('zzz'); if ($object instanceof DAOConnected) $dao = $object->dao(); else diff --git a/main/DAOs/GenericDAO.class.php b/main/DAOs/GenericDAO.class.php index c6366efa51..56ab695165 100755 --- a/main/DAOs/GenericDAO.class.php +++ b/main/DAOs/GenericDAO.class.php @@ -45,7 +45,6 @@ public function makeObject($array, $prefix = null) public function makeOnlyObject($array, $prefix = null) { - FirePHP::me()->log($array); // adding incomplete object to identity map // solves case with circular-dependent objects return $this->addObjectToMap( From 164b95e990f8563bad7a4c32dacd52c6c8747597 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Tue, 1 May 2012 20:39:11 +0400 Subject: [PATCH 077/418] FirePHP --- global.inc.php.tpl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/global.inc.php.tpl b/global.inc.php.tpl index 336f45415e..0c7a0cd4e1 100755 --- a/global.inc.php.tpl +++ b/global.inc.php.tpl @@ -173,6 +173,8 @@ .ONPHP_MAIN_PATH.'Charts'.DIRECTORY_SEPARATOR.'Google'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Monitoring'.PATH_SEPARATOR + .ONPHP_LIB_PATH.'FirePHP'.PATH_SEPARATOR + .ONPHP_META_CLASSES.PATH_SEPARATOR /* From 7b32cf2401aaa37f5197af4d427b925047e58987 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Tue, 1 May 2012 20:40:52 +0400 Subject: [PATCH 078/418] debug --- main/Base/AbstractProtoClass.class.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/main/Base/AbstractProtoClass.class.php b/main/Base/AbstractProtoClass.class.php index 22f8571636..5b49693c0d 100755 --- a/main/Base/AbstractProtoClass.class.php +++ b/main/Base/AbstractProtoClass.class.php @@ -373,8 +373,8 @@ private static function assemblyObject( Prototyped $object, $array, $prefix = null ) { - FirePHP::me()->log($array); - die('zzz'); +// FirePHP::me()->log($array); +// die('zzz'); if ($object instanceof DAOConnected) $dao = $object->dao(); else @@ -382,6 +382,8 @@ private static function assemblyObject( $proto = $object->proto(); + try { + foreach ($proto->getPropertyList() as $property) { $setter = $property->getSetter(); @@ -408,6 +410,13 @@ private static function assemblyObject( } } + } catch( Exception $e ) { + echo '
';
+				echo $e->getTraceAsString();
+				echo '
'; + die('error'); + } + return $object; } From fb2ba817f60d5e359b9ab3b55d4f2951c0e47c4c Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Tue, 1 May 2012 20:44:56 +0400 Subject: [PATCH 079/418] debug end --- main/Base/AbstractProtoClass.class.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/main/Base/AbstractProtoClass.class.php b/main/Base/AbstractProtoClass.class.php index 5b49693c0d..0e338cfcdb 100755 --- a/main/Base/AbstractProtoClass.class.php +++ b/main/Base/AbstractProtoClass.class.php @@ -373,8 +373,6 @@ private static function assemblyObject( Prototyped $object, $array, $prefix = null ) { -// FirePHP::me()->log($array); -// die('zzz'); if ($object instanceof DAOConnected) $dao = $object->dao(); else From c9aa36edc56ad3480fad078f4ad17b9e1880743d Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Tue, 1 May 2012 22:30:54 +0400 Subject: [PATCH 080/418] fix for missed required fields in NoSQL --- core/NoSQL/NoSqlDAO.class.php | 48 ++++++++++++++++++++++---- main/Base/AbstractProtoClass.class.php | 6 +++- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index c699ac4375..3c5cb5eae2 100755 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -245,6 +245,12 @@ public function take(Identifiable $object) { public function add(Identifiable $object) { $this->assertNoSqlObject( $object ); + // converting object into Array + $arrayObj = $object->toArray(); + + // checking object completance + $this->checkNoSqlObject( $object ); + // make sequence $link = NoSqlPool::getByDao( $this ); // $object->setId( @@ -258,12 +264,10 @@ public function add(Identifiable $object) { $link ->insert( $this->getTable(), - $object->toArray() + $arrayObj ); $object->setId( $entity['id'] ); - // проверка добавления - //$object = $this->getById( $entity['id'] ); return $object; } @@ -309,13 +313,19 @@ public function multiAdd(array $objectList) { public function save(Identifiable $object) { $this->assertNoSqlObject( $object ); + // converting object into Array + $arrayObj = $object->toArray(); + + // checking object completance + $this->checkNoSqlObject( $object ); + $link = NoSqlPool::getByDao( $this ); // save $entity = $link ->update( $this->getTable(), - $object->toArray() + $arrayObj ); $object->setId( $entity['id'] ); @@ -325,13 +335,19 @@ public function save(Identifiable $object) { public function import(Identifiable $object) { $this->assertNoSqlObject( $object ); + // converting object into Array + $arrayObj = $object->toArray(); + + // checking object completance + $this->checkNoSqlObject( $object ); + $link = NoSqlPool::getByDao( $this ); // insert $entity = $link ->insert( $this->getTable(), - $object->toArray() + $arrayObj ); $object->setId( $entity['id'] ); // проверка сохранения @@ -448,9 +464,29 @@ protected function assertNoSqlObject( $object ) { } } + /** + * @param Identifiable $object + * @return bool + * @throws NoSQLException + */ + protected function checkNoSqlObject(Identifiable $object) { + $className = get_class($object); + // checking by proto + Assert::methodExists($className, 'proto'); + /** @var $form Form */ + $form = $className::proto()->makeForm(null, false); + FormUtils::object2form($object, $form); + if( $form->getErrors() ) { + throw new NoSQLException( 'Object does not have all required fields: '.var_export($form->getErrors(), true) ); + } + + return true; + } + /** * @param array $row - * @param null $prefix + * @param null $prefix + * @throws WrongStateException * @return Identifiable|Prototyped */ public function makeNoSqlObject($row, $prefix = null) { diff --git a/main/Base/AbstractProtoClass.class.php b/main/Base/AbstractProtoClass.class.php index 0e338cfcdb..9dadaa02b0 100755 --- a/main/Base/AbstractProtoClass.class.php +++ b/main/Base/AbstractProtoClass.class.php @@ -196,11 +196,15 @@ public function isPropertyExists($name) /** * @return Form **/ - public function makeForm($prefix = null) + public function makeForm($prefix = null, $includeManyRelations = true) { $form = Form::create(); + /** @var $property LightMetaProperty */ foreach ($this->getPropertyList() as $property) { + if($property->getRelationId()!=MetaRelation::ONE_TO_ONE && $includeManyRelations==false) { + continue; + } $property->fillForm($form, $prefix); } From b7a9a9469571c6843787ed3f6fc7522d0f1cbeda Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Thu, 3 May 2012 18:26:17 +0400 Subject: [PATCH 081/418] nosql expression IN and NOT_IN --- core/Logic/NoSQLExpression.class.php | 40 +++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index c8dd11a847..6a749d25d3 100755 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -14,13 +14,15 @@ final class NoSQLExpression implements LogicalObject, MappableObject { const V_RIGHT = 102; const EXP_EQ = 1001; - const EXP_NOTEQ = 1002; + const EXP_NOT_EQ = 1002; const EXP_GT = 1003; const EXP_GTE = 1004; const EXP_LT = 1005; const EXP_LTE = 1006; const EXP_BTW_STR = 1007; const EXP_BTW_SFT = 1008; + const EXP_IN = 1009; + const EXP_NOT_IN = 1010; /** * true = объединять условия по И @@ -70,7 +72,7 @@ public function addEq($field, $value) { public function addNotEq($field, $value) { $this->conditions[] = array( - self::C_TYPE => self::EXP_NOTEQ, + self::C_TYPE => self::EXP_NOT_EQ, self::C_FIELD => (string)$field, self::C_VALUE => Assert::checkInteger($value) ? (int)$value : $value, ); @@ -138,6 +140,38 @@ public function addBetweenSoft($field, $left, $right) { ); return $this; } + + public function addIn($field, array $value) { + foreach($value as &$inVal) { + if(Assert::checkInteger($inVal)) { + $inVal = (int)$inVal; + } else { + $inVal = (string)$inVal; + } + } + $this->conditions[] = array( + self::C_TYPE => self::EXP_IN, + self::C_FIELD => (string)$field, + self::C_VALUE => $value, + ); + return $this; + } + + public function addNotIn($field, $value) { + foreach($value as &$inVal) { + if(Assert::checkInteger($inVal)) { + $inVal = (int)$inVal; + } else { + $inVal = (string)$inVal; + } + } + $this->conditions[] = array( + self::C_TYPE => self::EXP_NOT_IN, + self::C_FIELD => (string)$field, + self::C_VALUE => $value, + ); + return $this; + } //@} /// helper functions @@ -162,7 +196,7 @@ public function toMongoQuery() { } } break; - case self::EXP_NOTEQ: { + case self::EXP_NOT_EQ: { if( $this->unite ) { $query[ $condition[self::C_FIELD] ] = array('$ne' => $condition[self::C_VALUE]); } else { From e9abb715c175c97b05d5b52b936cfea8d1d18927 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Thu, 3 May 2012 18:32:40 +0400 Subject: [PATCH 082/418] exp in --- core/Logic/NoSQLExpression.class.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index 6a749d25d3..58efa285af 100755 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -245,8 +245,22 @@ public function toMongoQuery() { $query[] = array( $condition[self::C_FIELD] => array('$gte' => $condition[self::C_VALUE][self::V_LEFT], '$lte' => $condition[self::C_VALUE][self::V_RIGHT]) ); } } break; + case self::EXP_IN: { + if( $this->unite ) { + $query[ $condition[self::C_FIELD] ] = array('$in' => $condition[self::C_VALUE]); + } else { + $query[] = array( $condition[self::C_FIELD] => array('$in' => $condition[self::C_VALUE]) ); + } + } break; + case self::EXP_NOT_IN: { + if( $this->unite ) { + $query[ $condition[self::C_FIELD] ] = array('$nin' => $condition[self::C_VALUE]); + } else { + $query[] = array( $condition[self::C_FIELD] => array('$nin' => $condition[self::C_VALUE]) ); + } + } break; default: { - throw new WrongStateException( 'Sorry, I do not know how to work with you condition with ' ); + throw new WrongStateException( 'Sorry, I do not know how to work with you condition!' ); } break; } } From 31a56db8e77cbf5cb1e55bab81b622c84e5ca7a2 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Mon, 7 May 2012 19:40:00 +0400 Subject: [PATCH 083/418] ProtoUtils for action-core --- main/Utils/PrototypeUtils.class.php | 225 ++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100755 main/Utils/PrototypeUtils.class.php diff --git a/main/Utils/PrototypeUtils.class.php b/main/Utils/PrototypeUtils.class.php new file mode 100755 index 0000000000..375f5e26a6 --- /dev/null +++ b/main/Utils/PrototypeUtils.class.php @@ -0,0 +1,225 @@ + + * @date 2012.03.23 + */ +class PrototypeUtils +{ + protected static $identifiers = array('identifier', 'integerIdentifier', 'scalarIdentifier', 'uuidIdentifier'); + + /** + * @static + * @param AbstractProtoClass $proto + * @param int $depth max depth + * @param string $prefix + * @param array $exclude + * @return array + */ + public static function getFullPropertyList(AbstractProtoClass $proto, $depth = 99, $prefix = '', $exclude = array()) { + $properties = $proto->getPropertyList(); + $values = array(); + foreach ($properties as $name=>$prop) { + $values[] = $prefix . $name; + if ($prop->isIdentifier()) { + $exclude[] = $prop->getClassName(); + } + $class = $prop->getClassName(); + if (strlen($class) && is_subclass_of($class, 'Prototyped')) { + if ( !in_array($class, $exclude) && $depth > 0) { + $values = array_merge($values, + self::getFullPropertyList($class::proto(), $depth-1, $prefix . $prop->getName() . '.', $exclude) + ); + } + } + } + return $values; + } + + /** + * @static + * @param AbstractProtoClass $proto + * @param array $fields + * @return Form + */ + public static function makeForm(AbstractProtoClass $proto, array $fields) { + $form = Form::create(); + foreach ($fields as $field) { + try { + $property = self::getProperty($proto, $field); + } catch (MissingElementException $e) { + continue; //skip + } + $prefix = strrev(strrchr(strrev($field), '.')); + $property->fillForm($form, $prefix); + $primitive = $form->get($field); + if ($primitive instanceof PrimitiveString) { + if ($property->getMax()) { + $primitive->setImportFilter(FilterFactory::makeText()); + } else { + $primitive->setImportFilter(FilterFactory::makeString()); + } + } + } + return $form; + } + + /** + * @static + * @param AbstractProtoClass $proto + * @param $path + * @return LightMetaProperty + */ + public static function getProperty(AbstractProtoClass $proto, $path) { + $path = explode('.', $path); + $subProto = $proto; + foreach ($path as $propertyName) { + /** @var $property LightMetaProperty */ + $property = $subProto->getPropertyByName($propertyName); + $class = $property->getClassName(); + if (strlen($class) && is_subclass_of($class, 'Prototyped')) + $subProto = $class::proto(); + else break; + } + return $property; + } + + /** + * @static + * @param Prototyped $object + * @param $path + * @return mixed + */ + public static function getValue(Prototyped $object, $path) { + $path = explode('.', $path); + foreach ($path as $field) { + $getter = 'get' . ucfirst($field); + if (!method_exists($object, $getter)) { + throw new ObjectNotFoundException; + } + $object = $object->$getter(); + } + return $object; + } + + /** + * @static + * @param Prototyped $object + * @param $path + * @param $value + * @throws WrongArgumentException + */ + public static function setValue(Prototyped $object, $path, $value) { + $path = explode('.', $path); + $valueName = array_pop($path); + if ($path) + $object = self::getValue($object, implode('.', $path)); + + $setter = 'set' . ucfirst($valueName); + return $object->$setter($value); + + // old: + $property = self::getProperty($object->proto(), $path); + $setter = $property->getSetter(); + if (!method_exists($object, $setter)) { + throw new WrongArgumentException; + } + $object->$setter($value); + } + + public static function hasProperty(Prototyped $object, $path) { + try { + self::getValue($object, $path); + return true; + } catch (ObjectNotFoundException $e) { + return false; + } + } + + public static function getOwner(Prototyped $object, $path) { + $path = explode('.', $path); + array_pop($path); + if ($path) + $object = self::getValue($object, implode('.', $path)); + return $object; + } + + public static function getOwnerClass(Prototyped $object, $path) { + if (strpos($path, '.') === false) { + return get_class($object); + } + $parent = substr($path, 0, strrpos($path, '.')); + return self::getProperty($object->proto(), $parent)->getClassName(); + } + + /** + * @static + * @param Prototyped $object + * @param Form $form + * @return array modified objects to save + * @throws WrongArgumentException + */ + public static function fillObject(Prototyped $object, Form $form) { + $modifications = array(); + foreach ($form->getPrimitiveList() as $primitive) { + try { + $value = $primitive->getValue(); + $field = $primitive->getName(); + + if (!self::hasProperty($object, $field)) + continue; + + if (self::getValue($object, $field) != $value) { + self::setValue($object, $field, $value); + $owner = self::getOwner($object, $field); + $modifications[get_class($owner) . '#' . $owner->getId()] = $owner; + } + } catch (WrongArgumentException $e) { + throw $e; + } + } + + return ($modifications); + } + + /** + * @param Prototyped $object + * @return array + */ + public static function toArray(Prototyped $object) { + $entity = array(); + /** @var $property LightMetaProperty */ + foreach ($object->proto()->getPropertyList() as $property) { + // обрабатываем базовые типы + if( $property->isGenericType() ) { + $value = call_user_func(array($object, $property->getGetter())); + if( is_object( $value )&& $value instanceof Date ) { + $value = $value->toStamp(); + //$value = $value->toString(); + } + if( Assert::checkInteger($value) ) { + $entity[ $property->getColumnName() ] = (int)$value; + } elseif( Assert::checkFloat($value) ) { + $entity[ $property->getColumnName() ] = (float)$value; + } else { + $entity[ $property->getColumnName() ] = $value; + } + } // обрабатываем перечисления + elseif( $property->getType()=='enumeration' ) { + $value = call_user_func(array($object, $property->getGetter())); + $entity[ $property->getColumnName() ] = is_null($value) ? null : (int)$value->getId(); + } // обрабатываем связи 1к1 + elseif( in_array($property->getType(), self::$identifiers) && $property->getRelationId()==1 ) { + $value = call_user_func(array($object, $property->getGetter().'Id')); + $entity[ $property->getColumnName() ] = is_numeric($value) ? (int)$value : $value; + } + } + return $entity; + } + +} From 5aafa8198e015aba5f5009b5749db2fcbe5fabdc Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Mon, 7 May 2012 19:46:39 +0400 Subject: [PATCH 084/418] widgets --- global.inc.php.tpl | 1 + main/UI/Widget/BaseWidget.class.php | 150 ++++++ main/UI/Widget/DataGrid.class.php | 721 ++++++++++++++++++++++++++++ main/UI/Widget/IWidget.class.php | 15 + 4 files changed, 887 insertions(+) create mode 100755 main/UI/Widget/BaseWidget.class.php create mode 100755 main/UI/Widget/DataGrid.class.php create mode 100755 main/UI/Widget/IWidget.class.php diff --git a/global.inc.php.tpl b/global.inc.php.tpl index 0c7a0cd4e1..5712833a4b 100755 --- a/global.inc.php.tpl +++ b/global.inc.php.tpl @@ -148,6 +148,7 @@ .ONPHP_MAIN_PATH.'UI'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'UI'.DIRECTORY_SEPARATOR.'View'.PATH_SEPARATOR + .ONPHP_MAIN_PATH.'UI'.DIRECTORY_SEPARATOR.'Widget'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils' .PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'TuringTest'.PATH_SEPARATOR diff --git a/main/UI/Widget/BaseWidget.class.php b/main/UI/Widget/BaseWidget.class.php new file mode 100755 index 0000000000..24894a1f55 --- /dev/null +++ b/main/UI/Widget/BaseWidget.class.php @@ -0,0 +1,150 @@ + + * @date 2012.03.11 + */ +abstract class BaseWidget implements IWidget +{ + protected $name = null; + protected $templatePath = null; + protected $templateName = null; + protected $list = null; + + /** + * @var PartViewer + */ + protected $viewer = null; + + public function __construct($name = null) + { + $this->name = $name; + $this->viewer = Viewer::get(); + } + + /** + * @param string $key + * @param mixed $value + * @return BaseWidget + */ + public function set($key, $value) + { + if( ( mb_substr($key, 0, 1) != '_' ) ) + $key = '_'.$key; + + $this->list[$key] = $value; + + + return $this; + } + + /** + * @return BaseWidget + */ + public function setTemplateName($value) + { + $this->templateName = $value; + + return $this; + } + + /** + * @return string + */ + public function getTemplateName() + { + return $this->templateName; + } + + /** + * @return BaseWidget + */ + public function setViewer(PartViewer $viewer) + { + $this->viewer = $viewer; + + return $this; + } + + /** + * @return Model + */ + protected function makeModel() + { + $model = $this->viewer->getModel(); + $model->set('_name', $this->name); + + if( + is_array( $this->list ) && + count( $this->list ) + ){ + foreach ( $this->list as $key => $value ) { + $model->set($key, $value); + } + } + + return $model; + } + + /** (non-PHPdoc) + * @see core/Base/Stringable::toString() + * @return string + */ + public function toString() + { + try { + $this->makeModel(); + + ob_start(); + + $this->viewer->view( + $this->templatePath. DIRECTORY_SEPARATOR. $this->templateName + ); + + $source = ob_get_contents(); + + ob_end_clean(); + } + catch (Exception $e) { + // FIXME + error_log(__METHOD__ . ': '.$e->__toString() ); + throw $e; + } + + return (string) $source; + } + + /** + * @return PartViewer + */ + public function getViewer() + { + return $this->viewer; + } + + /** (non-PHPdoc) + * @see main/Flow/View::render() + * @param Model|null $model + * @return void + */ + public function render($model = null) + { + if( $model ) + $this->getViewer()-> + getModel()-> + merge($model); + + echo $this->toString(); + + return /*void*/; + } + + /** + * @return string + */ + public function __toString() + { + return $this->toString(); + } +} + diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php new file mode 100755 index 0000000000..4c85aedbd7 --- /dev/null +++ b/main/UI/Widget/DataGrid.class.php @@ -0,0 +1,721 @@ + + * @date 2012.03.19 + */ +class DataGrid extends BaseWidget +{ + /** @var DataGrid для вложенных таблиц */ + protected $parent = null; + + /** @var int предел вложенности */ + protected static $maxNesting = 1; + + /** @var array список дочерних объектов */ + protected $objects = array(); + + + /** @var array список 'fieldID' => 'Field name' */ + protected $fields = array(); + + /** @var array список полей, по которым можно сортировать. + * Фактически, исключает поля, добавленные через addColumn */ + protected $sortingFields = array(); + + /** @var array список 'fieldID' => callback() */ + protected $renderers = array(); + + /** @var array массив строк таблицы */ + protected $rows = array(); + + + /** @var array аттрибуты заголовков таблицы */ + protected $fieldHtmlOptions = array(); + + /** @var array аттрибуты
*/ + protected $formHtmlOptions = array(); + + /** @var bool показывать заголовки или нет */ + protected $showHeader = true; + + /** @var bool показывать кнопки сортировки */ + protected $showSorting = true; + + /** @var bool делать редактируемые поля */ + protected $isEditor = false; + + /** @var Form для вывода ошибок в заполнении полей */ + protected $form = null; + + /** @var string текстовый вывод булевого типа */ + public $trueName = null; + + /** @var string текстовый вывод булевого типа */ + public $falseName = null; + + /** + * Создает таблицу вида сводки (заголовок слева) + * @static + * @return DataGrid + */ + public static function details() { + $self = self::create(); + $self->templateName = 'DataGrid_details'; + $self->showSorting = false; + return $self; + } + + /** + * Создает обычную таблицу + * @static + * @return DataGrid + */ + public static function table() { + $self = self::create(); + $self->templateName = 'DataGrid_table'; + $self->showSorting = true; + return $self; + } + + /** + * DataGrid::details() в виде редактируемой формы. + * Следует добавлять только 1 объект. + * @static + * @return DataGrid + */ + public static function editor($subfield = null) { + $self = self::details(); + $self->isEditor = true; + return $self; + } + + /** + * @static + * @return DataGrid + */ + private static function create() { + $self = new self; + $self->trueName = __('Да'); + $self->falseName = __('Нет'); + return $self; + } + + /** + * Вызывает addRow для каждой из переданных строк + * @param array $data + * @return DataGrid + * @throws WrongArgumentException + */ + public function addRows(array $data) { + foreach ($data as $row) { + $this->addRow($row); + } + return $this; + } + + /** + * Добавляет строку в таблицу, определяет тип и имена ее полей + * @param $data + * @return DataGrid + * @throws WrongArgumentException + */ + public function addRow($data) { + $rowId = count($this->rows); // id следующей строки + + // если это объект, то смотрим его поля в протипе + // и через геттеры получаем все параметры, а если + // это массив, то берем его как есть. + + if (is_object($data) && $data instanceof Prototyped) { + /** @var $data Prototyped */ + $this->objects[$rowId] = $data; + $fieldIds = array(); + $row = array(); + foreach ($data->proto()->getPropertyList() as $property) { + try { + $getter = $property->getGetter(); + $value = $this->objects[$rowId]->$getter(); + } catch (BadMethodCallException $e) { + continue; + } catch (ObjectNotFoundException $e) { + $value = null; + } + $fieldIds[] = $property->getName(); + $row[$property->getName()] = $value; + } + } else if (is_array($data)) { + $fieldIds = array_keys($data); + $row = $data; + } else { + throw new WrongArgumentException('$data should be either array or prototyped object'); + } + // сохраним в список сортируемых полей + foreach ($fieldIds as $fieldId) { + if (!in_array($fieldId, $this->sortingFields)) { + $this->sortingFields[] = $fieldId; + } + } + + // построим массив полей в виде 'имяПоля' => 'Имя поля' + // ключ - имя параметра, значение - имя для отображения + $fields = array(); + foreach($fieldIds as $fieldId) { + $fieldName = self::beautifyFieldName($fieldId); + $fields[$fieldId] = $fieldName; + } + // сливаем с существующим списком, чтобы ничего не потерять, + // если например отработали не все геттеры, и поле пропущено + $this->fields = array_merge($this->fields, $fields); + + // записываем данные + foreach($row as $fieldId => $value) { + $this->setField($rowId, $fieldId, $value); + } + + return $this; + } + + /** + * Выставляет значение конкретного поля конкретной строки + * @param $rowId + * @param $fieldId + * @param $value + * @param $property LightMetaProperty если null, определится + * @return DataGrid + */ + private function setField($rowId, $fieldId, $value, $property = null) { + $this->rows[$rowId][$fieldId] = $value; + if (!isset($this->renderers[$fieldId])) { + if ($this->isEditor) { + if ($property == null) { + /** @var $object Prototyped */ + $object = $this->objects[$rowId]; + if ( !($object instanceof Prototyped) ) { + throw new WrongArgumentException; + } + $property = $object->proto()->getPropertyByName($fieldId); + } + + $this->renderers[$fieldId] = $this->getEditRenderer($fieldId, $property); + } else { + if ($value !== null) { + $this->renderers[$fieldId] = $this->getViewRenderer($value); + } + } + } + + return $this; + } + + + /** + * Дополнительная колонка + * @param string $fieldName + * @param Closure $renderer callback + * @param string|null $fieldId + * @return DataGrid + */ + public function addColumn($fieldName, $renderer, $fieldId = null) { + // если это поле не для данных (иконки действий, например) + // можно сгенерить рандомное имя поля, т.к. оно не важно + if ($fieldId === null) { + $fieldId = md5($fieldName); + } else { + // Если поле указано явно, добавим сразу для него сортировку + $this->sortingFields[] = $fieldId; + } + + $this->fields[$fieldId] = $fieldName; + $this->setRenderer($fieldId, $renderer); + return $this; + } + + /** + * @param string $fieldId + * @param LightMetaProperty $property + * @return closure + * @throws ClassNotFoundException + */ + protected function getEditRenderer($fieldId, LightMetaProperty $property) { + switch($property->getType()) { + case 'integer': + case 'float': + case 'string': + return function ($value) use ($fieldId, $property) { + if ($value instanceof Stringable) $value = $value->toString(); + if ($property->getType() == 'string' && !$property->getMax()) { + return ''; + } else { + $styleWidth = $property->getType() == 'string' ? 250 : 80; + $length = $property->getType() == 'string' ? $property->getMax() : 16; + return ''; + } + + }; + + case 'timestamp': + case 'date': + return function ($value) use ($fieldId, $property) { + if ($value instanceof Date) + $val = $value->toDate('-'); + else $val = ''; + + return ''; + }; + + case 'boolean': + return function ($value) use ($fieldId) { + return ''; + }; + + case 'enumeration': + return function ($value) use ($fieldId, $property) { + $class = $property->getClassName(); + if (!class_exists($class, true)) { + throw new ClassNotFoundException; + } + $list = $class::makeObjectList(); + $html = ''; + return $html; + }; + + case 'integerIdentifier': + return function ($value) use ($property) { + if ($value instanceof Identifiable) { + $value = $value->getId(); + } + return $property->getClassName() . ' ID: ' . $value; + }; + + case 'identifierList': + return function ($value) use ($property) { + //if (is_subclass_of($property->getClassName(), 'Enumeration')) { + // return 'enum'; + //} else { + return $property->getClassName(); + //} + }; + + default: + return function ($value) use ($property) { + // DEBUG + $props[] = 'name: ' . $property->getName(); + $props[] = 'className: ' . $property->getClassName(); + $props[] = 'type: ' . $property->getType(); + $props[] = 'min: ' . $property->getMin(); + $props[] = 'max: ' . $property->getMax(); + $props[] = 'relation: ' . $property->getRelationId(); + $props[] = 'fetch: ' . $property->getFetchStrategyId(); + //$props[] = 'value: ' . $value; + return implode(', ', $props); + }; + } + } + + /** + * Находит подходящий рендерер в соответствии с типом значения + * @param $value + * @return Closure + */ + protected function getViewRenderer($value) { + // переменные для замыканий, т.к. они не биндятся к this + $self = $this; + $trueName = $this->trueName; + $falseName = $this->falseName; + + // для прототипированного объекта можно построить + // вложенную табличку. Важно запомнить родителя, + // чтобы избежать бесконечной рекурсии + if ($value instanceof Prototyped) + return function($value, $object) use ($self) { + if ($self->hasParent($object)) { + return get_class($value) . ' ID:' . $value->getId(); + } else { + try { + return DataGrid::details()->setParent($self)->addRow($value)->ToString(); + } catch (Exception $e) { + return $e->getMessage(); + } + } + }; + + + // Это в основном для тех случаев, когда у объекта есть + // OneToMany свойство. UnifiedContainer позволяет получить + // список дочерних объектов + if ($value instanceof UnifiedContainer) + return function(UnifiedContainer $value, $object) use ($self) { + if ($self->hasParent($object)) { + return get_class($value) . ' count:' . $value->fetch()->getCount(); + } else { + try { + return DataGrid::table()->setParent($self)->addRows($value->fetch()->getList())->ToString(); + } catch (Exception $e) { + return $e->getMessage(); + } + } + }; + + + // Булевы выведем для удобства словами "Да" или "Нет" + if (is_bool($value)) + return function ($value) use ($trueName, $falseName) { + return $value ? $trueName : $falseName; + }; + + + // Встроенная табличка + if (is_array($value)) + return function($value) use ($self) { + try { + return DataGrid::table()->setParent($self)->addRows($value)->ToString(); + } catch (Exception $e) { + return $e->getMessage(); + } + }; + + + // Заглушка для всех прочих объектов + if (is_object($value)) + return function ($value) { + if (is_null($value)) { + return ''; + } + if ($value instanceof Stringable) + return $value->toString(); + if (method_exists($value, '__toString')) + return (string)$value; + return 'object('.get_class($value).')'; + }; + + if (is_string($value)) + return function ($value) { + return nl2br($value); + }; + + // прочие случаи + return function($value) { return $value; }; + } + + /** + * 'somePropertyName' => 'Some property name' + * @param $camelCaseString + * @return string + */ + public static function beautifyFieldName($camelCaseString) { + return ucfirst( + preg_replace_callback( + '/([a-z])([A-Z])/', + function($x) { + return $x[1] . ' ' . strtolower($x[2]); + }, + $camelCaseString + ) + ); + } + + /** + * @param DataGrid $parent + * @return DataGrid + */ + public function setParent(DataGrid $parent) { + $this->parent = $parent; + return $this; + } + + /** + * Рекурсивная проверка + * @param $object + * @return bool + */ + public function hasParent($object) { + $dataGrid = $this; + $nesting = 0; + while ($dataGrid = $dataGrid->parent) { + if ($nesting++ > self::$maxNesting) + return true; + foreach ($dataGrid->objects as $o) { + if ($o == $object) { + return true; + } + if ($o instanceof Identifiable && $object instanceof Identifiable + && get_class($o) == get_class($object) + && $o->getId() == $object->getId()) { + return true; + } + } + } + return false; + } + + /** + * @param $number + * @return DataGrid + */ + public function setMaxNesting($number) { + self::$maxNesting = $number; + return $this; + } + + /** + * @return int + */ + public static function getMaxNesting() { + return self::$maxNesting; + } + + /** + * Задает массив столбцов таблицы + * @param array $fields array('fieldID' => 'Field name', ...) + * @return DataGrid + */ + public function setFields(array $fields) { + $this->fields = $fields; + + /* При добавлении объекта, из него выгребаются все свойства, + * но только его собственные, а зависимые объекты не подгружаются + * Допустим, мы хотим добавить employee.user.name для отображении + * имени менеджера, когда выводим инфу по рекламодателю. Тогда + * следующий код сделает следующую цепочку вызовов: + * $advertiser->getEmployee()->getUser()->getName() + * и заполнит соответствующие поля таблицы значениями. + * */ + + foreach ($this->fields as $fieldId => $fieldName) { + if (strpos($fieldId, '.') !== false) { + $path = explode('.', $fieldId); + foreach ($this->rows as $rowId => $row) { + $object = $this->objects[$rowId]; + + $failed = false; + foreach ($path as $propertyName) { + if (!$object || !($object instanceof Prototyped)) { + $failed = true; + break; + } + $property = $object->proto()->getPropertyByName($propertyName); + if ($property != null) { + $getter = $property->getGetter(); + $object = $object->$getter(); + } else { + $failed = true; + break; + } + } + + if (!$failed) { + $this->setField($rowId, $fieldId, $object, $property); + $this->sortingFields[] = $fieldId; + } + } + } + } + + return $this; + } + + /** + * Исключает столбцы из таблицы + * можно использовать маски, напр: unsetFields('webmaster.*'); + * @param $_ string, string, ... OR array + * @return DataGrid + */ + public function unsetFields($_) { + if (is_array($_)) $fields = $_; + else $fields = func_get_args(); + foreach($fields as $fieldId) { + if (substr($fieldId, -1) == '*') { + $prefix = substr($fieldId, 0, strlen($fieldId) - 1); + foreach ($this->fields as $fieldId => $fieldName) { + if (substr($fieldId, 0, strlen($prefix)) == $prefix) { + unset($this->fields[$fieldId]); + } + } + } else { + unset($this->fields[$fieldId]); + } + } + return $this; + } + + /** + * @param $fieldId string + * @param $callback Closure function($value, $rowObject) {} + * @return DataGrid + */ + public function setRenderer($fieldId, $callback) { + $this->renderers[$fieldId] = $callback; + return $this; + } + + /** + * Показать названия колонок + * @return DataGrid + */ + public function showHeader() { + $this->showHeader = true; + return $this; + } + + /** + * Скрыть названия колонок + * @return DataGrid + */ + public function hideHeader() { + $this->showHeader = false; + return $this; + } + + /** + * @param array $fields + */ + public function setSortingFields(array $fields) { + $this->sortingFields = $fields; + return $this; + } + + /** + * Исключает столбцы из списка столбцов для сортировки + * @param $_ string, string, ... OR array + * @return DataGrid + */ + public function unsetSortingFields($_) { + if (is_array($_)) $fields = $_; + else $fields = func_get_args(); + foreach($fields as $fieldId) { + foreach($this->sortingFields as $k=>$v) { + if ($v == $fieldId) { + unset($this->sortingFields[$k]); + } + } + } + return $this; + } + + /** + * @return DataGrid + */ + public function showSorting() { + $this->showSorting = true; + return $this; + } + + /** + * @return DataGrid + */ + public function hideSorting() { + $this->showSorting = false; + return $this; + } + + /** + * @param string $fieldId + * @param array $htmlOptions + * @return DataGrid + */ + public function setHeaderOptions($fieldId, $htmlOptions) { + $this->fieldHtmlOptions[$fieldId] = $htmlOptions; + return $this; + } + + /** + * @param array $htmlOptions + * @return DataGrid + */ + public function setFormOptions($htmlOptions) { + $this->formHtmlOptions = $htmlOptions; + return $this; + } + + /** + * @param $formErrors + * @return DataGrid + */ + public function setForm(Form $form) { + $this->form = $form; + return $this; + } + + /** + * @return Model + */ + protected function makeModel() { + $data = array(); + // рендерим данные + foreach ($this->rows as $rowId => $row) { + foreach ($this->fields as $fieldId => $fieldName) { + $field = isset($row[$fieldId]) ? $row[$fieldId] : null; + if ($this->form instanceof Form && $this->form->exists($fieldId)) { + if ($this->form->get($fieldId)->isImported()) + $field = $this->form->get($fieldId)->getValue(); + else if ($this->form->hasError($fieldId)) + $field = $this->form->get($fieldId)->getRawValue(); + } + + // если есть рендерер, прогоним значение через него + if (isset($this->renderers[$fieldId])) { + $callback = $this->renderers[$fieldId]; + $object = isset($this->objects[$rowId]) ? $this->objects[$rowId] : $this->rows[$rowId]; + if ($this->renderers[$fieldId] instanceof Closure) { + $field = $callback($field, $object); + } else { + $field = call_user_func($callback, $field, $object); + } + } + $data[$rowId][$fieldId] = $field; + } + } + + // отрендерим аттрибуты html + $htmlOptions = array(); + foreach ($this->fields as $fieldId => $fieldName) { + if (isset($this->fieldHtmlOptions[$fieldId])) { + $htmlOptions[$fieldId] = Html::attributes($this->fieldHtmlOptions[$fieldId]); + } else { + $htmlOptions[$fieldId] = ''; + } + } + + // отрендерим аттрибуты формы + $selfUrl = null; + try { + $controller = Application::me()->getRunningController(); + $selfUrl = $controller->getSelfUrl()->__toString(); + } catch (UnexpectedValueException $e) { + $selfUrl = $_SERVER['REQUEST_URI']; + $this->hideSorting(); + } + $formOptions = Html::attributes(array_merge( + array('action' => $selfUrl, 'method' => 'POST'), + $this->formHtmlOptions + )); + + $model = parent::makeModel() + ->set('fields', $this->fields) + ->set('data', $data) + ->set('htmlOptions', $htmlOptions) + ->set('formOptions', $formOptions) + ->set('showHeader', $this->showHeader) + ->set('showSorting', $this->showSorting) + ->set('sortingFields', $this->sortingFields) + ->set('isEditor', $this->isEditor) + ->set('form', $this->form); + ; + + return $model; + } +} diff --git a/main/UI/Widget/IWidget.class.php b/main/UI/Widget/IWidget.class.php new file mode 100755 index 0000000000..dd5df64f11 --- /dev/null +++ b/main/UI/Widget/IWidget.class.php @@ -0,0 +1,15 @@ + Date: Fri, 11 May 2012 16:26:44 +0400 Subject: [PATCH 085/418] mongo fix --- core/NoSQL/MongoBase.class.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index eb836c014c..c36338ccfa 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -331,7 +331,13 @@ public function mapReduce($table, $map, $reduce, Criteria $criteria=null) { $command['limit'] = $options[self::C_LIMIT]; } - $result = $this->db->command($command); + try { + $result = $this->db->command($command, array('timeout'=>150000)); + } catch( Exception $e ) { + Logger::me()->error( $e ); + return array(); + } + // обрабатываем результаты $list = array(); if( is_array($result) && isset($result['ok']) && $result['ok']==1 ) { From 80702477f036692ee95495ea0118bf3e1799c78a Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Fri, 11 May 2012 16:28:13 +0400 Subject: [PATCH 086/418] mongo map-reduce timeout --- core/NoSQL/MongoBase.class.php | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index c36338ccfa..54726fa723 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -305,13 +305,15 @@ protected function mongoMakeCursor($table, array $query, array $fields=array(), } /** - * @param string $table - * @param string $map - * @param string $reduce + * @param string $table + * @param string $map + * @param string $reduce * @param Criteria $criteria + * @param int $timeout + * @throws NoSQLException * @return array */ - public function mapReduce($table, $map, $reduce, Criteria $criteria=null) { + public function mapReduce($table, $map, $reduce, Criteria $criteria=null, $timeout=30) { $options = $this->parseCriteria($criteria); $command = array( @@ -331,12 +333,7 @@ public function mapReduce($table, $map, $reduce, Criteria $criteria=null) { $command['limit'] = $options[self::C_LIMIT]; } - try { - $result = $this->db->command($command, array('timeout'=>150000)); - } catch( Exception $e ) { - Logger::me()->error( $e ); - return array(); - } + $result = $this->db->command($command, array('timeout'=>$timeout*1000)); // обрабатываем результаты $list = array(); From ab41069fe4bd62ec6e60226080e8c232f227b005 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Fri, 11 May 2012 16:29:32 +0400 Subject: [PATCH 087/418] nosql timeout --- core/NoSQL/NoSQL.class.php | 2 +- core/NoSQL/NoSqlDAO.class.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php index 21d70513c1..fd59d6b305 100755 --- a/core/NoSQL/NoSQL.class.php +++ b/core/NoSQL/NoSQL.class.php @@ -48,7 +48,7 @@ abstract public function find($table, $query); abstract public function findByCriteria(Criteria $criteria); abstract public function countByCriteria(Criteria $criteria); - abstract public function mapReduce($table, $map, $reduce, Criteria $criteria=null); + abstract public function mapReduce($table, $map, $reduce, Criteria $criteria=null, $timeout=30); public function getTableInfo($table) { throw new UnsupportedMethodException('Can not execute getTableInfo in NoSQL'); diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 3c5cb5eae2..d19771b4a7 100755 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -449,8 +449,8 @@ public function getCountByField($field, $value, Criteria $criteria = null) { /// map/reduce //@{ - public function mapReduce($map, $reduce, Criteria $criteria=null) { - return $this->getLink()->mapReduce( $this->getTable(), $map, $reduce, $criteria ); + public function mapReduce($map, $reduce, Criteria $criteria=null, $timeout=30) { + return $this->getLink()->mapReduce( $this->getTable(), $map, $reduce, $criteria, $timeout ); } //@} From 58720a8d8b38bf257d2b5816af08f1fe6bad6b41 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Sat, 12 May 2012 14:01:29 +0400 Subject: [PATCH 088/418] add field list to mongo queries --- core/Logic/NoSQLExpression.class.php | 17 +++++++++++++++++ core/NoSQL/MongoBase.class.php | 17 ++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index 58efa285af..2eb286ea8f 100755 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -31,6 +31,7 @@ final class NoSQLExpression implements LogicalObject, MappableObject { */ protected $unite = null; + protected $fields = array(); protected $conditions = array(); // public static function create($unite = true) { @@ -59,6 +60,18 @@ public function __construct($unite = true) { $this->unite = (bool)$unite; } +/// field list +//@{ + /** + * @param string $fieldName + * @return NoSQLExpression + */ + public function addField($fieldName) { + $this->fields = $fieldName; + return $this; + } +//@} + /// condition setters //@{ public function addEq($field, $value) { @@ -180,6 +193,10 @@ public function addNotIn($field, $value) { /// condition setters //@{ + public function getFieldList() { + return $this->fields; + } + public function toMongoQuery() { if( empty($this->conditions) ) { throw new WrongStateException('Sorry, query conditions are empty!'); diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 54726fa723..05ad36a817 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -11,10 +11,11 @@ class MongoBase extends NoSQL { const C_TABLE = 1001; - const C_QUERY = 1002; - const C_ORDER = 1003; - const C_LIMIT = 1004; - const C_SKIP = 1005; + const C_FILEDS = 1002; + const C_QUERY = 1003; + const C_ORDER = 1004; + const C_LIMIT = 1005; + const C_SKIP = 1006; /** * @var Mongo @@ -191,7 +192,7 @@ public function getTotalCount($table) { $this ->db ->selectCollection($table) - ->find() + ->find(array(), array('_id')) ->count(); } @@ -212,7 +213,7 @@ public function getListByField($table, $field, $value, Criteria $criteria = null $options = $this->parseCriteria($criteria); return - $this->mongoFind($table, array($field => $value), array(), $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); + $this->mongoFind($table, array($field => $value), $options[self::C_FILEDS], $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); } public function getIdListByField($table, $field, $value, Criteria $criteria = null) { @@ -241,7 +242,7 @@ public function findByCriteria(Criteria $criteria) { // } return - $this->mongoFind($options[self::C_TABLE], $options[self::C_QUERY], array(), $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); + $this->mongoFind($options[self::C_TABLE], $options[self::C_QUERY], $options[self::C_FILEDS], $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); } public function countByCriteria(Criteria $criteria) { @@ -413,8 +414,10 @@ protected function parseCriteria(Criteria $criteria=null) { $logic = $criteria->getLogic()->getChain(); $expression = array_shift($logic); if( $expression instanceof NoSQLExpression ) { + $result[self::C_FILEDS] = $expression->getFieldList(); $result[self::C_QUERY] = $expression->toMongoQuery(); } else { + $result[self::C_FILEDS] = array(); $result[self::C_QUERY] = array(); } } else { From 8b606097e62119fa512fbe810703c0d39a64e708 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Sat, 12 May 2012 18:15:06 +0400 Subject: [PATCH 089/418] fix --- core/NoSQL/MongoBase.class.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 05ad36a817..4126a758dd 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -11,7 +11,7 @@ class MongoBase extends NoSQL { const C_TABLE = 1001; - const C_FILEDS = 1002; + const C_FIELDS = 1002; const C_QUERY = 1003; const C_ORDER = 1004; const C_LIMIT = 1005; @@ -213,7 +213,7 @@ public function getListByField($table, $field, $value, Criteria $criteria = null $options = $this->parseCriteria($criteria); return - $this->mongoFind($table, array($field => $value), $options[self::C_FILEDS], $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); + $this->mongoFind($table, array($field => $value), $options[self::C_FIELDS], $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); } public function getIdListByField($table, $field, $value, Criteria $criteria = null) { @@ -242,7 +242,7 @@ public function findByCriteria(Criteria $criteria) { // } return - $this->mongoFind($options[self::C_TABLE], $options[self::C_QUERY], $options[self::C_FILEDS], $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); + $this->mongoFind($options[self::C_TABLE], $options[self::C_QUERY], $options[self::C_FIELDS], $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); } public function countByCriteria(Criteria $criteria) { @@ -414,13 +414,14 @@ protected function parseCriteria(Criteria $criteria=null) { $logic = $criteria->getLogic()->getChain(); $expression = array_shift($logic); if( $expression instanceof NoSQLExpression ) { - $result[self::C_FILEDS] = $expression->getFieldList(); + $result[self::C_FIELDS] = $expression->getFieldList(); $result[self::C_QUERY] = $expression->toMongoQuery(); } else { - $result[self::C_FILEDS] = array(); + $result[self::C_FIELDS] = array(); $result[self::C_QUERY] = array(); } } else { + $result[self::C_FIELDS] = array(); $result[self::C_QUERY] = array(); } // парсим сортировку From 0d8ae57714a7d165d41830c60c1d2deb89477e2c Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 21 May 2012 16:37:58 +0400 Subject: [PATCH 090/418] =?UTF-8?q?mapReduce=20-=20=D0=BF=D0=B0=D1=80?= =?UTF-8?q?=D0=B0=D0=BC=D0=B5=D1=82=D1=80=20"out"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/NoSQL/MongoBase.class.php | 29 +++++++++++++++++------------ core/NoSQL/NoSQL.class.php | 2 +- core/NoSQL/NoSqlDAO.class.php | 4 ++-- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 4126a758dd..b9816ac6b9 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -311,17 +311,18 @@ protected function mongoMakeCursor($table, array $query, array $fields=array(), * @param string $reduce * @param Criteria $criteria * @param int $timeout + * @param array $out * @throws NoSQLException * @return array */ - public function mapReduce($table, $map, $reduce, Criteria $criteria=null, $timeout=30) { + public function mapReduce($table, $map, $reduce, Criteria $criteria=null, $timeout=30, $out=array('inline'=>1)) { $options = $this->parseCriteria($criteria); $command = array( 'mapreduce' => $table, 'map' => new MongoCode($map), 'reduce' => new MongoCode($reduce), - 'out' => array('inline' => 1) + 'out' => $out ); // обрабатываем критерию if( !empty($options[self::C_QUERY]) ) { @@ -339,17 +340,21 @@ public function mapReduce($table, $map, $reduce, Criteria $criteria=null, $timeo // обрабатываем результаты $list = array(); if( is_array($result) && isset($result['ok']) && $result['ok']==1 ) { - foreach( $result['results'] as $row ) { - // prepare id - $row['id'] = $row['_id']; - unset($row['_id']); - // prepare values - foreach($row['value'] as $key=>$value) { - $row[$key] = is_bool($value) ? (int)$value : $value; + if (isset($result['results'])) { + foreach( $result['results'] as $row ) { + // prepare id + $row['id'] = $row['_id']; + unset($row['_id']); + // prepare values + foreach($row['value'] as $key=>$value) { + $row[$key] = is_bool($value) ? (int)$value : $value; + } + unset($row['value']); + + $list[ $row['id'] ] = $row; } - unset($row['value']); - - $list[ $row['id'] ] = $row; + } else { + $list = $result; } } else { throw new NoSQLException('Error during map/reduce running'); diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php index fd59d6b305..81dff388a1 100755 --- a/core/NoSQL/NoSQL.class.php +++ b/core/NoSQL/NoSQL.class.php @@ -48,7 +48,7 @@ abstract public function find($table, $query); abstract public function findByCriteria(Criteria $criteria); abstract public function countByCriteria(Criteria $criteria); - abstract public function mapReduce($table, $map, $reduce, Criteria $criteria=null, $timeout=30); + abstract public function mapReduce($table, $map, $reduce, Criteria $criteria=null, $timeout=30, $out=array('inline'=>1)); public function getTableInfo($table) { throw new UnsupportedMethodException('Can not execute getTableInfo in NoSQL'); diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index d19771b4a7..547b1470d7 100755 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -449,8 +449,8 @@ public function getCountByField($field, $value, Criteria $criteria = null) { /// map/reduce //@{ - public function mapReduce($map, $reduce, Criteria $criteria=null, $timeout=30) { - return $this->getLink()->mapReduce( $this->getTable(), $map, $reduce, $criteria, $timeout ); + public function mapReduce($map, $reduce, Criteria $criteria=null, $timeout=30, $out=array('inline'=>1)) { + return $this->getLink()->mapReduce( $this->getTable(), $map, $reduce, $criteria, $timeout, $out ); } //@} From 07b4f5586cdfcf866b332e1528714e6d39c64bd3 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 21 May 2012 18:58:01 +0400 Subject: [PATCH 091/418] deleteByCriteria --- core/NoSQL/MongoBase.class.php | 23 +++++++++++++++++++++++ core/NoSQL/NoSqlDAO.class.php | 11 +++++++++++ 2 files changed, 34 insertions(+) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index b9816ac6b9..db9f9d305d 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -259,6 +259,22 @@ public function countByCriteria(Criteria $criteria) { $this->mongoCount($options[self::C_TABLE], $options[self::C_QUERY], array(), $options[self::C_ORDER], $options[self::C_LIMIT], $options[self::C_SKIP]); } + public function deleteByCriteria(Criteria $criteria, array $options = array('safe' => true)) { + $query = $this->parseCriteria($criteria); + + if( !isset($query[self::C_TABLE]) ) { + throw new NoSQLException('Can not find without table!'); + } + + // extend options + $options = array_merge( + array('safe' => true), + $options + ); + + $this->mongoDelete($query[self::C_TABLE], $query[self::C_QUERY], $options); + } + protected function mongoFind($table, array $query, array $fields=array(), array $order=null, $limit=null, $skip=null) { // quering $cursor = $this->mongoMakeCursor($table, $query, $fields, $order, $limit, $skip); @@ -278,6 +294,13 @@ protected function mongoCount($table, array $query, array $fields=array(), array return $cursor->count(); } + protected function mongoDelete($table, array $query, array $options) { + $res = $this->db->selectCollection($table)->remove($query, $options); + if (isset($res['err']) && !is_null($res['err'])) { + throw new NoSQLException($res['err']); + } + } + /** * @param $table * @param array $query diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 547b1470d7..2984f68318 100755 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -220,6 +220,17 @@ public function dropByIds(array $ids) { $link = NoSqlPool::getByDao( $this ); return $link->deleteList($this->getTable(), $ids); } + + public function dropByCriteria(Criteria $criteria) { + $criteria->setDao($this); + $link = $this->getLink(); + if ($link instanceof MongoBase) { + /** @var $link MongoBase */ + $link->deleteByCriteria($criteria); + } else { + throw new WrongStateException('only available in MongoBase NoSqlDAO'); + } + } //@} /// injects From 95eee80a88ac78cbe189a87013f09982b7c7da23 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Tue, 22 May 2012 19:01:47 +0400 Subject: [PATCH 092/418] mongo replicaSets support --- core/NoSQL/MongoBase.class.php | 48 +- main/UI/Widget/DataGrid.class.php | 1442 ++++++++++++++--------------- 2 files changed, 764 insertions(+), 726 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index db9f9d305d..3dfd81cd5e 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -17,6 +17,16 @@ class MongoBase extends NoSQL { const C_LIMIT = 1005; const C_SKIP = 1006; + /** + * @var string|null + */ + protected $connectionString = null; + + /** + * @var array|null + */ + protected $connectionOptions = null; + /** * @var Mongo */ @@ -32,13 +42,23 @@ class MongoBase extends NoSQL { * @throws NoSQLException */ public function connect() { - $conn = - 'mongodb://' - .($this->username && $this->password ? "{$this->username}:{$this->password}@" : null) - .$this->hostname - .($this->port ? ":{$this->port}" : null); + if (empty($this->connectionString)) { + $conn = + 'mongodb://' + .($this->username && $this->password ? "{$this->username}:{$this->password}@" : null) + .$this->hostname + .($this->port ? ":{$this->port}" : null); + } else { + preg_match('#(.+)/(\w+)#', $this->connectionString, $matches); + $conn = $matches[1]; + $base = $matches[2]; + $this->setBasename($base); + } $options = array("connect" => true); + if (!empty($this->connectionOptions)) { + $options = array_merge($options, $this->connectionOptions); + } if ($this->persistent) { $options['persist'] = $this->hostname.'-'.$this->basename; @@ -79,6 +99,24 @@ public function isConnected() { return ($this->link instanceof Mongo && $this->link->connected); } + /** + * @param $connectionString + * @return MongoBase + */ + public function setConnectionString($connectionString) { + $this->connectionString = $connectionString; + return $this; + } + + /** + * @param $connectionOptions + * @return MongoBase + */ + public function setConnectionOptions($connectionOptions) { + $this->connectionOptions = $connectionOptions; + return $this; + } + /** * @param string $sequence * @return MongoId diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index 4c85aedbd7..a9d288f1a3 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -1,721 +1,721 @@ - - * @date 2012.03.19 - */ -class DataGrid extends BaseWidget -{ - /** @var DataGrid для вложенных таблиц */ - protected $parent = null; - - /** @var int предел вложенности */ - protected static $maxNesting = 1; - - /** @var array список дочерних объектов */ - protected $objects = array(); - - - /** @var array список 'fieldID' => 'Field name' */ - protected $fields = array(); - - /** @var array список полей, по которым можно сортировать. - * Фактически, исключает поля, добавленные через addColumn */ - protected $sortingFields = array(); - - /** @var array список 'fieldID' => callback() */ - protected $renderers = array(); - - /** @var array массив строк таблицы */ - protected $rows = array(); - - - /** @var array аттрибуты заголовков таблицы */ - protected $fieldHtmlOptions = array(); - - /** @var array аттрибуты */ - protected $formHtmlOptions = array(); - - /** @var bool показывать заголовки или нет */ - protected $showHeader = true; - - /** @var bool показывать кнопки сортировки */ - protected $showSorting = true; - - /** @var bool делать редактируемые поля */ - protected $isEditor = false; - - /** @var Form для вывода ошибок в заполнении полей */ - protected $form = null; - - /** @var string текстовый вывод булевого типа */ - public $trueName = null; - - /** @var string текстовый вывод булевого типа */ - public $falseName = null; - - /** - * Создает таблицу вида сводки (заголовок слева) - * @static - * @return DataGrid - */ - public static function details() { - $self = self::create(); - $self->templateName = 'DataGrid_details'; - $self->showSorting = false; - return $self; - } - - /** - * Создает обычную таблицу - * @static - * @return DataGrid - */ - public static function table() { - $self = self::create(); - $self->templateName = 'DataGrid_table'; - $self->showSorting = true; - return $self; - } - - /** - * DataGrid::details() в виде редактируемой формы. - * Следует добавлять только 1 объект. - * @static - * @return DataGrid - */ - public static function editor($subfield = null) { - $self = self::details(); - $self->isEditor = true; - return $self; - } - - /** - * @static - * @return DataGrid - */ - private static function create() { - $self = new self; - $self->trueName = __('Да'); - $self->falseName = __('Нет'); - return $self; - } - - /** - * Вызывает addRow для каждой из переданных строк - * @param array $data - * @return DataGrid - * @throws WrongArgumentException - */ - public function addRows(array $data) { - foreach ($data as $row) { - $this->addRow($row); - } - return $this; - } - - /** - * Добавляет строку в таблицу, определяет тип и имена ее полей - * @param $data - * @return DataGrid - * @throws WrongArgumentException - */ - public function addRow($data) { - $rowId = count($this->rows); // id следующей строки - - // если это объект, то смотрим его поля в протипе - // и через геттеры получаем все параметры, а если - // это массив, то берем его как есть. - - if (is_object($data) && $data instanceof Prototyped) { - /** @var $data Prototyped */ - $this->objects[$rowId] = $data; - $fieldIds = array(); - $row = array(); - foreach ($data->proto()->getPropertyList() as $property) { - try { - $getter = $property->getGetter(); - $value = $this->objects[$rowId]->$getter(); - } catch (BadMethodCallException $e) { - continue; - } catch (ObjectNotFoundException $e) { - $value = null; - } - $fieldIds[] = $property->getName(); - $row[$property->getName()] = $value; - } - } else if (is_array($data)) { - $fieldIds = array_keys($data); - $row = $data; - } else { - throw new WrongArgumentException('$data should be either array or prototyped object'); - } - // сохраним в список сортируемых полей - foreach ($fieldIds as $fieldId) { - if (!in_array($fieldId, $this->sortingFields)) { - $this->sortingFields[] = $fieldId; - } - } - - // построим массив полей в виде 'имяПоля' => 'Имя поля' - // ключ - имя параметра, значение - имя для отображения - $fields = array(); - foreach($fieldIds as $fieldId) { - $fieldName = self::beautifyFieldName($fieldId); - $fields[$fieldId] = $fieldName; - } - // сливаем с существующим списком, чтобы ничего не потерять, - // если например отработали не все геттеры, и поле пропущено - $this->fields = array_merge($this->fields, $fields); - - // записываем данные - foreach($row as $fieldId => $value) { - $this->setField($rowId, $fieldId, $value); - } - - return $this; - } - - /** - * Выставляет значение конкретного поля конкретной строки - * @param $rowId - * @param $fieldId - * @param $value - * @param $property LightMetaProperty если null, определится - * @return DataGrid - */ - private function setField($rowId, $fieldId, $value, $property = null) { - $this->rows[$rowId][$fieldId] = $value; - if (!isset($this->renderers[$fieldId])) { - if ($this->isEditor) { - if ($property == null) { - /** @var $object Prototyped */ - $object = $this->objects[$rowId]; - if ( !($object instanceof Prototyped) ) { - throw new WrongArgumentException; - } - $property = $object->proto()->getPropertyByName($fieldId); - } - - $this->renderers[$fieldId] = $this->getEditRenderer($fieldId, $property); - } else { - if ($value !== null) { - $this->renderers[$fieldId] = $this->getViewRenderer($value); - } - } - } - - return $this; - } - - - /** - * Дополнительная колонка - * @param string $fieldName - * @param Closure $renderer callback - * @param string|null $fieldId - * @return DataGrid - */ - public function addColumn($fieldName, $renderer, $fieldId = null) { - // если это поле не для данных (иконки действий, например) - // можно сгенерить рандомное имя поля, т.к. оно не важно - if ($fieldId === null) { - $fieldId = md5($fieldName); - } else { - // Если поле указано явно, добавим сразу для него сортировку - $this->sortingFields[] = $fieldId; - } - - $this->fields[$fieldId] = $fieldName; - $this->setRenderer($fieldId, $renderer); - return $this; - } - - /** - * @param string $fieldId - * @param LightMetaProperty $property - * @return closure - * @throws ClassNotFoundException - */ - protected function getEditRenderer($fieldId, LightMetaProperty $property) { - switch($property->getType()) { - case 'integer': - case 'float': - case 'string': - return function ($value) use ($fieldId, $property) { - if ($value instanceof Stringable) $value = $value->toString(); - if ($property->getType() == 'string' && !$property->getMax()) { - return ''; - } else { - $styleWidth = $property->getType() == 'string' ? 250 : 80; - $length = $property->getType() == 'string' ? $property->getMax() : 16; - return ''; - } - - }; - - case 'timestamp': - case 'date': - return function ($value) use ($fieldId, $property) { - if ($value instanceof Date) - $val = $value->toDate('-'); - else $val = ''; - - return ''; - }; - - case 'boolean': - return function ($value) use ($fieldId) { - return ''; - }; - - case 'enumeration': - return function ($value) use ($fieldId, $property) { - $class = $property->getClassName(); - if (!class_exists($class, true)) { - throw new ClassNotFoundException; - } - $list = $class::makeObjectList(); - $html = ''; - return $html; - }; - - case 'integerIdentifier': - return function ($value) use ($property) { - if ($value instanceof Identifiable) { - $value = $value->getId(); - } - return $property->getClassName() . ' ID: ' . $value; - }; - - case 'identifierList': - return function ($value) use ($property) { - //if (is_subclass_of($property->getClassName(), 'Enumeration')) { - // return 'enum'; - //} else { - return $property->getClassName(); - //} - }; - - default: - return function ($value) use ($property) { - // DEBUG - $props[] = 'name: ' . $property->getName(); - $props[] = 'className: ' . $property->getClassName(); - $props[] = 'type: ' . $property->getType(); - $props[] = 'min: ' . $property->getMin(); - $props[] = 'max: ' . $property->getMax(); - $props[] = 'relation: ' . $property->getRelationId(); - $props[] = 'fetch: ' . $property->getFetchStrategyId(); - //$props[] = 'value: ' . $value; - return implode(', ', $props); - }; - } - } - - /** - * Находит подходящий рендерер в соответствии с типом значения - * @param $value - * @return Closure - */ - protected function getViewRenderer($value) { - // переменные для замыканий, т.к. они не биндятся к this - $self = $this; - $trueName = $this->trueName; - $falseName = $this->falseName; - - // для прототипированного объекта можно построить - // вложенную табличку. Важно запомнить родителя, - // чтобы избежать бесконечной рекурсии - if ($value instanceof Prototyped) - return function($value, $object) use ($self) { - if ($self->hasParent($object)) { - return get_class($value) . ' ID:' . $value->getId(); - } else { - try { - return DataGrid::details()->setParent($self)->addRow($value)->ToString(); - } catch (Exception $e) { - return $e->getMessage(); - } - } - }; - - - // Это в основном для тех случаев, когда у объекта есть - // OneToMany свойство. UnifiedContainer позволяет получить - // список дочерних объектов - if ($value instanceof UnifiedContainer) - return function(UnifiedContainer $value, $object) use ($self) { - if ($self->hasParent($object)) { - return get_class($value) . ' count:' . $value->fetch()->getCount(); - } else { - try { - return DataGrid::table()->setParent($self)->addRows($value->fetch()->getList())->ToString(); - } catch (Exception $e) { - return $e->getMessage(); - } - } - }; - - - // Булевы выведем для удобства словами "Да" или "Нет" - if (is_bool($value)) - return function ($value) use ($trueName, $falseName) { - return $value ? $trueName : $falseName; - }; - - - // Встроенная табличка - if (is_array($value)) - return function($value) use ($self) { - try { - return DataGrid::table()->setParent($self)->addRows($value)->ToString(); - } catch (Exception $e) { - return $e->getMessage(); - } - }; - - - // Заглушка для всех прочих объектов - if (is_object($value)) - return function ($value) { - if (is_null($value)) { - return ''; - } - if ($value instanceof Stringable) - return $value->toString(); - if (method_exists($value, '__toString')) - return (string)$value; - return 'object('.get_class($value).')'; - }; - - if (is_string($value)) - return function ($value) { - return nl2br($value); - }; - - // прочие случаи - return function($value) { return $value; }; - } - - /** - * 'somePropertyName' => 'Some property name' - * @param $camelCaseString - * @return string - */ - public static function beautifyFieldName($camelCaseString) { - return ucfirst( - preg_replace_callback( - '/([a-z])([A-Z])/', - function($x) { - return $x[1] . ' ' . strtolower($x[2]); - }, - $camelCaseString - ) - ); - } - - /** - * @param DataGrid $parent - * @return DataGrid - */ - public function setParent(DataGrid $parent) { - $this->parent = $parent; - return $this; - } - - /** - * Рекурсивная проверка - * @param $object - * @return bool - */ - public function hasParent($object) { - $dataGrid = $this; - $nesting = 0; - while ($dataGrid = $dataGrid->parent) { - if ($nesting++ > self::$maxNesting) - return true; - foreach ($dataGrid->objects as $o) { - if ($o == $object) { - return true; - } - if ($o instanceof Identifiable && $object instanceof Identifiable - && get_class($o) == get_class($object) - && $o->getId() == $object->getId()) { - return true; - } - } - } - return false; - } - - /** - * @param $number - * @return DataGrid - */ - public function setMaxNesting($number) { - self::$maxNesting = $number; - return $this; - } - - /** - * @return int - */ - public static function getMaxNesting() { - return self::$maxNesting; - } - - /** - * Задает массив столбцов таблицы - * @param array $fields array('fieldID' => 'Field name', ...) - * @return DataGrid - */ - public function setFields(array $fields) { - $this->fields = $fields; - - /* При добавлении объекта, из него выгребаются все свойства, - * но только его собственные, а зависимые объекты не подгружаются - * Допустим, мы хотим добавить employee.user.name для отображении - * имени менеджера, когда выводим инфу по рекламодателю. Тогда - * следующий код сделает следующую цепочку вызовов: - * $advertiser->getEmployee()->getUser()->getName() - * и заполнит соответствующие поля таблицы значениями. - * */ - - foreach ($this->fields as $fieldId => $fieldName) { - if (strpos($fieldId, '.') !== false) { - $path = explode('.', $fieldId); - foreach ($this->rows as $rowId => $row) { - $object = $this->objects[$rowId]; - - $failed = false; - foreach ($path as $propertyName) { - if (!$object || !($object instanceof Prototyped)) { - $failed = true; - break; - } - $property = $object->proto()->getPropertyByName($propertyName); - if ($property != null) { - $getter = $property->getGetter(); - $object = $object->$getter(); - } else { - $failed = true; - break; - } - } - - if (!$failed) { - $this->setField($rowId, $fieldId, $object, $property); - $this->sortingFields[] = $fieldId; - } - } - } - } - - return $this; - } - - /** - * Исключает столбцы из таблицы - * можно использовать маски, напр: unsetFields('webmaster.*'); - * @param $_ string, string, ... OR array - * @return DataGrid - */ - public function unsetFields($_) { - if (is_array($_)) $fields = $_; - else $fields = func_get_args(); - foreach($fields as $fieldId) { - if (substr($fieldId, -1) == '*') { - $prefix = substr($fieldId, 0, strlen($fieldId) - 1); - foreach ($this->fields as $fieldId => $fieldName) { - if (substr($fieldId, 0, strlen($prefix)) == $prefix) { - unset($this->fields[$fieldId]); - } - } - } else { - unset($this->fields[$fieldId]); - } - } - return $this; - } - - /** - * @param $fieldId string - * @param $callback Closure function($value, $rowObject) {} - * @return DataGrid - */ - public function setRenderer($fieldId, $callback) { - $this->renderers[$fieldId] = $callback; - return $this; - } - - /** - * Показать названия колонок - * @return DataGrid - */ - public function showHeader() { - $this->showHeader = true; - return $this; - } - - /** - * Скрыть названия колонок - * @return DataGrid - */ - public function hideHeader() { - $this->showHeader = false; - return $this; - } - - /** - * @param array $fields - */ - public function setSortingFields(array $fields) { - $this->sortingFields = $fields; - return $this; - } - - /** - * Исключает столбцы из списка столбцов для сортировки - * @param $_ string, string, ... OR array - * @return DataGrid - */ - public function unsetSortingFields($_) { - if (is_array($_)) $fields = $_; - else $fields = func_get_args(); - foreach($fields as $fieldId) { - foreach($this->sortingFields as $k=>$v) { - if ($v == $fieldId) { - unset($this->sortingFields[$k]); - } - } - } - return $this; - } - - /** - * @return DataGrid - */ - public function showSorting() { - $this->showSorting = true; - return $this; - } - - /** - * @return DataGrid - */ - public function hideSorting() { - $this->showSorting = false; - return $this; - } - - /** - * @param string $fieldId - * @param array $htmlOptions - * @return DataGrid - */ - public function setHeaderOptions($fieldId, $htmlOptions) { - $this->fieldHtmlOptions[$fieldId] = $htmlOptions; - return $this; - } - - /** - * @param array $htmlOptions - * @return DataGrid - */ - public function setFormOptions($htmlOptions) { - $this->formHtmlOptions = $htmlOptions; - return $this; - } - - /** - * @param $formErrors - * @return DataGrid - */ - public function setForm(Form $form) { - $this->form = $form; - return $this; - } - - /** - * @return Model - */ - protected function makeModel() { - $data = array(); - // рендерим данные - foreach ($this->rows as $rowId => $row) { - foreach ($this->fields as $fieldId => $fieldName) { - $field = isset($row[$fieldId]) ? $row[$fieldId] : null; - if ($this->form instanceof Form && $this->form->exists($fieldId)) { - if ($this->form->get($fieldId)->isImported()) - $field = $this->form->get($fieldId)->getValue(); - else if ($this->form->hasError($fieldId)) - $field = $this->form->get($fieldId)->getRawValue(); - } - - // если есть рендерер, прогоним значение через него - if (isset($this->renderers[$fieldId])) { - $callback = $this->renderers[$fieldId]; - $object = isset($this->objects[$rowId]) ? $this->objects[$rowId] : $this->rows[$rowId]; - if ($this->renderers[$fieldId] instanceof Closure) { - $field = $callback($field, $object); - } else { - $field = call_user_func($callback, $field, $object); - } - } - $data[$rowId][$fieldId] = $field; - } - } - - // отрендерим аттрибуты html - $htmlOptions = array(); - foreach ($this->fields as $fieldId => $fieldName) { - if (isset($this->fieldHtmlOptions[$fieldId])) { - $htmlOptions[$fieldId] = Html::attributes($this->fieldHtmlOptions[$fieldId]); - } else { - $htmlOptions[$fieldId] = ''; - } - } - - // отрендерим аттрибуты формы - $selfUrl = null; - try { - $controller = Application::me()->getRunningController(); - $selfUrl = $controller->getSelfUrl()->__toString(); - } catch (UnexpectedValueException $e) { - $selfUrl = $_SERVER['REQUEST_URI']; - $this->hideSorting(); - } - $formOptions = Html::attributes(array_merge( - array('action' => $selfUrl, 'method' => 'POST'), - $this->formHtmlOptions - )); - - $model = parent::makeModel() - ->set('fields', $this->fields) - ->set('data', $data) - ->set('htmlOptions', $htmlOptions) - ->set('formOptions', $formOptions) - ->set('showHeader', $this->showHeader) - ->set('showSorting', $this->showSorting) - ->set('sortingFields', $this->sortingFields) - ->set('isEditor', $this->isEditor) - ->set('form', $this->form); - ; - - return $model; - } -} + + * @date 2012.03.19 + */ +class DataGrid extends BaseWidget +{ + /** @var DataGrid для вложенных таблиц */ + protected $parent = null; + + /** @var int предел вложенности */ + protected static $maxNesting = 1; + + /** @var array список дочерних объектов */ + protected $objects = array(); + + + /** @var array список 'fieldID' => 'Field name' */ + protected $fields = array(); + + /** @var array список полей, по которым можно сортировать. + * Фактически, исключает поля, добавленные через addColumn */ + protected $sortingFields = array(); + + /** @var array список 'fieldID' => callback() */ + protected $renderers = array(); + + /** @var array массив строк таблицы */ + protected $rows = array(); + + + /** @var array аттрибуты заголовков таблицы */ + protected $fieldHtmlOptions = array(); + + /** @var array аттрибуты */ + protected $formHtmlOptions = array(); + + /** @var bool показывать заголовки или нет */ + protected $showHeader = true; + + /** @var bool показывать кнопки сортировки */ + protected $showSorting = true; + + /** @var bool делать редактируемые поля */ + protected $isEditor = false; + + /** @var Form для вывода ошибок в заполнении полей */ + protected $form = null; + + /** @var string текстовый вывод булевого типа */ + public $trueName = null; + + /** @var string текстовый вывод булевого типа */ + public $falseName = null; + + /** + * Создает таблицу вида сводки (заголовок слева) + * @static + * @return DataGrid + */ + public static function details() { + $self = self::create(); + $self->templateName = 'DataGrid_details'; + $self->showSorting = false; + return $self; + } + + /** + * Создает обычную таблицу + * @static + * @return DataGrid + */ + public static function table() { + $self = self::create(); + $self->templateName = 'DataGrid_table'; + $self->showSorting = true; + return $self; + } + + /** + * DataGrid::details() в виде редактируемой формы. + * Следует добавлять только 1 объект. + * @static + * @return DataGrid + */ + public static function editor($subfield = null) { + $self = self::details(); + $self->isEditor = true; + return $self; + } + + /** + * @static + * @return DataGrid + */ + private static function create() { + $self = new self; + $self->trueName = __('Да'); + $self->falseName = __('Нет'); + return $self; + } + + /** + * Вызывает addRow для каждой из переданных строк + * @param array $data + * @return DataGrid + * @throws WrongArgumentException + */ + public function addRows(array $data) { + foreach ($data as $row) { + $this->addRow($row); + } + return $this; + } + + /** + * Добавляет строку в таблицу, определяет тип и имена ее полей + * @param $data + * @return DataGrid + * @throws WrongArgumentException + */ + public function addRow($data) { + $rowId = count($this->rows); // id следующей строки + + // если это объект, то смотрим его поля в протипе + // и через геттеры получаем все параметры, а если + // это массив, то берем его как есть. + + if (is_object($data) && $data instanceof Prototyped) { + /** @var $data Prototyped */ + $this->objects[$rowId] = $data; + $fieldIds = array(); + $row = array(); + foreach ($data->proto()->getPropertyList() as $property) { + try { + $getter = $property->getGetter(); + $value = $this->objects[$rowId]->$getter(); + } catch (BadMethodCallException $e) { + continue; + } catch (ObjectNotFoundException $e) { + $value = null; + } + $fieldIds[] = $property->getName(); + $row[$property->getName()] = $value; + } + } else if (is_array($data)) { + $fieldIds = array_keys($data); + $row = $data; + } else { + throw new WrongArgumentException('$data should be either array or prototyped object'); + } + // сохраним в список сортируемых полей + foreach ($fieldIds as $fieldId) { + if (!in_array($fieldId, $this->sortingFields)) { + $this->sortingFields[] = $fieldId; + } + } + + // построим массив полей в виде 'имяПоля' => 'Имя поля' + // ключ - имя параметра, значение - имя для отображения + $fields = array(); + foreach($fieldIds as $fieldId) { + $fieldName = self::beautifyFieldName($fieldId); + $fields[$fieldId] = $fieldName; + } + // сливаем с существующим списком, чтобы ничего не потерять, + // если например отработали не все геттеры, и поле пропущено + $this->fields = array_merge($this->fields, $fields); + + // записываем данные + foreach($row as $fieldId => $value) { + $this->setField($rowId, $fieldId, $value); + } + + return $this; + } + + /** + * Выставляет значение конкретного поля конкретной строки + * @param $rowId + * @param $fieldId + * @param $value + * @param $property LightMetaProperty если null, определится + * @return DataGrid + */ + private function setField($rowId, $fieldId, $value, $property = null) { + $this->rows[$rowId][$fieldId] = $value; + if (!isset($this->renderers[$fieldId])) { + if ($this->isEditor) { + if ($property == null) { + /** @var $object Prototyped */ + $object = $this->objects[$rowId]; + if ( !($object instanceof Prototyped) ) { + throw new WrongArgumentException; + } + $property = $object->proto()->getPropertyByName($fieldId); + } + + $this->renderers[$fieldId] = $this->getEditRenderer($fieldId, $property); + } else { + if ($value !== null) { + $this->renderers[$fieldId] = $this->getViewRenderer($value); + } + } + } + + return $this; + } + + + /** + * Дополнительная колонка + * @param string $fieldName + * @param Closure $renderer callback + * @param string|null $fieldId + * @return DataGrid + */ + public function addColumn($fieldName, $renderer, $fieldId = null) { + // если это поле не для данных (иконки действий, например) + // можно сгенерить рандомное имя поля, т.к. оно не важно + if ($fieldId === null) { + $fieldId = md5($fieldName); + } else { + // Если поле указано явно, добавим сразу для него сортировку + $this->sortingFields[] = $fieldId; + } + + $this->fields[$fieldId] = $fieldName; + $this->setRenderer($fieldId, $renderer); + return $this; + } + + /** + * @param string $fieldId + * @param LightMetaProperty $property + * @return closure + * @throws ClassNotFoundException + */ + protected function getEditRenderer($fieldId, LightMetaProperty $property) { + switch($property->getType()) { + case 'integer': + case 'float': + case 'string': + return function ($value) use ($fieldId, $property) { + if ($value instanceof Stringable) $value = $value->toString(); + if ($property->getType() == 'string' && !$property->getMax()) { + return ''; + } else { + $styleWidth = $property->getType() == 'string' ? 250 : 80; + $length = $property->getType() == 'string' ? $property->getMax() : 16; + return ''; + } + + }; + + case 'timestamp': + case 'date': + return function ($value) use ($fieldId, $property) { + if ($value instanceof Date) + $val = $value->toDate('-'); + else $val = ''; + + return ''; + }; + + case 'boolean': + return function ($value) use ($fieldId) { + return ''; + }; + + case 'enumeration': + return function ($value) use ($fieldId, $property) { + $class = $property->getClassName(); + if (!class_exists($class, true)) { + throw new ClassNotFoundException; + } + $list = $class::makeObjectList(); + $html = ''; + return $html; + }; + + case 'integerIdentifier': + return function ($value) use ($property) { + if ($value instanceof Identifiable) { + $value = $value->getId(); + } + return $property->getClassName() . ' ID: ' . $value; + }; + + case 'identifierList': + return function ($value) use ($property) { + //if (is_subclass_of($property->getClassName(), 'Enumeration')) { + // return 'enum'; + //} else { + return $property->getClassName(); + //} + }; + + default: + return function ($value) use ($property) { + // DEBUG + $props[] = 'name: ' . $property->getName(); + $props[] = 'className: ' . $property->getClassName(); + $props[] = 'type: ' . $property->getType(); + $props[] = 'min: ' . $property->getMin(); + $props[] = 'max: ' . $property->getMax(); + $props[] = 'relation: ' . $property->getRelationId(); + $props[] = 'fetch: ' . $property->getFetchStrategyId(); + //$props[] = 'value: ' . $value; + return implode(', ', $props); + }; + } + } + + /** + * Находит подходящий рендерер в соответствии с типом значения + * @param $value + * @return Closure + */ + protected function getViewRenderer($value) { + // переменные для замыканий, т.к. они не биндятся к this + $self = $this; + $trueName = $this->trueName; + $falseName = $this->falseName; + + // для прототипированного объекта можно построить + // вложенную табличку. Важно запомнить родителя, + // чтобы избежать бесконечной рекурсии + if ($value instanceof Prototyped) + return function($value, $object) use ($self) { + if ($self->hasParent($object)) { + return get_class($value) . ' ID:' . $value->getId(); + } else { + try { + return DataGrid::details()->setParent($self)->addRow($value)->ToString(); + } catch (Exception $e) { + return $e->getMessage(); + } + } + }; + + + // Это в основном для тех случаев, когда у объекта есть + // OneToMany свойство. UnifiedContainer позволяет получить + // список дочерних объектов + if ($value instanceof UnifiedContainer) + return function(UnifiedContainer $value, $object) use ($self) { + if ($self->hasParent($object)) { + return get_class($value) . ' count:' . $value->fetch()->getCount(); + } else { + try { + return DataGrid::table()->setParent($self)->addRows($value->fetch()->getList())->ToString(); + } catch (Exception $e) { + return $e->getMessage(); + } + } + }; + + + // Булевы выведем для удобства словами "Да" или "Нет" + if (is_bool($value)) + return function ($value) use ($trueName, $falseName) { + return $value ? $trueName : $falseName; + }; + + + // Встроенная табличка + if (is_array($value)) + return function($value) use ($self) { + try { + return DataGrid::table()->setParent($self)->addRows($value)->ToString(); + } catch (Exception $e) { + return $e->getMessage(); + } + }; + + + // Заглушка для всех прочих объектов + if (is_object($value)) + return function ($value) { + if (is_null($value)) { + return ''; + } + if ($value instanceof Stringable) + return $value->toString(); + if (method_exists($value, '__toString')) + return (string)$value; + return 'object('.get_class($value).')'; + }; + + if (is_string($value)) + return function ($value) { + return nl2br($value); + }; + + // прочие случаи + return function($value) { return $value; }; + } + + /** + * 'somePropertyName' => 'Some property name' + * @param $camelCaseString + * @return string + */ + public static function beautifyFieldName($camelCaseString) { + return ucfirst( + preg_replace_callback( + '/([a-z])([A-Z])/', + function($x) { + return $x[1] . ' ' . strtolower($x[2]); + }, + $camelCaseString + ) + ); + } + + /** + * @param DataGrid $parent + * @return DataGrid + */ + public function setParent(DataGrid $parent) { + $this->parent = $parent; + return $this; + } + + /** + * Рекурсивная проверка + * @param $object + * @return bool + */ + public function hasParent($object) { + $dataGrid = $this; + $nesting = 0; + while ($dataGrid = $dataGrid->parent) { + if ($nesting++ > self::$maxNesting) + return true; + foreach ($dataGrid->objects as $o) { + if ($o == $object) { + return true; + } + if ($o instanceof Identifiable && $object instanceof Identifiable + && get_class($o) == get_class($object) + && $o->getId() == $object->getId()) { + return true; + } + } + } + return false; + } + + /** + * @param $number + * @return DataGrid + */ + public function setMaxNesting($number) { + self::$maxNesting = $number; + return $this; + } + + /** + * @return int + */ + public static function getMaxNesting() { + return self::$maxNesting; + } + + /** + * Задает массив столбцов таблицы + * @param array $fields array('fieldID' => 'Field name', ...) + * @return DataGrid + */ + public function setFields(array $fields) { + $this->fields = $fields; + + /* При добавлении объекта, из него выгребаются все свойства, + * но только его собственные, а зависимые объекты не подгружаются + * Допустим, мы хотим добавить employee.user.name для отображении + * имени менеджера, когда выводим инфу по рекламодателю. Тогда + * следующий код сделает следующую цепочку вызовов: + * $advertiser->getEmployee()->getUser()->getName() + * и заполнит соответствующие поля таблицы значениями. + * */ + + foreach ($this->fields as $fieldId => $fieldName) { + if (strpos($fieldId, '.') !== false) { + $path = explode('.', $fieldId); + foreach ($this->rows as $rowId => $row) { + $object = $this->objects[$rowId]; + + $failed = false; + foreach ($path as $propertyName) { + if (!$object || !($object instanceof Prototyped)) { + $failed = true; + break; + } + $property = $object->proto()->getPropertyByName($propertyName); + if ($property != null) { + $getter = $property->getGetter(); + $object = $object->$getter(); + } else { + $failed = true; + break; + } + } + + if (!$failed) { + $this->setField($rowId, $fieldId, $object, $property); + $this->sortingFields[] = $fieldId; + } + } + } + } + + return $this; + } + + /** + * Исключает столбцы из таблицы + * можно использовать маски, напр: unsetFields('webmaster.*'); + * @param $_ string, string, ... OR array + * @return DataGrid + */ + public function unsetFields($_) { + if (is_array($_)) $fields = $_; + else $fields = func_get_args(); + foreach($fields as $fieldId) { + if (substr($fieldId, -1) == '*') { + $prefix = substr($fieldId, 0, strlen($fieldId) - 1); + foreach ($this->fields as $fieldId => $fieldName) { + if (substr($fieldId, 0, strlen($prefix)) == $prefix) { + unset($this->fields[$fieldId]); + } + } + } else { + unset($this->fields[$fieldId]); + } + } + return $this; + } + + /** + * @param $fieldId string + * @param $callback Closure function($value, $rowObject) {} + * @return DataGrid + */ + public function setRenderer($fieldId, $callback) { + $this->renderers[$fieldId] = $callback; + return $this; + } + + /** + * Показать названия колонок + * @return DataGrid + */ + public function showHeader() { + $this->showHeader = true; + return $this; + } + + /** + * Скрыть названия колонок + * @return DataGrid + */ + public function hideHeader() { + $this->showHeader = false; + return $this; + } + + /** + * @param array $fields + */ + public function setSortingFields(array $fields) { + $this->sortingFields = $fields; + return $this; + } + + /** + * Исключает столбцы из списка столбцов для сортировки + * @param $_ string, string, ... OR array + * @return DataGrid + */ + public function unsetSortingFields($_) { + if (is_array($_)) $fields = $_; + else $fields = func_get_args(); + foreach($fields as $fieldId) { + foreach($this->sortingFields as $k=>$v) { + if ($v == $fieldId) { + unset($this->sortingFields[$k]); + } + } + } + return $this; + } + + /** + * @return DataGrid + */ + public function showSorting() { + $this->showSorting = true; + return $this; + } + + /** + * @return DataGrid + */ + public function hideSorting() { + $this->showSorting = false; + return $this; + } + + /** + * @param string $fieldId + * @param array $htmlOptions + * @return DataGrid + */ + public function setHeaderOptions($fieldId, $htmlOptions) { + $this->fieldHtmlOptions[$fieldId] = $htmlOptions; + return $this; + } + + /** + * @param array $htmlOptions + * @return DataGrid + */ + public function setFormOptions($htmlOptions) { + $this->formHtmlOptions = $htmlOptions; + return $this; + } + + /** + * @param $formErrors + * @return DataGrid + */ + public function setForm(Form $form) { + $this->form = $form; + return $this; + } + + /** + * @return Model + */ + protected function makeModel() { + $data = array(); + // рендерим данные + foreach ($this->rows as $rowId => $row) { + foreach ($this->fields as $fieldId => $fieldName) { + $field = isset($row[$fieldId]) ? $row[$fieldId] : null; + if ($this->form instanceof Form && $this->form->exists($fieldId)) { + if ($this->form->get($fieldId)->isImported()) + $field = $this->form->get($fieldId)->getValue(); + else if ($this->form->hasError($fieldId)) + $field = $this->form->get($fieldId)->getRawValue(); + } + + // если есть рендерер, прогоним значение через него + if (isset($this->renderers[$fieldId])) { + $callback = $this->renderers[$fieldId]; + $object = isset($this->objects[$rowId]) ? $this->objects[$rowId] : $this->rows[$rowId]; + if ($this->renderers[$fieldId] instanceof Closure) { + $field = $callback($field, $object); + } else { + $field = call_user_func($callback, $field, $object); + } + } + $data[$rowId][$fieldId] = $field; + } + } + + // отрендерим аттрибуты html + $htmlOptions = array(); + foreach ($this->fields as $fieldId => $fieldName) { + if (isset($this->fieldHtmlOptions[$fieldId])) { + $htmlOptions[$fieldId] = Html::attributes($this->fieldHtmlOptions[$fieldId]); + } else { + $htmlOptions[$fieldId] = ''; + } + } + + // отрендерим аттрибуты формы + $selfUrl = null; + try { + $controller = Application::me()->getRunningController(); + $selfUrl = $controller->getSelfUrl()->__toString(); + } catch (UnexpectedValueException $e) { + $selfUrl = $_SERVER['REQUEST_URI']; + $this->hideSorting(); + } + $formOptions = Html::attributes(array_merge( + array('action' => $selfUrl, 'method' => 'POST'), + $this->formHtmlOptions + )); + + $model = parent::makeModel() + ->set('fields', $this->fields) + ->set('data', $data) + ->set('htmlOptions', $htmlOptions) + ->set('formOptions', $formOptions) + ->set('showHeader', $this->showHeader) + ->set('showSorting', $this->showSorting) + ->set('sortingFields', $this->sortingFields) + ->set('isEditor', $this->isEditor) + ->set('form', $this->form); + ; + + return $model; + } +} From 4b41e5c749e37568dcfeba165ec318efb7be0f72 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Fri, 1 Jun 2012 15:47:32 +0400 Subject: [PATCH 093/418] some mongo fixes --- core/NoSQL/MongoBase.class.php | 4 ++ core/NoSQL/NoSQL.class.php | 1 + core/NoSQL/NoSqlDAO.class.php | 4 ++ core/NoSQL/NoSqlObject.class.php | 2 +- main/Base/LightMetaProperty.class.php | 7 ++++ meta/builders/AutoClassBuilder.class.php | 1 + meta/types/BasePropertyType.class.php | 48 ++++++++++++++++++------ 7 files changed, 54 insertions(+), 13 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 3dfd81cd5e..12c5d2f9a7 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -423,6 +423,10 @@ public function mapReduce($table, $map, $reduce, Criteria $criteria=null, $timeo return $list; } + public function increment($table, array $fields, Criteria $criteria = null) { + return null; + } + /// helper functions //@{ /** diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php index 81dff388a1..9c5338873c 100755 --- a/core/NoSQL/NoSQL.class.php +++ b/core/NoSQL/NoSQL.class.php @@ -47,6 +47,7 @@ abstract public function getIdListByField($table, $field, $value, Criteria $crit abstract public function find($table, $query); abstract public function findByCriteria(Criteria $criteria); abstract public function countByCriteria(Criteria $criteria); + abstract public function increment($table, array $fields, Criteria $criteria = null); abstract public function mapReduce($table, $map, $reduce, Criteria $criteria=null, $timeout=30, $out=array('inline'=>1)); diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 2984f68318..a391360fa4 100755 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -463,6 +463,10 @@ public function getCountByField($field, $value, Criteria $criteria = null) { public function mapReduce($map, $reduce, Criteria $criteria=null, $timeout=30, $out=array('inline'=>1)) { return $this->getLink()->mapReduce( $this->getTable(), $map, $reduce, $criteria, $timeout, $out ); } + + public function increment($field, $value, $criteria) { + return $this->getLink()->increment( $this->getTable(), $field, $value, $criteria ); + } //@} /** diff --git a/core/NoSQL/NoSqlObject.class.php b/core/NoSQL/NoSqlObject.class.php index bbf7b32a80..202553344e 100755 --- a/core/NoSQL/NoSqlObject.class.php +++ b/core/NoSQL/NoSqlObject.class.php @@ -44,7 +44,7 @@ public function toArray() { } // обрабатываем связи 1к1 elseif( in_array($property->getType(), self::$identifiers) && $property->getRelationId()==1 ) { $value = call_user_func(array($this, $property->getGetter().'Id')); - $entity[ $property->getColumnName() ] = is_numeric($value) ? (int)$value : $value; + $entity[ $property->getColumnName() ] = Assert::checkInteger($value) ? (int)$value : $value; } } // $entity[ '_id' ] = $this->id; diff --git a/main/Base/LightMetaProperty.class.php b/main/Base/LightMetaProperty.class.php index 50e92ce457..8ca3dbb4f1 100755 --- a/main/Base/LightMetaProperty.class.php +++ b/main/Base/LightMetaProperty.class.php @@ -70,6 +70,7 @@ class LightMetaProperty implements Stringable private $getter = null; private $setter = null; private $dropper = null; + private $defaulter = null; private $identifier = null; @@ -98,6 +99,7 @@ public static function fill( $property->getter = 'get'.$methodSuffix; $property->setter = 'set'.$methodSuffix; $property->dropper = 'drop'.$methodSuffix; + $property->defaulter = 'getDefault'.$methodSuffix; if ($columnName) $property->columnName = $columnName; @@ -168,6 +170,11 @@ public function getDropper() return $this->dropper; } + public function getDefaulter() + { + return $this->defaulter; + } + /** * @return LightMetaProperty **/ diff --git a/meta/builders/AutoClassBuilder.class.php b/meta/builders/AutoClassBuilder.class.php index 413fcdcbfc..dcdab4d968 100755 --- a/meta/builders/AutoClassBuilder.class.php +++ b/meta/builders/AutoClassBuilder.class.php @@ -86,6 +86,7 @@ public function __construct() $out .= "}\n"; } + /** @var $property MetaClassProperty */ foreach ($class->getProperties() as $property) { if (!self::doPropertyBuild($class, $property, $isNamed)) continue; diff --git a/meta/types/BasePropertyType.class.php b/meta/types/BasePropertyType.class.php index 04049505a9..180b858784 100755 --- a/meta/types/BasePropertyType.class.php +++ b/meta/types/BasePropertyType.class.php @@ -18,14 +18,14 @@ abstract public function getDeclaration(); abstract public function isMeasurable(); abstract public function toColumnType(); abstract public function getPrimitiveName(); - + protected $default = null; - + public function isGeneric() { return true; } - + public function toMethods( MetaClass $class, MetaClassProperty $property, @@ -34,26 +34,27 @@ public function toMethods( { return $this->toGetter($class, $property, $holder) + .( $this->hasDefault() ? $this->toGetterDefault($class, $property, $holder) : '' ) .$this->toSetter($class, $property, $holder); } - + public function hasDefault() { return ($this->default !== null); } - + public function getDefault() { return $this->default; } - + public function setDefault($default) { throw new UnsupportedMethodException( 'only generic non-object types can have default values atm' ); } - + public function toGetter( MetaClass $class, MetaClassProperty $property, @@ -64,9 +65,9 @@ public function toGetter( $name = $holder->getName().'->get'.ucfirst($property->getName()).'()'; else $name = $property->getName(); - + $methodName = 'get'.ucfirst($property->getName()); - + return <<getName().'->get'.ucfirst($property->getName()).'()'; + else + $name = $property->getName(); + + $methodName = 'getDefault'.ucfirst($property->getName()); + + return <<getType()->getDeclaration()}; +} + +EOT; + } + public function toSetter( MetaClass $class, MetaClassProperty $property, @@ -85,7 +109,7 @@ public function toSetter( { $name = $property->getName(); $methodName = 'set'.ucfirst($name); - + if ($holder) { return << Date: Sat, 2 Jun 2012 17:47:38 +0400 Subject: [PATCH 094/418] DBRaw return to life :) --- core/OSQL/DBRaw.class.php | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/core/OSQL/DBRaw.class.php b/core/OSQL/DBRaw.class.php index 3bd7b6c232..12869291bb 100755 --- a/core/OSQL/DBRaw.class.php +++ b/core/OSQL/DBRaw.class.php @@ -11,30 +11,31 @@ /** * Karma's destroyer. - * - * @deprecated since the begining of time - * + * * @ingroup OSQL **/ final class DBRaw implements LogicalObject { private $string = null; - + + /** + * @return DBRaw + **/ + public static function create($value) + { + return new self($value); + } + public function __construct($rawString) { - if (!defined('__I_HATE_MY_KARMA__')) - throw new UnsupportedMethodException( - 'do not use it. please.' - ); - $this->string = $rawString; } - + public function toDialectString(Dialect $dialect) { return $this->string; } - + public function toBoolean(Form $form) { throw new UnsupportedMethodException(); From de7a3f35746691b217951503cdbd58a4e6de4617 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Tue, 5 Jun 2012 20:23:52 +0400 Subject: [PATCH 095/418] slaveok --- core/NoSQL/MongoBase.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 12c5d2f9a7..6f6696df3a 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -66,6 +66,7 @@ public function connect() { try { $this->link = new Mongo($conn, $options); $this->db = $this->link->selectDB($this->basename); + MongoCursor::$slaveOkay = true; } catch(MongoConnectionException $e) { throw new NoSQLException( 'can not connect to MongoBase server: '.$e->getMessage() From d1389dc7ab83ae35534145eb33d5b240cbd801e9 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Fri, 8 Jun 2012 19:47:50 +0400 Subject: [PATCH 096/418] setSlaveOkay fix --- core/NoSQL/MongoBase.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 6f6696df3a..e938839962 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -55,7 +55,7 @@ public function connect() { $this->setBasename($base); } - $options = array("connect" => true); + $options = array('connect' => true, 'slaveOkay' => true); if (!empty($this->connectionOptions)) { $options = array_merge($options, $this->connectionOptions); } @@ -66,7 +66,7 @@ public function connect() { try { $this->link = new Mongo($conn, $options); $this->db = $this->link->selectDB($this->basename); - MongoCursor::$slaveOkay = true; + $this->link->setSlaveOkay($options['slaveOkay']); } catch(MongoConnectionException $e) { throw new NoSQLException( 'can not connect to MongoBase server: '.$e->getMessage() From 3de2414108a595aae73f5c8d992fb83d360ef619 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Sun, 10 Jun 2012 16:14:43 +0400 Subject: [PATCH 097/418] debug --- core/NoSQL/MongoBase.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index e938839962..e89d83f165 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -350,6 +350,7 @@ protected function mongoDelete($table, array $query, array $options) { * @return MongoCursor */ protected function mongoMakeCursor($table, array $query, array $fields=array(), array $order=null, $limit=null, $skip=null) { + file_put_contents( '/tmp/ap_tracking.log', json_encode($query), FILE_APPEND ); $cursor = $this ->db From 54ee9b680f4753fd6b5a63abcf4e80880bc77ae5 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Sun, 10 Jun 2012 16:20:31 +0400 Subject: [PATCH 098/418] fix --- core/NoSQL/MongoBase.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index e89d83f165..e938839962 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -350,7 +350,6 @@ protected function mongoDelete($table, array $query, array $options) { * @return MongoCursor */ protected function mongoMakeCursor($table, array $query, array $fields=array(), array $order=null, $limit=null, $skip=null) { - file_put_contents( '/tmp/ap_tracking.log', json_encode($query), FILE_APPEND ); $cursor = $this ->db From 4e090758512ff22a7488681cb48aeba4c0139e4d Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Sun, 10 Jun 2012 16:34:42 +0400 Subject: [PATCH 099/418] nosql expression fix --- core/Logic/NoSQLExpression.class.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index 2eb286ea8f..6e4a6fef04 100755 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -75,10 +75,17 @@ public function addField($fieldName) { /// condition setters //@{ public function addEq($field, $value) { + $dbValue = (string)$value; + if( Assert::checkInteger($value) ) { + $dbValue = (int)$value; + } elseif( Assert::checkFloat($value) ) { + $dbValue = (float)$value; + } + $this->conditions[] = array( self::C_TYPE => self::EXP_EQ, self::C_FIELD => (string)$field, - self::C_VALUE => Assert::checkInteger($value) ? (int)$value : $value, + self::C_VALUE => $dbValue, ); return $this; } From eb34ee441c16d3741cab675ed36bc8a7ac367edf Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Sun, 10 Jun 2012 19:26:30 +0400 Subject: [PATCH 100/418] nosql fix --- core/Base/Assert.class.php | 7 ++++++- core/Logic/NoSQLExpression.class.php | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/core/Base/Assert.class.php b/core/Base/Assert.class.php index 39843f2689..7dcd40c7f5 100755 --- a/core/Base/Assert.class.php +++ b/core/Base/Assert.class.php @@ -148,7 +148,7 @@ public static function isString($variable, $message = null) public static function isBoolean($variable, $message = null) { - if (!($variable === true || $variable === false)) + if (!self::checkBoolean($variable)) throw new WrongArgumentException( $message.', '.self::dumpArgument($variable) ); @@ -301,6 +301,11 @@ public static function checkScalar($value) return is_scalar($value); } + public static function checkBoolean($value) + { + return ($value === true || $value === false); + } + /** * Checking UUID * @see http://tools.ietf.org/html/rfc4122 diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index 6e4a6fef04..b55a0aed81 100755 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -76,7 +76,9 @@ public function addField($fieldName) { //@{ public function addEq($field, $value) { $dbValue = (string)$value; - if( Assert::checkInteger($value) ) { + if( Assert::checkBoolean($value) ) { + $dbValue = (bool)$value; + } elseif( Assert::checkInteger($value) ) { $dbValue = (int)$value; } elseif( Assert::checkFloat($value) ) { $dbValue = (float)$value; From e96edb6f6ac45a7a17379adb073da9564fed7977 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Tue, 12 Jun 2012 15:35:40 +0400 Subject: [PATCH 101/418] data grid --- main/UI/Widget/DataGrid.class.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index a9d288f1a3..068ae7a1d9 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -29,6 +29,9 @@ class DataGrid extends BaseWidget /** @var array массив строк таблицы */ protected $rows = array(); + /** @var int ИД строки с "итого" */ + protected $totalId = null; + /** @var array аттрибуты заголовков таблицы */ protected $fieldHtmlOptions = array(); @@ -108,8 +111,8 @@ private static function create() { * @throws WrongArgumentException */ public function addRows(array $data) { - foreach ($data as $row) { - $this->addRow($row); + foreach ($data as $key=>$row) { + $this->addRow($row, $key); } return $this; } @@ -120,8 +123,11 @@ public function addRows(array $data) { * @return DataGrid * @throws WrongArgumentException */ - public function addRow($data) { + public function addRow($data, $key) { $rowId = count($this->rows); // id следующей строки + if( $key=='total' ) { + $this->totalId = $rowId; + } // если это объект, то смотрим его поля в протипе // и через геттеры получаем все параметры, а если @@ -707,6 +713,7 @@ protected function makeModel() { $model = parent::makeModel() ->set('fields', $this->fields) ->set('data', $data) + ->set('totalId', $this->totalId) ->set('htmlOptions', $htmlOptions) ->set('formOptions', $formOptions) ->set('showHeader', $this->showHeader) From 95eb191848f376f526ac23ce80e881c140822158 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Tue, 12 Jun 2012 17:32:57 +0400 Subject: [PATCH 102/418] data grid fix --- main/UI/Widget/DataGrid.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index 068ae7a1d9..6dca223ca4 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -123,7 +123,7 @@ public function addRows(array $data) { * @return DataGrid * @throws WrongArgumentException */ - public function addRow($data, $key) { + public function addRow($data, $key=null) { $rowId = count($this->rows); // id следующей строки if( $key=='total' ) { $this->totalId = $rowId; From 7b93af02e124c91a11083ce8510c87668842f467 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Wed, 13 Jun 2012 17:27:27 +0400 Subject: [PATCH 103/418] nodeLogs restorer, Mongo "safe" writes --- core/NoSQL/MongoBase.class.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index e938839962..44dca731c5 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -37,6 +37,11 @@ class MongoBase extends NoSQL { */ protected $db = null; + /** + * @var int параметр safe + */ + protected $safeOnWrite = true; + /** * @return MongoDB * @throws NoSQLException @@ -67,6 +72,15 @@ public function connect() { $this->link = new Mongo($conn, $options); $this->db = $this->link->selectDB($this->basename); $this->link->setSlaveOkay($options['slaveOkay']); + // получаем количество реплик в статусах PRIMARY и SECONDARY в сете + $safe = 0; + foreach ($this->link->getHosts() as $host) { + if ($host['state'] == 1 || $host['state'] == 2) { + $safe++; + } + } + $this->safeOnWrite = $safe; + } catch(MongoConnectionException $e) { throw new NoSQLException( 'can not connect to MongoBase server: '.$e->getMessage() @@ -162,7 +176,7 @@ public function insert($table, array $row) { $this ->db ->selectCollection($table) - ->insert($row); + ->insert($row, array('safe' => $this->safeOnWrite)); // checking result if( !$result ) { throw new NoSQLException('Could not insert object: '.var_export($row, true)); @@ -184,7 +198,7 @@ public function update($table, array $row) { $this ->db ->selectCollection($table) - ->update(array('_id' => $id), $row); + ->update(array('_id' => $id), $row, array('safe' => $this->safeOnWrite)); // checking result if( !$result ) { throw new NoSQLException('Could not update object: '.var_export($row, true)); From cf7e2fa6a867e0816dac4b30bc2fa4096d396a97 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Wed, 13 Jun 2012 17:59:45 +0400 Subject: [PATCH 104/418] nodeLogs restorer, Mongo "safe" writes --- core/NoSQL/MongoBase.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 44dca731c5..478e59c8a5 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -73,12 +73,12 @@ public function connect() { $this->db = $this->link->selectDB($this->basename); $this->link->setSlaveOkay($options['slaveOkay']); // получаем количество реплик в статусах PRIMARY и SECONDARY в сете - $safe = 0; - foreach ($this->link->getHosts() as $host) { + $safe = 2; + /*foreach ($this->link->getHosts() as $host) { if ($host['state'] == 1 || $host['state'] == 2) { $safe++; } - } + }*/ $this->safeOnWrite = $safe; } catch(MongoConnectionException $e) { From dce9c28e8c2472b82ed034202975cd5b1d280a8e Mon Sep 17 00:00:00 2001 From: klkvsk Date: Wed, 13 Jun 2012 18:00:51 +0400 Subject: [PATCH 105/418] nodeLogs restorer, Mongo "safe" writes --- core/NoSQL/MongoBase.class.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 478e59c8a5..9fe9553c8a 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -73,13 +73,15 @@ public function connect() { $this->db = $this->link->selectDB($this->basename); $this->link->setSlaveOkay($options['slaveOkay']); // получаем количество реплик в статусах PRIMARY и SECONDARY в сете - $safe = 2; - /*foreach ($this->link->getHosts() as $host) { - if ($host['state'] == 1 || $host['state'] == 2) { + $safe = 0; + foreach ($this->link->getHosts() as $host) { + if (isset($host['state']) && ($host['state'] == 1 || $host['state'] == 2)) { $safe++; } - }*/ - $this->safeOnWrite = $safe; + } + if ($safe > 0) { + $this->safeOnWrite = $safe; + } } catch(MongoConnectionException $e) { throw new NoSQLException( From 2e6bf5bc68e4da4d1bc41b2146ff8dfdff354890 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 18 Jun 2012 16:12:56 +0400 Subject: [PATCH 106/418] fix weak typing in nosql object properties --- core/Logic/NoSQLExpression.class.php | 22 +++++++++++++---- core/NoSQL/NoSqlObject.class.php | 35 ++++------------------------ main/Utils/PrototypeUtils.class.php | 4 ++-- 3 files changed, 23 insertions(+), 38 deletions(-) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index b55a0aed81..e6acbdf1bc 100755 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -75,20 +75,32 @@ public function addField($fieldName) { /// condition setters //@{ public function addEq($field, $value) { + $strict = true; $dbValue = (string)$value; if( Assert::checkBoolean($value) ) { $dbValue = (bool)$value; + $strict = false; } elseif( Assert::checkInteger($value) ) { $dbValue = (int)$value; + $strict = false; } elseif( Assert::checkFloat($value) ) { $dbValue = (float)$value; + $strict = false; } - $this->conditions[] = array( - self::C_TYPE => self::EXP_EQ, - self::C_FIELD => (string)$field, - self::C_VALUE => $dbValue, - ); + if (!$strict /* weak typing */) { + $this->conditions[] = array( + self::C_TYPE => self::EXP_IN, + self::C_FIELD => (string)$field, + self::C_VALUE => array($dbValue, (string)$value), + ); + } else { + $this->conditions[] = array( + self::C_TYPE => self::EXP_EQ, + self::C_FIELD => (string)$field, + self::C_VALUE => $dbValue, + ); + } return $this; } diff --git a/core/NoSQL/NoSqlObject.class.php b/core/NoSQL/NoSqlObject.class.php index 202553344e..563f3c2a2f 100755 --- a/core/NoSQL/NoSqlObject.class.php +++ b/core/NoSQL/NoSqlObject.class.php @@ -17,38 +17,11 @@ **/ class NoSqlObject extends IdentifiableObject { - protected static $identifiers = array('identifier', 'integerIdentifier', 'scalarIdentifier', 'uuidIdentifier'); - + /** + * @return array + */ public function toArray() { - $entity = array(); - /** @var $property LightMetaProperty */ - foreach ($this->proto()->getPropertyList() as $property) { - // обрабатываем базовые типы - if( $property->isGenericType() ) { - $value = call_user_func(array($this, $property->getGetter())); - if( is_object( $value )&& $value instanceof Date ) { - $value = $value->toStamp(); - //$value = $value->toString(); - } - if( Assert::checkInteger($value) ) { - $entity[ $property->getColumnName() ] = (int)$value; - } elseif( Assert::checkFloat($value) ) { - $entity[ $property->getColumnName() ] = (float)$value; - } else { - $entity[ $property->getColumnName() ] = $value; - } - } // обрабатываем перечисления - elseif( $property->getType()=='enumeration' ) { - $value = call_user_func(array($this, $property->getGetter())); - $entity[ $property->getColumnName() ] = is_null($value) ? null : (int)$value->getId(); - } // обрабатываем связи 1к1 - elseif( in_array($property->getType(), self::$identifiers) && $property->getRelationId()==1 ) { - $value = call_user_func(array($this, $property->getGetter().'Id')); - $entity[ $property->getColumnName() ] = Assert::checkInteger($value) ? (int)$value : $value; - } - } -// $entity[ '_id' ] = $this->id; - return $entity; + return PrototypeUtils::toArray($this); } } diff --git a/main/Utils/PrototypeUtils.class.php b/main/Utils/PrototypeUtils.class.php index 375f5e26a6..8c4295db23 100755 --- a/main/Utils/PrototypeUtils.class.php +++ b/main/Utils/PrototypeUtils.class.php @@ -202,9 +202,9 @@ public static function toArray(Prototyped $object) { $value = $value->toStamp(); //$value = $value->toString(); } - if( Assert::checkInteger($value) ) { + if( $property->getType() == 'integer' ) { $entity[ $property->getColumnName() ] = (int)$value; - } elseif( Assert::checkFloat($value) ) { + } elseif( $property->getType() == 'float' ) { $entity[ $property->getColumnName() ] = (float)$value; } else { $entity[ $property->getColumnName() ] = $value; From 3f88d46c96592b77402efa72a9e4909e6430b87d Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 18 Jun 2012 16:27:15 +0400 Subject: [PATCH 107/418] fix toArray string property max length --- main/Utils/PrototypeUtils.class.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/main/Utils/PrototypeUtils.class.php b/main/Utils/PrototypeUtils.class.php index 8c4295db23..b683bf5859 100755 --- a/main/Utils/PrototypeUtils.class.php +++ b/main/Utils/PrototypeUtils.class.php @@ -206,6 +206,12 @@ public static function toArray(Prototyped $object) { $entity[ $property->getColumnName() ] = (int)$value; } elseif( $property->getType() == 'float' ) { $entity[ $property->getColumnName() ] = (float)$value; + } elseif( $property->getType() == 'string' ) { + $value = (string)$value; + if ($property->getMax() > 0) { + $value = substr($value, 0, $property->getMax()); + } + $entity[ $property->getColumnName() ] = $value; } else { $entity[ $property->getColumnName() ] = $value; } From fb9f6aa3d3bc476e77ce5266089eb583ee495512 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 18 Jun 2012 17:49:30 +0400 Subject: [PATCH 108/418] weaker typing --- core/Logic/NoSQLExpression.class.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index e6acbdf1bc..87d5593525 100755 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -79,7 +79,6 @@ public function addEq($field, $value) { $dbValue = (string)$value; if( Assert::checkBoolean($value) ) { $dbValue = (bool)$value; - $strict = false; } elseif( Assert::checkInteger($value) ) { $dbValue = (int)$value; $strict = false; @@ -92,7 +91,7 @@ public function addEq($field, $value) { $this->conditions[] = array( self::C_TYPE => self::EXP_IN, self::C_FIELD => (string)$field, - self::C_VALUE => array($dbValue, (string)$value), + self::C_VALUE => array((string)$value, (float)$value, (int)$value), ); } else { $this->conditions[] = array( From 4e28d1a549a0e1ecefd1544ff783e812b13a8a3d Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 18 Jun 2012 18:36:47 +0400 Subject: [PATCH 109/418] NoSQLExpression - NULL value handling --- core/Logic/NoSQLExpression.class.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index 87d5593525..6d9dda4b2e 100755 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -76,15 +76,18 @@ public function addField($fieldName) { //@{ public function addEq($field, $value) { $strict = true; - $dbValue = (string)$value; - if( Assert::checkBoolean($value) ) { + if (is_null($value)) { + $dbValue = null; + } else if (Assert::checkBoolean($value)) { $dbValue = (bool)$value; - } elseif( Assert::checkInteger($value) ) { + } elseif (Assert::checkInteger($value)) { $dbValue = (int)$value; $strict = false; - } elseif( Assert::checkFloat($value) ) { + } elseif (Assert::checkFloat($value)) { $dbValue = (float)$value; $strict = false; + } else { + $dbValue = (string)$value; } if (!$strict /* weak typing */) { From 27939568b6a040ba6f0eb500bb4a116556e03c65 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 25 Jun 2012 21:18:53 +0400 Subject: [PATCH 110/418] always safe=true --- core/NoSQL/MongoBase.class.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 9fe9553c8a..a413e5a050 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -83,6 +83,8 @@ public function connect() { $this->safeOnWrite = $safe; } + $this->safeOnWrite = true; + } catch(MongoConnectionException $e) { throw new NoSQLException( 'can not connect to MongoBase server: '.$e->getMessage() From 727dc3f9acee51be88ad5716173f38577159c659 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Thu, 28 Jun 2012 14:29:41 +0400 Subject: [PATCH 111/418] RussianTypograph - fix nested quotes --- core/Form/Filters/RussianTypograph.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/Form/Filters/RussianTypograph.class.php b/core/Form/Filters/RussianTypograph.class.php index 6d96d692fd..31d59769e3 100755 --- a/core/Form/Filters/RussianTypograph.class.php +++ b/core/Form/Filters/RussianTypograph.class.php @@ -63,7 +63,7 @@ final class RussianTypograph extends BaseFilter '~(\s)\s*~u', // n -> 2 whitespaces to process short strings (bar to a foo) '~([\s\pP]|^)([\w\pL]{1,2})\s~Uu', // bar a foo | bar to a foo '~( |\s)\s+~u', // compress whitespaces - '~\"(.*)\"~e', // "qu"o"te" + '~\"(.*?)\"~e', // "qu"o"te" '~\"([^\s]*)\"~', // "quote" '~\"([^\s]*)\s+([^\s\.]*)\"~', // "quote quote" '~([\w\pL\']+)~eu' // rock'n'roll From be78a8b77d61249280fe5811656f54ee2b1445f0 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 2 Jul 2012 13:26:55 +0400 Subject: [PATCH 112/418] mongo iterated result --- core/NoSQL/MongoBase.class.php | 22 +++++++ core/NoSQL/NoSQL.class.php | 1 + core/NoSQL/NoSqlDAO.class.php | 8 +++ core/NoSQL/NoSqlResult.class.php | 99 ++++++++++++++++++++++++++++ core/NoSQL/NoSqlResultList.class.php | 88 +++++++++++++++++++++++++ core/OSQL/QueryResult.class.php | 2 +- main/Criteria/Criteria.class.php | 12 ++-- 7 files changed, 227 insertions(+), 5 deletions(-) create mode 100644 core/NoSQL/NoSqlResult.class.php create mode 100644 core/NoSQL/NoSqlResultList.class.php diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index a413e5a050..fcaa0aaedc 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -332,6 +332,28 @@ public function deleteByCriteria(Criteria $criteria, array $options = array('saf $this->mongoDelete($query[self::C_TABLE], $query[self::C_QUERY], $options); } + /** + * @param Criteria $criteria + * @return MongoCursor + * @throws NoSQLException + */ + public function makeCursorByCriteria(Criteria $criteria) { + $options = $this->parseCriteria($criteria); + + if (!isset($options[self::C_TABLE])) { + throw new NoSQLException('Can not find without table!'); + } + + return $this->mongoMakeCursor( + $options[self::C_TABLE], + $options[self::C_QUERY], + $options[self::C_FIELDS], + $options[self::C_ORDER], + $options[self::C_LIMIT], + $options[self::C_SKIP] + ); + } + protected function mongoFind($table, array $query, array $fields=array(), array $order=null, $limit=null, $skip=null) { // quering $cursor = $this->mongoMakeCursor($table, $query, $fields, $order, $limit, $skip); diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php index 9c5338873c..ac8aa41412 100755 --- a/core/NoSQL/NoSQL.class.php +++ b/core/NoSQL/NoSQL.class.php @@ -47,6 +47,7 @@ abstract public function getIdListByField($table, $field, $value, Criteria $crit abstract public function find($table, $query); abstract public function findByCriteria(Criteria $criteria); abstract public function countByCriteria(Criteria $criteria); + abstract public function makeCursorByCriteria(Criteria $criteria); abstract public function increment($table, array $fields, Criteria $criteria = null); abstract public function mapReduce($table, $map, $reduce, Criteria $criteria=null, $timeout=30, $out=array('inline'=>1)); diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index a391360fa4..f93378c6b5 100755 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -191,6 +191,14 @@ public function getCustomRowList(SelectQuery $query, $expires = Cache::DO_NOT_CA public function getQueryResult(SelectQuery $query, $expires = Cache::DO_NOT_CACHE) { throw new UnsupportedMethodException( 'Can not execute "getQueryResult" in NoSQL' ); } + + public function getNoSqlResult(Criteria $criteria, $expires = Cache::DO_NOT_CACHE) { + $criteria->setDao( $this ); + $cursor = $this->getLink()->makeCursorByCriteria($criteria); + return NoSqlResult::create() + ->setDao($this) + ->setMongoCursor($cursor); + } //@} /// some queries diff --git a/core/NoSQL/NoSqlResult.class.php b/core/NoSQL/NoSqlResult.class.php new file mode 100644 index 0000000000..48dd89906c --- /dev/null +++ b/core/NoSQL/NoSqlResult.class.php @@ -0,0 +1,99 @@ + + * @date 2012.07.02 + */ +class NoSqlResult extends QueryResult { + /** @var NoSqlDAO */ + protected $dao; + + /** @var MongoCursor */ + protected $mongoCursor; + + /** @var NoSqlResultList */ + protected $resultList; + + /** + * @static + * @param MongoCursor $cursor + * @return NoSqlResult + */ + public static function create() { + return new static; + } + + /** + * @return NoSqlResultList + */ + public function getList() { + return $this->resultList; + } + + /** + * @param $resultList + * @return NoSqlResult + * @throws WrongArgumentException + */ + public function setList($resultList) { + if (!($resultList instanceof NoSqlResultList)) { + throw new WrongArgumentException('NoSqlResult accepts only NoSqlResultList in setList'); + } + $this->resultList = $resultList; + return $this; + } + + /** + * @param MongoCursor $cursor + * @return NoSqlResult + */ + public function setMongoCursor(MongoCursor $cursor) { + $this->mongoCursor = $cursor; + $this + ->setList(NoSqlResultList::create($this)) + ->setCount($cursor->count()); + return $this; + } + + /** + * @return MongoCursor + */ + public function getMongoCursor() { + return $this->mongoCursor; + } + + /** + * @param NoSqlDAO $dao + * @return NoSqlResult + */ + public function setDao(NoSqlDAO $dao) { + $this->dao = $dao; + return $this; + } + + /** + * @return NoSqlDAO + */ + public function getDao() { + return $this->dao; + } + + /** + * @return null|string + */ + public function getId() { + if ($this->getMongoCursor() == null) { + return null; + } + $queryInfo = $this->getMongoCursor()->info(); + return '_result_nosql_' . sha1(json_encode($queryInfo['query'])); + } + + public function setQuery(SelectQuery $query) { + throw new UnimplementedFeatureException('NoSqlResult has no SelectQuery'); + } + + public function getQuery() { + throw new UnimplementedFeatureException('NoSqlResult has no SelectQuery'); + } +} diff --git a/core/NoSQL/NoSqlResultList.class.php b/core/NoSQL/NoSqlResultList.class.php new file mode 100644 index 0000000000..dc967d842e --- /dev/null +++ b/core/NoSQL/NoSqlResultList.class.php @@ -0,0 +1,88 @@ + + * @date 2012.07.02 + */ +class NoSqlResultList implements Iterator { + /** @var NoSqlResult */ + protected $result; + + /** + * @param NoSqlResult $result + */ + protected function __construct(NoSqlResult $result) { + $this->result = $result; + } + + /** + * @param NoSqlResult $result + * @return NoSqlResultList + */ + public static function create(NoSqlResult $result) { + return new static($result); + } + + public function getResult() { + return $this->result; + } + + public function getCursor() { + return $this->getResult()->getMongoCursor(); + } + + /** + * (PHP 5 >= 5.0.0)
+ * Return the current element + * @link http://php.net/manual/en/iterator.cur;rent.php + * @return mixed Can return any type. + */ + public function current() { + $row = $this->getCursor()->current(); + $row['id'] = (string)$row['_id']; + unset($row['_id']); + return $this->result->getDao()->makeNoSqlObject($row); + } + + /** + * (PHP 5 >= 5.0.0)
+ * Rewind the Iterator to the first element + * @link http://php.net/manual/en/iterator.rewind.php + * @return void Any returned value is ignored. + */ + public function rewind() { + $this->getCursor()->rewind(); + } + + /** + * (PHP 5 >= 5.0.0)
+ * Checks if current position is valid + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + */ + public function valid() { + return $this->getCursor()->valid(); + } + + /** + * (PHP 5 >= 5.0.0)
+ * Return the key of the current element + * @link http://php.net/manual/en/iterator.key.php + * @return scalar scalar on success, or null on failure. + */ + public function key() { + return $this->getCursor()->key(); + } + + /** + * (PHP 5 >= 5.0.0)
+ * Move forward to next element + * @link http://php.net/manual/en/iterator.next.php + * @return void Any returned value is ignored. + */ + public function next() { + $this->getCursor()->next(); + } + +} diff --git a/core/OSQL/QueryResult.class.php b/core/OSQL/QueryResult.class.php index dfd94d6b17..ad8d7d77cf 100755 --- a/core/OSQL/QueryResult.class.php +++ b/core/OSQL/QueryResult.class.php @@ -14,7 +14,7 @@ * * @ingroup OSQL **/ - final class QueryResult implements Identifiable + class QueryResult implements Identifiable { private $list = array(); diff --git a/main/Criteria/Criteria.class.php b/main/Criteria/Criteria.class.php index b2da79d0c0..9f7e49fa5b 100755 --- a/main/Criteria/Criteria.class.php +++ b/main/Criteria/Criteria.class.php @@ -371,13 +371,17 @@ public function getList() } /** - * @return QueryResult + * @return QueryResult|NoSqlResult **/ public function getResult() { - $result = - $this->checkAndGetDao()-> - getQueryResult($this->toSelectQuery()); + $dao = $this->checkAndGetDao(); + if ($dao instanceof NoSqlDAO) { + /** @var $dao NoSqlDAO */ + $result = $dao->getNoSqlResult($this); + } else { + $result = $dao->getQueryResult($this->toSelectQuery()); + } if (!$this->collections || !$result->getCount()) return $result; From e9c998f737b444cba1e28b0ffa74e78a4eeadcaf Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 2 Jul 2012 16:08:53 +0400 Subject: [PATCH 113/418] mongo - safe --- core/NoSQL/MongoBase.class.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index fcaa0aaedc..25d5263f71 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -83,8 +83,6 @@ public function connect() { $this->safeOnWrite = $safe; } - $this->safeOnWrite = true; - } catch(MongoConnectionException $e) { throw new NoSQLException( 'can not connect to MongoBase server: '.$e->getMessage() From c78ec4b7cb0e7338ecd9a12ebc90125171370bd4 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 2 Jul 2012 20:10:45 +0400 Subject: [PATCH 114/418] unsafe save in nosqldao --- core/NoSQL/NoSqlDAO.class.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index f93378c6b5..456d887cc8 100755 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -261,6 +261,20 @@ public function take(Identifiable $object) { : $this->add($object); } + public function addNoCheck(NoSqlObject $object) { + $link = NoSqlPool::getByDao( $this ); + $entity = + $link + ->insert( + $this->getTable(), + $object->toArray() + ); + + $object->setId( $entity['id'] ); + + return $object; + } + public function add(Identifiable $object) { $this->assertNoSqlObject( $object ); @@ -329,6 +343,20 @@ public function multiAdd(array $objectList) { return $objectList; } + public function saveNoCheck(NoSqlObject $object) { + $link = NoSqlPool::getByDao( $this ); + + $entity = + $link + ->update( + $this->getTable(), + $object->toArray() + ); + $object->setId( $entity['id'] ); + + return $object; + } + public function save(Identifiable $object) { $this->assertNoSqlObject( $object ); From e4b7d11283e17511432c3c4e3fb1e7ccb65be033 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Thu, 5 Jul 2012 16:25:38 +0400 Subject: [PATCH 115/418] lazy count in mongo result --- core/NoSQL/NoSqlResult.class.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/core/NoSQL/NoSqlResult.class.php b/core/NoSQL/NoSqlResult.class.php index 48dd89906c..3f5555c45c 100644 --- a/core/NoSQL/NoSqlResult.class.php +++ b/core/NoSQL/NoSqlResult.class.php @@ -14,6 +14,8 @@ class NoSqlResult extends QueryResult { /** @var NoSqlResultList */ protected $resultList; + protected $count = null; + /** * @static * @param MongoCursor $cursor @@ -23,6 +25,14 @@ public static function create() { return new static; } + public function getCount() { + if ($this->count == null && $this->getMongoCursor()) { + $this->count = $this->getMongoCursor()->count(); + } + return $this->count; + } + + /** * @return NoSqlResultList */ @@ -51,7 +61,7 @@ public function setMongoCursor(MongoCursor $cursor) { $this->mongoCursor = $cursor; $this ->setList(NoSqlResultList::create($this)) - ->setCount($cursor->count()); + ->setCount(null); // lazy return $this; } From 9459da9436103e80a3ab09344e3629ae699d5707 Mon Sep 17 00:00:00 2001 From: Alex Gorbylev Date: Fri, 6 Jul 2012 11:00:59 +0400 Subject: [PATCH 116/418] fix --- main/UI/Widget/DataGrid.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index 6dca223ca4..a1521857fb 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -125,7 +125,7 @@ public function addRows(array $data) { */ public function addRow($data, $key=null) { $rowId = count($this->rows); // id следующей строки - if( $key=='total' ) { + if( isset($key) && $key=='total' ) { $this->totalId = $rowId; } From 766e2e3af08206619f826d202ad91cc627a254d6 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Tue, 17 Jul 2012 20:38:55 +0400 Subject: [PATCH 117/418] mongo - "safe" option in dao methods --- core/NoSQL/MongoBase.class.php | 18 ++++++++++++++---- core/NoSQL/NoSQL.class.php | 4 ++-- core/NoSQL/NoSqlDAO.class.php | 10 ++++++---- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 25d5263f71..8fb6d7636c 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -171,14 +171,19 @@ public function selectList($table, array $keys) { return $rows; } - public function insert($table, array $row) { + public function insert($table, array $row, $options = array()) { $row = $this->encodeId($row); + $options = array_merge( + array('safe' => true), + $options + ); + if ($options['safe']) $options['safe'] = $this->safeOnWrite; // save $result = $this ->db ->selectCollection($table) - ->insert($row, array('safe' => $this->safeOnWrite)); + ->insert($row, $options); // checking result if( !$result ) { throw new NoSQLException('Could not insert object: '.var_export($row, true)); @@ -191,16 +196,21 @@ public function batchInsert($table, array $rows) { throw new UnimplementedFeatureException('Unfortunately method "batchInsert" is not implemented yet :('); } - public function update($table, array $row) { + public function update($table, array $row, $options = array()) { $row = $this->encodeId($row); $id = $row['_id']; unset($row['_id']); + $options = array_merge( + array('safe' => true), + $options + ); + if ($options['safe']) $options['safe'] = $this->safeOnWrite; $result = $this ->db ->selectCollection($table) - ->update(array('_id' => $id), $row, array('safe' => $this->safeOnWrite)); + ->update(array('_id' => $id), $row, $options); // checking result if( !$result ) { throw new NoSQLException('Could not update object: '.var_export($row, true)); diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php index ac8aa41412..8979c70614 100755 --- a/core/NoSQL/NoSQL.class.php +++ b/core/NoSQL/NoSQL.class.php @@ -30,9 +30,9 @@ abstract class NoSQL extends DB { // queries abstract public function selectOne($table, $key); abstract public function selectList($table, array $keys); - abstract public function insert($table, array $row); + abstract public function insert($table, array $row, $options = array()); abstract public function batchInsert($table, array $rows); - abstract public function update($table, array $row); + abstract public function update($table, array $row, $options = array()); abstract public function deleteOne($table, $key); abstract public function deleteList($table, array $keys); diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 456d887cc8..9b691b155e 100755 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -261,13 +261,14 @@ public function take(Identifiable $object) { : $this->add($object); } - public function addNoCheck(NoSqlObject $object) { + public function addNoCheck(NoSqlObject $object, $safe = true) { $link = NoSqlPool::getByDao( $this ); $entity = $link ->insert( $this->getTable(), - $object->toArray() + $object->toArray(), + array('safe' => $safe) ); $object->setId( $entity['id'] ); @@ -343,14 +344,15 @@ public function multiAdd(array $objectList) { return $objectList; } - public function saveNoCheck(NoSqlObject $object) { + public function saveNoCheck(NoSqlObject $object, $safe = true) { $link = NoSqlPool::getByDao( $this ); $entity = $link ->update( $this->getTable(), - $object->toArray() + $object->toArray(), + array('safe' => $safe) ); $object->setId( $entity['id'] ); From 8cf9e65dfb667d3eb99dd422efbb51481942e728 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 19 Jul 2012 18:53:29 +0400 Subject: [PATCH 118/418] nosql expression fix --- core/Logic/NoSQLExpression.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index 6d9dda4b2e..975a99ecfc 100755 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -179,7 +179,9 @@ public function addBetweenSoft($field, $left, $right) { public function addIn($field, array $value) { foreach($value as &$inVal) { - if(Assert::checkInteger($inVal)) { + if( is_null($inVal) ) { + $inVal = null; + } elseif( Assert::checkInteger($inVal) ) { $inVal = (int)$inVal; } else { $inVal = (string)$inVal; From 6b73c06fbcec5a298a2b4a9145295317f742f16e Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 23 Jul 2012 19:26:04 +0400 Subject: [PATCH 119/418] pass _id in update object --- core/NoSQL/MongoBase.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 8fb6d7636c..6618666ec0 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -199,7 +199,7 @@ public function batchInsert($table, array $rows) { public function update($table, array $row, $options = array()) { $row = $this->encodeId($row); $id = $row['_id']; - unset($row['_id']); + //unset($row['_id']); $options = array_merge( array('safe' => true), $options From 91d12e1756f9e6902f4c80915d5d7e986a4dfad4 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 24 Jul 2012 15:42:21 +0400 Subject: [PATCH 120/418] nosql fix --- core/NoSQL/NoSqlResult.class.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/core/NoSQL/NoSqlResult.class.php b/core/NoSQL/NoSqlResult.class.php index 3f5555c45c..6680a870ca 100644 --- a/core/NoSQL/NoSqlResult.class.php +++ b/core/NoSQL/NoSqlResult.class.php @@ -106,4 +106,16 @@ public function setQuery(SelectQuery $query) { public function getQuery() { throw new UnimplementedFeatureException('NoSqlResult has no SelectQuery'); } + + public function setLimit($limit) { + Assert::isInteger($limit); + $this->getMongoCursor()->limit($limit); + return $this; + } + + public function setOffset($offset) { + Assert::isInteger($offset); + $this->getMongoCursor()->skip($offset); + return $this; + } } From 409e6dc853f21cc1b04b0e47165130a4882022e7 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Fri, 27 Jul 2012 13:22:04 +0400 Subject: [PATCH 121/418] mongo: correct checking objects on save --- core/NoSQL/NoSqlDAO.class.php | 149 ++++++++++--------------- main/Base/AbstractProtoClass.class.php | 2 +- main/Utils/PrototypeUtils.class.php | 4 + 3 files changed, 61 insertions(+), 94 deletions(-) diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index 9b691b155e..e1c0c7eaad 100755 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -261,51 +261,6 @@ public function take(Identifiable $object) { : $this->add($object); } - public function addNoCheck(NoSqlObject $object, $safe = true) { - $link = NoSqlPool::getByDao( $this ); - $entity = - $link - ->insert( - $this->getTable(), - $object->toArray(), - array('safe' => $safe) - ); - - $object->setId( $entity['id'] ); - - return $object; - } - - public function add(Identifiable $object) { - $this->assertNoSqlObject( $object ); - - // converting object into Array - $arrayObj = $object->toArray(); - - // checking object completance - $this->checkNoSqlObject( $object ); - - // make sequence - $link = NoSqlPool::getByDao( $this ); -// $object->setId( -// $link->obtainSequence( -// $this->getSequence() -// ) -// ); - - // insert - $entity = - $link - ->insert( - $this->getTable(), - $arrayObj - ); - - $object->setId( $entity['id'] ); - - return $object; - } - /** * @param NoSqlObject[] $objectList * @return AbstractAmqpObject|mixed|null @@ -344,65 +299,57 @@ public function multiAdd(array $objectList) { return $objectList; } - public function saveNoCheck(NoSqlObject $object, $safe = true) { - $link = NoSqlPool::getByDao( $this ); - $entity = - $link - ->update( + public function addUnsafe(NoSqlObject $object) { + return $this->doAdd($object, false); + } + + public function add(Identifiable $object) { + $this->assertNoSqlObject( $object ); + return $this->doAdd($object, true); + } + + protected function doAdd(NoSqlObject $object, $safe = true) { + $this->checkNoSqlObject($object); + + $row = NoSqlPool::getByDao($this) + ->insert( $this->getTable(), $object->toArray(), array('safe' => $safe) ); - $object->setId( $entity['id'] ); + + $object->setId($row['id']); return $object; } + public function saveUnsafe(NoSqlObject $object) { + return $this->doSave($object, false); + } + public function save(Identifiable $object) { $this->assertNoSqlObject( $object ); + return $this->doSave($object, true); + } - // converting object into Array - $arrayObj = $object->toArray(); + protected function doSave(NoSqlObject $object, $safe = true) { + $this->checkNoSqlObject($object); - // checking object completance - $this->checkNoSqlObject( $object ); + $row = NoSqlPool::getByDao($this) + ->update( + $this->getTable(), + $object->toArray(), + array('safe' => $safe) + ); - $link = NoSqlPool::getByDao( $this ); - // save - $entity = - $link - ->update( - $this->getTable(), - $arrayObj - ); - $object->setId( $entity['id'] ); + //$object->setId($row['id']); return $object; } public function import(Identifiable $object) { - $this->assertNoSqlObject( $object ); - - // converting object into Array - $arrayObj = $object->toArray(); - - // checking object completance - $this->checkNoSqlObject( $object ); - - $link = NoSqlPool::getByDao( $this ); - // insert - $entity = - $link - ->insert( - $this->getTable(), - $arrayObj - ); - $object->setId( $entity['id'] ); - // проверка сохранения - //$object = $this->getById( $entity['id'] ); - - return $object; + return $this->save($object); } public function merge(Identifiable $object, $cacheOnly = true) { @@ -518,17 +465,33 @@ protected function assertNoSqlObject( $object ) { } /** - * @param Identifiable $object + * @param Prototyped $object * @return bool * @throws NoSQLException */ - protected function checkNoSqlObject(Identifiable $object) { - $className = get_class($object); - // checking by proto - Assert::methodExists($className, 'proto'); - /** @var $form Form */ - $form = $className::proto()->makeForm(null, false); - FormUtils::object2form($object, $form); + protected function checkNoSqlObject(Prototyped $object) { + $form = Form::create(); + foreach ($object->proto()->getPropertyList() as $property) { + /** @var $property LightMetaProperty */ + if ($property->isIdentifier() || $property->getRelationId() > MetaRelation::ONE_TO_ONE) { + continue; + } + if ($property->getType() == 'scalarIdentifier') { + $form->add( + Primitive::string($property->getColumnName()) + ->setRequired($property->isRequired()) + ); + } else if ($property->getType() == 'integerIdentifier') { + $form->add( + Primitive::integer($property->getColumnName()) + ->setRequired($property->isRequired()) + ); + } else { + $form->add($property->makePrimitive($property->getColumnName())); + } + } + + $form->import(PrototypeUtils::toArray($object)); if( $form->getErrors() ) { throw new NoSQLException( 'Object does not have all required fields: '.var_export($form->getErrors(), true) ); } diff --git a/main/Base/AbstractProtoClass.class.php b/main/Base/AbstractProtoClass.class.php index 9dadaa02b0..970f6bcc9d 100755 --- a/main/Base/AbstractProtoClass.class.php +++ b/main/Base/AbstractProtoClass.class.php @@ -202,7 +202,7 @@ public function makeForm($prefix = null, $includeManyRelations = true) /** @var $property LightMetaProperty */ foreach ($this->getPropertyList() as $property) { - if($property->getRelationId()!=MetaRelation::ONE_TO_ONE && $includeManyRelations==false) { + if ($property->getRelationId() > MetaRelation::ONE_TO_ONE && !$includeManyRelations) { continue; } $property->fillForm($form, $prefix); diff --git a/main/Utils/PrototypeUtils.class.php b/main/Utils/PrototypeUtils.class.php index b683bf5859..be6b095443 100755 --- a/main/Utils/PrototypeUtils.class.php +++ b/main/Utils/PrototypeUtils.class.php @@ -211,6 +211,10 @@ public static function toArray(Prototyped $object) { if ($property->getMax() > 0) { $value = substr($value, 0, $property->getMax()); } + if (empty($value)) { + // если false или "", то null + $value = null; + } $entity[ $property->getColumnName() ] = $value; } else { $entity[ $property->getColumnName() ] = $value; From aef8e53dbbbfa64d00e2f513e70e478660b61421 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Fri, 27 Jul 2012 14:09:19 +0400 Subject: [PATCH 122/418] mongo NoSqlExpression - weak typing check --- core/Logic/NoSQLExpression.class.php | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index 975a99ecfc..6ef205d3ed 100755 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -75,26 +75,19 @@ public function addField($fieldName) { /// condition setters //@{ public function addEq($field, $value) { - $strict = true; - if (is_null($value)) { - $dbValue = null; - } else if (Assert::checkBoolean($value)) { - $dbValue = (bool)$value; - } elseif (Assert::checkInteger($value)) { - $dbValue = (int)$value; - $strict = false; - } elseif (Assert::checkFloat($value)) { - $dbValue = (float)$value; - $strict = false; + if (is_string($value) && Assert::checkInteger($value)) { + $dbValue = array($value, (int)$value); + } elseif (is_string($value) && Assert::checkFloat($value)) { + $dbValue = array($value, (float)$value); } else { - $dbValue = (string)$value; + $dbValue = $value; } - if (!$strict /* weak typing */) { + if (is_array($dbValue) /* weak typing */) { $this->conditions[] = array( self::C_TYPE => self::EXP_IN, self::C_FIELD => (string)$field, - self::C_VALUE => array((string)$value, (float)$value, (int)$value), + self::C_VALUE => $dbValue, ); } else { $this->conditions[] = array( From 06eac669d42ffeeeed01de4aed862f33bb3ffb3c Mon Sep 17 00:00:00 2001 From: klkvsk Date: Thu, 2 Aug 2012 14:15:51 +0400 Subject: [PATCH 123/418] #906 banner rotators --- meta/types/ArrayType.class.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 meta/types/ArrayType.class.php diff --git a/meta/types/ArrayType.class.php b/meta/types/ArrayType.class.php new file mode 100644 index 0000000000..43e4901177 --- /dev/null +++ b/meta/types/ArrayType.class.php @@ -0,0 +1,25 @@ + + * @date 2012.08.02 + */ +class ArrayType extends BasePropertyType { + + public function getPrimitiveName() { + return 'set'; + } + + public function getDeclaration() { + return 'array()'; + } + + public function isMeasurable() { + return true; + } + + public function toColumnType() { + throw new UnimplementedFeatureException('ArrayType should not be used within SQL databases'); + } + +} From f678415048dde562df5632d548397ea1e091a8fd Mon Sep 17 00:00:00 2001 From: klkvsk Date: Fri, 17 Aug 2012 19:56:03 +0400 Subject: [PATCH 124/418] datagrid getPropertyValue --- main/UI/Widget/DataGrid.class.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index a1521857fb..d0b9377a23 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -140,8 +140,7 @@ public function addRow($data, $key=null) { $row = array(); foreach ($data->proto()->getPropertyList() as $property) { try { - $getter = $property->getGetter(); - $value = $this->objects[$rowId]->$getter(); + $value = $this->getPropertyValue($rowId, $property); } catch (BadMethodCallException $e) { continue; } catch (ObjectNotFoundException $e) { @@ -182,7 +181,18 @@ public function addRow($data, $key=null) { return $this; } - /** + /** + * @param $rowId + * @param $property + * @return mixed + */ + protected function getPropertyValue($rowId, $property) { + $getter = $property->getGetter(); + $value = $this->objects[$rowId]->$getter(); + return $value; + } + + /** * Выставляет значение конкретного поля конкретной строки * @param $rowId * @param $fieldId From 0aad693c483354b288760753ea5454f81c7970b0 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Tue, 21 Aug 2012 19:48:45 +0400 Subject: [PATCH 125/418] mongo safe count --- core/NoSQL/MongoBase.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 6618666ec0..bc2d23e776 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -75,9 +75,9 @@ public function connect() { // получаем количество реплик в статусах PRIMARY и SECONDARY в сете $safe = 0; foreach ($this->link->getHosts() as $host) { - if (isset($host['state']) && ($host['state'] == 1 || $host['state'] == 2)) { + //if (isset($host['state']) && ($host['state'] == 1 || $host['state'] == 2)) { $safe++; - } + //} } if ($safe > 0) { $this->safeOnWrite = $safe; From dcbae1205a0706298adc8682b1bafcd7612fab64 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Tue, 21 Aug 2012 20:12:13 +0400 Subject: [PATCH 126/418] mongo safe count --- core/NoSQL/MongoBase.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index bc2d23e776..99e8f2b643 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -60,7 +60,7 @@ public function connect() { $this->setBasename($base); } - $options = array('connect' => true, 'slaveOkay' => true); + $options = array('connect' => true, 'slaveOkay' => false); if (!empty($this->connectionOptions)) { $options = array_merge($options, $this->connectionOptions); } @@ -75,9 +75,9 @@ public function connect() { // получаем количество реплик в статусах PRIMARY и SECONDARY в сете $safe = 0; foreach ($this->link->getHosts() as $host) { - //if (isset($host['state']) && ($host['state'] == 1 || $host['state'] == 2)) { + if (isset($host['state']) && ($host['state'] == 1 || $host['state'] == 2)) { $safe++; - //} + } } if ($safe > 0) { $this->safeOnWrite = $safe; From 0c57e866c826b95518b52404afdf47a9eaee956d Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 24 Aug 2012 14:35:53 +0400 Subject: [PATCH 127/418] mail extends for additional headers --- main/Net/Mail/Mail.class.php | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/main/Net/Mail/Mail.class.php b/main/Net/Mail/Mail.class.php index a3530783bd..a26fd1af33 100755 --- a/main/Net/Mail/Mail.class.php +++ b/main/Net/Mail/Mail.class.php @@ -27,8 +27,9 @@ final class Mail private $contentType = null; private $returnPath = null; + private $sendmailAdditionalHeaders = null; private $sendmailAdditionalArgs = null; - + /** * @return Mail **/ @@ -114,6 +115,10 @@ public function send() $headers .= "Content-Transfer-Encoding: 8bit\n"; $headers .= "Date: ".date('r')."\n"; + + if($this->sendmailAdditionalHeaders != null) { + $headers .= $this->sendmailAdditionalHeaders."\n"; + } if ( !mail( @@ -221,5 +226,20 @@ public function setReturnPath($returnPath) $this->returnPath = $returnPath; return $this; } + + public function getSendmailAdditionalHeaders() + { + return $this->sendmailAdditionalHeaders; + } + + /** + * @return Mail + **/ + public function setSendmailAdditionalHeaders($sendmailAdditionalHeaders) + { + $this->sendmailAdditionalHeaders = $sendmailAdditionalHeaders; + return $this; + } + } ?> \ No newline at end of file From 38b611c12672e1d5caeead7f5f7fe862a02cec8d Mon Sep 17 00:00:00 2001 From: klkvsk Date: Thu, 30 Aug 2012 19:43:42 +0400 Subject: [PATCH 128/418] =?UTF-8?q?NoSQLExpression::addIn()=20-=20=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=BE=20=D0=B0=D0=B2?= =?UTF-8?q?=D1=82=D0=BE=D0=BC=D0=B0=D1=82=D0=B8=D1=87=D0=B5=D1=81=D0=BA?= =?UTF-8?q?=D0=BE=D0=B5=20=D0=BF=D1=80=D0=B8=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BA=20int?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/Logic/NoSQLExpression.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index 6ef205d3ed..a15f72cb03 100755 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -171,7 +171,7 @@ public function addBetweenSoft($field, $left, $right) { } public function addIn($field, array $value) { - foreach($value as &$inVal) { + /*foreach($value as &$inVal) { if( is_null($inVal) ) { $inVal = null; } elseif( Assert::checkInteger($inVal) ) { @@ -179,7 +179,7 @@ public function addIn($field, array $value) { } else { $inVal = (string)$inVal; } - } + }*/ $this->conditions[] = array( self::C_TYPE => self::EXP_IN, self::C_FIELD => (string)$field, From 6e6fba500f1bc9862a41091c6a08d17d1121c165 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 6 Sep 2012 14:42:40 +0400 Subject: [PATCH 129/418] FirePHP fix --- lib/FirePHP/FirePHP.class.php | 394 +++++++++++++++++----------------- 1 file changed, 197 insertions(+), 197 deletions(-) mode change 100755 => 100644 lib/FirePHP/FirePHP.class.php diff --git a/lib/FirePHP/FirePHP.class.php b/lib/FirePHP/FirePHP.class.php old mode 100755 new mode 100644 index 74d1c2d73e..f9e18783f8 --- a/lib/FirePHP/FirePHP.class.php +++ b/lib/FirePHP/FirePHP.class.php @@ -1,28 +1,28 @@ * @license http://www.opensource.org/licenses/bsd-license.php @@ -56,15 +56,15 @@ } if (!defined('E_USER_DEPRECATED')) { define('E_USER_DEPRECATED', 16384); -} - +} + /** * Sends the given data to the FirePHP Firefox Extension. * The data can be displayed in the Firebug Console or in the * "Server" request tab. - * + * * For more information see: http://www.firephp.org/ - * + * * @copyright Copyright (C) 2007-2009 Christoph Dorn * @author Christoph Dorn * @license http://www.opensource.org/licenses/bsd-license.php @@ -83,113 +83,113 @@ class FirePHP { * Firebug LOG level * * Logs a message to firebug console. - * + * * @var string */ const LOG = 'LOG'; - + /** * Firebug INFO level * * Logs a message to firebug console and displays an info icon before the message. - * + * * @var string */ const INFO = 'INFO'; - + /** * Firebug WARN level * * Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise. - * + * * @var string */ const WARN = 'WARN'; - + /** * Firebug ERROR level * * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count. - * + * * @var string */ const ERROR = 'ERROR'; - + /** * Dumps a variable to firebug's server panel * * @var string */ const DUMP = 'DUMP'; - + /** * Displays a stack trace in firebug console * * @var string */ const TRACE = 'TRACE'; - + /** * Displays an exception in firebug console - * + * * Increments the firebug error count. * * @var string */ const EXCEPTION = 'EXCEPTION'; - + /** * Displays an table in firebug console * * @var string */ const TABLE = 'TABLE'; - + /** * Starts a group in firebug console - * + * * @var string */ const GROUP_START = 'GROUP_START'; - + /** * Ends a group in firebug console - * + * * @var string */ const GROUP_END = 'GROUP_END'; - + /** * Singleton instance of FirePHP * * @var FirePHP */ protected static $instance = null; - + /** * Flag whether we are logging from within the exception handler - * + * * @var boolean */ protected $inExceptionHandler = false; - + /** * Flag whether to throw PHP errors that have been converted to ErrorExceptions - * + * * @var boolean */ protected $throwErrorExceptions = true; - + /** * Flag whether to convert PHP assertion errors to Exceptions - * + * * @var boolean */ protected $convertAssertionErrorsToExceptions = true; - + /** * Flag whether to throw PHP assertion errors that have been converted to Exceptions - * + * * @var boolean */ protected $throwAssertionExceptions = false; @@ -200,10 +200,10 @@ class FirePHP { * @var int */ protected $messageIndex = 1; - + /** * Options for the library - * + * * @var array */ protected $options = array('maxDepth' => 10, @@ -214,7 +214,7 @@ class FirePHP { /** * Filters used to exclude object members when encoding - * + * * @var array */ protected $objectFilters = array( @@ -224,30 +224,30 @@ class FirePHP { /** * A stack of objects used to detect recursion during object encoding - * + * * @var object */ protected $objectStack = array(); /** * Flag to enable/disable logging - * + * * @var boolean */ protected $enabled = true; /** * The insight console to log to if applicable - * + * * @var object */ protected $logToInsightConsole = null; /** * When the object gets serialized only include specific object members. - * + * * @return array - */ + */ public function __sleep() { return array('options','objectFilters','enabled'); @@ -256,7 +256,7 @@ public function __sleep() public static function me() { return self::getInstance(true); } - + /** * Gets singleton instance of FirePHP * @@ -270,7 +270,7 @@ public static function getInstance($AutoCreate = false) } return self::$instance; } - + /** * Creates FirePHP object and stores it for singleton access * @@ -283,7 +283,7 @@ public static function init() /** * Set the instance of the FirePHP singleton - * + * * @param FirePHP $instance The FirePHP object instance * @return FirePHP */ @@ -294,7 +294,7 @@ public static function setInstance($instance) /** * Set an Insight console to direct all logging calls to - * + * * @param object $console The console object to log to * @return void */ @@ -312,7 +312,7 @@ public function setLogToInsightConsole($console) /** * Enable and disable logging to Firebug - * + * * @param boolean $Enabled TRUE to enable, FALSE to disable * @return void */ @@ -320,22 +320,22 @@ public function setEnabled($Enabled) { $this->enabled = $Enabled; } - + /** * Check if logging is enabled - * + * * @return boolean TRUE if enabled */ public function getEnabled() { return $this->enabled; } - + /** * Specify a filter to be used when encoding an object - * + * * Filters are used to exclude object members. - * + * * @param string $Class The class name of the object * @param array $Filter An array of members to exclude * @return void @@ -344,17 +344,17 @@ public function setObjectFilter($Class, $Filter) { $this->objectFilters[strtolower($Class)] = $Filter; } - + /** * Set some options for the library - * + * * Options: * - maxDepth: The maximum depth to traverse (default: 10) * - maxObjectDepth: The maximum depth to traverse objects (default: 5) * - maxArrayDepth: The maximum depth to traverse arrays (default: 5) * - useNativeJsonEncode: If true will use json_encode() (default: true) * - includeLineNumbers: If true will include line numbers and filenames (default: true) - * + * * @param array $Options The options to be set * @return void */ @@ -375,12 +375,12 @@ public function getOptions() /** * Set an option for the library - * + * * @param string $Name * @param mixed $Value * @throws Exception * @return void - */ + */ public function setOption($Name, $Value) { if (!isset($this->options[$Name])) { @@ -406,9 +406,9 @@ public function getOption($Name) /** * Register FirePHP as your error handler - * + * * Will throw exceptions for each php error. - * + * * @return mixed Returns a string containing the previously defined error handler (if any) */ public function registerErrorHandler($throwErrorExceptions = false) @@ -417,15 +417,15 @@ public function registerErrorHandler($throwErrorExceptions = false) // E_ERROR, E_PARSE, E_CORE_ERROR, // E_CORE_WARNING, E_COMPILE_ERROR, // E_COMPILE_WARNING, E_STRICT - + $this->throwErrorExceptions = $throwErrorExceptions; - - return set_error_handler(array($this,'errorHandler')); + + return set_error_handler(array($this,'errorHandler')); } /** * FirePHP's error handler - * + * * Throws exception for each php error that will occur. * * @param int $errno @@ -451,22 +451,22 @@ public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) } } } - + /** * Register FirePHP as your exception handler - * + * * @return mixed Returns the name of the previously defined exception handler, * or NULL on error. * If no previous handler was defined, NULL is also returned. */ public function registerExceptionHandler() { - return set_exception_handler(array($this,'exceptionHandler')); + return set_exception_handler(array($this,'exceptionHandler')); } - + /** * FirePHP's exception handler - * + * * Logs all exceptions to your firebug console and then stops the script. * * @param Exception $Exception @@ -474,11 +474,11 @@ public function registerExceptionHandler() */ function exceptionHandler($Exception) { - + $this->inExceptionHandler = true; - + header('HTTP/1.1 500 Internal Server Error'); - + try { $this->fb($Exception); } catch (Exception $e) { @@ -486,10 +486,10 @@ function exceptionHandler($Exception) } $this->inExceptionHandler = false; } - + /** * Register FirePHP driver as your assert callback - * + * * @param boolean $convertAssertionErrorsToExceptions * @param boolean $throwAssertionExceptions * @return mixed Returns the original setting or FALSE on errors @@ -498,14 +498,14 @@ public function registerAssertionHandler($convertAssertionErrorsToExceptions = t { $this->convertAssertionErrorsToExceptions = $convertAssertionErrorsToExceptions; $this->throwAssertionExceptions = $throwAssertionExceptions; - + if ($throwAssertionExceptions && !$convertAssertionErrorsToExceptions) { throw $this->newException('Cannot throw assertion exceptions as assertion errors are not being converted to exceptions!'); } - + return assert_options(ASSERT_CALLBACK, array($this, 'assertionHandler')); } - + /** * FirePHP's assertion handler * @@ -518,23 +518,23 @@ public function registerAssertionHandler($convertAssertionErrorsToExceptions = t public function assertionHandler($file, $line, $code) { if ($this->convertAssertionErrorsToExceptions) { - + $exception = new ErrorException('Assertion Failed - Code[ '.$code.' ]', 0, null, $file, $line); - + if ($this->throwAssertionExceptions) { throw $exception; } else { $this->fb($exception); } - + } else { $this->fb($code, 'Assertion Failed', FirePHP::ERROR, array('File'=>$file,'Line'=>$line)); } } - + /** * Start a group for following messages. - * + * * Options: * Collapsed: [true|false] * Color: [#RRGGBB|ColorName] @@ -546,11 +546,11 @@ public function assertionHandler($file, $line, $code) */ public function group($Name, $Options = null) { - + if (!$Name) { throw $this->newException('You must specify a label for the group!'); } - + if ($Options) { if (!is_array($Options)) { throw $this->newException('Options must be defined as an array!'); @@ -559,10 +559,10 @@ public function group($Name, $Options = null) $Options['Collapsed'] = ($Options['Collapsed'])?'true':'false'; } } - + return $this->fb(null, $Name, FirePHP::GROUP_START, $Options); } - + /** * Ends a group you have started before * @@ -586,7 +586,7 @@ public function groupEnd() public function log($Object, $Label = null, $Options = array()) { return $this->fb($Object, $Label, FirePHP::LOG, $Options); - } + } /** * Log object with label to firebug console @@ -600,7 +600,7 @@ public function log($Object, $Label = null, $Options = array()) public function info($Object, $Label = null, $Options = array()) { return $this->fb($Object, $Label, FirePHP::INFO, $Options); - } + } /** * Log object with label to firebug console @@ -614,7 +614,7 @@ public function info($Object, $Label = null, $Options = array()) public function warn($Object, $Label = null, $Options = array()) { return $this->fb($Object, $Label, FirePHP::WARN, $Options); - } + } /** * Log object with label to firebug console @@ -628,7 +628,7 @@ public function warn($Object, $Label = null, $Options = array()) public function error($Object, $Label = null, $Options = array()) { return $this->fb($Object, $Label, FirePHP::ERROR, $Options); - } + } /** * Dumps key and variable to firebug server panel @@ -652,7 +652,7 @@ public function dump($Key, $Variable, $Options = array()) } return $this->fb($Variable, $Key, FirePHP::DUMP, $Options); } - + /** * Log a trace in the firebug console * @@ -664,7 +664,7 @@ public function dump($Key, $Variable, $Options = array()) public function trace($Label) { return $this->fb($Label, FirePHP::TRACE); - } + } /** * Log a table in the firebug console @@ -682,7 +682,7 @@ public function table($Label, $Table, $Options = array()) /** * Insight API wrapper - * + * * @see Insight_Helper::to() */ public static function to() @@ -697,7 +697,7 @@ public static function to() /** * Insight API wrapper - * + * * @see Insight_Helper::plugin() */ public static function plugin() @@ -729,10 +729,10 @@ public function detectClientExtension() } return false; } - + /** * Log varible to Firebug - * + * * @see http://www.firephp.org/Wiki/Reference/Fb * @param mixed $Object The variable to be logged * @return true Return TRUE if message was added to headers, FALSE otherwise @@ -761,11 +761,11 @@ public function fb($Object) throw $this->newException('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.'); } } - + $Type = null; $Label = null; $Options = array(); - + if (func_num_args()==1) { } else if (func_num_args()==2) { @@ -831,7 +831,7 @@ public function fb($Object) return $msg->log($Label); case self::GROUP_END: if(count($insightGroupStack)==0) { - throw new Error('Too many groupEnd() as opposed to group() calls!'); + throw new Exception('Too many groupEnd() as opposed to group() calls!'); } $group = array_pop($insightGroupStack); return $group->close(); @@ -843,22 +843,22 @@ public function fb($Object) if (!$this->detectClientExtension()) { return false; } - + $meta = array(); $skipFinalObjectEncode = false; - + if ($Object instanceof Exception) { - + $meta['file'] = $this->_escapeTraceFile($Object->getFile()); $meta['line'] = $Object->getLine(); - + $trace = $Object->getTrace(); if ($Object instanceof ErrorException && isset($trace[0]['function']) && $trace[0]['function']=='errorHandler' && isset($trace[0]['class']) && $trace[0]['class']=='FirePHP') { - + $severity = false; switch($Object->getSeverity()) { case E_WARNING: $severity = 'E_WARNING'; break; @@ -871,7 +871,7 @@ public function fb($Object) case E_DEPRECATED: $severity = 'E_DEPRECATED'; break; case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break; } - + $Object = array('Class'=>get_class($Object), 'Message'=>$severity.': '.$Object->getMessage(), 'File'=>$this->_escapeTraceFile($Object->getFile()), @@ -889,14 +889,14 @@ public function fb($Object) $skipFinalObjectEncode = true; } $Type = self::EXCEPTION; - + } else if ($Type==self::TRACE) { - + $trace = debug_backtrace(); if (!$trace) return false; for( $i=0 ; $iisset($trace[$i]['line'])?$trace[$i]['line']:'', 'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'', 'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1))); - + $skipFinalObjectEncode = true; $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; break; } } - + } else if ($Type==self::TABLE) { - + if (isset($Object[0]) && is_string($Object[0])) { $Object[1] = $this->encodeTable($Object[1]); } else { $Object = $this->encodeTable($Object); } - + $skipFinalObjectEncode = true; - + } else if ($Type==self::GROUP_START) { - + if (!$Label) { throw $this->newException('You must specify a label for the group!'); } - + } else { if ($Type===null) { $Type = self::LOG; } } - + if ($this->options['includeLineNumbers']) { if (!isset($meta['file']) || !isset($meta['line'])) { - + $trace = debug_backtrace(); for( $i=0 ; $trace && $isetHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2'); $this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION); - + $structure_index = 1; if ($Type==self::DUMP) { $structure_index = 2; @@ -1000,7 +1000,7 @@ public function fb($Object) } else { $this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'); } - + if ($Type==self::DUMP) { $msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}'; } else { @@ -1017,14 +1017,14 @@ public function fb($Object) } $msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']'; } - + $parts = explode("\n",chunk_split($msg, 5000, "\n")); - + for( $i=0 ; $i2) { // Message needs to be split into multiple parts $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, @@ -1035,20 +1035,20 @@ public function fb($Object) $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, strlen($part) . '|' . $part . '|'); } - + $this->messageIndex++; - + if ($this->messageIndex > 99999) { - throw $this->newException('Maximum number (99,999) of messages reached!'); + throw $this->newException('Maximum number (99,999) of messages reached!'); } } } - + $this->setHeader('X-Wf-1-Index',$this->messageIndex-1); - + return true; } - + /** * Standardizes path for windows systems. * @@ -1057,9 +1057,9 @@ public function fb($Object) */ protected function _standardizePath($Path) { - return preg_replace('/\\\\+/','/',$Path); + return preg_replace('/\\\\+/','/',$Path); } - + /** * Escape trace path for windows systems * @@ -1077,9 +1077,9 @@ protected function _escapeTrace($Trace) $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']); } } - return $Trace; + return $Trace; } - + /** * Escape file information of trace for windows systems * @@ -1091,9 +1091,9 @@ protected function _escapeTraceFile($File) /* Check if we have a windows filepath */ if (strpos($File,'\\')) { /* First strip down to single \ */ - + $file = preg_replace('/\\\\+/','\\',$File); - + return $file; } return $File; @@ -1134,7 +1134,7 @@ protected function getUserAgent() /** * Get all request headers - * + * * @return array */ public static function getAllRequestHeaders() { @@ -1181,12 +1181,12 @@ protected function newException($Message) { return new Exception($Message); } - + /** * Encode an object into a JSON string - * + * * Uses PHP's jeson_encode() if available - * + * * @param object $Object The object to be encoded * @return string The JSON string */ @@ -1195,10 +1195,10 @@ public function jsonEncode($Object, $skipObjectEncode = false) if (!$skipObjectEncode) { $Object = $this->encodeObject($Object); } - + if (function_exists('json_encode') && $this->options['useNativeJsonEncode']!=false) { - + return json_encode($Object); } else { return $this->json_encode($Object); @@ -1207,36 +1207,36 @@ public function jsonEncode($Object, $skipObjectEncode = false) /** * Encodes a table by encoding each row and column with encodeObject() - * + * * @param array $Table The table to be encoded * @return array - */ + */ protected function encodeTable($Table) { - + if (!$Table) return $Table; - + $new_table = array(); foreach($Table as $row) { - + if (is_array($row)) { $new_row = array(); - + foreach($row as $item) { $new_row[] = $this->encodeObject($item); } - + $new_table[] = $new_row; } } - + return $new_table; } /** * Encodes an object including members with * protected and private visibility - * + * * @param Object $Object The object to be encoded * @param int $Depth The current traversal depth * @return array All members of the object @@ -1248,38 +1248,38 @@ protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1, $Max } $return = array(); - + if (is_resource($Object)) { - + return '** '.(string)$Object.' **'; - - } else + + } else if (is_object($Object)) { - + if ($ObjectDepth > $this->options['maxObjectDepth']) { return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **'; } - + foreach ($this->objectStack as $refVal) { if ($refVal === $Object) { return '** Recursion ('.get_class($Object).') **'; } } array_push($this->objectStack, $Object); - + $return['__className'] = $class = get_class($Object); $class_lower = strtolower($class); - - $reflectionClass = new ReflectionClass($class); + + $reflectionClass = new ReflectionClass($class); $properties = array(); foreach( $reflectionClass->getProperties() as $property) { $properties[$property->getName()] = $property; } - + $members = (array)$Object; - + foreach( $properties as $plain_name => $property ) { - + $name = $raw_name = $plain_name; if ($property->isStatic()) { $name = 'static:'.$name; @@ -1295,16 +1295,16 @@ protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1, $Max $name = 'protected:'.$name; $raw_name = "\0".'*'."\0".$raw_name; } - + if (!(isset($this->objectFilters[$class_lower]) && is_array($this->objectFilters[$class_lower]) && in_array($plain_name,$this->objectFilters[$class_lower]))) { - + if (array_key_exists($raw_name,$members) && !$property->isStatic()) { - - $return[$name] = $this->encodeObject($members[$raw_name], $ObjectDepth + 1, 1, $MaxDepth + 1); - + + $return[$name] = $this->encodeObject($members[$raw_name], $ObjectDepth + 1, 1, $MaxDepth + 1); + } else { if (method_exists($property,'setAccessible')) { $property->setAccessible(true); @@ -1320,44 +1320,44 @@ protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1, $Max $return[$name] = '** Excluded by Filter **'; } } - + // Include all members that are not defined in the class // but exist in the object foreach( $members as $raw_name => $value ) { - + $name = $raw_name; - + if ($name{0} == "\0") { $parts = explode("\0", $name); $name = $parts[2]; } - + $plain_name = $name; - + if (!isset($properties[$name])) { $name = 'undeclared:'.$name; - + if (!(isset($this->objectFilters[$class_lower]) && is_array($this->objectFilters[$class_lower]) && in_array($plain_name,$this->objectFilters[$class_lower]))) { - + $return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1, $MaxDepth + 1); } else { $return[$name] = '** Excluded by Filter **'; } } } - + array_pop($this->objectStack); - + } elseif (is_array($Object)) { - + if ($ArrayDepth > $this->options['maxArrayDepth']) { return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **'; } - + foreach ($Object as $key => $val) { - + // Encoding the $GLOBALS PHP array causes an infinite loop // if the recursion is not reset here as it contains // a reference to itself. This is the only way I have come up @@ -1367,7 +1367,7 @@ protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1, $Max && array_key_exists('GLOBALS',$val)) { $val['GLOBALS'] = '** Recursion (GLOBALS) **'; } - + $return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1, $MaxDepth + 1); } } else { @@ -1414,7 +1414,7 @@ protected static function is_utf8($str) } } return true; - } + } /** * Converts to and from JSON format. @@ -1471,8 +1471,8 @@ protected static function is_utf8($str) * @license http://www.opensource.org/licenses/bsd-license.php * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 */ - - + + /** * Keep a list of objects as we descend into the array so we can detect recursion. */ @@ -1536,13 +1536,13 @@ private function json_utf82utf16($utf8) */ private function json_encode($var) { - + if (is_object($var)) { if (in_array($var,$this->json_objectStack)) { return '"** Recursion **"'; } } - + switch (gettype($var)) { case 'boolean': return $var ? 'true' : 'false'; @@ -1683,7 +1683,7 @@ private function json_encode($var) // treat as a JSON object if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { - + $this->json_objectStack[] = $var; $properties = array_map(array($this, 'json_name_value'), @@ -1726,13 +1726,13 @@ private function json_encode($var) array_values($vars)); array_pop($this->json_objectStack); - + foreach($properties as $property) { if ($property instanceof Exception) { return $property; } } - + return '{' . join(',', $properties) . '}'; default: @@ -1760,7 +1760,7 @@ private function json_name_value($name, $value) && array_key_exists('GLOBALS',$value)) { $value['GLOBALS'] = '** Recursion **'; } - + $encoded_value = $this->json_encode($value); if ($encoded_value instanceof Exception) { @@ -1772,7 +1772,7 @@ private function json_name_value($name, $value) /** * @deprecated - */ + */ public function setProcessorUrl($URL) { trigger_error("The FirePHP::setProcessorUrl() method is no longer supported", E_USER_DEPRECATED); @@ -1784,5 +1784,5 @@ public function setProcessorUrl($URL) public function setRendererUrl($URL) { trigger_error("The FirePHP::setRendererUrl() method is no longer supported", E_USER_DEPRECATED); - } + } } From ca475f00876d6ef68aa7f99f4b54347918b02876 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Wed, 22 Aug 2012 21:04:54 +0400 Subject: [PATCH 130/418] fake properties --- main/Base/AbstractProtoClass.class.php | 5 ++++- main/Base/LightMetaProperty.class.php | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/main/Base/AbstractProtoClass.class.php b/main/Base/AbstractProtoClass.class.php index 970f6bcc9d..5ded42cdb2 100755 --- a/main/Base/AbstractProtoClass.class.php +++ b/main/Base/AbstractProtoClass.class.php @@ -219,7 +219,10 @@ public function fillQuery( ) { foreach ($this->getPropertyList() as $property) { - $property->fillQuery($query, $object); + /** @var $property LightMetaProperty */ + if ($property->getColumnName()) { + $property->fillQuery($query, $object); + } } return $query; diff --git a/main/Base/LightMetaProperty.class.php b/main/Base/LightMetaProperty.class.php index 8ca3dbb4f1..9e1784f93c 100755 --- a/main/Base/LightMetaProperty.class.php +++ b/main/Base/LightMetaProperty.class.php @@ -103,7 +103,7 @@ public static function fill( if ($columnName) $property->columnName = $columnName; - else + else if ($columnName === null) $property->columnName = $name; $property->type = $type; @@ -322,6 +322,10 @@ public function makePrimitive($name) public function fillMapping(array $mapping) { + if (empty($this->columnName)) { + return $mapping; + } + if ( !$this->relationId || ( From 1166b5502e9e581c07d16a597b6d183e211f1ce9 Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Thu, 30 Aug 2012 15:15:04 +0400 Subject: [PATCH 131/418] =?UTF-8?q?=20#1000=20=D0=9F=D0=BE=D0=B4=D0=B3?= =?UTF-8?q?=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D0=B0=20=D0=BA=D1=80=D0=B8=D1=82?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D0=B8=20(=D0=BB=D0=BE=D0=BA=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/Criteria/Criteria.class.php | 35 +++++++++++++++++++ .../Projections/BaseProjection.class.php | 12 ++++++- .../Projections/ProjectionChain.class.php | 8 +++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/main/Criteria/Criteria.class.php b/main/Criteria/Criteria.class.php index 9f7e49fa5b..12f3acf872 100755 --- a/main/Criteria/Criteria.class.php +++ b/main/Criteria/Criteria.class.php @@ -33,6 +33,9 @@ final class Criteria extends QueryIdentification // dao-like behaviour: will throw ObjectNotFoundException when 'false' private $silent = true; + // Обработчик критерии перед вызовом + public static $prepareCriteriaCallBack = null; + /** * @return Criteria **/ @@ -117,6 +120,16 @@ public function getLogic() return $this->logic; } + /** + * @return Criteria + */ + public function dropLogic() + { + $this->logic = Expression::andBlock(); + + return $this; + } + /** * @return Criteria **/ @@ -462,11 +475,31 @@ public function toDialectString(Dialect $dialect) return $this->toSelectQuery()->toDialectString($dialect); } + /** + * Вызов before-обработчика + * @param bool $fullQuery обрабатываем всю критерию или нет (только select-часть) + */ + public function prepareCriteria($fullQuery = true) + { + if ( + self::$prepareCriteriaCallBack !== null && + is_callable(self::$prepareCriteriaCallBack) + ) { + try { + call_user_func_array( self::$prepareCriteriaCallBack, array($this, $fullQuery) ); + } + catch(Exception $e) { + // pass + } + } + } /** * @return SelectQuery **/ public function toSelectQuery() { + $this->prepareCriteria(false); + if (!$this->projection->isEmpty()) { $query = $this->getProjection()->process( @@ -488,6 +521,8 @@ public function toSelectQuery() **/ public function fillSelectQuery(SelectQuery $query) { + $this->prepareCriteria(true); + $query-> limit($this->limit, $this->offset); diff --git a/main/Criteria/Projections/BaseProjection.class.php b/main/Criteria/Projections/BaseProjection.class.php index dd3025f3a9..b7f9ff96eb 100755 --- a/main/Criteria/Projections/BaseProjection.class.php +++ b/main/Criteria/Projections/BaseProjection.class.php @@ -22,10 +22,20 @@ public function __construct($propertyName = null, $alias = null) $this->property = $propertyName; $this->alias = $alias; } - + public function getAlias() { return $this->alias; } + + public function getPropertyName() + { + return $this->property; + } + + public function setPropertyName($propertyName = null) + { + $this->property = $propertyName; + } } ?> \ No newline at end of file diff --git a/main/Criteria/Projections/ProjectionChain.class.php b/main/Criteria/Projections/ProjectionChain.class.php index b9c0c8e4c3..d60246bc32 100755 --- a/main/Criteria/Projections/ProjectionChain.class.php +++ b/main/Criteria/Projections/ProjectionChain.class.php @@ -31,6 +31,14 @@ public function add(ObjectProjection $projection, $name = null) return $this; } + + /** + * @return array + */ + public function getList() + { + return $this->list; + } /** * @return JoinCapableQuery From c0ed741c5ff25f11b5c09706a62df63cb3690177 Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Fri, 31 Aug 2012 21:53:22 +0400 Subject: [PATCH 132/418] =?UTF-8?q?=20#1000=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=BE=D0=B4?= =?UTF-8?q?=D1=8B=20=D0=BF=D0=BE=20=D0=BE=D1=81=D1=82=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D1=8B=D0=BC=20=D0=BF=D0=BE=D0=BB=D1=8F=D0=BC=20=D0=BD?= =?UTF-8?q?=D0=B5=D0=BE=D0=B1=D1=85=D0=BE=D0=B4=D0=B8=D0=BC=D1=8B=D1=85=20?= =?UTF-8?q?=D0=BE=D0=B1=D1=8A=D0=B5=D0=BA=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/Criteria/Criteria.class.php | 4 +++- main/UI/Widget/DataGrid.class.php | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/main/Criteria/Criteria.class.php b/main/Criteria/Criteria.class.php index 12f3acf872..ace16424f5 100755 --- a/main/Criteria/Criteria.class.php +++ b/main/Criteria/Criteria.class.php @@ -489,7 +489,9 @@ public function prepareCriteria($fullQuery = true) call_user_func_array( self::$prepareCriteriaCallBack, array($this, $fullQuery) ); } catch(Exception $e) { - // pass + // pass, saving + //Logger::me()->error($e); + throw $e; } } } diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index d0b9377a23..81f3af3e84 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -353,6 +353,11 @@ protected function getViewRenderer($value) { $trueName = $this->trueName; $falseName = $this->falseName; + if ($value instanceof InternationalString) { + return function ($value) { + return $value->__toString(); + }; + } // для прототипированного объекта можно построить // вложенную табличку. Важно запомнить родителя, // чтобы избежать бесконечной рекурсии From 378f9c8280fb55e9a21afcbe056babdff6678823 Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Mon, 3 Sep 2012 11:00:04 +0400 Subject: [PATCH 133/418] =?UTF-8?q?=20#1000=20=D0=A0=D0=B5=D1=84=D0=B0?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3,=20=D1=83=D0=BB?= =?UTF-8?q?=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/Criteria/Criteria.class.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/main/Criteria/Criteria.class.php b/main/Criteria/Criteria.class.php index ace16424f5..17a8edfc65 100755 --- a/main/Criteria/Criteria.class.php +++ b/main/Criteria/Criteria.class.php @@ -120,6 +120,16 @@ public function getLogic() return $this->logic; } + /** + * @param LogicalChain $logic + * @return Criteria + */ + public function setLogic(LogicalChain $logic) { + $this->logic = $logic; + + return $this; + } + /** * @return Criteria */ @@ -148,6 +158,16 @@ public function getOrder() return $this->order; } + /** + * @param OrderChain $order + * @return Criteria + */ + public function setOrder(OrderChain $order) { + $this->order = $order; + + return $this; + } + /** * @return Criteria **/ From 3f6773305b02e07e0cf31499f1c1bd8925409ec6 Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Thu, 6 Sep 2012 18:40:35 +0400 Subject: [PATCH 134/418] =?UTF-8?q?#1000=20=D0=9B=D0=BE=D0=BA=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D1=82=D0=B5=D1=81=D0=BA?= =?UTF-8?q?=D1=82=D0=BE=D0=B2,=20=D0=B5=D0=BD=D1=83=D0=BC=D0=BE=D0=B2,=20?= =?UTF-8?q?=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=D0=BE=D0=B2,=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20=D0=B8=20=D0=B4=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D0=B2=D0=BE=D0=B4=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/Base/Enumeration.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/Base/Enumeration.class.php b/core/Base/Enumeration.class.php index e52fc90ffa..bd94376685 100755 --- a/core/Base/Enumeration.class.php +++ b/core/Base/Enumeration.class.php @@ -21,7 +21,7 @@ abstract class Enumeration extends NamedObject implements Serializable { protected $names = array(/* override me */); - final public function __construct($id) + public function __construct($id) { $this->setId($id); } From 10e3b28ef3f789933b5bac91613114268315947c Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Mon, 10 Sep 2012 18:54:21 +0400 Subject: [PATCH 135/418] =?UTF-8?q?#1000=20=D0=9F=D0=BE=D0=B4=D0=B3=D0=BE?= =?UTF-8?q?=D1=82=D0=BE=D0=B2=D0=BA=D0=B0=20=D0=BA=D1=80=D0=B8=D1=82=D0=B5?= =?UTF-8?q?=D1=80=D0=B8=D0=B8,=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/OSQL/SQLChain.class.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/OSQL/SQLChain.class.php b/core/OSQL/SQLChain.class.php index 6d08b88e0c..923cd5050a 100755 --- a/core/OSQL/SQLChain.class.php +++ b/core/OSQL/SQLChain.class.php @@ -37,7 +37,13 @@ public function getChain() { return $this->chain; } - + + public function dropChain() + { + $this->chain = array(); + $this->logic = array(); + } + public function getLogic() { return $this->logic; From b81fa3b7e11dc7f427ddbe10a44f92e209fc78ef Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Wed, 26 Sep 2012 21:44:07 +0400 Subject: [PATCH 136/418] #1000 correction not translated objects in list --- core/OSQL/OrderChain.class.php | 5 +++++ core/OSQL/SelectQuery.class.php | 15 +++++++++++++++ main/Criteria/Criteria.class.php | 1 - .../Projections/ProjectionChain.class.php | 5 +++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/core/OSQL/OrderChain.class.php b/core/OSQL/OrderChain.class.php index 5eab7e2ee7..76cfba162d 100755 --- a/core/OSQL/OrderChain.class.php +++ b/core/OSQL/OrderChain.class.php @@ -59,6 +59,11 @@ public function getList() { return $this->chain; } + + public function dropChain() + { + $this->chain = array(); + } public function getCount() { diff --git a/core/OSQL/SelectQuery.class.php b/core/OSQL/SelectQuery.class.php index 7136be8387..454a546641 100755 --- a/core/OSQL/SelectQuery.class.php +++ b/core/OSQL/SelectQuery.class.php @@ -32,6 +32,9 @@ final class SelectQuery private $group = array(); private $having = null; + + // Обработчик логики джойна + public static $prepareJoinLogic = null; public function __construct() { @@ -115,6 +118,18 @@ public function join($table, LogicalObject $logic, $alias = null) **/ public function leftJoin($table, LogicalObject $logic, $alias = null) { + if ( + self::$prepareJoinLogic !== null && + is_callable(self::$prepareJoinLogic) + ) { + try { + $logic = call_user_func_array( self::$prepareJoinLogic, array($logic) ); + } + catch(Exception $e) { + // pass, saving + throw $e; + } + } $this->joiner->leftJoin(new SQLLeftJoin($table, $logic, $alias)); $this->aliases[$alias] = true; diff --git a/main/Criteria/Criteria.class.php b/main/Criteria/Criteria.class.php index 17a8edfc65..e04271132f 100755 --- a/main/Criteria/Criteria.class.php +++ b/main/Criteria/Criteria.class.php @@ -510,7 +510,6 @@ public function prepareCriteria($fullQuery = true) } catch(Exception $e) { // pass, saving - //Logger::me()->error($e); throw $e; } } diff --git a/main/Criteria/Projections/ProjectionChain.class.php b/main/Criteria/Projections/ProjectionChain.class.php index d60246bc32..155ae9693f 100755 --- a/main/Criteria/Projections/ProjectionChain.class.php +++ b/main/Criteria/Projections/ProjectionChain.class.php @@ -39,6 +39,11 @@ public function getList() { return $this->list; } + + public function dropChain() + { + $this->list = array(); + } /** * @return JoinCapableQuery From 019b69db7767c2ce06eeabe94c4ec83118ccc61c Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Thu, 27 Sep 2012 17:48:23 +0400 Subject: [PATCH 137/418] #1000 small fixes --- .../Primitives/PrimitiveReCaptcha.class.php | 16 ++++++---- core/OSQL/SelectQuery.class.php | 30 +++++++++---------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/core/Form/Primitives/PrimitiveReCaptcha.class.php b/core/Form/Primitives/PrimitiveReCaptcha.class.php index 3a9798f68a..945f0b562c 100755 --- a/core/Form/Primitives/PrimitiveReCaptcha.class.php +++ b/core/Form/Primitives/PrimitiveReCaptcha.class.php @@ -113,8 +113,8 @@ protected static function _recaptcha_http_post($host, $path, $data, $port = 80) * @return string - The HTML to be embedded in the user's form. */ - public static function getHtmlCode ($pubkey, $error = null, $use_ssl = false) { - if ($pubkey == null || $pubkey == '') { + public static function getHtmlCode ($pubKey, $lang = null, $error = null, $use_ssl = false) { + if ($pubKey == null || $pubKey == '') { die ("To use reCAPTCHA you must get an API key from https://www.google.com/recaptcha/admin/create"); } @@ -124,11 +124,17 @@ public static function getHtmlCode ($pubkey, $error = null, $use_ssl = false) { $server = self::RECAPTCHA_API_SERVER; } - $errorpart = ""; + $langPart = ""; + if ($lang) { + $langPart = "&hl=" . $lang; + } + + $errorPart = ""; if ($error) { - $errorpart = "&error=" . $error; + $errorPart = "&error=" . $error; } - return ''; + + return ''; } /** diff --git a/core/OSQL/SelectQuery.class.php b/core/OSQL/SelectQuery.class.php index 454a546641..fc9d9b9c64 100755 --- a/core/OSQL/SelectQuery.class.php +++ b/core/OSQL/SelectQuery.class.php @@ -35,34 +35,34 @@ final class SelectQuery // Обработчик логики джойна public static $prepareJoinLogic = null; - + public function __construct() { $this->joiner = new Joiner(); $this->order = new OrderChain(); } - + public function __clone() { $this->joiner = clone $this->joiner; $this->order = clone $this->order; } - + public function hasAliasInside($alias) { return isset($this->aliases[$alias]); } - + public function getAlias() { return $this->name; } - + public function getName() { return $this->name; } - + /** * @return SelectQuery **/ @@ -70,10 +70,10 @@ public function setName($name) { $this->name = $name; $this->aliases[$name] = true; - + return $this; } - + /** * @return SelectQuery **/ @@ -82,12 +82,12 @@ public function distinct() $this->distinct = true; return $this; } - + public function isDistinct() { return $this->distinct; } - + /** * @return SelectQuery **/ @@ -96,12 +96,12 @@ public function unDistinct() $this->distinct = false; return $this; } - + public function hasJoinedTable($table) { return $this->joiner->hasJoinedTable($table); } - + /** * @return SelectQuery **/ @@ -109,10 +109,10 @@ public function join($table, LogicalObject $logic, $alias = null) { $this->joiner->join(new SQLJoin($table, $logic, $alias)); $this->aliases[$alias] = true; - + return $this; } - + /** * @return SelectQuery **/ @@ -123,7 +123,7 @@ public function leftJoin($table, LogicalObject $logic, $alias = null) is_callable(self::$prepareJoinLogic) ) { try { - $logic = call_user_func_array( self::$prepareJoinLogic, array($logic) ); + $logic = call_user_func_array( self::$prepareJoinLogic, array($logic, $this) ); } catch(Exception $e) { // pass, saving From 7e60c6d975c59f5bbebd29231592e87ae9a595f7 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Tue, 2 Oct 2012 16:54:51 +0400 Subject: [PATCH 138/418] re-throw exception --- main/Base/AbstractProtoClass.class.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/main/Base/AbstractProtoClass.class.php b/main/Base/AbstractProtoClass.class.php index 5ded42cdb2..4898b8f7ad 100755 --- a/main/Base/AbstractProtoClass.class.php +++ b/main/Base/AbstractProtoClass.class.php @@ -416,10 +416,11 @@ private static function assemblyObject( } } catch( Exception $e ) { - echo '
';
-				echo $e->getTraceAsString();
-				echo '
'; - die('error'); +// echo '
';
+//				echo $e->getTraceAsString();
+//				echo '
'; +// die('error'); + throw $e; } return $object; From e865da73600f70c4f263b331608014dd646f2c91 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Wed, 3 Oct 2012 16:14:17 +0400 Subject: [PATCH 139/418] =?UTF-8?q?=D1=81=D0=BF=D0=BE=D1=80=D0=BD=D1=8B?= =?UTF-8?q?=D0=B9=20=D1=84=D0=B8=D0=BA=D1=81=20--=20https://github.com/onP?= =?UTF-8?q?HP/onphp-framework/issues/141?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- meta/builders/SchemaBuilder.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/builders/SchemaBuilder.class.php b/meta/builders/SchemaBuilder.class.php index bbacad5411..8d9fa3d72a 100755 --- a/meta/builders/SchemaBuilder.class.php +++ b/meta/builders/SchemaBuilder.class.php @@ -65,7 +65,7 @@ public static function buildRelations(MetaClass $class) // or table does not exist at all || !$foreignClass->getPattern()->tableExists() // no need to process them - || $class->getParent() + || !$class->getPattern()->tableExists() ) { continue; } elseif ( From f625b5576d1e6c2c18c444654e417ac5ce4b7e7f Mon Sep 17 00:00:00 2001 From: klkvsk Date: Fri, 5 Oct 2012 16:27:22 +0400 Subject: [PATCH 140/418] mongo cursor default timeout = 2 min --- core/NoSQL/MongoBase.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 99e8f2b643..983eca0f82 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -82,6 +82,7 @@ public function connect() { if ($safe > 0) { $this->safeOnWrite = $safe; } + MongoCursor::$timeout = 120 * 1000; // 2min } catch(MongoConnectionException $e) { throw new NoSQLException( From dd427f9bca339f4e4ea99252340cba211e5083c1 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 8 Oct 2012 16:11:06 +0400 Subject: [PATCH 141/418] MongoBase::deleteList() fixed wrong query --- core/NoSQL/MongoBase.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 983eca0f82..feab629abc 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -234,7 +234,7 @@ public function deleteList($table, array $keys) { $this ->db ->selectCollection($table) - ->remove( array('$or' => $this->makeIdList($keys)) ); + ->remove( array('_id' => array('$in' => $this->makeIdList($keys))) ); } public function getPlainList($table) { From ea93df3504787fffdd545d20cd9b3f7787bce9e4 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 9 Oct 2012 14:31:06 +0400 Subject: [PATCH 142/418] curl fix --- main/Flow/HttpRequest.class.php | 24 +++++++++++++++++++++-- main/Net/Http/CurlHttpClient.class.php | 27 ++++++++++++++------------ 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/main/Flow/HttpRequest.class.php b/main/Flow/HttpRequest.class.php index 42b1eb25a6..bbb02ab43e 100755 --- a/main/Flow/HttpRequest.class.php +++ b/main/Flow/HttpRequest.class.php @@ -82,7 +82,17 @@ public function setGetVar($name, $value) $this->get[$name] = $value; return $this; } - + + /** + * @return HttpRequest + **/ + public function setGetString($get) + { + $this->get = $get; + + return $this; + } + public function &getPost() { return $this->post; @@ -116,7 +126,17 @@ public function setPostVar($name, $value) $this->post[$name] = $value; return $this; } - + + /** + * @return HttpRequest + **/ + public function setPostString($post) + { + $this->post = $post; + + return $this; + } + public function &getServer() { return $this->server; diff --git a/main/Net/Http/CurlHttpClient.class.php b/main/Net/Http/CurlHttpClient.class.php index 574371cd9c..29f117682e 100755 --- a/main/Net/Http/CurlHttpClient.class.php +++ b/main/Net/Http/CurlHttpClient.class.php @@ -339,21 +339,24 @@ protected function makeResponse($handle, CurlHttpResponse $response) private function argumentsToString($array) { - Assert::isArray($array); - $result = array(); - - foreach ($array as $key => $value) { - if (is_array($value)) { - foreach ($value as $valueKey => $simpleValue) { - $result[] = - $key.'['.$valueKey.']='.urlencode($simpleValue); + if( is_array($array) ) { + $result = array(); + + foreach ($array as $key => $value) { + if (is_array($value)) { + foreach ($value as $valueKey => $simpleValue) { + $result[] = + $key.'['.$valueKey.']='.urlencode($simpleValue); + } + } else { + $result[] = $key.'='.urlencode($value); } - } else { - $result[] = $key.'='.urlencode($value); } + + return implode('&', $result); + } else { + return $array; } - - return implode('&', $result); } } ?> \ No newline at end of file From e681453584749b7fc3faa9904b5e88f90b6f7065 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 12 Oct 2012 19:05:12 +0400 Subject: [PATCH 143/418] mongo query fix --- core/Logic/NoSQLExpression.class.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/core/Logic/NoSQLExpression.class.php b/core/Logic/NoSQLExpression.class.php index a15f72cb03..0cd11d2927 100755 --- a/core/Logic/NoSQLExpression.class.php +++ b/core/Logic/NoSQLExpression.class.php @@ -215,9 +215,17 @@ public function getFieldList() { return $this->fields; } + /** + * @return array + */ + public function getConditions() { + return $this->conditions; + } + public function toMongoQuery() { if( empty($this->conditions) ) { - throw new WrongStateException('Sorry, query conditions are empty!'); + //throw new WrongStateException('Sorry, query conditions are empty!'); + return array(); } // make query $query = array(); From e474cfbc5a2175c7b4b4ab8be439fcaf3a76f5f7 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Thu, 18 Oct 2012 14:11:00 +0400 Subject: [PATCH 144/418] datagrid fixing --- main/UI/Widget/DataGrid.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index 81f3af3e84..810c50b27a 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -367,7 +367,9 @@ protected function getViewRenderer($value) { return get_class($value) . ' ID:' . $value->getId(); } else { try { - return DataGrid::details()->setParent($self)->addRow($value)->ToString(); + return + '' . get_class($value) . '
' . + DataGrid::details()->setParent($self)->addRow($value)->ToString(); } catch (Exception $e) { return $e->getMessage(); } From 5e66252688760ec7b2b0b5732a9733ecdcb76b61 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 19 Oct 2012 14:50:46 +0400 Subject: [PATCH 145/418] qury num rows --- core/DB/DB.class.php | 1 + core/DB/MySQL.class.php | 11 ++++++++++- core/DB/MySQLim.class.php | 11 ++++++++++- core/DB/PgSQL.class.php | 9 +++++++++ core/DB/SQLite.class.php | 11 ++++++++++- core/NoSQL/NoSQL.class.php | 4 ++++ 6 files changed, 44 insertions(+), 3 deletions(-) diff --git a/core/DB/DB.class.php b/core/DB/DB.class.php index 3477408563..1a3b8494a9 100755 --- a/core/DB/DB.class.php +++ b/core/DB/DB.class.php @@ -48,6 +48,7 @@ abstract public function queryRaw($queryString); abstract public function queryRow(Query $query); abstract public function querySet(Query $query); + abstract public function queryNumRows(Query $query); abstract public function queryColumn(Query $query); abstract public function queryCount(Query $query); diff --git a/core/DB/MySQL.class.php b/core/DB/MySQL.class.php index f69b8ca35d..db9dac840b 100755 --- a/core/DB/MySQL.class.php +++ b/core/DB/MySQL.class.php @@ -146,7 +146,16 @@ public function querySet(Query $query) } else return null; } - + + public function queryNumRows(Query $query) { + $res = $this->query($query); + + if ($res) { + return mysql_num_rows($res); + } else + return null; + } + public function queryRaw($queryString) { if (!$result = mysql_query($queryString, $this->link)) { diff --git a/core/DB/MySQLim.class.php b/core/DB/MySQLim.class.php index 5d9f78d493..d6c89cea30 100755 --- a/core/DB/MySQLim.class.php +++ b/core/DB/MySQLim.class.php @@ -131,7 +131,16 @@ public function querySet(Query $query) } else return null; } - + + public function queryNumRows(Query $query) { + $res = $this->query($query); + + if ($res) { + return mysqli_num_rows($res); + } else + return null; + } + public function queryRaw($queryString) { if (!$result = mysqli_query($this->link, $queryString)) { diff --git a/core/DB/PgSQL.class.php b/core/DB/PgSQL.class.php index 109cb69441..926f6eb2d9 100755 --- a/core/DB/PgSQL.class.php +++ b/core/DB/PgSQL.class.php @@ -187,6 +187,15 @@ public function querySet(Query $query) return null; } + public function queryNumRows(Query $query) { + $res = $this->query($query); + + if ($res) { + return pg_num_rows($res); + } else + return null; + } + public function hasSequences() { return true; diff --git a/core/DB/SQLite.class.php b/core/DB/SQLite.class.php index def227b74c..28e2de2a28 100755 --- a/core/DB/SQLite.class.php +++ b/core/DB/SQLite.class.php @@ -163,7 +163,16 @@ public function querySet(Query $query) } else return null; } - + + public function queryNumRows(Query $query) { + $res = $this->query($query); + + if ($res) { + return sqlite_num_rows($res); + } else + return null; + } + public function hasQueue() { return false; diff --git a/core/NoSQL/NoSQL.class.php b/core/NoSQL/NoSQL.class.php index 8979c70614..7d1628e3f2 100755 --- a/core/NoSQL/NoSQL.class.php +++ b/core/NoSQL/NoSQL.class.php @@ -68,6 +68,10 @@ public function querySet(Query $query) { throw new UnsupportedMethodException('Can not execute querySet in NoSQL'); } + public function queryNumRows(Query $query) { + throw new UnsupportedMethodException('Can not execute queryNumRows in NoSQL'); + } + public function queryColumn(Query $query) { throw new UnsupportedMethodException('Can not execute queryColumn in NoSQL'); } From 432c2eae38d0a6a4632de864730d8e21ad021b48 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 26 Oct 2012 11:43:20 +0400 Subject: [PATCH 146/418] criteria setSelectQuery --- main/Criteria/Criteria.class.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/main/Criteria/Criteria.class.php b/main/Criteria/Criteria.class.php index e04271132f..557439bf46 100755 --- a/main/Criteria/Criteria.class.php +++ b/main/Criteria/Criteria.class.php @@ -36,6 +36,9 @@ final class Criteria extends QueryIdentification // Обработчик критерии перед вызовом public static $prepareCriteriaCallBack = null; + // Кастомный запрос + private $selectQuery = null; + /** * @return Criteria **/ @@ -519,6 +522,10 @@ public function prepareCriteria($fullQuery = true) **/ public function toSelectQuery() { + if( !is_null($this->selectQuery) ) { + return $this->selectQuery; + } + $this->prepareCriteria(false); if (!$this->projection->isEmpty()) { @@ -592,6 +599,15 @@ public function dropProjectionByType(/* array */ $dropTypes) return $this; } + /** + * @param SelectQuery $query + * @return Criteria + **/ + public function setSelectQuery(SelectQuery $query) { + $this->selectQuery = $query; + return $this; + } + private function joinProperties( SelectQuery $query, ProtoDAO $parentDao, From 0514acabbfdd1961cb95bc443ec6c4ff348ef014 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Fri, 9 Nov 2012 12:20:42 +0400 Subject: [PATCH 147/418] add Utils/Translation to include path --- global.inc.php.tpl | 1 + 1 file changed, 1 insertion(+) diff --git a/global.inc.php.tpl b/global.inc.php.tpl index 5712833a4b..c1fb9bc023 100755 --- a/global.inc.php.tpl +++ b/global.inc.php.tpl @@ -158,6 +158,7 @@ .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Mobile'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'CommandLine'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Routers'.PATH_SEPARATOR + .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'Translation'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'AMQP'.PATH_SEPARATOR .ONPHP_MAIN_PATH.'Utils'.DIRECTORY_SEPARATOR.'AMQP' From d0126a040568d4b6ae4c98637ada406bb276d792 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Tue, 20 Nov 2012 12:33:17 +0400 Subject: [PATCH 148/418] Assert::isInteger - use Assert::checkInteger --- core/Base/Assert.class.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/core/Base/Assert.class.php b/core/Base/Assert.class.php index 7dcd40c7f5..950ff37450 100755 --- a/core/Base/Assert.class.php +++ b/core/Base/Assert.class.php @@ -108,12 +108,7 @@ public static function isNotEmptyArray(&$variable, $message = null) public static function isInteger($variable, $message = null) { - if ( - !( - is_numeric($variable) - && $variable == (int) $variable - ) - ) + if (!self::checkInteger($variable)) throw new WrongArgumentException( $message.', '.self::dumpArgument($variable) ); From 054266fa8e2747e9f1ba5c6865a4cc3cb9ca4d14 Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Tue, 20 Nov 2012 19:25:10 +0400 Subject: [PATCH 149/418] =?UTF-8?q?#1409=20=D0=9F=D0=BE=D0=B8=D1=81=D0=BA?= =?UTF-8?q?=20=D0=BF=D0=BE=20=D1=8F=D0=B7=D1=8B=D0=BA=D0=B0=D0=BC=20=D0=BF?= =?UTF-8?q?=D0=BE=20=D1=8F=D0=B7=D1=8B=D0=BA=D0=B0=D0=BC=20=D0=B2=20=D1=81?= =?UTF-8?q?=D0=BF=D0=B8=D1=81=D0=BA=D0=B5=20=D0=BE=D1=84=D1=84=D0=B5=D1=80?= =?UTF-8?q?=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/OSQL/SelectQuery.class.php | 16 ++++++++++++++++ main/Criteria/Criteria.class.php | 21 +++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/core/OSQL/SelectQuery.class.php b/core/OSQL/SelectQuery.class.php index fc9d9b9c64..7f8cbac4fc 100755 --- a/core/OSQL/SelectQuery.class.php +++ b/core/OSQL/SelectQuery.class.php @@ -33,6 +33,8 @@ final class SelectQuery private $having = null; + private $criteria = null; + // Обработчик логики джойна public static $prepareJoinLogic = null; @@ -485,5 +487,19 @@ private function makeOrder($field, $table = null) new DBField($field, $this->getLastTable($table)) ); } + + /** + * @param $criteria + */ + public function setCriteria($criteria) { + $this->criteria = $criteria; + } + + /* + * @return Criteria|null + */ + public function getCriteria() { + return $this->criteria; + } } ?> \ No newline at end of file diff --git a/main/Criteria/Criteria.class.php b/main/Criteria/Criteria.class.php index 557439bf46..4bd4e8bc57 100755 --- a/main/Criteria/Criteria.class.php +++ b/main/Criteria/Criteria.class.php @@ -36,6 +36,9 @@ final class Criteria extends QueryIdentification // Обработчик критерии перед вызовом public static $prepareCriteriaCallBack = null; + // Параметры локализации + private $localizeData = null; + // Кастомный запрос private $selectQuery = null; @@ -538,6 +541,8 @@ public function toSelectQuery() } else $query = $this->checkAndGetDao()->makeSelectHead(); + $query->setCriteria($this); + if ($this->distinct) $query->distinct(); @@ -724,5 +729,21 @@ private function getProto() array($this->checkAndGetDao()->getObjectName(), 'proto') ); } + + /** + * Устанавливает код языка локализации + * @param $localizeData + */ + public function setLocalizeData($languageCode) { + $this->localizeData = $languageCode; + } + + /** + * Возвращает код языка локализации + * @return string|null|false + */ + public function getLocalizeData() { + return $this->localizeData; + } } ?> \ No newline at end of file From d90456af9f2ab8514f9abdd841c27547e053e5e4 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Thu, 22 Nov 2012 12:02:31 +0400 Subject: [PATCH 150/418] PrototypeUtils::toArray(): substr() -> mb_substr() --- main/Utils/PrototypeUtils.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/Utils/PrototypeUtils.class.php b/main/Utils/PrototypeUtils.class.php index be6b095443..64e0886f3f 100755 --- a/main/Utils/PrototypeUtils.class.php +++ b/main/Utils/PrototypeUtils.class.php @@ -209,7 +209,7 @@ public static function toArray(Prototyped $object) { } elseif( $property->getType() == 'string' ) { $value = (string)$value; if ($property->getMax() > 0) { - $value = substr($value, 0, $property->getMax()); + $value = mb_substr($value, 0, $property->getMax()); } if (empty($value)) { // если false или "", то null From b6ecf6f1119a417cf7dc354c17ec023c8c121f05 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Fri, 23 Nov 2012 14:28:27 +0400 Subject: [PATCH 151/418] type hint mistake (int) --- main/Net/Http/CurlHttpClient.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/Net/Http/CurlHttpClient.class.php b/main/Net/Http/CurlHttpClient.class.php index 29f117682e..0429299e05 100755 --- a/main/Net/Http/CurlHttpClient.class.php +++ b/main/Net/Http/CurlHttpClient.class.php @@ -61,7 +61,7 @@ public function getOption($key) } /** - * @param $timeout in seconds + * @param $timeout int seconds * @return CurlHttpClient **/ public function setTimeout($timeout) From 87c853757ba25e14ece9c80721efdea0f03beb38 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 26 Nov 2012 13:09:42 +0400 Subject: [PATCH 152/418] mongo cursor timeout in config --- core/NoSQL/MongoBase.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index feab629abc..be85164889 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -82,7 +82,6 @@ public function connect() { if ($safe > 0) { $this->safeOnWrite = $safe; } - MongoCursor::$timeout = 120 * 1000; // 2min } catch(MongoConnectionException $e) { throw new NoSQLException( From 133ec4aeea8fe44435f47945cdcd7c8fcfe0ea16 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 26 Nov 2012 14:42:15 +0400 Subject: [PATCH 153/418] mongo cursor timeout in count --- core/NoSQL/NoSqlDAO.class.php | 1 + core/NoSQL/NoSqlResult.class.php | 61 +++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/core/NoSQL/NoSqlDAO.class.php b/core/NoSQL/NoSqlDAO.class.php index e1c0c7eaad..35e6e0dbc0 100755 --- a/core/NoSQL/NoSqlDAO.class.php +++ b/core/NoSQL/NoSqlDAO.class.php @@ -196,6 +196,7 @@ public function getNoSqlResult(Criteria $criteria, $expires = Cache::DO_NOT_CACH $criteria->setDao( $this ); $cursor = $this->getLink()->makeCursorByCriteria($criteria); return NoSqlResult::create() + ->setCriteria($criteria) ->setDao($this) ->setMongoCursor($cursor); } diff --git a/core/NoSQL/NoSqlResult.class.php b/core/NoSQL/NoSqlResult.class.php index 6680a870ca..fcdbe9e3df 100644 --- a/core/NoSQL/NoSqlResult.class.php +++ b/core/NoSQL/NoSqlResult.class.php @@ -14,6 +14,9 @@ class NoSqlResult extends QueryResult { /** @var NoSqlResultList */ protected $resultList; + /** @var Criteria */ + protected $criteria; + protected $count = null; /** @@ -25,9 +28,65 @@ public static function create() { return new static; } + + public function setCriteria(Criteria $criteria) { + $this->criteria = $criteria; + return $this; + } + + public function getCriteria() { + return $this->criteria; + } + public function getCount() { if ($this->count == null && $this->getMongoCursor()) { - $this->count = $this->getMongoCursor()->count(); + // пытаемся посчитать количество записей перебором, без использования count() + // откидиываем limit и offset + $criteria = clone $this->getCriteria(); + $criteria + ->setLimit(null) + ->setOffset(null); + // находим в логике NoSQLExpression + $expression = null; + foreach ($criteria->getLogic()->getChain() as $logic) { + if ($logic instanceof NoSQLExpression) { + $expression = $logic; + } + } + + // если нашли - делаем запрос + if ($expression instanceof NoSQLExpression) { + // берем первое попавшееся в запросе поле и запрашиваем только его + foreach ($expression->toMongoQuery() as $field => $condition) { + if ($field[0] != '$') { + $expression->addField(array($field)); + break; + } + } + + $timeStart = microtime(1); + $timeMax = Config::me()->getMongoTimeout() / 2; + $this->count = 0; + /** @var $db MongoBase */ + $db = NoSqlPool::me()->getByDao($this->getDao()); + $cursor = $db->makeCursorByCriteria($criteria); + // пересчитываем количество выбранных записей + foreach ($cursor as $item) { + $this->count++; + + // следим за таймаутом, т.к. время запроса к базе не учитывается + // в max_execution_time + if (microtime(1) - $timeStart > $timeMax) { + throw new MongoCursorTimeoutException( + 'failed to count in ' . $timeMax . ' seconds: ' + . json_encode($expression->toMongoQuery()) + ); + } + } + + } else { + $this->count = $this->getMongoCursor()->count(); + } } return $this->count; } From 070da4498c74a6b2aafaae366503dba59b60f453 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 26 Nov 2012 16:35:23 +0400 Subject: [PATCH 154/418] mongo cursor timeout in count --- core/NoSQL/NoSqlResult.class.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/NoSQL/NoSqlResult.class.php b/core/NoSQL/NoSqlResult.class.php index fcdbe9e3df..a94ae5e5d1 100644 --- a/core/NoSQL/NoSqlResult.class.php +++ b/core/NoSQL/NoSqlResult.class.php @@ -40,6 +40,9 @@ public function getCriteria() { public function getCount() { if ($this->count == null && $this->getMongoCursor()) { + $this->count = $this->getMongoCursor()->count(); + + /* -- плохой вариант, долго считает // пытаемся посчитать количество записей перебором, без использования count() // откидиываем limit и offset $criteria = clone $this->getCriteria(); @@ -67,7 +70,6 @@ public function getCount() { $timeStart = microtime(1); $timeMax = Config::me()->getMongoTimeout() / 2; $this->count = 0; - /** @var $db MongoBase */ $db = NoSqlPool::me()->getByDao($this->getDao()); $cursor = $db->makeCursorByCriteria($criteria); // пересчитываем количество выбранных записей @@ -87,6 +89,7 @@ public function getCount() { } else { $this->count = $this->getMongoCursor()->count(); } + */ } return $this->count; } From 526db2e578ceee54109817764953acc947e65d60 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 6 Dec 2012 18:04:03 +0400 Subject: [PATCH 155/418] fixed DataGrid::table + CrippleClassProjection --- core/DB/PgSQL.class.php | 4 +- main/Criteria/Projection.class.php | 8 + .../CrippleClassProjection.class.php | 29 +++ main/UI/Widget/DataGrid.class.php | 177 ++++++++++++++++-- 4 files changed, 204 insertions(+), 14 deletions(-) create mode 100644 main/Criteria/Projections/CrippleClassProjection.class.php diff --git a/core/DB/PgSQL.class.php b/core/DB/PgSQL.class.php index 926f6eb2d9..071cf973cc 100755 --- a/core/DB/PgSQL.class.php +++ b/core/DB/PgSQL.class.php @@ -115,7 +115,9 @@ public function setDbEncoding() public function queryRaw($queryString) { - if( defined('DB_PROFILE_LOG') ) { file_put_contents(DB_PROFILE_LOG, $queryString."\n", FILE_APPEND); } + if( defined('DB_PROFILE_LOG') ) { + file_put_contents(DB_PROFILE_LOG, date('Y-m-d H:i:s').' :: '.$queryString."\n", FILE_APPEND); + } try { return pg_query($this->link, $queryString); } catch (BaseException $e) { diff --git a/main/Criteria/Projection.class.php b/main/Criteria/Projection.class.php index eeff26453f..92f12eaf87 100755 --- a/main/Criteria/Projection.class.php +++ b/main/Criteria/Projection.class.php @@ -119,5 +119,13 @@ public static function clazz($className) { return new ClassProjection($className); } + + /** + * @return CrippleClassProjection + **/ + public static function crippleClass($className) + { + return new CrippleClassProjection($className); + } } ?> \ No newline at end of file diff --git a/main/Criteria/Projections/CrippleClassProjection.class.php b/main/Criteria/Projections/CrippleClassProjection.class.php new file mode 100644 index 0000000000..a98cbda369 --- /dev/null +++ b/main/Criteria/Projections/CrippleClassProjection.class.php @@ -0,0 +1,29 @@ + + * @author Alex Gorbylev + * @date 2012.12.06 + */ +class CrippleClassProjection extends ClassProjection { + + private $excludedFields = array(); + + public function excludeField($field) { + Assert::isString($field); + $this->excludedFields[$field] = $field; + return $this; + } + + /* void */ + protected function subProcess(JoinCapableQuery $query, DBField $field) { + // if need to exclude change field to NULL + if( array_key_exists($field->getField(), $this->excludedFields) ) { + $nullField = DBRaw::create('NULL'); + $query->get($nullField, $field->getField()); + } else { + $query->get($field); + } + } + + +} diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index 810c50b27a..030362034c 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -133,21 +133,24 @@ public function addRow($data, $key=null) { // и через геттеры получаем все параметры, а если // это массив, то берем его как есть. - if (is_object($data) && $data instanceof Prototyped) { + if ($data instanceof Prototyped) { /** @var $data Prototyped */ $this->objects[$rowId] = $data; $fieldIds = array(); +// $this->rows[$rowId] = null; $row = array(); + /** @var $property LightMetaProperty */ foreach ($data->proto()->getPropertyList() as $property) { - try { - $value = $this->getPropertyValue($rowId, $property); - } catch (BadMethodCallException $e) { - continue; - } catch (ObjectNotFoundException $e) { - $value = null; - } +// try { +// $value = $this->getPropertyValue($rowId, $property); +// } catch (BadMethodCallException $e) { +// continue; +// } catch (ObjectNotFoundException $e) { +// $value = null; +// } $fieldIds[] = $property->getName(); - $row[$property->getName()] = $value; + $row[$property->getName()] = null; +// $value = null; } } else if (is_array($data)) { $fieldIds = array_keys($data); @@ -175,7 +178,8 @@ public function addRow($data, $key=null) { // записываем данные foreach($row as $fieldId => $value) { - $this->setField($rowId, $fieldId, $value); + $property = ($data instanceof Prototyped) ? $data->proto()->getPropertyByName($fieldId) : null; + $this->setField($rowId, $fieldId, $value, $property); } return $this; @@ -215,7 +219,9 @@ private function setField($rowId, $fieldId, $value, $property = null) { $this->renderers[$fieldId] = $this->getEditRenderer($fieldId, $property); } else { - if ($value !== null) { + if($property instanceof LightMetaProperty) { + $this->renderers[$fieldId] = $this->getLazyViewRenderer($fieldId, $property); + } elseif($value !== null) { $this->renderers[$fieldId] = $this->getViewRenderer($value); } } @@ -342,6 +348,136 @@ protected function getEditRenderer($fieldId, LightMetaProperty $property) { } } + /** + * @param string $fieldId + * @param LightMetaProperty $property + * @return closure + * @throws ClassNotFoundException + */ + protected function getLazyViewRenderer($fieldId, LightMetaProperty $property) { + // переменные для замыканий, т.к. они не биндятся к this + $self = $this; + $trueName = $this->trueName; + $falseName = $this->falseName; + + switch($property->getType()) { + + // OneToOne + case 'integerIdentifier': + case 'scalarIdentifier': { + if( $property->getClassName()=='InternationalString' ) { + return function ($value) use ($property) { + return $value->__toString(); + }; + } elseif( $property->isIdentifier() ) { + return function ($value) use ($property) { + return $value; + }; + } elseif( is_subclass_of($property->getClassName(), 'Prototyped') ) { + return function($value, $object) use ($self) { + if ($self->hasParent($object)) { + return get_class($value) . ' ID:' . $value->getId(); + } else { + try { + return + '' . get_class($value) . '
' . + DataGrid::details()->setParent($self)->addRow($value)->ToString(); + } catch (Exception $e) { + return $e->getMessage(); + } + } + }; + } else { + return function ($value) { + return 'Object is not prototyped!'; + }; + } + } + + // OneToMany & ManyToMany + case 'identifierList': { + return function(UnifiedContainer $value, $object) use ($self) { + if ($self->hasParent($object)) { + return get_class($value) . ' count:' . $value->fetch()->getCount(); + } else { + try { + return DataGrid::table()->setParent($self)->addRows($value->fetch()->getList())->ToString(); + } catch (Exception $e) { + return $e->getMessage(); + } + } + }; + } + + case 'boolean': { + return function ($value) use ($trueName, $falseName) { + return $value ? $trueName : $falseName; + }; + } + + case 'set': { + return function($value) use ($self) { + try { + return DataGrid::table()->setParent($self)->addRows($value)->ToString(); + } catch (Exception $e) { + return $e->getMessage(); + } + }; + } + + case 'integer': { + return function ($value) { + return $value; + }; + } + + case 'float': { + return function ($value) { + return number_format($value, 2, ',', ''); + }; + } + + case 'string': { + return function ($value) { + return nl2br($value); + }; + } + + case 'timestamp': + case 'date': { + return function ($value) { + if( $value instanceof Timestamp ) { + return $value->toFormatString('d-m-Y H:i:s'); + } elseif( $value instanceof Date ) { + return $value->toFormatString('d-m-Y'); + } else { + return ''; + } + }; + } + + case 'enumeration': { + return function ($value) { + return $value->getName(); + }; + } + + default: + return function ($value) use ($property) { + // DEBUG + $props[] = 'name: ' . $property->getName(); + $props[] = 'className: ' . $property->getClassName(); + $props[] = 'type: ' . $property->getType(); + $props[] = 'min: ' . $property->getMin(); + $props[] = 'max: ' . $property->getMax(); + $props[] = 'relation: ' . $property->getRelationId(); + $props[] = 'fetch: ' . $property->getFetchStrategyId(); + //$props[] = 'value: ' . $value; + return implode(', ', $props); + }; + } + } + /** * Находит подходящий рендерер в соответствии с типом значения * @param $value @@ -681,7 +817,21 @@ protected function makeModel() { // рендерим данные foreach ($this->rows as $rowId => $row) { foreach ($this->fields as $fieldId => $fieldName) { - $field = isset($row[$fieldId]) ? $row[$fieldId] : null; + $object = isset($this->objects[$rowId]) ? $this->objects[$rowId] : $this->rows[$rowId]; + if( $object instanceof Prototyped ) { + try { + $field = PrototypeUtils::getValue($object, $fieldId); +// $property = $object->proto()->getPropertyByName($fieldId); +// $field = $object->{$property->getGetter()}(); + } catch( Exception $e ) { + $field = null; + } + } elseif( isset($row[$fieldId]) ) { + $field = $row[$fieldId]; + } else { + $field = null; + } + if ($this->form instanceof Form && $this->form->exists($fieldId)) { if ($this->form->get($fieldId)->isImported()) $field = $this->form->get($fieldId)->getValue(); @@ -690,9 +840,10 @@ protected function makeModel() { } // если есть рендерер, прогоним значение через него +// var_dump($this->renderers); +// die(); if (isset($this->renderers[$fieldId])) { $callback = $this->renderers[$fieldId]; - $object = isset($this->objects[$rowId]) ? $this->objects[$rowId] : $this->rows[$rowId]; if ($this->renderers[$fieldId] instanceof Closure) { $field = $callback($field, $object); } else { From cccd787c49163d4994279dcabbd5c2a42395db0d Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 6 Dec 2012 18:30:52 +0400 Subject: [PATCH 156/418] DataGrid fix --- main/UI/Widget/DataGrid.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index 030362034c..08a1d7ecf4 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -458,7 +458,11 @@ protected function getLazyViewRenderer($fieldId, LightMetaProperty $property) { case 'enumeration': { return function ($value) { - return $value->getName(); + if( $value instanceof Enumeration ) { + return $value->getName(); + } else { + return ''; + } }; } From c566eac8501527322fca14acec3e6184fe4ba34b Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 7 Dec 2012 10:55:46 +0400 Subject: [PATCH 157/418] MongoDB driver 1.3 support --- core/NoSQL/MongoBase.class.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index be85164889..f2ae9967cf 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -47,6 +47,8 @@ class MongoBase extends NoSQL { * @throws NoSQLException */ public function connect() { + $Mongo = class_exists('MongoClient') ? 'MongoClient' : 'Mongo'; + if (empty($this->connectionString)) { $conn = 'mongodb://' @@ -69,9 +71,13 @@ public function connect() { $options['persist'] = $this->hostname.'-'.$this->basename; } try { - $this->link = new Mongo($conn, $options); + $this->link = new $Mongo($conn, $options); $this->db = $this->link->selectDB($this->basename); - $this->link->setSlaveOkay($options['slaveOkay']); + if( method_exists($Mongo, 'setReadPreference') ) { + $this->link->setReadPreference($options['slaveOkay'] ? Mongo::RP_SECONDARY_PREFERRED : Mongo::RP_PRIMARY_PREFERRED); + } else { + $this->link->setSlaveOkay($options['slaveOkay']); + } // получаем количество реплик в статусах PRIMARY и SECONDARY в сете $safe = 0; foreach ($this->link->getHosts() as $host) { From 9c7ed54959fd2783bb1f305c5f9682ba8382ba15 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 7 Dec 2012 11:12:28 +0400 Subject: [PATCH 158/418] fix --- core/NoSQL/MongoBase.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index f2ae9967cf..08431678b1 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -47,7 +47,8 @@ class MongoBase extends NoSQL { * @throws NoSQLException */ public function connect() { - $Mongo = class_exists('MongoClient') ? 'MongoClient' : 'Mongo'; + //$Mongo = class_exists('MongoClient') ? 'MongoClient' : 'Mongo'; + $Mongo = 'Mongo'; if (empty($this->connectionString)) { $conn = From a47dacc538ad14462b15e84f343e98d4531a1c5a Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 7 Dec 2012 11:49:36 +0400 Subject: [PATCH 159/418] mongo fix --- core/NoSQL/MongoBase.class.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 08431678b1..d5913bc25d 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -47,8 +47,13 @@ class MongoBase extends NoSQL { * @throws NoSQLException */ public function connect() { - //$Mongo = class_exists('MongoClient') ? 'MongoClient' : 'Mongo'; - $Mongo = 'Mongo'; + // в зависимости от версии драйвера создаем нужного клиента + try { + Assert::classExists('MongoClient'); + $Mongo = 'MongoClient'; + } catch( Exception $e ) { + $Mongo = 'Mongo'; + } if (empty($this->connectionString)) { $conn = From d22687a45efb5bcd6c0783cea51f553c6a5f6d22 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 10 Dec 2012 18:07:42 +0400 Subject: [PATCH 160/418] DataGrid - allow non-prototyped getters --- main/UI/Widget/DataGrid.class.php | 40 +++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index 08a1d7ecf4..8d8bc51d7a 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -666,19 +666,33 @@ public function setFields(array $fields) { $failed = false; foreach ($path as $propertyName) { - if (!$object || !($object instanceof Prototyped)) { - $failed = true; - break; - } - $property = $object->proto()->getPropertyByName($propertyName); - if ($property != null) { - $getter = $property->getGetter(); - $object = $object->$getter(); - } else { - $failed = true; - break; - } - } + + if ($object instanceof Prototyped) { + try { + $property = $object->proto()->getPropertyByName($propertyName); + $getter = $property->getGetter(); + $object = $object->$getter(); + continue; + } catch (MissingElementException $e) { + // none + } + } + + if (is_object($object)) { + try { + // support non-prototyped getters + $getter = 'get' . ucfirst($propertyName); + Assert::methodExists($object, $getter); + $object = $object->$getter(); + continue; + } catch (WrongArgumentException $e) { + // none + } + } + + $failed = true; + break; + } if (!$failed) { $this->setField($rowId, $fieldId, $object, $property); From 45fff4aa29afad528254438617404f9eeed3f8f9 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 10 Dec 2012 18:09:09 +0400 Subject: [PATCH 161/418] PrototypeUtils::setValue - use 'dropper' method (if available) when setting null --- main/Utils/PrototypeUtils.class.php | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/main/Utils/PrototypeUtils.class.php b/main/Utils/PrototypeUtils.class.php index 64e0886f3f..257810379d 100755 --- a/main/Utils/PrototypeUtils.class.php +++ b/main/Utils/PrototypeUtils.class.php @@ -121,15 +121,12 @@ public static function setValue(Prototyped $object, $path, $value) { $object = self::getValue($object, implode('.', $path)); $setter = 'set' . ucfirst($valueName); - return $object->$setter($value); - - // old: - $property = self::getProperty($object->proto(), $path); - $setter = $property->getSetter(); - if (!method_exists($object, $setter)) { - throw new WrongArgumentException; - } - $object->$setter($value); + $dropper = 'drop' . ucfirst($valueName); + if (is_null($value) && method_exists($object, $dropper)) { + return $object->$dropper(); + } else { + return $object->$setter($value); + } } public static function hasProperty(Prototyped $object, $path) { From e16038dd360fc377d8c97b6ab7646ceadae24cab Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Wed, 12 Dec 2012 19:24:09 +0400 Subject: [PATCH 162/418] =?UTF-8?q?#2095=20=D0=97=D0=B0=D0=BB=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20=D0=BF=D0=BE=D1=80=D1=82=D1=83=D0=B3=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D1=81=D0=BA=D0=B8=D0=B5=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=BE?= =?UTF-8?q?=D0=B4=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/UI/Widget/DataGrid.class.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index 8d8bc51d7a..dba56ef6e8 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -19,6 +19,9 @@ class DataGrid extends BaseWidget /** @var array список 'fieldID' => 'Field name' */ protected $fields = array(); + /** @var array список локализованных полей */ + protected $localizedFields = array(); + /** @var array список полей, по которым можно сортировать. * Фактически, исключает поля, добавленные через addColumn */ protected $sortingFields = array(); @@ -134,6 +137,14 @@ public function addRow($data, $key=null) { // это массив, то берем его как есть. if ($data instanceof Prototyped) { + if ($data instanceof TranslatableFieldsObject) { + /** @var $data TranslatableFieldsObject */ + $localizedFields = $data->getLocalizedFields(); + $this->localizedFields = array_merge( + array_keys($localizedFields), + array_values($localizedFields) + ); + } /** @var $data Prototyped */ $this->objects[$rowId] = $data; $fieldIds = array(); @@ -898,6 +909,7 @@ protected function makeModel() { $model = parent::makeModel() ->set('fields', $this->fields) + ->set('localizedFields', $this->localizedFields) ->set('data', $data) ->set('totalId', $this->totalId) ->set('htmlOptions', $htmlOptions) From dfec15506a218690f3a014c233b30007dee66e42 Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Wed, 12 Dec 2012 19:59:16 +0400 Subject: [PATCH 163/418] =?UTF-8?q?=D0=BC=D0=B0=D1=81=D1=81=D0=B8=D0=B2=20?= =?UTF-8?q?=D0=BB=D0=BE=D0=BA=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BF=D0=BE=D0=BB=D0=B5=D0=B9=20-?= =?UTF-8?q?=20=D1=81=D0=BE=D0=B1=D0=B8=D1=80=D0=B0=D0=B5=D0=BC=20=D0=BE?= =?UTF-8?q?=D0=B4=D0=B8=D0=BD=20=D1=80=D0=B0=D0=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/UI/Widget/DataGrid.class.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index dba56ef6e8..f93504127d 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -20,7 +20,7 @@ class DataGrid extends BaseWidget protected $fields = array(); /** @var array список локализованных полей */ - protected $localizedFields = array(); + protected $localizedFields = null; /** @var array список полей, по которым можно сортировать. * Фактически, исключает поля, добавленные через addColumn */ @@ -137,7 +137,10 @@ public function addRow($data, $key=null) { // это массив, то берем его как есть. if ($data instanceof Prototyped) { - if ($data instanceof TranslatableFieldsObject) { + if ( + $data instanceof TranslatableFieldsObject + && is_null($this->localizedFields) + ) { /** @var $data TranslatableFieldsObject */ $localizedFields = $data->getLocalizedFields(); $this->localizedFields = array_merge( @@ -909,7 +912,7 @@ protected function makeModel() { $model = parent::makeModel() ->set('fields', $this->fields) - ->set('localizedFields', $this->localizedFields) + ->set('localizedFields', $this->localizedFields ? : array()) ->set('data', $data) ->set('totalId', $this->totalId) ->set('htmlOptions', $htmlOptions) From cccff9cfb5a245c1662f0f0b026bad9b31548e12 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 20 Dec 2012 17:55:31 +0400 Subject: [PATCH 164/418] RedisNoSQL cache peer --- core/NoSQL/RedisNoSQL.class.php | 215 ++++++++++++++++++++++++++++ core/NoSQL/RedisNoSQLList.class.php | 161 +++++++++++++++++++++ 2 files changed, 376 insertions(+) create mode 100644 core/NoSQL/RedisNoSQL.class.php create mode 100644 core/NoSQL/RedisNoSQLList.class.php diff --git a/core/NoSQL/RedisNoSQL.class.php b/core/NoSQL/RedisNoSQL.class.php new file mode 100644 index 0000000000..cb2bfb9bab --- /dev/null +++ b/core/NoSQL/RedisNoSQL.class.php @@ -0,0 +1,215 @@ +host = $host; + $this->port = $port; + $this->timeout = $timeout; + } + + public function __destruct() + { + if ($this->alive) { + try { + $this->redis->close(); //if pconnect - it will be ignored + } catch (RedisException $e) { + // shhhh. + } + } + } + + public function clean() + { + $this->ensureTriedToConnect(); + + try { + $this->redis->flushDB(); + } catch (RedisException $e) { + $this->alive = false; + } + + return parent::clean(); + } + + public function isAlive() + { + $this->ensureTriedToConnect(); + + try { + $this->alive = $this->redis->ping() == '+PONG'; + } catch (RedisException $e) { + $this->alive = false; + } + + return parent::isAlive(); + } + + public function append($key, $data) + { + $this->ensureTriedToConnect(); + + try { + return $this->redis->append($key, $data); + } catch (RedisException $e) { + return $this->alive = false; + } + } + + public function decrement($key, $value) + { + $this->ensureTriedToConnect(); + + try { + return $this->redis->decrBy($key, $value); + } catch (RedisException $e) { + return null; + } + } + + public function delete($key) + { + $this->ensureTriedToConnect(); + + try { + return $this->redis->delete($key); + } catch (RedisException $e) { + return $this->alive = false; + } + } + + public function get($key) + { + $this->ensureTriedToConnect(); + + try { + return $this->redis->get($key); + } catch (RedisException $e) { + $this->alive = false; + + return null; + } + } + + public function increment($key, $value) + { + $this->ensureTriedToConnect(); + + try { + return $this->redis->incrBy($key, $value); + } catch (RedisException $e) { + return null; + } + } + + /** + * @param string $key + * + * @return RedisNoSQLList + */ + public function fetchList($key, $timeout = null) + { + $this->ensureTriedToConnect(); + + return new RedisNoSQLList($this->redis, $key, $timeout); + } + + /** + * @param string $key + * + * @return RedisNoSQLSet + */ + public function fetchSet($key) + { + throw new UnimplementedFeatureException(); + } + + /** + * @param string $key + * + * @return RedisNoSQLHash + */ + public function fetchHash($key) + { + throw new UnimplementedFeatureException(); + } + + protected function store($action, $key, $value, $expires = Cache::EXPIRES_MEDIUM) + { + $this->ensureTriedToConnect(); + + switch ($action) { + case 'set': + case 'replace': + case 'add': + try { + $result = $this->redis->set($key, $value); + $this->redis->expire($key, $expires); + return $result; + } catch (RedisException $e) { + return $this->alive = false; + } + + default: + throw new UnimplementedFeatureException(); + } + } + + protected function ensureTriedToConnect() + { + if ($this->triedConnect) + return $this; + + $this->triedConnect = true; + + $this->redis = new Redis(); + + try { + $this->redis->pconnect($this->host, $this->port, $this->timeout); + $this->isAlive(); + } catch (RedisException $e) { + $this->alive = false; + } + + return $this; + } +} diff --git a/core/NoSQL/RedisNoSQLList.class.php b/core/NoSQL/RedisNoSQLList.class.php new file mode 100644 index 0000000000..3e5f06a15d --- /dev/null +++ b/core/NoSQL/RedisNoSQLList.class.php @@ -0,0 +1,161 @@ +redis = $redis; + $this->key = $key; + $this->timeout = $timeout; + } + + /** + * @param mixed $value + * @return RedisList + */ + public function append($value) + { + $this->redis->rpush($this->key, $value); + + if ($this->timeout) + $this->redis->setTimeout($this->key, $this->timeout); + + return $this; + } + + /** + * @param mixed $value + * @return RedisList + */ + public function prepend($value) + { + $this->redis->lpush($this->key, $value); + + if ($this->timeout) + $this->redis->setTimeout($this->key, $this->timeout); + + return $this; + } + + /** + * @return RedisList + */ + public function clear() + { + $this->redis->LTrim($this->key, -1, 0); + + return $this; + } + + + public function count() + { + return $this->redis->lsize($this->key); + } + + public function pop() + { + return $this->redis->lpop($this->key); + } + + public function range($start, $length = null) + { + $end = is_null($length) + ? -1 + : $start + $length; + + return $this->redis->lrange($this->key, $start, $end); + } + + public function get($index) + { + return $this->redis->lget($this->key, $index); + } + + public function set($index, $value) + { + $this->redis->lset($this->key, $index, $value); + + if ($this->timeout) + $this->redis->expire($this->key, $this->timeout); + + return $this; + } + + public function trim($start, $length = null) + { + $end = is_null($length) + ? -1 + : $start + $length - 1; + + $this->redis->ltrim($this->key, $start, $end); + } + + //region Iterator + public function current() + { + return $this->get($this->position); + } + + public function key() + { + return $this->position; + } + + public function next() + { + $this->position++; + } + + public function rewind() + { + $this->position = 0; + } + + public function valid() + { + return $this->offsetExists($this->position); + } + //endregion + + //region ArrayAccess + + public function offsetExists($offset) + { + return false !== $this->get($offset); + } + + public function offsetGet($offset) + { + return $this->get($offset); + } + + public function offsetSet($offset, $value) + { + return $this->set($offset, $value); + } + + public function offsetUnset($offset) + { + throw new UnimplementedFeatureException(); + } + + public function seek($position) { + $this->position = $position; + } + //endregion +} \ No newline at end of file From 30c5dc9355584e85b1a2e6213ce1ca1ef3e6bd0c Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 25 Dec 2012 15:12:41 +0400 Subject: [PATCH 165/418] redis fix --- core/Cache/ListGenerator.class.php | 21 +++++++++++++++++++++ core/NoSQL/RedisNoSQL.class.php | 4 ++++ 2 files changed, 25 insertions(+) create mode 100644 core/Cache/ListGenerator.class.php diff --git a/core/Cache/ListGenerator.class.php b/core/Cache/ListGenerator.class.php new file mode 100644 index 0000000000..b21a2a61b5 --- /dev/null +++ b/core/Cache/ListGenerator.class.php @@ -0,0 +1,21 @@ +redis->info(); + } + protected function store($action, $key, $value, $expires = Cache::EXPIRES_MEDIUM) { $this->ensureTriedToConnect(); From 791ca7fcbc13fffacb5dcb73e391d0533ee3b2ae Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 25 Dec 2012 16:16:13 +0400 Subject: [PATCH 166/418] interface Listable add --- core/Base/Listable.class.php | 65 ++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 core/Base/Listable.class.php diff --git a/core/Base/Listable.class.php b/core/Base/Listable.class.php new file mode 100644 index 0000000000..958486f772 --- /dev/null +++ b/core/Base/Listable.class.php @@ -0,0 +1,65 @@ + Date: Wed, 16 Jan 2013 09:47:04 +0400 Subject: [PATCH 167/418] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B0=D1=82=D1=82=D1=80=D0=B8=D0=B1=D1=83=D1=82?= =?UTF-8?q?=D1=8B=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B5=20=D1=82=D0=B0?= =?UTF-8?q?=D0=B1=D0=BB=D0=B8=D1=86=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/UI/Widget/DataGrid.class.php | 33 ++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index f93504127d..7b0c320ee3 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -59,6 +59,9 @@ class DataGrid extends BaseWidget /** @var string текстовый вывод булевого типа */ public $falseName = null; + + /** @var array аттрибуты строки таблицы */ + public $rowAttrs = array(); /** * Создает таблицу вида сводки (заголовок слева) @@ -840,16 +843,31 @@ public function setForm(Form $form) { $this->form = $form; return $this; } + + /** + * + * @param array $rowAttrs + * @return DataGrid + */ + public function setRowAttrs($rowAttrs) { + $this->rowAttrs = $rowAttrs; + return $this; + } /** * @return Model */ protected function makeModel() { $data = array(); + + if (empty($this->rowAttrs['class'])) { + $this->rowAttrs['class'] = ''; + } + // рендерим данные foreach ($this->rows as $rowId => $row) { + $object = isset($this->objects[$rowId]) ? $this->objects[$rowId] : $this->rows[$rowId]; foreach ($this->fields as $fieldId => $fieldName) { - $object = isset($this->objects[$rowId]) ? $this->objects[$rowId] : $this->rows[$rowId]; if( $object instanceof Prototyped ) { try { $field = PrototypeUtils::getValue($object, $fieldId); @@ -884,6 +902,19 @@ protected function makeModel() { } $data[$rowId][$fieldId] = $field; } + + $attrs = array(); + + foreach ($this->rowAttrs as $key => $value) { + if ($value instanceof Closure) { + $value = $value($object); + } + if ('class' == $key) { + $value = ($rowId % 2 ? 'odd ' : 'even ') . $value; + } + array_push($attrs, $key . '="' . $value . '"'); + } + $data[$rowId]['attrs'] = implode(' ', $attrs); } // отрендерим аттрибуты html From 96dc34ec7eb73f2ef0b74257158bc5168fbe4ebe Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 25 Jan 2013 16:33:16 +0400 Subject: [PATCH 168/418] JsonView supports callback --- main/UI/View/JsonView.class.php | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) mode change 100755 => 100644 main/UI/View/JsonView.class.php diff --git a/main/UI/View/JsonView.class.php b/main/UI/View/JsonView.class.php old mode 100755 new mode 100644 index 3df47ca817..de84cc89bd --- a/main/UI/View/JsonView.class.php +++ b/main/UI/View/JsonView.class.php @@ -15,6 +15,7 @@ final class JsonView implements View, Stringable { protected $options = 0; + protected $callback = null; /** * @return JsonView @@ -147,13 +148,31 @@ public function setUnescapedSlashes($flag = false) return $this; } + + /** + * создание callback + * + * @param $callback + * @return JsonView + */ + public function setCallBack($callback) + { + $this->callback = $callback; + + return $this; + } /** * @return JsonView **/ public function render(/* Model */ $model = null) { - echo $this->toString($model); + if (is_null($this->callback)) { + echo $this->toString($model); + } + else { + echo $this->callback.'('.$this->toString($model).')'; + } return $this; } From 8743bb80e7bb2d0e20d9ae5500807c33a68e0979 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Tue, 29 Jan 2013 13:00:11 +0400 Subject: [PATCH 169/418] =?UTF-8?q?PrototypeUtils::same()=20--=20=D1=81?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=B2?= =?UTF-8?q?=D1=83=D1=85=20=D0=BE=D0=B1=D1=8A=D0=B5=D0=BA=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/Utils/PrototypeUtils.class.php | 49 +++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/main/Utils/PrototypeUtils.class.php b/main/Utils/PrototypeUtils.class.php index 257810379d..08efb76ab7 100755 --- a/main/Utils/PrototypeUtils.class.php +++ b/main/Utils/PrototypeUtils.class.php @@ -229,4 +229,53 @@ public static function toArray(Prototyped $object) { return $entity; } + /** + * @param Prototyped $a first object + * @param Prototyped $b second object + * @param array $ignore properties to ignore + * @return bool + * @throws WrongArgumentException + */ + public static function same(Prototyped $a, Prototyped $b, $ignore = array('id')) { + // проверим что прото совпадают + if (get_class($a->proto()) != get_class($b->proto())) { + throw new WrongArgumentException('objects have different protos'); + } + + // берем первое прото + $proto = $a->proto(); + + // собираем список геттеров + $getters = array(); + foreach ($proto->getPropertyList() as $property) { + /** @var $property LightMetaProperty */ + + // исключаем указанные в параметре $ignore + if (in_array($property->getName(), $ignore)) { + continue; + } + + // обычные свойства + if ($property->getRelationId() == null) { + $getters []= $property->getGetter(); + } + + // свойства, ссылающиеся на объект - берем ID + if ($property->getRelationId() == MetaRelation::ONE_TO_ONE) { + $getters []= $property->getGetter() . 'Id'; + } + + // one-to-many, many-to-many не проверяем + } + + // сравнение + foreach ($getters as $getter) { + if ($a->{$getter}() != $b->{$getter}()) { + return false; + } + } + + return true; + } + } From 55ce5a9b07be9bf16dd36113925dbcdd122c3dfa Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Wed, 30 Jan 2013 20:17:29 +0400 Subject: [PATCH 170/418] =?UTF-8?q?#2174=20=D0=A1=D0=BF=D0=B8=D1=81=D0=BE?= =?UTF-8?q?=D0=BA=20=D0=B0=D0=BA=D1=86=D0=B8=D0=B9=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=B2=D0=B5=D0=B1=D0=B0:=20=D0=B4=D0=B8=D0=BD=D0=B0=D0=BC?= =?UTF-8?q?=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B0=D1=8F=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B0=20=D0=B4=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D1=85=20=D0=B8=20=D0=BA=D1=8D=D1=88=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/UI/Widget/DataGrid.class.php | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index 7b0c320ee3..8cf293d2df 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -42,8 +42,11 @@ class DataGrid extends BaseWidget /** @var array аттрибуты */ protected $formHtmlOptions = array(); - /** @var bool показывать заголовки или нет */ - protected $showHeader = true; + /** @var bool показывать начальный тег */ + protected $showHeadTag = true; + + /** @var bool показывать заголовки или нет */ + protected $showHeader = true; /** @var bool показывать кнопки сортировки */ protected $showSorting = true; @@ -756,6 +759,24 @@ public function setRenderer($fieldId, $callback) { return $this; } + /** + * Показать начальный тег + * @return DataGrid + */ + public function showHeadTag() { + $this->showHeadTag = true; + return $this; + } + + /** + * Скрыть начальный тег + * @return DataGrid + */ + public function hideHeadTag() { + $this->showHeadTag = false; + return $this; + } + /** * Показать названия колонок * @return DataGrid @@ -948,6 +969,7 @@ protected function makeModel() { ->set('totalId', $this->totalId) ->set('htmlOptions', $htmlOptions) ->set('formOptions', $formOptions) + ->set('showHeadTag', $this->showHeadTag) ->set('showHeader', $this->showHeader) ->set('showSorting', $this->showSorting) ->set('sortingFields', $this->sortingFields) From 7c3a618c3dea379bf3cab43957933282b2b25a53 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 7 Feb 2013 17:52:43 +0400 Subject: [PATCH 171/418] PrimitiveMultiList fix --- core/Form/Primitives/PrimitiveMultiList.class.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/Form/Primitives/PrimitiveMultiList.class.php b/core/Form/Primitives/PrimitiveMultiList.class.php index a8844a25c3..2a0ca278ab 100755 --- a/core/Form/Primitives/PrimitiveMultiList.class.php +++ b/core/Form/Primitives/PrimitiveMultiList.class.php @@ -46,8 +46,9 @@ public function setDefault($default) foreach ($default as $index) Assert::isTrue(array_key_exists($index, $this->list)); - - return parent::setDefault($default); + + $this->default = $default; + return $this; } public function import($scope) From d15abfffca37ecf5c47dbe5b782055fc8c8b6b7b Mon Sep 17 00:00:00 2001 From: klkvsk Date: Wed, 13 Feb 2013 12:47:06 +0400 Subject: [PATCH 172/418] MongoBase - writeConcern --- core/NoSQL/MongoBase.class.php | 70 ++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index d5913bc25d..b0f8bdd6ee 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -38,9 +38,9 @@ class MongoBase extends NoSQL { protected $db = null; /** - * @var int параметр safe + * @var int параметр "safe" ("w" в 1.3.0+) */ - protected $safeOnWrite = true; + protected $writeConcern = 1; /** * @return MongoDB @@ -48,12 +48,7 @@ class MongoBase extends NoSQL { */ public function connect() { // в зависимости от версии драйвера создаем нужного клиента - try { - Assert::classExists('MongoClient'); - $Mongo = 'MongoClient'; - } catch( Exception $e ) { - $Mongo = 'Mongo'; - } + $Mongo = self::getClientClass(); if (empty($this->connectionString)) { $conn = @@ -80,19 +75,12 @@ public function connect() { $this->link = new $Mongo($conn, $options); $this->db = $this->link->selectDB($this->basename); if( method_exists($Mongo, 'setReadPreference') ) { - $this->link->setReadPreference($options['slaveOkay'] ? Mongo::RP_SECONDARY_PREFERRED : Mongo::RP_PRIMARY_PREFERRED); + $this->link->setReadPreference($options['slaveOkay'] ? $Mongo::RP_SECONDARY_PREFERRED : $Mongo::RP_PRIMARY_PREFERRED); } else { $this->link->setSlaveOkay($options['slaveOkay']); } - // получаем количество реплик в статусах PRIMARY и SECONDARY в сете - $safe = 0; - foreach ($this->link->getHosts() as $host) { - if (isset($host['state']) && ($host['state'] == 1 || $host['state'] == 2)) { - $safe++; - } - } - if ($safe > 0) { - $this->safeOnWrite = $safe; + if (isset($options['w'])) { + $this->writeConcern = $options['w']; } } catch(MongoConnectionException $e) { @@ -189,7 +177,14 @@ public function insert($table, array $row, $options = array()) { array('safe' => true), $options ); - if ($options['safe']) $options['safe'] = $this->safeOnWrite; + if ($options['safe']) { + if ($this->checkVersion('1.3.0')) { + $options['w'] = $this->writeConcern; + unset($options['safe']); + } else { + $options['safe'] = $this->writeConcern; + } + } // save $result = $this @@ -216,7 +211,14 @@ public function update($table, array $row, $options = array()) { array('safe' => true), $options ); - if ($options['safe']) $options['safe'] = $this->safeOnWrite; + if ($options['safe']) { + if ($this->checkVersion('1.3.0')) { + $options['w'] = $this->writeConcern; + unset($options['safe']); + } else { + $options['safe'] = $this->writeConcern; + } + } $result = $this @@ -583,5 +585,33 @@ protected function parseCriteria(Criteria $criteria=null) { return $result; } + /** + * Возвращает актуальное имя класса клиента + * @return string + */ + public static function getClientClass() { + try { + Assert::classExists('MongoClient'); + return 'MongoClient'; + } catch( Exception $e ) { + return 'Mongo'; + } + } + + /** + * Проверяет, что драйвер соответствует или новее версии $lowest + * @param string $lowest версия в виде "1.2.3" + * @return boolean + */ + public static function checkVersion($lowest) { + $Mongo = self::getClientClass(); + try { + $version = constant($Mongo . '::VERSION'); + } catch (BaseException $e) { + return false; + } + return version_compare($version, $lowest, '>='); + } + //@} } From 62232e112bbacb9dab9b6bc20bf69eca0757d086 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 28 Feb 2013 16:08:12 +0400 Subject: [PATCH 173/418] MimeMail improvement --- main/Net/Mail/MimeMail.class.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/main/Net/Mail/MimeMail.class.php b/main/Net/Mail/MimeMail.class.php index bfeb2caf9f..95834042da 100755 --- a/main/Net/Mail/MimeMail.class.php +++ b/main/Net/Mail/MimeMail.class.php @@ -23,6 +23,8 @@ final class MimeMail implements MailBuilder private $headers = null; private $boundary = null; + + private $contentType= null; /** * @return MimeMail @@ -41,10 +43,10 @@ public function build() if (!$this->boundary) $this->boundary = '=_'.md5(microtime(true)); - + $mail = MimePart::create()-> - setContentType('multipart/mixed')-> + setContentType(is_null($this->contentType)?'multipart/mixed':$this->contentType)-> setBoundary($this->boundary); $this->headers = @@ -93,5 +95,13 @@ public function getBoundary() { return $this->boundary; } + + public function setContentType($type) { + $this->contentType = $type; + + return $this; + } + + } ?> \ No newline at end of file From 554baac4378bac159902e6d05fef53bd9d01c2bd Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Mon, 11 Mar 2013 12:17:16 +0400 Subject: [PATCH 174/418] create index unique fix --- core/OSQL/DBTable.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/OSQL/DBTable.class.php b/core/OSQL/DBTable.class.php index 2f176b034d..6e89fedbc8 100755 --- a/core/OSQL/DBTable.class.php +++ b/core/OSQL/DBTable.class.php @@ -213,7 +213,8 @@ public static function findDifferences( if ($column->hasReference()) { $out[] = - 'CREATE INDEX '.$dialect->quoteField($name.'_idx') + 'CREATE INDEX '.$dialect->quoteTable($target->getName()).'_' + .$dialect->quoteField($name.'_idx') .' ON '.$dialect->quoteTable($target->getName()). '('.$dialect->quoteField($name).');'; } From 44632c74eb232dfb3110af8ddb5a6038337ec46d Mon Sep 17 00:00:00 2001 From: klkvsk Date: Tue, 12 Mar 2013 18:36:55 +0400 Subject: [PATCH 175/418] MongoBase -- reconnect and retry on error while saving --- core/NoSQL/MongoBase.class.php | 94 ++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 17 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index b0f8bdd6ee..1893b3c093 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -42,8 +42,23 @@ class MongoBase extends NoSQL { */ protected $writeConcern = 1; + /** @var bool */ + protected $isRetrying = false; + + protected function reconnectAndRetry($function, $args) { + $this->disconnect()->connect(); + $this->isRetrying = true; + try { + call_user_func_array(array($this, $function), $args); + } catch (Exception $e) { + $this->isRetrying = false; + throw $e; + } + $this->isRetrying = false; + } + /** - * @return MongoDB + * @return MongoBase * @throws NoSQLException */ public function connect() { @@ -97,7 +112,7 @@ public function connect() { } /** - * @return MongoDB + * @return MongoBase */ public function disconnect() { if( $this->isConnected() ) { @@ -185,16 +200,34 @@ public function insert($table, array $row, $options = array()) { $options['safe'] = $this->writeConcern; } } - // save - $result = - $this - ->db + + $isSafe = isset($options['safe']) || isset($options['w']); + + try { + $result = + $this->db ->selectCollection($table) ->insert($row, $options); - // checking result - if( !$result ) { - throw new NoSQLException('Could not insert object: '.var_export($row, true)); + + if ($isSafe && is_array($result)) { + $this->checkResult($result); + } + + } catch (Exception $e) { + if ($this->isRetrying) { + if ($e instanceof MongoCursorException && $e->getCode() == 11000) { + // E11000 == duplicate key error index + // если это вылезло при повторной попытке, значит первый раз таки вставили + } else { + throw $e; + } + } elseif ($e instanceof MongoCursorTimeoutException) { + $this->reconnectAndRetry(__FUNCTION__, func_get_args()); + } else { + throw $e; + } } + // return clean row return $this->decodeId($row); } @@ -220,20 +253,47 @@ public function update($table, array $row, $options = array()) { } } - $result = - $this - ->db - ->selectCollection($table) - ->update(array('_id' => $id), $row, $options); - // checking result - if( !$result ) { - throw new NoSQLException('Could not update object: '.var_export($row, true)); + $isSafe = isset($options['safe']) || isset($options['w']); + + try { + + $result = + $this + ->db + ->selectCollection($table) + ->update(array('_id' => $id), $row, $options); + + if ($isSafe && is_array($result)) { + $this->checkResult($result); + } + + } catch (Exception $e) { + if ($e instanceof MongoCursorTimeoutException && !$this->isRetrying) { + $this->reconnectAndRetry(__FUNCTION__, func_get_args()); + } else { + throw $e; + } } + $row['_id'] = $id; // return clean row return $this->decodeId($row); } + protected function checkResult($result) { + if (!isset($result['ok']) || $result['ok'] == 0) { + $code = isset($result['code']) ? $result['code'] : 0; + $message = ''; + if (isset($result['err'])) { + $message .= 'err: ' . $result['err'] . '. '; + } + if (isset($result['errmsg'])) { + $message .= 'errmsg: ' . $result['errmsg'] . '. '; + } + throw new MongoException($message, $code); + } + } + public function deleteOne($table, $key) { return $this From 29c29f52d9758cd251f11ca8f7599b3aaf085933 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Wed, 13 Mar 2013 13:17:44 +0400 Subject: [PATCH 176/418] reconnectAndRetry -- add pause --- core/NoSQL/MongoBase.class.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 1893b3c093..0be0e6e524 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -46,7 +46,10 @@ class MongoBase extends NoSQL { protected $isRetrying = false; protected function reconnectAndRetry($function, $args) { - $this->disconnect()->connect(); + // have you tried turning it off and on again? (c) + $this->disconnect(); + sleep(1); + $this->connect(); $this->isRetrying = true; try { call_user_func_array(array($this, $function), $args); From 23a455f5f201a18bcd742100eed1693c539f5fcf Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Wed, 13 Mar 2013 20:00:04 +0400 Subject: [PATCH 177/418] #2248 add executor + fixes --- core/OSQL/DBTable.class.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/OSQL/DBTable.class.php b/core/OSQL/DBTable.class.php index 6e89fedbc8..1af47df39f 100755 --- a/core/OSQL/DBTable.class.php +++ b/core/OSQL/DBTable.class.php @@ -213,8 +213,7 @@ public static function findDifferences( if ($column->hasReference()) { $out[] = - 'CREATE INDEX '.$dialect->quoteTable($target->getName()).'_' - .$dialect->quoteField($name.'_idx') + 'CREATE INDEX '.$dialect->quoteField($target->getName().'_'.$name.'_idx') .' ON '.$dialect->quoteTable($target->getName()). '('.$dialect->quoteField($name).');'; } From 2ec88ed9cb519b3ea8bedf026221efcf8ae925a0 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 27 Mar 2013 10:37:18 +0400 Subject: [PATCH 178/418] hstore build fix --- core/DB/PgSQL.class.php | 2 +- core/OSQL/DataType.class.php | 2 ++ meta/types/HstoreType.class.php | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/DB/PgSQL.class.php b/core/DB/PgSQL.class.php index 071cf973cc..4adb416f68 100755 --- a/core/DB/PgSQL.class.php +++ b/core/DB/PgSQL.class.php @@ -236,12 +236,12 @@ public function getTableInfo($table) 'ip4r' => DataType::IP_RANGE, 'uuid' => DataType::UUID, + 'hstore' => DataType::HSTORE, // unhandled types, not ours anyway 'tsvector' => null, 'ltree' => null, - 'hstore' => null, ); try { diff --git a/core/OSQL/DataType.class.php b/core/OSQL/DataType.class.php index 6f7bd72739..078da17ca0 100755 --- a/core/OSQL/DataType.class.php +++ b/core/OSQL/DataType.class.php @@ -41,6 +41,7 @@ final class DataType extends Enumeration implements DialectString const IP_RANGE = 0x000011; const UUID = 0x000005; + const HSTORE = 0x000020; const HAVE_SIZE = 0x000100; const HAVE_PRECISION = 0x000200; @@ -68,6 +69,7 @@ final class DataType extends Enumeration implements DialectString self::BOOLEAN => 'BOOLEAN', self::UUID => 'UUID', + self::HSTORE => 'HSTORE', self::CHAR => 'CHARACTER', self::VARCHAR => 'CHARACTER VARYING', diff --git a/meta/types/HstoreType.class.php b/meta/types/HstoreType.class.php index 1fec26f43b..bd9b546abf 100755 --- a/meta/types/HstoreType.class.php +++ b/meta/types/HstoreType.class.php @@ -40,7 +40,7 @@ public function getDeclaration() public function toColumnType() { - return 'DataType::create(DataType::TEXT)'; + return 'DataType::create(DataType::HSTORE)'; } } ?> \ No newline at end of file From 436974aa5f4505d7225ab7bb0a2c9ff964c2e8ed Mon Sep 17 00:00:00 2001 From: klkvsk Date: Tue, 2 Apr 2013 12:32:53 +0400 Subject: [PATCH 179/418] mongo count - check returned value --- core/NoSQL/MongoBase.class.php | 20 ++++++++++++++++++-- core/NoSQL/NoSqlResult.class.php | 5 ++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/core/NoSQL/MongoBase.class.php b/core/NoSQL/MongoBase.class.php index 0be0e6e524..83350b55b8 100755 --- a/core/NoSQL/MongoBase.class.php +++ b/core/NoSQL/MongoBase.class.php @@ -454,8 +454,24 @@ protected function mongoFind($table, array $query, array $fields=array(), array protected function mongoCount($table, array $query, array $fields=array(), array $order=null, $limit=null, $skip=null) { // quering $cursor = $this->mongoMakeCursor($table, $query, $fields, $order, $limit, $skip); - // return result - return $cursor->count(); + // fetch result + $count = $cursor->count(); + // check result + self::assertCountResult($count); + // return count + return $count; + } + + public static function assertCountResult($count) { + if (!Assert::checkInteger($count) || $count < 0) { + if (is_array($count)) { + $code = isset($count['code']) ? $count['code'] : null; + $text = isset($count['errmsg']) ? $count['errmsg'] : json_encode($count); + throw new MongoCursorException($text, $code); + } else { + throw new UnexpectedValueException($count); + } + } } protected function mongoDelete($table, array $query, array $options) { diff --git a/core/NoSQL/NoSqlResult.class.php b/core/NoSQL/NoSqlResult.class.php index a94ae5e5d1..24f4129af6 100644 --- a/core/NoSQL/NoSqlResult.class.php +++ b/core/NoSQL/NoSqlResult.class.php @@ -40,7 +40,10 @@ public function getCriteria() { public function getCount() { if ($this->count == null && $this->getMongoCursor()) { - $this->count = $this->getMongoCursor()->count(); + $count = $this->getMongoCursor()->count(); + MongoBase::assertCountResult($count); + + $this->count = $count; /* -- плохой вариант, долго считает // пытаемся посчитать количество записей перебором, без использования count() From a86de6c9299d0a10d7870f1a53284468ac390685 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Fri, 5 Apr 2013 15:51:52 +0400 Subject: [PATCH 180/418] build.php -- support more colour-capable $TERM-s --- meta/bin/build.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/meta/bin/build.php b/meta/bin/build.php index f6d5490010..b179aeff23 100755 --- a/meta/bin/build.php +++ b/meta/bin/build.php @@ -211,10 +211,9 @@ function stop($message = null) if ( isset($_SERVER['TERM']) - && ( - $_SERVER['TERM'] == 'xterm' - || $_SERVER['TERM'] == 'linux' - ) + && in_array($_SERVER['TERM'], array( + 'xterm', 'linux', 'screen', 'screen-256color' + )) && !$metaNoColor ) { $out = new ColoredTextOutput(); From 6a5a67c97e320b6598ba32916436c0278c2aad10 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Wed, 10 Apr 2013 16:23:46 +0400 Subject: [PATCH 181/418] main/Net/Mail/MimePart -- include sub-parts --- main/Net/Mail/MimePart.class.php | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/main/Net/Mail/MimePart.class.php b/main/Net/Mail/MimePart.class.php index f0e808b0c2..3f40df7ce4 100755 --- a/main/Net/Mail/MimePart.class.php +++ b/main/Net/Mail/MimePart.class.php @@ -254,14 +254,31 @@ public function getEncodedBody() default: throw new WrongStateException('unknown mail encoding given'); } - + + if (!$this->boundary) { + throw new UnexpectedValueException('set boundary or call getHeader() first'); + } + + foreach ($this->parts as $part) { + /** @var $part MimePart */ + $body .= + '--' . $this->boundary . "\n" + . $part->getHeaders() . "\n\n" + . $part->getEncodedBody() . "\n\n" + ; + } + return $body; } - + public function getHeaders() { $headers = array(); - + + if ($this->parts && !$this->boundary) { + $this->boundary = '=_'.md5(microtime(true)); + } + if ($this->contentType) { $header = "Content-Type: {$this->contentType};"; From a40c065f49963cbf46133b0aca58e18be7fffe9b Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Wed, 10 Apr 2013 16:39:11 +0400 Subject: [PATCH 182/418] ArrayOfStrings --- core/DB/Dialect.class.php | 5 ++ core/DB/PgSQL.class.php | 2 + core/DB/PostgresDialect.class.php | 9 +++ core/Logic/ArrayExpression.class.php | 80 +++++++++++++++++++++++++ core/OSQL/DataType.class.php | 15 ++++- core/OSQL/InsertQuery.class.php | 4 +- core/OSQL/UpdateQuery.class.php | 3 + main/Base/LightMetaProperty.class.php | 14 +++++ main/UI/Widget/DataGrid.class.php | 8 +-- meta/types/ArrayOfStringsType.class.php | 14 +++++ 10 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 core/Logic/ArrayExpression.class.php create mode 100644 meta/types/ArrayOfStringsType.class.php diff --git a/core/DB/Dialect.class.php b/core/DB/Dialect.class.php index e0a29dc310..b85f38bf88 100755 --- a/core/DB/Dialect.class.php +++ b/core/DB/Dialect.class.php @@ -162,5 +162,10 @@ public function quoteIpInRange($range, $ip) { throw new UnimplementedFeatureException(); } + + public function arrayToString($values) + { + throw new UnimplementedFeatureException(); + } } ?> \ No newline at end of file diff --git a/core/DB/PgSQL.class.php b/core/DB/PgSQL.class.php index 4adb416f68..3d0eaffc65 100755 --- a/core/DB/PgSQL.class.php +++ b/core/DB/PgSQL.class.php @@ -238,6 +238,8 @@ public function getTableInfo($table) 'uuid' => DataType::UUID, 'hstore' => DataType::HSTORE, + '_varchar' => DataType::SET_OF_STRINGS, + // unhandled types, not ours anyway 'tsvector' => null, diff --git a/core/DB/PostgresDialect.class.php b/core/DB/PostgresDialect.class.php index e87cadda43..a8a39908eb 100755 --- a/core/DB/PostgresDialect.class.php +++ b/core/DB/PostgresDialect.class.php @@ -172,6 +172,15 @@ public function quoteIpInRange($range, $ip) return $string; } + public function arrayToString($values) + { + // add qoutes + foreach($values as &$item) { + $item = $this->quoteValue($item); + } + return 'ARRAY['.implode(', ',$values).']'; + } + protected function makeSequenceName(DBColumn $column) { return $column->getTable()->getName().'_'.$column->getName(); diff --git a/core/Logic/ArrayExpression.class.php b/core/Logic/ArrayExpression.class.php new file mode 100644 index 0000000000..e1f8d27e86 --- /dev/null +++ b/core/Logic/ArrayExpression.class.php @@ -0,0 +1,80 @@ + + * @date 2013.04.03 + */ +class ArrayExpression implements LogicalObject, MappableObject { + + const FIELD = null; + const ANY = 'ANY'; + const ALL = 'ALL'; + + protected + $subject = null, + $field = null, + $logic = null; + + protected function __construct($subject, $field, $logic) { + $this->subject = $subject; + $this->field = $field; + $this->logic = $logic; + } + + public static function field($subject, $field) + { + return new self($subject, $field, self::FIELD); + } + + public static function any($subject) + { + return new self($subject, null, self::ANY); + } + + public static function anyEq($field, $value) { + return Expression::eq(DBValue::create($value), self::any($field)); + } + + public static function all($subject) + { + return new self($subject, null, self::ALL); + } + + public static function allEq($subject, $value) { + return Expression::eq(DBValue::create($value), self::all($subject)); + } + + public function toDialectString(Dialect $dialect) + { + $tableField = $dialect->toFieldString($this->subject); + if( !is_null($this->field) ) { + $tableField .= "[{$this->field}]"; + } + + if( $this->logic === self::FIELD ) { + return $tableField; + } + + return + $dialect->logicToString($this->logic). + '(' + .$tableField + .')'; + } + + /** + * @return BinaryExpression + **/ + public function toMapped(ProtoDAO $dao, JoinCapableQuery $query) + { + return new self( + $dao->guessAtom($this->subject, $query), + $this->field, + $this->logic + ); + } + + public function toBoolean(Form $form) { + throw new UnsupportedMethodException('Method tpBoolean is not supported by ArrayExpression'); + } +} \ No newline at end of file diff --git a/core/OSQL/DataType.class.php b/core/OSQL/DataType.class.php index 078da17ca0..479714ea47 100755 --- a/core/OSQL/DataType.class.php +++ b/core/OSQL/DataType.class.php @@ -43,11 +43,14 @@ final class DataType extends Enumeration implements DialectString const UUID = 0x000005; const HSTORE = 0x000020; + const SET_OF_STRINGS = 0x010121; + const HAVE_SIZE = 0x000100; const HAVE_PRECISION = 0x000200; const HAVE_SCALE = 0x000400; const HAVE_TIMEZONE = 0x000800; const CAN_BE_UNSIGNED = 0x001000; + const ARRAY_COLUMN = 0x010000; private $size = null; private $precision = null; @@ -83,7 +86,9 @@ final class DataType extends Enumeration implements DialectString self::BINARY => 'BINARY', self::IP => 'IP', - self::IP_RANGE => 'IP_RANGE' + self::IP_RANGE => 'IP_RANGE', + + self::SET_OF_STRINGS => 'CHARACTER VARYING', ); /** @@ -217,6 +222,11 @@ public function isUnsigned() return $this->unsigned; } + public function isArrayColumn() + { + return (bool) ($this->id & self::ARRAY_COLUMN); + } + public function toDialectString(Dialect $dialect) { $out = $dialect->typeToString($this); @@ -257,6 +267,9 @@ public function toDialectString(Dialect $dialect) $out .= "({$this->size})"; } + if ($this->isArrayColumn()) { + $out .= "[]"; + } if ($this->id & self::HAVE_TIMEZONE) $out .= $dialect->timeZone($this->timezone); diff --git a/core/OSQL/InsertQuery.class.php b/core/OSQL/InsertQuery.class.php index e37b2ba217..2ce942f26d 100755 --- a/core/OSQL/InsertQuery.class.php +++ b/core/OSQL/InsertQuery.class.php @@ -83,7 +83,7 @@ protected function toDialectStringValues($query, Dialect $dialect) { $fields = array(); $values = array(); - + foreach ($this->fields as $var => $val) { $fields[] = $dialect->quoteField($var); @@ -95,6 +95,8 @@ protected function toDialectStringValues($query, Dialect $dialect) $values[] = $dialect->literalToString(Dialect::LITERAL_FALSE); elseif ($val instanceof DialectString) $values[] = $val->toDialectString($dialect); + elseif (is_array($val)) + $values[] = $dialect->arrayToString($val); else $values[] = $dialect->quoteValue($val); } diff --git a/core/OSQL/UpdateQuery.class.php b/core/OSQL/UpdateQuery.class.php index 4dd2f1ac62..f54788e822 100755 --- a/core/OSQL/UpdateQuery.class.php +++ b/core/OSQL/UpdateQuery.class.php @@ -103,6 +103,9 @@ public function toDialectString(Dialect $dialect) elseif (false === $val) $sets[] = $dialect->quoteField($var).' = ' .$dialect->literalToString(Dialect::LITERAL_FALSE); + elseif (is_array($val)) + $sets[] = $dialect->quoteField($var).' = ' + .$dialect->arrayToString($val); else $sets[] = $dialect->quoteField($var) diff --git a/main/Base/LightMetaProperty.class.php b/main/Base/LightMetaProperty.class.php index 9e1784f93c..29cfb029c8 100755 --- a/main/Base/LightMetaProperty.class.php +++ b/main/Base/LightMetaProperty.class.php @@ -404,6 +404,20 @@ public function toValue(ProtoDAO $dao = null, $array, $prefix = null) return HttpUrl::create()->parse($raw); } + if ($this->type == 'set') { + // MongoDB driver compatibility + if( is_array($raw) ) { + return $raw; + } + // PgSQL driver compatibility + $matches = array(); + if( preg_match('/^{(.*)}$/', $raw, $matches) ) { + return str_getcsv($matches[1]); + } + // empty array + return array(); + } + if ( !$this->identifier && $this->generic diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index 8cf293d2df..c865e5e8d2 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -930,9 +930,9 @@ protected function makeModel() { if ($value instanceof Closure) { $value = $value($object); } - if ('class' == $key) { - $value = ($rowId % 2 ? 'odd ' : 'even ') . $value; - } +// if ('class' == $key) { +// $value = ($rowId % 2 ? 'odd ' : 'even ') . $value; +// } array_push($attrs, $key . '="' . $value . '"'); } $data[$rowId]['attrs'] = implode(' ', $attrs); @@ -951,7 +951,7 @@ protected function makeModel() { // отрендерим аттрибуты формы $selfUrl = null; try { - $controller = Application::me()->getRunningController(); + $controller = Application::me()->getRunningActionController(); $selfUrl = $controller->getSelfUrl()->__toString(); } catch (UnexpectedValueException $e) { $selfUrl = $_SERVER['REQUEST_URI']; diff --git a/meta/types/ArrayOfStringsType.class.php b/meta/types/ArrayOfStringsType.class.php new file mode 100644 index 0000000000..b7d8f74185 --- /dev/null +++ b/meta/types/ArrayOfStringsType.class.php @@ -0,0 +1,14 @@ + + * @date 2013.04.02 + */ + +class ArrayOfStringsType extends ArrayType { + + public function toColumnType() { + return 'DataType::create(DataType::SET_OF_STRINGS)'; + } + +} \ No newline at end of file From 568bb42385e269a6beff2e1be6d55713dc1e9482 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Wed, 10 Apr 2013 16:23:46 +0400 Subject: [PATCH 183/418] main/Net/Mail/MimePart -- include sub-parts --- main/Net/Mail/MimePart.class.php | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/main/Net/Mail/MimePart.class.php b/main/Net/Mail/MimePart.class.php index f0e808b0c2..e8b9110b51 100755 --- a/main/Net/Mail/MimePart.class.php +++ b/main/Net/Mail/MimePart.class.php @@ -254,14 +254,31 @@ public function getEncodedBody() default: throw new WrongStateException('unknown mail encoding given'); } - + + if ($this->parts && !$this->boundary) { + throw new UnexpectedValueException('set boundary or call getHeader() first'); + } + + foreach ($this->parts as $part) { + /** @var $part MimePart */ + $body .= + '--' . $this->boundary . "\n" + . $part->getHeaders() . "\n\n" + . $part->getEncodedBody() . "\n\n" + ; + } + return $body; } - + public function getHeaders() { $headers = array(); - + + if ($this->parts && !$this->boundary) { + $this->boundary = '=_'.md5(microtime(true)); + } + if ($this->contentType) { $header = "Content-Type: {$this->contentType};"; From 1a52e6db501b461b6ed7e256c8d36c8042d9bd63 Mon Sep 17 00:00:00 2001 From: ilya_shvedov Date: Thu, 11 Apr 2013 18:36:41 +0400 Subject: [PATCH 184/418] mail boundary fix --- main/Net/Mail/MimeMail.class.php | 4 ++-- main/Net/Mail/MimePart.class.php | 32 ++++++++++++++++++-------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/main/Net/Mail/MimeMail.class.php b/main/Net/Mail/MimeMail.class.php index 95834042da..e034bde37b 100755 --- a/main/Net/Mail/MimeMail.class.php +++ b/main/Net/Mail/MimeMail.class.php @@ -42,7 +42,7 @@ public function build() throw new UnimplementedFeatureException(); if (!$this->boundary) - $this->boundary = '=_'.md5(microtime(true)); + $this->boundary = '=_'.md5(microtime(true) . uniqid()); $mail = MimePart::create()-> @@ -59,7 +59,7 @@ public function build() .$part->getHeaders() ."\n\n" .$part->getEncodedBody()."\n"; - + $this->body .= '--'.$this->boundary."--"."\n\n"; } diff --git a/main/Net/Mail/MimePart.class.php b/main/Net/Mail/MimePart.class.php index e8b9110b51..3e7373ab40 100755 --- a/main/Net/Mail/MimePart.class.php +++ b/main/Net/Mail/MimePart.class.php @@ -19,7 +19,7 @@ final class MimePart implements MailBuilder private $contentId = null; private $contentType = null; private $boundary = null; - + private $encoding = null; private $charset = null; @@ -63,7 +63,7 @@ public function getBoundary() { return $this->boundary; } - + public function getContentId() { return $this->contentId; @@ -255,17 +255,21 @@ public function getEncodedBody() throw new WrongStateException('unknown mail encoding given'); } - if ($this->parts && !$this->boundary) { - throw new UnexpectedValueException('set boundary or call getHeader() first'); - } + if ($this->parts) { + if (!$this->boundary) { + throw new UnexpectedValueException('set boundary or call getHeader() first'); + } + + foreach ($this->parts as $part) { + /** @var $part MimePart */ + $body .= + '--' . $this->boundary . "\n" + . $part->getHeaders() . "\n\n" + . $part->getEncodedBody() . "\n\n" + ; + } - foreach ($this->parts as $part) { - /** @var $part MimePart */ - $body .= - '--' . $this->boundary . "\n" - . $part->getHeaders() . "\n\n" - . $part->getEncodedBody() . "\n\n" - ; + $this->body .= '--'.$this->boundary."--"."\n"; } return $body; @@ -276,7 +280,7 @@ public function getHeaders() $headers = array(); if ($this->parts && !$this->boundary) { - $this->boundary = '=_'.md5(microtime(true)); + $this->boundary = '=_'.md5(microtime(true) . uniqid()); } if ($this->contentType) { @@ -288,7 +292,7 @@ public function getHeaders() if ($this->boundary) $header .= "\n\tboundary=\"{$this->boundary}\""; - + $headers[] = $header; } From afab099047b9f8c03d4345a1b73729b256c57afe Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 11 Apr 2013 20:13:29 +0400 Subject: [PATCH 185/418] prototyped utils addons --- main/Utils/PrototypeUtils.class.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/main/Utils/PrototypeUtils.class.php b/main/Utils/PrototypeUtils.class.php index 08efb76ab7..9d04f90741 100755 --- a/main/Utils/PrototypeUtils.class.php +++ b/main/Utils/PrototypeUtils.class.php @@ -89,6 +89,28 @@ public static function getProperty(AbstractProtoClass $proto, $path) { return $property; } + public static function propertyExists(AbstractProtoClass $proto, $path) { + $result = true; + $subProto = $proto; + foreach (explode('.', $path) as $propertyName) { + /** @var $property LightMetaProperty */ + try { + $property = $subProto->getPropertyByName($propertyName); + } catch(Exception $e) { + $result = false; + break; + } + $class = $property->getClassName(); + if (strlen($class) && is_subclass_of($class, 'Prototyped')) { + $subProto = $class::proto(); + } else { + $result = false; + break; + } + } + return $result; + } + /** * @static * @param Prototyped $object From 10d026965edb321d2f8242171d5b62956394bb85 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 12 Apr 2013 12:21:12 +0400 Subject: [PATCH 186/418] array of integers --- core/DB/PgSQL.class.php | 1 + core/OSQL/DataType.class.php | 2 ++ meta/types/ArrayOfIntegersType.class.php | 14 ++++++++++++++ 3 files changed, 17 insertions(+) create mode 100644 meta/types/ArrayOfIntegersType.class.php diff --git a/core/DB/PgSQL.class.php b/core/DB/PgSQL.class.php index 3d0eaffc65..c2b4b559d2 100755 --- a/core/DB/PgSQL.class.php +++ b/core/DB/PgSQL.class.php @@ -239,6 +239,7 @@ public function getTableInfo($table) 'hstore' => DataType::HSTORE, '_varchar' => DataType::SET_OF_STRINGS, + '_int4' => DataType::SET_OF_INTEGERS, // unhandled types, not ours anyway 'tsvector' => null, diff --git a/core/OSQL/DataType.class.php b/core/OSQL/DataType.class.php index 479714ea47..a3eb03dd49 100755 --- a/core/OSQL/DataType.class.php +++ b/core/OSQL/DataType.class.php @@ -44,6 +44,7 @@ final class DataType extends Enumeration implements DialectString const HSTORE = 0x000020; const SET_OF_STRINGS = 0x010121; + const SET_OF_INTEGERS = 0x010022; const HAVE_SIZE = 0x000100; const HAVE_PRECISION = 0x000200; @@ -89,6 +90,7 @@ final class DataType extends Enumeration implements DialectString self::IP_RANGE => 'IP_RANGE', self::SET_OF_STRINGS => 'CHARACTER VARYING', + self::SET_OF_INTEGERS => 'INTEGER', ); /** diff --git a/meta/types/ArrayOfIntegersType.class.php b/meta/types/ArrayOfIntegersType.class.php new file mode 100644 index 0000000000..1c91c953e7 --- /dev/null +++ b/meta/types/ArrayOfIntegersType.class.php @@ -0,0 +1,14 @@ + + * @date 2013.04.02 + */ + +class ArrayOfIntegersType extends ArrayType { + + public function toColumnType() { + return 'DataType::create(DataType::SET_OF_INTEGERS)'; + } + +} \ No newline at end of file From 58654bd06c25a5c1b0179ab6451849af42a07e40 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 12 Apr 2013 16:32:12 +0400 Subject: [PATCH 187/418] pg dialect for array fix --- core/DB/PostgresDialect.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/DB/PostgresDialect.class.php b/core/DB/PostgresDialect.class.php index a8a39908eb..cc727efb4f 100755 --- a/core/DB/PostgresDialect.class.php +++ b/core/DB/PostgresDialect.class.php @@ -176,7 +176,7 @@ public function arrayToString($values) { // add qoutes foreach($values as &$item) { - $item = $this->quoteValue($item); + $item = is_numeric($item) ? $item : $this->quoteValue($item); } return 'ARRAY['.implode(', ',$values).']'; } From 2804ce856e5cf61923adeef7a1910cb1f0305416 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Mon, 15 Apr 2013 13:22:50 +0400 Subject: [PATCH 188/418] array type implemention v2.0 --- core/DB/Dialect.class.php | 2 +- core/DB/PostgresDialect.class.php | 10 ++++-- core/Form/Primitive.class.php | 16 +++++++++ core/OSQL/DBArray.class.php | 42 ++++++++++++++++++++++++ core/OSQL/InsertQuery.class.php | 3 -- core/OSQL/UpdateQuery.class.php | 3 -- main/Base/LightMetaProperty.class.php | 27 ++++++++++++--- meta/types/ArrayOfIntegersType.class.php | 4 +++ meta/types/ArrayOfStringsType.class.php | 4 +++ 9 files changed, 98 insertions(+), 13 deletions(-) create mode 100644 core/OSQL/DBArray.class.php diff --git a/core/DB/Dialect.class.php b/core/DB/Dialect.class.php index b85f38bf88..e2b6851128 100755 --- a/core/DB/Dialect.class.php +++ b/core/DB/Dialect.class.php @@ -163,7 +163,7 @@ public function quoteIpInRange($range, $ip) throw new UnimplementedFeatureException(); } - public function arrayToString($values) + public function quoteArray($values, $type) { throw new UnimplementedFeatureException(); } diff --git a/core/DB/PostgresDialect.class.php b/core/DB/PostgresDialect.class.php index cc727efb4f..337b0392b7 100755 --- a/core/DB/PostgresDialect.class.php +++ b/core/DB/PostgresDialect.class.php @@ -172,11 +172,17 @@ public function quoteIpInRange($range, $ip) return $string; } - public function arrayToString($values) + public function quoteArray($values, $type) { // add qoutes foreach($values as &$item) { - $item = is_numeric($item) ? $item : $this->quoteValue($item); + if( $type===DataType::INTEGER ) { + $item = intval($item); + } elseif( $type===DataType::VARCHAR ) { + $item = $this->quoteValue($item); + } else { + throw new WrongArgumentException('unknown type of array!'); + } } return 'ARRAY['.implode(', ',$values).']'; } diff --git a/core/Form/Primitive.class.php b/core/Form/Primitive.class.php index 80526283b9..17d5e1ec47 100755 --- a/core/Form/Primitive.class.php +++ b/core/Form/Primitive.class.php @@ -211,6 +211,22 @@ public static function set($name) return new PrimitiveArray($name); } + /** + * @return PrimitiveArray + **/ + public static function arrayOfStrings($name) + { + return new PrimitiveArray($name); + } + + /** + * @return PrimitiveArray + **/ + public static function arrayOfIntegers($name) + { + return new PrimitiveArray($name); + } + /** * @return PrimitiveHstore **/ diff --git a/core/OSQL/DBArray.class.php b/core/OSQL/DBArray.class.php new file mode 100644 index 0000000000..b356639cad --- /dev/null +++ b/core/OSQL/DBArray.class.php @@ -0,0 +1,42 @@ + + * @date 2013.04.15 + */ + + /** + * Container for passing array values into OSQL queries. + * + * @ingroup OSQL + * @ingroup Module + **/ + class DBArray extends DBValue { + + protected $type = null; + + /** + * @param int $value + * @return DBArray + */ + public static function create($value) + { + return new self($value); + } + + public function integers() { + $this->type = DataType::INTEGER; + return $this; + } + + public function strings() { + $this->type = DataType::VARCHAR; + return $this; + } + + public function toDialectString(Dialect $dialect) + { + return $dialect->quoteArray($this->getValue(), $this->type); + } + + } \ No newline at end of file diff --git a/core/OSQL/InsertQuery.class.php b/core/OSQL/InsertQuery.class.php index 2ce942f26d..537b85848f 100755 --- a/core/OSQL/InsertQuery.class.php +++ b/core/OSQL/InsertQuery.class.php @@ -60,7 +60,6 @@ public function toDialectString(Dialect $dialect) } $query .= parent::toDialectString($dialect); - return $query; } @@ -95,8 +94,6 @@ protected function toDialectStringValues($query, Dialect $dialect) $values[] = $dialect->literalToString(Dialect::LITERAL_FALSE); elseif ($val instanceof DialectString) $values[] = $val->toDialectString($dialect); - elseif (is_array($val)) - $values[] = $dialect->arrayToString($val); else $values[] = $dialect->quoteValue($val); } diff --git a/core/OSQL/UpdateQuery.class.php b/core/OSQL/UpdateQuery.class.php index f54788e822..4dd2f1ac62 100755 --- a/core/OSQL/UpdateQuery.class.php +++ b/core/OSQL/UpdateQuery.class.php @@ -103,9 +103,6 @@ public function toDialectString(Dialect $dialect) elseif (false === $val) $sets[] = $dialect->quoteField($var).' = ' .$dialect->literalToString(Dialect::LITERAL_FALSE); - elseif (is_array($val)) - $sets[] = $dialect->quoteField($var).' = ' - .$dialect->arrayToString($val); else $sets[] = $dialect->quoteField($var) diff --git a/main/Base/LightMetaProperty.class.php b/main/Base/LightMetaProperty.class.php index 29cfb029c8..51b8ccf744 100755 --- a/main/Base/LightMetaProperty.class.php +++ b/main/Base/LightMetaProperty.class.php @@ -384,6 +384,10 @@ public function fillQuery( if ($this->type == 'binary') { $query->set($this->columnName, new DBBinary($value)); + } elseif($this->type == 'arrayOfIntegers') { + $query->set($this->columnName, DBArray::create($value)->integers()); + } elseif($this->type == 'arrayOfStrings') { + $query->set($this->columnName, DBArray::create($value)->strings()); } else { $query->lazySet($this->columnName, $value); } @@ -404,18 +408,33 @@ public function toValue(ProtoDAO $dao = null, $array, $prefix = null) return HttpUrl::create()->parse($raw); } - if ($this->type == 'set') { + if($this->type == 'set') { // MongoDB driver compatibility if( is_array($raw) ) { return $raw; + } else { + throw new WrongArgumentException('raw data is not array!'); } + } + + if( $this->type == 'arrayOfIntegers' ) { // PgSQL driver compatibility $matches = array(); if( preg_match('/^{(.*)}$/', $raw, $matches) ) { - return str_getcsv($matches[1]); + return array_map('intval', str_getcsv($matches[1])); + } else { + throw new WrongArgumentException('raw data is not compatible with PgArray!'); + } + } + + if ( $this->type == 'arrayOfStrings') { + // PgSQL driver compatibility + $matches = array(); + if( preg_match('/^{(.*)}$/', $raw, $matches) ) { + return array_map('strval', str_getcsv($matches[1])); + } else { + throw new WrongArgumentException('raw data is not compatible with PgArray!'); } - // empty array - return array(); } if ( diff --git a/meta/types/ArrayOfIntegersType.class.php b/meta/types/ArrayOfIntegersType.class.php index 1c91c953e7..c20f9f6ffc 100644 --- a/meta/types/ArrayOfIntegersType.class.php +++ b/meta/types/ArrayOfIntegersType.class.php @@ -7,6 +7,10 @@ class ArrayOfIntegersType extends ArrayType { + public function getPrimitiveName() { + return 'arrayOfIntegers'; + } + public function toColumnType() { return 'DataType::create(DataType::SET_OF_INTEGERS)'; } diff --git a/meta/types/ArrayOfStringsType.class.php b/meta/types/ArrayOfStringsType.class.php index b7d8f74185..a757a96f99 100644 --- a/meta/types/ArrayOfStringsType.class.php +++ b/meta/types/ArrayOfStringsType.class.php @@ -7,6 +7,10 @@ class ArrayOfStringsType extends ArrayType { + public function getPrimitiveName() { + return 'arrayOfStrings'; + } + public function toColumnType() { return 'DataType::create(DataType::SET_OF_STRINGS)'; } From c99e1af8f1a880e2208655cc08149d11042b2949 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Tue, 16 Apr 2013 11:48:48 +0400 Subject: [PATCH 189/418] postgres array fix --- core/DB/PostgresDialect.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/DB/PostgresDialect.class.php b/core/DB/PostgresDialect.class.php index 337b0392b7..f236b2d65c 100755 --- a/core/DB/PostgresDialect.class.php +++ b/core/DB/PostgresDialect.class.php @@ -174,6 +174,9 @@ public function quoteIpInRange($range, $ip) public function quoteArray($values, $type) { + if( empty($values) ) { + return self::LITERAL_NULL; + } // add qoutes foreach($values as &$item) { if( $type===DataType::INTEGER ) { From 800ecd74717245d21cf3ddd3e9e2147b0f0a1cca Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Thu, 25 Apr 2013 13:35:11 +0400 Subject: [PATCH 190/418] Redis select db --- core/NoSQL/RedisNoSQL.class.php | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/core/NoSQL/RedisNoSQL.class.php b/core/NoSQL/RedisNoSQL.class.php index 43188938c1..423400aef0 100644 --- a/core/NoSQL/RedisNoSQL.class.php +++ b/core/NoSQL/RedisNoSQL.class.php @@ -30,10 +30,13 @@ final class RedisNoSQL extends CachePeer implements ListGenerator public static function create( $host = self::DEFAULT_HOST, $port = self::DEFAULT_PORT, - $timeout = self::DEFAULT_TIMEOUT + $timeout = self::DEFAULT_TIMEOUT, + $db = 0 ) { - return new self($host, $port, $timeout); + $instance = new self($host, $port, $timeout); + $instance->select($db); + return $instance; } public function __construct( @@ -177,6 +180,19 @@ public function info() { return $this->redis->info(); } + public function select($db) { + $this->ensureTriedToConnect(); + + if( is_null($db) || !Assert::checkInteger($db) ) { + throw new WrongArgumentException('DB id should be an integer'); + } + $result = $this->redis->select($db); + if( !$result ) { + throw new WrongStateException('could not change db'); + } + return $result; + } + protected function store($action, $key, $value, $expires = Cache::EXPIRES_MEDIUM) { $this->ensureTriedToConnect(); From 80dcb39a50b4a4d8695eafcd07a224d1365e3d1e Mon Sep 17 00:00:00 2001 From: klkvsk Date: Thu, 25 Apr 2013 15:45:58 +0400 Subject: [PATCH 191/418] PrototypeUtils::toArray - support for hstore --- main/Utils/PrototypeUtils.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main/Utils/PrototypeUtils.class.php b/main/Utils/PrototypeUtils.class.php index 9d04f90741..8f8b2c08d9 100755 --- a/main/Utils/PrototypeUtils.class.php +++ b/main/Utils/PrototypeUtils.class.php @@ -235,6 +235,9 @@ public static function toArray(Prototyped $object) { $value = null; } $entity[ $property->getColumnName() ] = $value; + } elseif ($property->getType() == 'hstore') { + /** @var $value Hstore */ + $entity[ $property->getColumnName() ] = $value->getList(); } else { $entity[ $property->getColumnName() ] = $value; } From ac758df57f8eba74a7c41d234974a6a73b2cc241 Mon Sep 17 00:00:00 2001 From: Alexey Gorbylev Date: Fri, 26 Apr 2013 12:06:17 +0400 Subject: [PATCH 192/418] db cursor --- main/Criteria/Criteria.class.php | 7 ++ main/Criteria/Cursor.class.php | 195 +++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 main/Criteria/Cursor.class.php diff --git a/main/Criteria/Criteria.class.php b/main/Criteria/Criteria.class.php index 4bd4e8bc57..16c2831533 100755 --- a/main/Criteria/Criteria.class.php +++ b/main/Criteria/Criteria.class.php @@ -472,6 +472,13 @@ public function getCustomList() } } + /** + * @return Cursor + */ + public function getCursor() { + return Cursor::create($this->getDao(), $this->toSelectQuery()); + } + public function getPropertyList() { try { diff --git a/main/Criteria/Cursor.class.php b/main/Criteria/Cursor.class.php new file mode 100644 index 0000000000..ff53d05dd4 --- /dev/null +++ b/main/Criteria/Cursor.class.php @@ -0,0 +1,195 @@ + + * @date 2013.04.25 + */ +final class Cursor implements Iterator { + + /** @var ProtoDAO */ + protected $dao = null; + + /** @var SelectQuery */ + protected $selectQuery = null; + + /** @var DB */ + protected $db = null; + + /** @var string */ + protected $cursorName = null; + + /** @var array */ + protected $buffer = array(); + + /** @var int */ + protected $batchSize = 250; + + /** @var bool */ + protected $iterateObjects = null; + + /** @var int */ + protected $iteratorPosition = 0; + + /** @var mixed */ + protected $iteratorCurrent = null; + + public static function create(ProtoDAO $dao, SelectQuery $query = null) { + return new self($dao, $query); + } + + public function __construct(ProtoDAO $dao, SelectQuery $query = null) { + if ($query) + Assert::isTrue($query instanceof SelectQuery); + + $this->dao = $dao; + $this->db = DBPool::getByDao($this->dao); + $this->selectQuery = $query; + + $this->db->begin(); + $this->declareCursor(); + $this->openCursor(); + } + + function __destruct() { + if( $this->db->inTransaction() && is_resource($this->db->getLink()) ) { + $this->closeCursor(); + $this->db->commit(); + } + } + + public function __clone() + { + $this->dao = clone $this->dao; + $this->selectQuery = clone $this->selectQuery; + } + + /** + * @return Cursor + */ + public function asObjects() { + $this->iterateObjects = true; + return $this; + } + + /** + * @return Cursor + */ + public function asRows() { + $this->iterateObjects = false; + return $this; + } + + public function setBatchSize($size) { + if( Assert::checkInteger($size) && $size>0 ) { + $this->batchSize = $size; + } + return $this; + } + + /** + * @param bool $strict + * @throws ObjectNotFoundException + * @return Prototyped|bool + */ + public function getNext($strict=false) { + $row = $this->fetchRow(); + if( !$row ) { + if( $strict ) { + throw new ObjectNotFoundException(); + } + return false; + } + return $this->dao->getProtoClass()->makeOnlyObject($this->dao->getObjectName(), $row); + } + + /** + * @param bool $strict + * @throws ObjectNotFoundException + * @return array|bool + */ + public function getNextRow($strict=false) { + $row = $this->fetchRow(); + if( !$row ) { + if( $strict ) { + throw new ObjectNotFoundException(); + } + return false; + } + return $row; + } + + public function current() { + return $this->iteratorCurrent; + } + + public function key() { + return $this->iteratorPosition; + } + + public function next() { + $this->iteratorPosition++; + } + + public function valid() { + $this->iteratorCurrent = $this->iterateObjects ? $this->getNext() : $this->getNextRow(); + return $this->iteratorCurrent===false ? false : true; + } + + public function rewind() { + if( is_null($this->iterateObjects) ) { + throw new WrongStateException('Type of iterating objects is not defined, use asObjects() or asRows()'); + } + $this->iteratorPosition = 0; + } + + + /** + * @return SelectQuery + */ + protected function getSelectQuery() { + if( is_null($this->selectQuery) ) { + $this->selectQuery = $this->dao->makeSelectHead(); + } + return $this->selectQuery; + + } + + /** + * @return string + */ + protected function getCursorName() { + if( is_null($this->cursorName) ) { + $this->cursorName = 'cursor_'.dechex(crc32(time().$this->dao->getTable())); + } + return $this->cursorName; + } + + protected function declareCursor() { + $queryDeclare = 'DECLARE '.$this->getCursorName().' CURSOR FOR '.$this->getSelectQuery()->toDialectString($this->db->getDialect()); + $this->db->queryRaw($queryDeclare); + } + + protected function openCursor() { +// $queryOpen = 'OPEN '.$this->getCursorName(); +// $this->db->queryRaw($queryOpen); + } + + protected function fetchRow() { + if( empty($this->buffer) ) { + $resource = $this->db->queryRaw('FETCH FORWARD 250 FROM '.$this->getCursorName()); + $this->buffer = pg_fetch_all($resource); + } + if( !$this->buffer ) { + return false; + } + return array_shift($this->buffer); + } + + protected function closeCursor() { + $queryOpen = 'CLOSE '.$this->getCursorName(); + $this->db->queryRaw($queryOpen); + } + + final private function __sleep() {/* restless class */} + final private function __wakeup() {/* restless class */} +} \ No newline at end of file From ba28c936ac9504c72b0990bb12bc06be0308aee9 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Wed, 15 May 2013 15:20:48 +0400 Subject: [PATCH 193/418] new pattern - ObjectWithEmptyDAOClass --- main/DAOs/EmptyDAO.class.php | 18 +++++++ main/Utils/PrototypeUtils.class.php | 4 +- meta/builders/AutoEmptyDaoBuilder.class.php | 38 +++++++++++++ meta/classes/MetaConfiguration.class.php | 5 ++ meta/dtd/meta.dtd | 1 + .../ObjectWithEmptyDAOClassPattern.class.php | 53 +++++++++++++++++++ 6 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 main/DAOs/EmptyDAO.class.php create mode 100644 meta/builders/AutoEmptyDaoBuilder.class.php create mode 100644 meta/patterns/ObjectWithEmptyDAOClassPattern.class.php diff --git a/main/DAOs/EmptyDAO.class.php b/main/DAOs/EmptyDAO.class.php new file mode 100644 index 0000000000..7a420942aa --- /dev/null +++ b/main/DAOs/EmptyDAO.class.php @@ -0,0 +1,18 @@ + + * @date 2013.04.19 + */ + +abstract class EmptyDAO extends Singleton { + + public function getIdName() { + return 'id'; + } + + public function getById($id) { + throw new UnimplementedFeatureException; + } + +} \ No newline at end of file diff --git a/main/Utils/PrototypeUtils.class.php b/main/Utils/PrototypeUtils.class.php index 8f8b2c08d9..4fa822d70b 100755 --- a/main/Utils/PrototypeUtils.class.php +++ b/main/Utils/PrototypeUtils.class.php @@ -222,9 +222,9 @@ public static function toArray(Prototyped $object) { //$value = $value->toString(); } if( $property->getType() == 'integer' ) { - $entity[ $property->getColumnName() ] = (int)$value; + $entity[ $property->getColumnName() ] = ($value === null) ? null : (int)$value; } elseif( $property->getType() == 'float' ) { - $entity[ $property->getColumnName() ] = (float)$value; + $entity[ $property->getColumnName() ] = ($value === null) ? null : (float)$value; } elseif( $property->getType() == 'string' ) { $value = (string)$value; if ($property->getMax() > 0) { diff --git a/meta/builders/AutoEmptyDaoBuilder.class.php b/meta/builders/AutoEmptyDaoBuilder.class.php new file mode 100644 index 0000000000..b4ef0ba399 --- /dev/null +++ b/meta/builders/AutoEmptyDaoBuilder.class.php @@ -0,0 +1,38 @@ + + * @date 2013.04.19 + */ + +/** + * @ingroup Builders + */ +final class AutoEmptyDaoBuilder extends BaseBuilder { + + public static function build(MetaClass $class) + { + if ( + is_null( $class->getParent() ) + || + $class->getParent()->getPattern() instanceof InternalClassPattern + ) { + $parentName = 'EmptyDAO'; + } else { + $parentName = $class->getParent()->getName().'DAO'; + } + + $out = self::getHead(); + + $out .= <<getName()}DAO extends {$parentName} +{ + +EOT; + + $out .= self::buildPointers($class)."\n}\n"; + + return $out.self::getHeel(); + } + +} diff --git a/meta/classes/MetaConfiguration.class.php b/meta/classes/MetaConfiguration.class.php index 0f6bd73a76..9c75eba7d2 100755 --- a/meta/classes/MetaConfiguration.class.php +++ b/meta/classes/MetaConfiguration.class.php @@ -547,6 +547,11 @@ class_exists($class->getName(), true) $dao = $object->dao(); + if (!$dao instanceof GenericDAO) { + $out->info(', '); + continue; + } + Assert::isEqual( $dao->getIdName(), $class->getIdentifier()->getColumnName(), diff --git a/meta/dtd/meta.dtd b/meta/dtd/meta.dtd index 79666a3691..d16c1cd9de 100755 --- a/meta/dtd/meta.dtd +++ b/meta/dtd/meta.dtd @@ -52,6 +52,7 @@ |ValueObject |InternalClass |NosqlClass + |ObjectWithEmptyDAOClass ) #REQUIRED fetch (lazy|cascade) #IMPLIED > diff --git a/meta/patterns/ObjectWithEmptyDAOClassPattern.class.php b/meta/patterns/ObjectWithEmptyDAOClassPattern.class.php new file mode 100644 index 0000000000..d3896c304d --- /dev/null +++ b/meta/patterns/ObjectWithEmptyDAOClassPattern.class.php @@ -0,0 +1,53 @@ + + * @date 2013.04.19 + */ + +final class ObjectWithEmptyDAOClassPattern extends BasePattern { + + public function tableExists() + { + return false; + } + + public function daoExists() + { + return true; + } + + /** + * @param $class MetaClass + * @return self + **/ + protected function fullBuild(MetaClass $class) + { + return $this + ->buildBusiness($class) + ->buildProto($class) + ->buildDao($class); + } + + protected function buildDao(MetaClass $class) { + $this->dumpFile( + ONPHP_META_AUTO_DAO_DIR.'Auto'.$class->getName().'DAO'.EXT_CLASS, + Format::indentize(AutoEmptyDaoBuilder::build($class)) + ); + + $userFile = ONPHP_META_DAO_DIR.$class->getName().'DAO'.EXT_CLASS; + + if ( + MetaConfiguration::me()->isForcedGeneration() + || !file_exists($userFile) + ) + $this->dumpFile( + $userFile, + Format::indentize(DaoBuilder::build($class)) + ); + + return $this; + } + + +} \ No newline at end of file From d8b6aee5e865dc131b681215163052cb34344c35 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Fri, 17 May 2013 13:50:04 +0400 Subject: [PATCH 194/418] fix quotes in datagrid input --- main/UI/Widget/DataGrid.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index c865e5e8d2..cbc4c6c7d6 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -286,7 +286,8 @@ protected function getEditRenderer($fieldId, LightMetaProperty $property) { case 'string': return function ($value) use ($fieldId, $property) { if ($value instanceof Stringable) $value = $value->toString(); - if ($property->getType() == 'string' && !$property->getMax()) { + $value = htmlspecialchars($value); + if ($property->getType() == 'string' && !$property->getMax()) { return ''; } else { - $styleWidth = $property->getType() == 'string' ? 250 : 80; - $length = $property->getType() == 'string' ? $property->getMax() : 16; + if ($property->getType() == 'string') { + $length = $property->getMax(); + $styleWidth = 250; + } else if ($property->getType() == 'hstore') { + $length = null; + $styleWidth = 250; + } else { + $length = 16; + $styleWidth = 80; + } + return ''; + .'" value="' . $value . '" ' + . ($length ? 'length="' . $length . '" ' : '') + .'/>'; } }; From 34dcc342a054716a0be103716638319f6ce66a8f Mon Sep 17 00:00:00 2001 From: klkvsk Date: Thu, 16 Jan 2014 16:51:03 +0400 Subject: [PATCH 285/418] fix for optional international strings --- meta/types/TranslatedStoreType.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/meta/types/TranslatedStoreType.class.php b/meta/types/TranslatedStoreType.class.php index 073f7a0bad..fbea2acae4 100644 --- a/meta/types/TranslatedStoreType.class.php +++ b/meta/types/TranslatedStoreType.class.php @@ -57,7 +57,11 @@ public function {$methodName}(\$langCode = null) } if (method_exists(\$this, '{$methodName}Translated')) { - return \$this->{$methodName}Translated()->toString(); + \$internationalString = \$this->{$methodName}Translated(); + if (\$internationalString instanceof InternationalString) { + return \$internationalString->toString(); + } + return null; } if (!\$langCode) { From 58a4017ef5a8cf81ff03227c887dc53e801b008a Mon Sep 17 00:00:00 2001 From: klkvsk Date: Mon, 20 Jan 2014 18:16:04 +0400 Subject: [PATCH 286/418] fix DBHstoreField.class.php - add '( .. )' --- core/OSQL/DBHstoreField.class.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/OSQL/DBHstoreField.class.php b/core/OSQL/DBHstoreField.class.php index c76ba067e7..38f841a8fe 100644 --- a/core/OSQL/DBHstoreField.class.php +++ b/core/OSQL/DBHstoreField.class.php @@ -46,6 +46,8 @@ public function toDialectString(Dialect $dialect) $field .= '->\'' . $this->key . '\''; } + $field = '(' . $field . ')'; + return $this->cast ? $dialect->toCasted($field, $this->cast) From 8fc4159d071751bcb1c12479a7ebb03dad337f49 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Tue, 21 Jan 2014 18:09:00 +0400 Subject: [PATCH 287/418] remove helper code --- meta/types/TranslatedStoreType.class.php | 42 ++++++++---------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/meta/types/TranslatedStoreType.class.php b/meta/types/TranslatedStoreType.class.php index fbea2acae4..fd3a9e90b7 100644 --- a/meta/types/TranslatedStoreType.class.php +++ b/meta/types/TranslatedStoreType.class.php @@ -52,42 +52,28 @@ public function {$methodName}Store() **/ public function {$methodName}(\$langCode = null) { - if (\$this->useTranslatedStore()) { - return \$this->{$methodName}Store(); - } - - if (method_exists(\$this, '{$methodName}Translated')) { - \$internationalString = \$this->{$methodName}Translated(); - if (\$internationalString instanceof InternationalString) { - return \$internationalString->toString(); - } - return null; - } - - if (!\$langCode) { - \$langCode = self::getLanguageCode(); - } - /** @var \$store {$this->getClassName()} */ \$store = \$this->{$methodName}Store(); - if (\$store->has(\$langCode)) { - return \$store->get(\$langCode); - } - - if (\$store->has(self::getDefaultLanguageCode())) { - return \$store->get(self::getDefaultLanguageCode()); + if (\$this->useTranslatedStore()) { + return \$store; } - \${$name} = null; - foreach (self::getLanguageCodes() as \$code) { - if (\$store->has(\$code)) { - \${$name} = \$store->get(\$code); - break; + \$languageCodes = array_merge( + array( + \$langCode ?: self::getLanguageCode(), + self::getDefaultLanguageCode() + ), + self::getLanguageCodes() + ); + + foreach (\$languageCodes as \$langCode) { + if (\$store->has(\$langCode)) { + return \$store->get(\$langCode); } } - return \${$name}; + return null; } EOT; From 261966eb2a49ed686b02e01958fbac0b6df4b056 Mon Sep 17 00:00:00 2001 From: klkvsk Date: Wed, 22 Jan 2014 13:02:59 +0400 Subject: [PATCH 288/418] allow limiting sizes of strings stored in TranslatedStore --- core/OSQL/DataType.class.php | 2 +- main/UI/Widget/DataGrid.class.php | 41 ++++++++++++------------------- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/core/OSQL/DataType.class.php b/core/OSQL/DataType.class.php index 5c2ad9e374..1a9af0ca8d 100755 --- a/core/OSQL/DataType.class.php +++ b/core/OSQL/DataType.class.php @@ -120,7 +120,7 @@ public function getSize() public function setSize($size) { Assert::isInteger($size); - Assert::isTrue($this->hasSize()); + Assert::isTrue($this->hasSize() || $this->id == self::HSTORE); $this->size = $size; diff --git a/main/UI/Widget/DataGrid.class.php b/main/UI/Widget/DataGrid.class.php index 671fda1ba7..5a0f88c4f6 100755 --- a/main/UI/Widget/DataGrid.class.php +++ b/main/UI/Widget/DataGrid.class.php @@ -139,12 +139,13 @@ public function addRows(array $data) { return $this; } - /** - * Добавляет строку в таблицу, определяет тип и имена ее полей - * @param $data - * @return DataGrid - * @throws WrongArgumentException - */ + /** + * Добавляет строку в таблицу, определяет тип и имена ее полей + * @param $data + * @param null $key + * @throws WrongArgumentException + * @return DataGrid + */ public function addRow($data, $key=null) { $rowId = count($this->rows); // id следующей строки if( isset($key) && $key=='total' ) { @@ -157,16 +158,15 @@ public function addRow($data, $key=null) { if ($data instanceof Prototyped) { if ( - $data instanceof TranslatableFieldsObject + $data instanceof TranslatableObject && is_null($this->localizedFields) ) { - /** @var $data TranslatableFieldsObject */ - $localizedFields = $data->getLocalizedFields(); - $this->localizedFields = array_merge( - array_keys($localizedFields), - array_values($localizedFields) - ); + $dataProto = $data->proto(); + if ($dataProto instanceof ProtoTranslatableObject) { + $this->localizedFields = $dataProto->getTranslatablePropertyNames(); + } } + /** @var $data Prototyped */ $this->objects[$rowId] = $data; $fieldIds = array(); @@ -301,7 +301,7 @@ protected function getEditRenderer($fieldId, LightMetaProperty $property) { return function ($value) use ($fieldId, $property) { if ($value instanceof Stringable) $value = $value->toString(); $value = htmlentities($value, ENT_COMPAT, 'UTF-8', false); - if ($property->getType() == 'string' && !$property->getMax()) { + if (in_array($property->getType(), array('string', 'hstore')) && !$property->getMax()) { return '