From 81298f969fb3dcf4a7034f89fb9513e91f14ccd0 Mon Sep 17 00:00:00 2001 From: romanb Date: Fri, 12 Sep 2008 09:19:25 +0000 Subject: [PATCH] new TODO namespace --- lib/Doctrine/TODO/AuditLog/Listener.php | 91 ++ lib/Doctrine/TODO/Builder/Exception.php | 45 + lib/Doctrine/TODO/Builder/Migration.php | 299 +++++ lib/Doctrine/TODO/Builder/Record.php | 808 +++++++++++++ lib/Doctrine/TODO/Cli/AnsiColorFormatter.php | 155 +++ lib/Doctrine/TODO/Cli/Exception.php | 34 + lib/Doctrine/TODO/Cli/Formatter.php | 111 ++ lib/Doctrine/TODO/Data/Exception.php | 34 + lib/Doctrine/TODO/Data/Export.php | 183 +++ lib/Doctrine/TODO/Data/Import.php | 380 +++++++ lib/Doctrine/TODO/File/Index.php | 56 + lib/Doctrine/TODO/FileFinder/GlobToRegex.php | 127 +++ .../TODO/FileFinder/NumberCompare.php | 106 ++ lib/Doctrine/TODO/I18n/Exception.php | 34 + lib/Doctrine/TODO/Log/Exception.php | 34 + lib/Doctrine/TODO/Log/Filter/Interface.php | 41 + lib/Doctrine/TODO/Log/Filter/Message.php | 64 ++ lib/Doctrine/TODO/Log/Filter/Priority.php | 72 ++ lib/Doctrine/TODO/Log/Filter/Suppress.php | 63 + lib/Doctrine/TODO/Log/Formatter/Interface.php | 41 + lib/Doctrine/TODO/Log/Formatter/Simple.php | 72 ++ lib/Doctrine/TODO/Log/Formatter/Xml.php | 84 ++ lib/Doctrine/TODO/Log/Writer/Abstract.php | 103 ++ lib/Doctrine/TODO/Log/Writer/Db.php | 107 ++ lib/Doctrine/TODO/Log/Writer/Mock.php | 64 ++ lib/Doctrine/TODO/Log/Writer/Null.php | 43 + lib/Doctrine/TODO/Log/Writer/Stream.php | 94 ++ lib/Doctrine/TODO/Migration/Diff.php | 155 +++ lib/Doctrine/TODO/Migration/Exception.php | 34 + .../IrreversibleMigrationException.php | 34 + lib/Doctrine/TODO/Migration/Process.php | 251 ++++ lib/Doctrine/TODO/Node/AdjacencyList.php | 34 + .../Node/AdjacencyList/LevelOrderIterator.php | 34 + .../Node/AdjacencyList/PostOrderIterator.php | 34 + .../Node/AdjacencyList/PreOrderIterator.php | 34 + lib/Doctrine/TODO/Node/Exception.php | 34 + lib/Doctrine/TODO/Node/Interface.php | 268 +++++ lib/Doctrine/TODO/Node/MaterializedPath.php | 34 + .../MaterializedPath/LevelOrderIterator.php | 68 ++ .../MaterializedPath/PostOrderIterator.php | 68 ++ .../MaterializedPath/PreOrderIterator.php | 68 ++ lib/Doctrine/TODO/Node/NestedSet.php | 1009 +++++++++++++++++ .../Node/NestedSet/LevelOrderIterator.php | 34 + .../TODO/Node/NestedSet/PostOrderIterator.php | 34 + .../TODO/Node/NestedSet/PreOrderIterator.php | 183 +++ lib/Doctrine/TODO/Pager/Exception.php | 37 + lib/Doctrine/TODO/Pager/Layout.php | 516 +++++++++ lib/Doctrine/TODO/Pager/Range.php | 176 +++ lib/Doctrine/TODO/Pager/Range/Jumping.php | 120 ++ lib/Doctrine/TODO/Pager/Range/Sliding.php | 136 +++ lib/Doctrine/TODO/Parser/Exception.php | 34 + lib/Doctrine/TODO/Parser/Json.php | 68 ++ lib/Doctrine/TODO/Parser/Serialize.php | 65 ++ lib/Doctrine/TODO/Parser/Xml.php | 140 +++ lib/Doctrine/TODO/Parser/Yml.php | 74 ++ lib/Doctrine/TODO/Parser/spyc.php | 881 ++++++++++++++ lib/Doctrine/TODO/Record/Generator.php | 286 +++++ lib/Doctrine/TODO/Search/Analyzer.php | 39 + .../TODO/Search/Analyzer/Exception.php | 34 + .../TODO/Search/Analyzer/Interface.php | 36 + .../TODO/Search/Analyzer/Standard.php | 298 +++++ lib/Doctrine/TODO/Search/Exception.php | 34 + lib/Doctrine/TODO/Search/File.php | 80 ++ lib/Doctrine/TODO/Search/Indexer.php | 75 ++ lib/Doctrine/TODO/Search/Indexer/Dir.php | 47 + .../TODO/Search/Indexer/Exception.php | 34 + lib/Doctrine/TODO/Search/Listener.php | 56 + lib/Doctrine/TODO/Search/Parser.php | 41 + lib/Doctrine/TODO/Search/Query.php | 235 ++++ lib/Doctrine/TODO/Search/Record.php | 47 + lib/Doctrine/TODO/Search/Scorer.php | 63 + lib/Doctrine/TODO/Task/BuildAll.php | 65 ++ lib/Doctrine/TODO/Task/BuildAllLoad.php | 58 + lib/Doctrine/TODO/Task/BuildAllReload.php | 58 + lib/Doctrine/TODO/Task/Compile.php | 46 + lib/Doctrine/TODO/Task/CreateDb.php | 48 + lib/Doctrine/TODO/Task/CreateTables.php | 45 + lib/Doctrine/TODO/Task/Dql.php | 76 ++ lib/Doctrine/TODO/Task/DropDb.php | 59 + lib/Doctrine/TODO/Task/DumpData.php | 54 + lib/Doctrine/TODO/Task/Exception.php | 34 + lib/Doctrine/TODO/Task/GenerateMigration.php | 46 + .../TODO/Task/GenerateMigrationsDb.php | 45 + .../TODO/Task/GenerateMigrationsModels.php | 46 + lib/Doctrine/TODO/Task/GenerateModelsDb.php | 45 + lib/Doctrine/TODO/Task/GenerateModelsYaml.php | 46 + lib/Doctrine/TODO/Task/GenerateSql.php | 56 + lib/Doctrine/TODO/Task/GenerateYamlDb.php | 45 + lib/Doctrine/TODO/Task/GenerateYamlModels.php | 46 + lib/Doctrine/TODO/Task/LoadData.php | 47 + lib/Doctrine/TODO/Task/LoadDummyData.php | 47 + lib/Doctrine/TODO/Task/Migrate.php | 45 + lib/Doctrine/TODO/Task/RebuildDb.php | 58 + lib/Doctrine/TODO/Template/Geographical.php | 120 ++ lib/Doctrine/TODO/Template/I18n.php | 64 ++ .../TODO/Template/Listener/Sluggable.php | 79 ++ .../TODO/Template/Listener/Timestampable.php | 110 ++ lib/Doctrine/TODO/Template/NestedSet.php | 52 + lib/Doctrine/TODO/Template/Searchable.php | 51 + lib/Doctrine/TODO/Template/Sluggable.php | 70 ++ lib/Doctrine/TODO/Template/Taggable.php | 34 + lib/Doctrine/TODO/Template/Timestampable.php | 84 ++ lib/Doctrine/TODO/Template/Versionable.php | 52 + lib/Doctrine/TODO/Tree/AdjacencyList.php | 34 + lib/Doctrine/TODO/Tree/Exception.php | 34 + lib/Doctrine/TODO/Tree/Interface.php | 65 ++ lib/Doctrine/TODO/Tree/MaterializedPath.php | 34 + lib/Doctrine/TODO/Tree/NestedSet.php | 322 ++++++ lib/Doctrine/TODO/Validator/Country.php | 302 +++++ lib/Doctrine/TODO/Validator/Creditcard.php | 47 + lib/Doctrine/TODO/Validator/Date.php | 53 + lib/Doctrine/TODO/Validator/Driver.php | 116 ++ lib/Doctrine/TODO/Validator/Email.php | 78 ++ lib/Doctrine/TODO/Validator/ErrorStack.php | 149 +++ lib/Doctrine/TODO/Validator/Exception.php | 100 ++ lib/Doctrine/TODO/Validator/Future.php | 79 ++ lib/Doctrine/TODO/Validator/Htmlcolor.php | 48 + lib/Doctrine/TODO/Validator/Ip.php | 45 + lib/Doctrine/TODO/Validator/Minlength.php | 49 + lib/Doctrine/TODO/Validator/Nospace.php | 45 + lib/Doctrine/TODO/Validator/Notblank.php | 46 + lib/Doctrine/TODO/Validator/Notnull.php | 45 + lib/Doctrine/TODO/Validator/Past.php | 79 ++ lib/Doctrine/TODO/Validator/Protected.php | 1 + lib/Doctrine/TODO/Validator/Range.php | 51 + lib/Doctrine/TODO/Validator/Readonly.php | 43 + lib/Doctrine/TODO/Validator/Regexp.php | 62 + lib/Doctrine/TODO/Validator/Time.php | 62 + lib/Doctrine/TODO/Validator/Timestamp.php | 66 ++ lib/Doctrine/TODO/Validator/Unique.php | 71 ++ lib/Doctrine/TODO/Validator/Unsigned.php | 50 + lib/Doctrine/TODO/Validator/Usstate.php | 105 ++ 132 files changed, 13519 insertions(+) create mode 100644 lib/Doctrine/TODO/AuditLog/Listener.php create mode 100644 lib/Doctrine/TODO/Builder/Exception.php create mode 100644 lib/Doctrine/TODO/Builder/Migration.php create mode 100644 lib/Doctrine/TODO/Builder/Record.php create mode 100644 lib/Doctrine/TODO/Cli/AnsiColorFormatter.php create mode 100644 lib/Doctrine/TODO/Cli/Exception.php create mode 100644 lib/Doctrine/TODO/Cli/Formatter.php create mode 100644 lib/Doctrine/TODO/Data/Exception.php create mode 100644 lib/Doctrine/TODO/Data/Export.php create mode 100644 lib/Doctrine/TODO/Data/Import.php create mode 100644 lib/Doctrine/TODO/File/Index.php create mode 100644 lib/Doctrine/TODO/FileFinder/GlobToRegex.php create mode 100644 lib/Doctrine/TODO/FileFinder/NumberCompare.php create mode 100644 lib/Doctrine/TODO/I18n/Exception.php create mode 100755 lib/Doctrine/TODO/Log/Exception.php create mode 100644 lib/Doctrine/TODO/Log/Filter/Interface.php create mode 100644 lib/Doctrine/TODO/Log/Filter/Message.php create mode 100644 lib/Doctrine/TODO/Log/Filter/Priority.php create mode 100644 lib/Doctrine/TODO/Log/Filter/Suppress.php create mode 100644 lib/Doctrine/TODO/Log/Formatter/Interface.php create mode 100644 lib/Doctrine/TODO/Log/Formatter/Simple.php create mode 100644 lib/Doctrine/TODO/Log/Formatter/Xml.php create mode 100644 lib/Doctrine/TODO/Log/Writer/Abstract.php create mode 100644 lib/Doctrine/TODO/Log/Writer/Db.php create mode 100644 lib/Doctrine/TODO/Log/Writer/Mock.php create mode 100644 lib/Doctrine/TODO/Log/Writer/Null.php create mode 100644 lib/Doctrine/TODO/Log/Writer/Stream.php create mode 100644 lib/Doctrine/TODO/Migration/Diff.php create mode 100644 lib/Doctrine/TODO/Migration/Exception.php create mode 100644 lib/Doctrine/TODO/Migration/IrreversibleMigrationException.php create mode 100644 lib/Doctrine/TODO/Migration/Process.php create mode 100644 lib/Doctrine/TODO/Node/AdjacencyList.php create mode 100644 lib/Doctrine/TODO/Node/AdjacencyList/LevelOrderIterator.php create mode 100644 lib/Doctrine/TODO/Node/AdjacencyList/PostOrderIterator.php create mode 100644 lib/Doctrine/TODO/Node/AdjacencyList/PreOrderIterator.php create mode 100644 lib/Doctrine/TODO/Node/Exception.php create mode 100644 lib/Doctrine/TODO/Node/Interface.php create mode 100644 lib/Doctrine/TODO/Node/MaterializedPath.php create mode 100644 lib/Doctrine/TODO/Node/MaterializedPath/LevelOrderIterator.php create mode 100644 lib/Doctrine/TODO/Node/MaterializedPath/PostOrderIterator.php create mode 100644 lib/Doctrine/TODO/Node/MaterializedPath/PreOrderIterator.php create mode 100644 lib/Doctrine/TODO/Node/NestedSet.php create mode 100644 lib/Doctrine/TODO/Node/NestedSet/LevelOrderIterator.php create mode 100644 lib/Doctrine/TODO/Node/NestedSet/PostOrderIterator.php create mode 100644 lib/Doctrine/TODO/Node/NestedSet/PreOrderIterator.php create mode 100644 lib/Doctrine/TODO/Pager/Exception.php create mode 100644 lib/Doctrine/TODO/Pager/Layout.php create mode 100644 lib/Doctrine/TODO/Pager/Range.php create mode 100644 lib/Doctrine/TODO/Pager/Range/Jumping.php create mode 100644 lib/Doctrine/TODO/Pager/Range/Sliding.php create mode 100644 lib/Doctrine/TODO/Parser/Exception.php create mode 100644 lib/Doctrine/TODO/Parser/Json.php create mode 100644 lib/Doctrine/TODO/Parser/Serialize.php create mode 100644 lib/Doctrine/TODO/Parser/Xml.php create mode 100644 lib/Doctrine/TODO/Parser/Yml.php create mode 100644 lib/Doctrine/TODO/Parser/spyc.php create mode 100644 lib/Doctrine/TODO/Record/Generator.php create mode 100644 lib/Doctrine/TODO/Search/Analyzer.php create mode 100644 lib/Doctrine/TODO/Search/Analyzer/Exception.php create mode 100644 lib/Doctrine/TODO/Search/Analyzer/Interface.php create mode 100644 lib/Doctrine/TODO/Search/Analyzer/Standard.php create mode 100644 lib/Doctrine/TODO/Search/Exception.php create mode 100644 lib/Doctrine/TODO/Search/File.php create mode 100644 lib/Doctrine/TODO/Search/Indexer.php create mode 100644 lib/Doctrine/TODO/Search/Indexer/Dir.php create mode 100644 lib/Doctrine/TODO/Search/Indexer/Exception.php create mode 100644 lib/Doctrine/TODO/Search/Listener.php create mode 100644 lib/Doctrine/TODO/Search/Parser.php create mode 100644 lib/Doctrine/TODO/Search/Query.php create mode 100644 lib/Doctrine/TODO/Search/Record.php create mode 100644 lib/Doctrine/TODO/Search/Scorer.php create mode 100644 lib/Doctrine/TODO/Task/BuildAll.php create mode 100644 lib/Doctrine/TODO/Task/BuildAllLoad.php create mode 100644 lib/Doctrine/TODO/Task/BuildAllReload.php create mode 100644 lib/Doctrine/TODO/Task/Compile.php create mode 100644 lib/Doctrine/TODO/Task/CreateDb.php create mode 100644 lib/Doctrine/TODO/Task/CreateTables.php create mode 100644 lib/Doctrine/TODO/Task/Dql.php create mode 100644 lib/Doctrine/TODO/Task/DropDb.php create mode 100644 lib/Doctrine/TODO/Task/DumpData.php create mode 100644 lib/Doctrine/TODO/Task/Exception.php create mode 100644 lib/Doctrine/TODO/Task/GenerateMigration.php create mode 100644 lib/Doctrine/TODO/Task/GenerateMigrationsDb.php create mode 100644 lib/Doctrine/TODO/Task/GenerateMigrationsModels.php create mode 100644 lib/Doctrine/TODO/Task/GenerateModelsDb.php create mode 100644 lib/Doctrine/TODO/Task/GenerateModelsYaml.php create mode 100644 lib/Doctrine/TODO/Task/GenerateSql.php create mode 100644 lib/Doctrine/TODO/Task/GenerateYamlDb.php create mode 100644 lib/Doctrine/TODO/Task/GenerateYamlModels.php create mode 100644 lib/Doctrine/TODO/Task/LoadData.php create mode 100644 lib/Doctrine/TODO/Task/LoadDummyData.php create mode 100644 lib/Doctrine/TODO/Task/Migrate.php create mode 100644 lib/Doctrine/TODO/Task/RebuildDb.php create mode 100644 lib/Doctrine/TODO/Template/Geographical.php create mode 100644 lib/Doctrine/TODO/Template/I18n.php create mode 100644 lib/Doctrine/TODO/Template/Listener/Sluggable.php create mode 100644 lib/Doctrine/TODO/Template/Listener/Timestampable.php create mode 100644 lib/Doctrine/TODO/Template/NestedSet.php create mode 100644 lib/Doctrine/TODO/Template/Searchable.php create mode 100644 lib/Doctrine/TODO/Template/Sluggable.php create mode 100644 lib/Doctrine/TODO/Template/Taggable.php create mode 100644 lib/Doctrine/TODO/Template/Timestampable.php create mode 100644 lib/Doctrine/TODO/Template/Versionable.php create mode 100644 lib/Doctrine/TODO/Tree/AdjacencyList.php create mode 100644 lib/Doctrine/TODO/Tree/Exception.php create mode 100644 lib/Doctrine/TODO/Tree/Interface.php create mode 100644 lib/Doctrine/TODO/Tree/MaterializedPath.php create mode 100644 lib/Doctrine/TODO/Tree/NestedSet.php create mode 100644 lib/Doctrine/TODO/Validator/Country.php create mode 100644 lib/Doctrine/TODO/Validator/Creditcard.php create mode 100644 lib/Doctrine/TODO/Validator/Date.php create mode 100644 lib/Doctrine/TODO/Validator/Driver.php create mode 100644 lib/Doctrine/TODO/Validator/Email.php create mode 100644 lib/Doctrine/TODO/Validator/ErrorStack.php create mode 100644 lib/Doctrine/TODO/Validator/Exception.php create mode 100644 lib/Doctrine/TODO/Validator/Future.php create mode 100644 lib/Doctrine/TODO/Validator/Htmlcolor.php create mode 100644 lib/Doctrine/TODO/Validator/Ip.php create mode 100644 lib/Doctrine/TODO/Validator/Minlength.php create mode 100644 lib/Doctrine/TODO/Validator/Nospace.php create mode 100644 lib/Doctrine/TODO/Validator/Notblank.php create mode 100644 lib/Doctrine/TODO/Validator/Notnull.php create mode 100644 lib/Doctrine/TODO/Validator/Past.php create mode 100644 lib/Doctrine/TODO/Validator/Protected.php create mode 100644 lib/Doctrine/TODO/Validator/Range.php create mode 100644 lib/Doctrine/TODO/Validator/Readonly.php create mode 100644 lib/Doctrine/TODO/Validator/Regexp.php create mode 100644 lib/Doctrine/TODO/Validator/Time.php create mode 100644 lib/Doctrine/TODO/Validator/Timestamp.php create mode 100644 lib/Doctrine/TODO/Validator/Unique.php create mode 100644 lib/Doctrine/TODO/Validator/Unsigned.php create mode 100644 lib/Doctrine/TODO/Validator/Usstate.php diff --git a/lib/Doctrine/TODO/AuditLog/Listener.php b/lib/Doctrine/TODO/AuditLog/Listener.php new file mode 100644 index 000000000..dcea2a9d6 --- /dev/null +++ b/lib/Doctrine/TODO/AuditLog/Listener.php @@ -0,0 +1,91 @@ +. + */ +Doctrine::autoload('Doctrine_Record_Listener'); +/** + * Doctrine_AuditLog_Listener + * + * @package Doctrine + * @subpackage AuditLog + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + * @author Konsta Vesterinen + */ +class Doctrine_AuditLog_Listener extends Doctrine_Record_Listener +{ + + protected $_auditLog; + + public function __construct(Doctrine_AuditLog $auditLog) + { + $this->_auditLog = $auditLog; + } + + public function preInsert(Doctrine_Event $event) + { + $versionColumn = $this->_auditLog->getOption('versionColumn'); + + $event->getInvoker()->set($versionColumn, 1); + } + + public function postInsert(Doctrine_Event $event) + { + $class = $this->_auditLog->getOption('className'); + + $record = $event->getInvoker(); + $version = new $class(); + $version->merge($record->toArray()); + $version->save(); + } + + public function preDelete(Doctrine_Event $event) + { + $class = $this->_auditLog->getOption('className'); + + $record = $event->getInvoker(); + + $versionColumn = $this->_auditLog->getOption('versionColumn'); + $version = $record->get($versionColumn); + + $record->set($versionColumn, ++$version); + + $version = new $class(); + $version->merge($record->toArray()); + $version->save(); + } + + public function preUpdate(Doctrine_Event $event) + { + $class = $this->_auditLog->getOption('className'); + $record = $event->getInvoker(); + + $versionColumn = $this->_auditLog->getOption('versionColumn'); + + $version = $record->get($versionColumn); + + $record->set($versionColumn, ++$version); + + $version = new $class(); + $version->merge($record->toArray()); + $version->save(); + } +} diff --git a/lib/Doctrine/TODO/Builder/Exception.php b/lib/Doctrine/TODO/Builder/Exception.php new file mode 100644 index 000000000..c8728ce7e --- /dev/null +++ b/lib/Doctrine/TODO/Builder/Exception.php @@ -0,0 +1,45 @@ +. + */ +Doctrine::autoload('Doctrine_Exception'); +/** + * @package Doctrine + * @subpackage Import + * @url http://www.phpdoctrine.org + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Jukka Hassinen + * @version $Id: Exception.php 3570 2008-01-22 22:52:53Z jwage $ + */ + +/** + * Doctrine_Builder_Exception + * + * @package Doctrine + * @subpackage Builder + * @link www.phpdoctrine.org + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @since 1.0 + * @version $Revision: 3570 $ + * @author Konsta Vesterinen + * @author Jonathan H. Wage + */ +class Doctrine_Builder_Exception extends Doctrine_Exception +{ +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Builder/Migration.php b/lib/Doctrine/TODO/Builder/Migration.php new file mode 100644 index 000000000..c5dff41bd --- /dev/null +++ b/lib/Doctrine/TODO/Builder/Migration.php @@ -0,0 +1,299 @@ +. + */ + +/** + * Doctrine_Builder_Migration + * + * @package Doctrine + * @subpackage Builder + * @author Konsta Vesterinen + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2939 $ + */ +class Doctrine_Builder_Migration extends Doctrine_Builder +{ + /** + * migrationsPath + * + * The path to your migration classes directory + * + * @var string + */ + private $_migrationsPath = ''; + + /** + * suffix + * + * File suffix to use when writing class definitions + * + * @var string $suffix + */ + private $_suffix = '.class.php'; + + /** + * tpl + * + * Class template used for writing classes + * + * @var $_tpl + */ + private static $_tpl; + + /** + * __construct + * + * @return void + */ + public function __construct($migrationsPath = null) + { + if ($migrationsPath) { + $this->setMigrationsPath($migrationsPath); + } + + $this->_loadTemplate(); + } + + /** + * setMigrationsPath + * + * @param string path the path where migration classes are stored and being generated + * @return + */ + public function setMigrationsPath($path) + { + Doctrine_Lib::makeDirectories($path); + + $this->_migrationsPath = $path; + } + + /** + * getMigrationsPath + * + * @return string the path where migration classes are stored and being generated + */ + public function getMigrationsPath() + { + return $this->_migrationsPath; + } + + /** + * loadTemplate + * + * Loads the class template used for generating classes + * + * @return void + */ + protected function _loadTemplate() + { + if (isset(self::$_tpl)) { + return; + } + + self::$_tpl =<<generateMigrationsFromModels($directory); + + Doctrine_Lib::removeDirectories($directory); + + return $result; + } + + /** + * generateMigrationsFromModels + * + * @param string $modelsPath + * @return void + */ + public function generateMigrationsFromModels($modelsPath = null) + { + if ($modelsPath) { + $models = Doctrine::loadModels($modelsPath); + } else { + $models = Doctrine::getLoadedModels(); + } + + $foreignKeys = array(); + + foreach ($models as $model) { + $export = Doctrine::getTable($model)->getExportableFormat(); + + $foreignKeys[$export['tableName']] = $export['options']['foreignKeys']; + + $up = $this->buildCreateTable($export); + $down = $this->buildDropTable($export); + + $className = 'Add' . Doctrine::classify($export['tableName']); + + $this->generateMigrationClass($className, array(), $up, $down); + } + + $className = 'ApplyForeignKeyConstraints'; + + $up = ''; + $down = ''; + foreach ($foreignKeys as $tableName => $definitions) { + $tableForeignKeyNames[$tableName] = array(); + + foreach ($definitions as $definition) { + $definition['name'] = $tableName . '_' . $definition['foreignTable'] . '_' . $definition['local'] . '_' . $definition['foreign']; + + $up .= $this->buildCreateForeignKey($tableName, $definition); + $down .= $this->buildDropForeignKey($tableName, $definition); + } + } + + $this->generateMigrationClass($className, array(), $up, $down); + + return true; + } + + /** + * buildCreateForeignKey + * + * @param string $tableName + * @param string $definition + * @return void + */ + public function buildCreateForeignKey($tableName, $definition) + { + return "\t\t\$this->createForeignKey('" . $tableName . "', " . var_export($definition, true) . ");"; + } + + /** + * buildDropForeignKey + * + * @param string $tableName + * @param string $definition + * @return void + */ + public function buildDropForeignKey($tableName, $definition) + { + return "\t\t\$this->dropForeignKey('" . $tableName . "', '" . $definition['name'] . "');\n"; + } + + /** + * buildCreateTable + * + * @param string $tableData + * @return void + */ + public function buildCreateTable($tableData) + { + $code = "\t\t\$this->createTable('" . $tableData['tableName'] . "', "; + + $code .= var_export($tableData['columns'], true) . ", "; + + $code .= var_export(array('indexes' => $tableData['options']['indexes'], 'primary' => $tableData['options']['primary']), true); + + $code .= ");"; + + return $code; + } + + /** + * buildDropTable + * + * @param string $tableData + * @return string + */ + public function buildDropTable($tableData) + { + return "\t\t\$this->dropTable('" . $tableData['tableName'] . "');"; + } + + /** + * generateMigrationClass + * + * @return void + */ + public function generateMigrationClass($className, $options = array(), $up = null, $down = null, $return = false) + { + if ($return || !$this->getMigrationsPath()) { + return $this->buildMigrationClass($className, null, $options, $up, $down); + } else { + if ( ! $this->getMigrationsPath()) { + throw new Doctrine_Migration_Exception('You must specify the path to your migrations.'); + } + + $migration = new Doctrine_Migration($this->getMigrationsPath()); + $next = (string) $migration->getNextVersion(); + + $fileName = str_repeat('0', (3 - strlen($next))) . $next . '_' . Doctrine::tableize($className) . $this->_suffix; + + $class = $this->buildMigrationClass($className, $fileName, $options, $up, $down); + + $path = $this->getMigrationsPath() . DIRECTORY_SEPARATOR . $fileName; + + file_put_contents($path, $class); + } + } + + /** + * buildMigrationClass + * + * @return string + */ + public function buildMigrationClass($className, $fileName = null, $options = array(), $up = null, $down = null) + { + $extends = isset($options['extends']) ? $options['extends']:'Doctrine_Migration'; + + $content = '. + */ + +/** + * Doctrine_Builder_Record + * + * Import builder is responsible of building Doctrine_Entity classes + * based on a database schema. + * + * @package Doctrine + * @subpackage Builder + * @link www.phpdoctrine.org + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @since 1.0 + * @version $Revision: 4866 $ + * @author Konsta Vesterinen + * @author Jukka Hassinen + * @author Nicolas BĂ©rard-Nault + * @author Jonathan H. Wage + */ +class Doctrine_Builder_Record +{ + /** + * Path + * + * the path where imported files are being generated + * + * @var string $_path + */ + protected $_path = ''; + + /** + * packagesPrefix + * + * @var string + */ + protected $_packagesPrefix = 'Package'; + + /** + * packagesPath + * + * @var string + */ + protected $_packagesPath = ''; + + /** + * suffix + * + * File suffix to use when writing class definitions + * + * @var string $suffix + */ + protected $_suffix = '.php'; + + /** + * generateBaseClasses + * + * Bool true/false for whether or not to generate base classes + * + * @var string $suffix + */ + protected $_generateBaseClasses = true; + + /** + * baseClassesDirectory + * + * Directory to put the generate base classes in + * + * @var string $suffix + */ + protected $_baseClassesDirectory = 'generated'; + + /** + * baseClassName + * + * @var string + */ + protected $_baseClassName = 'Doctrine_Entity'; + + /** + * tpl + * + * Class template used for writing classes + * + * @var $_tpl + */ + protected static $_tpl; + + /** + * __construct + * + * @return void + */ + public function __construct() + { + $this->loadTemplate(); + } + + /** + * setTargetPath + * + * @param string path the path where imported files are being generated + * @return + */ + public function setTargetPath($path) + { + if ( ! $this->_packagesPath) { + $this->setPackagesPath($path . DIRECTORY_SEPARATOR . 'packages'); + } + + $this->_path = $path; + } + + /** + * setPackagePath + * + * @param string $packagesPrefix + * @return void + */ + public function setPackagesPrefix($packagesPrefix) + { + $this->_packagesPrefix = $packagesPrefix; + } + + /** + * setPackagesPath + * + * @param string $packagesPath + * @return void + */ + public function setPackagesPath($packagesPath) + { + $this->_packagesPath = $packagesPath; + } + + /** + * generateBaseClasses + * + * Specify whether or not to generate classes which extend from generated base classes + * + * @param string $bool + * @return void + */ + public function generateBaseClasses($bool = null) + { + if ($bool !== null) { + $this->_generateBaseClasses = $bool; + } + + return $this->_generateBaseClasses; + } + + /** + * setBaseClassesDirectory + * + * @return void + */ + public function setBaseClassesDirectory($baseClassesDirectory) + { + $this->_baseClassesDirectory; + } + + /** + * setBaseClassName + * + * @package default + */ + public function setBaseClassName($className) + { + $this->_baseClassName = $className; + } + + /** + * setSuffix + * + * @param string $suffix + * @return void + */ + public function setSuffix($suffix) + { + $this->_suffix = $suffix; + } + + /** + * getTargetPath + * + * @return string the path where imported files are being generated + */ + public function getTargetPath() + { + return $this->_path; + } + + /** + * setOptions + * + * @param string $options + * @return void + */ + public function setOptions($options) + { + if (!empty($options)) { + foreach ($options as $key => $value) { + $this->setOption($key, $value); + } + } + } + + /** + * setOption + * + * @param string $key + * @param string $value + * @return void + */ + public function setOption($key, $value) + { + $name = 'set' . Doctrine::classify($key); + + if (method_exists($this, $name)) { + $this->$name($value); + } else { + $key = '_' . $key; + $this->$key = $value; + } + } + + /** + * loadTemplate + * + * Loads the class template used for generating classes + * + * @return void + */ + public function loadTemplate() + { + if (isset(self::$_tpl)) { + return; + } + + self::$_tpl =<<setTableName(\''. $definition['tableName'].'\');'; + + $i++; + } + + if (isset($definition['columns']) && is_array($definition['columns']) && !empty($definition['columns'])) { + $ret[$i] = $this->buildColumns($definition['columns']); + $i++; + } + + if (isset($definition['indexes']) && is_array($definition['indexes']) && !empty($definition['indexes'])) { + $ret[$i] = $this->buildIndexes($definition['indexes']); + $i++; + } + + if (isset($definition['attributes']) && is_array($definition['attributes']) && !empty($definition['attributes'])) { + $ret[$i] = $this->buildAttributes($definition['attributes']); + $i++; + } + + if (isset($definition['options']) && is_array($definition['options']) && !empty($definition['options'])) { + $ret[$i] = $this->buildOptions($definition['options']); + $i++; + } + + if (isset($definition['subclasses']) && is_array($definition['subclasses']) && !empty($definition['subclasses'])) { + $ret[$i] = ' $this->setSubclasses(' . var_export($definition['subclasses'], true) . ');'; + $i++; + } + + $code = implode("\n", $ret); + $code = trim($code); + + if ($code) { + return "\n public function setTableDefinition()"."\n {\n ".$code."\n }"; + } + } + + /** + * buildSetUp + * + * @param array $options + * @param array $columns + * @param array $relations + * @return string + */ + public function buildSetUp(array $definition) + { + $ret = array(); + $i = 0; + + if (isset($definition['inheritance']['extends']) && ! (isset($definition['override_parent']) && $definition['override_parent'] == true)) { + $ret[$i] = " parent::setUp();"; + $i++; + } + + if (isset($definition['relations']) && is_array($definition['relations']) && !empty($definition['relations'])) { + foreach ($definition['relations'] as $name => $relation) { + $class = isset($relation['class']) ? $relation['class']:$name; + $alias = (isset($relation['alias']) && $relation['alias'] !== $relation['class']) ? ' as ' . $relation['alias'] : ''; + + if ( ! isset($relation['type'])) { + $relation['type'] = Doctrine_Relation::ONE; + } + + if ($relation['type'] === Doctrine_Relation::ONE || + $relation['type'] === Doctrine_Relation::ONE_COMPOSITE) { + $ret[$i] = " ".'$this->hasOne(\'' . $class . $alias . '\''; + } else { + $ret[$i] = " ".'$this->hasMany(\'' . $class . $alias . '\''; + } + + $a = array(); + + if (isset($relation['refClass'])) { + $a[] = '\'refClass\' => ' . var_export($relation['refClass'], true); + } + + if (isset($relation['deferred']) && $relation['deferred']) { + $a[] = '\'default\' => ' . var_export($relation['deferred'], true); + } + + if (isset($relation['local']) && $relation['local']) { + $a[] = '\'local\' => ' . var_export($relation['local'], true); + } + + if (isset($relation['foreign']) && $relation['foreign']) { + $a[] = '\'foreign\' => ' . var_export($relation['foreign'], true); + } + + if (isset($relation['onDelete']) && $relation['onDelete']) { + $a[] = '\'onDelete\' => ' . var_export($relation['onDelete'], true); + } + + if (isset($relation['onUpdate']) && $relation['onUpdate']) { + $a[] = '\'onUpdate\' => ' . var_export($relation['onUpdate'], true); + } + + if (isset($relation['equal']) && $relation['equal']) { + $a[] = '\'equal\' => ' . var_export($relation['equal'], true); + } + + if ( ! empty($a)) { + $ret[$i] .= ', ' . 'array('; + $length = strlen($ret[$i]); + $ret[$i] .= implode(',' . PHP_EOL . str_repeat(' ', $length), $a) . ')'; + } + + $ret[$i] .= ');'."\n"; + $i++; + } + } + + if (isset($definition['templates']) && is_array($definition['templates']) && !empty($definition['templates'])) { + $ret[$i] = $this->buildTemplates($definition['templates']); + $i++; + } + + if (isset($definition['actAs']) && is_array($definition['actAs']) && !empty($definition['actAs'])) { + $ret[$i] = $this->buildActAs($definition['actAs']); + $i++; + } + + $code = implode("\n", $ret); + $code = trim($code); + + if ($code) { + return "\n public function setUp()\n {\n ".$code."\n }"; + } + } + + /** + * buildColumns + * + * @param string $array + * @return void + */ + public function buildColumns(array $columns) + { + $build = null; + foreach ($columns as $name => $column) { + $build .= " ".'$this->hasColumn(\'' . $name . '\', \'' . $column['type'] . '\''; + + if ($column['length']) { + $build .= ', ' . $column['length']; + } else { + $build .= ', null'; + } + + $options = $column; + $unset = array('name', 'type', 'length', 'ptype'); + foreach ($options as $key => $value) { + if (in_array($key, $unset) || $value === null) { + unset($options[$key]); + } + } + + if (is_array($options) && !empty($options)) { + $build .= ', ' . var_export($options, true); + } + + $build .= ");\n"; + } + + return $build; + } + + /* + * Build the accessors + * + * @param string $table + * @param array $columns + */ + public function buildAccessors(array $definition) + { + $accessors = array(); + foreach (array_keys($definition['columns']) as $name) { + $accessors[] = $name; + } + + foreach ($definition['relations'] as $relation) { + $accessors[] = $relation['alias']; + } + + $ret = ''; + foreach ($accessors as $name) { + // getters + $ret .= "\n public function get" . Doctrine_Inflector::classify(Doctrine_Inflector::tableize($name)) . "(\$load = true)\n"; + $ret .= " {\n"; + $ret .= " return \$this->get('{$name}', \$load);\n"; + $ret .= " }\n"; + + // setters + $ret .= "\n public function set" . Doctrine_Inflector::classify(Doctrine_Inflector::tableize($name)) . "(\${$name}, \$load = true)\n"; + $ret .= " {\n"; + $ret .= " return \$this->set('{$name}', \${$name}, \$load);\n"; + $ret .= " }\n"; + } + + return $ret; + } + + /** + * buildTemplates + * + * @param string $array + * @return void + */ + public function buildTemplates(array $templates) + { + $build = ''; + foreach ($templates as $name => $options) { + + if (is_array($options) && !empty($options)) { + $optionsPhp = var_export($options, true); + + $build .= " \$this->loadTemplate('" . $name . "', " . $optionsPhp . ");\n"; + } else { + if (isset($templates[0])) { + $build .= " \$this->loadTemplate('" . $options . "');\n"; + } else { + $build .= " \$this->loadTemplate('" . $name . "');\n"; + } + } + } + + return $build; + } + + /** + * buildActAs + * + * @param string $array + * @return void + */ + public function buildActAs(array $actAs) + { + $build = ''; + foreach ($actAs as $name => $options) { + if (is_array($options) && !empty($options)) { + $optionsPhp = var_export($options, true); + + $build .= " \$this->actAs('" . $name . "', " . $optionsPhp . ");\n"; + } else { + if (isset($actAs[0])) { + $build .= " \$this->actAs('" . $options . "');\n"; + } else { + $build .= " \$this->actAs('" . $name . "');\n"; + } + } + } + + return $build; + } + + /** + * buildAttributes + * + * @param string $array + * @return void + */ + public function buildAttributes(array $attributes) + { + $build = "\n"; + foreach ($attributes as $key => $value) { + + if (is_bool($value)) + { + $values = $value ? 'true':'false'; + } else { + if ( ! is_array($value)) { + $value = array($value); + } + + $values = ''; + foreach ($value as $attr) { + $values .= "Doctrine::" . strtoupper($key) . "_" . strtoupper($attr) . ' ^ '; + } + + // Trim last ^ + $values = substr($values, 0, strlen($values) - 3); + } + + $build .= " \$this->setAttribute(Doctrine::ATTR_" . strtoupper($key) . ", " . $values . ");\n"; + } + + return $build; + } + + /** + * buildTableOptions + * + * @param string $array + * @return void + */ + public function buildOptions(array $options) + { + $build = ''; + foreach ($options as $name => $value) { + $build .= " \$this->option('$name', " . var_export($value, true) . ");\n"; + } + + return $build; + } + + /** + * buildIndexes + * + * @param string $array + * @return void + */ + public function buildIndexes(array $indexes) + { + $build = ''; + + foreach ($indexes as $indexName => $definitions) { + $build .= "\n \$this->index('" . $indexName . "'"; + $build .= ', ' . var_export($definitions, true); + $build .= ');'; + } + + return $build; + } + + /** + * buildDefinition + * + * @param array $definition + * @return string + */ + public function buildDefinition(array $definition) + { + if ( ! isset($definition['className'])) { + throw new Doctrine_Builder_Exception('Missing class name.'); + } + + $abstract = isset($definition['abstract']) && $definition['abstract'] === true ? 'abstract ':null; + $className = $definition['className']; + $extends = isset($definition['inheritance']['extends']) ? $definition['inheritance']['extends']:$this->_baseClassName; + + if ( ! (isset($definition['no_definition']) && $definition['no_definition'] === true)) { + $tableDefinitionCode = $this->buildTableDefinition($definition); + $setUpCode = $this->buildSetUp($definition); + } else { + $tableDefinitionCode = null; + $setUpCode = null; + } + + $accessorsCode = (isset($definition['generate_accessors']) && $definition['generate_accessors'] === true) ? $this->buildAccessors($definition):null; + + $content = sprintf(self::$_tpl, $abstract, + $className, + $extends, + $tableDefinitionCode, + $setUpCode, + $accessorsCode); + + return $content; + } + + /** + * buildRecord + * + * @param array $options + * @param array $columns + * @param array $relations + * @param array $indexes + * @param array $attributes + * @param array $templates + * @param array $actAs + * @return void= + */ + public function buildRecord(array $definition) + { + if ( ! isset($definition['className'])) { + throw new Doctrine_Builder_Exception('Missing class name.'); + } + + if ($this->generateBaseClasses()) { + $definition['is_package'] = (isset($definition['package']) && $definition['package']) ? true:false; + + if ($definition['is_package']) { + $e = explode('.', $definition['package']); + $definition['package_name'] = $e[0]; + unset($e[0]); + + $definition['package_path'] = implode(DIRECTORY_SEPARATOR, $e); + } + + // Top level definition that extends from all the others + $topLevel = $definition; + unset($topLevel['tableName']); + + // If we have a package then we need to make this extend the package definition and not the base definition + // The package definition will then extends the base definition + $topLevel['inheritance']['extends'] = (isset($topLevel['package']) && $topLevel['package']) ? $this->_packagesPrefix . $topLevel['className']:'Base' . $topLevel['className']; + $topLevel['no_definition'] = true; + $topLevel['generate_once'] = true; + $topLevel['is_main_class'] = true; + unset($topLevel['connection']); + + // Package level definition that extends from the base definition + if (isset($definition['package'])) { + + $packageLevel = $definition; + $packageLevel['className'] = $topLevel['inheritance']['extends']; + $packageLevel['inheritance']['extends'] = 'Base' . $topLevel['className']; + $packageLevel['no_definition'] = true; + $packageLevel['abstract'] = true; + $packageLevel['override_parent'] = true; + $packageLevel['generate_once'] = true; + $packageLevel['is_package_class'] = true; + unset($packageLevel['connection']); + } + + $baseClass = $definition; + $baseClass['className'] = 'Base' . $baseClass['className']; + $baseClass['abstract'] = true; + $baseClass['override_parent'] = false; + $baseClass['is_base_class'] = true; + + $this->writeDefinition($baseClass); + + if (!empty($packageLevel)) { + $this->writeDefinition($packageLevel); + } + + $this->writeDefinition($topLevel); + } else { + $this->writeDefinition($definition); + } + } + + /** + * writeDefinition + * + * @param array $options + * @param array $columns + * @param array $relations + * @param array $indexes + * @param array $attributes + * @param array $templates + * @param array $actAs + * @return void + */ + public function writeDefinition(array $definition) + { + $definitionCode = $this->buildDefinition($definition); + + $fileName = $definition['className'] . $this->_suffix; + + $packagesPath = $this->_packagesPath ? $this->_packagesPath:$this->_path; + + // If this is a main class that either extends from Base or Package class + if (isset($definition['is_main_class']) && $definition['is_main_class']) { + // If is package then we need to put it in a package subfolder + if (isset($definition['is_package']) && $definition['is_package']) { + $writePath = $this->_path . DIRECTORY_SEPARATOR . $definition['package_name']; + // Otherwise lets just put it in the root of the path + } else { + $writePath = $this->_path; + } + } + + // If is the package class then we need to make the path to the complete package + if (isset($definition['is_package_class']) && $definition['is_package_class']) { + $path = str_replace('.', DIRECTORY_SEPARATOR, trim($definition['package'])); + + $writePath = $packagesPath . DIRECTORY_SEPARATOR . $path; + } + + // If it is the base class of the doctrine record definition + if (isset($definition['is_base_class']) && $definition['is_base_class']) { + // If it is a part of a package then we need to put it in a package subfolder + if (isset($definition['is_package']) && $definition['is_package']) { + $writePath = $this->_path . DIRECTORY_SEPARATOR . $definition['package_name'] . DIRECTORY_SEPARATOR . $this->_baseClassesDirectory; + // Otherwise lets just put it in the root generated folder + } else { + $writePath = $this->_path . DIRECTORY_SEPARATOR . $this->_baseClassesDirectory; + } + } + + if (isset($writePath)) { + Doctrine_Lib::makeDirectories($writePath); + + $writePath .= DIRECTORY_SEPARATOR . $fileName; + } else { + Doctrine_Lib::makeDirectories($this->_path); + + $writePath = $this->_path . DIRECTORY_SEPARATOR . $fileName; + } + + $code = "bindComponent('" . $definition['connectionClassName'] . "', '" . $definition['connection'] . "');\n"; + } + + $code .= PHP_EOL . $definitionCode; + + if (isset($definition['generate_once']) && $definition['generate_once'] === true) { + if (!file_exists($writePath)) { + $bytes = file_put_contents($writePath, $code); + } + } else { + $bytes = file_put_contents($writePath, $code); + } + + if (isset($bytes) && $bytes === false) { + throw new Doctrine_Builder_Exception("Couldn't write file " . $writePath); + } + } +} diff --git a/lib/Doctrine/TODO/Cli/AnsiColorFormatter.php b/lib/Doctrine/TODO/Cli/AnsiColorFormatter.php new file mode 100644 index 000000000..4ba2eaebc --- /dev/null +++ b/lib/Doctrine/TODO/Cli/AnsiColorFormatter.php @@ -0,0 +1,155 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/* + * $Id: AnsiColorFormatter.php 2702 2007-10-03 21:43:22Z Jonathan.Wage $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER OR 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. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information, see + * . + */ + +/** + * Doctrine_AnsiColorFormatter provides methods to colorize text to be displayed on a console. + * + * @package Doctrine + * @subpackage Cli + * @author Fabien Potencier + * @version SVN: $Id: sfAnsiColorFormatter.class.php 5250 2007-09-24 08:11:50Z fabien $ + */ +class Doctrine_Cli_AnsiColorFormatter extends Doctrine_Cli_Formatter +{ + protected + $_styles = array( + 'HEADER' => array('fg' => 'black', 'bold' => true), + 'ERROR' => array('bg' => 'red', 'fg' => 'white', 'bold' => true), + 'INFO' => array('fg' => 'green', 'bold' => true), + 'COMMENT' => array('fg' => 'yellow'), + ), + $_options = array('bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8), + $_foreground = array('black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37), + $_background = array('black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47); + + /** + * Sets a new style. + * + * @param string The style name + * @param array An array of options + */ + public function setStyle($name, $options = array()) + { + $this->_styles[$name] = $options; + } + + /** + * Formats a text according to the given style or parameters. + * + * @param string The test to style + * @param mixed An array of options or a style name + * + * @return string The styled text + */ + public function format($text = '', $parameters = array(), $stream = STDOUT) + { + if ( ! $this->supportsColors($stream)) { + return $text; + } + + if ( ! is_array($parameters) && 'NONE' == $parameters) { + return $text; + } + + if ( ! is_array($parameters) && isset($this->_styles[$parameters])) { + $parameters = $this->_styles[$parameters]; + } + + $codes = array(); + if (isset($parameters['fg'])) { + $codes[] = $this->_foreground[$parameters['fg']]; + } + + if (isset($parameters['bg'])) { + $codes[] = $this->_background[$parameters['bg']]; + } + + foreach ($this->_options as $option => $value) { + if (isset($parameters[$option]) && $parameters[$option]) { + $codes[] = $value; + } + } + + return "\033[".implode(';', $codes).'m'.$text."\033[0m"; + } + + /** + * Formats a message within a section. + * + * @param string The section name + * @param string The text message + * @param integer The maximum size allowed for a line (65 by default) + */ + public function formatSection($section, $text, $size = null) + { + $width = 9 + strlen($this->format('', 'INFO')); + + return sprintf(">> %-${width}s %s", $this->format($section, 'INFO'), $this->excerpt($text, $size)); + } + + /** + * Truncates a line. + * + * @param string The text + * @param integer The maximum size of the returned string (65 by default) + * + * @return string The truncated string + */ + public function excerpt($text, $size = null) + { + if ( ! $size) { + $size = $this->size; + } + + if (strlen($text) < $size) { + return $text; + } + + $subsize = floor(($size - 3) / 2); + + return substr($text, 0, $subsize).$this->format('...', 'INFO').substr($text, -$subsize); + } + + /** + * Returns true if the stream supports colorization. + * + * Colorization is disabled if not supported by the stream: + * + * - windows + * - non tty consoles + * + * @param mixed A stream + * + * @return Boolean true if the stream supports colorization, false otherwise + */ + public function supportsColors($stream) + { + return DIRECTORY_SEPARATOR != '\\' && function_exists('posix_isatty') && @posix_isatty($stream); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Cli/Exception.php b/lib/Doctrine/TODO/Cli/Exception.php new file mode 100644 index 000000000..108275abb --- /dev/null +++ b/lib/Doctrine/TODO/Cli/Exception.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Cli_Exception + * + * @package Doctrine + * @subpackage Cli + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Cli_Exception extends Doctrine_Exception +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Cli/Formatter.php b/lib/Doctrine/TODO/Cli/Formatter.php new file mode 100644 index 000000000..469c53d47 --- /dev/null +++ b/lib/Doctrine/TODO/Cli/Formatter.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/* + * $Id: Formatter.php 2702 2007-10-03 21:43:22Z Jonathan.Wage $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER OR 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. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information, see + * . + */ + +/** + * Doctrine_Cli_Formatter provides methods to format text to be displayed on a console. + * + * @package Doctrine + * @subpackage Cli + * @author Fabien Potencier + * @version SVN: $Id: Doctrine_Cli_Formatter.class.php 5250 2007-09-24 08:11:50Z fabien $ + */ +class Doctrine_Cli_Formatter +{ + protected $_size = 65; + + /** + * __construct + * + * @param string $maxLineSize + * @return void + */ + function __construct($maxLineSize = 65) + { + $this->_size = $maxLineSize; + } + + /** + * Formats a text according to the given parameters. + * + * @param string The test to style + * @param mixed An array of parameters + * @param stream A stream (default to STDOUT) + * + * @return string The formatted text + */ + public function format($text = '', $parameters = array(), $stream = STDOUT) + { + return $text; + } + + /** + * Formats a message within a section. + * + * @param string The section name + * @param string The text message + * @param integer The maximum size allowed for a line (65 by default) + */ + public function formatSection($section, $text, $size = null) + { + return sprintf(">> %-$9s %s", $section, $this->excerpt($text, $size)); + } + + /** + * Truncates a line. + * + * @param string The text + * @param integer The maximum size of the returned string (65 by default) + * + * @return string The truncated string + */ + public function excerpt($text, $size = null) + { + if ( ! $size) { + $size = $this->_size; + } + + if (strlen($text) < $size) { + return $text; + } + + $subsize = floor(($size - 3) / 2); + + return substr($text, 0, $subsize).'...'.substr($text, -$subsize); + } + + /** + * Sets the maximum line size. + * + * @param integer The maximum line size for a message + */ + public function setMaxLineSize($size) + { + $this->_size = $size; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Data/Exception.php b/lib/Doctrine/TODO/Data/Exception.php new file mode 100644 index 000000000..05a4b8c1f --- /dev/null +++ b/lib/Doctrine/TODO/Data/Exception.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Data_Exception + * + * @package Doctrine + * @subpackage Data + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2552 $ + */ +class Doctrine_Data_Exception extends Doctrine_Exception +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Data/Export.php b/lib/Doctrine/TODO/Data/Export.php new file mode 100644 index 000000000..5d86ce1b4 --- /dev/null +++ b/lib/Doctrine/TODO/Data/Export.php @@ -0,0 +1,183 @@ +. + */ + +/** + * Doctrine_Data_Export + * + * @package Doctrine + * @subpackage Data + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2552 $ + */ +class Doctrine_Data_Export extends Doctrine_Data +{ + /** + * constructor + * + * @param string $directory + * @return void + */ + public function __construct($directory) + { + $this->setDirectory($directory); + } + + /** + * doExport + * + * @return void + */ + public function doExport() + { + $models = Doctrine::getLoadedModels(); + $specifiedModels = $this->getModels(); + + $data = array(); + + $outputAll = true; + + // for situation when the $models array is empty, but the $specifiedModels array isn't + if (empty($models)) { + $models = $specifiedModels; + } + + foreach ($models AS $name) { + + if ( ! empty($specifiedModels) AND !in_array($name, $specifiedModels)) { + continue; + } + + $class = new $name(); + $table = $class->getTable(); + $result = $table->findAll(); + + if ( ! empty($result)) { + $data[$name] = $result; + } + } + + $data = $this->prepareData($data); + + return $this->dumpData($data); + } + + /** + * dumpData + * + * Dump the prepared data to the fixtures files + * + * @param string $array + * @return void + */ + public function dumpData(array $data) + { + $directory = $this->getDirectory(); + $format = $this->getFormat(); + + if ($this->exportIndividualFiles()) { + + if (is_array($directory)) { + throw new Doctrine_Data_Exception('You must specify a single path to a folder in order to export individual files.'); + } else if ( ! is_dir($directory) && is_file($directory)) { + $directory = dirname($directory); + } + + foreach ($data as $className => $classData) { + if ( ! empty($classData)) { + Doctrine_Parser::dump(array($className => $classData), $format, $directory.DIRECTORY_SEPARATOR.$className.'.'.$format); + } + } + } else { + if (is_dir($directory)) { + $directory .= DIRECTORY_SEPARATOR . 'data.' . $format; + } + + if ( ! empty($data)) { + return Doctrine_Parser::dump($data, $format, $directory); + } + } + } + + /** + * prepareData + * + * Prepare the raw data to be exported with the parser + * + * @param string $data + * @return array + */ + public function prepareData($data) + { + $preparedData = array(); + + foreach ($data AS $className => $classData) { + + foreach ($classData as $record) { + $className = get_class($record); + $recordKey = $className . '_' . implode('_', $record->identifier()); + + $recordData = $record->toArray(); + + foreach ($recordData as $key => $value) { + if ( ! $value) { + continue; + } + + // skip single primary keys, we need to maintain composite primary keys + $keys = (array)$record->getTable()->getIdentifier(); + + if (count($keys) <= 1 && in_array($key, $keys)) { + continue; + } + + if ($relation = $this->isRelation($record, $key)) { + $relationAlias = $relation['alias']; + $relationRecord = $record->$relationAlias; + + // If collection then get first so we have an instance of the related record + if ($relationRecord instanceof Doctrine_Collection) { + $relationRecord = $relationRecord->getFirst(); + } + + // If relation is null or does not exist then continue + if ($relationRecord instanceof Doctrine_Null || !$relationRecord) { + continue; + } + + // Get class name for relation + $relationClassName = get_class($relationRecord); + + $relationValue = $relationClassName . '_' . $value; + + $preparedData[$className][$recordKey][$relationAlias] = $relationValue; + } else { + $preparedData[$className][$recordKey][$key] = $value; + } + } + } + } + + return $preparedData; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Data/Import.php b/lib/Doctrine/TODO/Data/Import.php new file mode 100644 index 000000000..482e29701 --- /dev/null +++ b/lib/Doctrine/TODO/Data/Import.php @@ -0,0 +1,380 @@ +. + */ + +/** + * Doctrine_Data_Import + * + * @package Doctrine + * @package Data + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2552 $ + */ +class Doctrine_Data_Import extends Doctrine_Data +{ + protected $_importedObjects = array(); + protected $_rows = array(); + + /** + * constructor + * + * @param string $directory + * @return void + */ + public function __construct($directory = null) + { + if ($directory !== null) { + $this->setDirectory($directory); + } + } + + /** + * doImport + * + * @return void + */ + public function doImport() + { + $directory = $this->getDirectory(); + + $array = array(); + + if ($directory !== null) { + foreach ((array) $directory as $dir) { + $e = explode('.', $dir); + + // If they specified a specific yml file + if (end($e) == 'yml') { + $array = array_merge($array, Doctrine_Parser::load($dir, $this->getFormat())); + // If they specified a directory + } else if(is_dir($dir)) { + $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), + RecursiveIteratorIterator::LEAVES_ONLY); + + foreach ($it as $file) { + $e = explode('.', $file->getFileName()); + if (in_array(end($e), $this->getFormats())) { + $array = array_merge($array, Doctrine_Parser::load($file->getPathName(), $this->getFormat())); + } + } + } + } + } + + $this->_loadData($array); + } + + protected function _buildRows($className, $data) + { + foreach ($data as $rowKey => $row) { + // do the same for the row information + $this->_rows[$className][$rowKey] = $row; + + foreach ($row as $key => $value) { + if (Doctrine::getTable($className)->hasRelation($key) && is_array($value)) { + $keys = array_keys($value); + + // Skip associative arrays defining keys to relationships + if (!isset($keys[0])) { + $this->_buildRows(Doctrine::getTable($className)->getRelation($key)->getTable()->getOption('name'), $value); + } + } + } + } + } + + protected function _buildNestedSetRows($className, $data) + { + foreach ($data as $rowKey => $row) { + $children = isset($row['children']) ? $row['children']:array(); + unset($row['children']); + $this->_rows[$className][$rowKey] = $row; + + $this->_buildNestedSetRows($className, $children); + } + } + + protected function _getImportedObject($rowKey) + { + if (isset($this->_importedObjects[$rowKey])) { + return $this->_importedObjects[$rowKey]; + } else { + throw new Doctrine_Data_Exception('Invalid row key specified: ' . $rowKey); + } + } + + protected function _processRow($rowKey, $row) + { + $obj = $this->_importedObjects[$rowKey]; + + foreach ($row as $key => $value) { + if ($obj->getTable()->hasField($key)) { + $obj->set($key, $value); + } else if (method_exists($obj, 'set' . Doctrine::classify($key))) { + $func = 'set' . Doctrine::classify($key); + $obj->$func($value); + } else if ($obj->getTable()->hasRelation($key)) { + if (is_array($value)) { + if (isset($value[0])) { + foreach ($value as $link) { + + if ($obj->getTable()->getRelation($key)->getType() === Doctrine_Relation::ONE) { + $obj->set($key, $this->_getImportedObject($link)); + } else if ($obj->getTable()->getRelation($key)->getType() === Doctrine_Relation::MANY) { + $relation = $obj->$key; + + $relation[] = $this->_getImportedObject($link); + } + } + } else { + $obj->$key->fromArray($value); + } + } else { + $obj->set($key, $this->_getImportedObject($value)); + } + } + } + } + + /** + * loadData + * + * @param string $array + * @return void + */ + protected function _loadData(array $array) + { + $nestedSets = array(); + + $specifiedModels = $this->getModels(); + $rows = array(); + + foreach ($array as $className => $data) { + + if ( ! empty($specifiedModels) && !in_array($className, $specifiedModels)) { + continue; + } + + // This is simple here to get the templates present for this model + // better way? + $obj = new $className(null, true); + $templates = array_keys($obj->getTable()->getBehaviors()); + + if (in_array('Doctrine_Template_NestedSet', $templates)) { + $nestedSets[$className][] = $data; + $this->_buildNestedSetRows($className, $data); + } else { + $this->_buildRows($className, $data); + } + } + + $buildRows = array(); + foreach ($this->_rows as $className => $classRows) { + foreach ($classRows as $rowKey => $row) { + $buildRows[$rowKey] = $row; + $this->_importedObjects[$rowKey] = new $className(); + } + } + + foreach($buildRows as $rowKey => $row) { + $this->_processRow($rowKey, $row); + } + + $objects = array(); + foreach ($this->_importedObjects as $object) { + $className = get_class($object); + $objects[$className] = $className; + } + + $manager = Doctrine_Manager::getInstance(); + foreach ($manager as $connection) { + $tree = $connection->unitOfWork->buildFlushTree($objects); + + foreach ($tree as $model) { + foreach ($this->_importedObjects as $obj) { + $templates = array_keys($obj->getTable()->getTemplates()); + + if ($obj instanceof $model && !in_array('Doctrine_Template_NestedSet', $templates)) { + $obj->save(); + } + } + } + } + + foreach ($nestedSets as $className => $sets) { + foreach ($sets as $data) { + $this->_loadNestedSetData($className, $data); + } + } + } + + protected function _loadNestedSetData($model, $nestedSetData, $parent = null) + { + $manager = Doctrine_Manager::getInstance(); + + foreach($nestedSetData AS $rowKey => $nestedSet) + { + $children = array(); + $data = array(); + + if( array_key_exists('children', $nestedSet) ) + { + $children = $nestedSet['children']; + $children = array_reverse($children, true); + unset($nestedSet['children']); + } + + $record = $this->_importedObjects[$rowKey]; + + if( !$parent ) + { + $manager->getTable($model)->getTree()->createRoot($record); + } else { + $parent->getNode()->addChild($record); + } + + if( is_array($children) AND !empty($children) ) + { + $this->_loadNestedSetData($model, $children, $record); + } + } + } + + /** + * doImportDummyData + * + * @param string $num + * @return void + */ + public function doImportDummyData($num = 3) + { + $models = Doctrine::getLoadedModels(); + + $specifiedModels = $this->getModels(); + + foreach ($models as $name) { + if ( ! empty($specifiedModels) && !in_array($name, $specifiedModels)) { + continue; + } + + for ($i = 0; $i < $num; $i++) { + $obj = new $name(); + + $this->populateDummyRecord($obj); + + $obj->save(); + + $ids[get_class($obj)][] = $obj->identifier(); + } + } + } + + public function populateDummyRecord(Doctrine_Entity $record) + { + $lorem = explode(' ', "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem + Ipsum has been the industry's standard dummy text ever since the 1500s, when an + unknown printer took a galley of type and scrambled it to make a type specimen book. + It has survived not only five centuries, but also the leap into electronic + typesetting, remaining essentially unchanged. It was popularised in the 1960s with + the release of Letraset sheets containing Lorem Ipsum passages, and more recently + with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."); + + $columns = array_keys($record->toArray()); + $pks = (array)$record->getTable()->getIdentifier(); + + foreach ($columns as $column) { + + if ( ! in_array($column, $pks)) { + if ($relation = $this->isRelation($record, $column)) { + $alias = $relation['alias']; + $relationObj = $record->$alias; + + $this->populateDummyRecord($relationObj); + + } else { + + $definition = $record->getTable()->getDefinitionOf($column); + + switch($definition['type']) + { + case 'string'; + shuffle($lorem); + + $record->$column = substr(implode(' ', $lorem), 0, $definition['length']); + break; + + case 'integer': + $record->$column = rand(); + break; + + case 'boolean': + $record->$column = true; + break; + + case 'float': + $record->$column = number_format(rand($definition['length'], $definition['length']), 2, '.', null); + break; + + case 'array': + $record->$column = array('test' => 'test'); + break; + + case 'object': + $record->$column = new stdObject(); + break; + + case 'blob': + $record->$column = ''; + break; + + case 'clob': + $record->$column = ''; + break; + + case 'timestamp': + $record->$column = date('Y-m-d h:i:s', time()); + break; + + case 'time': + $record->$column = date('h:i:s', time()); + break; + + case 'date': + $record->$column = date('Y-m-d', time()); + break; + + case 'enum': + $record->$column = 'test'; + break; + + case 'gzip': + $record->$column = 'test'; + break; + } + } + } + } + + return $record; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/File/Index.php b/lib/Doctrine/TODO/File/Index.php new file mode 100644 index 000000000..a0b302d3e --- /dev/null +++ b/lib/Doctrine/TODO/File/Index.php @@ -0,0 +1,56 @@ +. + */ + +/** + * Doctrine_File_Index + * + * @package Doctrine + * @subpackage File + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_File_Index extends Doctrine_Entity +{ + public function setTableDefinition() + { + $this->hasColumn('keyword', 'string', 255, array('notnull' => true, + 'primary' => true)); + + $this->hasColumn('field', 'string', 50, array('notnull' => true, + 'primary' => true)); + + $this->hasColumn('position', 'string', 255, array('notnull' => true, + 'primary' => true)); + + $this->hasColumn('file_id', 'integer', 8, array('notnull' => true, + 'primary' => true)); + } + public function setUp() + { + $this->hasOne('Doctrine_File', array('local' => 'file_id', + 'foreign' => 'id', + 'onDelete' => 'CASCADE', + 'onUpdate' => 'CASCADE')); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/FileFinder/GlobToRegex.php b/lib/Doctrine/TODO/FileFinder/GlobToRegex.php new file mode 100644 index 000000000..8ec65312f --- /dev/null +++ b/lib/Doctrine/TODO/FileFinder/GlobToRegex.php @@ -0,0 +1,127 @@ +. + */ + +/** + * Doctrine_FileFinder_GlobToRegex + * + * Match globbing patterns against text. + * + * if match_glob("foo.*", "foo.bar") echo "matched\n"; + * + * // prints foo.bar and foo.baz + * $regex = globToRegex("foo.*"); + * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t) + * { + * if (/$regex/) echo "matched: $car\n"; + * } + * + * Doctrine_FileFinder_GlobToRegex implements glob(3) style matching that can be used to match + * against text, rather than fetching names from a filesystem. + * + * based on perl Text::Glob module. + * + * @package Doctrine + * @subpackage FileFinder + * @author Fabien Potencier php port + * @author Richard Clamp perl version + * @copyright 2004-2005 Fabien Potencier + * @copyright 2002 Richard Clamp + * @version SVN: $Id: Doctrine_FileFinder.class.php 5110 2007-09-15 12:07:18Z fabien $ + */ +class Doctrine_FileFinder_GlobToRegex +{ + protected static $strictLeadingDot = true; + protected static $strictWildcardSlash = true; + + public static function setStrictLeadingDot($boolean) + { + self::$strictLeadingDot = $boolean; + } + + public static function setStrictWildcardSlash($boolean) + { + self::$strictWildcardSlash = $boolean; + } + + /** + * Returns a compiled regex which is the equiavlent of the globbing pattern. + * + * @param string glob pattern + * @return string regex + */ + public static function globToRegex($glob) + { + $firstByte = true; + $escaping = false; + $inCurlies = 0; + $regex = ''; + for ($i = 0; $i < strlen($glob); $i++) { + $car = $glob[$i]; + if ($firstByte) { + if (self::$strictLeadingDot && $car != '.') { + $regex .= '(?=[^\.])'; + } + + $firstByte = false; + } + + if ($car == '/') { + $firstByte = true; + } + + if ($car == '.' || $car == '(' || $car == ')' || $car == '|' || $car == '+' || $car == '^' || $car == '$') { + $regex .= "\\$car"; + } else if ($car == '*') { + $regex .= ($escaping ? "\\*" : (self::$strictWildcardSlash ? "[^/]*" : ".*")); + } else if ($car == '?') { + $regex .= ($escaping ? "\\?" : (self::$strictWildcardSlash ? "[^/]" : ".")); + } else if ($car == '{') { + $regex .= ($escaping ? "\\{" : "("); + if ( ! $escaping) { + ++$inCurlies; + } + } else if ($car == '}' && $inCurlies) { + $regex .= ($escaping ? "}" : ")"); + if ( ! $escaping) { + --$inCurlies; + } + } else if ($car == ',' && $inCurlies) { + $regex .= ($escaping ? "," : "|"); + } else if ($car == "\\") { + if ($escaping) { + $regex .= "\\\\"; + $escaping = false; + } else { + $escaping = true; + } + + continue; + } else { + $regex .= $car; + $escaping = false; + } + + $escaping = false; + } + + return "#^$regex$#"; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/FileFinder/NumberCompare.php b/lib/Doctrine/TODO/FileFinder/NumberCompare.php new file mode 100644 index 000000000..ab435dc76 --- /dev/null +++ b/lib/Doctrine/TODO/FileFinder/NumberCompare.php @@ -0,0 +1,106 @@ +. + */ + +/** + * Doctrine_FileFinder_NumberCompare + * + * Numeric comparisons. + * + * Doctrine_FileFinder_NumberCompare compiles a simple comparison to an anonymous + * subroutine, which you can call with a value to be tested again. + * + * Now this would be very pointless, if Doctrine_FileFinder_NumberCompare didn't understand + * magnitudes. + * + * The target value may use magnitudes of kilobytes (k, ki), + * megabytes (m, mi), or gigabytes (g, gi). Those suffixed + * with an i use the appropriate 2**n version in accordance with the + * IEC standard: http://physics.nist.gov/cuu/Units/binary.html + * + * based on perl Number::Compare module. + * + * @package Doctrine + * @subpackage FileFinder + * @author Fabien Potencier php port + * @author Richard Clamp perl version + * @copyright 2004-2005 Fabien Potencier + * @copyright 2002 Richard Clamp + * @see http://physics.nist.gov/cuu/Units/binary.html + * @version SVN: $Id: Doctrine_FileFinder.class.php 5110 2007-09-15 12:07:18Z fabien $ + */ +class Doctrine_FileFinder_NumberCompare +{ + protected $test = ''; + + public function __construct($test) + { + $this->test = $test; + } + + public function test($number) + { + if ( ! preg_match('{^([<>]=?)?(.*?)([kmg]i?)?$}i', $this->test, $matches)) { + throw new Doctrine_Exception(sprintf('don\'t understand "%s" as a test.', $this->test)); + } + + $target = array_key_exists(2, $matches) ? $matches[2] : ''; + $magnitude = array_key_exists(3, $matches) ? $matches[3] : ''; + if (strtolower($magnitude) == 'k') { + $target *= 1000; + } + + if (strtolower($magnitude) == 'ki') { + $target *= 1024; + } + + if (strtolower($magnitude) == 'm') { + $target *= 1000000; + } + + if (strtolower($magnitude) == 'mi') { + $target *= 1024*1024; + } + + if (strtolower($magnitude) == 'g') { + $target *= 1000000000; + } + + if (strtolower($magnitude) == 'gi') { + $target *= 1024*1024*1024; + } + + $comparison = array_key_exists(1, $matches) ? $matches[1] : '=='; + + if ($comparison == '==' || $comparison == '') { + return ($number == $target); + } else if ($comparison == '>') { + return ($number > $target); + } else if ($comparison == '>=') { + return ($number >= $target); + } else if ($comparison == '<') { + return ($number < $target); + } else if ($comparison == '<=') { + return ($number <= $target); + } + + return false; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/I18n/Exception.php b/lib/Doctrine/TODO/I18n/Exception.php new file mode 100644 index 000000000..cb5abd460 --- /dev/null +++ b/lib/Doctrine/TODO/I18n/Exception.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_I18n_Exception + * + * @package Doctrine + * @subpackage I18n + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + * @author Konsta Vesterinen + */ +class Doctrine_I18n_Exception extends Doctrine_Exception +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Log/Exception.php b/lib/Doctrine/TODO/Log/Exception.php new file mode 100755 index 000000000..bb62d9099 --- /dev/null +++ b/lib/Doctrine/TODO/Log/Exception.php @@ -0,0 +1,34 @@ +. + */ + +/** + * @category Doctrine + * @package Log + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3155 $ + */ +class Doctrine_Log_Exception extends Doctrine_Exception +{ + +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Log/Filter/Interface.php b/lib/Doctrine/TODO/Log/Filter/Interface.php new file mode 100644 index 000000000..43a1bd6d9 --- /dev/null +++ b/lib/Doctrine/TODO/Log/Filter/Interface.php @@ -0,0 +1,41 @@ +. + */ + +/** + * @package Doctrine + * @subpackage Log + * @author Konsta Vesterinen + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3155 $ + */ +interface Doctrine_Log_Filter_Interface +{ + /** + * Returns TRUE to accept the message, FALSE to block it. + * + * @param array $event event data + * @return boolean accepted? + */ + public function accept($event); +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Log/Filter/Message.php b/lib/Doctrine/TODO/Log/Filter/Message.php new file mode 100644 index 000000000..4a9f97aac --- /dev/null +++ b/lib/Doctrine/TODO/Log/Filter/Message.php @@ -0,0 +1,64 @@ +. + */ + +/** + * @package Doctrine + * @subpackage Log + * @author Konsta Vesterinen + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3155 $ + */ +class Doctrine_Log_Filter_Message implements Doctrine_Log_Filter_Interface +{ + /** + * @var string + */ + protected $_regexp; + + /** + * Filter out any log messages not matching $regexp. + * + * @param string $regexp Regular expression to test the log message + * @throws Doctrine_Log_Exception + */ + public function __construct($regexp) + { + if (@preg_match($regexp, '') === false) { + throw new Doctrine_Log_Exception("Invalid regular expression '$regexp'"); + } + $this->_regexp = $regexp; + } + + /** + * Returns TRUE to accept the message, FALSE to block it. + * + * @param array $event event data + * @return boolean accepted? + */ + public function accept($event) + { + return preg_match($this->_regexp, $event['message']) > 0; + } + +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Log/Filter/Priority.php b/lib/Doctrine/TODO/Log/Filter/Priority.php new file mode 100644 index 000000000..e51d75a04 --- /dev/null +++ b/lib/Doctrine/TODO/Log/Filter/Priority.php @@ -0,0 +1,72 @@ +. + */ + +/** + * @package Doctrine + * @subpackage Log + * @author Konsta Vesterinen + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3155 $ + */ +class Doctrine_Log_Filter_Priority implements Doctrine_Log_Filter_Interface +{ + /** + * @var integer + */ + protected $_priority; + + /** + * @var string + */ + protected $_operator; + + /** + * Filter logging by $priority. By default, it will accept any log + * event whose priority value is less than or equal to $priority. + * + * @param integer $priority Priority + * @param string $operator Comparison operator + * @throws Doctrine_Log_Exception + */ + public function __construct($priority, $operator = '<=') + { + if (! is_integer($priority)) { + throw new Doctrine_Log_Exception('Priority must be an integer'); + } + + $this->_priority = $priority; + $this->_operator = $operator; + } + + /** + * Returns TRUE to accept the message, FALSE to block it. + * + * @param array $event event data + * @return boolean accepted? + */ + public function accept($event) + { + return version_compare($event['priority'], $this->_priority, $this->_operator); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Log/Filter/Suppress.php b/lib/Doctrine/TODO/Log/Filter/Suppress.php new file mode 100644 index 000000000..fc801dd8e --- /dev/null +++ b/lib/Doctrine/TODO/Log/Filter/Suppress.php @@ -0,0 +1,63 @@ +. + */ + +/** + * @package Doctrine + * @subpackage Log + * @author Konsta Vesterinen + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3155 $ + */ +class Doctrine_Log_Filter_Suppress implements Doctrine_Log_Filter_Interface +{ + /** + * @var boolean + */ + protected $_accept = true; + + /** + * This is a simple boolean filter. + * + * Call suppress(true) to suppress all log events. + * Call suppress(false) to accept all log events. + * + * @param boolean $suppress Should all log events be suppressed? + * @return void + */ + public function suppress($suppress) + { + $this->_accept = (! $suppress); + } + + /** + * Returns TRUE to accept the message, FALSE to block it. + * + * @param array $event event data + * @return boolean accepted? + */ + public function accept($event) + { + return $this->_accept; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Log/Formatter/Interface.php b/lib/Doctrine/TODO/Log/Formatter/Interface.php new file mode 100644 index 000000000..5a8494227 --- /dev/null +++ b/lib/Doctrine/TODO/Log/Formatter/Interface.php @@ -0,0 +1,41 @@ +. + */ + +/** + * @package Doctrine + * @subpackage Log + * @author Konsta Vesterinen + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3155 $ + */ +interface Doctrine_Log_Formatter_Interface +{ + /** + * Formats data into a single line to be written by the writer. + * + * @param array $event event data + * @return string formatted line to write to the log + */ + public function format($event); +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Log/Formatter/Simple.php b/lib/Doctrine/TODO/Log/Formatter/Simple.php new file mode 100644 index 000000000..b14ccff41 --- /dev/null +++ b/lib/Doctrine/TODO/Log/Formatter/Simple.php @@ -0,0 +1,72 @@ +. + */ + +/** + * @package Doctrine + * @subpackage Log + * @author Konsta Vesterinen + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3155 $ + */ +class Doctrine_Log_Formatter_Simple implements Doctrine_Log_Formatter_Interface +{ + /** + * @var string + */ + protected $_format; + + /** + * Class constructor + * + * @param null|string $format Format specifier for log messages + * @throws Doctrine_Log_Exception + */ + public function __construct($format = null) + { + if ($format === null) { + $format = '%timestamp% %priorityName% (%priority%): %message%' . PHP_EOL; + } + + if (! is_string($format)) { + throw new Doctrine_Log_Exception('Format must be a string'); + } + + $this->_format = $format; + } + + /** + * Formats data into a single line to be written by the writer. + * + * @param array $event event data + * @return string formatted line to write to the log + */ + public function format($event) + { + $output = $this->_format; + foreach ($event as $name => $value) { + $output = str_replace("%$name%", $value, $output); + } + return $output; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Log/Formatter/Xml.php b/lib/Doctrine/TODO/Log/Formatter/Xml.php new file mode 100644 index 000000000..424f849d1 --- /dev/null +++ b/lib/Doctrine/TODO/Log/Formatter/Xml.php @@ -0,0 +1,84 @@ +. + */ + +/** + * @package Doctrine + * @subpackage Log + * @author Konsta Vesterinen + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3155 $ + */ +class Doctrine_Log_Formatter_Xml implements Doctrine_Log_Formatter_Interface +{ + /** + * @var Relates XML elements to log data field keys. + */ + protected $_rootElement; + + /** + * @var Relates XML elements to log data field keys. + */ + protected $_elementMap; + + /** + * Class constructor + * + * @param array $elementMap + */ + public function __construct($rootElement = 'logEntry', $elementMap = null) + { + $this->_rootElement = $rootElement; + $this->_elementMap = $elementMap; + } + + /** + * Formats data into a single line to be written by the writer. + * + * @param array $event event data + * @return string formatted line to write to the log + */ + public function format($event) + { + if ($this->_elementMap === null) { + $dataToInsert = $event; + } else { + $dataToInsert = array(); + foreach ($this->_elementMap as $elementName => $fieldKey) { + $dataToInsert[$elementName] = $event[$fieldKey]; + } + } + + $dom = new DOMDocument(); + $elt = $dom->appendChild(new DOMElement($this->_rootElement)); + + foreach ($dataToInsert as $key => $value) { + $elt->appendChild(new DOMElement($key, $value)); + } + + $xml = $dom->saveXML(); + $xml = preg_replace('/<\?xml version="1.0"( encoding="[^\"]*")?\?>\n/u', '', $xml); + + return $xml . PHP_EOL; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Log/Writer/Abstract.php b/lib/Doctrine/TODO/Log/Writer/Abstract.php new file mode 100644 index 000000000..7b83538c8 --- /dev/null +++ b/lib/Doctrine/TODO/Log/Writer/Abstract.php @@ -0,0 +1,103 @@ +. + */ + +/** + * @package Doctrine + * @subpackage Log + * @author Konsta Vesterinen + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3155 $ + */ +abstract class Doctrine_Log_Writer_Abstract +{ + /** + * @var array of Doctrine_Log_Filter_Interface + */ + protected $_filters = array(); + + /** + * Formats the log message before writing. + * @var Doctrine_Log_Formatter_Interface + */ + protected $_formatter; + + /** + * Add a filter specific to this writer. + * + * @param Doctrine_Log_Filter_Interface $filter + * @return void + */ + public function addFilter($filter) + { + if (is_integer($filter)) { + $filter = new Doctrine_Log_Filter_Priority($filter); + } + + $this->_filters[] = $filter; + } + + /** + * Log a message to this writer. + * + * @param array $event log data event + * @return void + */ + public function write($event) + { + foreach ($this->_filters as $filter) { + if (! $filter->accept($event)) { + return; + } + } + + // exception occurs on error + $this->_write($event); + } + + /** + * Set a new formatter for this writer + * + * @param Doctrine_Log_Formatter_Interface $formatter + * @return void + */ + public function setFormatter($formatter) { + $this->_formatter = $formatter; + } + + /** + * Perform shutdown activites such as closing open resources + * + * @return void + */ + public function shutdown() + {} + + /** + * Write a message to the log. + * + * @param array $event log data event + * @return void + */ + abstract protected function _write($event); +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Log/Writer/Db.php b/lib/Doctrine/TODO/Log/Writer/Db.php new file mode 100644 index 000000000..88f52e087 --- /dev/null +++ b/lib/Doctrine/TODO/Log/Writer/Db.php @@ -0,0 +1,107 @@ +. + */ + +/** + * @package Doctrine + * @subpackage Log + * @author Konsta Vesterinen + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3155 $ + */ +class Doctrine_Log_Writer_Db extends Doctrine_Log_Writer_Abstract +{ + /** + * Doctrine_Table instance + * + * @var string + */ + private $_table; + + /** + * Relates database columns names to log data field keys. + * + * @var null|array + */ + private $_columnMap; + + /** + * Class constructor + * + * @param Doctrine_Db_Adapter $db Database adapter instance + * @param string $table Log table in database + * @param array $columnMap + */ + public function __construct($table, $columnMap = null) + { + if (!$table instanceof Doctrine_Table) { + $table = Doctrine::getTable($table); + } + + $this->_table = $table; + $this->_columnMap = $columnMap; + } + + /** + * Formatting is not possible on this writer + */ + public function setFormatter($formatter) + { + throw new Doctrine_Log_Exception(get_class() . ' does not support formatting'); + } + + /** + * Remove reference to database adapter + * + * @return void + */ + public function shutdown() + { + $this->_table = null; + } + + /** + * Write a message to the log. + * + * @param array $event event data + * @return void + */ + protected function _write($event) + { + if ($this->_table === null) { + throw new Doctrine_Log_Exception('Database adapter instance has been removed by shutdown'); + } + + if ($this->_columnMap === null) { + $dataToInsert = $event; + } else { + $dataToInsert = array(); + foreach ($this->_columnMap as $columnName => $fieldKey) { + $dataToInsert[$columnName] = $event[$fieldKey]; + } + } + + $record = $this->_table->create($dataToInsert); + $record->save(); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Log/Writer/Mock.php b/lib/Doctrine/TODO/Log/Writer/Mock.php new file mode 100644 index 000000000..e174f2c18 --- /dev/null +++ b/lib/Doctrine/TODO/Log/Writer/Mock.php @@ -0,0 +1,64 @@ +. + */ + +/** + * @package Doctrine + * @subpackage Log + * @author Konsta Vesterinen + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3155 $ + */ +class Doctrine_Log_Writer_Mock extends Doctrine_Log_Writer_Abstract +{ + /** + * array of log events + */ + public $events = array(); + + /** + * shutdown called? + */ + public $shutdown = false; + + /** + * Write a message to the log. + * + * @param array $event event data + * @return void + */ + public function _write($event) + { + $this->events[] = $event; + } + + /** + * Record shutdown + * + * @return void + */ + public function shutdown() + { + $this->shutdown = true; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Log/Writer/Null.php b/lib/Doctrine/TODO/Log/Writer/Null.php new file mode 100644 index 000000000..02083b63d --- /dev/null +++ b/lib/Doctrine/TODO/Log/Writer/Null.php @@ -0,0 +1,43 @@ +. + */ + +/** + * @package Doctrine + * @subpackage Log + * @author Konsta Vesterinen + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3155 $ + */ +class Doctrine_Log_Writer_Null extends Doctrine_Log_Writer_Abstract +{ + /** + * Write a message to the log. + * + * @param array $event event data + * @return void + */ + protected function _write($event) + { + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Log/Writer/Stream.php b/lib/Doctrine/TODO/Log/Writer/Stream.php new file mode 100644 index 000000000..510eea8a4 --- /dev/null +++ b/lib/Doctrine/TODO/Log/Writer/Stream.php @@ -0,0 +1,94 @@ +. + */ + +/** + * @package Doctrine + * @subpackage Log + * @author Konsta Vesterinen + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3155 $ + */ +class Doctrine_Log_Writer_Stream extends Doctrine_Log_Writer_Abstract +{ + /** + * Holds the PHP stream to log to. + * @var null|stream + */ + protected $_stream = null; + + /** + * Class Constructor + * + * @param streamOrUrl Stream or URL to open as a stream + * @param mode Mode, only applicable if a URL is given + */ + public function __construct($streamOrUrl, $mode = 'a') + { + if (is_resource($streamOrUrl)) { + if (get_resource_type($streamOrUrl) != 'stream') { + throw new Doctrine_Log_Exception('Resource is not a stream'); + } + + if ($mode != 'a') { + throw new Doctrine_Log_Exception('Mode cannot be changed on existing streams'); + } + + $this->_stream = $streamOrUrl; + } else { + if (! $this->_stream = @fopen($streamOrUrl, $mode, false)) { + $msg = "\"$streamOrUrl\" cannot be opened with mode \"$mode\""; + throw new Doctrine_Log_Exception($msg); + } + } + + $this->_formatter = new Doctrine_Log_Formatter_Simple(); + } + + /** + * Close the stream resource. + * + * @return void + */ + public function shutdown() + { + if (is_resource($this->_stream)) { + fclose($this->_stream); + } + } + + /** + * Write a message to the log. + * + * @param array $event event data + * @return void + */ + protected function _write($event) + { + $line = $this->_formatter->format($event); + + if (false === @fwrite($this->_stream, $line)) { + throw new Doctrine_Log_Exception("Unable to write to stream"); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Migration/Diff.php b/lib/Doctrine/TODO/Migration/Diff.php new file mode 100644 index 000000000..81bde94ab --- /dev/null +++ b/lib/Doctrine/TODO/Migration/Diff.php @@ -0,0 +1,155 @@ +. + */ + +/** + * Doctrine_Migration_Diff + * + * @package Doctrine + * @subpackage Migration + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 1080 $ + * @author Jonathan H. Wage + */ +class Doctrine_Migration_Diff +{ + protected $_from, + $_to, + $_changes = array(), + $_migrationsPath; + + public function __construct($from = null, $to = null) + { + $this->_from = $from; + $this->_to = $to; + } + + protected function getUniqueId() + { + return md5($this->_from.$this->_to); + } + + public function setMigrationsPath($migrationsPath) + { + $this->_migrationsPath = $migrationsPath; + } + + public function generate() + { + $from = $this->_generateModels('From', $this->_from); + $to = $this->_generateModels('To', $this->_to); + + $differences = $this->_diff($from, $to); + + print_r($differences); + } + + protected function _diff($from, $to) + { + $fromTmpPath = sys_get_temp_dir() . $this->getUniqueId() . '_from'; + $toTmpPath = sys_get_temp_dir() . $this->getUniqueId() . '_to'; + + if ( ! file_exists($fromTmpPath)) { + $fromModels = Doctrine::loadModels($from); + $fromInfo = $this->_buildModelInformation($fromModels); + + file_put_contents($fromTmpPath, serialize($fromInfo)); + } else { + if ( ! file_exists($toTmpPath)) { + $toModels = Doctrine::loadModels($to); + $toInfo = $this->_buildModelInformation($toModels); + + file_put_contents($toTmpPath, serialize($toInfo)); + } else { + $fromInfo = unserialize(file_get_contents($fromTmpPath)); + $toInfo = unserialize(file_get_contents($toTmpPath)); + + $this->_buildChanges($fromInfo, $toInfo); + + // clean up + unlink($fromTmpPath); + unlink($toTmpPath); + Doctrine_Lib::removeDirectories(sys_get_temp_dir() . 'from_doctrine_tmp_dirs'); + Doctrine_Lib::removeDirectories(sys_get_temp_dir() . 'to_doctrine_tmp_dirs'); + } + } + } + + protected function _buildChanges($from, $to) + { + foreach ($to as $key => $model) { + $columns = $model['columns']; + + foreach ($columns as $columnKey => $column) { + //if (isset($to[$key]['columns'][$columnKey])) + } + } + } + + protected function _buildModelInformation(array $models) + { + $info = array(); + + foreach ($models as $key => $model) { + $info[$model] = Doctrine::getTable($model)->getExportableFormat(); + } + + return $info; + } + + protected function _generateModels($prefix, $item) + { + $path = sys_get_temp_dir() . $prefix . '_doctrine_tmp_dirs'; + + if ( is_dir($item)) { + $files = glob($item . DIRECTORY_SEPARATOR . '*.*'); + + if (isset($files[0])) { + $pathInfo = pathinfo($files[0]); + $extension = $pathInfo['extension']; + } + + if ($extension === 'yml') { + Doctrine::generateModelsFromYaml($item, $path); + + return $path; + } else if ($extension === 'php') { + + Doctrine_Lib::copyDirectory($item, $path); + + return $path; + } else { + throw new Doctrine_Migration_Exception('No php or yml files found at path: "' . $item . '"'); + } + } else { + try { + $connection = Doctrine_Manager::getInstance()->getConnection($item); + + Doctrine::generateModelsFromDb($path, array($item)); + + return $path; + } catch (Exception $e) { + throw new Doctrine_Migration_Exception('Could not generate models from connection: ' . $e->getMessage()); + } + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Migration/Exception.php b/lib/Doctrine/TODO/Migration/Exception.php new file mode 100644 index 000000000..9780241d0 --- /dev/null +++ b/lib/Doctrine/TODO/Migration/Exception.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Migration_Exception + * + * @package Doctrine + * @subpackage Migration + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 1080 $ + * @author Jonathan H. Wage + */ +class Doctrine_Migration_Exception extends Doctrine_Exception +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Migration/IrreversibleMigrationException.php b/lib/Doctrine/TODO/Migration/IrreversibleMigrationException.php new file mode 100644 index 000000000..14d5785bf --- /dev/null +++ b/lib/Doctrine/TODO/Migration/IrreversibleMigrationException.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Migration_IrreversibleMigration + * + * @package Doctrine + * @subpackage Migration + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 1080 $ + * @author Jonathan H. Wage + */ +class Doctrine_Migration_IrreversibleMigrationException extends Doctrine_Migration_Exception +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Migration/Process.php b/lib/Doctrine/TODO/Migration/Process.php new file mode 100644 index 000000000..58a552936 --- /dev/null +++ b/lib/Doctrine/TODO/Migration/Process.php @@ -0,0 +1,251 @@ +. + */ + +/** + * Doctrine_Migration_Process + * + * @package Doctrine + * @subpackage Migration + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 1080 $ + * @author Jonathan H. Wage + */ +class Doctrine_Migration_Process +{ + /** + * getConnection + * + * @param string $tableName + * @return void + */ + public function getConnection($tableName) + { + return Doctrine::getConnectionByTableName($tableName); + } + + /** + * processCreatedTables + * + * @param string $tables + * @return void + */ + public function processCreatedTables($tables) + { + foreach ($tables as $table) { + $conn = $this->getConnection($table['tableName']); + + $conn->export->createTable($table['tableName'], $table['fields'], $table['options']); + } + } + + /** + * processDroppedTables + * + * @param string $tables + * @return void + */ + public function processDroppedTables($tables) + { + foreach ($tables as $table) { + $conn = $this->getConnection($table['tableName']); + + $conn->export->dropTable($table['tableName']); + } + } + + /** + * processRenamedTables + * + * @param string $tables + * @return void + */ + public function processRenamedTables($tables) + { + foreach ($tables as $table) { + $conn = $this->getConnection($table['newTableName']); + + $conn->export->alterTable($table['oldTableName'], array('name' => $table['newTableName'])); + } + } + + /** + * processAddedColumns + * + * @param string $columns + * @return void + */ + public function processAddedColumns($columns) + { + foreach ($columns as $column) { + $conn = $this->getConnection($column['tableName']); + + $options = array(); + $options = $column['options']; + $options['type'] = $column['type']; + + $conn->export->alterTable($column['tableName'], array('add' => array($column['columnName'] => $options))); + } + } + + /** + * processRenamedColumns + * + * @param string $columns + * @return void + */ + public function processRenamedColumns($columns) + { + foreach ($columns as $column) { + $conn = $this->getConnection($column['tableName']); + + $columnList = $conn->import->listTableColumns($column['tableName']); + if (isset($columnList[$column['oldColumnName']])) { + $conn->export->alterTable($column['tableName'], + array('rename' => array($column['oldColumnName'] => array('name' => $column['newColumnName'], + 'definition'=>$columnList[$column['oldColumnName']])))); + } + } + } + + /** + * processChangedColumns + * + * @param string $columns + * @return void + */ + public function processChangedColumns($columns) + { + foreach ($columns as $column) { + $conn = $this->getConnection($column['tableName']); + + $options = array(); + $options = $column['options']; + $options['type'] = $column['type']; + + $conn->export->alterTable($column['tableName'], array('change' => array($column['columnName'] => array('definition' => $options)))); + } + } + + /** + * processRemovedColumns + * + * @param string $columns + * @return void + */ + public function processRemovedColumns($columns) + { + foreach ($columns as $column) { + $conn = $this->getConnection($column['tableName']); + + $conn->export->alterTable($column['tableName'], array('remove' => array($column['columnName'] => array()))); + } + } + + /** + * processAddexIndexes + * + * @param string $indexes + * @return void + */ + public function processAddedIndexes($indexes) + { + foreach ($indexes as $index) { + $conn = $this->getConnection($index['tableName']); + + $conn->export->createIndex($index['tableName'], $index['indexName'], $index['definition']); + } + } + + /** + * processRemovedIndexes + * + * @param string $indexes + * @return void + */ + public function processRemovedIndexes($indexes) + { + foreach ($indexes as $index) { + $conn = $this->getConnection($index['tableName']); + + $conn->export->dropIndex($index['tableName'], $index['indexName']); + } + } + + /** + * processCreatedConstraints + * + * @param string $constraints + * @return void + */ + public function processCreatedConstraints($constraints) + { + foreach ($constraints as $constraint) { + $conn = $this->getConnection($constraint['tableName']); + $conn->export->createConstraint($constraint['tableName'], $constraint['constraintName'], + $constraint['definition']); + } + } + + /** + * processDroppedConstraints + * + * @param string $constraints + * @return void + */ + public function processDroppedConstraints($constraints) + { + foreach ($constraints as $constraint) { + $conn = $this->getConnection($constraint['tableName']); + $conn->export->dropConstraint($constraint['tableName'], $constraint['constraintName'], + $constraint['primary']); + } + } + + /** + * processCreatedFks + * + * @param string $foreignKeys + * @return void + */ + public function processCreatedFks($foreignKeys) + { + foreach ($foreignKeys as $fk) { + $conn = $this->getConnection($fk['tableName']); + $conn->export->createForeignKey($fk['tableName'], $fk['definition']); + } + } + + /** + * processDroppedFks + * + * @param string $foreignKeys + * @return void + */ + public function processDroppedFks($foreignKeys) + { + foreach ($foreignKeys as $fk) { + $conn = $this->getConnection($fk['tableName']); + $conn->export->dropForeignKey($fk['tableName'], $fk['fkName']); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/AdjacencyList.php b/lib/Doctrine/TODO/Node/AdjacencyList.php new file mode 100644 index 000000000..ff091e720 --- /dev/null +++ b/lib/Doctrine/TODO/Node/AdjacencyList.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Node_AdjacencyList + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Joe Simms + */ +abstract class Doctrine_Node_AdjacencyList extends Doctrine_Node implements Doctrine_Node_Interface +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/AdjacencyList/LevelOrderIterator.php b/lib/Doctrine/TODO/Node/AdjacencyList/LevelOrderIterator.php new file mode 100644 index 000000000..c8d73bb7b --- /dev/null +++ b/lib/Doctrine/TODO/Node/AdjacencyList/LevelOrderIterator.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Node_AdjacencyList_LevelOrderIterator + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Joe Simms + */ +abstract class Doctrine_Node_AdjacencyList_LevelOrderIterator implements Iterator +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/AdjacencyList/PostOrderIterator.php b/lib/Doctrine/TODO/Node/AdjacencyList/PostOrderIterator.php new file mode 100644 index 000000000..bb56e79a5 --- /dev/null +++ b/lib/Doctrine/TODO/Node/AdjacencyList/PostOrderIterator.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Node_AdjacencyList_PostOrderIterator + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Joe Simms + */ +abstract class Doctrine_Node_AdjacencyList_PostOrderIterator implements Iterator +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/AdjacencyList/PreOrderIterator.php b/lib/Doctrine/TODO/Node/AdjacencyList/PreOrderIterator.php new file mode 100644 index 000000000..5d031fffc --- /dev/null +++ b/lib/Doctrine/TODO/Node/AdjacencyList/PreOrderIterator.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Node_AdjacencyList_PreOrderIterator + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Joe Simms + */ +abstract class Doctrine_Node_AdjacencyList_PreOrderIterator implements Iterator +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/Exception.php b/lib/Doctrine/TODO/Node/Exception.php new file mode 100644 index 000000000..a16bc1847 --- /dev/null +++ b/lib/Doctrine/TODO/Node/Exception.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Node_Exception + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Joe Simms + */ +class Doctrine_Node_Exception extends Doctrine_Exception +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/Interface.php b/lib/Doctrine/TODO/Node/Interface.php new file mode 100644 index 000000000..72ebeef05 --- /dev/null +++ b/lib/Doctrine/TODO/Node/Interface.php @@ -0,0 +1,268 @@ +. + */ + +/** + * Doctrine_Node_Interface + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 4364 $ + * @author Joe Simms + */ +interface Doctrine_Node_Interface { + + /** + * test if node has previous sibling + * + * @return bool + */ + public function hasPrevSibling(); + + /** + * test if node has next sibling + * + * @return bool + */ + public function hasNextSibling(); + + /** + * test if node has children + * + * @return bool + */ + public function hasChildren(); + + /** + * test if node has parent + * + * @return bool + */ + public function hasParent(); + + /** + * gets record of prev sibling or empty record + * + * @return object Doctrine_Entity + */ + public function getPrevSibling(); + + /** + * gets record of next sibling or empty record + * + * @return object Doctrine_Entity + */ + public function getNextSibling(); + + /** + * gets siblings for node + * + * @return array array of sibling Doctrine_Entity objects + */ + public function getSiblings($includeNode = false); + + /** + * gets record of first child or empty record + * + * @return object Doctrine_Entity + */ + public function getFirstChild(); + + /** + * gets record of last child or empty record + * + * @return object Doctrine_Entity + */ + public function getLastChild(); + + /** + * gets children for node (direct descendants only) + * + * @return array array of sibling Doctrine_Entity objects + */ + public function getChildren(); + + /** + * gets descendants for node (direct descendants only) + * + * @return iterator iterator to traverse descendants from node + */ + public function getDescendants(); + + /** + * gets record of parent or empty record + * + * @return object Doctrine_Entity + */ + public function getParent(); + + /** + * gets ancestors for node + * + * @return object Doctrine_Collection + */ + public function getAncestors(); + + /** + * gets path to node from root, uses record::toString() method to get node names + * + * @param string $seperator path seperator + * @param bool $includeNode whether or not to include node at end of path + * @return string string representation of path + */ + public function getPath($seperator = ' > ', $includeNode = false); + + /** + * gets level (depth) of node in the tree + * + * @return int + */ + public function getLevel(); + + /** + * gets number of children (direct descendants) + * + * @return int + */ + public function getNumberChildren(); + + /** + * gets number of descendants (children and their children) + * + * @return int + */ + public function getNumberDescendants(); + + /** + * inserts node as parent of dest record + * + * @return bool + */ + public function insertAsParentOf(Doctrine_Entity $dest); + + /** + * inserts node as previous sibling of dest record + * + * @return bool + */ + public function insertAsPrevSiblingOf(Doctrine_Entity $dest); + + /** + * inserts node as next sibling of dest record + * + * @return bool + */ + public function insertAsNextSiblingOf(Doctrine_Entity $dest); + + /** + * inserts node as first child of dest record + * + * @return bool + */ + public function insertAsFirstChildOf(Doctrine_Entity $dest); + + /** + * inserts node as first child of dest record + * + * @return bool + */ + public function insertAsLastChildOf(Doctrine_Entity $dest); + + /** + * moves node as prev sibling of dest record + * + */ + public function moveAsPrevSiblingOf(Doctrine_Entity $dest); + + /** + * moves node as next sibling of dest record + * + */ + public function moveAsNextSiblingOf(Doctrine_Entity $dest); + + /** + * moves node as first child of dest record + * + */ + public function moveAsFirstChildOf(Doctrine_Entity $dest); + + /** + * moves node as last child of dest record + * + */ + public function moveAsLastChildOf(Doctrine_Entity $dest); + + /** + * adds node as last child of record + * + */ + public function addChild(Doctrine_Entity $record); + + /** + * determines if node is leaf + * + * @return bool + */ + public function isLeaf(); + + /** + * determines if node is root + * + * @return bool + */ + public function isRoot(); + + /** + * determines if node is equal to subject node + * + * @return bool + */ + public function isEqualTo(Doctrine_Entity $subj); + + /** + * determines if node is child of subject node + * + * @return bool + */ + public function isDescendantOf(Doctrine_Entity $subj); + + /** + * determines if node is child of or sibling to subject node + * + * @return bool + */ + public function isDescendantOfOrEqualTo(Doctrine_Entity $subj); + + /** + * determines if node is valid + * + * @return bool + */ + public function isValidNode(); + + /** + * deletes node and it's descendants + * + */ + public function delete(); +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/MaterializedPath.php b/lib/Doctrine/TODO/Node/MaterializedPath.php new file mode 100644 index 000000000..e1b3aa867 --- /dev/null +++ b/lib/Doctrine/TODO/Node/MaterializedPath.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Node_MaterializedPath + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Joe Simms + */ +abstract class Doctrine_Node_MaterializedPath extends Doctrine_Node implements Doctrine_Node_Interface +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/MaterializedPath/LevelOrderIterator.php b/lib/Doctrine/TODO/Node/MaterializedPath/LevelOrderIterator.php new file mode 100644 index 000000000..a92130f49 --- /dev/null +++ b/lib/Doctrine/TODO/Node/MaterializedPath/LevelOrderIterator.php @@ -0,0 +1,68 @@ +. + */ + +/** + * Doctrine_Node_MaterializedPath_LevelOrderIterator + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Joe Simms + */ +class Doctrine_Node_MaterializedPath_LevelOrderIterator implements Iterator +{ + private $topNode = null; + + private $curNode = null; + + public function __construct($node, $opts) + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function rewind() + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function valid() + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function current() + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function key() + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function next() + { + throw new Doctrine_Exception('Not yet implemented'); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/MaterializedPath/PostOrderIterator.php b/lib/Doctrine/TODO/Node/MaterializedPath/PostOrderIterator.php new file mode 100644 index 000000000..2e26cc603 --- /dev/null +++ b/lib/Doctrine/TODO/Node/MaterializedPath/PostOrderIterator.php @@ -0,0 +1,68 @@ +. + */ + +/** + * Doctrine_Node_MaterializedPath_PostOrderIterator + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Joe Simms + */ +class Doctrine_Node_MaterializedPath_PostOrderIterator implements Iterator +{ + private $topNode = null; + + private $curNode = null; + + public function __construct($node, $opts) + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function rewind() + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function valid() + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function current() + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function key() + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function next() + { + throw new Doctrine_Exception('Not yet implemented'); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/MaterializedPath/PreOrderIterator.php b/lib/Doctrine/TODO/Node/MaterializedPath/PreOrderIterator.php new file mode 100644 index 000000000..540f319c2 --- /dev/null +++ b/lib/Doctrine/TODO/Node/MaterializedPath/PreOrderIterator.php @@ -0,0 +1,68 @@ +. + */ + +/** + * Doctrine_Node_MaterializedPath_PreOrderIterator + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Joe Simms + */ +class Doctrine_Node_MaterializedPath_PreOrderIterator implements Iterator +{ + private $topNode = null; + + private $curNode = null; + + public function __construct($node, $opts) + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function rewind() + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function valid() + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function current() + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function key() + { + throw new Doctrine_Exception('Not yet implemented'); + } + + public function next() + { + throw new Doctrine_Exception('Not yet implemented'); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/NestedSet.php b/lib/Doctrine/TODO/Node/NestedSet.php new file mode 100644 index 000000000..892549594 --- /dev/null +++ b/lib/Doctrine/TODO/Node/NestedSet.php @@ -0,0 +1,1009 @@ +. + */ + +/** + * Doctrine_Node_NestedSet + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 4364 $ + * @author Joe Simms + * @author Roman Borschel + */ +class Doctrine_Node_NestedSet extends Doctrine_Node implements Doctrine_Node_Interface +{ + /** + * test if node has previous sibling + * + * @return bool + */ + public function hasPrevSibling() + { + return $this->isValidNode($this->getPrevSibling()); + } + + /** + * test if node has next sibling + * + * @return bool + */ + public function hasNextSibling() + { + return $this->isValidNode($this->getNextSibling()); + } + + /** + * test if node has children + * + * @return bool + */ + public function hasChildren() + { + return (($this->getRightValue() - $this->getLeftValue()) > 1); + } + + /** + * test if node has parent + * + * @return bool + */ + public function hasParent() + { + return !$this->isRoot(); + } + + /** + * gets record of prev sibling or empty record + * + * @return object Doctrine_Entity + */ + public function getPrevSibling() + { + $baseAlias = $this->_tree->getBaseAlias(); + $q = $this->_tree->getBaseQuery(); + $q = $q->addWhere("$baseAlias.rgt = ?", $this->getLeftValue() - 1); + $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue()); + $result = $q->execute(); + + if (count($result) <= 0) { + return false; + } + + if ($result instanceof Doctrine_Collection) { + $sibling = $result->getFirst(); + } else if (is_array($result)) { + $sibling = array_shift($result); + } + + return $sibling; + } + + /** + * gets record of next sibling or empty record + * + * @return object Doctrine_Entity + */ + public function getNextSibling() + { + $baseAlias = $this->_tree->getBaseAlias(); + $q = $this->_tree->getBaseQuery(); + $q = $q->addWhere("$baseAlias.lft = ?", $this->getRightValue() + 1); + $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue()); + $result = $q->execute(); + + if (count($result) <= 0) { + return false; + } + + if ($result instanceof Doctrine_Collection) { + $sibling = $result->getFirst(); + } else if (is_array($result)) { + $sibling = array_shift($result); + } + + return $sibling; + } + + /** + * gets siblings for node + * + * @return array array of sibling Doctrine_Entity objects + */ + public function getSiblings($includeNode = false) + { + $parent = $this->getParent(); + $siblings = array(); + if ($parent->exists()) { + foreach ($parent->getNode()->getChildren() as $child) { + if ($this->isEqualTo($child) && !$includeNode) { + continue; + } + $siblings[] = $child; + } + } + return $siblings; + } + + /** + * gets record of first child or empty record + * + * @return object Doctrine_Entity + */ + public function getFirstChild() + { + $baseAlias = $this->_tree->getBaseAlias(); + $q = $this->_tree->getBaseQuery(); + $q->addWhere("$baseAlias.lft = ?", $this->getLeftValue() + 1); + $this->_tree->returnQueryWithRootId($q, $this->getRootValue()); + $result = $q->execute(); + + if (count($result) <= 0) { + return false; + } + + if ($result instanceof Doctrine_Collection) { + $child = $result->getFirst(); + } else if (is_array($result)) { + $child = array_shift($result); + } + + return $child; + } + + /** + * gets record of last child or empty record + * + * @return object Doctrine_Entity + */ + public function getLastChild() + { + $baseAlias = $this->_tree->getBaseAlias(); + $q = $this->_tree->getBaseQuery(); + $q->addWhere("$baseAlias.rgt = ?", $this->getRightValue() - 1); + $this->_tree->returnQueryWithRootId($q, $this->getRootValue()); + $result = $q->execute(); + + if (count($result) <= 0) { + return false; + } + + if ($result instanceof Doctrine_Collection) { + $child = $result->getFirst(); + } else if (is_array($result)) { + $child = array_shift($result); + } + + return $child; + } + + /** + * gets children for node (direct descendants only) + * + * @return mixed The children of the node or FALSE if the node has no children. + */ + public function getChildren() + { + return $this->getDescendants(1); + } + + /** + * gets descendants for node (direct descendants only) + * + * @return mixed The descendants of the node or FALSE if the node has no descendants. + * @todo Currently all descendants are fetched, no matter the depth. Maybe there is a better + * solution with less overhead. + */ + public function getDescendants($depth = null, $includeNode = false) + { + $baseAlias = $this->_tree->getBaseAlias(); + $q = $this->_tree->getBaseQuery(); + $params = array($this->record->get('lft'), $this->record->get('rgt')); + + if ($includeNode) { + $q->addWhere("$baseAlias.lft >= ? AND $baseAlias.rgt <= ?", $params)->addOrderBy("$baseAlias.lft asc"); + } else { + $q->addWhere("$baseAlias.lft > ? AND $baseAlias.rgt < ?", $params)->addOrderBy("$baseAlias.lft asc"); + } + + if ($depth !== null) { + $q->addWhere("$baseAlias.level <= ?", $this->record['level'] + $depth); + } + + $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue()); + $result = $q->execute(); + + if (count($result) <= 0) { + return false; + } + + return $result; + } + + /** + * gets record of parent or empty record + * + * @return object Doctrine_Entity + */ + public function getParent() + { + $baseAlias = $this->_tree->getBaseAlias(); + $q = $this->_tree->getBaseQuery(); + $q->addWhere("$baseAlias.lft < ? AND $baseAlias.rgt > ?", array($this->getLeftValue(), $this->getRightValue())) + ->addOrderBy("$baseAlias.rgt asc"); + $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue()); + $result = $q->execute(); + + if (count($result) <= 0) { + return false; + } + + if ($result instanceof Doctrine_Collection) { + $parent = $result->getFirst(); + } else if (is_array($result)) { + $parent = array_shift($result); + } + + return $parent; + } + + /** + * gets ancestors for node + * + * @param integer $deth The depth 'upstairs'. + * @return mixed The ancestors of the node or FALSE if the node has no ancestors (this + * basically means it's a root node). + */ + public function getAncestors($depth = null) + { + $baseAlias = $this->_tree->getBaseAlias(); + $q = $this->_tree->getBaseQuery(); + $q->addWhere("$baseAlias.lft < ? AND $baseAlias.rgt > ?", array($this->getLeftValue(), $this->getRightValue())) + ->addOrderBy("$baseAlias.lft asc"); + if ($depth !== null) { + $q->addWhere("$baseAlias.level >= ?", $this->record['level'] - $depth); + } + $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue()); + $ancestors = $q->execute(); + if (count($ancestors) <= 0) { + return false; + } + return $ancestors; + } + + /** + * gets path to node from root, uses record::toString() method to get node names + * + * @param string $seperator path seperator + * @param bool $includeNode whether or not to include node at end of path + * @return string string representation of path + */ + public function getPath($seperator = ' > ', $includeRecord = false) + { + $path = array(); + $ancestors = $this->getAncestors(); + if ($ancestors) { + foreach ($ancestors as $ancestor) { + $path[] = $ancestor->__toString(); + } + } + if ($includeRecord) { + $path[] = $this->getRecord()->__toString(); + } + + return implode($seperator, $path); + } + + /** + * gets number of children (direct descendants) + * + * @return int + */ + public function getNumberChildren() + { + return count($this->getChildren()); + } + + /** + * gets number of descendants (children and their children) + * + * @return int + */ + public function getNumberDescendants() + { + return ($this->getRightValue() - $this->getLeftValue() - 1) / 2; + } + + /** + * inserts node as parent of dest record + * + * @return bool + * @todo Wrap in transaction + */ + public function insertAsParentOf(Doctrine_Entity $dest) + { + // cannot insert a node that has already has a place within the tree + if ($this->isValidNode()) { + return false; + } + // cannot insert as parent of root + if ($dest->getNode()->isRoot()) { + return false; + } + + $newLeft = $dest->getNode()->getLeftValue(); + $newRight = $dest->getNode()->getRightValue() + 2; + $newRoot = $dest->getNode()->getRootValue(); + $newLevel = $dest->getNode()->getLevel(); + + // Make space for new node + $this->shiftRLValues($dest->getNode()->getRightValue() + 1, 2, $newRoot); + + // Slide child nodes over one and down one to allow new parent to wrap them + $componentName = $this->_tree->getBaseComponent(); + $q = new Doctrine_Query(); + $q->update($componentName); + $q->set("$componentName.lft", "$componentName.lft + 1"); + $q->set("$componentName.rgt", "$componentName.rgt + 1"); + $q->set("$componentName.level", "$componentName.level + 1"); + $q->where("$componentName.lft >= ? AND $componentName.rgt <= ?", array($newLeft, $newRight)); + $q = $this->_tree->returnQueryWithRootId($q, $newRoot); + $q->execute(); + + $this->record['level'] = $newLevel; + $this->insertNode($newLeft, $newRight, $newRoot); + + return true; + } + + /** + * inserts node as previous sibling of dest record + * + * @return bool + * @todo Wrap in transaction + */ + public function insertAsPrevSiblingOf(Doctrine_Entity $dest) + { + // cannot insert a node that has already has a place within the tree + if ($this->isValidNode()) + return false; + + $newLeft = $dest->getNode()->getLeftValue(); + $newRight = $dest->getNode()->getLeftValue() + 1; + $newRoot = $dest->getNode()->getRootValue(); + + $this->shiftRLValues($newLeft, 2, $newRoot); + $this->record['level'] = $dest['level']; + $this->insertNode($newLeft, $newRight, $newRoot); + // update destination left/right values to prevent a refresh + // $dest->getNode()->setLeftValue($dest->getNode()->getLeftValue() + 2); + // $dest->getNode()->setRightValue($dest->getNode()->getRightValue() + 2); + + return true; + } + + /** + * inserts node as next sibling of dest record + * + * @return bool + * @todo Wrap in transaction + */ + public function insertAsNextSiblingOf(Doctrine_Entity $dest) + { + // cannot insert a node that has already has a place within the tree + if ($this->isValidNode()) + return false; + + $newLeft = $dest->getNode()->getRightValue() + 1; + $newRight = $dest->getNode()->getRightValue() + 2; + $newRoot = $dest->getNode()->getRootValue(); + + $this->shiftRLValues($newLeft, 2, $newRoot); + $this->record['level'] = $dest['level']; + $this->insertNode($newLeft, $newRight, $newRoot); + + // update destination left/right values to prevent a refresh + // no need, node not affected + + return true; + } + + /** + * inserts node as first child of dest record + * + * @return bool + * @todo Wrap in transaction + */ + public function insertAsFirstChildOf(Doctrine_Entity $dest) + { + // cannot insert a node that has already has a place within the tree + if ($this->isValidNode()) + return false; + + $newLeft = $dest->getNode()->getLeftValue() + 1; + $newRight = $dest->getNode()->getLeftValue() + 2; + $newRoot = $dest->getNode()->getRootValue(); + + $this->shiftRLValues($newLeft, 2, $newRoot); + $this->record['level'] = $dest['level'] + 1; + $this->insertNode($newLeft, $newRight, $newRoot); + + // update destination left/right values to prevent a refresh + // $dest->getNode()->setRightValue($dest->getNode()->getRightValue() + 2); + + return true; + } + + /** + * inserts node as last child of dest record + * + * @return bool + * @todo Wrap in transaction + */ + public function insertAsLastChildOf(Doctrine_Entity $dest) + { + // cannot insert a node that has already has a place within the tree + if ($this->isValidNode()) + return false; + + $newLeft = $dest->getNode()->getRightValue(); + $newRight = $dest->getNode()->getRightValue() + 1; + $newRoot = $dest->getNode()->getRootValue(); + + $this->shiftRLValues($newLeft, 2, $newRoot); + $this->record['level'] = $dest['level'] + 1; + $this->insertNode($newLeft, $newRight, $newRoot); + + // update destination left/right values to prevent a refresh + // $dest->getNode()->setRightValue($dest->getNode()->getRightValue() + 2); + + return true; + } + + /** + * Accomplishes moving of nodes between different trees. + * Used by the move* methods if the root values of the two nodes are different. + * + * @param Doctrine_Entity $dest + * @param unknown_type $newLeftValue + * @param unknown_type $moveType + * @todo Better exception handling/wrapping + */ + private function _moveBetweenTrees(Doctrine_Entity $dest, $newLeftValue, $moveType) + { + $conn = $this->record->getTable()->getConnection(); + + try { + $conn->beginTransaction(); + + // Move between trees: Detach from old tree & insert into new tree + $newRoot = $dest->getNode()->getRootValue(); + $oldRoot = $this->getRootValue(); + $oldLft = $this->getLeftValue(); + $oldRgt = $this->getRightValue(); + $oldLevel = $this->record['level']; + + // Prepare target tree for insertion, make room + $this->shiftRlValues($newLeftValue, $oldRgt - $oldLft - 1, $newRoot); + + // Set new root id for this node + $this->setRootValue($newRoot); + $this->record->save(); + + // Close gap in old tree + $first = $oldRgt + 1; + $delta = $oldLft - $oldRgt - 1; + $this->shiftRLValues($first, $delta, $oldRoot); + + // Insert this node as a new node + $this->setRightValue(0); + $this->setLeftValue(0); + + switch ($moveType) { + case 'moveAsPrevSiblingOf': + $this->insertAsPrevSiblingOf($dest); + break; + case 'moveAsFirstChildOf': + $this->insertAsFirstChildOf($dest); + break; + case 'moveAsNextSiblingOf': + $this->insertAsNextSiblingOf($dest); + break; + case 'moveAsLastChildOf': + $this->insertAsLastChildOf($dest); + break; + default: + throw new Exception("Unknown move operation: $moveType."); + } + + $diff = $oldRgt - $oldLft; + $this->setRightValue($this->getLeftValue() + ($oldRgt - $oldLft)); + $this->record->save(); + + $newLevel = $this->record['level']; + $levelDiff = $newLevel - $oldLevel; + + // Relocate descendants of the node + $diff = $this->getLeftValue() - $oldLft; + $componentName = $this->_tree->getBaseComponent(); + $rootColName = $this->_tree->getAttribute('rootColumnName'); + + // Update lft/rgt/root/level for all descendants + $q = new Doctrine_Query($conn); + $q = $q->update($componentName) + ->set($componentName . '.lft', 'lft + ?', $diff) + ->set($componentName . '.rgt', 'rgt + ?', $diff) + ->set($componentName . '.level', 'level + ?', $levelDiff) + ->set($componentName . '.' . $rootColName, '?', $newRoot) + ->where($componentName . '.lft > ? AND ' . $componentName . '.rgt < ?', + array($oldLft, $oldRgt)); + $q = $this->_tree->returnQueryWithRootId($q, $oldRoot); + $q->execute(); + + $conn->commit(); + } catch (Exception $e) { + $conn->rollback(); + throw $e; + } + } + + /** + * moves node as prev sibling of dest record + * + */ + public function moveAsPrevSiblingOf(Doctrine_Entity $dest) + { + if ($dest->getNode()->getRootValue() != $this->getRootValue()) { + // Move between trees + $this->_moveBetweenTrees($dest, $dest->getNode()->getLeftValue(), __FUNCTION__); + } else { + // Move within the tree + $oldLevel = $this->record['level']; + $this->record['level'] = $dest['level']; + $this->updateNode($dest->getNode()->getLeftValue(), $this->record['level'] - $oldLevel); + } + } + + /** + * moves node as next sibling of dest record + * + */ + public function moveAsNextSiblingOf(Doctrine_Entity $dest) + { + if ($dest->getNode()->getRootValue() != $this->getRootValue()) { + // Move between trees + $this->_moveBetweenTrees($dest, $dest->getNode()->getRightValue() + 1, __FUNCTION__); + } else { + // Move within tree + $oldLevel = $this->record['level']; + $this->record['level'] = $dest['level']; + $this->updateNode($dest->getNode()->getRightValue() + 1, $this->record['level'] - $oldLevel); + } + } + + /** + * moves node as first child of dest record + * + */ + public function moveAsFirstChildOf(Doctrine_Entity $dest) + { + if ($dest->getNode()->getRootValue() != $this->getRootValue()) { + // Move between trees + $this->_moveBetweenTrees($dest, $dest->getNode()->getLeftValue() + 1, __FUNCTION__); + } else { + // Move within tree + $oldLevel = $this->record['level']; + $this->record['level'] = $dest['level'] + 1; + $this->updateNode($dest->getNode()->getLeftValue() + 1, $this->record['level'] - $oldLevel); + } + } + + /** + * moves node as last child of dest record + * + */ + public function moveAsLastChildOf(Doctrine_Entity $dest) + { + if ($dest->getNode()->getRootValue() != $this->getRootValue()) { + // Move between trees + $this->_moveBetweenTrees($dest, $dest->getNode()->getRightValue(), __FUNCTION__); + } else { + // Move within tree + $oldLevel = $this->record['level']; + $this->record['level'] = $dest['level'] + 1; + $this->updateNode($dest->getNode()->getRightValue(), $this->record['level'] - $oldLevel); + } + } + + /** + * Makes this node a root node. Only used in multiple-root trees. + * + * @todo Exception handling/wrapping + */ + public function makeRoot($newRootId) + { + // TODO: throw exception instead? + if ($this->getLeftValue() == 1 || ! $this->_tree->getAttribute('hasManyRoots')) { + return false; + } + + $oldRgt = $this->getRightValue(); + $oldLft = $this->getLeftValue(); + $oldRoot = $this->getRootValue(); + $oldLevel = $this->record['level']; + + try { + $conn = $this->record->getTable()->getConnection(); + $conn->beginTransaction(); + + // Detach from old tree (close gap in old tree) + $first = $oldRgt + 1; + $delta = $oldLft - $oldRgt - 1; + $this->shiftRLValues($first, $delta, $this->getRootValue()); + + // Set new lft/rgt/root/level values for root node + $this->setLeftValue(1); + $this->setRightValue($oldRgt - $oldLft + 1); + $this->setRootValue($newRootId); + $this->record['level'] = 0; + + // Update descendants lft/rgt/root/level values + $diff = 1 - $oldLft; + $newRoot = $newRootId; + $componentName = $this->_tree->getBaseComponent(); + $rootColName = $this->_tree->getAttribute('rootColumnName'); + $q = new Doctrine_Query($conn); + $q = $q->update($componentName) + ->set($componentName . '.lft', 'lft + ?', $diff) + ->set($componentName . '.rgt', 'rgt + ?', $diff) + ->set($componentName . '.level', 'level - ?', $oldLevel) + ->set($componentName . '.' . $rootColName, '?', $newRoot) + ->where($componentName . '.lft > ? AND ' . $componentName . '.rgt < ?', + array($oldLft, $oldRgt)); + $q = $this->_tree->returnQueryWithRootId($q, $oldRoot); + $q->execute(); + + $conn->commit(); + + } catch (Exception $e) { + $conn->rollback(); + throw $e; + } + } + + /** + * adds node as last child of record + * + */ + public function addChild(Doctrine_Entity $record) + { + $record->getNode()->insertAsLastChildOf($this->getRecord()); + } + + /** + * determines if node is leaf + * + * @return bool + */ + public function isLeaf() + { + return (($this->getRightValue() - $this->getLeftValue()) == 1); + } + + /** + * determines if node is root + * + * @return bool + */ + public function isRoot() + { + return ($this->getLeftValue() == 1); + } + + /** + * determines if node is equal to subject node + * + * @return bool + */ + public function isEqualTo(Doctrine_Entity $subj) + { + return (($this->getLeftValue() == $subj->getNode()->getLeftValue()) && + ($this->getRightValue() == $subj->getNode()->getRightValue()) && + ($this->getRootValue() == $subj->getNode()->getRootValue()) + ); + } + + /** + * determines if node is child of subject node + * + * @return bool + */ + public function isDescendantOf(Doctrine_Entity $subj) + { + return (($this->getLeftValue() > $subj->getNode()->getLeftValue()) && + ($this->getRightValue() < $subj->getNode()->getRightValue()) && + ($this->getRootValue() == $subj->getNode()->getRootValue())); + } + + /** + * determines if node is child of or sibling to subject node + * + * @return bool + */ + public function isDescendantOfOrEqualTo(Doctrine_Entity $subj) + { + return (($this->getLeftValue() >= $subj->getNode()->getLeftValue()) && + ($this->getRightValue() <= $subj->getNode()->getRightValue()) && + ($this->getRootValue() == $subj->getNode()->getRootValue())); + } + + /** + * determines if node is valid + * + * @return bool + */ + public function isValidNode($record = null) + { + if ($record === null) { + return ($this->getRightValue() > $this->getLeftValue()); + } else if ( $record instanceof Doctrine_Entity ) { + return ($record->getNode()->getRightValue() > $record->getNode()->getLeftValue()); + } else { + return false; + } + } + + /** + * deletes node and it's descendants + * @todo Delete more efficiently. Wrap in transaction if needed. + */ + public function delete() + { + // TODO: add the setting whether or not to delete descendants or relocate children + $oldRoot = $this->getRootValue(); + $q = $this->_tree->getBaseQuery(); + + $baseAlias = $this->_tree->getBaseAlias(); + $componentName = $this->_tree->getBaseComponent(); + + $q = $q->addWhere("$baseAlias.lft >= ? AND $baseAlias.rgt <= ?", array($this->getLeftValue(), $this->getRightValue())); + + $q = $this->_tree->returnQueryWithRootId($q, $oldRoot); + + $coll = $q->execute(); + + $coll->delete(); + + $first = $this->getRightValue() + 1; + $delta = $this->getLeftValue() - $this->getRightValue() - 1; + $this->shiftRLValues($first, $delta, $oldRoot); + + return true; + } + + /** + * sets node's left and right values and save's it + * + * @param int $destLeft node left value + * @param int $destRight node right value + */ + private function insertNode($destLeft = 0, $destRight = 0, $destRoot = 1) + { + $this->setLeftValue($destLeft); + $this->setRightValue($destRight); + $this->setRootValue($destRoot); + $this->record->save(); + } + + /** + * move node's and its children to location $destLeft and updates rest of tree + * + * @param int $destLeft destination left value + * @todo Wrap in transaction + */ + private function updateNode($destLeft, $levelDiff) + { + $componentName = $this->_tree->getBaseComponent(); + $left = $this->getLeftValue(); + $right = $this->getRightValue(); + $rootId = $this->getRootValue(); + + $treeSize = $right - $left + 1; + + // Make room in the new branch + $this->shiftRLValues($destLeft, $treeSize, $rootId); + + if ($left >= $destLeft) { // src was shifted too? + $left += $treeSize; + $right += $treeSize; + } + + // update level for descendants + $q = new Doctrine_Query(); + $q = $q->update($componentName) + ->set($componentName . '.level', 'level + ?') + ->where($componentName . '.lft > ? AND ' . $componentName . '.rgt < ?', + array($levelDiff, $left, $right)); + $q = $this->_tree->returnQueryWithRootId($q, $rootId); + $q->execute(); + + // now there's enough room next to target to move the subtree + $this->shiftRLRange($left, $right, $destLeft - $left, $rootId); + + // correct values after source (close gap in old tree) + $this->shiftRLValues($right + 1, -$treeSize, $rootId); + + $this->record->save(); + $this->record->refresh(); + } + + /** + * adds '$delta' to all Left and Right values that are >= '$first'. '$delta' can also be negative. + * + * @param int $first First node to be shifted + * @param int $delta Value to be shifted by, can be negative + */ + private function shiftRlValues($first, $delta, $rootId = 1) + { + $qLeft = new Doctrine_Query(); + $qRight = new Doctrine_Query(); + + // shift left columns + $componentName = $this->_tree->getBaseComponent(); + $qLeft = $qLeft->update($componentName) + ->set($componentName . '.lft', 'lft + ?') + ->where($componentName . '.lft >= ?', array($delta, $first)); + + $qLeft = $this->_tree->returnQueryWithRootId($qLeft, $rootId); + + $resultLeft = $qLeft->execute(); + + // shift right columns + $resultRight = $qRight->update($componentName) + ->set($componentName . '.rgt', 'rgt + ?') + ->where($componentName . '.rgt >= ?', array($delta, $first)); + + $qRight = $this->_tree->returnQueryWithRootId($qRight, $rootId); + + $resultRight = $qRight->execute(); + } + + /** + * adds '$delta' to all Left and Right values that are >= '$first' and <= '$last'. + * '$delta' can also be negative. + * + * @param int $first First node to be shifted (L value) + * @param int $last Last node to be shifted (L value) + * @param int $delta Value to be shifted by, can be negative + */ + private function shiftRlRange($first, $last, $delta, $rootId = 1) + { + $qLeft = new Doctrine_Query(); + $qRight = new Doctrine_Query(); + + // shift left column values + $componentName = $this->_tree->getBaseComponent(); + $qLeft = $qLeft->update($componentName) + ->set($componentName . '.lft', 'lft + ?') + ->where($componentName . '.lft >= ? AND ' . $componentName . '.lft <= ?', array($delta, $first, $last)); + + $qLeft = $this->_tree->returnQueryWithRootId($qLeft, $rootId); + + $resultLeft = $qLeft->execute(); + + // shift right column values + $qRight = $qRight->update($componentName) + ->set($componentName . '.rgt', 'rgt + ?') + ->where($componentName . '.rgt >= ? AND ' . $componentName . '.rgt <= ?', array($delta, $first, $last)); + + $qRight = $this->_tree->returnQueryWithRootId($qRight, $rootId); + + $resultRight = $qRight->execute(); + } + + /** + * gets record's left value + * + * @return int + */ + public function getLeftValue() + { + return $this->record->get('lft'); + } + + /** + * sets record's left value + * + * @param int + */ + public function setLeftValue($lft) + { + $this->record->set('lft', $lft); + } + + /** + * gets record's right value + * + * @return int + */ + public function getRightValue() + { + return $this->record->get('rgt'); + } + + /** + * sets record's right value + * + * @param int + */ + public function setRightValue($rgt) + { + $this->record->set('rgt', $rgt); + } + + /** + * gets level (depth) of node in the tree + * + * @return int + */ + public function getLevel() + { + if ( ! isset($this->record['level'])) { + $baseAlias = $this->_tree->getBaseAlias(); + $componentName = $this->_tree->getBaseComponent(); + $q = $this->_tree->getBaseQuery(); + $q = $q->addWhere("$baseAlias.lft < ? AND $baseAlias.rgt > ?", array($this->getLeftValue(), $this->getRightValue())); + + $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue()); + + $coll = $q->execute(); + + $this->record['level'] = count($coll) ? count($coll) : 0; + } + return $this->record['level']; + } + + /** + * get records root id value + * + */ + public function getRootValue() + { + if ($this->_tree->getAttribute('hasManyRoots')) { + return $this->record->get($this->_tree->getAttribute('rootColumnName')); + } + return 1; + } + + /** + * sets records root id value + * + * @param int + */ + public function setRootValue($value) + { + if ($this->_tree->getAttribute('hasManyRoots')) { + $this->record->set($this->_tree->getAttribute('rootColumnName'), $value); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/NestedSet/LevelOrderIterator.php b/lib/Doctrine/TODO/Node/NestedSet/LevelOrderIterator.php new file mode 100644 index 000000000..92110f08e --- /dev/null +++ b/lib/Doctrine/TODO/Node/NestedSet/LevelOrderIterator.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Node_NestedSet_LevelOrderIterator + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Joe Simms + */ +class Doctrine_Node_NestedSet_LevelOrderIterator +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/NestedSet/PostOrderIterator.php b/lib/Doctrine/TODO/Node/NestedSet/PostOrderIterator.php new file mode 100644 index 000000000..833bb83e7 --- /dev/null +++ b/lib/Doctrine/TODO/Node/NestedSet/PostOrderIterator.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Node_NestedSet_PostOrderIterator + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Joe Simms + */ +class Doctrine_Node_NestedSet_PostOrderIterator +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Node/NestedSet/PreOrderIterator.php b/lib/Doctrine/TODO/Node/NestedSet/PreOrderIterator.php new file mode 100644 index 000000000..4d61b1835 --- /dev/null +++ b/lib/Doctrine/TODO/Node/NestedSet/PreOrderIterator.php @@ -0,0 +1,183 @@ +. + */ + +/** + * Doctrine_Node_NestedSet_PreOrderIterator + * + * @package Doctrine + * @subpackage Node + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 4364 $ + * @author Joe Simms + */ +class Doctrine_Node_NestedSet_PreOrderIterator implements Iterator +{ + /** + * @var Doctrine_Collection $collection + */ + protected $collection; + + /** + * @var array $keys + */ + protected $keys; + + /** + * @var mixed $key + */ + protected $key; + + /** + * @var integer $index + */ + protected $index; + + /** + * @var integer $index + */ + protected $prevIndex; + + /** + * @var integer $index + */ + protected $traverseLevel; + + /** + * @var integer $count + */ + protected $count; + + public function __construct($record, $opts) + { + $componentName = $record->getTable()->getComponentName(); + + $q = $record->getTable()->createQuery(); + + $params = array($record->get('lft'), $record->get('rgt')); + if (isset($opts['include_record']) && $opts['include_record']) { + $query = $q->where("$componentName.lft >= ? AND $componentName.rgt <= ?", $params)->orderBy("$componentName.lft asc"); + } else { + $query = $q->where("$componentName.lft > ? AND $componentName.rgt < ?", $params)->orderBy("$componentName.lft asc"); + } + + $query = $record->getTable()->getTree()->returnQueryWithRootId($query, $record->getNode()->getRootValue()); + + $this->maxLevel = isset($opts['depth']) ? ($opts['depth'] + $record->getNode()->getLevel()) : 0; + $this->options = $opts; + $this->collection = isset($opts['collection']) ? $opts['collection'] : $query->execute(); + $this->keys = $this->collection->getKeys(); + $this->count = $this->collection->count(); + $this->index = -1; + $this->level = $record->getNode()->getLevel(); + $this->prevLeft = $record->getNode()->getLeftValue(); + + // clear the table identity cache + $record->getTable()->clear(); + } + + /** + * rewinds the iterator + * + * @return void + */ + public function rewind() + { + $this->index = -1; + $this->key = null; + } + + /** + * returns the current key + * + * @return integer + */ + public function key() + { + return $this->key; + } + + /** + * returns the current record + * + * @return Doctrine_Entity + */ + public function current() + { + $record = $this->collection->get($this->key); + $record->getNode()->setLevel($this->level); + return $record; + } + + /** + * advances the internal pointer + * + * @return void + */ + public function next() + { + while ($current = $this->advanceIndex()) { + if ($this->maxLevel && ($this->level > $this->maxLevel)) { + continue; + } + + return $current; + } + + return false; + } + + /** + * @return boolean whether or not the iteration will continue + */ + public function valid() + { + return ($this->index < $this->count); + } + + public function count() + { + return $this->count; + } + + private function updateLevel() + { + if ( ! (isset($this->options['include_record']) && $this->options['include_record'] && $this->index == 0)) { + $left = $this->collection->get($this->key)->getNode()->getLeftValue(); + $this->level += $this->prevLeft - $left + 2; + $this->prevLeft = $left; + } + } + + private function advanceIndex() + { + $this->index++; + $i = $this->index; + if (isset($this->keys[$i])) { + $this->key = $this->keys[$i]; + $this->updateLevel(); + return $this->current(); + } + + return false; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Pager/Exception.php b/lib/Doctrine/TODO/Pager/Exception.php new file mode 100644 index 000000000..0cbc25de9 --- /dev/null +++ b/lib/Doctrine/TODO/Pager/Exception.php @@ -0,0 +1,37 @@ +. + */ + +Doctrine::autoload('Doctrine_Exception'); + +/** + * Doctrine_Pager_Exception + * + * @author Guilherme Blanco + * @package Doctrine + * @subpackage Pager + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 0.9 + */ +class Doctrine_Pager_Exception extends Doctrine_Exception +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Pager/Layout.php b/lib/Doctrine/TODO/Pager/Layout.php new file mode 100644 index 000000000..1eb6851a4 --- /dev/null +++ b/lib/Doctrine/TODO/Pager/Layout.php @@ -0,0 +1,516 @@ +. + */ + +Doctrine::autoload('Doctrine_Pager_Range'); + +/** + * Doctrine_Pager_Layout + * + * @author Guilherme Blanco + * @package Doctrine + * @subpackage Pager + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 0.9 + */ +class Doctrine_Pager_Layout +{ + /** + * @var Doctrine_Pager $_pager Doctrine_Pager object related to the pager layout + */ + private $_pager; + + /** + * @var Doctrine_Pager_Range $_pagerRange Doctrine_Pager_Range object related to the pager layout + */ + private $_pagerRange; + + /** + * @var string $_template Template to be applied for inactive pages + * (and also active is selected template is not defined) + */ + private $_template; + + /** + * @var string $_selectedTemplate Template to be applied for active page + */ + private $_selectedTemplate; + + /** + * @var string $_separatorTemplate Separator template, applied between each page + */ + private $_separatorTemplate; + + /** + * @var string $_urlMask URL to be assigned for each page. Masks are used as: {%var_name} + */ + private $_urlMask; + + /** + * @var array $_maskReplacements Stores references of masks and their correspondent + * (replaces defined masks with new masks or values) + */ + private $_maskReplacements = array(); + + + /** + * __construct + * + * @param Doctrine_Pager $pager Doctrine_Pager object related to the pager layout + * @param Doctrine_Pager_Range $pagerRange Doctrine_Pager_Range object related to the pager layout + * @param string $urlMask URL to be assigned for each page + * @return void + */ + public function __construct($pager, $pagerRange, $urlMask) + { + $this->_setPager($pager); + $this->_setPagerRange($pagerRange); + $this->_setUrlMask($urlMask); + + $this->setTemplate('[{%page}]'); + $this->setSelectedTemplate(''); + $this->setSeparatorTemplate(''); + } + + + /** + * getPager + * + * Returns the Doctrine_Pager object related to the pager layout + * + * @return Doctrine_Pager Doctrine_Pager object related to the pager range + */ + public function getPager() + { + return $this->_pager; + } + + + /** + * _setPager + * + * Defines the Doctrine_Pager object related to the pager layout + * + * @param $pager Doctrine_Pager object related to the pager range + * @return void + */ + protected function _setPager($pager) + { + $this->_pager = $pager; + } + + + /** + * execute + * + * Handy method to execute the query without need to retrieve the Pager instance + * + * @param $params Optional parameters to Doctrine_Query::execute + * @param $hydrationMode Hydration Mode of Doctrine_Query::execute + * returned ResultSet. Doctrine::Default is FETCH_RECORD + * @return Doctrine_Collection The root collection + */ + public function execute($params = array(), $hydrationMode = Doctrine::FETCH_RECORD) + { + return $this->getPager()->execute($params, $hydrationMode); + } + + + /** + * getPagerRange + * + * Returns the Doctrine_Pager_Range subclass object related to the pager layout + * + * @return Doctrine_Pager_Range Doctrine_Pager_Range subclass object related to the pager range + */ + public function getPagerRange() + { + return $this->_pagerRange; + } + + + /** + * _setPagerRange + * + * Defines the Doctrine_Pager_Range subclass object related to the pager layout + * + * @param $pagerRange Doctrine_Pager_Range subclass object related to the pager range + * @return void + */ + protected function _setPagerRange($pagerRange) + { + $this->_pagerRange = $pagerRange; + $this->getPagerRange()->setPager($this->getPager()); + } + + + /** + * getUrlMask + * + * Returns the URL to be assigned for each page + * + * @return string URL to be assigned for each page + */ + public function getUrlMask() + { + return $this->_urlMask; + } + + + /** + * _setUrlMask + * + * Defines the URL to be assigned for each page + * + * @param $urlMask URL to be assigned for each page + * @return void + */ + protected function _setUrlMask($urlMask) + { + $this->_urlMask = $urlMask; + } + + + /** + * getTemplate + * + * Returns the Template to be applied for inactive pages + * + * @return string Template to be applied for inactive pages + */ + public function getTemplate() + { + return $this->_template; + } + + + /** + * setTemplate + * + * Defines the Template to be applied for inactive pages + * (also active page if selected template not defined) + * + * @param $template Template to be applied for inactive pages + * @return void + */ + public function setTemplate($template) + { + $this->_template = $template; + } + + + /** + * getSelectedTemplate + * + * Returns the Template to be applied for active page + * + * @return string Template to be applied for active page + */ + public function getSelectedTemplate() + { + return $this->_selectedTemplate; + } + + + /** + * setSelectedTemplate + * + * Defines the Template to be applied for active page + * + * @param $selectedTemplate Template to be applied for active page + * @return void + */ + public function setSelectedTemplate($selectedTemplate) + { + $this->_selectedTemplate = $selectedTemplate; + } + + + /** + * getSeparatorTemplate + * + * Returns the Separator template, applied between each page + * + * @return string Separator template, applied between each page + */ + public function getSeparatorTemplate() + { + return $this->_separatorTemplate; + } + + + /** + * setSeparatorTemplate + * + * Defines the Separator template, applied between each page + * + * @param $separatorTemplate Separator template, applied between each page + * @return void + */ + public function setSeparatorTemplate($separatorTemplate) + { + $this->_separatorTemplate = $separatorTemplate; + } + + + /** + * addMaskReplacement + * + * Defines a mask replacement. When parsing template, it converts replacement + * masks into new ones (or values), allowing to change masks behavior on the fly + * + * @param $oldMask Mask to be replaced + * @param $newMask Mask or Value that will be defined after replacement + * @param $asValue Optional value (default false) that if defined as true, + * changes the bahavior of replacement mask to replacement + * value + * @return void + */ + public function addMaskReplacement($oldMask, $newMask, $asValue = false) + { + if (($oldMask = trim($oldMask)) != 'page_number') { + $this->_maskReplacements[$oldMask] = array( + 'newMask' => $newMask, + 'asValue' => ($asValue === false) ? false : true + ); + } + } + + + /** + * removeMaskReplacement + * + * Remove a mask replacement + * + * @param $oldMask Replacement Mask to be removed + * @return void + */ + public function removeMaskReplacement($oldMask) + { + if (isset($this->_maskReplacements[$oldMask])) { + $this->_maskReplacements[$oldMask] = null; + unset($this->_maskReplacements[$oldMask]); + } + } + + + /** + * cleanMaskReplacements + * + * Remove all mask replacements + * + * @return void + */ + public function cleanMaskReplacements() + { + $this->_maskReplacements = null; + $this->_maskReplacements = array(); + } + + + /** + * display + * + * Displays the pager on screen based on templates and options defined + * + * @param $options Optional parameters to be applied in template and url mask + * @param $return Optional parameter if you want to capture the output of this method call + * (Default value is false), instead of printing it + * @return mixed If you would like to capture the output of Doctrine_Pager_Layout::display(), + * use the return parameter. If this parameter is set to TRUE, this method + * will return its output, instead of printing it (which it does by default) + */ + public function display($options = array(), $return = false) + { + $range = $this->getPagerRange()->rangeAroundPage(); + $str = ''; + + // For each page in range + for ($i = 0, $l = count($range); $i < $l; $i++) { + // Define some optional mask values + $options['page_number'] = $range[$i]; + + $str .= $this->processPage($options); + + // Apply separator between pages + if ($i < $l - 1) { + $str .= $this->getSeparatorTemplate(); + } + } + + // Possible wish to return value instead of print it on screen + if ($return) { + return $str; + } + + echo $str; + } + + + /** + * processPage + * + * Parses the template and returns the string of a processed page + * + * @param array Optional parameters to be applied in template and url mask + * @return string Processed template for the given page + */ + public function processPage($options = array()) + { + // Check if at least basic options are defined + if (!isset($options['page_number'])) { + throw new Doctrine_Pager_Exception( + 'Cannot process template of the given page. ' . + 'Missing at least one of needed parameters: \'page\' or \'page_number\'' + ); + + // Should never reach here + return ''; + } + + // Assign "page" options index if not defined yet + if (!isset($this->_maskReplacements['page']) && !isset($options['page'])) { + $options['page'] = $options['page_number']; + } + + return $this->_parseTemplate($options); + } + + + /** + * Simply calls display, and returns the output. + */ + public function __toString() + { + return $this->display(array(), true); + } + + + /** + * _parseTemplate + * + * Parse the template of a given page and return the processed template + * + * @param array Optional parameters to be applied in template and url mask + * @return string + */ + protected function _parseTemplate($options = array()) + { + $str = $this->_parseUrlTemplate($options); + $replacements = $this->_parseReplacementsTemplate($options); + + return strtr($str, $replacements); + } + + + /** + * _parseUrlTemplate + * + * Parse the url mask to return the correct template depending of the options sent. + * Already process the mask replacements assigned. + * + * @param $options Optional parameters to be applied in template and url mask + * @return string + */ + protected function _parseUrlTemplate($options = array()) + { + $str = ''; + + // If given page is the current active one + if ($options['page_number'] == $this->getPager()->getPage()) { + $str = $this->_parseMaskReplacements($this->getSelectedTemplate()); + } + + // Possible attempt where Selected == Template + if ($str == '') { + $str = $this->_parseMaskReplacements($this->getTemplate()); + } + + return $str; + } + + + /** + * _parseUrl + * + * Parse the mask replacements of a given page + * + * @param $options Optional parameters to be applied in template and url mask + * @return string + */ + protected function _parseReplacementsTemplate($options = array()) + { + // Defining "url" options index to allow {%url} mask + $options['url'] = $this->_parseUrl($options); + + $replacements = array(); + + foreach ($options as $k => $v) { + $replacements['{%'.$k.'}'] = $v; + } + + return $replacements; + } + + + /** + * _parseUrl + * + * Parse the url mask of a given page and return the processed url + * + * @param $options Optional parameters to be applied in template and url mask + * @return string + */ + protected function _parseUrl($options = array()) + { + $str = $this->_parseMaskReplacements($this->getUrlMask()); + + $replacements = array(); + + foreach ($options as $k => $v) { + $replacements['{%'.$k.'}'] = $v; + } + + return strtr($str, $replacements); + } + + + /** + * _parseMaskReplacements + * + * Parse the mask replacements, changing from to-be replaced mask with new masks/values + * + * @param $str String to have masks replaced + * @return string + */ + protected function _parseMaskReplacements($str) + { + $replacements = array(); + + foreach ($this->_maskReplacements as $k => $v) { + $replacements['{%'.$k.'}'] = ($v['asValue'] === true) ? $v['newMask'] : '{%'.$v['newMask'].'}'; + } + + return strtr($str, $replacements); + } +} diff --git a/lib/Doctrine/TODO/Pager/Range.php b/lib/Doctrine/TODO/Pager/Range.php new file mode 100644 index 000000000..396cebfb1 --- /dev/null +++ b/lib/Doctrine/TODO/Pager/Range.php @@ -0,0 +1,176 @@ +. + */ + +/** + * Doctrine_Pager_Range + * + * @author Guilherme Blanco + * @package Doctrine + * @subpackage Pager + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 0.9 + */ +abstract class Doctrine_Pager_Range +{ + /** + * @var array $_options Custom Doctrine_Pager_Range implementation options + */ + protected $_options; + + /** + * @var Doctrine_Pager $pager Doctrine_Pager object related to the pager range + */ + private $pager; + + + /** + * __construct + * + * @param array $options Custom subclass implementation options. + * Default is a blank array + * @param Doctrine_Pager $pager Optional Doctrine_Pager object to be associated + * @return void + */ + final public function __construct($options = array(), $pager = null) + { + $this->_setOptions($options); + + if ($pager !== null) { + $this->setPager($pager); + } + } + + + /** + * getPager + * + * Returns the Doctrine_Pager object related to the pager range + * + * @return Doctrine_Pager Doctrine_Pager object related to the pager range + */ + public function getPager() + { + return $this->pager; + } + + + /** + * setPager + * + * Defines the Doctrine_Pager object related to the pager range and + * automatically (re-)initialize Doctrine_Pager_Range + * + * @param $pager Doctrine_Pager object related to the pager range + * @return void + */ + public function setPager($pager) + { + $this->pager = $pager; + + // Lazy-load initialization. It only should be called when all + // needed information data is ready (this can only happens when we have + // options stored and a Doctrine_Pager assocated) + $this->_initialize(); + } + + + /** + * getOptions + * + * Returns the custom Doctrine_Pager_Range implementation options + * + * @return array Custom Doctrine_Pager_Range implementation options + */ + public function getOptions() + { + return $this->_options; + } + + + /** + * getOption + * + * Returns the custom Doctrine_Pager_Range implementation offset option + * + * @return array Custom Doctrine_Pager_Range implementation options + */ + public function getOption($option) + { + if (isset($this->_options[$option])) { + return $this->_options[$option]; + } + + throw new Doctrine_Pager_Exception( + 'Cannot access unexistent option \'' . $option . '\' in Doctrine_Pager_Range class' + ); + } + + + /** + * _setOptions + * + * Defines the subclass implementation options + * + * @param $options Custom Doctrine_Pager_Range implementation options + * @return void + */ + protected function _setOptions($options) + { + $this->_options = $options; + } + + + /** + * isInRange + * + * Check if a given page is in the range + * + * @param $page Page to be checked + * @return boolean + */ + public function isInRange($page) + { + return (array_search($page, $this->rangeAroundPage()) !== false); + } + + + /** + * _initialize + * + * Initialize Doctrine_Page_Range subclass which does custom class definitions + * + * @return void + */ + abstract protected function _initialize(); + + + /** + * rangeAroundPage + * + * Calculate and returns an array representing the range around the current page + * + * @return array + */ + abstract public function rangeAroundPage(); +} diff --git a/lib/Doctrine/TODO/Pager/Range/Jumping.php b/lib/Doctrine/TODO/Pager/Range/Jumping.php new file mode 100644 index 000000000..1c238a724 --- /dev/null +++ b/lib/Doctrine/TODO/Pager/Range/Jumping.php @@ -0,0 +1,120 @@ +. + */ + +Doctrine::autoload('Doctrine_Pager_Range'); + +/** + * Doctrine_Pager_Range_Jumping + * + * @author Guilherme Blanco + * @package Doctrine + * @subpackage Pager + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 0.9 + */ +class Doctrine_Pager_Range_Jumping extends Doctrine_Pager_Range +{ + /** + * @var int $_chunkLength Chunk length to be returned + */ + private $_chunkLength; + + + /** + * _initialize + * + * Initialize Doctrine_Pager_Range_Jumping and does custom assignments + * + * @return void + */ + protected function _initialize() + { + if (isset($this->_options['chunk'])) { + $this->_setChunkLength($this->_options['chunk']); + } else { + throw new Doctrine_Pager_Exception('Missing parameter \'chunk\' that must be define in options.'); + } + } + + + /** + * getChunkLength + * + * Returns the size of the chunk defined + * + * @return int Chunk length + */ + public function getChunkLength() + { + return $this->_chunkLength; + } + + + /** + * _setChunkLength + * + * Defines the size of the chunk + * + * @param $chunkLength Chunk length + * @return void + */ + protected function _setChunkLength($chunkLength) + { + $this->_chunkLength = $chunkLength; + } + + + /** + * rangeAroundPage + * + * Calculate and returns an array representing the range around the current page + * + * @return array + */ + public function rangeAroundPage() + { + $pager = $this->getPager(); + + if ($pager->getExecuted()) { + $page = $pager->getPage(); + + // Define initial assignments for StartPage and EndPage + $startPage = $page - ($page - 1) % $this->getChunkLength(); + $endPage = ($startPage + $this->getChunkLength()) - 1; + + // Check for EndPage out-range + if ($endPage > $pager->getLastPage()) { + $endPage = $pager->getLastPage(); + } + + // No need to check for out-range in start, it will never happens + + return range($startPage, $endPage); + } + + throw new Doctrine_Pager_Exception( + 'Cannot retrieve the range around the page of a not yet executed Pager query' + ); + } +} diff --git a/lib/Doctrine/TODO/Pager/Range/Sliding.php b/lib/Doctrine/TODO/Pager/Range/Sliding.php new file mode 100644 index 000000000..92b84a405 --- /dev/null +++ b/lib/Doctrine/TODO/Pager/Range/Sliding.php @@ -0,0 +1,136 @@ +. + */ + +Doctrine::autoload('Doctrine_Pager_Range'); + +/** + * Doctrine_Pager_Range_Sliding + * + * @author Guilherme Blanco + * @package Doctrine + * @subpackage Pager + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 0.9 + */ +class Doctrine_Pager_Range_Sliding extends Doctrine_Pager_Range +{ + /** + * @var int $_chunkLength Chunk length to be returned + */ + private $_chunkLength; + + + /** + * _initialize + * + * Initialize Doctrine_Pager_Range_Sliding and does custom assignments + * + * @return void + */ + protected function _initialize() + { + if (isset($this->_options['chunk'])) { + $this->_setChunkLength($this->_options['chunk']); + } else { + throw new Doctrine_Pager_Exception('Missing parameter \'chunk\' that must be defined in options.'); + } + } + + + /** + * getChunkLength + * + * Returns the size of the chunk defined + * + * @return int Chunk length + */ + public function getChunkLength() + { + return $this->_chunkLength; + } + + + /** + * _setChunkLength + * + * Defines the size of the chunk + * + * @param $chunkLength Chunk length + * @return void + */ + protected function _setChunkLength($chunkLength) + { + $chunkLength = (int) $chunkLength; + if (!$chunkLength) { + $chunkLength = 1; + } else { + $this->_chunkLength = $chunkLength; + } + } + + + /** + * rangeAroundPage + * + * Calculate and returns an array representing the range around the current page + * + * @return array + */ + public function rangeAroundPage() + { + $pager = $this->getPager(); + + if ($pager->getExecuted()) { + $page = $pager->getPage(); + $pages = $pager->getLastPage(); + + $chunk = $this->getChunkLength(); + + if ($chunk > $pages) { + $chunk = $pages; + } + + $chunkStart = $page - (floor($chunk / 2)); + $chunkEnd = $page + (ceil($chunk / 2)-1); + + if ($chunkStart < 1) { + $adjust = 1 - $chunkStart; + $chunkStart = 1; + $chunkEnd = $chunkEnd + $adjust; + } + + if ($chunkEnd > $pages) { + $adjust = $chunkEnd - $pages; + $chunkStart = $chunkStart - $adjust; + $chunkEnd = $pages; + } + + return range($chunkStart, $chunkEnd); + } + + throw new Doctrine_Pager_Exception( + 'Cannot retrieve the range around the page of a not yet executed Pager query' + ); + } +} diff --git a/lib/Doctrine/TODO/Parser/Exception.php b/lib/Doctrine/TODO/Parser/Exception.php new file mode 100644 index 000000000..64a1301c8 --- /dev/null +++ b/lib/Doctrine/TODO/Parser/Exception.php @@ -0,0 +1,34 @@ +. + */ +Doctrine::autoload('Doctrine_Exception'); +/** + * Doctrine_Parser_Exception + * + * @package Doctrine + * @subpackage Parser + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 1080 $ + * @author Jonathan H. Wage + */ +class Doctrine_Parser_Exception extends Doctrine_Exception +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Parser/Json.php b/lib/Doctrine/TODO/Parser/Json.php new file mode 100644 index 000000000..b05bb28b4 --- /dev/null +++ b/lib/Doctrine/TODO/Parser/Json.php @@ -0,0 +1,68 @@ +. + */ + +/** + * Doctrine_Parser_Json + * + * @package Doctrine + * @subpackage Parser + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 1080 $ + * @author Jonathan H. Wage + */ +class Doctrine_Parser_Json extends Doctrine_Parser +{ + /** + * dumpData + * + * Dump an array of data to a specified path or return + * + * @param string $array Array of data to dump to json + * @param string $path Path to dump json data to + * @return string $json + * @return void + */ + public function dumpData($array, $path = null) + { + $data = json_encode($array); + + return $this->doDump($data, $path); + } + + /** + * loadData + * + * Load and unserialize data from a file or from passed data + * + * @param string $path Path to dump data to + * @return array $json Array of json objects + */ + public function loadData($path) + { + $contents = $this->doLoad($path); + + $json = json_decode($contents); + + return $json; + } +} diff --git a/lib/Doctrine/TODO/Parser/Serialize.php b/lib/Doctrine/TODO/Parser/Serialize.php new file mode 100644 index 000000000..57a40964e --- /dev/null +++ b/lib/Doctrine/TODO/Parser/Serialize.php @@ -0,0 +1,65 @@ +. + */ + +/** + * Doctrine_Parser_Serialize + * + * @package Doctrine + * @subpackage Parser + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 1080 $ + * @author Jonathan H. Wage + */ +class Doctrine_Parser_Serialize extends Doctrine_Parser +{ + /** + * dumpData + * + * Dump an array of data to a specified path or return + * + * @param string $array + * @param string $path + * @return void + */ + public function dumpData($array, $path = null) + { + $data = serialize($array); + + return $this->doDump($data, $path); + } + + /** + * loadData + * + * Load and unserialize data from a file or from passed data + * + * @param string $path + * @return void + */ + public function loadData($path) + { + $contents = $this->doLoad($path); + + return unserialize($contents); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Parser/Xml.php b/lib/Doctrine/TODO/Parser/Xml.php new file mode 100644 index 000000000..397086a8b --- /dev/null +++ b/lib/Doctrine/TODO/Parser/Xml.php @@ -0,0 +1,140 @@ +. + */ + +/** + * Doctrine_Parser_Xml + * + * @package Doctrine + * @subpackage Parser + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 1080 $ + * @author Jonathan H. Wage + */ +class Doctrine_Parser_Xml extends Doctrine_Parser +{ + /** + * dumpData + * + * Convert array to xml and dump to specified path or return the xml + * + * @param string $array Array of data to convert to xml + * @param string $path Path to write xml data to + * @return string $xml + * @return void + */ + public function dumpData($array, $path = null) + { + $data = $this->arrayToXml($array); + + return $this->doDump($data, $path); + } + + /** + * arrayToXml + * + * @param string $array Array to convert to xml + * @param string $rootNodeName Name of the root node + * @param string $xml SimpleXmlElement + * @return string $asXml String of xml built from array + */ + public function arrayToXml($array, $rootNodeName = 'data', $xml = null) + { + if ($xml === null) { + $xml = new SimpleXmlElement("<$rootNodeName/>"); + } + + foreach($array as $key => $value) + { + if (is_array($value)) { + $node = $xml->addChild($key); + + $this->arrayToXml($value, $rootNodeName, $node); + } else { + $value = htmlentities($value); + + $xml->addChild($key, $value); + } + } + + return $xml->asXML(); + } + + /** + * loadData + * + * Load xml file and return array of data + * + * @param string $path Path to load xml data from + * @return array $array Array of data converted from xml + */ + public function loadData($path) + { + $contents = $this->doLoad($path); + + $simpleXml = simplexml_load_string($contents); + + return $this->prepareData($simpleXml); + } + + /** + * prepareData + * + * Prepare simple xml to array for return + * + * @param string $simpleXml + * @return array $return + */ + public function prepareData($simpleXml) + { + if ($simpleXml instanceof SimpleXMLElement) { + $children = $simpleXml->children(); + $return = null; + } + + foreach ($children as $element => $value) { + if ($value instanceof SimpleXMLElement) { + $values = (array) $value->children(); + + if (count($values) > 0) { + $return[$element] = $this->prepareData($value); + } else { + if ( ! isset($return[$element])) { + $return[$element] = (string) $value; + } else { + if ( ! is_array($return[$element])) { + $return[$element] = array($return[$element], (string) $value); + } else { + $return[$element][] = (string) $value; + } + } + } + } + } + + if (is_array($return)) { + return $return; + } else { + return array(); + } + } +} diff --git a/lib/Doctrine/TODO/Parser/Yml.php b/lib/Doctrine/TODO/Parser/Yml.php new file mode 100644 index 000000000..fae25e1d2 --- /dev/null +++ b/lib/Doctrine/TODO/Parser/Yml.php @@ -0,0 +1,74 @@ +. + */ + +/** + * Doctrine_Parser_Yml + * + * @package Doctrine + * @subpackage Parser + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 1080 $ + * @author Jonathan H. Wage + */ +class Doctrine_Parser_Yml extends Doctrine_Parser +{ + /** + * dumpData + * + * Dump an array of data to a specified path or return + * + * @param string $array Array of data to dump to yaml + * @param string $path Path to dump the yaml to + * @return string $yaml + * @return void + */ + public function dumpData($array, $path = null) + { + $spyc = new Doctrine_Spyc(); + + $data = $spyc->dump($array, false, false); + + return $this->doDump($data, $path); + } + + /** + * loadData + * + * Load and parse data from a yml file + * + * @param string $path Path to load yaml data from + * @return array $array Array of parsed yaml data + */ + public function loadData($path) + { + $contents = $this->doLoad($path); + + $spyc = new Doctrine_Spyc(); + + $array = $spyc->load($contents); + + return $array; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Parser/spyc.php b/lib/Doctrine/TODO/Parser/spyc.php new file mode 100644 index 000000000..6d146657c --- /dev/null +++ b/lib/Doctrine/TODO/Parser/spyc.php @@ -0,0 +1,881 @@ + + * @author Vlad Andersen + * @link http://spyc.sourceforge.net/ + * @copyright Copyright 2005-2006 Chris Wanstrath + * @license http://www.opensource.org/licenses/mit-license.php MIT License + * @package Doctrine + * @subpackage Spyc + */ + + /** + * A node, used by Doctrine_Spyc for parsing YAML. + * @package Doctrine + * @subpackage Spyc + */ + class Doctrine_YamlNode { + /**#@+ + * @access public + * @var string + */ + var $parent; + var $id; + + /**#@+*/ + /** + * @access public + * @var mixed + */ + var $data; + + /** + * @access public + * @var int + */ + var $indent; + + /** + * @access public + * @var bool + */ + var $children = false; + + /** + * The constructor assigns the node a unique ID. + * @access public + * @return void + */ + function Doctrine_YamlNode($nodeId) { + $this->id = $nodeId; + } + } + + /** + * The Simple PHP YAML Class. + * + * This class can be used to read a YAML file and convert its contents + * into a PHP array. It currently supports a very limited subsection of + * the YAML spec. + * + * Usage: + * + * $parser = new Doctrine_Spyc; + * $array = $parser->load($file); + * + * @package Doctrine + * @subpackage Spyc + */ + class Doctrine_Spyc { + + /** + * Load YAML into a PHP array statically + * + * The load method, when supplied with a YAML stream (string or file), + * will do its best to convert YAML in a file into a PHP array. Pretty + * simple. + * Usage: + * + * $array = Doctrine_Spyc::YAMLLoad('lucky.yaml'); + * print_r($array); + * + * @access public + * @return array + * @param string $input Path of YAML file or string containing YAML + */ + function YAMLLoad($input) { + $spyc = new Doctrine_Spyc; + return $spyc->load($input); + } + + /** + * Dump YAML from PHP array statically + * + * The dump method, when supplied with an array, will do its best + * to convert the array into friendly YAML. Pretty simple. Feel free to + * save the returned string as nothing.yaml and pass it around. + * + * Oh, and you can decide how big the indent is and what the wordwrap + * for folding is. Pretty cool -- just pass in 'false' for either if + * you want to use the default. + * + * Indent's default is 2 spaces, wordwrap's default is 40 characters. And + * you can turn off wordwrap by passing in 0. + * + * @access public + * @return string + * @param array $array PHP array + * @param int $indent Pass in false to use the default, which is 2 + * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) + */ + function YAMLDump($array,$indent = false,$wordwrap = false) { + $spyc = new Doctrine_Spyc; + return $spyc->dump($array,$indent,$wordwrap); + } + + /** + * Load YAML into a PHP array from an instantiated object + * + * The load method, when supplied with a YAML stream (string or file path), + * will do its best to convert the YAML into a PHP array. Pretty simple. + * Usage: + * + * $parser = new Doctrine_Spyc; + * $array = $parser->load('lucky.yaml'); + * print_r($array); + * + * @access public + * @return array + * @param string $input Path of YAML file or string containing YAML + */ + function load($input) { + // See what type of input we're talking about + // If it's not a file, assume it's a string + if ( ! empty($input) && (strpos($input, "\n") === false) + && file_exists($input)) { + $yaml = file($input); + } else { + $yaml = explode("\n",$input); + } + // Initiate some objects and values + $base = new Doctrine_YamlNode (1); + $base->indent = 0; + $this->_lastIndent = 0; + $this->_lastNode = $base->id; + $this->_inBlock = false; + $this->_isInline = false; + $this->_nodeId = 2; + + foreach ($yaml as $linenum => $line) { + $ifchk = trim($line); + + // If the line starts with a tab (instead of a space), throw a fit. + if (preg_match('/^(\t)+(\w+)/', $line)) { + $err = 'ERROR: Line '. ($linenum + 1) .' in your input YAML begins'. + ' with a tab. YAML only recognizes spaces. Please reformat.'; + die($err); + } + + if ($this->_inBlock === false && empty($ifchk)) { + continue; + } elseif ($this->_inBlock == true && empty($ifchk)) { + $last =& $this->_allNodes[$this->_lastNode]; + $last->data[key($last->data)] .= "\n"; + } elseif ($ifchk{0} != '#' && substr($ifchk,0,3) != '---') { + // Create a new node and get its indent + $node = new Doctrine_YamlNode ($this->_nodeId); + $this->_nodeId++; + + $node->indent = $this->_getIndent($line); + + // Check where the node lies in the hierarchy + if ($this->_lastIndent == $node->indent) { + // If we're in a block, add the text to the parent's data + if ($this->_inBlock === true) { + $parent =& $this->_allNodes[$this->_lastNode]; + $parent->data[key($parent->data)] .= trim($line).$this->_blockEnd; + } else { + // The current node's parent is the same as the previous node's + if (isset($this->_allNodes[$this->_lastNode])) { + $node->parent = $this->_allNodes[$this->_lastNode]->parent; + } + } + } elseif ($this->_lastIndent < $node->indent) { + if ($this->_inBlock === true) { + $parent =& $this->_allNodes[$this->_lastNode]; + $parent->data[key($parent->data)] .= trim($line).$this->_blockEnd; + } elseif ($this->_inBlock === false) { + // The current node's parent is the previous node + $node->parent = $this->_lastNode; + + // If the value of the last node's data was > or | we need to + // start blocking i.e. taking in all lines as a text value until + // we drop our indent. + $parent =& $this->_allNodes[$node->parent]; + $this->_allNodes[$node->parent]->children = true; + if (is_array($parent->data)) { + $chk = ''; + if (isset ($parent->data[key($parent->data)])) + $chk = $parent->data[key($parent->data)]; + if ($chk === '>') { + $this->_inBlock = true; + $this->_blockEnd = ' '; + $parent->data[key($parent->data)] = + str_replace('>','',$parent->data[key($parent->data)]); + $parent->data[key($parent->data)] .= trim($line).' '; + $this->_allNodes[$node->parent]->children = false; + $this->_lastIndent = $node->indent; + } elseif ($chk === '|') { + $this->_inBlock = true; + $this->_blockEnd = "\n"; + $parent->data[key($parent->data)] = + str_replace('|','',$parent->data[key($parent->data)]); + $parent->data[key($parent->data)] .= trim($line)."\n"; + $this->_allNodes[$node->parent]->children = false; + $this->_lastIndent = $node->indent; + } + } + } + } elseif ($this->_lastIndent > $node->indent) { + // Any block we had going is dead now + if ($this->_inBlock === true) { + $this->_inBlock = false; + if ($this->_blockEnd = "\n") { + $last =& $this->_allNodes[$this->_lastNode]; + $last->data[key($last->data)] = + trim($last->data[key($last->data)]); + } + } + + // We don't know the parent of the node so we have to find it + // foreach ($this->_allNodes as $n) { + foreach ($this->_indentSort[$node->indent] as $n) { + if ($n->indent == $node->indent) { + $node->parent = $n->parent; + } + } + } + + if ($this->_inBlock === false) { + // Set these properties with information from our current node + $this->_lastIndent = $node->indent; + // Set the last node + $this->_lastNode = $node->id; + // Parse the YAML line and return its data + $node->data = $this->_parseLine($line); + // Add the node to the master list + $this->_allNodes[$node->id] = $node; + // Add a reference to the parent list + $this->_allParent[intval($node->parent)][] = $node->id; + // Add a reference to the node in an indent array + $this->_indentSort[$node->indent][] =& $this->_allNodes[$node->id]; + // Add a reference to the node in a References array if this node + // has a YAML reference in it. + if ( + ( (is_array($node->data)) && + isset($node->data[key($node->data)]) && + ( ! is_array($node->data[key($node->data)])) ) + && + ( (preg_match('/^&([^ ]+)/',$node->data[key($node->data)])) + || + (preg_match('/^\*([^ ]+)/',$node->data[key($node->data)])) ) + ) { + $this->_haveRefs[] =& $this->_allNodes[$node->id]; + } elseif ( + ( (is_array($node->data)) && + isset($node->data[key($node->data)]) && + (is_array($node->data[key($node->data)])) ) + ) { + // Incomplete reference making code. Ugly, needs cleaned up. + foreach ($node->data[key($node->data)] as $d) { + if ( !is_array($d) && + ( (preg_match('/^&([^ ]+)/',$d)) + || + (preg_match('/^\*([^ ]+)/',$d)) ) + ) { + $this->_haveRefs[] =& $this->_allNodes[$node->id]; + } + } + } + } + } + } + unset($node); + + // Here we travel through node-space and pick out references (& and *) + $this->_linkReferences(); + + // Build the PHP array out of node-space + $trunk = $this->_buildArray(); + return $trunk; + } + + /** + * Dump PHP array to YAML + * + * The dump method, when supplied with an array, will do its best + * to convert the array into friendly YAML. Pretty simple. Feel free to + * save the returned string as tasteful.yaml and pass it around. + * + * Oh, and you can decide how big the indent is and what the wordwrap + * for folding is. Pretty cool -- just pass in 'false' for either if + * you want to use the default. + * + * Indent's default is 2 spaces, wordwrap's default is 40 characters. And + * you can turn off wordwrap by passing in 0. + * + * @access public + * @return string + * @param array $array PHP array + * @param int $indent Pass in false to use the default, which is 2 + * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) + */ + function dump($array,$indent = false,$wordwrap = false) { + // Dumps to some very clean YAML. We'll have to add some more features + // and options soon. And better support for folding. + + // New features and options. + if ($indent === false or !is_numeric($indent)) { + $this->_dumpIndent = 2; + } else { + $this->_dumpIndent = $indent; + } + + if ($wordwrap === false or !is_numeric($wordwrap)) { + $this->_dumpWordWrap = 40; + } else { + $this->_dumpWordWrap = $wordwrap; + } + + // New YAML document + $string = "---\n"; + + // Start at the base of the array and move through it. + foreach ($array as $key => $value) { + $string .= $this->_yamlize($key,$value,0); + } + return $string; + } + + /**** Private Properties ****/ + + /**#@+ + * @access private + * @var mixed + */ + var $_haveRefs; + var $_allNodes; + var $_allParent; + var $_lastIndent; + var $_lastNode; + var $_inBlock; + var $_isInline; + var $_dumpIndent; + var $_dumpWordWrap; + + /**#@+*/ + + /**** Public Properties ****/ + + /**#@+ + * @access public + * @var mixed + */ + var $_nodeId; + + /**#@+*/ + + /**** Private Methods ****/ + + /** + * Attempts to convert a key / value array item to YAML + * @access private + * @return string + * @param $key The name of the key + * @param $value The value of the item + * @param $indent The indent of the current node + */ + function _yamlize($key,$value,$indent) { + if (is_array($value)) { + // It has children. What to do? + // Make it the right kind of item + $string = $this->_dumpNode($key,NULL,$indent); + // Add the indent + $indent += $this->_dumpIndent; + // Yamlize the array + $string .= $this->_yamlizeArray($value,$indent); + } elseif ( ! is_array($value)) { + // It doesn't have children. Yip. + $string = $this->_dumpNode($key,$value,$indent); + } + return $string; + } + + /** + * Attempts to convert an array to YAML + * @access private + * @return string + * @param $array The array you want to convert + * @param $indent The indent of the current level + */ + function _yamlizeArray($array,$indent) { + if (is_array($array)) { + $string = ''; + foreach ($array as $key => $value) { + $string .= $this->_yamlize($key,$value,$indent); + } + return $string; + } else { + return false; + } + } + + /** + * Returns YAML from a key and a value + * @access private + * @return string + * @param $key The name of the key + * @param $value The value of the item + * @param $indent The indent of the current node + */ + function _dumpNode($key,$value,$indent) { + // do some folding here, for blocks + if (strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false) { + $value = $this->_doLiteralBlock($value,$indent); + } else { + $value = $this->_doFolding($value,$indent); + } + + if (is_bool($value)) { + $value = ($value) ? "true" : "false"; + } + + $spaces = str_repeat(' ',$indent); + + if (is_int($key)) { + // It's a sequence + $string = $spaces.'- '.$value."\n"; + } else { + // It's mapped + $string = $spaces.$key.': '.$value."\n"; + } + return $string; + } + + /** + * Creates a literal block for dumping + * @access private + * @return string + * @param $value + * @param $indent int The value of the indent + */ + function _doLiteralBlock($value,$indent) { + $exploded = explode("\n",$value); + $newValue = '|'; + $indent += $this->_dumpIndent; + $spaces = str_repeat(' ',$indent); + foreach ($exploded as $line) { + $newValue .= "\n" . $spaces . trim($line); + } + return $newValue; + } + + /** + * Folds a string of text, if necessary + * @access private + * @return string + * @param $value The string you wish to fold + */ + function _doFolding($value,$indent) { + // Don't do anything if wordwrap is set to 0 + if ($this->_dumpWordWrap === 0) { + return $value; + } + + if (strlen($value) > $this->_dumpWordWrap) { + $indent += $this->_dumpIndent; + $indent = str_repeat(' ',$indent); + $wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent"); + $value = ">\n".$indent.$wrapped; + } + return $value; + } + + /* Methods used in loading */ + + /** + * Finds and returns the indentation of a YAML line + * @access private + * @return int + * @param string $line A line from the YAML file + */ + function _getIndent($line) { + preg_match('/^\s{1,}/',$line,$match); + if ( ! empty($match[0])) { + $indent = substr_count($match[0],' '); + } else { + $indent = 0; + } + return $indent; + } + + /** + * Parses YAML code and returns an array for a node + * @access private + * @return array + * @param string $line A line from the YAML file + */ + function _parseLine($line) { + $line = trim($line); + + if(!preg_match("/\\\#/", $line)) { + $line = trim(preg_replace('/#.*$/', '', $line)); + } + + $array = array(); + + if (preg_match('/^-(.*):$/',$line)) { + // It's a mapped sequence + $key = trim(substr(substr($line,1),0,-1)); + $array[$key] = ''; + } elseif ($line[0] == '-' && substr($line,0,3) != '---') { + // It's a list item but not a new stream + if (strlen($line) > 1) { + $value = trim(substr($line,1)); + // Set the type of the value. Int, string, etc + $value = $this->_toType($value); + $array[] = $value; + } else { + $array[] = array(); + } + } elseif (preg_match('/^(.+):/',$line,$key)) { + // It's a key/value pair most likely + // If the key is in double quotes pull it out + if (preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) { + $value = trim(str_replace($matches[1],'',$line)); + $key = $matches[2]; + } else { + // Do some guesswork as to the key and the value + $explode = explode(':',$line); + $key = trim($explode[0]); + array_shift($explode); + $value = trim(implode(':',$explode)); + } + + // Set the type of the value. Int, string, etc + $value = $this->_toType($value); + if (empty($key)) { + $array[] = $value; + } else { + $array[$key] = $value; + } + } + return $array; + } + + /** + * Finds the type of the passed value, returns the value as the new type. + * @access private + * @param string $value + * @return mixed + */ + function _toType($value) { + if (preg_match('/^("(.*)"|\'(.*)\')/',$value,$matches)) { + $value = (string)preg_replace('/(\'\'|\\\\\')/',"'",end($matches)); + $value = preg_replace('/\\\\"/','"',$value); + } elseif (preg_match('/^\\[(.+)\\]$/',$value,$matches)) { + // Inline Sequence + + // Take out strings sequences and mappings + $explode = $this->_inlineEscape($matches[1]); + + // Propogate value array + $value = array(); + foreach ($explode as $v) { + $value[] = $this->_toType($v); + } + } elseif (strpos($value,': ')!==false && !preg_match('/^{(.+)/',$value)) { + // It's a map + $array = explode(': ',$value); + $key = trim($array[0]); + array_shift($array); + $value = trim(implode(': ',$array)); + $value = $this->_toType($value); + $value = array($key => $value); + } elseif (preg_match("/{(.+)}$/",$value,$matches)) { + // Inline Mapping + + // Take out strings sequences and mappings + $explode = $this->_inlineEscape($matches[1]); + + // Propogate value array + $array = array(); + foreach ($explode as $v) { + $array = $array + $this->_toType($v); + } + $value = $array; + } elseif (strtolower($value) == 'null' or $value == '' or $value == '~') { + $value = NULL; + } elseif (preg_match ('/^[0-9]+$/', $value)) { + // Cheeky change for compartibility with PHP < 4.2.0 + $value = (int)$value; + } elseif (in_array(strtolower($value), + array('true', 'on', '+', 'yes', 'y'))) { + $value = true; + } elseif (in_array(strtolower($value), + array('false', 'off', '-', 'no', 'n'))) { + $value = false; + } elseif (is_numeric($value)) { + $value = (float)$value; + } else { + // Just a normal string, right? + $value = trim(preg_replace('/#(.+)$/','',$value)); + } + + return $value; + } + + /** + * Used in inlines to check for more inlines or quoted strings + * @access private + * @return array + */ + function _inlineEscape($inline) { + // There's gotta be a cleaner way to do this... + // While pure sequences seem to be nesting just fine, + // pure mappings and mappings with sequences inside can't go very + // deep. This needs to be fixed. + + $saved_strings = array(); + + // Check for strings + $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/'; + if (preg_match_all($regex,$inline,$strings)) { + $saved_strings = $strings[0]; + $inline = preg_replace($regex,'YAMLString',$inline); + } + unset($regex); + + // Check for sequences + if (preg_match_all('/\[(.+)\]/U',$inline,$seqs)) { + $inline = preg_replace('/\[(.+)\]/U','YAMLSeq',$inline); + $seqs = $seqs[0]; + } + + // Check for mappings + if (preg_match_all('/{(.+)}/U',$inline,$maps)) { + $inline = preg_replace('/{(.+)}/U','YAMLMap',$inline); + $maps = $maps[0]; + } + + $explode = explode(', ',$inline); + + + // Re-add the sequences + if ( ! empty($seqs)) { + $i = 0; + foreach ($explode as $key => $value) { + if (strpos($value,'YAMLSeq') !== false) { + $explode[$key] = str_replace('YAMLSeq',$seqs[$i],$value); + ++$i; + } + } + } + + // Re-add the mappings + if ( ! empty($maps)) { + $i = 0; + foreach ($explode as $key => $value) { + if (strpos($value,'YAMLMap') !== false) { + $explode[$key] = str_replace('YAMLMap',$maps[$i],$value); + ++$i; + } + } + } + + // Re-add the strings + if ( ! empty($saved_strings)) { + $i = 0; + foreach ($explode as $key => $value) { + while (strpos($value,'YAMLString') !== false) { + $explode[$key] = preg_replace('/YAMLString/',$saved_strings[$i],$value, 1); + ++$i; + $value = $explode[$key]; + } + } + } + + return $explode; + } + + /** + * Builds the PHP array from all the YAML nodes we've gathered + * @access private + * @return array + */ + function _buildArray() { + $trunk = array(); + + if ( ! isset($this->_indentSort[0])) { + return $trunk; + } + + foreach ($this->_indentSort[0] as $n) { + if (empty($n->parent)) { + $this->_nodeArrayizeData($n); + // Check for references and copy the needed data to complete them. + $this->_makeReferences($n); + // Merge our data with the big array we're building + $trunk = $this->_array_kmerge($trunk,$n->data); + } + } + + return $trunk; + } + + /** + * Traverses node-space and sets references (& and *) accordingly + * @access private + * @return bool + */ + function _linkReferences() { + if (is_array($this->_haveRefs)) { + foreach ($this->_haveRefs as $node) { + if ( ! empty($node->data)) { + $key = key($node->data); + // If it's an array, don't check. + if (is_array($node->data[$key])) { + foreach ($node->data[$key] as $k => $v) { + $this->_linkRef($node,$key,$k,$v); + } + } else { + $this->_linkRef($node,$key); + } + } + } + } + return true; + } + + function _linkRef(&$n,$key,$k = NULL,$v = NULL) { + if (empty($k) && empty($v)) { + // Look for &refs + if (preg_match('/^&([^ ]+)/',$n->data[$key],$matches)) { + // Flag the node so we know it's a reference + $this->_allNodes[$n->id]->ref = substr($matches[0],1); + $this->_allNodes[$n->id]->data[$key] = + substr($n->data[$key],strlen($matches[0])+1); + // Look for *refs + } elseif (preg_match('/^\*([^ ]+)/',$n->data[$key],$matches)) { + $ref = substr($matches[0],1); + // Flag the node as having a reference + $this->_allNodes[$n->id]->refKey = $ref; + } + } elseif ( ! empty($k) && !empty($v)) { + if (preg_match('/^&([^ ]+)/',$v,$matches)) { + // Flag the node so we know it's a reference + $this->_allNodes[$n->id]->ref = substr($matches[0],1); + $this->_allNodes[$n->id]->data[$key][$k] = + substr($v,strlen($matches[0])+1); + // Look for *refs + } elseif (preg_match('/^\*([^ ]+)/',$v,$matches)) { + $ref = substr($matches[0],1); + // Flag the node as having a reference + $this->_allNodes[$n->id]->refKey = $ref; + } + } + } + + /** + * Finds the children of a node and aids in the building of the PHP array + * @access private + * @param int $nid The id of the node whose children we're gathering + * @return array + */ + function _gatherChildren($nid) { + $return = array(); + $node =& $this->_allNodes[$nid]; + if (is_array ($this->_allParent[$node->id])) { + foreach ($this->_allParent[$node->id] as $nodeZ) { + $z =& $this->_allNodes[$nodeZ]; + // We found a child + $this->_nodeArrayizeData($z); + // Check for references + $this->_makeReferences($z); + // Merge with the big array we're returning + // The big array being all the data of the children of our parent node + $return = $this->_array_kmerge($return,$z->data); + } + } + return $return; + } + + /** + * Turns a node's data and its children's data into a PHP array + * + * @access private + * @param array $node The node which you want to arrayize + * @return boolean + */ + function _nodeArrayizeData(&$node) { + if (is_array($node->data) && $node->children == true) { + // This node has children, so we need to find them + $childs = $this->_gatherChildren($node->id); + // We've gathered all our children's data and are ready to use it + $key = key($node->data); + $key = empty($key) ? 0 : $key; + // If it's an array, add to it of course + if (isset ($node->data[$key])) { + if (is_array($node->data[$key])) { + $node->data[$key] = $this->_array_kmerge($node->data[$key],$childs); + } else { + $node->data[$key] = $childs; + } + } else { + $node->data[$key] = $childs; + } + } elseif ( ! is_array($node->data) && $node->children == true) { + // Same as above, find the children of this node + $childs = $this->_gatherChildren($node->id); + $node->data = array(); + $node->data[] = $childs; + } + + // We edited $node by reference, so just return true + return true; + } + + /** + * Traverses node-space and copies references to / from this object. + * @access private + * @param object $z A node whose references we wish to make real + * @return bool + */ + function _makeReferences(&$z) { + // It is a reference + if (isset($z->ref)) { + $key = key($z->data); + // Copy the data to this object for easy retrieval later + $this->ref[$z->ref] =& $z->data[$key]; + // It has a reference + } elseif (isset($z->refKey)) { + if (isset($this->ref[$z->refKey])) { + $key = key($z->data); + // Copy the data from this object to make the node a real reference + $z->data[$key] =& $this->ref[$z->refKey]; + } + } + return true; + } + + + /** + * Merges arrays and maintains numeric keys. + * + * An ever-so-slightly modified version of the array_kmerge() function posted + * to php.net by mail at nospam dot iaindooley dot com on 2004-04-08. + * + * http://us3.php.net/manual/en/function.array-merge.php#41394 + * + * @access private + * @param array $arr1 + * @param array $arr2 + * @return array + */ + function _array_kmerge($arr1,$arr2) { + if( ! is_array($arr1)) $arr1 = array(); + if( ! is_array($arr2)) $arr2 = array(); + + $keys = array_merge(array_keys($arr1),array_keys($arr2)); + $vals = array_merge(array_values($arr1),array_values($arr2)); + $ret = array(); + foreach($keys as $key) { + list($unused,$val) = each($vals); + if (isset($ret[$key]) and is_int($key)) $ret[] = $val; else $ret[$key] = $val; + } + return $ret; + } + } +?> diff --git a/lib/Doctrine/TODO/Record/Generator.php b/lib/Doctrine/TODO/Record/Generator.php new file mode 100644 index 000000000..35f31ca2a --- /dev/null +++ b/lib/Doctrine/TODO/Record/Generator.php @@ -0,0 +1,286 @@ +. + */ + +/** + * Doctrine_Record_Generator + * + * @author Konsta Vesterinen + * @package Doctrine + * @subpackage Plugin + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + * @todo Rename. Move. Reimpl? + */ +abstract class Doctrine_Record_Generator +{ + /** + * @var array $_options an array of plugin specific options + */ + protected $_options = array('generateFiles' => false, + 'identifier' => false, + 'generateFiles' => false, + 'table' => false, + 'pluginTable' => false, + 'children' => array()); + + protected $_initialized = false; + /** + * __get + * an alias for getOption + * + * @param string $option + */ + public function __get($option) + { + if (isset($this->_options[$option])) { + return $this->_options[$option]; + } + return null; + } + + /** + * __isset + * + * @param string $option + */ + public function __isset($option) + { + return isset($this->_options[$option]); + } + + /** + * returns the value of an option + * + * @param $option the name of the option to retrieve + * @return mixed the value of the option + */ + public function getOption($name) + { + if ( ! isset($this->_options[$name])) { + throw new Doctrine_Plugin_Exception('Unknown option ' . $name); + } + + return $this->_options[$name]; + } + + /** + * sets given value to an option + * + * @param $option the name of the option to be changed + * @param $value the value of the option + * @return Doctrine_Plugin this object + */ + public function setOption($name, $value) + { + $this->_options[$name] = $value; + + return $this; + } + + public function addChild(Doctrine_Record_Generator $template) + { + $this->_options['children'][] = $template; + } + + /** + * returns all options and their associated values + * + * @return array all options as an associative array + */ + public function getOptions() + { + return $this->_options; + } + + public function initialize($table) + { + if ($this->_initialized) { + return false; + } + + $this->_initialized = true; + + $this->initOptions(); + + $table->addGenerator($this, get_class($this)); + + $this->_options['table'] = $table; + + $this->_options['className'] = str_replace('%CLASS%', + $this->_options['table']->getComponentName(), + $this->_options['className']); + + // check that class doesn't exist (otherwise we cannot create it) + if (class_exists($this->_options['className'])) { + return false; + } + + $conn = $this->_options['table']->getConnection(); + + $this->_table = new Doctrine_Table($this->_options['className'], $conn); + + $conn->addTable($this->_table); + + $fk = $this->buildForeignKeys($this->_options['table']); + + $this->_table->setColumns($fk); + + $this->buildRelation(); + + $this->setTableDefinition(); + $this->setUp(); + + $this->generateClass($this->_table->getColumns()); + + $this->buildChildDefinitions(); + + } + /** + * empty template method for providing the concrete plugins the ability + * to initialize options before the actual definition is being built + * + * @return void + */ + public function initOptions() + { + + } + public function buildChildDefinitions() + { + if ( ! isset($this->_options['children'])) { + throw new Doctrine_Plugin_Exception("Unknown option 'children'."); + } + + foreach ($this->_options['children'] as $child) { + $this->_table->addGenerator($child, get_class($child)); + + $child->setTable($this->_table); + + $child->setUp(); + } + } + + /** + * generates foreign keys for the plugin table based on the owner table + * + * the foreign keys generated by this method can be used for + * setting the relations between the owner and the plugin classes + * + * @param Doctrine_Table $table the table object that owns the plugin + * @return array an array of foreign key definitions + */ + public function buildForeignKeys($table) + { + $fk = array(); + + foreach ((array) $table->getIdentifier() as $column) { + $def = $table->getDefinitionOf($column); + + unset($def['autoincrement']); + unset($def['sequence']); + unset($def['primary']); + + $col = $column; + + $def['primary'] = true; + $fk[$col] = $def; + } + return $fk; + } + + public function buildLocalRelation() + { + $options = array('local' => $this->_options['table']->getIdentifier(), + 'foreign' => $this->_options['table']->getIdentifier(), + 'type' => Doctrine_Relation::MANY); + + $options['type'] = Doctrine_Relation::ONE; + $options['onDelete'] = 'CASCADE'; + $options['onUpdate'] = 'CASCADE'; + + $this->_table->getRelationParser()->bind($this->_options['table']->getComponentName(), $options); + } + + public function buildForeignRelation($alias = null) + { + $options = array('local' => $this->_options['table']->getIdentifier(), + 'foreign' => $this->_options['table']->getIdentifier(), + 'type' => Doctrine_Relation::MANY); + + $aliasStr = ''; + + if ($alias !== null) { + $aliasStr = ' as ' . $alias; + } + + $this->_options['table']->getRelationParser()->bind($this->_table->getComponentName() . $aliasStr, + $options); + } + + /** + * build a relation array to given table + * + * this method can be used for generating the relation from the plugin + * table to the owner table + * + * @return array the generated relation array + */ + public function buildRelation() + { + $this->buildForeignRelation(); + $this->buildLocalRelation(); + } + + /** + * generates the class definition for plugin class + * + * @param array $columns the plugin class columns, keys representing the column names + * and values as column definitions + * + * @param array $relations the bound relations of the plugin class + * + * @param array $options plugin class options, keys representing the option names + * and values as option values + * @return void + */ + public function generateClass(array $columns = array(), array $relations = array(), array $options = array()) + { + $options['className'] = $this->_options['className']; + + $builder = new Doctrine_Builder_Record(); + + if ($this->_options['generateFiles']) { + if (isset($this->_options['generatePath']) && $this->_options['generatePath']) { + $builder->setTargetPath($this->_options['generatePath']); + + $builder->buildRecord($options, $columns, $relations); + } else { + throw new Doctrine_Record_Exception('If you wish to generate files then you must specify the path to generate the files in.'); + } + } else { + $def = $builder->buildDefinition($options, $columns, $relations); + + eval($def); + } + } +} diff --git a/lib/Doctrine/TODO/Search/Analyzer.php b/lib/Doctrine/TODO/Search/Analyzer.php new file mode 100644 index 000000000..28b55bcd7 --- /dev/null +++ b/lib/Doctrine/TODO/Search/Analyzer.php @@ -0,0 +1,39 @@ +. + */ + +/** + * Doctrine_Search_Analyzer + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Search_Analyzer implements Doctrine_Search_Analyzer_Interface +{ + public function analyze($text) + { + + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Search/Analyzer/Exception.php b/lib/Doctrine/TODO/Search/Analyzer/Exception.php new file mode 100644 index 000000000..53829108a --- /dev/null +++ b/lib/Doctrine/TODO/Search/Analyzer/Exception.php @@ -0,0 +1,34 @@ +. + */ +Doctrine::autoload('Doctrine_Search_Exception'); +/** + * Doctrine_Search_Analyzer_Exception + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Search_Analyzer_Exception extends Doctrine_Search_Exception +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Search/Analyzer/Interface.php b/lib/Doctrine/TODO/Search/Analyzer/Interface.php new file mode 100644 index 000000000..c810d2b3b --- /dev/null +++ b/lib/Doctrine/TODO/Search/Analyzer/Interface.php @@ -0,0 +1,36 @@ +. + */ + +/** + * Doctrine_Search_Analyzer_Interface + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +interface Doctrine_Search_Analyzer_Interface +{ + public function analyze($text); +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Search/Analyzer/Standard.php b/lib/Doctrine/TODO/Search/Analyzer/Standard.php new file mode 100644 index 000000000..aaa7d6f00 --- /dev/null +++ b/lib/Doctrine/TODO/Search/Analyzer/Standard.php @@ -0,0 +1,298 @@ +. + */ + +/** + * Doctrine_Search_Analyzer_Standard + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Search_Analyzer_Standard implements Doctrine_Search_Analyzer_Interface +{ + protected static $_stopwords = array( + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '10', + 'a', + 'about', + 'after', + 'all', + 'almost', + 'along', + 'also', + 'although', + 'amp', + 'an', + 'and', + 'another', + 'any', + 'are', + 'area', + 'arent', + 'around', + 'as', + 'at', + 'available', + 'back', + 'be', + 'because', + 'been', + 'before', + 'being', + 'best', + 'better', + 'big', + 'bit', + 'both', + 'but', + 'by', + 'c', + 'came', + 'can', + 'capable', + 'control', + 'could', + 'course', + 'd', + 'dan', + 'day', + 'decided', + 'did', + 'didn', + 'different', + 'div', + 'do', + 'doesn', + 'don', + 'down', + 'drive', + 'e', + 'each', + 'easily', + 'easy', + 'edition', + 'either', + 'end', + 'enough', + 'even', + 'every', + 'example', + 'few', + 'find', + 'first', + 'for', + 'found', + 'from', + 'get', + 'go', + 'going', + 'good', + 'got', + 'gt', + 'had', + 'hard', + 'has', + 'have', + 'he', + 'her', + 'here', + 'how', + 'i', + 'if', + 'in', + 'into', + 'is', + 'isn', + 'it', + 'just', + 'know', + 'last', + 'left', + 'li', + 'like', + 'little', + 'll', + 'long', + 'look', + 'lot', + 'lt', + 'm', + 'made', + 'make', + 'many', + 'mb', + 'me', + 'menu', + 'might', + 'mm', + 'more', + 'most', + 'much', + 'my', + 'name', + 'nbsp', + 'need', + 'new', + 'no', + 'not', + 'now', + 'number', + 'of', + 'off', + 'old', + 'on', + 'one', + 'only', + 'or', + 'original', + 'other', + 'our', + 'out', + 'over', + 'part', + 'place', + 'point', + 'pretty', + 'probably', + 'problem', + 'put', + 'quite', + 'quot', + 'r', + 're', + 'really', + 'results', + 'right', + 's', + 'same', + 'saw', + 'see', + 'set', + 'several', + 'she', + 'sherree', + 'should', + 'since', + 'size', + 'small', + 'so', + 'some', + 'something', + 'special', + 'still', + 'stuff', + 'such', + 'sure', + 'system', + 't', + 'take', + 'than', + 'that', + 'the', + 'their', + 'them', + 'then', + 'there', + 'these', + 'they', + 'thing', + 'things', + 'think', + 'this', + 'those', + 'though', + 'through', + 'time', + 'to', + 'today', + 'together', + 'too', + 'took', + 'two', + 'up', + 'us', + 'use', + 'used', + 'using', + 've', + 'very', + 'want', + 'was', + 'way', + 'we', + 'well', + 'went', + 'were', + 'what', + 'when', + 'where', + 'which', + 'while', + 'white', + 'who', + 'will', + 'with', + 'would', + 'yet', + 'you', + 'your', + 'yours' + ); + + public function analyze($text) + { + $text = preg_replace('/[\'`´"]/', '', $text); + $text = preg_replace('/[^A-Za-z0-9]/', ' ', $text); + $text = str_replace(' ', ' ', $text); + + $terms = explode(' ', $text); + + $ret = array(); + if ( ! empty($terms)) { + foreach ($terms as $i => $term) { + if (empty($term)) { + continue; + } + $lower = strtolower(trim($term)); + + if (in_array($lower, self::$_stopwords)) { + continue; + } + + $ret[$i] = $lower; + } + } + return $ret; + } +} diff --git a/lib/Doctrine/TODO/Search/Exception.php b/lib/Doctrine/TODO/Search/Exception.php new file mode 100644 index 000000000..d6bc83c34 --- /dev/null +++ b/lib/Doctrine/TODO/Search/Exception.php @@ -0,0 +1,34 @@ +. + */ +Doctrine::autoload('Doctrine_Exception'); +/** + * Doctrine_Search_Exception + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Search_Exception extends Doctrine_Exception +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Search/File.php b/lib/Doctrine/TODO/Search/File.php new file mode 100644 index 000000000..75ca6c1a6 --- /dev/null +++ b/lib/Doctrine/TODO/Search/File.php @@ -0,0 +1,80 @@ +. + */ + +/** + * Doctrine_Search + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Search_File extends Doctrine_Search +{ + /** + * constructor + * + * @param array $options an array of plugin options + */ + public function __construct(array $options = array()) + { + parent::__construct($options); + + if ( ! isset($this->_options['resource'])) { + $table = new Doctrine_Table('File', Doctrine_Manager::connection()); + + $table->setColumn('url', 'string', 255, array('primary' => true)); + } + + if (empty($this->_options['fields'])) { + $this->_options['fields'] = array('url', 'content'); + } + + $this->initialize($table); + } + public function buildRelation() + { + + } + /** + * indexes given directory + * + * @param string $dir the name of the directory to index + * @return void + */ + public function indexDirectory($dir) + { + $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), + RecursiveIteratorIterator::LEAVES_ONLY); + + foreach ($it as $file) { + if (strpos($file, DIRECTORY_SEPARATOR . '.svn') !== false) { + continue; + } + + $this->updateIndex(array('url' => $file->getPathName(), + 'content' => file_get_contents($file))); + } + } +} diff --git a/lib/Doctrine/TODO/Search/Indexer.php b/lib/Doctrine/TODO/Search/Indexer.php new file mode 100644 index 000000000..b07144d28 --- /dev/null +++ b/lib/Doctrine/TODO/Search/Indexer.php @@ -0,0 +1,75 @@ +. + */ + +/** + * Doctrine_Search_Indexer + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Search_Indexer +{ + public function indexDirectory($dir) + { + if ( ! file_exists($dir)) { + throw new Doctrine_Search_Indexer_Exception('Unknown directory ' . $dir); + } + + $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY); + + $files = array(); + foreach ($it as $file) { + $name = $file->getPathName(); + if (strpos($name, '.svn') === false) { + $files[] = $name; + } + } + + $q = new Doctrine_Query(); + $q->delete() + ->from('Doctrine_File f') + ->where('f.url LIKE ?', array($dir . '%')) + ->execute(); + + // clear the index + $q = new Doctrine_Query(); + $q->delete() + ->from('Doctrine_File_Index i') + ->where('i.file_id = ?') + ->execute(); + + + $conn = Doctrine_Manager::connection(); + + $coll = new Doctrine_Collection('Doctrine_File'); + + foreach ($files as $file) { + $coll[]->url = $file; + } + + $coll->save(); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Search/Indexer/Dir.php b/lib/Doctrine/TODO/Search/Indexer/Dir.php new file mode 100644 index 000000000..ea2dedfcf --- /dev/null +++ b/lib/Doctrine/TODO/Search/Indexer/Dir.php @@ -0,0 +1,47 @@ +. + */ + +/** + * Doctrine_Search_Indexer_Dir + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Search_Indexer_Dir +{ + public function add($dir) + { + if ( ! file_exists($dir)) { + throw new Doctrine_Search_Indexer_Exception('Unknown directory ' . $dir); + } + + $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY); + + foreach ($it as $file) { + $this->indexFile($file); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Search/Indexer/Exception.php b/lib/Doctrine/TODO/Search/Indexer/Exception.php new file mode 100644 index 000000000..3595144cf --- /dev/null +++ b/lib/Doctrine/TODO/Search/Indexer/Exception.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Search_Indexer + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Search_Indexer_Exception extends Doctrine_Search_Exception +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Search/Listener.php b/lib/Doctrine/TODO/Search/Listener.php new file mode 100644 index 000000000..6e97ccb1e --- /dev/null +++ b/lib/Doctrine/TODO/Search/Listener.php @@ -0,0 +1,56 @@ +. + */ + +/** + * Doctrine_Search_Listener + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Search_Listener extends Doctrine_Record_Listener +{ + protected $_search; + + public function __construct(Doctrine_Search $search) + { + $this->_search = $search; + } + + public function preUpdate(Doctrine_Event $event) + { + } + + public function postUpdate(Doctrine_Event $event) + { + + } + public function postInsert(Doctrine_Event $event) + { + $record = $event->getInvoker(); + + $this->_search->updateIndex($record->toArray()); + } +} diff --git a/lib/Doctrine/TODO/Search/Parser.php b/lib/Doctrine/TODO/Search/Parser.php new file mode 100644 index 000000000..8710e1cd2 --- /dev/null +++ b/lib/Doctrine/TODO/Search/Parser.php @@ -0,0 +1,41 @@ +. + */ + +/** + * Doctrine_Search_Parser_Standard + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Search_Parser +{ + public function parse($file) + { + $contents = file_get_contents($file); + + return array('url' => $file, 'contents' => $contents); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Search/Query.php b/lib/Doctrine/TODO/Search/Query.php new file mode 100644 index 000000000..466574e99 --- /dev/null +++ b/lib/Doctrine/TODO/Search/Query.php @@ -0,0 +1,235 @@ +. + */ + +/** + * Doctrine_Search_Query + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Search_Query +{ + + /** + * @var Doctrine_Table $_table the index table + */ + protected $_table = array(); + + protected $_sql = ''; + + protected $_params = array(); + + protected $_words = array(); + + protected $_tokenizer; + + protected $_condition; + + /** + * @param Doctrine_Table $_table the index table + */ + public function __construct($table) + { + if (is_string($table)) { + $table = Doctrine_Manager::table($table); + } else { + if ( ! $table instanceof Doctrine_Table) { + throw new Doctrine_Search_Exception('Invalid argument type. Expected instance of Doctrine_Table.'); + } + } + + $this->_tokenizer = new Doctrine_Query_Tokenizer(); + $this->_table = $table; + + $foreignId = current(array_diff($this->_table->getColumnNames(), array('keyword', 'field', 'position'))); + + $this->_condition = $foreignId . ' %s (SELECT ' . $foreignId . ' FROM ' . $this->_table->getTableName() . ' WHERE '; + } + + + public function query($text) + { + $text = trim($text); + + $foreignId = current(array_diff($this->_table->getColumnNames(), array('keyword', 'field', 'position'))); + + $weighted = false; + if (strpos($text, '^') === false) { + $select = 'SELECT COUNT(keyword) AS relevance, ' . $foreignId; + $from = 'FROM ' . $this->_table->getTableName(); + } else { + // organize terms according weights + $weighted = true; + + $select = 'SELECT SUM(sub_relevance) AS relevance, ' . $foreignId; + $from = 'FROM ' ; + } + + $where = 'WHERE '; + $where .= $this->parseClause($text); + + $groupby = 'GROUP BY ' . $foreignId; + $orderby = 'ORDER BY relevance DESC'; + + $this->_sql = $select . ' ' . $from . ' ' . $where . ' ' . $groupby . ' ' . $orderby; + } + + public function parseClause($originalClause, $recursive = false) + { + $clause = $this->_tokenizer->bracketTrim($originalClause); + + $brackets = false; + + if ($clause !== $originalClause) { + $brackets = true; + } + + $foreignId = current(array_diff($this->_table->getColumnNames(), array('keyword', 'field', 'position'))); + + $terms = $this->_tokenizer->sqlExplode($clause, ' OR ', '(', ')'); + + $ret = array(); + + if (count($terms) > 1) { + $leavesOnly = true; + + foreach ($terms as $k => $term) { + if ($this->isExpression($term)) { + $ret[$k] = $this->parseClause($term, true); + $leavesOnly = false; + } else { + $ret[$k] = $this->parseTerm($term); + } + } + + $return = implode(' OR ', $ret); + + if ($leavesOnly && $recursive) { + $return = sprintf($this->_condition, 'IN') . $return . ')'; + $brackets = false; + } + } else { + $terms = $this->_tokenizer->sqlExplode($clause, ' ', '(', ')'); + + if (count($terms) === 1 && ! $recursive) { + $return = $this->parseTerm($clause); + } else { + foreach ($terms as $k => $term) { + $term = trim($term); + + if ($term === 'AND') { + continue; + } + + if (substr($term, 0, 1) === '-') { + $operator = 'NOT IN'; + $term = substr($term, 1); + } else { + $operator = 'IN'; + } + + if ($this->isExpression($term)) { + $ret[$k] = $this->parseClause($term, true); + } else { + $ret[$k] = sprintf($this->_condition, $operator) . $this->parseTerm($term) . ')'; + } + } + $return = implode(' AND ', $ret); + } + } + + if ($brackets) { + return '(' . $return . ')'; + } else { + return $return; + } + } + public function isExpression($term) + { + if (strpos($term, '(') !== false) { + return true; + } else { + $terms = $this->_tokenizer->quoteExplode($term); + + return (count($terms) > 1); + } + } + + public function parseTerm($term) + { + $negation = false; + + if (strpos($term, "'") === false) { + $where = $this->parseWord($term); + } else { + $term = trim($term, "' "); + + $terms = $this->_tokenizer->quoteExplode($term); + $where = $this->parseWord($terms[0]); + + foreach ($terms as $k => $word) { + if ($k === 0) { + continue; + } + $where .= ' AND (position + ' . $k . ') = (SELECT position FROM ' . $this->_table->getTableName() . ' WHERE ' . $this->parseWord($word) . ')'; + } + } + return $where; + } + public function parseWord($word) + { + $this->_words[] = str_replace('*', '', $word); + + if (strpos($word, '?') !== false || + strpos($word, '*') !== false) { + + $word = str_replace('*', '%', $word); + + $where = 'keyword LIKE ?'; + + $params = array($word); + } else { + $where = 'keyword = ?'; + } + + $this->_params[] = $word; + + return $where; + } + + public function getWords() + { + return $this->_words; + } + public function getParams() + { + return $this->_params; + } + public function getSql() + { + return $this->_sql; + } +} diff --git a/lib/Doctrine/TODO/Search/Record.php b/lib/Doctrine/TODO/Search/Record.php new file mode 100644 index 000000000..95015c003 --- /dev/null +++ b/lib/Doctrine/TODO/Search/Record.php @@ -0,0 +1,47 @@ +. + */ + +/** + * Doctrine_Search_Record + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Search_Record extends Doctrine_Template +{ + public function setTableDefinition() + { + $this->hasColumn('keyword', 'string', 250, array('notnull' => true)); + $this->hasColumn('field', 'string', 50, array('notnull' => true)); + $this->hasColumn('position', 'integer', 8); + // depending on the identifiers of the owner record this record + // has also one to many foreign key columns + } + public function setUp() + { + $this->hasOne('[Component]', array('onDelete' => 'CASCADE')); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Search/Scorer.php b/lib/Doctrine/TODO/Search/Scorer.php new file mode 100644 index 000000000..d8ac7b8d0 --- /dev/null +++ b/lib/Doctrine/TODO/Search/Scorer.php @@ -0,0 +1,63 @@ +. + */ + +/** + * Doctrine_Search_Scorer + * + * @package Doctrine + * @subpackage Search + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Search_Scorer +{ + protected $_resultSet; + + protected $_components = array(); + + public function __construct($resultSet) + { + $this->_resultSet = $resultSet; + } + + public function addComponent($component) + { + $this->_components[] = $component; + } + + public function process() + { + foreach ($this->_resultSet as $mainRow) { + if (isset($mainRow[$component])) { + if ( ! is_array($mainRow[$component])) { + throw new Doctrine_Search_Exception('Wrong data type in result set.'); + } + + foreach ($mainRow[$component] as $indexRow) { + + } + } + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/BuildAll.php b/lib/Doctrine/TODO/Task/BuildAll.php new file mode 100644 index 000000000..bb71c7f69 --- /dev/null +++ b/lib/Doctrine/TODO/Task/BuildAll.php @@ -0,0 +1,65 @@ +. + */ + +/** + * Doctrine_Task_BuildAll + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_BuildAll extends Doctrine_Task +{ + public $description = 'Calls generate-models-from-yaml, create-db, and create-tables', + $requiredArguments = array(), + $optionalArguments = array(); + + protected $models, + $tables; + + public function __construct($dispatcher = null) + { + parent::__construct($dispatcher); + + $this->models = new Doctrine_Task_GenerateModelsYaml($this->dispatcher); + $this->createDb = new Doctrine_Task_CreateDb($this->dispatcher); + $this->tables = new Doctrine_Task_CreateTables($this->dispatcher); + + $this->requiredArguments = array_merge($this->requiredArguments, $this->models->requiredArguments, $this->createDb->requiredArguments, $this->tables->requiredArguments); + $this->optionalArguments = array_merge($this->optionalArguments, $this->models->optionalArguments, $this->createDb->optionalArguments, $this->tables->optionalArguments); + } + + public function execute() + { + $this->models->setArguments($this->getArguments()); + $this->models->execute(); + + $this->createDb->setArguments($this->getArguments()); + $this->createDb->execute(); + + $this->tables->setArguments($this->getArguments()); + $this->tables->execute(); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/BuildAllLoad.php b/lib/Doctrine/TODO/Task/BuildAllLoad.php new file mode 100644 index 000000000..b4e50311b --- /dev/null +++ b/lib/Doctrine/TODO/Task/BuildAllLoad.php @@ -0,0 +1,58 @@ +. + */ + +/** + * Doctrine_Task_BuildAllLoad + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_BuildAllLoad extends Doctrine_Task +{ + public $description = 'Calls build-all, and load-data', + $requiredArguments = array(), + $optionalArguments = array(); + + public function __construct($dispatcher = null) + { + parent::__construct($dispatcher); + + $this->buildAll = new Doctrine_Task_BuildAll($this->dispatcher); + $this->loadData = new Doctrine_Task_LoadData($this->dispatcher); + + $this->requiredArguments = array_merge($this->requiredArguments, $this->buildAll->requiredArguments, $this->loadData->requiredArguments); + $this->optionalArguments = array_merge($this->optionalArguments, $this->buildAll->optionalArguments, $this->loadData->optionalArguments); + } + + public function execute() + { + $this->buildAll->setArguments($this->getArguments()); + $this->buildAll->execute(); + + $this->loadData->setArguments($this->getArguments()); + $this->loadData->execute(); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/BuildAllReload.php b/lib/Doctrine/TODO/Task/BuildAllReload.php new file mode 100644 index 000000000..efd258dc2 --- /dev/null +++ b/lib/Doctrine/TODO/Task/BuildAllReload.php @@ -0,0 +1,58 @@ +. + */ + +/** + * Doctrine_Task_BuildAllReload + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_BuildAllReload extends Doctrine_Task +{ + public $description = 'Calls rebuild-db and load-data', + $requiredArguments = array(), + $optionalArguments = array(); + + public function __construct($dispatcher = null) + { + parent::__construct($dispatcher); + + $this->rebuildDb = new Doctrine_Task_RebuildDb($this->dispatcher); + $this->loadData = new Doctrine_Task_LoadData($this->dispatcher); + + $this->requiredArguments = array_merge($this->requiredArguments, $this->rebuildDb->requiredArguments, $this->loadData->requiredArguments); + $this->optionalArguments = array_merge($this->optionalArguments, $this->rebuildDb->optionalArguments, $this->loadData->optionalArguments); + } + + public function execute() + { + $this->rebuildDb->setArguments($this->getArguments()); + $this->rebuildDb->execute(); + + $this->loadData->setArguments($this->getArguments()); + $this->loadData->execute(); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/Compile.php b/lib/Doctrine/TODO/Task/Compile.php new file mode 100644 index 000000000..d1b4ceaab --- /dev/null +++ b/lib/Doctrine/TODO/Task/Compile.php @@ -0,0 +1,46 @@ +. + */ + +/** + * Doctrine_Task_Compile + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_Compile extends Doctrine_Task +{ + public $description = 'Compile doctrine classes in to one single php file', + $requiredArguments = array(), + $optionalArguments = array('drivers' => 'Specify list of drivers you wish to compile. Ex: mysql|mssql|sqlite', + 'compiled_path' => 'The path where you want to write the compiled doctrine libs.'); + + public function execute() + { + $compiledPath = Doctrine_Compiler::compile($this->getArgument('compiled_path'), $this->getArgument('drivers', array())); + + $this->notify('Compiled Doctrine successfully to: ' . $compiledPath); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/CreateDb.php b/lib/Doctrine/TODO/Task/CreateDb.php new file mode 100644 index 000000000..c00b577fa --- /dev/null +++ b/lib/Doctrine/TODO/Task/CreateDb.php @@ -0,0 +1,48 @@ +. + */ + +/** + * Doctrine_Task_CreateDb + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_CreateDb extends Doctrine_Task +{ + public $description = 'Create all databases for your connections. If the database already exists, nothing happens.', + $optionalArguments = array(); + + public function execute() + { + $results = Doctrine::createDatabases(); + + foreach ($results as $name => $result) { + $msg = $result instanceof Exception ? 'Could not create database for connection: "' .$name . '." Failed with exception: ' . $result->getMessage():$result; + + $this->notify($msg); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/CreateTables.php b/lib/Doctrine/TODO/Task/CreateTables.php new file mode 100644 index 000000000..213e7b335 --- /dev/null +++ b/lib/Doctrine/TODO/Task/CreateTables.php @@ -0,0 +1,45 @@ +. + */ + +/** + * Doctrine_Task_CreateTables + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_CreateTables extends Doctrine_Task +{ + public $description = 'Create tables for all existing database connections. If table exists nothing happens.', + $requiredArguments = array('models_path' => 'Specify path to your models directory.'), + $optionalArguments = array(); + + public function execute() + { + Doctrine::createTablesFromModels($this->getArgument('models_path')); + + $this->dispatcher->notify('Created tables successfully'); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/Dql.php b/lib/Doctrine/TODO/Task/Dql.php new file mode 100644 index 000000000..0f706399f --- /dev/null +++ b/lib/Doctrine/TODO/Task/Dql.php @@ -0,0 +1,76 @@ +. + */ + +/** + * Doctrine_Task_Dql + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_Dql extends Doctrine_Task +{ + public $description = 'Execute dql query and display the results', + $requiredArguments = array('models_path' => 'Specify path to your Doctrine_Record definitions.', + 'dql_query' => 'Specify the complete dql query to execute.'), + $optionalArguments = array('params' => 'Comma separated list of the params to replace the ? tokens in the dql'); + + public function execute() + { + Doctrine::loadModels($this->getArgument('models_path')); + + $dql = $this->getArgument('dql_query'); + + $query = new Doctrine_Query(); + + $params = $this->getArgument('params'); + $params = $params ? explode(',', $params):array(); + + $this->notify('executing: "' . $dql . '" (' . implode(', ', $params) . ')'); + + $results = $query->query($dql); + + $this->_printResults($results); + } + + protected function _printResults($data) + { + $array = $data->toArray(true); + + $yaml = Doctrine_Parser::dump($array, 'yml'); + $lines = explode("\n", $yaml); + + unset($lines[0]); + $lines[1] = $data->getTable()->getOption('name') . ':'; + + foreach ($lines as $yamlLine) { + $line = trim($yamlLine); + + if ($line) { + $this->notify($yamlLine); + } + } + } +} diff --git a/lib/Doctrine/TODO/Task/DropDb.php b/lib/Doctrine/TODO/Task/DropDb.php new file mode 100644 index 000000000..7eb1ab092 --- /dev/null +++ b/lib/Doctrine/TODO/Task/DropDb.php @@ -0,0 +1,59 @@ +. + */ + +/** + * Doctrine_Task_DropDb + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_DropDb extends Doctrine_Task +{ + public $description = 'Drop database for all existing connections', + $requiredArguments = array(), + $optionalArguments = array('force' => 'Whether or not to force the drop database task'); + + public function execute() + { + if ( ! $this->getArgument('force')) { + $answer = $this->ask('Are you sure you wish to drop your databases? (y/n)'); + + if ($answer != 'y') { + $this->notify('Successfully cancelled'); + + return; + } + } + + $results = Doctrine::dropDatabases(); + + foreach ($results as $name => $result) { + $msg = $result instanceof Exception ? 'Could not drop database for connection: "' .$name . '." Failed with exception: ' . $result->getMessage():$result; + + $this->notify($msg); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/DumpData.php b/lib/Doctrine/TODO/Task/DumpData.php new file mode 100644 index 000000000..dddd4cefa --- /dev/null +++ b/lib/Doctrine/TODO/Task/DumpData.php @@ -0,0 +1,54 @@ +. + */ + +/** + * Doctrine_Task_DumpData + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_DumpData extends Doctrine_Task +{ + public $description = 'Dump data to a yaml data fixture file.', + $requiredArguments = array('data_fixtures_path' => 'Specify path to write the yaml data fixtures file to.', + 'models_path' => 'Specify path to your Doctrine_Record definitions.'), + $optionalArguments = array(); + + public function execute() + { + Doctrine::loadModels($this->getArgument('models_path')); + + $path = $this->getArgument('data_fixtures_path'); + + if (is_array($path)) { + $path = $path[0]; + } + + Doctrine::dumpData($path); + + $this->dispatcher->notify(sprintf('Dumped data successfully to: %s', $path)); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/Exception.php b/lib/Doctrine/TODO/Task/Exception.php new file mode 100644 index 000000000..febadc321 --- /dev/null +++ b/lib/Doctrine/TODO/Task/Exception.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Task_Exception + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_Exception extends Doctrine_Exception +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/GenerateMigration.php b/lib/Doctrine/TODO/Task/GenerateMigration.php new file mode 100644 index 000000000..29075257a --- /dev/null +++ b/lib/Doctrine/TODO/Task/GenerateMigration.php @@ -0,0 +1,46 @@ +. + */ + +/** + * Doctrine_Task_GenerateMigration + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_GenerateMigration extends Doctrine_Task +{ + public $description = 'Generate new migration class definition', + $requiredArguments = array('class_name' => 'Name of the migration class to generate', + 'migrations_path' => 'Specify the complete path to your migration classes folder.'), + $optionalArguments = array(); + + public function execute() + { + Doctrine::generateMigrationClass($this->getArgument('class_name'), $this->getArgument('migrations_path')); + + $this->dispatcher->notify(sprintf('Generated migration class: %s successfully to %s', $this->getArgument('class_name'), $this->getArgument('migrations_path'))); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/GenerateMigrationsDb.php b/lib/Doctrine/TODO/Task/GenerateMigrationsDb.php new file mode 100644 index 000000000..b26639398 --- /dev/null +++ b/lib/Doctrine/TODO/Task/GenerateMigrationsDb.php @@ -0,0 +1,45 @@ +. + */ + +/** + * Doctrine_Task_GenerateMigrationsDb + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_GenerateMigrationsDb extends Doctrine_Task +{ + public $description = 'Generate migration classes for an existing database', + $requiredArguments = array('migrations_path' => 'Specify the complete path to your migration classes folder.'), + $optionalArguments = array(); + + public function execute() + { + Doctrine::generateMigrationsFromDb($this->getArgument('migrations_path')); + + $this->dispatcher->notify('Generated migration classes successfully from database'); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/GenerateMigrationsModels.php b/lib/Doctrine/TODO/Task/GenerateMigrationsModels.php new file mode 100644 index 000000000..e2f17de9b --- /dev/null +++ b/lib/Doctrine/TODO/Task/GenerateMigrationsModels.php @@ -0,0 +1,46 @@ +. + */ + +/** + * Doctrine_Task_GenerateMigrationsModels + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_GenerateMigrationsModels extends Doctrine_Task +{ + public $description = 'Generate migration classes for an existing set of models', + $requiredArguments = array('migrations_path' => 'Specify the path to your migration classes folder.', + 'models_path' => 'Specify the path to your doctrine models folder.'), + $optionalArguments = array(); + + public function execute() + { + Doctrine::generateMigrationsFromModels($this->getArgument('migrations_path'), $this->getArgument('models_path')); + + $this->dispatcher->notify('Generated migration classes successfully from models'); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/GenerateModelsDb.php b/lib/Doctrine/TODO/Task/GenerateModelsDb.php new file mode 100644 index 000000000..afe3ff01a --- /dev/null +++ b/lib/Doctrine/TODO/Task/GenerateModelsDb.php @@ -0,0 +1,45 @@ +. + */ + +/** + * Doctrine_Task_GenerateModelsDb + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_GenerateModelsDb extends Doctrine_Task +{ + public $description = 'Generates your Doctrine_Record definitions from your existing database connections.', + $requiredArguments = array('models_path' => 'Specify path to your Doctrine_Record definitions.'), + $optionalArguments = array('connection' => 'Optionally specify a single connection to generate the models for.'); + + public function execute() + { + Doctrine::generateModelsFromDb($this->getArgument('models_path'), (array) $this->getArgument('connection')); + + $this->dispatcher->notify('Generated models successfully from databases'); + } +} diff --git a/lib/Doctrine/TODO/Task/GenerateModelsYaml.php b/lib/Doctrine/TODO/Task/GenerateModelsYaml.php new file mode 100644 index 000000000..79b6098cf --- /dev/null +++ b/lib/Doctrine/TODO/Task/GenerateModelsYaml.php @@ -0,0 +1,46 @@ +. + */ + +/** + * Doctrine_Task_GenerateModelsYaml + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_GenerateModelsYaml extends Doctrine_Task +{ + public $description = 'Generates your Doctrine_Record definitions from a Yaml schema file', + $requiredArguments = array('yaml_schema_path' => 'Specify the complete directory path to your yaml schema files.', + 'models_path' => 'Specify complete path to your Doctrine_Record definitions.'), + $optionalArguments = array(); + + public function execute() + { + Doctrine::generateModelsFromYaml($this->getArgument('yaml_schema_path'), $this->getArgument('models_path')); + + $this->notify('Generated models successfully from YAML schema'); + } +} diff --git a/lib/Doctrine/TODO/Task/GenerateSql.php b/lib/Doctrine/TODO/Task/GenerateSql.php new file mode 100644 index 000000000..e67c620fa --- /dev/null +++ b/lib/Doctrine/TODO/Task/GenerateSql.php @@ -0,0 +1,56 @@ +. + */ + +/** + * Doctrine_Task_GenerateSql + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_GenerateSql extends Doctrine_Task +{ + public $description = 'Generate sql for all existing database connections.', + $requiredArguments = array('models_path' => 'Specify complete path to your Doctrine_Record definitions.', + 'sql_path' => 'Path to write the generated sql.'), + $optionalArguments = array(); + + public function execute() + { + if (is_dir($this->getArgument('sql_path'))) { + $path = $this->getArgument('sql_path') . DIRECTORY_SEPARATOR . 'schema.sql'; + } else if (is_file($this->getArgument('sql_path'))) { + $path = $this->getArgument('sql_path'); + } else { + throw new Doctrine_Task_Exception('Invalid sql path.'); + } + + $sql = Doctrine::generateSqlFromModels($this->getArgument('models_path')); + + file_put_contents($path, $sql); + + $this->dispatcher->notify('Generated SQL successfully for models'); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/GenerateYamlDb.php b/lib/Doctrine/TODO/Task/GenerateYamlDb.php new file mode 100644 index 000000000..2ae2a014d --- /dev/null +++ b/lib/Doctrine/TODO/Task/GenerateYamlDb.php @@ -0,0 +1,45 @@ +. + */ + +/** + * Doctrine_Task_GenerateYamlDb + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_GenerateYamlDb extends Doctrine_Task +{ + public $description = 'Generates a Yaml schema file from an existing database', + $requiredArguments = array('yaml_schema_path' => 'Specify the path to your yaml schema files.'), + $optionalArguments = array(); + + public function execute() + { + Doctrine::generateYamlFromDb($this->getArgument('yaml_schema_path')); + + $this->dispatcher->notify('Generate YAML schema successfully from database'); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/GenerateYamlModels.php b/lib/Doctrine/TODO/Task/GenerateYamlModels.php new file mode 100644 index 000000000..5cb55b2b6 --- /dev/null +++ b/lib/Doctrine/TODO/Task/GenerateYamlModels.php @@ -0,0 +1,46 @@ +. + */ + +/** + * Doctrine_Task_GenerateFromModels + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_GenerateYamlModels extends Doctrine_Task +{ + public $description = 'Generates a Yaml schema file from existing Doctrine_Record definitions', + $requiredArguments = array('yaml_schema_path' => 'Specify the complete directory path to your yaml schema files.', + 'models_path' => 'Specify complete path to your Doctrine_Record definitions.'), + $optionalArguments = array(); + + public function execute() + { + Doctrine::generateYamlFromModels($this->getArgument('yaml_schema_path'), $this->getArgument('models_path')); + + $this->dispatcher->notify('Generated YAML schema successfully from models'); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/LoadData.php b/lib/Doctrine/TODO/Task/LoadData.php new file mode 100644 index 000000000..84078207a --- /dev/null +++ b/lib/Doctrine/TODO/Task/LoadData.php @@ -0,0 +1,47 @@ +. + */ + +/** + * Doctrine_Task_LoadData + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_LoadData extends Doctrine_Task +{ + public $description = 'Load data from a yaml data fixture file.', + $requiredArguments = array('data_fixtures_path' => 'Specify the complete path to load the yaml data fixtures files from.', + 'models_path' => 'Specify path to your Doctrine_Record definitions.'), + $optionalArguments = array(); + + public function execute() + { + Doctrine::loadModels($this->getArgument('models_path')); + Doctrine::loadData($this->getArgument('data_fixtures_path')); + + $this->dispatcher->notify('Data was successfully loaded'); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/LoadDummyData.php b/lib/Doctrine/TODO/Task/LoadDummyData.php new file mode 100644 index 000000000..81c0f80e2 --- /dev/null +++ b/lib/Doctrine/TODO/Task/LoadDummyData.php @@ -0,0 +1,47 @@ +. + */ + +/** + * Doctrine_Task_LoadDummyData + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_LoadDummyData extends Doctrine_Task +{ + public $description = 'Load data from a yaml data fixture file.', + $requiredArguments = array('models_path' => 'Specify path to your Doctrine_Record definitions.'), + $optionalArguments = array('append' => 'Whether or not to append the data or to delete all data before loading.', + 'num' => 'Number of records to populate for each model.'); + + public function execute() + { + Doctrine::loadModels($this->getArgument('models_path')); + Doctrine::loadDummyData($this->getArgument('append') ? true:false, $this->getArgument('num') ? $this->getArgument('num'):5); + + $this->dispatcher->notify('Dummy data was successfully loaded'); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/Migrate.php b/lib/Doctrine/TODO/Task/Migrate.php new file mode 100644 index 000000000..eb14449d1 --- /dev/null +++ b/lib/Doctrine/TODO/Task/Migrate.php @@ -0,0 +1,45 @@ +. + */ + +/** + * Doctrine_Task_Migrate + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_Migrate extends Doctrine_Task +{ + public $description = 'Migrate database to latest version or the specified version', + $requiredArguments = array('migrations_path' => 'Specify path to your migrations directory.'), + $optionalArguments = array('version' => 'Version to migrate to. If you do not specify, the db will be migrated from the current version to the latest.'); + + public function execute() + { + $version = Doctrine::migrate($this->getArgument('migrations_path'), $this->getArgument('version')); + + $this->dispatcher->notify('migrated successfully to version #' . $version); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Task/RebuildDb.php b/lib/Doctrine/TODO/Task/RebuildDb.php new file mode 100644 index 000000000..e374136da --- /dev/null +++ b/lib/Doctrine/TODO/Task/RebuildDb.php @@ -0,0 +1,58 @@ +. + */ + +/** + * Doctrine_Task_RebuildDb + * + * @package Doctrine + * @subpackage Task + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Task_RebuildDb extends Doctrine_Task +{ + public $description = 'Drops and re-creates databases', + $requiredArguments = array(), + $optionalArguments = array(); + + public function __construct($dispatcher = null) + { + parent::__construct($dispatcher); + + $this->dropDb = new Doctrine_Task_DropDb($this->dispatcher); + $this->buildAll = new Doctrine_Task_BuildAll($this->dispatcher); + + $this->requiredArguments = array_merge($this->requiredArguments, $this->dropDb->requiredArguments, $this->buildAll->requiredArguments); + $this->optionalArguments = array_merge($this->optionalArguments, $this->dropDb->optionalArguments, $this->buildAll->optionalArguments); + } + + public function execute() + { + $this->dropDb->setArguments($this->getArguments()); + $this->dropDb->execute(); + + $this->buildAll->setArguments($this->getArguments()); + $this->buildAll->execute(); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Template/Geographical.php b/lib/Doctrine/TODO/Template/Geographical.php new file mode 100644 index 000000000..4fc1cb46f --- /dev/null +++ b/lib/Doctrine/TODO/Template/Geographical.php @@ -0,0 +1,120 @@ +. + */ + +/** + * Doctrine_Template_Geographical + * + * Easily add created and updated at timestamps to your doctrine records + * + * @package Doctrine + * @subpackage Template + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + * @author Konsta Vesterinen + */ +class Doctrine_Template_Geographical extends Doctrine_Template +{ + /** + * Array of timestampable options + * + * @var string + */ + protected $_options = array('latitude' => array('name' => 'latitude', + 'type' => 'float', + 'size' => 4, + 'options' => array()), + 'longitude' => array('name' => 'longitude', + 'type' => 'float', + 'size' => 4, + 'options' => array())); + + /** + * __construct + * + * @param string $array + * @return void + */ + public function __construct(array $options) + { + $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options); + } + + /** + * setTableDefinition + * + * @return void + */ + public function setTableDefinition() + { + $this->hasColumn($this->_options['latitude']['name'], $this->_options['latitude']['type'], $this->_options['latitude']['size'], $this->_options['latitude']['options']); + $this->hasColumn($this->_options['longitude']['name'], $this->_options['longitude']['type'], $this->_options['longitude']['size'], $this->_options['longitude']['options']); + } + + public function getDistanceQuery() + { + $invoker = $this->getInvoker(); + $query = $invoker->getTable()->createQuery(); + + $rootAlias = $query->getRootAlias(); + $latName = $this->_options['latitude']['name']; + $longName = $this->_options['longitude']['name']; + + $query->addSelect($rootAlias . '.*'); + + $sql = "((ACOS(SIN(%s * PI() / 180) * SIN(" . $rootAlias . "." . $latName . " * PI() / 180) + COS(%s * PI() / 180) * COS(" . $rootAlias . "." . $latName . " * PI() / 180) * COS((%s - " . $rootAlias . "." . $longName . ") * PI() / 180)) * 180 / PI()) * 60 * %s) as %s"; + + $milesSql = sprintf($sql, number_format($invoker->get('latitude'), 1), $invoker->get('latitude'), $invoker->get('longitude'), '1.1515', 'miles'); + $query->addSelect($milesSql); + + $kilometersSql = sprintf($sql, number_format($invoker->get('latitude'), 1), $invoker->get('latitude'), $invoker->get('longitude'), '1.1515 * 1.609344', 'kilometers'); + $query->addSelect($kilometersSql); + + return $query; + } + + public function getDistance(Doctrine_Entity $record, $kilometers = false) + { + $query = $this->getDistanceQuery($kilometers); + + $conditions = array(); + $values = array(); + foreach ((array) $record->getTable()->getIdentifier() as $id) { + $conditions[] = $query->getRootAlias() . '.' . $id . ' = ?'; + $values[] = $record->get($id); + } + + $where = implode(' AND ', $conditions); + + $query->addWhere($where, $values); + + $query->limit(1); + + $result = $query->execute()->getFirst(); + + if (isset($result['kilometers']) && $result['miles']) { + return $kilometers ? $result->get('kilometers'):$result->get('miles'); + } else { + return 0; + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Template/I18n.php b/lib/Doctrine/TODO/Template/I18n.php new file mode 100644 index 000000000..72c019366 --- /dev/null +++ b/lib/Doctrine/TODO/Template/I18n.php @@ -0,0 +1,64 @@ +. + */ + +/** + * Doctrine_Template_I18n + * + * @package Doctrine + * @subpackage Template + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + * @author Konsta Vesterinen + */ +class Doctrine_Template_I18n extends Doctrine_Template +{ + /** + * __construct + * + * @param string $array + * @return void + */ + public function __construct(array $options = array()) + { + $this->_plugin = new Doctrine_I18n($options); + } + /** + * setUp + * + * @return void + */ + public function setUp() + { + $this->_plugin->initialize($this->_table); + } + + /** + * getI18n + * + * @return void + */ + public function getI18n() + { + return $this->_plugin; + } +} diff --git a/lib/Doctrine/TODO/Template/Listener/Sluggable.php b/lib/Doctrine/TODO/Template/Listener/Sluggable.php new file mode 100644 index 000000000..5da04ff99 --- /dev/null +++ b/lib/Doctrine/TODO/Template/Listener/Sluggable.php @@ -0,0 +1,79 @@ +. + */ + +/** + * Doctrine_Template_Listener_Sluggable + * + * Easily create a slug for each record based on a specified set of fields + * + * @package Doctrine + * @subpackage Template + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + * @author Konsta Vesterinen + */ +class Doctrine_Template_Listener_Sluggable extends Doctrine_Record_Listener +{ + /** + * Array of timestampable options + * + * @var string + */ + protected $_options = array(); + + /** + * __construct + * + * @param string $array + * @return void + */ + public function __construct(array $options) + { + $this->_options = $options; + } + + public function preInsert(Doctrine_Event $event) + { + $name = $this->_options['name']; + + $record = $event->getInvoker(); + + if (!$record->$name) { + $record->$name = $this->buildSlug($record); + } + } + + protected function buildSlug($record) + { + if (empty($this->_options['fields'])) { + $value = (string) $record; + } else { + $value = ''; + foreach ($this->_options['fields'] as $field) { + $value .= $record->$field . ' '; + } + } + + return Doctrine_Inflector::urlize($value); + } +} diff --git a/lib/Doctrine/TODO/Template/Listener/Timestampable.php b/lib/Doctrine/TODO/Template/Listener/Timestampable.php new file mode 100644 index 000000000..d330b6c70 --- /dev/null +++ b/lib/Doctrine/TODO/Template/Listener/Timestampable.php @@ -0,0 +1,110 @@ +. + */ + +/** + * Doctrine_Template_Listener_Timestampable + * + * @package Doctrine + * @subpackage Template + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + * @author Konsta Vesterinen + */ +class Doctrine_Template_Listener_Timestampable extends Doctrine_Record_Listener +{ + /** + * Array of timestampable options + * + * @var string + */ + protected $_options = array(); + + /** + * __construct + * + * @param string $options + * @return void + */ + public function __construct(array $options) + { + $this->_options = $options; + } + + /** + * preInsert + * + * @param object $Doctrine_Event + * @return void + */ + public function preInsert(Doctrine_Event $event) + { + if( ! $this->_options['created']['disabled']) { + $createdName = $this->_options['created']['name']; + $event->getInvoker()->$createdName = $this->getTimestamp('created'); + } + + if( ! $this->_options['updated']['disabled'] && $this->_options['updated']['onInsert']) { + $updatedName = $this->_options['updated']['name']; + $event->getInvoker()->$updatedName = $this->getTimestamp('updated'); + } + } + + /** + * preUpdate + * + * @param object $Doctrine_Event + * @return void + */ + public function preUpdate(Doctrine_Event $event) + { + if( ! $this->_options['updated']['disabled']) { + $updatedName = $this->_options['updated']['name']; + $event->getInvoker()->$updatedName = $this->getTimestamp('updated'); + } + } + + /** + * getTimestamp + * + * Gets the timestamp in the correct format + * + * @param string $type + * @return void + */ + public function getTimestamp($type) + { + $options = $this->_options[$type]; + + if ($options['expression'] !== false && is_string($options['expression'])) { + return new Doctrine_Expression($options['expression']); + } else { + if ($options['type'] == 'date') { + return date($options['format'], time()); + } else if ($options['type'] == 'timestamp') { + return date($options['format'], time()); + } else { + return time(); + } + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Template/NestedSet.php b/lib/Doctrine/TODO/Template/NestedSet.php new file mode 100644 index 000000000..2d9954c44 --- /dev/null +++ b/lib/Doctrine/TODO/Template/NestedSet.php @@ -0,0 +1,52 @@ +. + */ + +/** + * Doctrine_Template_NestedSet + * + * @package Doctrine + * @subpackage Template + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + * @author Roman Borschel + */ +class Doctrine_Template_NestedSet extends Doctrine_Template +{ + private $_options; + + public function __construct(array $options) + { + $this->_options = $options; + } + + public function setUp() + { + $this->_table->setOption('treeOptions', $this->_options); + $this->_table->setOption('treeImpl', 'NestedSet'); + } + + public function setTableDefinition() + { + $this->_table->getTree()->setTableDefinition(); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Template/Searchable.php b/lib/Doctrine/TODO/Template/Searchable.php new file mode 100644 index 000000000..c4054d5de --- /dev/null +++ b/lib/Doctrine/TODO/Template/Searchable.php @@ -0,0 +1,51 @@ +. + */ + +/** + * Doctrine_Template_Searchable + * + * @author Konsta Vesterinen + * @package Doctrine + * @subpackage Template + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Template_Searchable extends Doctrine_Template +{ + public function __construct(array $options) + { + $this->_plugin = new Doctrine_Search($options); + } + + public function setUp() + { + $this->_plugin->initialize($this->_table); + + $this->addListener(new Doctrine_Search_Listener($this->_plugin)); + } + + public function batchUpdateIndex($limit = null, $offset = null) + { + $this->_plugin->batchUpdateIndex($limit, $offset); + } +} diff --git a/lib/Doctrine/TODO/Template/Sluggable.php b/lib/Doctrine/TODO/Template/Sluggable.php new file mode 100644 index 000000000..ae6ec1a3f --- /dev/null +++ b/lib/Doctrine/TODO/Template/Sluggable.php @@ -0,0 +1,70 @@ +. + */ + +/** + * Doctrine_Template_Sluggable + * + * Easily create a slug for each record based on a specified set of fields + * + * @package Doctrine + * @subpackage Template + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + * @author Konsta Vesterinen + */ +class Doctrine_Template_Sluggable extends Doctrine_Template +{ + /** + * Array of timestampable options + * + * @var string + */ + protected $_options = array('name' => 'slug', + 'type' => 'clob', + 'length' => null, + 'options' => array(), + 'fields' => array()); + + /** + * __construct + * + * @param string $array + * @return void + */ + public function __construct(array $options) + { + $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options); + } + + /** + * setTableDefinition + * + * @return void + */ + public function setTableDefinition() + { + $this->hasColumn($this->_options['name'], $this->_options['type'], $this->_options['length'], $this->_options['options']); + + $this->addListener(new Doctrine_Template_Listener_Sluggable($this->_options)); + } +} diff --git a/lib/Doctrine/TODO/Template/Taggable.php b/lib/Doctrine/TODO/Template/Taggable.php new file mode 100644 index 000000000..2eb475925 --- /dev/null +++ b/lib/Doctrine/TODO/Template/Taggable.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Template_Taggable + * + * @author Konsta Vesterinen + * @package Doctrine + * @subpackage Template + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.phpdoctrine.org + * @since 1.0 + */ +class Doctrine_Template_Taggable extends Doctrine_Template +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Template/Timestampable.php b/lib/Doctrine/TODO/Template/Timestampable.php new file mode 100644 index 000000000..3cd4b1775 --- /dev/null +++ b/lib/Doctrine/TODO/Template/Timestampable.php @@ -0,0 +1,84 @@ +. + */ + +/** + * Doctrine_Template_Timestampable + * + * Easily add created and updated at timestamps to your doctrine records + * + * @package Doctrine + * @subpackage Template + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + * @author Konsta Vesterinen + */ +class Doctrine_Template_Timestampable extends Doctrine_Template +{ + /** + * Array of timestampable options + * + * @var string + */ + protected $_options = array('created' => array('name' => 'created_at', + 'type' => 'timestamp', + 'format' => 'Y-m-d H:i:s', + 'disabled' => false, + 'expression' => false, + 'options' => array()), + 'updated' => array('name' => 'updated_at', + 'type' => 'timestamp', + 'format' => 'Y-m-d H:i:s', + 'disabled' => false, + 'expression' => false, + 'onInsert' => true, + 'options' => array())); + + /** + * __construct + * + * @param string $array + * @return void + */ + public function __construct(array $options) + { + $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options); + } + + /** + * setTableDefinition + * + * @return void + */ + public function setTableDefinition() + { + if( ! $this->_options['created']['disabled']) { + $this->hasColumn($this->_options['created']['name'], $this->_options['created']['type'], null, $this->_options['created']['options']); + } + + if( ! $this->_options['updated']['disabled']) { + $this->hasColumn($this->_options['updated']['name'], $this->_options['updated']['type'], null, $this->_options['updated']['options']); + } + + $this->addListener(new Doctrine_Template_Listener_Timestampable($this->_options)); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Template/Versionable.php b/lib/Doctrine/TODO/Template/Versionable.php new file mode 100644 index 000000000..d31a3a3ef --- /dev/null +++ b/lib/Doctrine/TODO/Template/Versionable.php @@ -0,0 +1,52 @@ +. + */ + +/** + * Doctrine_Template_Versionable + * + * @package Doctrine + * @subpackage Template + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + * @author Konsta Vesterinen + */ +class Doctrine_Template_Versionable extends Doctrine_Template +{ + public function __construct(array $options) + { + $this->_plugin = new Doctrine_AuditLog($options); + } + public function setUp() + { + $this->_plugin->initialize($this->_table); + + $this->hasColumn('version', 'integer', 8); + + $this->addListener(new Doctrine_AuditLog_Listener($this->_plugin)); + } + public function getAuditLog() + { + return $this->_plugin; + } + +} diff --git a/lib/Doctrine/TODO/Tree/AdjacencyList.php b/lib/Doctrine/TODO/Tree/AdjacencyList.php new file mode 100644 index 000000000..102c2a84b --- /dev/null +++ b/lib/Doctrine/TODO/Tree/AdjacencyList.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Tree_AdjacencyList + * + * @package Doctrine + * @subpackage Tree + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Joe Simms + */ +abstract class Doctrine_Tree_AdjacencyList extends Doctrine_Tree implements Doctrine_Tree_Interface +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Tree/Exception.php b/lib/Doctrine/TODO/Tree/Exception.php new file mode 100644 index 000000000..c510d0c26 --- /dev/null +++ b/lib/Doctrine/TODO/Tree/Exception.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Tree_Exception + * + * @package Doctrine + * @subpackage Tree + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Konsta Vesterinen + */ +class Doctrine_Tree_Exception extends Doctrine_Exception +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Tree/Interface.php b/lib/Doctrine/TODO/Tree/Interface.php new file mode 100644 index 000000000..9972e3be5 --- /dev/null +++ b/lib/Doctrine/TODO/Tree/Interface.php @@ -0,0 +1,65 @@ +. + */ + +/** + * Doctrine_Tree_Interface + * + * @package Doctrine + * @subpackage Tree + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 4364 $ + * @author Joe Simms + */ +interface Doctrine_Tree_Interface { + + /** + * creates root node from given record or from a new record + * + * @param object $record instance of Doctrine_Entity + */ + public function createRoot(Doctrine_Entity $record = null); + + /** + * returns root node + * + * @return object $record instance of Doctrine_Entity + */ + public function findRoot($root_id = 1); + + /** + * optimised method to returns iterator for traversal of the entire tree from root + * + * @param array $options options + * @return object $iterator instance of Doctrine_Node__PreOrderIterator + */ + public function fetchTree($options = array()); + + /** + * optimised method that returns iterator for traversal of the tree from the given record primary key + * + * @param mixed $pk primary key as used by table::find() to locate node to traverse tree from + * @param array $options options + * @return iterator instance of Doctrine_Node__PreOrderIterator + */ + public function fetchBranch($pk, $options = array()); +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Tree/MaterializedPath.php b/lib/Doctrine/TODO/Tree/MaterializedPath.php new file mode 100644 index 000000000..1b1383731 --- /dev/null +++ b/lib/Doctrine/TODO/Tree/MaterializedPath.php @@ -0,0 +1,34 @@ +. + */ + +/** + * Doctrine_Tree_MaterializedPath + * + * @package Doctrine + * @subpackage Tree + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Joe Simms + */ +abstract class Doctrine_Tree_MaterializedPath extends Doctrine_Tree implements Doctrine_Tree_Interface +{ } \ No newline at end of file diff --git a/lib/Doctrine/TODO/Tree/NestedSet.php b/lib/Doctrine/TODO/Tree/NestedSet.php new file mode 100644 index 000000000..b1b69417a --- /dev/null +++ b/lib/Doctrine/TODO/Tree/NestedSet.php @@ -0,0 +1,322 @@ +. + */ + +/** + * Doctrine_Tree_NestedSet + * + * @package Doctrine + * @subpackage Tree + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 4364 $ + * @author Joe Simms + */ +class Doctrine_Tree_NestedSet extends Doctrine_Tree implements Doctrine_Tree_Interface +{ + private $_baseQuery; + private $_baseAlias = "base"; + + /** + * constructor, creates tree with reference to table and sets default root options + * + * @param object $table instance of Doctrine_Table + * @param array $options options + */ + public function __construct($table, $options) + { + // set default many root attributes + $options['hasManyRoots'] = isset($options['hasManyRoots']) ? $options['hasManyRoots'] : false; + if ($options['hasManyRoots']) { + $options['rootColumnName'] = isset($options['rootColumnName']) ? $options['rootColumnName'] : 'root_id'; + } + + parent::__construct($table, $options); + } + + /** + * used to define table attributes required for the NestetSet implementation + * adds lft and rgt columns for corresponding left and right values + * + */ + public function setTableDefinition() + { + if ($root = $this->getAttribute('rootColumnName')) { + $this->table->setColumn($root, 'integer', 4); + } + + $this->table->setColumn('lft', 'integer', 4); + $this->table->setColumn('rgt', 'integer', 4); + $this->table->setColumn('level', 'integer', 2); + } + + /** + * creates root node from given record or from a new record + * + * @param object $record instance of Doctrine_Entity + */ + public function createRoot(Doctrine_Entity $record = null) + { + if ( ! $record) { + $record = $this->table->create(); + } + + // if tree is many roots, and no root id has been set, then get next root id + if ($root = $this->getAttribute('hasManyRoots') && $record->getNode()->getRootValue() <= 0) { + $record->getNode()->setRootValue($this->getNextRootId()); + } + + $record->set('lft', '1'); + $record->set('rgt', '2'); + $record->set('level', 0); + + $record->save(); + + return $record; + } + + /** + * returns root node + * + * @return object $record instance of Doctrine_Entity + * @deprecated Use fetchRoot() + */ + public function findRoot($rootId = 1) + { + return $this->fetchRoot($rootId); + } + + /** + * Fetches a/the root node. + * + * @param integer $rootId + */ + public function fetchRoot($rootId = 1) + { + $q = $this->getBaseQuery(); + $q = $q->addWhere($this->_baseAlias . '.lft = ?', 1); + + // if tree has many roots, then specify root id + $q = $this->returnQueryWithRootId($q, $rootId); + $data = $q->execute(); + + if (count($data) <= 0) { + return false; + } + + if ($data instanceof Doctrine_Collection) { + $root = $data->getFirst(); + $root['level'] = 0; + } else if (is_array($data)) { + $root = array_shift($data); + $root['level'] = 0; + } else { + throw new Doctrine_Tree_Exception("Unexpected data structure returned."); + } + + return $root; + } + + /** + * Fetches a tree. + * + * @param array $options Options + * @return mixed The tree or FALSE if the tree could not be found. + */ + public function fetchTree($options = array()) + { + // fetch tree + $q = $this->getBaseQuery(); + + $q = $q->addWhere($this->_baseAlias . ".lft >= ?", 1); + + // if tree has many roots, then specify root id + $rootId = isset($options['root_id']) ? $options['root_id'] : '1'; + if (is_array($rootId)) { + $q->addOrderBy($this->_baseAlias . "." . $this->getAttribute('rootColumnName') . + ", " . $this->_baseAlias . ".lft ASC"); + } else { + $q->addOrderBy($this->_baseAlias . ".lft ASC"); + } + + $q = $this->returnQueryWithRootId($q, $rootId); + $tree = $q->execute(); + + if (count($tree) <= 0) { + return false; + } + + return $tree; + } + + /** + * Fetches a branch of a tree. + * + * @param mixed $pk primary key as used by table::find() to locate node to traverse tree from + * @param array $options Options. + * @return mixed The branch or FALSE if the branch could not be found. + * @todo Only fetch the lft and rgt values of the initial record. more is not needed. + */ + public function fetchBranch($pk, $options = array()) + { + $record = $this->table->find($pk); + if ( ! ($record instanceof Doctrine_Entity) || !$record->exists()) { + // TODO: if record doesn't exist, throw exception or similar? + return false; + } + //$depth = isset($options['depth']) ? $options['depth'] : null; + + $q = $this->getBaseQuery(); + $params = array($record->get('lft'), $record->get('rgt')); + $q->addWhere($this->_baseAlias . ".lft >= ? AND " . $this->_baseAlias . ".rgt <= ?", $params) + ->addOrderBy($this->_baseAlias . ".lft asc"); + $q = $this->returnQueryWithRootId($q, $record->getNode()->getRootValue()); + return $q->execute(); + } + + /** + * Fetches all root nodes. If the tree has only one root this is the same as + * fetchRoot(). + * + * @return mixed The root nodes. + */ + public function fetchRoots() + { + $q = $this->getBaseQuery(); + $q = $q->addWhere($this->_baseAlias . '.lft = ?', 1); + return $q->execute(); + } + + /** + * calculates the next available root id + * + * @return integer + */ + public function getNextRootId() + { + return $this->getMaxRootId() + 1; + } + + /** + * calculates the current max root id + * + * @return integer + */ + public function getMaxRootId() + { + $component = $this->table->getComponentName(); + $column = $this->getAttribute('rootColumnName'); + + // cannot get this dql to work, cannot retrieve result using $coll[0]->max + //$dql = "SELECT MAX(c.$column) FROM $component c"; + + $dql = 'SELECT c.' . $column . ' FROM ' . $component . ' c ORDER BY c.' . $column . ' DESC LIMIT 1'; + + $coll = $this->table->getConnection()->query($dql); + + $max = $coll[0]->get($column); + + $max = !is_null($max) ? $max : 0; + + return $max; + } + + /** + * returns parsed query with root id where clause added if applicable + * + * @param object $query Doctrine_Query + * @param integer $root_id id of destination root + * @return object Doctrine_Query + */ + public function returnQueryWithRootId($query, $rootId = 1) + { + if ($root = $this->getAttribute('rootColumnName')) { + if (is_array($rootId)) { + $query->addWhere($root . ' IN (' . implode(',', array_fill(0, count($rootId), '?')) . ')', + $rootId); + } else { + $query->addWhere($root . ' = ?', $rootId); + } + } + + return $query; + } + + /** + * Enter description here... + * + * @param array $options + * @return unknown + */ + public function getBaseQuery() + { + if ( ! isset($this->_baseQuery)) { + $this->_baseQuery = $this->_createBaseQuery(); + } + return $this->_baseQuery->copy(); + } + + /** + * Enter description here... + * + */ + public function getBaseAlias() + { + return $this->_baseAlias; + } + + /** + * Enter description here... + * + */ + private function _createBaseQuery() + { + $this->_baseAlias = "base"; + $q = new Doctrine_Query(); + $q->select($this->_baseAlias . ".*")->from($this->getBaseComponent() . " " . $this->_baseAlias); + return $q; + } + + /** + * Enter description here... + * + * @param Doctrine_Query $query + */ + public function setBaseQuery(Doctrine_Query $query) + { + $this->_baseAlias = $query->getRootAlias(); + $query->addSelect($this->_baseAlias . ".lft, " . $this->_baseAlias . ".rgt, ". $this->_baseAlias . ".level"); + if ($this->getAttribute('rootColumnName')) { + $query->addSelect($this->_baseAlias . "." . $this->getAttribute('rootColumnName')); + } + $this->_baseQuery = $query; + } + + /** + * Enter description here... + * + */ + public function resetBaseQuery() + { + $this->_baseQuery = $this->_createBaseQuery(); + } + +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Country.php b/lib/Doctrine/TODO/Validator/Country.php new file mode 100644 index 000000000..664b5ec57 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Country.php @@ -0,0 +1,302 @@ +. + */ + +/** + * Doctrine_Validator_Country + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Country +{ + private static $countries = array( + 'ad' => 'Andorra', + 'ae' => 'United Arab Emirates', + 'af' => 'Afghanistan', + 'ag' => 'Antigua and Barbuda', + 'ai' => 'Anguilla', + 'al' => 'Albania', + 'am' => 'Armenia', + 'an' => 'Netherlands Antilles', + 'ao' => 'Angola', + 'aq' => 'Antarctica', + 'ar' => 'Argentina', + 'as' => 'American Samoa', + 'at' => 'Austria', + 'au' => 'Australia', + 'aw' => 'Aruba', + 'az' => 'Azerbaijan', + 'ba' => 'Bosnia Hercegovina', + 'bb' => 'Barbados', + 'bd' => 'Bangladesh', + 'be' => 'Belgium', + 'bf' => 'Burkina Faso', + 'bg' => 'Bulgaria', + 'bh' => 'Bahrain', + 'bi' => 'Burundi', + 'bj' => 'Benin', + 'bm' => 'Bermuda', + 'bn' => 'Brunei Darussalam', + 'bo' => 'Bolivia', + 'br' => 'Brazil', + 'bs' => 'Bahamas', + 'bt' => 'Bhutan', + 'bv' => 'Bouvet Island', + 'bw' => 'Botswana', + 'by' => 'Belarus (Byelorussia)', + 'bz' => 'Belize', + 'ca' => 'Canada', + 'cc' => 'Cocos Islands', + 'cd' => 'Congo, The Democratic Republic of the', + 'cf' => 'Central African Republic', + 'cg' => 'Congo', + 'ch' => 'Switzerland', + 'ci' => 'Ivory Coast', + 'ck' => 'Cook Islands', + 'cl' => 'Chile', + 'cm' => 'Cameroon', + 'cn' => 'China', + 'co' => 'Colombia', + 'cr' => 'Costa Rica', + 'cs' => 'Czechoslovakia', + 'cu' => 'Cuba', + 'cv' => 'Cape Verde', + 'cx' => 'Christmas Island', + 'cy' => 'Cyprus', + 'cz' => 'Czech Republic', + 'de' => 'Germany', + 'dj' => 'Djibouti', + 'dk' => 'Denmark', + 'dm' => 'Dominica', + 'do' => 'Dominican Republic', + 'dz' => 'Algeria', + 'ec' => 'Ecuador', + 'ee' => 'Estonia', + 'eg' => 'Egypt', + 'eh' => 'Western Sahara', + 'er' => 'Eritrea', + 'es' => 'Spain', + 'et' => 'Ethiopia', + 'fi' => 'Finland', + 'fj' => 'Fiji', + 'fk' => 'Falkland Islands', + 'fm' => 'Micronesia', + 'fo' => 'Faroe Islands', + 'fr' => 'France', + 'fx' => 'France, Metropolitan FX', + 'ga' => 'Gabon', + 'gb' => 'United Kingdom (Great Britain)', + 'gd' => 'Grenada', + 'ge' => 'Georgia', + 'gf' => 'French Guiana', + 'gh' => 'Ghana', + 'gi' => 'Gibraltar', + 'gl' => 'Greenland', + 'gm' => 'Gambia', + 'gn' => 'Guinea', + 'gp' => 'Guadeloupe', + 'gq' => 'Equatorial Guinea', + 'gr' => 'Greece', + 'gs' => 'South Georgia and the South Sandwich Islands', + 'gt' => 'Guatemala', + 'gu' => 'Guam', + 'gw' => 'Guinea-bissau', + 'gy' => 'Guyana', + 'hk' => 'Hong Kong', + 'hm' => 'Heard and McDonald Islands', + 'hn' => 'Honduras', + 'hr' => 'Croatia', + 'ht' => 'Haiti', + 'hu' => 'Hungary', + 'id' => 'Indonesia', + 'ie' => 'Ireland', + 'il' => 'Israel', + 'in' => 'India', + 'io' => 'British Indian Ocean Territory', + 'iq' => 'Iraq', + 'ir' => 'Iran', + 'is' => 'Iceland', + 'it' => 'Italy', + 'jm' => 'Jamaica', + 'jo' => 'Jordan', + 'jp' => 'Japan', + 'ke' => 'Kenya', + 'kg' => 'Kyrgyzstan', + 'kh' => 'Cambodia', + 'ki' => 'Kiribati', + 'km' => 'Comoros', + 'kn' => 'Saint Kitts and Nevis', + 'kp' => 'North Korea', + 'kr' => 'South Korea', + 'kw' => 'Kuwait', + 'ky' => 'Cayman Islands', + 'kz' => 'Kazakhstan', + 'la' => 'Laos', + 'lb' => 'Lebanon', + 'lc' => 'Saint Lucia', + 'li' => 'Lichtenstein', + 'lk' => 'Sri Lanka', + 'lr' => 'Liberia', + 'ls' => 'Lesotho', + 'lt' => 'Lithuania', + 'lu' => 'Luxembourg', + 'lv' => 'Latvia', + 'ly' => 'Libya', + 'ma' => 'Morocco', + 'mc' => 'Monaco', + 'md' => 'Moldova Republic', + 'mg' => 'Madagascar', + 'mh' => 'Marshall Islands', + 'mk' => 'Macedonia, The Former Yugoslav Republic of', + 'ml' => 'Mali', + 'mm' => 'Myanmar', + 'mn' => 'Mongolia', + 'mo' => 'Macau', + 'mp' => 'Northern Mariana Islands', + 'mq' => 'Martinique', + 'mr' => 'Mauritania', + 'ms' => 'Montserrat', + 'mt' => 'Malta', + 'mu' => 'Mauritius', + 'mv' => 'Maldives', + 'mw' => 'Malawi', + 'mx' => 'Mexico', + 'my' => 'Malaysia', + 'mz' => 'Mozambique', + 'na' => 'Namibia', + 'nc' => 'New Caledonia', + 'ne' => 'Niger', + 'nf' => 'Norfolk Island', + 'ng' => 'Nigeria', + 'ni' => 'Nicaragua', + 'nl' => 'Netherlands', + 'no' => 'Norway', + 'np' => 'Nepal', + 'nr' => 'Nauru', + 'nt' => 'Neutral Zone', + 'nu' => 'Niue', + 'nz' => 'New Zealand', + 'om' => 'Oman', + 'pa' => 'Panama', + 'pe' => 'Peru', + 'pf' => 'French Polynesia', + 'pg' => 'Papua New Guinea', + 'ph' => 'Philippines', + 'pk' => 'Pakistan', + 'pl' => 'Poland', + 'pm' => 'St. Pierre and Miquelon', + 'pn' => 'Pitcairn', + 'pr' => 'Puerto Rico', + 'pt' => 'Portugal', + 'pw' => 'Palau', + 'py' => 'Paraguay', + 'qa' => 'Qatar', + 're' => 'Reunion', + 'ro' => 'Romania', + 'ru' => 'Russia', + 'rw' => 'Rwanda', + 'sa' => 'Saudi Arabia', + 'sb' => 'Solomon Islands', + 'sc' => 'Seychelles', + 'sd' => 'Sudan', + 'se' => 'Sweden', + 'sg' => 'Singapore', + 'sh' => 'St. Helena', + 'si' => 'Slovenia', + 'sj' => 'Svalbard and Jan Mayen Islands', + 'sk' => 'Slovakia (Slovak Republic)', + 'sl' => 'Sierra Leone', + 'sm' => 'San Marino', + 'sn' => 'Senegal', + 'so' => 'Somalia', + 'sr' => 'Suriname', + 'st' => 'Sao Tome and Principe', + 'sv' => 'El Salvador', + 'sy' => 'Syria', + 'sz' => 'Swaziland', + 'tc' => 'Turks and Caicos Islands', + 'td' => 'Chad', + 'tf' => 'French Southern Territories', + 'tg' => 'Togo', + 'th' => 'Thailand', + 'tj' => 'Tajikistan', + 'tk' => 'Tokelau', + 'tm' => 'Turkmenistan', + 'tn' => 'Tunisia', + 'to' => 'Tonga', + 'tp' => 'East Timor', + 'tr' => 'Turkey', + 'tt' => 'Trinidad, Tobago', + 'tv' => 'Tuvalu', + 'tw' => 'Taiwan', + 'tz' => 'Tanzania', + 'ua' => 'Ukraine', + 'ug' => 'Uganda', + 'uk' => 'United Kingdom', + 'um' => 'United States Minor Islands', + 'us' => 'United States of America', + 'uy' => 'Uruguay', + 'uz' => 'Uzbekistan', + 'va' => 'Vatican City', + 'vc' => 'Saint Vincent, Grenadines', + 've' => 'Venezuela', + 'vg' => 'Virgin Islands (British)', + 'vi' => 'Virgin Islands (USA)', + 'vn' => 'Viet Nam', + 'vu' => 'Vanuatu', + 'wf' => 'Wallis and Futuna Islands', + 'ws' => 'Samoa', + 'ye' => 'Yemen', + 'yt' => 'Mayotte', + 'yu' => 'Yugoslavia', + 'za' => 'South Africa', + 'zm' => 'Zambia', + 'zr' => 'Zaire', + 'zw' => 'Zimbabwe'); + + /** + * returns all available country codes + * + * @return array + */ + public static function getCountries() + { + return self::$countries; + } + + /** + * checks if given value is a valid country code + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + $value = strtolower($value); + + return isset(self::$countries[$value]); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Creditcard.php b/lib/Doctrine/TODO/Validator/Creditcard.php new file mode 100644 index 000000000..90e2f7a6d --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Creditcard.php @@ -0,0 +1,47 @@ +. + */ + +/** + * Doctrine_Validator_Creditcard + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Creditcard +{ + /** + * checks if given value is a valid credit card number + * + * @link http://www.owasp.org/index.php/OWASP_Validation_Regex_Repository + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + return preg_match('#^((4\d{3})|(5[1-5]\d{2})|(6011)|(7\d{3}))-?\d{4}-?\d{4}-?\d{4}|3[4,7]\d{13}$#', $value); + } + +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Date.php b/lib/Doctrine/TODO/Validator/Date.php new file mode 100644 index 000000000..289d5257a --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Date.php @@ -0,0 +1,53 @@ +. + */ + +/** + * Doctrine_Validator_Date + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Date +{ + /** + * checks if given value is a valid date + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + if ($value === null) { + return true; + } + $e = explode('-', $value); + + if (count($e) !== 3) { + return false; + } + return checkdate($e[1], $e[2], $e[0]); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Driver.php b/lib/Doctrine/TODO/Validator/Driver.php new file mode 100644 index 000000000..3093f8320 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Driver.php @@ -0,0 +1,116 @@ +. + */ + +/** + * Doctrine_Validator_Driver + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 1080 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Driver +{ + /** + * @var array $_args an array of plugin specific args + */ + protected $_args = array(); + + /** + * __get + * an alias for getOption + * + * @param string $arg + */ + public function __get($arg) + { + if (isset($this->_args[$arg])) { + return $this->_args[$arg]; + } + return null; + } + + /** + * __isset + * + * @param string $arg + */ + public function __isset($arg) + { + return isset($this->_args[$arg]); + } + + /** + * sets given value to an argument + * + * @param $arg the name of the option to be changed + * @param $value the value of the option + * @return Doctrine_Validator_Driver this object + */ + public function __set($arg, $value) + { + $this->_args[$arg] = $value; + + return $this; + } + + /** + * returns the value of an argument + * + * @param $arg the name of the option to retrieve + * @return mixed the value of the option + */ + public function getArg($arg) + { + if ( ! isset($this->_args[$arg])) { + throw new Doctrine_Plugin_Exception('Unknown option ' . $arg); + } + + return $this->_args[$arg]; + } + + /** + * sets given value to an argument + * + * @param $arg the name of the option to be changed + * @param $value the value of the option + * @return Doctrine_Validator_Driver this object + */ + public function setArg($arg, $value) + { + $this->_args[$arg] = $value; + + return $this; + } + + /** + * returns all args and their associated values + * + * @return array all args as an associative array + */ + public function getArgs() + { + return $this->_args; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Email.php b/lib/Doctrine/TODO/Validator/Email.php new file mode 100644 index 000000000..411e3e8fd --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Email.php @@ -0,0 +1,78 @@ +. + */ + +/** + * Doctrine_Validator_Email + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Email +{ + /** + * checks if given value is a valid email address + * + * @link http://iamcal.com/publish/articles/php/parsing_email/pdf/ + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + if ($value === null) { + return true; + } + if (isset($this->args)) { + $parts = explode('@', $value); + if (isset($parts[1]) && function_exists('checkdnsrr')) { + if ( ! checkdnsrr($parts[1], 'MX')) { + return false; + } + } + } + + $qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'; + $dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]'; + $atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+'; + $quotedPair = '\\x5c[\\x00-\\x7f]'; + $domainLiteral = "\\x5b($dtext|$quotedPair)*\\x5d"; + $quotedString = "\\x22($qtext|$quotedPair)*\\x22"; + $domain_ref = $atom; + $subDomain = "($domain_ref|$domainLiteral)"; + $word = "($atom|$quotedString)"; + $domain = "$subDomain(\\x2e$subDomain)+"; + /* + following pseudocode to allow strict checking - ask pookey about this if you're puzzled + + if ($this->getValidationOption('strict_checking') == true) { + $domain = "$sub_domain(\\x2e$sub_domain)*"; + } + */ + $localPart = "$word(\\x2e$word)*"; + $addrSpec = "$localPart\\x40$domain"; + + return (bool) preg_match("!^$addrSpec$!D", $value); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/ErrorStack.php b/lib/Doctrine/TODO/Validator/ErrorStack.php new file mode 100644 index 000000000..a2d04acd8 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/ErrorStack.php @@ -0,0 +1,149 @@ +. + */ + +/** + * Doctrine_Validator_ErrorStack + * + * @package Doctrine + * @subpackage Validator + * @author Konsta Vesterinen + * @author Roman Borschel + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + */ +class Doctrine_Validator_ErrorStack extends Doctrine_Access implements Countable, IteratorAggregate +{ + + /** + * The errors of the error stack. + * + * @var array + */ + protected $errors = array(); + + protected $classname = ""; + + /** + * Constructor + * + */ + public function __construct($classname = "") + { + $this->classname = $classname; + } + + /** + * Adds an error to the stack. + * + * @param string $invalidFieldName + * @param string $errorType + */ + public function add($invalidFieldName, $errorCode = 'general') + { + $this->errors[$invalidFieldName][] = $errorCode; + } + + /** + * Removes all existing errors for the specified field from the stack. + * + * @param string $fieldName + */ + public function remove($fieldName) + { + if (isset($this->errors[$fieldName])) { + unset($this->errors[$fieldName]); + } + } + + /** + * Enter description here... + * + * @param unknown_type $name + * @return unknown + */ + public function get($fieldName) + { + return isset($this->errors[$fieldName]) ? $this->errors[$fieldName] : null; + } + + /** + * Enter description here... + * + * @param unknown_type $name + */ + public function set($fieldName, $errorCode) + { + $this->add($fieldName, $errorCode); + } + + /** + * Enter description here... + * + * @return unknown + */ + public function contains($fieldName) + { + return array_key_exists($fieldName, $this->errors); + } + + /** + * Removes all errors from the stack. + */ + public function clear() + { + $this->errors = array(); + } + + /** + * Enter description here... + * + * @return unknown + */ + public function getIterator() + { + return new ArrayIterator($this->errors); + } + + public function toArray() + { + return $this->errors; + } + + /** + * Enter description here... + * + * @return unknown + */ + public function count() + { + return count($this->errors); + } + + /** + * Get the classname where the errors occured + * + */ + public function getClassname(){ + return $this->classname; + } +} diff --git a/lib/Doctrine/TODO/Validator/Exception.php b/lib/Doctrine/TODO/Validator/Exception.php new file mode 100644 index 000000000..2fffea53c --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Exception.php @@ -0,0 +1,100 @@ +. + */ +Doctrine::autoload('Doctrine_Exception'); +/** + * Doctrine_Validator_Exception + * + * @package Doctrine + * @subpackage Validator + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + */ +class Doctrine_Validator_Exception extends Doctrine_Exception implements Countable, IteratorAggregate +{ + /** + * @var array $invalid + */ + private $invalid = array(); + + /** + * @param Doctrine_Validator $validator + */ + public function __construct(array $invalid) + { + $this->invalid = $invalid; + parent::__construct($this->generateMessage()); + } + + public function getInvalidRecords() + { + return $this->invalid; + } + + public function getIterator() + { + return new ArrayIterator($this->invalid); + } + + public function count() + { + return count($this->invalid); + } + + /** + * __toString + * + * @return string + */ + public function __toString() + { + + return parent::__toString(); + } + + /** + * Generate a message with all classes that have exceptions + */ + private function generateMessage() + { + $message = ""; + foreach ($this->invalid as $record) { + $message .= "Validaton error in class " . get_class($record) . " "; + } + return $message; + } + + /** + * This method will apply the value of the $function variable as a user_func + * to tall errorstack objects in the exception + * + * @param mixed Either string with function name or array with object, + * functionname. See call_user_func in php manual for more inforamtion + */ + public function inspect($function) + { + foreach ($this->invalid as $record) { + call_user_func($function, $record->getErrorStack()); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Future.php b/lib/Doctrine/TODO/Validator/Future.php new file mode 100644 index 000000000..7eac4066d --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Future.php @@ -0,0 +1,79 @@ +. + */ + +/** + * Doctrine_Validator_Future + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + * @author Roman Borschel + */ +class Doctrine_Validator_Future +{ + /** + * checks if the given value is a valid date in the future. + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + if ($value === null) { + return true; + } + $e = explode('-', $value); + + if (count($e) !== 3) { + return false; + } + + if (is_array($this->args) && isset($this->args['timezone'])) { + switch (strtolower($this->args['timezone'])) { + case 'gmt': + $now = gmdate("U") - date("Z"); + break; + default: + $now = getdate(); + break; + } + } else { + $now = getdate(); + } + + if ($now['year'] > $e[0]) { + return false; + } else if ($now['year'] == $e[0]) { + if ($now['mon'] > $e[1]) { + return false; + } else if ($now['mon'] == $e[1]) { + return $now['mday'] < $e[2]; + } else { + return true; + } + } else { + return true; + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Htmlcolor.php b/lib/Doctrine/TODO/Validator/Htmlcolor.php new file mode 100644 index 000000000..117142aa5 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Htmlcolor.php @@ -0,0 +1,48 @@ +. + */ + +/** + * Doctrine_Validator_HtmlColor + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_HtmlColor +{ + /** + * checks if given value is a valid html color code + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + if ( ! preg_match("/^#{0,1}[0-9]{6}$/", $value)) { + return false; + } + return true; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Ip.php b/lib/Doctrine/TODO/Validator/Ip.php new file mode 100644 index 000000000..b7d09f568 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Ip.php @@ -0,0 +1,45 @@ +. + */ + +/** + * Doctrine_Validator_Ip + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Ip +{ + /** + * checks if given value is valid ip address + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + return (bool) ip2long(str_replace("\0", '', $value)); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Minlength.php b/lib/Doctrine/TODO/Validator/Minlength.php new file mode 100644 index 000000000..62d69f167 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Minlength.php @@ -0,0 +1,49 @@ +. + */ + +/** + * Doctrine_Validator_Regexp + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Gijs van Dulmen + */ +class Doctrine_Validator_Minlength +{ + /** + * checks if given value is more length than the minimum length required + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + if (isset($this->args) && strlen($value) < $this->args) { + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Nospace.php b/lib/Doctrine/TODO/Validator/Nospace.php new file mode 100644 index 000000000..cf735d8dd --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Nospace.php @@ -0,0 +1,45 @@ +. + */ + +/** + * Doctrine_Validator_Nospace + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Nospace extends Doctrine_Validator_Driver +{ + /** + * checks that value doesn't contain any space chars + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + return ($value === null || ! preg_match('/\s/', $value)); + } +} diff --git a/lib/Doctrine/TODO/Validator/Notblank.php b/lib/Doctrine/TODO/Validator/Notblank.php new file mode 100644 index 000000000..092aec992 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Notblank.php @@ -0,0 +1,46 @@ +. + */ + +/** + * Doctrine_Validator_Notblank + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Notblank extends Doctrine_Validator_Driver +{ + /** + * checks that value isn't blank + * a value is blank when its either null or contains only space characters + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + return (trim($value) !== '' && $value !== null); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Notnull.php b/lib/Doctrine/TODO/Validator/Notnull.php new file mode 100644 index 000000000..dee5bcf8c --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Notnull.php @@ -0,0 +1,45 @@ +. + */ + +/** + * Doctrine_Validator_Notnull + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Notnull extends Doctrine_Validator_Driver +{ + /** + * checks that given value isn't null + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + return ($value !== null); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Past.php b/lib/Doctrine/TODO/Validator/Past.php new file mode 100644 index 000000000..53a277bc9 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Past.php @@ -0,0 +1,79 @@ +. + */ + +/** + * Doctrine_Validator_Past + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + * @author Roman Borschel + */ +class Doctrine_Validator_Past +{ + /** + * checks if the given value is a valid date in the past. + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + if ($value === null) { + return true; + } + $e = explode('-', $value); + + if (count($e) !== 3) { + return false; + } + + if (is_array($this->args) && isset($this->args['timezone'])) { + switch (strtolower($this->args['timezone'])) { + case 'gmt': + $now = gmdate("U") - date("Z"); + break; + default: + $now = getdate(); + break; + } + } else { + $now = getdate(); + } + + if ($now['year'] < $e[0]) { + return false; + } else if ($now['year'] == $e[0]) { + if ($now['mon'] < $e[1]) { + return false; + } else if ($now['mon'] == $e[1]) { + return $now['mday'] > $e[2]; + } else { + return true; + } + } else { + return true; + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Protected.php b/lib/Doctrine/TODO/Validator/Protected.php new file mode 100644 index 000000000..6fd199e66 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Protected.php @@ -0,0 +1 @@ +. + */ + +/** + * Doctrine_Validator_Range + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Range +{ + /** + * checks if value is within given range + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + if (isset($this->args[0]) && $value < $this->args[0]) { + return false; + } + if (isset($this->args[1]) && $value > $this->args[1]) { + return false; + } + return true; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Readonly.php b/lib/Doctrine/TODO/Validator/Readonly.php new file mode 100644 index 000000000..51caaf4ca --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Readonly.php @@ -0,0 +1,43 @@ +. + */ + +/** + * Doctrine_Validator_Readonly + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @author Adam Huttler + */ +class Doctrine_Validator_Readonly +{ + /** + * checks if value has been modified + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + $modified = $this->invoker->getModified(); + + return array_key_exists($this->field, $modified) ? false : true; + } +} diff --git a/lib/Doctrine/TODO/Validator/Regexp.php b/lib/Doctrine/TODO/Validator/Regexp.php new file mode 100644 index 000000000..0ab524d63 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Regexp.php @@ -0,0 +1,62 @@ +. + */ + +/** + * Doctrine_Validator_Regexp + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Regexp +{ + /** + * checks if given value satisfies a regular expression + * + * @param mixed $value + * @param mixed $args + * @return boolean + */ + public function validate($value) + { + if ( ! isset($this->args)) { + return true; + } + if (is_array($this->args)) { + foreach ($this->args as $regexp) { + if ( ! preg_match($regexp, $value)) { + return false; + } + } + return true; + } else { + if (preg_match($this->args, $value)) { + return true; + } + } + + return false; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Time.php b/lib/Doctrine/TODO/Validator/Time.php new file mode 100644 index 000000000..1f9fd4115 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Time.php @@ -0,0 +1,62 @@ +. + */ + +/** + * Doctrine_Validator_Time + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3884 $ + * @author Mark Pearson + */ +class Doctrine_Validator_Time +{ + /** + * checks if given value is a valid time + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + if ($value === null) { + return true; + } + $e = explode(':', $value); + + if (count($e) !== 3) { + return false; + } + + if (!preg_match('/^ *[0-9]{2}:[0-9]{2}:[0-9]{2} *$/', $value)) { + return false; + } + + $hr = intval($e[0], 10); + $min = intval($e[1], 10); + $sec = intval($e[2], 10); + + return $hr >= 0 && $hr <= 23 && $min >= 0 && $min <= 59 && $sec >= 0 && $sec <= 59; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Timestamp.php b/lib/Doctrine/TODO/Validator/Timestamp.php new file mode 100644 index 000000000..a5ca739e4 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Timestamp.php @@ -0,0 +1,66 @@ +. + */ + +/** + * Doctrine_Validator_Timestamp + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3884 $ + * @author Mark Pearson + */ +class Doctrine_Validator_Timestamp +{ + /** + * checks if given value is a valid timestamp (YYYY-MM-DD HH:MM:SS) + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + if ($value === null) { + return true; + } + + if (!preg_match('/^ *[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} *$/', $value)) { + return false; + } + + list($date, $time) = explode(' ', trim($value)); + + $dateValidator = Doctrine_Validator::getValidator('date'); + $timeValidator = Doctrine_Validator::getValidator('time'); + + if (!$dateValidator->validate($date)) { + return false; + } + + if (!$timeValidator->validate($time)) { + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Unique.php b/lib/Doctrine/TODO/Validator/Unique.php new file mode 100644 index 000000000..aa861336e --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Unique.php @@ -0,0 +1,71 @@ +. + */ + +/** + * Doctrine_Validator_Unique + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 4364 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Unique +{ + /** + * checks if given value is unique + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + $table = $this->invoker->getTable(); + $pks = (array)$table->getIdentifier(); + + if ( is_array($pks) ) { + $pks = join(',', $pks); + } + + $sql = 'SELECT ' . $pks . ' FROM ' . $table->getTableName() . ' WHERE ' . $this->field . ' = ?'; + + $values = array(); + $values[] = $value; + + // If the record is not new we need to add primary key checks because its ok if the + // unique value already exists in the database IF the record in the database is the same + // as the one that is validated here. + $state = $this->invoker->state(); + if ( ! ($state == Doctrine_Entity::STATE_TDIRTY || $state == Doctrine_Entity::STATE_TCLEAN)) { + foreach ((array) $table->getIdentifier() as $pk) { + $sql .= " AND {$pk} != ?"; + $values[] = $this->invoker->$pk; + } + } + + $stmt = $table->getConnection()->getDbh()->prepare($sql); + $stmt->execute($values); + + return ( ! is_array($stmt->fetch())); + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Unsigned.php b/lib/Doctrine/TODO/Validator/Unsigned.php new file mode 100644 index 000000000..02af1fd37 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Unsigned.php @@ -0,0 +1,50 @@ +. + */ + +/** + * Doctrine_Validator_Unsigned + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 1080 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Unsigned +{ + /** + * checks if given value is a valid unsigned integer + * + * @param mixed $value + * @return boolean + */ + public function validate($value) + { + $int = (int) $value; + + if ($int != $value || $int < 0) { + return false; + } + return true; + } +} \ No newline at end of file diff --git a/lib/Doctrine/TODO/Validator/Usstate.php b/lib/Doctrine/TODO/Validator/Usstate.php new file mode 100644 index 000000000..b5dbc50d5 --- /dev/null +++ b/lib/Doctrine/TODO/Validator/Usstate.php @@ -0,0 +1,105 @@ +. + */ + +/** + * Doctrine_Validator_Usstate + * + * @package Doctrine + * @subpackage Validator + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.org + * @since 1.0 + * @version $Revision: 3882 $ + * @author Konsta Vesterinen + */ +class Doctrine_Validator_Usstate +{ + private static $states = array( + 'AK' => true, + 'AL' => true, + 'AR' => true, + 'AZ' => true, + 'CA' => true, + 'CO' => true, + 'CT' => true, + 'DC' => true, + 'DE' => true, + 'FL' => true, + 'GA' => true, + 'HI' => true, + 'IA' => true, + 'ID' => true, + 'IL' => true, + 'IN' => true, + 'KS' => true, + 'KY' => true, + 'LA' => true, + 'MA' => true, + 'MD' => true, + 'ME' => true, + 'MI' => true, + 'MN' => true, + 'MO' => true, + 'MS' => true, + 'MT' => true, + 'NC' => true, + 'ND' => true, + 'NE' => true, + 'NH' => true, + 'NJ' => true, + 'NM' => true, + 'NV' => true, + 'NY' => true, + 'OH' => true, + 'OK' => true, + 'OR' => true, + 'PA' => true, + 'PR' => true, + 'RI' => true, + 'SC' => true, + 'SD' => true, + 'TN' => true, + 'TX' => true, + 'UT' => true, + 'VA' => true, + 'VI' => true, + 'VT' => true, + 'WA' => true, + 'WI' => true, + 'WV' => true, + 'WY' => true + ); + public function getStates() + { + return self::$states; + } + + /** + * checks if given value is a valid US state code + * + * @param string $args + * @return boolean + */ + public function validate($value) + { + return isset(self::$states[$value]); + } +} \ No newline at end of file