From 975b74bd6f0f72ab3ab781ce1235d34c3b45dcb7 Mon Sep 17 00:00:00 2001 From: "Jonathan.Wage" Date: Sat, 20 Oct 2007 06:12:20 +0000 Subject: [PATCH] Enhancements to CLI and removing sandbox files. Will add ignores. --- lib/Doctrine/Adapter.php | 1 + lib/Doctrine/Cli.php | 179 +++-- lib/Doctrine/Cli/AnsiColorFormatter.php | 162 ++++ lib/Doctrine/Cli/Formatter.php | 108 +++ lib/Doctrine/FileFinder.php | 746 ++++++++++++++++++ lib/Doctrine/Migration.php | 4 +- lib/Doctrine/Task.php | 18 +- lib/Doctrine/Task/CreateTables.php | 2 + lib/Doctrine/Task/DropDb.php | 2 + lib/Doctrine/Task/DumpData.php | 2 + lib/Doctrine/Task/GenerateMigration.php | 2 + .../Task/GenerateMigrationsFromDb.php | 2 + .../Task/GenerateMigrationsFromModels.php | 2 + lib/Doctrine/Task/GenerateModelsFromDb.php | 2 + lib/Doctrine/Task/GenerateModelsFromYaml.php | 2 + lib/Doctrine/Task/GenerateSql.php | 2 + lib/Doctrine/Task/GenerateYamlFromDb.php | 2 + lib/Doctrine/Task/GenerateYamlFromModels.php | 2 + lib/Doctrine/Task/LoadData.php | 2 + lib/Doctrine/Task/LoadDummyData.php | 2 + lib/Doctrine/Task/Migrate.php | 4 +- sandbox/cli.php | 2 +- sandbox/data/fixtures/adult.yml | 5 - sandbox/data/fixtures/car.yml | 8 - sandbox/data/fixtures/child.yml | 5 - sandbox/data/fixtures/data.yml | 8 - sandbox/data/fixtures/dog.yml | 11 - sandbox/data/fixtures/self_reference.yml | 20 - sandbox/data/fixtures/user_car.yml | 11 - sandbox/migrations/001_add_adult.class.php | 42 - sandbox/migrations/002_add_car.class.php | 37 - sandbox/migrations/003_add_child.class.php | 42 - sandbox/migrations/004_add_contact.class.php | 37 - sandbox/migrations/005_add_dog.class.php | 42 - sandbox/migrations/006_add_entity.class.php | 32 - sandbox/migrations/007_add_groups.class.php | 38 - sandbox/models/Adult.class.php | 12 - sandbox/models/Car.class.php | 12 - sandbox/models/Child.class.php | 12 - sandbox/models/Contact.class.php | 12 - sandbox/models/Dog.class.php | 12 - sandbox/models/Entity.class.php | 12 - sandbox/models/Group.class.php | 12 - sandbox/models/SelfReference.class.php | 12 - sandbox/models/User.class.php | 12 - sandbox/models/UserCar.class.php | 12 - sandbox/models/UserGroup.class.php | 12 - sandbox/models/generated/BaseAdult.class.php | 34 - sandbox/models/generated/BaseCar.class.php | 30 - sandbox/models/generated/BaseChild.class.php | 31 - .../models/generated/BaseContact.class.php | 32 - sandbox/models/generated/BaseDog.class.php | 31 - sandbox/models/generated/BaseEntity.class.php | 22 - sandbox/models/generated/BaseGroup.class.php | 31 - .../generated/BaseSelfReference.class.php | 52 -- sandbox/models/generated/BaseUser.class.php | 51 -- .../models/generated/BaseUserCar.class.php | 31 - .../models/generated/BaseUserGroup.class.php | 31 - sandbox/schema/adult.yml | 17 - sandbox/schema/car.yml | 15 - sandbox/schema/child.yml | 17 - sandbox/schema/contact.yml | 11 - sandbox/schema/dog.yml | 17 - sandbox/schema/entity.yml | 8 - sandbox/schema/group.yml | 18 - sandbox/schema/self_reference.yml | 40 - sandbox/schema/user.yml | 38 - sandbox/schema/user_car.yml | 14 - sandbox/schema/user_group.yml | 14 - 69 files changed, 1189 insertions(+), 1116 deletions(-) create mode 100644 lib/Doctrine/Cli/AnsiColorFormatter.php create mode 100644 lib/Doctrine/Cli/Formatter.php create mode 100644 lib/Doctrine/FileFinder.php delete mode 100644 sandbox/data/fixtures/adult.yml delete mode 100644 sandbox/data/fixtures/car.yml delete mode 100644 sandbox/data/fixtures/child.yml delete mode 100644 sandbox/data/fixtures/data.yml delete mode 100644 sandbox/data/fixtures/dog.yml delete mode 100644 sandbox/data/fixtures/self_reference.yml delete mode 100644 sandbox/data/fixtures/user_car.yml delete mode 100644 sandbox/migrations/001_add_adult.class.php delete mode 100644 sandbox/migrations/002_add_car.class.php delete mode 100644 sandbox/migrations/003_add_child.class.php delete mode 100644 sandbox/migrations/004_add_contact.class.php delete mode 100644 sandbox/migrations/005_add_dog.class.php delete mode 100644 sandbox/migrations/006_add_entity.class.php delete mode 100644 sandbox/migrations/007_add_groups.class.php delete mode 100644 sandbox/models/Adult.class.php delete mode 100644 sandbox/models/Car.class.php delete mode 100644 sandbox/models/Child.class.php delete mode 100644 sandbox/models/Contact.class.php delete mode 100644 sandbox/models/Dog.class.php delete mode 100644 sandbox/models/Entity.class.php delete mode 100644 sandbox/models/Group.class.php delete mode 100644 sandbox/models/SelfReference.class.php delete mode 100644 sandbox/models/User.class.php delete mode 100644 sandbox/models/UserCar.class.php delete mode 100644 sandbox/models/UserGroup.class.php delete mode 100644 sandbox/models/generated/BaseAdult.class.php delete mode 100644 sandbox/models/generated/BaseCar.class.php delete mode 100644 sandbox/models/generated/BaseChild.class.php delete mode 100644 sandbox/models/generated/BaseContact.class.php delete mode 100644 sandbox/models/generated/BaseDog.class.php delete mode 100644 sandbox/models/generated/BaseEntity.class.php delete mode 100644 sandbox/models/generated/BaseGroup.class.php delete mode 100644 sandbox/models/generated/BaseSelfReference.class.php delete mode 100644 sandbox/models/generated/BaseUser.class.php delete mode 100644 sandbox/models/generated/BaseUserCar.class.php delete mode 100644 sandbox/models/generated/BaseUserGroup.class.php delete mode 100644 sandbox/schema/adult.yml delete mode 100644 sandbox/schema/car.yml delete mode 100644 sandbox/schema/child.yml delete mode 100644 sandbox/schema/contact.yml delete mode 100644 sandbox/schema/dog.yml delete mode 100644 sandbox/schema/entity.yml delete mode 100644 sandbox/schema/group.yml delete mode 100644 sandbox/schema/self_reference.yml delete mode 100644 sandbox/schema/user.yml delete mode 100644 sandbox/schema/user_car.yml delete mode 100644 sandbox/schema/user_group.yml diff --git a/lib/Doctrine/Adapter.php b/lib/Doctrine/Adapter.php index 3ad92b500..92389526b 100644 --- a/lib/Doctrine/Adapter.php +++ b/lib/Doctrine/Adapter.php @@ -18,6 +18,7 @@ * and is licensed under the LGPL. For more information, see * . */ + /** * * Doctrine_Adapter diff --git a/lib/Doctrine/Cli.php b/lib/Doctrine/Cli.php index 3d7d866f8..20e04a3ad 100644 --- a/lib/Doctrine/Cli.php +++ b/lib/Doctrine/Cli.php @@ -32,10 +32,13 @@ */ class Doctrine_Cli { - protected $tasks = array(); - protected $scriptName = null; - protected $config = array(); - + protected $tasks = array(), + $taskInstance = null, + $formatter = null, + $scriptName = null, + $message = null, + $config = array(); + /** * __construct * @@ -45,6 +48,29 @@ class Doctrine_Cli public function __construct($config = array()) { $this->config = $config; + $this->formatter = new Doctrine_Cli_AnsiColorFormatter(); + } + + /** + * notify + * + * @param string $notification + * @return void + */ + public function notify($notification = null) + { + echo $this->formatter->format($this->taskInstance->getTaskName(), 'INFO') . ' - ' . $this->formatter->format($notification, 'HEADER') . "\n"; + } + + /** + * notifyException + * + * @param string $exception + * @return void + */ + public function notifyException($exception) + { + echo $this->formatter->format($exception->getMessage(), 'ERROR') . "\n"; } /** @@ -56,43 +82,79 @@ class Doctrine_Cli */ public function run($args) { - $this->scriptName = $args[0]; + echo "\n"; - if (!isset($args[1])) { - echo $this->printTasks(); + try { + $this->_run($args); + } catch (Exception $exception) { + $this->notifyException($exception); + } + + echo "\n"; + } + + protected function _getTaskClassFromArgs($args) + { + $taskName = str_replace('-', '_', $args[1]); + $taskClass = 'Doctrine_Task_' . Doctrine::classify($taskName); + + return $taskClass; + } + + protected function _run($args) + { + $this->scriptName = $args[0]; + $taskName = $args[1]; + + $arg1 = isset($args[1]) ? $args[1]:null; + + if (!$arg1 || $arg1 == 'help') { + echo $this->printTasks(null, $arg1 == 'help' ? true:false); return; } + if (isset($args[1]) && isset($args[2]) && $args[2] == 'help') { + echo $this->printTasks($args[1], true); + return; + } + + $taskClass = $this->_getTaskClassFromArgs($args); + + if (!class_exists($taskClass)) { + throw new Doctrine_Cli_Exception('Cli task could not be found: ' . $taskClass); + } + unset($args[0]); - $taskName = str_replace('-', '_', $args[1]); unset($args[1]); - $taskClass = 'Doctrine_Task_' . Doctrine::classify($taskName); + $this->taskInstance = new $taskClass($this); - if (class_exists($taskClass)) { - $taskInstance = new $taskClass(); - - $args = $this->prepareArgs($taskInstance, $args); - - $taskInstance->setArguments($args); - - if ($taskInstance->validate()) { - $taskInstance->execute(); + $args = $this->prepareArgs($args); + + $this->taskInstance->setArguments($args); + + try { + if ($this->taskInstance->validate()) { + $this->taskInstance->execute(); + } else { + echo $this->formatter->format('Requires arguments missing!!', 'ERROR') . "\n\n"; + echo $this->printTasks($taskName, true); } - } else { - throw new Doctrine_Cli_Exception('Cli task could not be found: '.$taskClass); + } catch (Exception $e) { + throw new Doctrine_Cli_Exception($e->getMessage()); } } /** * prepareArgs * - * @param string $taskInstance * @param string $args * @return array $prepared */ - protected function prepareArgs($taskInstance, $args) + protected function prepareArgs($args) { + $taskInstance = $this->taskInstance; + $args = array_values($args); // First lets load populate an array with all the possible arguments. required and optional @@ -137,54 +199,63 @@ class Doctrine_Cli * * @return void */ - public function printTasks() + public function printTasks($task = null, $full = false) { + $task = Doctrine::classify(str_replace('-', '_', $task)); + $tasks = $this->loadTasks(); - echo "\nAvailable Doctrine Command Line Interface Tasks\n"; - echo str_repeat('-', 40)."\n\n"; + echo $this->formatter->format("Doctrine Command Line Interface", 'HEADER') . "\n\n"; foreach ($tasks as $taskName) { + if ($task != null && strtolower($task) != strtolower($taskName)) { + continue; + } + $className = 'Doctrine_Task_' . $taskName; $taskInstance = new $className(); - $taskInstance->taskName = str_replace('_', '-', Doctrine::tableize($taskName)); + $taskInstance->taskName = str_replace('_', '-', Doctrine::tableize($taskName)); - echo $taskInstance->getDescription() . "\n"; + $syntax = $this->scriptName . ' ' . $taskInstance->getTaskName(); - $syntax = "Syntax: "; + echo $this->formatter->format($syntax, 'INFO'); - $syntax .= $this->scriptName . ' ' . $taskInstance->getTaskName(); + if ($full) { + echo " - " . $taskInstance->getDescription() . "\n"; + + $args = null; + + $requiredArguments = $taskInstance->getRequiredArgumentsDescriptions(); + + if (!empty($requiredArguments)) { + foreach ($requiredArguments as $name => $description) { + $args .= $this->formatter->format($name, "ERROR"); + + if (isset($this->config[$name])) { + $args .= " - " . $this->formatter->format($this->config[$name], 'COMMENT'); + } else { + $args .= " - " . $description; + } + + $args .= "\n"; + } + } - if ($required = $taskInstance->getRequiredArguments()) { - $syntax .= ' <' . implode('> <', $required) . '>'; - } - - if ($optional = $taskInstance->getOptionalArguments()) { - $syntax .= ' <' . implode('> <', $optional) . '>'; - } + $optionalArguments = $taskInstance->getOptionalArgumentsDescriptions(); + + if (!empty($optionalArguments)) { + foreach ($optionalArguments as $name => $description) { + $args .= $name . ' - ' . $description."\n"; + } + } - echo $syntax."\n"; - - $args = null; - if ($requiredArguments = $taskInstance->getRequiredArgumentsDescriptions()) { - foreach ($requiredArguments as $name => $description) { - $args .= '*' . $name . ' - ' . $description."\n"; + if ($args) { + echo "\n" . $this->formatter->format('Arguments:', 'HEADER') . "\n" . $args; } } - if ($optionalArguments = $taskInstance->getOptionalArgumentsDescriptions()) { - foreach ($optionalArguments as $name => $description) { - $args .= $name . ' - ' . $description."\n"; - } - } - - if ($args) { - echo "\nArguments (* = required):\n"; - echo $args; - } - - echo "\n".str_repeat("-", 40)."\n"; + echo "\n"; } } diff --git a/lib/Doctrine/Cli/AnsiColorFormatter.php b/lib/Doctrine/Cli/AnsiColorFormatter.php new file mode 100644 index 000000000..616611fc2 --- /dev/null +++ b/lib/Doctrine/Cli/AnsiColorFormatter.php @@ -0,0 +1,162 @@ + + * + * 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/Cli/Formatter.php b/lib/Doctrine/Cli/Formatter.php new file mode 100644 index 000000000..305979fce --- /dev/null +++ b/lib/Doctrine/Cli/Formatter.php @@ -0,0 +1,108 @@ + + * + * 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; + + 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/FileFinder.php b/lib/Doctrine/FileFinder.php new file mode 100644 index 000000000..303e94f9f --- /dev/null +++ b/lib/Doctrine/FileFinder.php @@ -0,0 +1,746 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/* + * $Id$ + * + * 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 + * . + */ + +/** + * + * This is a port of sfFinder from the symfony-project. + * http://www.symfony-project.com + * + * Allow to build rules to find files and directories. + * + * All rules may be invoked several times, except for ->in() method. + * Some rules are cumulative (->name() for example) whereas others are destructive + * (most recent value is used, ->maxdepth() method for example). + * + * All methods return the current Doctrine_FileFinder object to allow easy chaining: + * + * $files = Doctrine_FileFinder::type('file')->name('*.php')->in(.); + * + * Interface loosely based on perl File::Find::Rule module. + * + * Doctrine_FileFinder + * + * @package Doctrine + * @subpackage FileFinder + * @author Symfony Project/Fabien Potencier + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision$ + * @link www.symfony-project.com + * @since 1.0 + */ +class Doctrine_FileFinder +{ + protected $type = 'file'; + protected $names = array(); + protected $prunes = array(); + protected $discards = array(); + protected $execs = array(); + protected $mindepth = 0; + protected $sizes = array(); + protected $maxdepth = 1000000; + protected $relative = false; + protected $follow_link = false; + + /** + * Sets maximum directory depth. + * + * Finder will descend at most $level levels of directories below the starting point. + * + * @param integer level + * @return object current Doctrine_FileFinder object + */ + public function maxdepth($level) + { + $this->maxdepth = $level; + + return $this; + } + + /** + * Sets minimum directory depth. + * + * Finder will start applying tests at level $level. + * + * @param integer level + * @return object current Doctrine_FileFinder object + */ + public function mindepth($level) + { + $this->mindepth = $level; + + return $this; + } + + public function get_type() + { + return $this->type; + } + + /** + * Sets the type of elements to returns. + * + * @param string directory or file or any (for both file and directory) + * @return object new Doctrine_FileFinder object + */ + public static function type($name) + { + $finder = new Doctrine_FileFinder(); + return $finder->setType($name); + } + + public function setType($name) + { + if (strtolower(substr($name, 0, 3)) == 'dir') + { + $this->type = 'directory'; + } + else if (strtolower($name) == 'any') + { + $this->type = 'any'; + } + else + { + $this->type = 'file'; + } + + return $this; + } + + /* + * glob, patterns (must be //) or strings + */ + protected function to_regex($str) + { + if ($str{0} == '/' && $str{strlen($str) - 1} == '/') + { + return $str; + } + else + { + return Doctrine_GlobToRegex::glob_to_regex($str); + } + } + + protected function args_to_array($arg_list, $not = false) + { + $list = array(); + + for ($i = 0; $i < count($arg_list); $i++) + { + if (is_array($arg_list[$i])) + { + foreach ($arg_list[$i] as $arg) + { + $list[] = array($not, $this->to_regex($arg)); + } + } + else + { + $list[] = array($not, $this->to_regex($arg_list[$i])); + } + } + + return $list; + } + + /** + * Adds rules that files must match. + * + * You can use patterns (delimited with / sign), globs or simple strings. + * + * $finder->name('*.php') + * $finder->name('/\.php$/') // same as above + * $finder->name('test.php') + * + * @param list a list of patterns, globs or strings + * @return object current Doctrine_FileFinder object + */ + public function name() + { + $args = func_get_args(); + $this->names = array_merge($this->names, $this->args_to_array($args)); + + return $this; + } + + /** + * Adds rules that files must not match. + * + * @see ->name() + * @param list a list of patterns, globs or strings + * @return object current Doctrine_FileFinder object + */ + public function not_name() + { + $args = func_get_args(); + $this->names = array_merge($this->names, $this->args_to_array($args, true)); + + return $this; + } + + /** + * Adds tests for file sizes. + * + * $finder->size('> 10K'); + * $finder->size('<= 1Ki'); + * $finder->size(4); + * + * @param list a list of comparison strings + * @return object current Doctrine_FileFinder object + */ + public function size() + { + $args = func_get_args(); + for ($i = 0; $i < count($args); $i++) + { + $this->sizes[] = new Doctrine_NumberCompare($args[$i]); + } + + return $this; + } + + /** + * Traverses no further. + * + * @param list a list of patterns, globs to match + * @return object current Doctrine_FileFinder object + */ + public function prune() + { + $args = func_get_args(); + $this->prunes = array_merge($this->prunes, $this->args_to_array($args)); + + return $this; + } + + /** + * Discards elements that matches. + * + * @param list a list of patterns, globs to match + * @return object current Doctrine_FileFinder object + */ + public function discard() + { + $args = func_get_args(); + $this->discards = array_merge($this->discards, $this->args_to_array($args)); + + return $this; + } + + /** + * Ignores version control directories. + * + * Currently supports subversion, CVS, DARCS, Gnu Arch, Monotone, Bazaar-NG + * + * @return object current Doctrine_FileFinder object + */ + public function ignore_version_control() + { + $ignores = array('.svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr'); + + return $this->discard($ignores)->prune($ignores); + } + + /** + * Executes function or method for each element. + * + * Element match if functino or method returns true. + * + * $finder->exec('myfunction'); + * $finder->exec(array($object, 'mymethod')); + * + * @param mixed function or method to call + * @return object current Doctrine_FileFinder object + */ + public function exec() + { + $args = func_get_args(); + for ($i = 0; $i < count($args); $i++) + { + if (is_array($args[$i]) && !method_exists($args[$i][0], $args[$i][1])) + { + throw new Doctrine_Exception(sprintf('method "%s" does not exist for object "%s".', $args[$i][1], $args[$i][0])); + } + else if (!is_array($args[$i]) && !function_exists($args[$i])) + { + throw new Doctrine_Exception(sprintf('function "%s" does not exist.', $args[$i])); + } + + $this->execs[] = $args[$i]; + } + + return $this; + } + + /** + * Returns relative paths for all files and directories. + * + * @return object current Doctrine_FileFinder object + */ + public function relative() + { + $this->relative = true; + + return $this; + } + + /** + * Symlink following. + * + * @return object current Doctrine_FileFinder object + */ + public function follow_link() + { + $this->follow_link = true; + + return $this; + } + + /** + * Searches files and directories which match defined rules. + * + * @return array list of files and directories + */ + public function in() + { + $files = array(); + $here_dir = getcwd(); + $numargs = func_num_args(); + $arg_list = func_get_args(); + + // first argument is an array? + if ($numargs == 1 && is_array($arg_list[0])) + { + $arg_list = $arg_list[0]; + $numargs = count($arg_list); + } + + for ($i = 0; $i < $numargs; $i++) + { + $real_dir = realpath($arg_list[$i]); + + // absolute path? + if (!self::isPathAbsolute($real_dir)) + { + $dir = $here_dir.DIRECTORY_SEPARATOR.$real_dir; + } + else + { + $dir = $real_dir; + } + + if (!is_dir($real_dir)) + { + continue; + } + + if ($this->relative) + { + $files = array_merge($files, str_replace($dir.DIRECTORY_SEPARATOR, '', $this->search_in($dir))); + } + else + { + $files = array_merge($files, $this->search_in($dir)); + } + } + + return array_unique($files); + } + + protected function search_in($dir, $depth = 0) + { + if ($depth > $this->maxdepth) + { + return array(); + } + + if (is_link($dir) && !$this->follow_link) + { + return array(); + } + + $files = array(); + + if (is_dir($dir)) + { + $current_dir = opendir($dir); + while (false !== $entryname = readdir($current_dir)) + { + if ($entryname == '.' || $entryname == '..') continue; + + $current_entry = $dir.DIRECTORY_SEPARATOR.$entryname; + if (is_link($current_entry) && !$this->follow_link) + { + continue; + } + + if (is_dir($current_entry)) + { + if (($this->type == 'directory' || $this->type == 'any') && ($depth >= $this->mindepth) && !$this->is_discarded($dir, $entryname) && $this->match_names($dir, $entryname) && $this->exec_ok($dir, $entryname)) + { + $files[] = realpath($current_entry); + } + + if (!$this->is_pruned($dir, $entryname)) + { + $files = array_merge($files, $this->search_in($current_entry, $depth + 1)); + } + } + else + { + if (($this->type != 'directory' || $this->type == 'any') && ($depth >= $this->mindepth) && !$this->is_discarded($dir, $entryname) && $this->match_names($dir, $entryname) && $this->size_ok($dir, $entryname) && $this->exec_ok($dir, $entryname)) + { + $files[] = realpath($current_entry); + } + } + } + closedir($current_dir); + } + + return $files; + } + + protected function match_names($dir, $entry) + { + if (!count($this->names)) return true; + + // we must match one "not_name" rules to be ko + $one_not_name_rule = false; + foreach ($this->names as $args) + { + list($not, $regex) = $args; + if ($not) + { + $one_not_name_rule = true; + if (preg_match($regex, $entry)) + { + return false; + } + } + } + + $one_name_rule = false; + // we must match one "name" rules to be ok + foreach ($this->names as $args) + { + list($not, $regex) = $args; + if (!$not) + { + $one_name_rule = true; + if (preg_match($regex, $entry)) + { + return true; + } + } + } + + if ($one_not_name_rule && $one_name_rule) + { + return false; + } + else if ($one_not_name_rule) + { + return true; + } + else if ($one_name_rule) + { + return false; + } + else + { + return true; + } + } + + protected function size_ok($dir, $entry) + { + if (!count($this->sizes)) return true; + + if (!is_file($dir.DIRECTORY_SEPARATOR.$entry)) return true; + + $filesize = filesize($dir.DIRECTORY_SEPARATOR.$entry); + foreach ($this->sizes as $number_compare) + { + if (!$number_compare->test($filesize)) return false; + } + + return true; + } + + protected function is_pruned($dir, $entry) + { + if (!count($this->prunes)) return false; + + foreach ($this->prunes as $args) + { + $regex = $args[1]; + if (preg_match($regex, $entry)) return true; + } + + return false; + } + + protected function is_discarded($dir, $entry) + { + if (!count($this->discards)) return false; + + foreach ($this->discards as $args) + { + $regex = $args[1]; + if (preg_match($regex, $entry)) return true; + } + + return false; + } + + protected function exec_ok($dir, $entry) + { + if (!count($this->execs)) return true; + + foreach ($this->execs as $exec) + { + if (!call_user_func_array($exec, array($dir, $entry))) return false; + } + + return true; + } + + public static function isPathAbsolute($path) + { + if ($path{0} == '/' || $path{0} == '\\' || + (strlen($path) > 3 && ctype_alpha($path{0}) && + $path{1} == ':' && + ($path{2} == '\\' || $path{2} == '/') + ) + ) + { + return true; + } + + return false; + } +} + +/** + * Match globbing patterns against text. + * + * if match_glob("foo.*", "foo.bar") echo "matched\n"; + * + * // prints foo.bar and foo.baz + * $regex = glob_to_regex("foo.*"); + * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t) + * { + * if (/$regex/) echo "matched: $car\n"; + * } + * + * Doctrine_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_GlobToRegex +{ + protected static $strict_leading_dot = true; + protected static $strict_wildcard_slash = true; + + public static function setStrictLeadingDot($boolean) + { + self::$strict_leading_dot = $boolean; + } + + public static function setStrictWildcardSlash($boolean) + { + self::$strict_wildcard_slash = $boolean; + } + + /** + * Returns a compiled regex which is the equiavlent of the globbing pattern. + * + * @param string glob pattern + * @return string regex + */ + public static function glob_to_regex($glob) + { + $first_byte = true; + $escaping = false; + $in_curlies = 0; + $regex = ''; + for ($i = 0; $i < strlen($glob); $i++) + { + $car = $glob[$i]; + if ($first_byte) + { + if (self::$strict_leading_dot && $car != '.') + { + $regex .= '(?=[^\.])'; + } + + $first_byte = false; + } + + if ($car == '/') + { + $first_byte = true; + } + + if ($car == '.' || $car == '(' || $car == ')' || $car == '|' || $car == '+' || $car == '^' || $car == '$') + { + $regex .= "\\$car"; + } + else if ($car == '*') + { + $regex .= ($escaping ? "\\*" : (self::$strict_wildcard_slash ? "[^/]*" : ".*")); + } + else if ($car == '?') + { + $regex .= ($escaping ? "\\?" : (self::$strict_wildcard_slash ? "[^/]" : ".")); + } + else if ($car == '{') + { + $regex .= ($escaping ? "\\{" : "("); + if (!$escaping) ++$in_curlies; + } + else if ($car == '}' && $in_curlies) + { + $regex .= ($escaping ? "}" : ")"); + if (!$escaping) --$in_curlies; + } + else if ($car == ',' && $in_curlies) + { + $regex .= ($escaping ? "," : "|"); + } + else if ($car == "\\") + { + if ($escaping) + { + $regex .= "\\\\"; + $escaping = false; + } + else + { + $escaping = true; + } + + continue; + } + else + { + $regex .= $car; + $escaping = false; + } + $escaping = false; + } + + return "#^$regex$#"; + } +} + +/** + * Numeric comparisons. + * + * Doctrine_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_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_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/Migration.php b/lib/Doctrine/Migration.php index bbfbdde32..1c10070ff 100644 --- a/lib/Doctrine/Migration.php +++ b/lib/Doctrine/Migration.php @@ -326,7 +326,7 @@ class Doctrine_Migration } if ($from == $to) { - throw new Doctrine_Migration_Exception('Already at version: ' . $to); + throw new Doctrine_Migration_Exception('Already at version # ' . $to); } $direction = $from > $to ? 'down':'up'; @@ -343,7 +343,7 @@ class Doctrine_Migration $this->setCurrentVersion($to); - return true; + return $to; } /** diff --git a/lib/Doctrine/Task.php b/lib/Doctrine/Task.php index 11d74e37f..8658f1bd1 100644 --- a/lib/Doctrine/Task.php +++ b/lib/Doctrine/Task.php @@ -34,7 +34,8 @@ */ abstract class Doctrine_Task { - public $taskName = null, + public $dispatcher = null, + $taskName = null, $description = null, $arguments = array(), $requiredArguments = array(), @@ -48,11 +49,22 @@ abstract class Doctrine_Task * * @return void */ - public function __construct() + public function __construct($dispatcher = null) { + $this->dispatcher = $dispatcher; + $this->taskName = str_replace('_', '-', Doctrine::tableize(str_replace('Doctrine_Task_', '', get_class($this)))); } + public function notify($message) + { + if (is_object($message)) { + return $message->notify($message); + } else { + return $message; + } + } + /** * execute * @@ -76,7 +88,7 @@ abstract class Doctrine_Task foreach ($requiredArguments as $arg) { if (!isset($this->arguments[$arg])) { - throw new Doctrine_Task_Exception('Required arguments missing. The follow arguments are required: ' . implode(', ', $requiredArguments)); + return false; } } diff --git a/lib/Doctrine/Task/CreateTables.php b/lib/Doctrine/Task/CreateTables.php index fd6591a6a..7b77644e7 100644 --- a/lib/Doctrine/Task/CreateTables.php +++ b/lib/Doctrine/Task/CreateTables.php @@ -39,5 +39,7 @@ class Doctrine_Task_CreateTables extends Doctrine_Task public function execute() { Doctrine::createTablesFromModels($this->getArgument('models_path')); + + $this->dispatcher->notify('successfully created tables'); } } \ No newline at end of file diff --git a/lib/Doctrine/Task/DropDb.php b/lib/Doctrine/Task/DropDb.php index 8e22227da..6c42f19d5 100644 --- a/lib/Doctrine/Task/DropDb.php +++ b/lib/Doctrine/Task/DropDb.php @@ -39,5 +39,7 @@ class Doctrine_Task_DropDb extends Doctrine_Task public function execute() { Doctrine::dropDatabases($this->getArgument('connection')); + + $this->dispatcher->notify('Successfully dropped all databases'); } } \ No newline at end of file diff --git a/lib/Doctrine/Task/DumpData.php b/lib/Doctrine/Task/DumpData.php index 8c396f8f6..902d61ef7 100644 --- a/lib/Doctrine/Task/DumpData.php +++ b/lib/Doctrine/Task/DumpData.php @@ -54,5 +54,7 @@ class Doctrine_Task_DumpData extends Doctrine_Task } Doctrine::dumpData($path, $individualFiles); + + $this->dispatcher->notify(sprintf('successfully dumped data to %s', $path)); } } \ No newline at end of file diff --git a/lib/Doctrine/Task/GenerateMigration.php b/lib/Doctrine/Task/GenerateMigration.php index 4684e9935..132bc551b 100644 --- a/lib/Doctrine/Task/GenerateMigration.php +++ b/lib/Doctrine/Task/GenerateMigration.php @@ -40,5 +40,7 @@ class Doctrine_Task_GenerateMigration extends Doctrine_Task public function execute() { Doctrine::generateMigrationClass($this->getArgument('class_name'), $this->getArgument('migrations_path')); + + $this->dispatcher->notify(sprintf('successfully generated migration class: %s to %s', $this->getArgument('class_name'), $this->getArgument('migrations_path'))); } } \ No newline at end of file diff --git a/lib/Doctrine/Task/GenerateMigrationsFromDb.php b/lib/Doctrine/Task/GenerateMigrationsFromDb.php index aa27789a2..c400d5dee 100644 --- a/lib/Doctrine/Task/GenerateMigrationsFromDb.php +++ b/lib/Doctrine/Task/GenerateMigrationsFromDb.php @@ -39,5 +39,7 @@ class Doctrine_Task_GenerateMigrationsFromDb extends Doctrine_Task public function execute() { Doctrine::generateMigrationsFromDb($this->getArgument('migrations_path')); + + $this->dispatcher->notify('successfully generated migration classes from databases'); } } \ No newline at end of file diff --git a/lib/Doctrine/Task/GenerateMigrationsFromModels.php b/lib/Doctrine/Task/GenerateMigrationsFromModels.php index 6824fc28b..b9377452d 100644 --- a/lib/Doctrine/Task/GenerateMigrationsFromModels.php +++ b/lib/Doctrine/Task/GenerateMigrationsFromModels.php @@ -40,5 +40,7 @@ class Doctrine_Task_GenerateMigrationsFromModels extends Doctrine_Task public function execute() { Doctrine::generateMigrationsFromModels($this->getArgument('migrations_path'), $this->getArgument('models_path')); + + $this->dispatcher->notify('successfully generated migrations from models'); } } \ No newline at end of file diff --git a/lib/Doctrine/Task/GenerateModelsFromDb.php b/lib/Doctrine/Task/GenerateModelsFromDb.php index 3d68fbbcf..1e845d2ca 100644 --- a/lib/Doctrine/Task/GenerateModelsFromDb.php +++ b/lib/Doctrine/Task/GenerateModelsFromDb.php @@ -39,5 +39,7 @@ class Doctrine_Task_GenerateModelsFromDb extends Doctrine_Task public function execute() { Doctrine::generateModelsFromDb($this->getArgument('models_path'), (array) $this->getArgument('connection')); + + $this->dispatcher->notify('successfully generated models from databases'); } } \ No newline at end of file diff --git a/lib/Doctrine/Task/GenerateModelsFromYaml.php b/lib/Doctrine/Task/GenerateModelsFromYaml.php index 798e128db..e9a1f782b 100644 --- a/lib/Doctrine/Task/GenerateModelsFromYaml.php +++ b/lib/Doctrine/Task/GenerateModelsFromYaml.php @@ -40,5 +40,7 @@ class Doctrine_Task_GenerateModelsFromYaml extends Doctrine_Task public function execute() { Doctrine::generateModelsFromYaml($this->getArgument('yaml_schema_path'), $this->getArgument('models_path')); + + $this->dispatcher->notify('successfully generated models from yaml'); } } \ No newline at end of file diff --git a/lib/Doctrine/Task/GenerateSql.php b/lib/Doctrine/Task/GenerateSql.php index 1780f7398..48d72e6be 100644 --- a/lib/Doctrine/Task/GenerateSql.php +++ b/lib/Doctrine/Task/GenerateSql.php @@ -50,5 +50,7 @@ class Doctrine_Task_GenerateSql extends Doctrine_Task $sql = Doctrine::generateSqlFromModels($this->getArgument('models_path')); file_put_contents($path, $sql); + + $this->dispatcher->notify('successfully generated sql for models'); } } \ No newline at end of file diff --git a/lib/Doctrine/Task/GenerateYamlFromDb.php b/lib/Doctrine/Task/GenerateYamlFromDb.php index d56e53378..52a2df229 100644 --- a/lib/Doctrine/Task/GenerateYamlFromDb.php +++ b/lib/Doctrine/Task/GenerateYamlFromDb.php @@ -39,5 +39,7 @@ class Doctrine_Task_GenerateYamlFromDb extends Doctrine_Task public function execute() { Doctrine::generateYamlFromDb($this->getArgument('yaml_schema_path')); + + $this->dispatcher->notify('successfully generated yaml schema from databases'); } } \ No newline at end of file diff --git a/lib/Doctrine/Task/GenerateYamlFromModels.php b/lib/Doctrine/Task/GenerateYamlFromModels.php index 0f045985c..1ca1adcfa 100644 --- a/lib/Doctrine/Task/GenerateYamlFromModels.php +++ b/lib/Doctrine/Task/GenerateYamlFromModels.php @@ -40,5 +40,7 @@ class Doctrine_Task_GenerateYamlFromModels extends Doctrine_Task public function execute() { Doctrine::generateYamlFromModels($this->getArgument('yaml_schema_path'), $this->getArgument('models_path')); + + $this->dispatcher->notify('successfully generated yaml schema from models'); } } \ No newline at end of file diff --git a/lib/Doctrine/Task/LoadData.php b/lib/Doctrine/Task/LoadData.php index b1222d3ac..9fd5c836c 100644 --- a/lib/Doctrine/Task/LoadData.php +++ b/lib/Doctrine/Task/LoadData.php @@ -41,5 +41,7 @@ class Doctrine_Task_LoadData extends Doctrine_Task { 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/Task/LoadDummyData.php b/lib/Doctrine/Task/LoadDummyData.php index 15b2e7fac..83603cdba 100644 --- a/lib/Doctrine/Task/LoadDummyData.php +++ b/lib/Doctrine/Task/LoadDummyData.php @@ -41,5 +41,7 @@ class Doctrine_Task_LoadDummyData extends Doctrine_Task { 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 successfully loaded'); } } \ No newline at end of file diff --git a/lib/Doctrine/Task/Migrate.php b/lib/Doctrine/Task/Migrate.php index a5c8df308..f4a03b157 100644 --- a/lib/Doctrine/Task/Migrate.php +++ b/lib/Doctrine/Task/Migrate.php @@ -38,6 +38,8 @@ class Doctrine_Task_Migrate extends Doctrine_Task public function execute() { - Doctrine::migrate($this->getArgument('migrations_path'), $this->getArgument('version')); + $version = Doctrine::migrate($this->getArgument('migrations_path'), $this->getArgument('version')); + + $this->dispatcher->notify('migrated to version # ' . $version); } } \ No newline at end of file diff --git a/sandbox/cli.php b/sandbox/cli.php index e0651351e..76b0a2ea9 100644 --- a/sandbox/cli.php +++ b/sandbox/cli.php @@ -10,4 +10,4 @@ $config = array('data_fixtures_path' => DATA_FIXTURES_PATH, 'yaml_schema_path' => YAML_SCHEMA_PATH); $cli = new Doctrine_Cli($config); -$cli->run($_SERVER['argv']); \ No newline at end of file +$cli->run($_SERVER['argv']); diff --git a/sandbox/data/fixtures/adult.yml b/sandbox/data/fixtures/adult.yml deleted file mode 100644 index 9e5cea976..000000000 --- a/sandbox/data/fixtures/adult.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -Adult: - Adult_1: - name: Parent 1 - Contact: Contact_1 \ No newline at end of file diff --git a/sandbox/data/fixtures/car.yml b/sandbox/data/fixtures/car.yml deleted file mode 100644 index f4982734f..000000000 --- a/sandbox/data/fixtures/car.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -Car: - Car_1: - name: Chevorlet Trailblazer - Car_2: - name: Chevorlet Blazer - Car_3: - name: Buick \ No newline at end of file diff --git a/sandbox/data/fixtures/child.yml b/sandbox/data/fixtures/child.yml deleted file mode 100644 index abcb32122..000000000 --- a/sandbox/data/fixtures/child.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -Child: - Child_1: - name: Child 1 - Adult: Adult_1 \ No newline at end of file diff --git a/sandbox/data/fixtures/data.yml b/sandbox/data/fixtures/data.yml deleted file mode 100644 index a0b665c20..000000000 --- a/sandbox/data/fixtures/data.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -Contact: - Contact_1: - name: jonathan h. wage -User: - User_1: - username: jonwage - Contact: Contact_1 diff --git a/sandbox/data/fixtures/dog.yml b/sandbox/data/fixtures/dog.yml deleted file mode 100644 index 8c2794300..000000000 --- a/sandbox/data/fixtures/dog.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -Dog: - Dog_1: - name: Sam - User: User_1 - Dog_2: - name: Dixie - User: User_2 - Dog_3: - name: Chief - User: User_3 \ No newline at end of file diff --git a/sandbox/data/fixtures/self_reference.yml b/sandbox/data/fixtures/self_reference.yml deleted file mode 100644 index 8a2cefadb..000000000 --- a/sandbox/data/fixtures/self_reference.yml +++ /dev/null @@ -1,20 +0,0 @@ ---- -SelfReference: - SelfReference_1: - User1: User_1 - User2: User_2 - name: Self Reference 1 - SelfReference1: SelfReference_2 - SelfReference2: SelfReference_3 - SelfReference_2: - User1: User_2 - User2: User_1 - name: Self Reference 2 - SelfReference1: SelfReference_1 - SelfReference2: SelfReference_1 - SelfReference_3: - User1: User_2 - User2: User_1 - name: Self Reference 3 - SelfReference1: SelfReference_3 - SelfReference2: SelfReference_3 \ No newline at end of file diff --git a/sandbox/data/fixtures/user_car.yml b/sandbox/data/fixtures/user_car.yml deleted file mode 100644 index af7802614..000000000 --- a/sandbox/data/fixtures/user_car.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -UserCar: - UserCar_1: - User: User_1 - Car: Car_1 - UserCar_2: - User: User_2 - Car: Car_2 - UserCar_3: - User: User_3 - Car: Car_3 \ No newline at end of file diff --git a/sandbox/migrations/001_add_adult.class.php b/sandbox/migrations/001_add_adult.class.php deleted file mode 100644 index 3f52a4316..000000000 --- a/sandbox/migrations/001_add_adult.class.php +++ /dev/null @@ -1,42 +0,0 @@ -createTable('adult', array ( - 'id' => - array ( - 'primary' => true, - 'autoincrement' => true, - 'type' => 'integer', - 'length' => 11, - ), - 'name' => - array ( - 'type' => 'string', - 'length' => 255, - ), - 'contact_id' => - array ( - 'type' => 'integer', - 'length' => 11, - ), -), array ( - 'indexes' => - array ( - ), - 'primary' => - array ( - 0 => 'id', - ), -)); - } - - public function down() - { - $this->dropTable('adult'); - } -} \ No newline at end of file diff --git a/sandbox/migrations/002_add_car.class.php b/sandbox/migrations/002_add_car.class.php deleted file mode 100644 index 74a7de623..000000000 --- a/sandbox/migrations/002_add_car.class.php +++ /dev/null @@ -1,37 +0,0 @@ -createTable('car', array ( - 'id' => - array ( - 'primary' => true, - 'autoincrement' => true, - 'type' => 'integer', - 'length' => 11, - ), - 'name' => - array ( - 'type' => 'string', - 'length' => 255, - ), -), array ( - 'indexes' => - array ( - ), - 'primary' => - array ( - 0 => 'id', - ), -)); - } - - public function down() - { - $this->dropTable('car'); - } -} \ No newline at end of file diff --git a/sandbox/migrations/003_add_child.class.php b/sandbox/migrations/003_add_child.class.php deleted file mode 100644 index 07c65aa57..000000000 --- a/sandbox/migrations/003_add_child.class.php +++ /dev/null @@ -1,42 +0,0 @@ -createTable('child', array ( - 'id' => - array ( - 'primary' => true, - 'autoincrement' => true, - 'type' => 'integer', - 'length' => 11, - ), - 'name' => - array ( - 'type' => 'string', - 'length' => 255, - ), - 'adult_id' => - array ( - 'type' => 'integer', - 'length' => 11, - ), -), array ( - 'indexes' => - array ( - ), - 'primary' => - array ( - 0 => 'id', - ), -)); - } - - public function down() - { - $this->dropTable('child'); - } -} \ No newline at end of file diff --git a/sandbox/migrations/004_add_contact.class.php b/sandbox/migrations/004_add_contact.class.php deleted file mode 100644 index b9757934b..000000000 --- a/sandbox/migrations/004_add_contact.class.php +++ /dev/null @@ -1,37 +0,0 @@ -createTable('contact', array ( - 'id' => - array ( - 'primary' => true, - 'autoincrement' => true, - 'type' => 'integer', - 'length' => 11, - ), - 'name' => - array ( - 'type' => 'string', - 'length' => 255, - ), -), array ( - 'indexes' => - array ( - ), - 'primary' => - array ( - 0 => 'id', - ), -)); - } - - public function down() - { - $this->dropTable('contact'); - } -} \ No newline at end of file diff --git a/sandbox/migrations/005_add_dog.class.php b/sandbox/migrations/005_add_dog.class.php deleted file mode 100644 index 760fa202b..000000000 --- a/sandbox/migrations/005_add_dog.class.php +++ /dev/null @@ -1,42 +0,0 @@ -createTable('dog', array ( - 'id' => - array ( - 'primary' => true, - 'autoincrement' => true, - 'type' => 'integer', - 'length' => 11, - ), - 'name' => - array ( - 'type' => 'string', - 'length' => 255, - ), - 'user_id' => - array ( - 'type' => 'integer', - 'length' => 11, - ), -), array ( - 'indexes' => - array ( - ), - 'primary' => - array ( - 0 => 'id', - ), -)); - } - - public function down() - { - $this->dropTable('dog'); - } -} \ No newline at end of file diff --git a/sandbox/migrations/006_add_entity.class.php b/sandbox/migrations/006_add_entity.class.php deleted file mode 100644 index 5226c3a3d..000000000 --- a/sandbox/migrations/006_add_entity.class.php +++ /dev/null @@ -1,32 +0,0 @@ -createTable('entity', array ( - 'id' => - array ( - 'primary' => true, - 'autoincrement' => true, - 'type' => 'integer', - 'length' => 11, - ), -), array ( - 'indexes' => - array ( - ), - 'primary' => - array ( - 0 => 'id', - ), -)); - } - - public function down() - { - $this->dropTable('entity'); - } -} \ No newline at end of file diff --git a/sandbox/migrations/007_add_groups.class.php b/sandbox/migrations/007_add_groups.class.php deleted file mode 100644 index 4e202c175..000000000 --- a/sandbox/migrations/007_add_groups.class.php +++ /dev/null @@ -1,38 +0,0 @@ -createTable('groups', array ( - 'id' => - array ( - 'notnull' => true, - 'primary' => true, - 'autoincrement' => true, - 'type' => 'integer', - 'length' => 11, - ), - 'name' => - array ( - 'type' => 'string', - 'length' => 255, - ), -), array ( - 'indexes' => - array ( - ), - 'primary' => - array ( - 0 => 'id', - ), -)); - } - - public function down() - { - $this->dropTable('groups'); - } -} \ No newline at end of file diff --git a/sandbox/models/Adult.class.php b/sandbox/models/Adult.class.php deleted file mode 100644 index c3bdc3146..000000000 --- a/sandbox/models/Adult.class.php +++ /dev/null @@ -1,12 +0,0 @@ -setTableName('adult'); - $this->hasColumn('id', 'integer', 11, array('primary' => true, - 'autoincrement' => true)); - - $this->hasColumn('name', 'string', 255); - $this->hasColumn('contact_id', 'integer', 11); - - - - - - } - - public function setUp() - { - $this->hasOne('Contact', array('local' => 'contact_id', - 'foreign' => 'id')); - - $this->hasMany('Child as Children', array('local' => 'id', - 'foreign' => 'adult_id')); - - } - -} \ No newline at end of file diff --git a/sandbox/models/generated/BaseCar.class.php b/sandbox/models/generated/BaseCar.class.php deleted file mode 100644 index 20550425f..000000000 --- a/sandbox/models/generated/BaseCar.class.php +++ /dev/null @@ -1,30 +0,0 @@ -setTableName('car'); - $this->hasColumn('id', 'integer', 11, array('primary' => true, - 'autoincrement' => true)); - $this->hasColumn('name', 'string', 255); - - - - - - } - - public function setUp() - { - $this->hasMany('User as Users', array('refClass' => 'UserCar', - 'local' => 'car_id', - 'foreign' => 'user_id')); - - } - -} \ No newline at end of file diff --git a/sandbox/models/generated/BaseChild.class.php b/sandbox/models/generated/BaseChild.class.php deleted file mode 100644 index 77ca67798..000000000 --- a/sandbox/models/generated/BaseChild.class.php +++ /dev/null @@ -1,31 +0,0 @@ -setTableName('child'); - $this->hasColumn('id', 'integer', 11, array('primary' => true, - 'autoincrement' => true)); - - $this->hasColumn('name', 'string', 255); - $this->hasColumn('adult_id', 'integer', 11); - - - - - - } - - public function setUp() - { - $this->hasOne('Adult', array('local' => 'adult_id', - 'foreign' => 'id')); - - } - -} \ No newline at end of file diff --git a/sandbox/models/generated/BaseContact.class.php b/sandbox/models/generated/BaseContact.class.php deleted file mode 100644 index 59000f584..000000000 --- a/sandbox/models/generated/BaseContact.class.php +++ /dev/null @@ -1,32 +0,0 @@ -setTableName('contact'); - $this->hasColumn('id', 'integer', 11, array('primary' => true, - 'autoincrement' => true)); - $this->hasColumn('name', 'string', 255); - - - - - - } - - public function setUp() - { - $this->hasOne('Adult', array('local' => 'id', - 'foreign' => 'contact_id')); - - $this->hasOne('User', array('local' => 'id', - 'foreign' => 'contact_id')); - - } - -} \ No newline at end of file diff --git a/sandbox/models/generated/BaseDog.class.php b/sandbox/models/generated/BaseDog.class.php deleted file mode 100644 index 2fbd9408f..000000000 --- a/sandbox/models/generated/BaseDog.class.php +++ /dev/null @@ -1,31 +0,0 @@ -setTableName('dog'); - $this->hasColumn('id', 'integer', 11, array('primary' => true, - 'autoincrement' => true)); - - $this->hasColumn('name', 'string', 255); - $this->hasColumn('user_id', 'integer', 11); - - - - - - } - - public function setUp() - { - $this->hasOne('User', array('local' => 'user_id', - 'foreign' => 'id')); - - } - -} \ No newline at end of file diff --git a/sandbox/models/generated/BaseEntity.class.php b/sandbox/models/generated/BaseEntity.class.php deleted file mode 100644 index 16e4f421b..000000000 --- a/sandbox/models/generated/BaseEntity.class.php +++ /dev/null @@ -1,22 +0,0 @@ -setTableName('entity'); - $this->hasColumn('id', 'integer', 11, array('primary' => true, - 'autoincrement' => true)); - - - - - - } - - -} \ No newline at end of file diff --git a/sandbox/models/generated/BaseGroup.class.php b/sandbox/models/generated/BaseGroup.class.php deleted file mode 100644 index ab882814c..000000000 --- a/sandbox/models/generated/BaseGroup.class.php +++ /dev/null @@ -1,31 +0,0 @@ -setTableName('groups'); - $this->hasColumn('id', 'integer', 11, array('notnull' => true, - 'primary' => true, - 'autoincrement' => true)); - $this->hasColumn('name', 'string', 255); - - - - - - } - - public function setUp() - { - $this->hasMany('User as Users', array('refClass' => 'UserGroup', - 'local' => 'group_id', - 'foreign' => 'user_id')); - - } - -} \ No newline at end of file diff --git a/sandbox/models/generated/BaseSelfReference.class.php b/sandbox/models/generated/BaseSelfReference.class.php deleted file mode 100644 index 414ce81fb..000000000 --- a/sandbox/models/generated/BaseSelfReference.class.php +++ /dev/null @@ -1,52 +0,0 @@ -setTableName('self_reference'); - $this->hasColumn('id', 'integer', 11, array('primary' => true, - 'autoincrement' => true)); - - $this->hasColumn('name', 'string', 255); - - $this->hasColumn('user_id1', 'integer', 11); - - $this->hasColumn('user_id2', 'integer', 11); - - $this->hasColumn('parent_self_reference_id', 'integer', 11); - $this->hasColumn('parent_self_reference_id2', 'integer', 11); - - - - - - } - - public function setUp() - { - $this->hasOne('User as User1', array('local' => 'user_id1', - 'foreign' => 'id')); - - $this->hasOne('User as User2', array('local' => 'user_id2', - 'foreign' => 'id')); - - $this->hasOne('SelfReference as SelfReference1', array('local' => 'parent_self_reference_id', - 'foreign' => 'id')); - - $this->hasOne('SelfReference as SelfReference2', array('local' => 'parent_self_reference_id2', - 'foreign' => 'id')); - - $this->hasMany('SelfReference as SelfReferences1', array('local' => 'id', - 'foreign' => 'parent_self_reference_id')); - - $this->hasMany('SelfReference as SelfReferences2', array('local' => 'id', - 'foreign' => 'parent_self_reference_id2')); - - } - -} \ No newline at end of file diff --git a/sandbox/models/generated/BaseUser.class.php b/sandbox/models/generated/BaseUser.class.php deleted file mode 100644 index a962dc96e..000000000 --- a/sandbox/models/generated/BaseUser.class.php +++ /dev/null @@ -1,51 +0,0 @@ -setTableName('user'); - $this->hasColumn('id', 'integer', 11, array('primary' => true, - 'autoincrement' => true)); - - $this->hasColumn('username', 'string', 255); - - $this->hasColumn('hair_color', 'string', 255); - $this->hasColumn('contact_id', 'integer', 11); - - $this->index('name_x', array('fields' => array('username' => array( 'sorting' => 'ASC', 'length' => '11', 'primary' => true, ), ), 'type' => 'unique')); - - - - - } - - public function setUp() - { - $this->hasOne('Contact', array('local' => 'contact_id', - 'foreign' => 'id')); - - $this->hasMany('Car as Cars', array('refClass' => 'UserCar', - 'local' => 'user_id', - 'foreign' => 'car_id')); - - $this->hasMany('Group as Groups', array('refClass' => 'UserGroup', - 'local' => 'user_id', - 'foreign' => 'group_id')); - - $this->hasOne('Dog', array('local' => 'id', - 'foreign' => 'user_id')); - - $this->hasMany('SelfReference as SelfReference1', array('local' => 'id', - 'foreign' => 'user_id1')); - - $this->hasMany('SelfReference as SelfReference2', array('local' => 'id', - 'foreign' => 'user_id2')); - - } - -} \ No newline at end of file diff --git a/sandbox/models/generated/BaseUserCar.class.php b/sandbox/models/generated/BaseUserCar.class.php deleted file mode 100644 index ac7e0c001..000000000 --- a/sandbox/models/generated/BaseUserCar.class.php +++ /dev/null @@ -1,31 +0,0 @@ -setTableName('user_car'); - $this->hasColumn('user_id', 'integer', 11, array('primary' => true)); - $this->hasColumn('car_id', 'integer', 11, array('primary' => true)); - - - - - - } - - public function setUp() - { - $this->hasOne('User', array('local' => 'user_id', - 'foreign' => 'id')); - - $this->hasOne('Car', array('local' => 'car_id', - 'foreign' => 'id')); - - } - -} \ No newline at end of file diff --git a/sandbox/models/generated/BaseUserGroup.class.php b/sandbox/models/generated/BaseUserGroup.class.php deleted file mode 100644 index d7183f467..000000000 --- a/sandbox/models/generated/BaseUserGroup.class.php +++ /dev/null @@ -1,31 +0,0 @@ -setTableName('user_group'); - $this->hasColumn('user_id', 'integer', 11, array('primary' => true)); - $this->hasColumn('group_id', 'integer', 11, array('primary' => true)); - - - - - - } - - public function setUp() - { - $this->hasOne('User', array('local' => 'user_id', - 'foreign' => 'id')); - - $this->hasOne('Group', array('local' => 'group_id', - 'foreign' => 'id')); - - } - -} \ No newline at end of file diff --git a/sandbox/schema/adult.yml b/sandbox/schema/adult.yml deleted file mode 100644 index 37c71fed0..000000000 --- a/sandbox/schema/adult.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -Adult: - fields: - id: - type: integer - size: 11 - primary: true - autoincrement: true - name: - type: string - size: 255 - contact_id: - type: integer - size: 11 - relations: - Contact: - foreignType: one \ No newline at end of file diff --git a/sandbox/schema/car.yml b/sandbox/schema/car.yml deleted file mode 100644 index 4553ef4b3..000000000 --- a/sandbox/schema/car.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- -Car: - columns: - id: - type: integer - length: 11 - primary: true - autoincrement: true - name: - type: string - length: 255 - relations: - Users: - class: User - refClass: UserCar \ No newline at end of file diff --git a/sandbox/schema/child.yml b/sandbox/schema/child.yml deleted file mode 100644 index 8bf108d98..000000000 --- a/sandbox/schema/child.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -Child: - fields: - id: - type: integer - size: 11 - primary: true - autoincrement: true - name: - type: string - size: 255 - adult_id: - type: integer - size: 11 - relations: - Adult: - foreignAlias: Children \ No newline at end of file diff --git a/sandbox/schema/contact.yml b/sandbox/schema/contact.yml deleted file mode 100644 index 3fadb71ae..000000000 --- a/sandbox/schema/contact.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -Contact: - columns: - id: - type: integer - length: 11 - primary: true - autoincrement: true - name: - type: string - length: 255 \ No newline at end of file diff --git a/sandbox/schema/dog.yml b/sandbox/schema/dog.yml deleted file mode 100644 index 34551e187..000000000 --- a/sandbox/schema/dog.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -Dog: - columns: - id: - type: integer - length: 11 - primary: true - autoincrement: true - name: - type: string - length: 255 - user_id: - type: integer - length: 11 - relations: - User: - foreignType: one \ No newline at end of file diff --git a/sandbox/schema/entity.yml b/sandbox/schema/entity.yml deleted file mode 100644 index 47282a80d..000000000 --- a/sandbox/schema/entity.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -Entity: - columns: - id: - type: integer - size: 11 - primary: true - autoincrement: true \ No newline at end of file diff --git a/sandbox/schema/group.yml b/sandbox/schema/group.yml deleted file mode 100644 index ad891519e..000000000 --- a/sandbox/schema/group.yml +++ /dev/null @@ -1,18 +0,0 @@ ---- -Group: - tableName: groups - columns: - id: - notnull: true - primary: true - autoincrement: true - type: integer - length: 11 - name: id - name: - type: string - length: 255 - relations: - Users: - class: User - refClass: UserGroup diff --git a/sandbox/schema/self_reference.yml b/sandbox/schema/self_reference.yml deleted file mode 100644 index 3a78b68b1..000000000 --- a/sandbox/schema/self_reference.yml +++ /dev/null @@ -1,40 +0,0 @@ ---- -SelfReference: - fields: - id: - type: integer - length: 11 - primary: true - autoincrement: true - name: - type: string - length: 255 - user_id1: - type: integer - length: 11 - user_id2: - type: integer - length: 11 - parent_self_reference_id: - type: integer - length: 11 - parent_self_reference_id2: - type: integer - length: 11 - relations: - User1: - class: User - local: user_id1 - foreignAlias: SelfReference1 - User2: - class: User - local: user_id2 - foreignAlias: SelfReference2 - SelfReference1: - class: SelfReference - local: parent_self_reference_id - foreignAlias: SelfReferences1 - SelfReference2: - class: SelfReference - local: parent_self_reference_id2 - foreignAlias: SelfReferences2 diff --git a/sandbox/schema/user.yml b/sandbox/schema/user.yml deleted file mode 100644 index 43dde72c9..000000000 --- a/sandbox/schema/user.yml +++ /dev/null @@ -1,38 +0,0 @@ ---- -User: - inheritance: - extends: Entity - fields: - id: - type: integer - size: 11 - primary: true - autoincrement: true - username: - type: string - length: 255 - hair_color: - type: string - length: 255 - contact_id: - type: integer - length: 11 - relations: - Contact: - local: contact_id - foreign: id - foreignType: one - Cars: - class: Car - refClass: UserCar - Groups: - class: Group - refClass: UserGroup - indexes: - name_x: - columns: - username: - sorting: ASC - length: 11 - primary: true - type: unique \ No newline at end of file diff --git a/sandbox/schema/user_car.yml b/sandbox/schema/user_car.yml deleted file mode 100644 index 204d047e5..000000000 --- a/sandbox/schema/user_car.yml +++ /dev/null @@ -1,14 +0,0 @@ ---- -UserCar: - columns: - user_id: - type: integer - length: 11 - primary: true - car_id: - type: integer - length: 11 - primary: true - relations: - User: - - Car: - \ No newline at end of file diff --git a/sandbox/schema/user_group.yml b/sandbox/schema/user_group.yml deleted file mode 100644 index 6642aa826..000000000 --- a/sandbox/schema/user_group.yml +++ /dev/null @@ -1,14 +0,0 @@ ---- -UserGroup: - columns: - user_id: - type: integer - length: 11 - primary: true - group_id: - type: integer - length: 11 - primary: true - relations: - User: - - Group: -