diff --git a/config/ProjectConfiguration.class.php b/config/ProjectConfiguration.class.php index 56bb991..ec3b8b1 100644 --- a/config/ProjectConfiguration.class.php +++ b/config/ProjectConfiguration.class.php @@ -1,13 +1,18 @@ $webDir, + 'sf_upload_dir' => $webDir.DIRECTORY_SEPARATOR.'uploads', + 'sf_language_dir' => $webDir.DIRECTORY_SEPARATOR.'language_files', + )); $this->enablePlugins('sfDoctrinePlugin'); } } diff --git a/config/databases-sample.yml b/config/databases-sample.yml index 538f281..a56aa8e 100644 --- a/config/databases-sample.yml +++ b/config/databases-sample.yml @@ -5,7 +5,7 @@ all: doctrine: class: sfDoctrineDatabase param: - dsn: mysql:host=;dbname= + dsn: 'mysql:host=;dbname=;charset=utf8mb4' username: password: test: diff --git a/data/localizit.sql b/data/localizit.sql index 60a1e9e..8ef1c23 100755 --- a/data/localizit.sql +++ b/data/localizit.sql @@ -29,7 +29,7 @@ CREATE TABLE IF NOT EXISTS `ohrm_group` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ; +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=8 ; -- -- Dumping data for table `ohrm_group` @@ -57,7 +57,7 @@ CREATE TABLE IF NOT EXISTS `ohrm_language` ( `name` varchar(255) DEFAULT NULL, `code` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ; -- -- Dumping data for table `ohrm_language` @@ -107,7 +107,7 @@ CREATE TABLE IF NOT EXISTS `ohrm_source` ( `note` text, PRIMARY KEY (`id`), KEY `group_id_idx` (`group_id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ; -- -- Dumping data for table `ohrm_source` @@ -129,7 +129,7 @@ CREATE TABLE IF NOT EXISTS `ohrm_target` ( PRIMARY KEY (`id`), KEY `source_id_idx` (`source_id`), KEY `language_id_idx` (`language_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci AUTO_INCREMENT=1 ; -- -- Dumping data for table `ohrm_target` @@ -152,7 +152,7 @@ CREATE TABLE IF NOT EXISTS `ohrm_user` ( `password` varchar(250) DEFAULT NULL, PRIMARY KEY (`id`), KEY `user_type_id_idx` (`user_type_id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ; +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4 ; -- -- Dumping data for table `ohrm_user` @@ -175,7 +175,7 @@ CREATE TABLE IF NOT EXISTS `ohrm_user_language` ( PRIMARY KEY (`id`), KEY `language_id_idx` (`language_id`), KEY `user_id_idx` (`user_id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ; -- -- Dumping data for table `ohrm_user_language` @@ -192,7 +192,7 @@ CREATE TABLE IF NOT EXISTS `ohrm_user_type` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_type` varchar(25) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ; -- -- Dumping data for table `ohrm_user_type` diff --git a/lib/composer.json b/lib/composer.json new file mode 100644 index 0000000..7d9498a --- /dev/null +++ b/lib/composer.json @@ -0,0 +1,29 @@ +{ + + "name": "orangehrm/orange-localizit", + "keywords": ["orangehrm"], + "type": "project", + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/orangehrm/symfony1" + }, + { + "type": "vcs", + "url": "https://github.com/orangehrm/doctrine1" + } + ], + "config": { + "vendor-dir": "vendor" + }, + "require": { + "lexpress/symfony1": "dev-ohrm", + "lexpress/doctrine1": "dev-master" + }, + "extra": { + "installer-types": ["library"], + "installer-paths": { + "vendor/symfony/": ["lexpress/symfony1"] + } + } +} diff --git a/lib/composer.lock b/lib/composer.lock new file mode 100644 index 0000000..6e34863 --- /dev/null +++ b/lib/composer.lock @@ -0,0 +1,351 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "b004b95aca931e37af6c4cf28e9641e6", + "packages": [ + { + "name": "composer/installers", + "version": "v1.9.0", + "source": { + "type": "git", + "url": "https://github.com/composer/installers.git", + "reference": "b93bcf0fa1fccb0b7d176b0967d969691cd74cca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/installers/zipball/b93bcf0fa1fccb0b7d176b0967d969691cd74cca", + "reference": "b93bcf0fa1fccb0b7d176b0967d969691cd74cca", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0" + }, + "replace": { + "roundcube/plugin-installer": "*", + "shama/baton": "*" + }, + "require-dev": { + "composer/composer": "1.6.* || 2.0.*@dev", + "composer/semver": "1.0.* || 2.0.*@dev", + "phpunit/phpunit": "^4.8.36", + "sebastian/comparator": "^1.2.4", + "symfony/process": "^2.3" + }, + "type": "composer-plugin", + "extra": { + "class": "Composer\\Installers\\Plugin", + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Installers\\": "src/Composer/Installers" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kyle Robinson Young", + "email": "kyle@dontkry.com", + "homepage": "https://github.com/shama" + } + ], + "description": "A multi-framework Composer library installer", + "homepage": "https://composer.github.io/installers/", + "keywords": [ + "Craft", + "Dolibarr", + "Eliasis", + "Hurad", + "ImageCMS", + "Kanboard", + "Lan Management System", + "MODX Evo", + "MantisBT", + "Mautic", + "Maya", + "OXID", + "Plentymarkets", + "Porto", + "RadPHP", + "SMF", + "Thelia", + "Whmcs", + "WolfCMS", + "agl", + "aimeos", + "annotatecms", + "attogram", + "bitrix", + "cakephp", + "chef", + "cockpit", + "codeigniter", + "concrete5", + "croogo", + "dokuwiki", + "drupal", + "eZ Platform", + "elgg", + "expressionengine", + "fuelphp", + "grav", + "installer", + "itop", + "joomla", + "known", + "kohana", + "laravel", + "lavalite", + "lithium", + "magento", + "majima", + "mako", + "mediawiki", + "modulework", + "modx", + "moodle", + "osclass", + "phpbb", + "piwik", + "ppi", + "puppet", + "pxcms", + "reindex", + "roundcube", + "shopware", + "silverstripe", + "sydes", + "sylius", + "symfony", + "typo3", + "wordpress", + "yawik", + "zend", + "zikula" + ], + "time": "2020-04-07T06:57:05+00:00" + }, + { + "name": "lexpress/doctrine1", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfSymfony1/doctrine1.git", + "reference": "3ef85915e56b29475e9bff85bfc1f80d41028a7f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfSymfony1/doctrine1/zipball/3ef85915e56b29475e9bff85bfc1f80d41028a7f", + "reference": "3ef85915e56b29475e9bff85bfc1f80d41028a7f", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-pdo": "*", + "php": ">=5.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine_": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Konsta Vesterinen", + "email": "kvesteri@cc.hut.fi" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Doctrine1 Contributors", + "homepage": "https://github.com/FriendsOfSymfony1/doctrine1/graphs/contributors" + } + ], + "description": "PHP Database ORM for Symfony1. Do NOT use for new projects: please move to a newest Symfony release and Doctrine2", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "doctrine1", + "orm", + "symfony1" + ], + "time": "2020-07-10T03:00:50+00:00" + }, + { + "name": "lexpress/symfony1", + "version": "dev-ohrm", + "source": { + "type": "git", + "url": "https://github.com/orangehrm/symfony1.git", + "reference": "38e9b72dac7e9b92453796cc00194709e21d95b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orangehrm/symfony1/zipball/38e9b72dac7e9b92453796cc00194709e21d95b8", + "reference": "38e9b72dac7e9b92453796cc00194709e21d95b8", + "shasum": "" + }, + "require": { + "oomphinc/composer-installers-extender": "^1.1", + "swiftmailer/swiftmailer": "~5.2" + }, + "require-dev": { + "psr/log": "*" + }, + "suggest": { + "lexpress/doctrine1": "Doctrine plugin", + "propel/sf-propel-o-r-m-plugin": "Propel plugin", + "psr/log": "Psr logger" + }, + "bin": [ + "data/bin/symfony" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "files": [ + "autoload.php" + ] + }, + "license": [ + "MIT" + ], + "description": "Fork of symfony 1.4 with dic, form enhancements, latest swiftmailer and better performance", + "support": { + "source": "https://github.com/orangehrm/symfony1/tree/ohrm" + }, + "time": "2020-04-21T02:58:39+00:00" + }, + { + "name": "oomphinc/composer-installers-extender", + "version": "v1.1.2", + "source": { + "type": "git", + "url": "https://github.com/oomphinc/composer-installers-extender.git", + "reference": "ca1c4b16b0905c81d1e77e608f36a2eff1a56f56" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/oomphinc/composer-installers-extender/zipball/ca1c4b16b0905c81d1e77e608f36a2eff1a56f56", + "reference": "ca1c4b16b0905c81d1e77e608f36a2eff1a56f56", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0", + "composer/installers": "^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "OomphInc\\ComposerInstallersExtender\\Plugin" + }, + "autoload": { + "psr-4": { + "OomphInc\\ComposerInstallersExtender\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Stephen Beemsterboer", + "email": "stephen@oomphinc.com", + "homepage": "https://github.com/balbuf" + } + ], + "description": "Extend the composer/installers plugin to accept any arbitrary package type.", + "homepage": "http://www.oomphinc.com/", + "time": "2017-03-31T16:57:39+00:00" + }, + { + "name": "swiftmailer/swiftmailer", + "version": "v5.4.12", + "source": { + "type": "git", + "url": "https://github.com/swiftmailer/swiftmailer.git", + "reference": "181b89f18a90f8925ef805f950d47a7190e9b950" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/181b89f18a90f8925ef805f950d47a7190e9b950", + "reference": "181b89f18a90f8925ef805f950d47a7190e9b950", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "mockery/mockery": "~0.9.1", + "symfony/phpunit-bridge": "~3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.4-dev" + } + }, + "autoload": { + "files": [ + "lib/swift_required.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Corbyn" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Swiftmailer, free feature-rich PHP mailer", + "homepage": "https://swiftmailer.symfony.com", + "keywords": [ + "email", + "mail", + "mailer" + ], + "time": "2018-07-31T09:26:32+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "lexpress/symfony1": 20, + "lexpress/doctrine1": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/lib/model/Doctrine.php b/lib/model/Doctrine.php new file mode 100644 index 0000000..83e9439 --- /dev/null +++ b/lib/model/Doctrine.php @@ -0,0 +1,11 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + private $classMapAuthoritative = false; + private $missingClasses = array(); + private $apcuPrefix; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/lib/vendor/composer/LICENSE b/lib/vendor/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/lib/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/lib/vendor/composer/autoload_classmap.php b/lib/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..7a91153 --- /dev/null +++ b/lib/vendor/composer/autoload_classmap.php @@ -0,0 +1,9 @@ + $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php', + '5a4f8922d6b478e5112a2fcfcd7f5db2' => $vendorDir . '/symfony/autoload.php', +); diff --git a/lib/vendor/composer/autoload_namespaces.php b/lib/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..0b651e0 --- /dev/null +++ b/lib/vendor/composer/autoload_namespaces.php @@ -0,0 +1,10 @@ + array($vendorDir . '/lexpress/doctrine1/lib'), +); diff --git a/lib/vendor/composer/autoload_psr4.php b/lib/vendor/composer/autoload_psr4.php new file mode 100644 index 0000000..6cf0c47 --- /dev/null +++ b/lib/vendor/composer/autoload_psr4.php @@ -0,0 +1,11 @@ + array($vendorDir . '/oomphinc/composer-installers-extender/src'), + 'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src/Composer/Installers'), +); diff --git a/lib/vendor/composer/autoload_real.php b/lib/vendor/composer/autoload_real.php new file mode 100644 index 0000000..b62033e --- /dev/null +++ b/lib/vendor/composer/autoload_real.php @@ -0,0 +1,70 @@ += 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require_once __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInit2a1159440bc6539ffd8a15aab9623e0c::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + if ($useStaticLoader) { + $includeFiles = Composer\Autoload\ComposerStaticInit2a1159440bc6539ffd8a15aab9623e0c::$files; + } else { + $includeFiles = require __DIR__ . '/autoload_files.php'; + } + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequire2a1159440bc6539ffd8a15aab9623e0c($fileIdentifier, $file); + } + + return $loader; + } +} + +function composerRequire2a1159440bc6539ffd8a15aab9623e0c($fileIdentifier, $file) +{ + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + require $file; + + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + } +} diff --git a/lib/vendor/composer/autoload_static.php b/lib/vendor/composer/autoload_static.php new file mode 100644 index 0000000..4088b34 --- /dev/null +++ b/lib/vendor/composer/autoload_static.php @@ -0,0 +1,55 @@ + __DIR__ . '/..' . '/swiftmailer/swiftmailer/lib/swift_required.php', + '5a4f8922d6b478e5112a2fcfcd7f5db2' => __DIR__ . '/..' . '/symfony/autoload.php', + ); + + public static $prefixLengthsPsr4 = array ( + 'O' => + array ( + 'OomphInc\\ComposerInstallersExtender\\' => 36, + ), + 'C' => + array ( + 'Composer\\Installers\\' => 20, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'OomphInc\\ComposerInstallersExtender\\' => + array ( + 0 => __DIR__ . '/..' . '/oomphinc/composer-installers-extender/src', + ), + 'Composer\\Installers\\' => + array ( + 0 => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers', + ), + ); + + public static $prefixesPsr0 = array ( + 'D' => + array ( + 'Doctrine_' => + array ( + 0 => __DIR__ . '/..' . '/lexpress/doctrine1/lib', + ), + ), + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInit2a1159440bc6539ffd8a15aab9623e0c::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit2a1159440bc6539ffd8a15aab9623e0c::$prefixDirsPsr4; + $loader->prefixesPsr0 = ComposerStaticInit2a1159440bc6539ffd8a15aab9623e0c::$prefixesPsr0; + + }, null, ClassLoader::class); + } +} diff --git a/lib/vendor/composer/installed.json b/lib/vendor/composer/installed.json new file mode 100644 index 0000000..b7ad33c --- /dev/null +++ b/lib/vendor/composer/installed.json @@ -0,0 +1,342 @@ +[ + { + "name": "composer/installers", + "version": "v1.9.0", + "version_normalized": "1.9.0.0", + "source": { + "type": "git", + "url": "https://github.com/composer/installers.git", + "reference": "b93bcf0fa1fccb0b7d176b0967d969691cd74cca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/installers/zipball/b93bcf0fa1fccb0b7d176b0967d969691cd74cca", + "reference": "b93bcf0fa1fccb0b7d176b0967d969691cd74cca", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0" + }, + "replace": { + "roundcube/plugin-installer": "*", + "shama/baton": "*" + }, + "require-dev": { + "composer/composer": "1.6.* || 2.0.*@dev", + "composer/semver": "1.0.* || 2.0.*@dev", + "phpunit/phpunit": "^4.8.36", + "sebastian/comparator": "^1.2.4", + "symfony/process": "^2.3" + }, + "time": "2020-04-07T06:57:05+00:00", + "type": "composer-plugin", + "extra": { + "class": "Composer\\Installers\\Plugin", + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Composer\\Installers\\": "src/Composer/Installers" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kyle Robinson Young", + "email": "kyle@dontkry.com", + "homepage": "https://github.com/shama" + } + ], + "description": "A multi-framework Composer library installer", + "homepage": "https://composer.github.io/installers/", + "keywords": [ + "Craft", + "Dolibarr", + "Eliasis", + "Hurad", + "ImageCMS", + "Kanboard", + "Lan Management System", + "MODX Evo", + "MantisBT", + "Mautic", + "Maya", + "OXID", + "Plentymarkets", + "Porto", + "RadPHP", + "SMF", + "Thelia", + "Whmcs", + "WolfCMS", + "agl", + "aimeos", + "annotatecms", + "attogram", + "bitrix", + "cakephp", + "chef", + "cockpit", + "codeigniter", + "concrete5", + "croogo", + "dokuwiki", + "drupal", + "eZ Platform", + "elgg", + "expressionengine", + "fuelphp", + "grav", + "installer", + "itop", + "joomla", + "known", + "kohana", + "laravel", + "lavalite", + "lithium", + "magento", + "majima", + "mako", + "mediawiki", + "modulework", + "modx", + "moodle", + "osclass", + "phpbb", + "piwik", + "ppi", + "puppet", + "pxcms", + "reindex", + "roundcube", + "shopware", + "silverstripe", + "sydes", + "sylius", + "symfony", + "typo3", + "wordpress", + "yawik", + "zend", + "zikula" + ] + }, + { + "name": "lexpress/doctrine1", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfSymfony1/doctrine1.git", + "reference": "3ef85915e56b29475e9bff85bfc1f80d41028a7f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfSymfony1/doctrine1/zipball/3ef85915e56b29475e9bff85bfc1f80d41028a7f", + "reference": "3ef85915e56b29475e9bff85bfc1f80d41028a7f", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-pdo": "*", + "php": ">=5.3" + }, + "time": "2020-07-10T03:00:50+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "installation-source": "source", + "autoload": { + "psr-0": { + "Doctrine_": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Konsta Vesterinen", + "email": "kvesteri@cc.hut.fi" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Doctrine1 Contributors", + "homepage": "https://github.com/FriendsOfSymfony1/doctrine1/graphs/contributors" + } + ], + "description": "PHP Database ORM for Symfony1. Do NOT use for new projects: please move to a newest Symfony release and Doctrine2", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "doctrine1", + "orm", + "symfony1" + ] + }, + { + "name": "lexpress/symfony1", + "version": "dev-ohrm", + "version_normalized": "dev-ohrm", + "source": { + "type": "git", + "url": "https://github.com/orangehrm/symfony1.git", + "reference": "38e9b72dac7e9b92453796cc00194709e21d95b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orangehrm/symfony1/zipball/38e9b72dac7e9b92453796cc00194709e21d95b8", + "reference": "38e9b72dac7e9b92453796cc00194709e21d95b8", + "shasum": "" + }, + "require": { + "oomphinc/composer-installers-extender": "^1.1", + "swiftmailer/swiftmailer": "~5.2" + }, + "require-dev": { + "psr/log": "*" + }, + "suggest": { + "lexpress/doctrine1": "Doctrine plugin", + "propel/sf-propel-o-r-m-plugin": "Propel plugin", + "psr/log": "Psr logger" + }, + "time": "2020-04-21T02:58:39+00:00", + "bin": [ + "data/bin/symfony" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "installation-source": "source", + "autoload": { + "files": [ + "autoload.php" + ] + }, + "license": [ + "MIT" + ], + "description": "Fork of symfony 1.4 with dic, form enhancements, latest swiftmailer and better performance", + "support": { + "source": "https://github.com/orangehrm/symfony1/tree/ohrm" + } + }, + { + "name": "oomphinc/composer-installers-extender", + "version": "v1.1.2", + "version_normalized": "1.1.2.0", + "source": { + "type": "git", + "url": "https://github.com/oomphinc/composer-installers-extender.git", + "reference": "ca1c4b16b0905c81d1e77e608f36a2eff1a56f56" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/oomphinc/composer-installers-extender/zipball/ca1c4b16b0905c81d1e77e608f36a2eff1a56f56", + "reference": "ca1c4b16b0905c81d1e77e608f36a2eff1a56f56", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0", + "composer/installers": "^1.0" + }, + "time": "2017-03-31T16:57:39+00:00", + "type": "composer-plugin", + "extra": { + "class": "OomphInc\\ComposerInstallersExtender\\Plugin" + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "OomphInc\\ComposerInstallersExtender\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Stephen Beemsterboer", + "email": "stephen@oomphinc.com", + "homepage": "https://github.com/balbuf" + } + ], + "description": "Extend the composer/installers plugin to accept any arbitrary package type.", + "homepage": "http://www.oomphinc.com/" + }, + { + "name": "swiftmailer/swiftmailer", + "version": "v5.4.12", + "version_normalized": "5.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/swiftmailer/swiftmailer.git", + "reference": "181b89f18a90f8925ef805f950d47a7190e9b950" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/181b89f18a90f8925ef805f950d47a7190e9b950", + "reference": "181b89f18a90f8925ef805f950d47a7190e9b950", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "mockery/mockery": "~0.9.1", + "symfony/phpunit-bridge": "~3.2" + }, + "time": "2018-07-31T09:26:32+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "lib/swift_required.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Corbyn" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Swiftmailer, free feature-rich PHP mailer", + "homepage": "https://swiftmailer.symfony.com", + "keywords": [ + "email", + "mail", + "mailer" + ] + } +] diff --git a/lib/vendor/composer/installers/LICENSE b/lib/vendor/composer/installers/LICENSE new file mode 100644 index 0000000..85f97fc --- /dev/null +++ b/lib/vendor/composer/installers/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012 Kyle Robinson Young + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/lib/vendor/composer/installers/composer.json b/lib/vendor/composer/installers/composer.json new file mode 100644 index 0000000..c21715d --- /dev/null +++ b/lib/vendor/composer/installers/composer.json @@ -0,0 +1,112 @@ +{ + "name": "composer/installers", + "type": "composer-plugin", + "license": "MIT", + "description": "A multi-framework Composer library installer", + "keywords": [ + "installer", + "Aimeos", + "AGL", + "AnnotateCms", + "Attogram", + "Bitrix", + "CakePHP", + "Chef", + "Cockpit", + "CodeIgniter", + "concrete5", + "Craft", + "Croogo", + "DokuWiki", + "Dolibarr", + "Drupal", + "Elgg", + "Eliasis", + "ExpressionEngine", + "eZ Platform", + "FuelPHP", + "Grav", + "Hurad", + "ImageCMS", + "iTop", + "Joomla", + "Kanboard", + "Known", + "Kohana", + "Lan Management System", + "Laravel", + "Lavalite", + "Lithium", + "Magento", + "majima", + "Mako", + "MantisBT", + "Mautic", + "Maya", + "MODX", + "MODX Evo", + "MediaWiki", + "OXID", + "osclass", + "MODULEWork", + "Moodle", + "Piwik", + "pxcms", + "phpBB", + "Plentymarkets", + "PPI", + "Puppet", + "Porto", + "RadPHP", + "ReIndex", + "Roundcube", + "shopware", + "SilverStripe", + "SMF", + "SyDES", + "Sylius", + "symfony", + "Thelia", + "TYPO3", + "WHMCS", + "WolfCMS", + "WordPress", + "YAWIK", + "Zend", + "Zikula" + ], + "homepage": "https://composer.github.io/installers/", + "authors": [ + { + "name": "Kyle Robinson Young", + "email": "kyle@dontkry.com", + "homepage": "https://github.com/shama" + } + ], + "autoload": { + "psr-4": { "Composer\\Installers\\": "src/Composer/Installers" } + }, + "extra": { + "class": "Composer\\Installers\\Plugin", + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "replace": { + "shama/baton": "*", + "roundcube/plugin-installer": "*" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0" + }, + "require-dev": { + "composer/composer": "1.6.* || 2.0.*@dev", + "composer/semver": "1.0.* || 2.0.*@dev", + "phpunit/phpunit": "^4.8.36", + "sebastian/comparator": "^1.2.4", + "symfony/process": "^2.3" + }, + "scripts": { + "test": "phpunit" + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/AglInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/AglInstaller.php new file mode 100644 index 0000000..01b8a41 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/AglInstaller.php @@ -0,0 +1,21 @@ + 'More/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars($vars) + { + $vars['name'] = preg_replace_callback('/(?:^|_|-)(.?)/', function ($matches) { + return strtoupper($matches[1]); + }, $vars['name']); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/AimeosInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/AimeosInstaller.php new file mode 100644 index 0000000..79a0e95 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/AimeosInstaller.php @@ -0,0 +1,9 @@ + 'ext/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php new file mode 100644 index 0000000..89d7ad9 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php @@ -0,0 +1,11 @@ + 'addons/modules/{$name}/', + 'component' => 'addons/components/{$name}/', + 'service' => 'addons/services/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/AsgardInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/AsgardInstaller.php new file mode 100644 index 0000000..22dad1b --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/AsgardInstaller.php @@ -0,0 +1,49 @@ + 'Modules/{$name}/', + 'theme' => 'Themes/{$name}/' + ); + + /** + * Format package name. + * + * For package type asgard-module, cut off a trailing '-plugin' if present. + * + * For package type asgard-theme, cut off a trailing '-theme' if present. + * + */ + public function inflectPackageVars($vars) + { + if ($vars['type'] === 'asgard-module') { + return $this->inflectPluginVars($vars); + } + + if ($vars['type'] === 'asgard-theme') { + return $this->inflectThemeVars($vars); + } + + return $vars; + } + + protected function inflectPluginVars($vars) + { + $vars['name'] = preg_replace('/-module$/', '', $vars['name']); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } + + protected function inflectThemeVars($vars) + { + $vars['name'] = preg_replace('/-theme$/', '', $vars['name']); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/AttogramInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/AttogramInstaller.php new file mode 100644 index 0000000..d62fd8f --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/AttogramInstaller.php @@ -0,0 +1,9 @@ + 'modules/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/BaseInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/BaseInstaller.php new file mode 100644 index 0000000..d9d6073 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/BaseInstaller.php @@ -0,0 +1,137 @@ +composer = $composer; + $this->package = $package; + $this->io = $io; + } + + /** + * Return the install path based on package type. + * + * @param PackageInterface $package + * @param string $frameworkType + * @return string + */ + public function getInstallPath(PackageInterface $package, $frameworkType = '') + { + $type = $this->package->getType(); + + $prettyName = $this->package->getPrettyName(); + if (strpos($prettyName, '/') !== false) { + list($vendor, $name) = explode('/', $prettyName); + } else { + $vendor = ''; + $name = $prettyName; + } + + $availableVars = $this->inflectPackageVars(compact('name', 'vendor', 'type')); + + $extra = $package->getExtra(); + if (!empty($extra['installer-name'])) { + $availableVars['name'] = $extra['installer-name']; + } + + if ($this->composer->getPackage()) { + $extra = $this->composer->getPackage()->getExtra(); + if (!empty($extra['installer-paths'])) { + $customPath = $this->mapCustomInstallPaths($extra['installer-paths'], $prettyName, $type, $vendor); + if ($customPath !== false) { + return $this->templatePath($customPath, $availableVars); + } + } + } + + $packageType = substr($type, strlen($frameworkType) + 1); + $locations = $this->getLocations(); + if (!isset($locations[$packageType])) { + throw new \InvalidArgumentException(sprintf('Package type "%s" is not supported', $type)); + } + + return $this->templatePath($locations[$packageType], $availableVars); + } + + /** + * For an installer to override to modify the vars per installer. + * + * @param array $vars + * @return array + */ + public function inflectPackageVars($vars) + { + return $vars; + } + + /** + * Gets the installer's locations + * + * @return array + */ + public function getLocations() + { + return $this->locations; + } + + /** + * Replace vars in a path + * + * @param string $path + * @param array $vars + * @return string + */ + protected function templatePath($path, array $vars = array()) + { + if (strpos($path, '{') !== false) { + extract($vars); + preg_match_all('@\{\$([A-Za-z0-9_]*)\}@i', $path, $matches); + if (!empty($matches[1])) { + foreach ($matches[1] as $var) { + $path = str_replace('{$' . $var . '}', $$var, $path); + } + } + } + + return $path; + } + + /** + * Search through a passed paths array for a custom install path. + * + * @param array $paths + * @param string $name + * @param string $type + * @param string $vendor = NULL + * @return string + */ + protected function mapCustomInstallPaths(array $paths, $name, $type, $vendor = NULL) + { + foreach ($paths as $path => $names) { + $names = (array) $names; + if (in_array($name, $names) || in_array('type:' . $type, $names) || in_array('vendor:' . $vendor, $names)) { + return $path; + } + } + + return false; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/BitrixInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/BitrixInstaller.php new file mode 100644 index 0000000..e80cd1e --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/BitrixInstaller.php @@ -0,0 +1,126 @@ +.`. + * - `bitrix-d7-component` — copy the component to directory `bitrix/components//`. + * - `bitrix-d7-template` — copy the template to directory `bitrix/templates/_`. + * + * You can set custom path to directory with Bitrix kernel in `composer.json`: + * + * ```json + * { + * "extra": { + * "bitrix-dir": "s1/bitrix" + * } + * } + * ``` + * + * @author Nik Samokhvalov + * @author Denis Kulichkin + */ +class BitrixInstaller extends BaseInstaller +{ + protected $locations = array( + 'module' => '{$bitrix_dir}/modules/{$name}/', // deprecated, remove on the major release (Backward compatibility will be broken) + 'component' => '{$bitrix_dir}/components/{$name}/', // deprecated, remove on the major release (Backward compatibility will be broken) + 'theme' => '{$bitrix_dir}/templates/{$name}/', // deprecated, remove on the major release (Backward compatibility will be broken) + 'd7-module' => '{$bitrix_dir}/modules/{$vendor}.{$name}/', + 'd7-component' => '{$bitrix_dir}/components/{$vendor}/{$name}/', + 'd7-template' => '{$bitrix_dir}/templates/{$vendor}_{$name}/', + ); + + /** + * @var array Storage for informations about duplicates at all the time of installation packages. + */ + private static $checkedDuplicates = array(); + + /** + * {@inheritdoc} + */ + public function inflectPackageVars($vars) + { + if ($this->composer->getPackage()) { + $extra = $this->composer->getPackage()->getExtra(); + + if (isset($extra['bitrix-dir'])) { + $vars['bitrix_dir'] = $extra['bitrix-dir']; + } + } + + if (!isset($vars['bitrix_dir'])) { + $vars['bitrix_dir'] = 'bitrix'; + } + + return parent::inflectPackageVars($vars); + } + + /** + * {@inheritdoc} + */ + protected function templatePath($path, array $vars = array()) + { + $templatePath = parent::templatePath($path, $vars); + $this->checkDuplicates($templatePath, $vars); + + return $templatePath; + } + + /** + * Duplicates search packages. + * + * @param string $path + * @param array $vars + */ + protected function checkDuplicates($path, array $vars = array()) + { + $packageType = substr($vars['type'], strlen('bitrix') + 1); + $localDir = explode('/', $vars['bitrix_dir']); + array_pop($localDir); + $localDir[] = 'local'; + $localDir = implode('/', $localDir); + + $oldPath = str_replace( + array('{$bitrix_dir}', '{$name}'), + array($localDir, $vars['name']), + $this->locations[$packageType] + ); + + if (in_array($oldPath, static::$checkedDuplicates)) { + return; + } + + if ($oldPath !== $path && file_exists($oldPath) && $this->io && $this->io->isInteractive()) { + + $this->io->writeError(' Duplication of packages:'); + $this->io->writeError(' Package ' . $oldPath . ' will be called instead package ' . $path . ''); + + while (true) { + switch ($this->io->ask(' Delete ' . $oldPath . ' [y,n,?]? ', '?')) { + case 'y': + $fs = new Filesystem(); + $fs->removeDirectory($oldPath); + break 2; + + case 'n': + break 2; + + case '?': + default: + $this->io->writeError(array( + ' y - delete package ' . $oldPath . ' and to continue with the installation', + ' n - don\'t delete and to continue with the installation', + )); + $this->io->writeError(' ? - print help'); + break; + } + } + } + + static::$checkedDuplicates[] = $oldPath; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/BonefishInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/BonefishInstaller.php new file mode 100644 index 0000000..da3aad2 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/BonefishInstaller.php @@ -0,0 +1,9 @@ + 'Packages/{$vendor}/{$name}/' + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/CakePHPInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/CakePHPInstaller.php new file mode 100644 index 0000000..71ee2ef --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/CakePHPInstaller.php @@ -0,0 +1,72 @@ + 'Plugin/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars($vars) + { + if ($this->matchesCakeVersion('>=', '3.0.0')) { + return $vars; + } + + $nameParts = explode('/', $vars['name']); + foreach ($nameParts as &$value) { + $value = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $value)); + $value = str_replace(array('-', '_'), ' ', $value); + $value = str_replace(' ', '', ucwords($value)); + } + $vars['name'] = implode('/', $nameParts); + + return $vars; + } + + /** + * Change the default plugin location when cakephp >= 3.0 + */ + public function getLocations() + { + if ($this->matchesCakeVersion('>=', '3.0.0')) { + $this->locations['plugin'] = $this->composer->getConfig()->get('vendor-dir') . '/{$vendor}/{$name}/'; + } + return $this->locations; + } + + /** + * Check if CakePHP version matches against a version + * + * @param string $matcher + * @param string $version + * @return bool + */ + protected function matchesCakeVersion($matcher, $version) + { + if (class_exists('Composer\Semver\Constraint\MultiConstraint')) { + $multiClass = 'Composer\Semver\Constraint\MultiConstraint'; + $constraintClass = 'Composer\Semver\Constraint\Constraint'; + } else { + $multiClass = 'Composer\Package\LinkConstraint\MultiConstraint'; + $constraintClass = 'Composer\Package\LinkConstraint\VersionConstraint'; + } + + $repositoryManager = $this->composer->getRepositoryManager(); + if (! $repositoryManager) { + return false; + } + + $repos = $repositoryManager->getLocalRepository(); + if (!$repos) { + return false; + } + + return $repos->findPackage('cakephp/cakephp', new $constraintClass($matcher, $version)) !== null; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/ChefInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/ChefInstaller.php new file mode 100644 index 0000000..ab2f9aa --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/ChefInstaller.php @@ -0,0 +1,11 @@ + 'Chef/{$vendor}/{$name}/', + 'role' => 'Chef/roles/{$name}/', + ); +} + diff --git a/lib/vendor/composer/installers/src/Composer/Installers/CiviCrmInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/CiviCrmInstaller.php new file mode 100644 index 0000000..6673aea --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/CiviCrmInstaller.php @@ -0,0 +1,9 @@ + 'ext/{$name}/' + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php new file mode 100644 index 0000000..c887815 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php @@ -0,0 +1,10 @@ + 'CCF/orbit/{$name}/', + 'theme' => 'CCF/app/themes/{$name}/', + ); +} \ No newline at end of file diff --git a/lib/vendor/composer/installers/src/Composer/Installers/CockpitInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/CockpitInstaller.php new file mode 100644 index 0000000..c7816df --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/CockpitInstaller.php @@ -0,0 +1,34 @@ + 'cockpit/modules/addons/{$name}/', + ); + + /** + * Format module name. + * + * Strip `module-` prefix from package name. + * + * @param array @vars + * + * @return array + */ + public function inflectPackageVars($vars) + { + if ($vars['type'] == 'cockpit-module') { + return $this->inflectModuleVars($vars); + } + + return $vars; + } + + public function inflectModuleVars($vars) + { + $vars['name'] = ucfirst(preg_replace('/cockpit-/i', '', $vars['name'])); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php new file mode 100644 index 0000000..3b4a4ec --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php @@ -0,0 +1,11 @@ + 'application/libraries/{$name}/', + 'third-party' => 'application/third_party/{$name}/', + 'module' => 'application/modules/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/Concrete5Installer.php b/lib/vendor/composer/installers/src/Composer/Installers/Concrete5Installer.php new file mode 100644 index 0000000..5c01baf --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/Concrete5Installer.php @@ -0,0 +1,13 @@ + 'concrete/', + 'block' => 'application/blocks/{$name}/', + 'package' => 'packages/{$name}/', + 'theme' => 'application/themes/{$name}/', + 'update' => 'updates/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/CraftInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/CraftInstaller.php new file mode 100644 index 0000000..d37a77a --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/CraftInstaller.php @@ -0,0 +1,35 @@ + 'craft/plugins/{$name}/', + ); + + /** + * Strip `craft-` prefix and/or `-plugin` suffix from package names + * + * @param array $vars + * + * @return array + */ + final public function inflectPackageVars($vars) + { + return $this->inflectPluginVars($vars); + } + + private function inflectPluginVars($vars) + { + $vars['name'] = preg_replace('/-' . self::NAME_SUFFIX . '$/i', '', $vars['name']); + $vars['name'] = preg_replace('/^' . self::NAME_PREFIX . '-/i', '', $vars['name']); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/CroogoInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/CroogoInstaller.php new file mode 100644 index 0000000..d94219d --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/CroogoInstaller.php @@ -0,0 +1,21 @@ + 'Plugin/{$name}/', + 'theme' => 'View/Themed/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars($vars) + { + $vars['name'] = strtolower(str_replace(array('-', '_'), ' ', $vars['name'])); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/DecibelInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/DecibelInstaller.php new file mode 100644 index 0000000..f4837a6 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/DecibelInstaller.php @@ -0,0 +1,10 @@ + 'app/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/DframeInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/DframeInstaller.php new file mode 100644 index 0000000..7078816 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/DframeInstaller.php @@ -0,0 +1,10 @@ + 'modules/{$vendor}/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/DokuWikiInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/DokuWikiInstaller.php new file mode 100644 index 0000000..cfd638d --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/DokuWikiInstaller.php @@ -0,0 +1,50 @@ + 'lib/plugins/{$name}/', + 'template' => 'lib/tpl/{$name}/', + ); + + /** + * Format package name. + * + * For package type dokuwiki-plugin, cut off a trailing '-plugin', + * or leading dokuwiki_ if present. + * + * For package type dokuwiki-template, cut off a trailing '-template' if present. + * + */ + public function inflectPackageVars($vars) + { + + if ($vars['type'] === 'dokuwiki-plugin') { + return $this->inflectPluginVars($vars); + } + + if ($vars['type'] === 'dokuwiki-template') { + return $this->inflectTemplateVars($vars); + } + + return $vars; + } + + protected function inflectPluginVars($vars) + { + $vars['name'] = preg_replace('/-plugin$/', '', $vars['name']); + $vars['name'] = preg_replace('/^dokuwiki_?-?/', '', $vars['name']); + + return $vars; + } + + protected function inflectTemplateVars($vars) + { + $vars['name'] = preg_replace('/-template$/', '', $vars['name']); + $vars['name'] = preg_replace('/^dokuwiki_?-?/', '', $vars['name']); + + return $vars; + } + +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/DolibarrInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/DolibarrInstaller.php new file mode 100644 index 0000000..21f7e8e --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/DolibarrInstaller.php @@ -0,0 +1,16 @@ + + */ +class DolibarrInstaller extends BaseInstaller +{ + //TODO: Add support for scripts and themes + protected $locations = array( + 'module' => 'htdocs/custom/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/DrupalInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/DrupalInstaller.php new file mode 100644 index 0000000..7328239 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/DrupalInstaller.php @@ -0,0 +1,22 @@ + 'core/', + 'module' => 'modules/{$name}/', + 'theme' => 'themes/{$name}/', + 'library' => 'libraries/{$name}/', + 'profile' => 'profiles/{$name}/', + 'database-driver' => 'drivers/lib/Drupal/Driver/Database/{$name}/', + 'drush' => 'drush/{$name}/', + 'custom-theme' => 'themes/custom/{$name}/', + 'custom-module' => 'modules/custom/{$name}/', + 'custom-profile' => 'profiles/custom/{$name}/', + 'drupal-multisite' => 'sites/{$name}/', + 'console' => 'console/{$name}/', + 'console-language' => 'console/language/{$name}/', + 'config' => 'config/sync/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/ElggInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/ElggInstaller.php new file mode 100644 index 0000000..c0bb609 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/ElggInstaller.php @@ -0,0 +1,9 @@ + 'mod/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/EliasisInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/EliasisInstaller.php new file mode 100644 index 0000000..6f3dc97 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/EliasisInstaller.php @@ -0,0 +1,12 @@ + 'components/{$name}/', + 'module' => 'modules/{$name}/', + 'plugin' => 'plugins/{$name}/', + 'template' => 'templates/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php new file mode 100644 index 0000000..d5321a8 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php @@ -0,0 +1,29 @@ + 'system/expressionengine/third_party/{$name}/', + 'theme' => 'themes/third_party/{$name}/', + ); + + private $ee3Locations = array( + 'addon' => 'system/user/addons/{$name}/', + 'theme' => 'themes/user/{$name}/', + ); + + public function getInstallPath(PackageInterface $package, $frameworkType = '') + { + + $version = "{$frameworkType}Locations"; + $this->locations = $this->$version; + + return parent::getInstallPath($package, $frameworkType); + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/EzPlatformInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/EzPlatformInstaller.php new file mode 100644 index 0000000..f30ebcc --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/EzPlatformInstaller.php @@ -0,0 +1,10 @@ + 'web/assets/ezplatform/', + 'assets' => 'web/assets/ezplatform/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/FuelInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/FuelInstaller.php new file mode 100644 index 0000000..6eba2e3 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/FuelInstaller.php @@ -0,0 +1,11 @@ + 'fuel/app/modules/{$name}/', + 'package' => 'fuel/packages/{$name}/', + 'theme' => 'fuel/app/themes/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/FuelphpInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/FuelphpInstaller.php new file mode 100644 index 0000000..29d980b --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/FuelphpInstaller.php @@ -0,0 +1,9 @@ + 'components/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/GravInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/GravInstaller.php new file mode 100644 index 0000000..dbe63e0 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/GravInstaller.php @@ -0,0 +1,30 @@ + 'user/plugins/{$name}/', + 'theme' => 'user/themes/{$name}/', + ); + + /** + * Format package name + * + * @param array $vars + * + * @return array + */ + public function inflectPackageVars($vars) + { + $restrictedWords = implode('|', array_keys($this->locations)); + + $vars['name'] = strtolower($vars['name']); + $vars['name'] = preg_replace('/^(?:grav-)?(?:(?:'.$restrictedWords.')-)?(.*?)(?:-(?:'.$restrictedWords.'))?$/ui', + '$1', + $vars['name'] + ); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/HuradInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/HuradInstaller.php new file mode 100644 index 0000000..8fe017f --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/HuradInstaller.php @@ -0,0 +1,25 @@ + 'plugins/{$name}/', + 'theme' => 'plugins/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars($vars) + { + $nameParts = explode('/', $vars['name']); + foreach ($nameParts as &$value) { + $value = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $value)); + $value = str_replace(array('-', '_'), ' ', $value); + $value = str_replace(' ', '', ucwords($value)); + } + $vars['name'] = implode('/', $nameParts); + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/ImageCMSInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/ImageCMSInstaller.php new file mode 100644 index 0000000..5e2142e --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/ImageCMSInstaller.php @@ -0,0 +1,11 @@ + 'templates/{$name}/', + 'module' => 'application/modules/{$name}/', + 'library' => 'application/libraries/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/Installer.php b/lib/vendor/composer/installers/src/Composer/Installers/Installer.php new file mode 100644 index 0000000..d1d43b9 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/Installer.php @@ -0,0 +1,280 @@ + 'AimeosInstaller', + 'asgard' => 'AsgardInstaller', + 'attogram' => 'AttogramInstaller', + 'agl' => 'AglInstaller', + 'annotatecms' => 'AnnotateCmsInstaller', + 'bitrix' => 'BitrixInstaller', + 'bonefish' => 'BonefishInstaller', + 'cakephp' => 'CakePHPInstaller', + 'chef' => 'ChefInstaller', + 'civicrm' => 'CiviCrmInstaller', + 'ccframework' => 'ClanCatsFrameworkInstaller', + 'cockpit' => 'CockpitInstaller', + 'codeigniter' => 'CodeIgniterInstaller', + 'concrete5' => 'Concrete5Installer', + 'craft' => 'CraftInstaller', + 'croogo' => 'CroogoInstaller', + 'dframe' => 'DframeInstaller', + 'dokuwiki' => 'DokuWikiInstaller', + 'dolibarr' => 'DolibarrInstaller', + 'decibel' => 'DecibelInstaller', + 'drupal' => 'DrupalInstaller', + 'elgg' => 'ElggInstaller', + 'eliasis' => 'EliasisInstaller', + 'ee3' => 'ExpressionEngineInstaller', + 'ee2' => 'ExpressionEngineInstaller', + 'ezplatform' => 'EzPlatformInstaller', + 'fuel' => 'FuelInstaller', + 'fuelphp' => 'FuelphpInstaller', + 'grav' => 'GravInstaller', + 'hurad' => 'HuradInstaller', + 'imagecms' => 'ImageCMSInstaller', + 'itop' => 'ItopInstaller', + 'joomla' => 'JoomlaInstaller', + 'kanboard' => 'KanboardInstaller', + 'kirby' => 'KirbyInstaller', + 'known' => 'KnownInstaller', + 'kodicms' => 'KodiCMSInstaller', + 'kohana' => 'KohanaInstaller', + 'lms' => 'LanManagementSystemInstaller', + 'laravel' => 'LaravelInstaller', + 'lavalite' => 'LavaLiteInstaller', + 'lithium' => 'LithiumInstaller', + 'magento' => 'MagentoInstaller', + 'majima' => 'MajimaInstaller', + 'mantisbt' => 'MantisBTInstaller', + 'mako' => 'MakoInstaller', + 'maya' => 'MayaInstaller', + 'mautic' => 'MauticInstaller', + 'mediawiki' => 'MediaWikiInstaller', + 'microweber' => 'MicroweberInstaller', + 'modulework' => 'MODULEWorkInstaller', + 'modx' => 'ModxInstaller', + 'modxevo' => 'MODXEvoInstaller', + 'moodle' => 'MoodleInstaller', + 'october' => 'OctoberInstaller', + 'ontowiki' => 'OntoWikiInstaller', + 'oxid' => 'OxidInstaller', + 'osclass' => 'OsclassInstaller', + 'pxcms' => 'PxcmsInstaller', + 'phpbb' => 'PhpBBInstaller', + 'pimcore' => 'PimcoreInstaller', + 'piwik' => 'PiwikInstaller', + 'plentymarkets'=> 'PlentymarketsInstaller', + 'ppi' => 'PPIInstaller', + 'puppet' => 'PuppetInstaller', + 'radphp' => 'RadPHPInstaller', + 'phifty' => 'PhiftyInstaller', + 'porto' => 'PortoInstaller', + 'redaxo' => 'RedaxoInstaller', + 'redaxo5' => 'Redaxo5Installer', + 'reindex' => 'ReIndexInstaller', + 'roundcube' => 'RoundcubeInstaller', + 'shopware' => 'ShopwareInstaller', + 'sitedirect' => 'SiteDirectInstaller', + 'silverstripe' => 'SilverStripeInstaller', + 'smf' => 'SMFInstaller', + 'sydes' => 'SyDESInstaller', + 'sylius' => 'SyliusInstaller', + 'symfony1' => 'Symfony1Installer', + 'tao' => 'TaoInstaller', + 'thelia' => 'TheliaInstaller', + 'tusk' => 'TuskInstaller', + 'typo3-cms' => 'TYPO3CmsInstaller', + 'typo3-flow' => 'TYPO3FlowInstaller', + 'userfrosting' => 'UserFrostingInstaller', + 'vanilla' => 'VanillaInstaller', + 'whmcs' => 'WHMCSInstaller', + 'wolfcms' => 'WolfCMSInstaller', + 'wordpress' => 'WordPressInstaller', + 'yawik' => 'YawikInstaller', + 'zend' => 'ZendInstaller', + 'zikula' => 'ZikulaInstaller', + 'prestashop' => 'PrestashopInstaller' + ); + + /** + * Installer constructor. + * + * Disables installers specified in main composer extra installer-disable + * list + * + * @param IOInterface $io + * @param Composer $composer + * @param string $type + * @param Filesystem|null $filesystem + * @param BinaryInstaller|null $binaryInstaller + */ + public function __construct( + IOInterface $io, + Composer $composer, + $type = 'library', + Filesystem $filesystem = null, + BinaryInstaller $binaryInstaller = null + ) { + parent::__construct($io, $composer, $type, $filesystem, + $binaryInstaller); + $this->removeDisabledInstallers(); + } + + /** + * {@inheritDoc} + */ + public function getInstallPath(PackageInterface $package) + { + $type = $package->getType(); + $frameworkType = $this->findFrameworkType($type); + + if ($frameworkType === false) { + throw new \InvalidArgumentException( + 'Sorry the package type of this package is not yet supported.' + ); + } + + $class = 'Composer\\Installers\\' . $this->supportedTypes[$frameworkType]; + $installer = new $class($package, $this->composer, $this->getIO()); + + return $installer->getInstallPath($package, $frameworkType); + } + + public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package) + { + parent::uninstall($repo, $package); + $installPath = $this->getPackageBasePath($package); + $this->io->write(sprintf('Deleting %s - %s', $installPath, !file_exists($installPath) ? 'deleted' : 'not deleted')); + } + + /** + * {@inheritDoc} + */ + public function supports($packageType) + { + $frameworkType = $this->findFrameworkType($packageType); + + if ($frameworkType === false) { + return false; + } + + $locationPattern = $this->getLocationPattern($frameworkType); + + return preg_match('#' . $frameworkType . '-' . $locationPattern . '#', $packageType, $matches) === 1; + } + + /** + * Finds a supported framework type if it exists and returns it + * + * @param string $type + * @return string + */ + protected function findFrameworkType($type) + { + $frameworkType = false; + + krsort($this->supportedTypes); + + foreach ($this->supportedTypes as $key => $val) { + if ($key === substr($type, 0, strlen($key))) { + $frameworkType = substr($type, 0, strlen($key)); + break; + } + } + + return $frameworkType; + } + + /** + * Get the second part of the regular expression to check for support of a + * package type + * + * @param string $frameworkType + * @return string + */ + protected function getLocationPattern($frameworkType) + { + $pattern = false; + if (!empty($this->supportedTypes[$frameworkType])) { + $frameworkClass = 'Composer\\Installers\\' . $this->supportedTypes[$frameworkType]; + /** @var BaseInstaller $framework */ + $framework = new $frameworkClass(null, $this->composer, $this->getIO()); + $locations = array_keys($framework->getLocations()); + $pattern = $locations ? '(' . implode('|', $locations) . ')' : false; + } + + return $pattern ? : '(\w+)'; + } + + /** + * Get I/O object + * + * @return IOInterface + */ + private function getIO() + { + return $this->io; + } + + /** + * Look for installers set to be disabled in composer's extra config and + * remove them from the list of supported installers. + * + * Globals: + * - true, "all", and "*" - disable all installers. + * - false - enable all installers (useful with + * wikimedia/composer-merge-plugin or similar) + * + * @return void + */ + protected function removeDisabledInstallers() + { + $extra = $this->composer->getPackage()->getExtra(); + + if (!isset($extra['installer-disable']) || $extra['installer-disable'] === false) { + // No installers are disabled + return; + } + + // Get installers to disable + $disable = $extra['installer-disable']; + + // Ensure $disabled is an array + if (!is_array($disable)) { + $disable = array($disable); + } + + // Check which installers should be disabled + $all = array(true, "all", "*"); + $intersect = array_intersect($all, $disable); + if (!empty($intersect)) { + // Disable all installers + $this->supportedTypes = array(); + } else { + // Disable specified installers + foreach ($disable as $key => $installer) { + if (is_string($installer) && key_exists($installer, $this->supportedTypes)) { + unset($this->supportedTypes[$installer]); + } + } + } + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/ItopInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/ItopInstaller.php new file mode 100644 index 0000000..c6c1b33 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/ItopInstaller.php @@ -0,0 +1,9 @@ + 'extensions/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/JoomlaInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/JoomlaInstaller.php new file mode 100644 index 0000000..9ee7759 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/JoomlaInstaller.php @@ -0,0 +1,15 @@ + 'components/{$name}/', + 'module' => 'modules/{$name}/', + 'template' => 'templates/{$name}/', + 'plugin' => 'plugins/{$name}/', + 'library' => 'libraries/{$name}/', + ); + + // TODO: Add inflector for mod_ and com_ names +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/KanboardInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/KanboardInstaller.php new file mode 100644 index 0000000..9cb7b8c --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/KanboardInstaller.php @@ -0,0 +1,18 @@ + 'plugins/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php new file mode 100644 index 0000000..36b2f84 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php @@ -0,0 +1,11 @@ + 'site/plugins/{$name}/', + 'field' => 'site/fields/{$name}/', + 'tag' => 'site/tags/{$name}/' + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/KnownInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/KnownInstaller.php new file mode 100644 index 0000000..c5d08c5 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/KnownInstaller.php @@ -0,0 +1,11 @@ + 'IdnoPlugins/{$name}/', + 'theme' => 'Themes/{$name}/', + 'console' => 'ConsolePlugins/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/KodiCMSInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/KodiCMSInstaller.php new file mode 100644 index 0000000..7143e23 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/KodiCMSInstaller.php @@ -0,0 +1,10 @@ + 'cms/plugins/{$name}/', + 'media' => 'cms/media/vendor/{$name}/' + ); +} \ No newline at end of file diff --git a/lib/vendor/composer/installers/src/Composer/Installers/KohanaInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/KohanaInstaller.php new file mode 100644 index 0000000..dcd6d26 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/KohanaInstaller.php @@ -0,0 +1,9 @@ + 'modules/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php new file mode 100644 index 0000000..903143a --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php @@ -0,0 +1,27 @@ + 'plugins/{$name}/', + 'template' => 'templates/{$name}/', + 'document-template' => 'documents/templates/{$name}/', + 'userpanel-module' => 'userpanel/modules/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars($vars) + { + $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } + +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/LaravelInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/LaravelInstaller.php new file mode 100644 index 0000000..be4d53a --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/LaravelInstaller.php @@ -0,0 +1,9 @@ + 'libraries/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/LavaLiteInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/LavaLiteInstaller.php new file mode 100644 index 0000000..412c0b5 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/LavaLiteInstaller.php @@ -0,0 +1,10 @@ + 'packages/{$vendor}/{$name}/', + 'theme' => 'public/themes/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/LithiumInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/LithiumInstaller.php new file mode 100644 index 0000000..47bbd4c --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/LithiumInstaller.php @@ -0,0 +1,10 @@ + 'libraries/{$name}/', + 'source' => 'libraries/_source/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php new file mode 100644 index 0000000..9c2e9fb --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php @@ -0,0 +1,9 @@ + 'modules/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/MODXEvoInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/MODXEvoInstaller.php new file mode 100644 index 0000000..5a66460 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/MODXEvoInstaller.php @@ -0,0 +1,16 @@ + 'assets/snippets/{$name}/', + 'plugin' => 'assets/plugins/{$name}/', + 'module' => 'assets/modules/{$name}/', + 'template' => 'assets/templates/{$name}/', + 'lib' => 'assets/lib/{$name}/' + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/MagentoInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/MagentoInstaller.php new file mode 100644 index 0000000..cf18e94 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/MagentoInstaller.php @@ -0,0 +1,11 @@ + 'app/design/frontend/{$name}/', + 'skin' => 'skin/frontend/default/{$name}/', + 'library' => 'lib/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/MajimaInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/MajimaInstaller.php new file mode 100644 index 0000000..e463756 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/MajimaInstaller.php @@ -0,0 +1,37 @@ + 'plugins/{$name}/', + ); + + /** + * Transforms the names + * @param array $vars + * @return array + */ + public function inflectPackageVars($vars) + { + return $this->correctPluginName($vars); + } + + /** + * Change hyphenated names to camelcase + * @param array $vars + * @return array + */ + private function correctPluginName($vars) + { + $camelCasedName = preg_replace_callback('/(-[a-z])/', function ($matches) { + return strtoupper($matches[0][1]); + }, $vars['name']); + $vars['name'] = ucfirst($camelCasedName); + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/MakoInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/MakoInstaller.php new file mode 100644 index 0000000..ca3cfac --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/MakoInstaller.php @@ -0,0 +1,9 @@ + 'app/packages/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/MantisBTInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/MantisBTInstaller.php new file mode 100644 index 0000000..dadb1db --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/MantisBTInstaller.php @@ -0,0 +1,23 @@ + 'plugins/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars($vars) + { + $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/MauticInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/MauticInstaller.php new file mode 100644 index 0000000..3e1ce2b --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/MauticInstaller.php @@ -0,0 +1,25 @@ + 'plugins/{$name}/', + 'theme' => 'themes/{$name}/', + ); + + /** + * Format package name of mautic-plugins to CamelCase + */ + public function inflectPackageVars($vars) + { + if ($vars['type'] == 'mautic-plugin') { + $vars['name'] = preg_replace_callback('/(-[a-z])/', function ($matches) { + return strtoupper($matches[0][1]); + }, ucfirst($vars['name'])); + } + + return $vars; + } + +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/MayaInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/MayaInstaller.php new file mode 100644 index 0000000..30a9167 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/MayaInstaller.php @@ -0,0 +1,33 @@ + 'modules/{$name}/', + ); + + /** + * Format package name. + * + * For package type maya-module, cut off a trailing '-module' if present. + * + */ + public function inflectPackageVars($vars) + { + if ($vars['type'] === 'maya-module') { + return $this->inflectModuleVars($vars); + } + + return $vars; + } + + protected function inflectModuleVars($vars) + { + $vars['name'] = preg_replace('/-module$/', '', $vars['name']); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/MediaWikiInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/MediaWikiInstaller.php new file mode 100644 index 0000000..f5a8957 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/MediaWikiInstaller.php @@ -0,0 +1,51 @@ + 'core/', + 'extension' => 'extensions/{$name}/', + 'skin' => 'skins/{$name}/', + ); + + /** + * Format package name. + * + * For package type mediawiki-extension, cut off a trailing '-extension' if present and transform + * to CamelCase keeping existing uppercase chars. + * + * For package type mediawiki-skin, cut off a trailing '-skin' if present. + * + */ + public function inflectPackageVars($vars) + { + + if ($vars['type'] === 'mediawiki-extension') { + return $this->inflectExtensionVars($vars); + } + + if ($vars['type'] === 'mediawiki-skin') { + return $this->inflectSkinVars($vars); + } + + return $vars; + } + + protected function inflectExtensionVars($vars) + { + $vars['name'] = preg_replace('/-extension$/', '', $vars['name']); + $vars['name'] = str_replace('-', ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } + + protected function inflectSkinVars($vars) + { + $vars['name'] = preg_replace('/-skin$/', '', $vars['name']); + + return $vars; + } + +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/MicroweberInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/MicroweberInstaller.php new file mode 100644 index 0000000..b7d9703 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/MicroweberInstaller.php @@ -0,0 +1,119 @@ + 'userfiles/modules/{$install_item_dir}/', + 'module-skin' => 'userfiles/modules/{$install_item_dir}/templates/', + 'template' => 'userfiles/templates/{$install_item_dir}/', + 'element' => 'userfiles/elements/{$install_item_dir}/', + 'vendor' => 'vendor/{$install_item_dir}/', + 'components' => 'components/{$install_item_dir}/' + ); + + /** + * Format package name. + * + * For package type microweber-module, cut off a trailing '-module' if present + * + * For package type microweber-template, cut off a trailing '-template' if present. + * + */ + public function inflectPackageVars($vars) + { + + + if ($this->package->getTargetDir()) { + $vars['install_item_dir'] = $this->package->getTargetDir(); + } else { + $vars['install_item_dir'] = $vars['name']; + if ($vars['type'] === 'microweber-template') { + return $this->inflectTemplateVars($vars); + } + if ($vars['type'] === 'microweber-templates') { + return $this->inflectTemplatesVars($vars); + } + if ($vars['type'] === 'microweber-core') { + return $this->inflectCoreVars($vars); + } + if ($vars['type'] === 'microweber-adapter') { + return $this->inflectCoreVars($vars); + } + if ($vars['type'] === 'microweber-module') { + return $this->inflectModuleVars($vars); + } + if ($vars['type'] === 'microweber-modules') { + return $this->inflectModulesVars($vars); + } + if ($vars['type'] === 'microweber-skin') { + return $this->inflectSkinVars($vars); + } + if ($vars['type'] === 'microweber-element' or $vars['type'] === 'microweber-elements') { + return $this->inflectElementVars($vars); + } + } + + + return $vars; + } + + protected function inflectTemplateVars($vars) + { + $vars['install_item_dir'] = preg_replace('/-template$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = preg_replace('/template-$/', '', $vars['install_item_dir']); + + return $vars; + } + + protected function inflectTemplatesVars($vars) + { + $vars['install_item_dir'] = preg_replace('/-templates$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = preg_replace('/templates-$/', '', $vars['install_item_dir']); + + return $vars; + } + + protected function inflectCoreVars($vars) + { + $vars['install_item_dir'] = preg_replace('/-providers$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = preg_replace('/-provider$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = preg_replace('/-adapter$/', '', $vars['install_item_dir']); + + return $vars; + } + + protected function inflectModuleVars($vars) + { + $vars['install_item_dir'] = preg_replace('/-module$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = preg_replace('/module-$/', '', $vars['install_item_dir']); + + return $vars; + } + + protected function inflectModulesVars($vars) + { + $vars['install_item_dir'] = preg_replace('/-modules$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = preg_replace('/modules-$/', '', $vars['install_item_dir']); + + return $vars; + } + + protected function inflectSkinVars($vars) + { + $vars['install_item_dir'] = preg_replace('/-skin$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = preg_replace('/skin-$/', '', $vars['install_item_dir']); + + return $vars; + } + + protected function inflectElementVars($vars) + { + $vars['install_item_dir'] = preg_replace('/-elements$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = preg_replace('/elements-$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = preg_replace('/-element$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = preg_replace('/element-$/', '', $vars['install_item_dir']); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/ModxInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/ModxInstaller.php new file mode 100644 index 0000000..0ee140a --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/ModxInstaller.php @@ -0,0 +1,12 @@ + 'core/packages/{$name}/' + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/MoodleInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/MoodleInstaller.php new file mode 100644 index 0000000..75dbe71 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/MoodleInstaller.php @@ -0,0 +1,58 @@ + 'mod/{$name}/', + 'admin_report' => 'admin/report/{$name}/', + 'atto' => 'lib/editor/atto/plugins/{$name}/', + 'tool' => 'admin/tool/{$name}/', + 'assignment' => 'mod/assignment/type/{$name}/', + 'assignsubmission' => 'mod/assign/submission/{$name}/', + 'assignfeedback' => 'mod/assign/feedback/{$name}/', + 'auth' => 'auth/{$name}/', + 'availability' => 'availability/condition/{$name}/', + 'block' => 'blocks/{$name}/', + 'booktool' => 'mod/book/tool/{$name}/', + 'cachestore' => 'cache/stores/{$name}/', + 'cachelock' => 'cache/locks/{$name}/', + 'calendartype' => 'calendar/type/{$name}/', + 'format' => 'course/format/{$name}/', + 'coursereport' => 'course/report/{$name}/', + 'customcertelement' => 'mod/customcert/element/{$name}/', + 'datafield' => 'mod/data/field/{$name}/', + 'datapreset' => 'mod/data/preset/{$name}/', + 'editor' => 'lib/editor/{$name}/', + 'enrol' => 'enrol/{$name}/', + 'filter' => 'filter/{$name}/', + 'gradeexport' => 'grade/export/{$name}/', + 'gradeimport' => 'grade/import/{$name}/', + 'gradereport' => 'grade/report/{$name}/', + 'gradingform' => 'grade/grading/form/{$name}/', + 'local' => 'local/{$name}/', + 'logstore' => 'admin/tool/log/store/{$name}/', + 'ltisource' => 'mod/lti/source/{$name}/', + 'ltiservice' => 'mod/lti/service/{$name}/', + 'message' => 'message/output/{$name}/', + 'mnetservice' => 'mnet/service/{$name}/', + 'plagiarism' => 'plagiarism/{$name}/', + 'portfolio' => 'portfolio/{$name}/', + 'qbehaviour' => 'question/behaviour/{$name}/', + 'qformat' => 'question/format/{$name}/', + 'qtype' => 'question/type/{$name}/', + 'quizaccess' => 'mod/quiz/accessrule/{$name}/', + 'quiz' => 'mod/quiz/report/{$name}/', + 'report' => 'report/{$name}/', + 'repository' => 'repository/{$name}/', + 'scormreport' => 'mod/scorm/report/{$name}/', + 'search' => 'search/engine/{$name}/', + 'theme' => 'theme/{$name}/', + 'tinymce' => 'lib/editor/tinymce/plugins/{$name}/', + 'profilefield' => 'user/profile/field/{$name}/', + 'webservice' => 'webservice/{$name}/', + 'workshopallocation' => 'mod/workshop/allocation/{$name}/', + 'workshopeval' => 'mod/workshop/eval/{$name}/', + 'workshopform' => 'mod/workshop/form/{$name}/' + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/OctoberInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/OctoberInstaller.php new file mode 100644 index 0000000..08d5dc4 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/OctoberInstaller.php @@ -0,0 +1,47 @@ + 'modules/{$name}/', + 'plugin' => 'plugins/{$vendor}/{$name}/', + 'theme' => 'themes/{$name}/' + ); + + /** + * Format package name. + * + * For package type october-plugin, cut off a trailing '-plugin' if present. + * + * For package type october-theme, cut off a trailing '-theme' if present. + * + */ + public function inflectPackageVars($vars) + { + if ($vars['type'] === 'october-plugin') { + return $this->inflectPluginVars($vars); + } + + if ($vars['type'] === 'october-theme') { + return $this->inflectThemeVars($vars); + } + + return $vars; + } + + protected function inflectPluginVars($vars) + { + $vars['name'] = preg_replace('/^oc-|-plugin$/', '', $vars['name']); + $vars['vendor'] = preg_replace('/[^a-z0-9_]/i', '', $vars['vendor']); + + return $vars; + } + + protected function inflectThemeVars($vars) + { + $vars['name'] = preg_replace('/^oc-|-theme$/', '', $vars['name']); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/OntoWikiInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/OntoWikiInstaller.php new file mode 100644 index 0000000..5dd3438 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/OntoWikiInstaller.php @@ -0,0 +1,24 @@ + 'extensions/{$name}/', + 'theme' => 'extensions/themes/{$name}/', + 'translation' => 'extensions/translations/{$name}/', + ); + + /** + * Format package name to lower case and remove ".ontowiki" suffix + */ + public function inflectPackageVars($vars) + { + $vars['name'] = strtolower($vars['name']); + $vars['name'] = preg_replace('/.ontowiki$/', '', $vars['name']); + $vars['name'] = preg_replace('/-theme$/', '', $vars['name']); + $vars['name'] = preg_replace('/-translation$/', '', $vars['name']); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/OsclassInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/OsclassInstaller.php new file mode 100644 index 0000000..3ca7954 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/OsclassInstaller.php @@ -0,0 +1,14 @@ + 'oc-content/plugins/{$name}/', + 'theme' => 'oc-content/themes/{$name}/', + 'language' => 'oc-content/languages/{$name}/', + ); + +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/OxidInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/OxidInstaller.php new file mode 100644 index 0000000..49940ff --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/OxidInstaller.php @@ -0,0 +1,59 @@ +.+)\/.+/'; + + protected $locations = array( + 'module' => 'modules/{$name}/', + 'theme' => 'application/views/{$name}/', + 'out' => 'out/{$name}/', + ); + + /** + * getInstallPath + * + * @param PackageInterface $package + * @param string $frameworkType + * @return void + */ + public function getInstallPath(PackageInterface $package, $frameworkType = '') + { + $installPath = parent::getInstallPath($package, $frameworkType); + $type = $this->package->getType(); + if ($type === 'oxid-module') { + $this->prepareVendorDirectory($installPath); + } + return $installPath; + } + + /** + * prepareVendorDirectory + * + * Makes sure there is a vendormetadata.php file inside + * the vendor folder if there is a vendor folder. + * + * @param string $installPath + * @return void + */ + protected function prepareVendorDirectory($installPath) + { + $matches = ''; + $hasVendorDirectory = preg_match(self::VENDOR_PATTERN, $installPath, $matches); + if (!$hasVendorDirectory) { + return; + } + + $vendorDirectory = $matches['vendor']; + $vendorPath = getcwd() . '/modules/' . $vendorDirectory; + if (!file_exists($vendorPath)) { + mkdir($vendorPath, 0755, true); + } + + $vendorMetaDataPath = $vendorPath . '/vendormetadata.php'; + touch($vendorMetaDataPath); + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/PPIInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/PPIInstaller.php new file mode 100644 index 0000000..170136f --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/PPIInstaller.php @@ -0,0 +1,9 @@ + 'modules/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/PhiftyInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/PhiftyInstaller.php new file mode 100644 index 0000000..4e59a8a --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/PhiftyInstaller.php @@ -0,0 +1,11 @@ + 'bundles/{$name}/', + 'library' => 'libraries/{$name}/', + 'framework' => 'frameworks/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/PhpBBInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/PhpBBInstaller.php new file mode 100644 index 0000000..deb2b77 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/PhpBBInstaller.php @@ -0,0 +1,11 @@ + 'ext/{$vendor}/{$name}/', + 'language' => 'language/{$name}/', + 'style' => 'styles/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/PimcoreInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/PimcoreInstaller.php new file mode 100644 index 0000000..4781fa6 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/PimcoreInstaller.php @@ -0,0 +1,21 @@ + 'plugins/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars($vars) + { + $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/PiwikInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/PiwikInstaller.php new file mode 100644 index 0000000..c17f457 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/PiwikInstaller.php @@ -0,0 +1,32 @@ + 'plugins/{$name}/', + ); + + /** + * Format package name to CamelCase + * @param array $vars + * + * @return array + */ + public function inflectPackageVars($vars) + { + $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php new file mode 100644 index 0000000..903e55f --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php @@ -0,0 +1,29 @@ + '{$name}/' + ); + + /** + * Remove hyphen, "plugin" and format to camelcase + * @param array $vars + * + * @return array + */ + public function inflectPackageVars($vars) + { + $vars['name'] = explode("-", $vars['name']); + foreach ($vars['name'] as $key => $name) { + $vars['name'][$key] = ucfirst($vars['name'][$key]); + if (strcasecmp($name, "Plugin") == 0) { + unset($vars['name'][$key]); + } + } + $vars['name'] = implode("",$vars['name']); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/Plugin.php b/lib/vendor/composer/installers/src/Composer/Installers/Plugin.php new file mode 100644 index 0000000..e60da0e --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/Plugin.php @@ -0,0 +1,27 @@ +installer = new Installer($io, $composer); + $composer->getInstallationManager()->addInstaller($this->installer); + } + + public function deactivate(Composer $composer, IOInterface $io) + { + $composer->getInstallationManager()->removeInstaller($this->installer); + } + + public function uninstall(Composer $composer, IOInterface $io) + { + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/PortoInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/PortoInstaller.php new file mode 100644 index 0000000..dbf85e6 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/PortoInstaller.php @@ -0,0 +1,9 @@ + 'app/Containers/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/PrestashopInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/PrestashopInstaller.php new file mode 100644 index 0000000..4c8421e --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/PrestashopInstaller.php @@ -0,0 +1,10 @@ + 'modules/{$name}/', + 'theme' => 'themes/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/PuppetInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/PuppetInstaller.php new file mode 100644 index 0000000..77cc3dd --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/PuppetInstaller.php @@ -0,0 +1,11 @@ + 'modules/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/PxcmsInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/PxcmsInstaller.php new file mode 100644 index 0000000..6551058 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/PxcmsInstaller.php @@ -0,0 +1,63 @@ + 'app/Modules/{$name}/', + 'theme' => 'themes/{$name}/', + ); + + /** + * Format package name. + * + * @param array $vars + * + * @return array + */ + public function inflectPackageVars($vars) + { + if ($vars['type'] === 'pxcms-module') { + return $this->inflectModuleVars($vars); + } + + if ($vars['type'] === 'pxcms-theme') { + return $this->inflectThemeVars($vars); + } + + return $vars; + } + + /** + * For package type pxcms-module, cut off a trailing '-plugin' if present. + * + * return string + */ + protected function inflectModuleVars($vars) + { + $vars['name'] = str_replace('pxcms-', '', $vars['name']); // strip out pxcms- just incase (legacy) + $vars['name'] = str_replace('module-', '', $vars['name']); // strip out module- + $vars['name'] = preg_replace('/-module$/', '', $vars['name']); // strip out -module + $vars['name'] = str_replace('-', '_', $vars['name']); // make -'s be _'s + $vars['name'] = ucwords($vars['name']); // make module name camelcased + + return $vars; + } + + + /** + * For package type pxcms-module, cut off a trailing '-plugin' if present. + * + * return string + */ + protected function inflectThemeVars($vars) + { + $vars['name'] = str_replace('pxcms-', '', $vars['name']); // strip out pxcms- just incase (legacy) + $vars['name'] = str_replace('theme-', '', $vars['name']); // strip out theme- + $vars['name'] = preg_replace('/-theme$/', '', $vars['name']); // strip out -theme + $vars['name'] = str_replace('-', '_', $vars['name']); // make -'s be _'s + $vars['name'] = ucwords($vars['name']); // make module name camelcased + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/RadPHPInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/RadPHPInstaller.php new file mode 100644 index 0000000..0f78b5c --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/RadPHPInstaller.php @@ -0,0 +1,24 @@ + 'src/{$name}/' + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars($vars) + { + $nameParts = explode('/', $vars['name']); + foreach ($nameParts as &$value) { + $value = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $value)); + $value = str_replace(array('-', '_'), ' ', $value); + $value = str_replace(' ', '', ucwords($value)); + } + $vars['name'] = implode('/', $nameParts); + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/ReIndexInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/ReIndexInstaller.php new file mode 100644 index 0000000..252c733 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/ReIndexInstaller.php @@ -0,0 +1,10 @@ + 'themes/{$name}/', + 'plugin' => 'plugins/{$name}/' + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/Redaxo5Installer.php b/lib/vendor/composer/installers/src/Composer/Installers/Redaxo5Installer.php new file mode 100644 index 0000000..23a2034 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/Redaxo5Installer.php @@ -0,0 +1,10 @@ + 'redaxo/src/addons/{$name}/', + 'bestyle-plugin' => 'redaxo/src/addons/be_style/plugins/{$name}/' + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/RedaxoInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/RedaxoInstaller.php new file mode 100644 index 0000000..0954457 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/RedaxoInstaller.php @@ -0,0 +1,10 @@ + 'redaxo/include/addons/{$name}/', + 'bestyle-plugin' => 'redaxo/include/addons/be_style/plugins/{$name}/' + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/RoundcubeInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/RoundcubeInstaller.php new file mode 100644 index 0000000..d8d795b --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/RoundcubeInstaller.php @@ -0,0 +1,22 @@ + 'plugins/{$name}/', + ); + + /** + * Lowercase name and changes the name to a underscores + * + * @param array $vars + * @return array + */ + public function inflectPackageVars($vars) + { + $vars['name'] = strtolower(str_replace('-', '_', $vars['name'])); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/SMFInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/SMFInstaller.php new file mode 100644 index 0000000..1acd3b1 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/SMFInstaller.php @@ -0,0 +1,10 @@ + 'Sources/{$name}/', + 'theme' => 'Themes/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/ShopwareInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/ShopwareInstaller.php new file mode 100644 index 0000000..7d20d27 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/ShopwareInstaller.php @@ -0,0 +1,60 @@ + 'engine/Shopware/Plugins/Local/Backend/{$name}/', + 'core-plugin' => 'engine/Shopware/Plugins/Local/Core/{$name}/', + 'frontend-plugin' => 'engine/Shopware/Plugins/Local/Frontend/{$name}/', + 'theme' => 'templates/{$name}/', + 'plugin' => 'custom/plugins/{$name}/', + 'frontend-theme' => 'themes/Frontend/{$name}/', + ); + + /** + * Transforms the names + * @param array $vars + * @return array + */ + public function inflectPackageVars($vars) + { + if ($vars['type'] === 'shopware-theme') { + return $this->correctThemeName($vars); + } + + return $this->correctPluginName($vars); + } + + /** + * Changes the name to a camelcased combination of vendor and name + * @param array $vars + * @return array + */ + private function correctPluginName($vars) + { + $camelCasedName = preg_replace_callback('/(-[a-z])/', function ($matches) { + return strtoupper($matches[0][1]); + }, $vars['name']); + + $vars['name'] = ucfirst($vars['vendor']) . ucfirst($camelCasedName); + + return $vars; + } + + /** + * Changes the name to a underscore separated name + * @param array $vars + * @return array + */ + private function correctThemeName($vars) + { + $vars['name'] = str_replace('-', '_', $vars['name']); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/SilverStripeInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/SilverStripeInstaller.php new file mode 100644 index 0000000..81910e9 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/SilverStripeInstaller.php @@ -0,0 +1,35 @@ + '{$name}/', + 'theme' => 'themes/{$name}/', + ); + + /** + * Return the install path based on package type. + * + * Relies on built-in BaseInstaller behaviour with one exception: silverstripe/framework + * must be installed to 'sapphire' and not 'framework' if the version is <3.0.0 + * + * @param PackageInterface $package + * @param string $frameworkType + * @return string + */ + public function getInstallPath(PackageInterface $package, $frameworkType = '') + { + if ( + $package->getName() == 'silverstripe/framework' + && preg_match('/^\d+\.\d+\.\d+/', $package->getVersion()) + && version_compare($package->getVersion(), '2.999.999') < 0 + ) { + return $this->templatePath($this->locations['module'], array('name' => 'sapphire')); + } + + return parent::getInstallPath($package, $frameworkType); + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/SiteDirectInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/SiteDirectInstaller.php new file mode 100644 index 0000000..762d94c --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/SiteDirectInstaller.php @@ -0,0 +1,25 @@ + 'modules/{$vendor}/{$name}/', + 'plugin' => 'plugins/{$vendor}/{$name}/' + ); + + public function inflectPackageVars($vars) + { + return $this->parseVars($vars); + } + + protected function parseVars($vars) + { + $vars['vendor'] = strtolower($vars['vendor']) == 'sitedirect' ? 'SiteDirect' : $vars['vendor']; + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/SyDESInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/SyDESInstaller.php new file mode 100644 index 0000000..83ef9d0 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/SyDESInstaller.php @@ -0,0 +1,49 @@ + 'app/modules/{$name}/', + 'theme' => 'themes/{$name}/', + ); + + /** + * Format module name. + * + * Strip `sydes-` prefix and a trailing '-theme' or '-module' from package name if present. + * + * @param array @vars + * + * @return array + */ + public function inflectPackageVars($vars) + { + if ($vars['type'] == 'sydes-module') { + return $this->inflectModuleVars($vars); + } + + if ($vars['type'] === 'sydes-theme') { + return $this->inflectThemeVars($vars); + } + + return $vars; + } + + public function inflectModuleVars($vars) + { + $vars['name'] = preg_replace('/(^sydes-|-module$)/i', '', $vars['name']); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } + + protected function inflectThemeVars($vars) + { + $vars['name'] = preg_replace('/(^sydes-|-theme$)/', '', $vars['name']); + $vars['name'] = strtolower($vars['name']); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/SyliusInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/SyliusInstaller.php new file mode 100644 index 0000000..4357a35 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/SyliusInstaller.php @@ -0,0 +1,9 @@ + 'themes/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/Symfony1Installer.php b/lib/vendor/composer/installers/src/Composer/Installers/Symfony1Installer.php new file mode 100644 index 0000000..1675c4f --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/Symfony1Installer.php @@ -0,0 +1,26 @@ + + */ +class Symfony1Installer extends BaseInstaller +{ + protected $locations = array( + 'plugin' => 'plugins/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars($vars) + { + $vars['name'] = preg_replace_callback('/(-[a-z])/', function ($matches) { + return strtoupper($matches[0][1]); + }, $vars['name']); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php new file mode 100644 index 0000000..b1663e8 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php @@ -0,0 +1,16 @@ + + */ +class TYPO3CmsInstaller extends BaseInstaller +{ + protected $locations = array( + 'extension' => 'typo3conf/ext/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php new file mode 100644 index 0000000..42572f4 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php @@ -0,0 +1,38 @@ + 'Packages/Application/{$name}/', + 'framework' => 'Packages/Framework/{$name}/', + 'plugin' => 'Packages/Plugins/{$name}/', + 'site' => 'Packages/Sites/{$name}/', + 'boilerplate' => 'Packages/Boilerplates/{$name}/', + 'build' => 'Build/{$name}/', + ); + + /** + * Modify the package name to be a TYPO3 Flow style key. + * + * @param array $vars + * @return array + */ + public function inflectPackageVars($vars) + { + $autoload = $this->package->getAutoload(); + if (isset($autoload['psr-0']) && is_array($autoload['psr-0'])) { + $namespace = key($autoload['psr-0']); + $vars['name'] = str_replace('\\', '.', $namespace); + } + if (isset($autoload['psr-4']) && is_array($autoload['psr-4'])) { + $namespace = key($autoload['psr-4']); + $vars['name'] = rtrim(str_replace('\\', '.', $namespace), '.'); + } + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/TaoInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/TaoInstaller.php new file mode 100644 index 0000000..108def1 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/TaoInstaller.php @@ -0,0 +1,12 @@ + '{$name}' + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/TheliaInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/TheliaInstaller.php new file mode 100644 index 0000000..158af52 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/TheliaInstaller.php @@ -0,0 +1,12 @@ + 'local/modules/{$name}/', + 'frontoffice-template' => 'templates/frontOffice/{$name}/', + 'backoffice-template' => 'templates/backOffice/{$name}/', + 'email-template' => 'templates/email/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/TuskInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/TuskInstaller.php new file mode 100644 index 0000000..7c0113b --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/TuskInstaller.php @@ -0,0 +1,14 @@ + + */ + class TuskInstaller extends BaseInstaller + { + protected $locations = array( + 'task' => '.tusk/tasks/{$name}/', + 'command' => '.tusk/commands/{$name}/', + 'asset' => 'assets/tusk/{$name}/', + ); + } diff --git a/lib/vendor/composer/installers/src/Composer/Installers/UserFrostingInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/UserFrostingInstaller.php new file mode 100644 index 0000000..fcb414a --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/UserFrostingInstaller.php @@ -0,0 +1,9 @@ + 'app/sprinkles/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/VanillaInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/VanillaInstaller.php new file mode 100644 index 0000000..24ca645 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/VanillaInstaller.php @@ -0,0 +1,10 @@ + 'plugins/{$name}/', + 'theme' => 'themes/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/VgmcpInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/VgmcpInstaller.php new file mode 100644 index 0000000..7d90c5e --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/VgmcpInstaller.php @@ -0,0 +1,49 @@ + 'src/{$vendor}/{$name}/', + 'theme' => 'themes/{$name}/' + ); + + /** + * Format package name. + * + * For package type vgmcp-bundle, cut off a trailing '-bundle' if present. + * + * For package type vgmcp-theme, cut off a trailing '-theme' if present. + * + */ + public function inflectPackageVars($vars) + { + if ($vars['type'] === 'vgmcp-bundle') { + return $this->inflectPluginVars($vars); + } + + if ($vars['type'] === 'vgmcp-theme') { + return $this->inflectThemeVars($vars); + } + + return $vars; + } + + protected function inflectPluginVars($vars) + { + $vars['name'] = preg_replace('/-bundle$/', '', $vars['name']); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } + + protected function inflectThemeVars($vars) + { + $vars['name'] = preg_replace('/-theme$/', '', $vars['name']); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/WHMCSInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/WHMCSInstaller.php new file mode 100644 index 0000000..b65dbba --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/WHMCSInstaller.php @@ -0,0 +1,21 @@ + 'modules/addons/{$vendor}_{$name}/', + 'fraud' => 'modules/fraud/{$vendor}_{$name}/', + 'gateways' => 'modules/gateways/{$vendor}_{$name}/', + 'notifications' => 'modules/notifications/{$vendor}_{$name}/', + 'registrars' => 'modules/registrars/{$vendor}_{$name}/', + 'reports' => 'modules/reports/{$vendor}_{$name}/', + 'security' => 'modules/security/{$vendor}_{$name}/', + 'servers' => 'modules/servers/{$vendor}_{$name}/', + 'social' => 'modules/social/{$vendor}_{$name}/', + 'support' => 'modules/support/{$vendor}_{$name}/', + 'templates' => 'templates/{$vendor}_{$name}/', + 'includes' => 'includes/{$vendor}_{$name}/' + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/WolfCMSInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/WolfCMSInstaller.php new file mode 100644 index 0000000..cb38788 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/WolfCMSInstaller.php @@ -0,0 +1,9 @@ + 'wolf/plugins/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/WordPressInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/WordPressInstaller.php new file mode 100644 index 0000000..91c46ad --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/WordPressInstaller.php @@ -0,0 +1,12 @@ + 'wp-content/plugins/{$name}/', + 'theme' => 'wp-content/themes/{$name}/', + 'muplugin' => 'wp-content/mu-plugins/{$name}/', + 'dropin' => 'wp-content/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/YawikInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/YawikInstaller.php new file mode 100644 index 0000000..27f429f --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/YawikInstaller.php @@ -0,0 +1,32 @@ + 'module/{$name}/', + ); + + /** + * Format package name to CamelCase + * @param array $vars + * + * @return array + */ + public function inflectPackageVars($vars) + { + $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} \ No newline at end of file diff --git a/lib/vendor/composer/installers/src/Composer/Installers/ZendInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/ZendInstaller.php new file mode 100644 index 0000000..bde9bc8 --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/ZendInstaller.php @@ -0,0 +1,11 @@ + 'library/{$name}/', + 'extra' => 'extras/library/{$name}/', + 'module' => 'module/{$name}/', + ); +} diff --git a/lib/vendor/composer/installers/src/Composer/Installers/ZikulaInstaller.php b/lib/vendor/composer/installers/src/Composer/Installers/ZikulaInstaller.php new file mode 100644 index 0000000..56cdf5d --- /dev/null +++ b/lib/vendor/composer/installers/src/Composer/Installers/ZikulaInstaller.php @@ -0,0 +1,10 @@ + 'modules/{$vendor}-{$name}/', + 'theme' => 'themes/{$vendor}-{$name}/' + ); +} diff --git a/lib/vendor/composer/installers/src/bootstrap.php b/lib/vendor/composer/installers/src/bootstrap.php new file mode 100644 index 0000000..0de276e --- /dev/null +++ b/lib/vendor/composer/installers/src/bootstrap.php @@ -0,0 +1,13 @@ +instantiate(\My\ClassName\Here::class); +``` + +## Contributing + +Please read the [CONTRIBUTING.md](CONTRIBUTING.md) contents if you wish to help out! + +## Credits + +This library was migrated from [ocramius/instantiator](https://github.com/Ocramius/Instantiator), which +has been donated to the doctrine organization, and which is now deprecated in favour of this package. diff --git a/lib/vendor/doctrine/instantiator/composer.json b/lib/vendor/doctrine/instantiator/composer.json new file mode 100644 index 0000000..9002a91 --- /dev/null +++ b/lib/vendor/doctrine/instantiator/composer.json @@ -0,0 +1,47 @@ +{ + "name": "doctrine/instantiator", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "type": "library", + "license": "MIT", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "instantiate", + "constructor" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "require": { + "php": "^7.1" + }, + "require-dev": { + "ext-phar": "*", + "ext-pdo": "*", + "doctrine/coding-standard": "^6.0", + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "autoload-dev": { + "psr-0": { + "DoctrineTest\\InstantiatorPerformance\\": "tests", + "DoctrineTest\\InstantiatorTest\\": "tests", + "DoctrineTest\\InstantiatorTestAsset\\": "tests" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + } +} diff --git a/lib/vendor/doctrine/instantiator/docs/en/index.rst b/lib/vendor/doctrine/instantiator/docs/en/index.rst new file mode 100644 index 0000000..0c85da0 --- /dev/null +++ b/lib/vendor/doctrine/instantiator/docs/en/index.rst @@ -0,0 +1,68 @@ +Introduction +============ + +This library provides a way of avoiding usage of constructors when instantiating PHP classes. + +Installation +============ + +The suggested installation method is via `composer`_: + +.. code-block:: console + + $ composer require doctrine/instantiator + +Usage +===== + +The instantiator is able to create new instances of any class without +using the constructor or any API of the class itself: + +.. code-block:: php + + instantiate(User::class); + +Contributing +============ + +- Follow the `Doctrine Coding Standard`_ +- The project will follow strict `object calisthenics`_ +- Any contribution must provide tests for additional introduced + conditions +- Any un-confirmed issue needs a failing test case before being + accepted +- Pull requests must be sent from a new hotfix/feature branch, not from + ``master``. + +Testing +======= + +The PHPUnit version to be used is the one installed as a dev- dependency +via composer: + +.. code-block:: console + + $ ./vendor/bin/phpunit + +Accepted coverage for new contributions is 80%. Any contribution not +satisfying this requirement won’t be merged. + +Credits +======= + +This library was migrated from `ocramius/instantiator`_, which has been +donated to the doctrine organization, and which is now deprecated in +favour of this package. + +.. _composer: https://getcomposer.org/ +.. _CONTRIBUTING.md: CONTRIBUTING.md +.. _ocramius/instantiator: https://github.com/Ocramius/Instantiator +.. _Doctrine Coding Standard: https://github.com/doctrine/coding-standard +.. _object calisthenics: http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php diff --git a/lib/vendor/doctrine/instantiator/docs/en/sidebar.rst b/lib/vendor/doctrine/instantiator/docs/en/sidebar.rst new file mode 100644 index 0000000..0c36479 --- /dev/null +++ b/lib/vendor/doctrine/instantiator/docs/en/sidebar.rst @@ -0,0 +1,4 @@ +.. toctree:: + :depth: 3 + + index diff --git a/lib/vendor/doctrine/instantiator/phpbench.json b/lib/vendor/doctrine/instantiator/phpbench.json new file mode 100644 index 0000000..fce5dd6 --- /dev/null +++ b/lib/vendor/doctrine/instantiator/phpbench.json @@ -0,0 +1,4 @@ +{ + "bootstrap": "vendor/autoload.php", + "path": "tests/DoctrineTest/InstantiatorPerformance" +} diff --git a/lib/vendor/doctrine/instantiator/phpcs.xml.dist b/lib/vendor/doctrine/instantiator/phpcs.xml.dist new file mode 100644 index 0000000..1fcac4a --- /dev/null +++ b/lib/vendor/doctrine/instantiator/phpcs.xml.dist @@ -0,0 +1,35 @@ + + + + + + + + + + + + src + tests + + + + + + + + + + tests/DoctrineTest/InstantiatorTestAsset/AbstractClassAsset.php + + + + src/Doctrine/Instantiator/Exception/UnexpectedValueException.php + src/Doctrine/Instantiator/Exception/InvalidArgumentException.php + + + + src/Doctrine/Instantiator/Exception/ExceptionInterface.php + src/Doctrine/Instantiator/InstantiatorInterface.php + + diff --git a/lib/vendor/doctrine/instantiator/phpstan.neon.dist b/lib/vendor/doctrine/instantiator/phpstan.neon.dist new file mode 100644 index 0000000..ecc38ef --- /dev/null +++ b/lib/vendor/doctrine/instantiator/phpstan.neon.dist @@ -0,0 +1,19 @@ +includes: + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-phpunit/rules.neon + +parameters: + level: max + paths: + - src + - tests + + ignoreErrors: + - + message: '#::__construct\(\) does not call parent constructor from#' + path: '*/tests/DoctrineTest/InstantiatorTestAsset/*.php' + + # dynamic properties confuse static analysis + - + message: '#Access to an undefined property object::\$foo\.#' + path: '*/tests/DoctrineTest/InstantiatorTest/InstantiatorTest.php' diff --git a/lib/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php b/lib/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php new file mode 100644 index 0000000..e6a5195 --- /dev/null +++ b/lib/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php @@ -0,0 +1,12 @@ += 50400 && trait_exists($className)) { + return new self(sprintf('The provided type "%s" is a trait, and can not be instantiated', $className)); + } + + return new self(sprintf('The provided class "%s" does not exist', $className)); + } + + public static function fromAbstractClass(ReflectionClass $reflectionClass) : self + { + return new self(sprintf( + 'The provided class "%s" is abstract, and can not be instantiated', + $reflectionClass->getName() + )); + } +} diff --git a/lib/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php b/lib/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php new file mode 100644 index 0000000..d946731 --- /dev/null +++ b/lib/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php @@ -0,0 +1,48 @@ +getName() + ), + 0, + $exception + ); + } + + public static function fromUncleanUnSerialization( + ReflectionClass $reflectionClass, + string $errorString, + int $errorCode, + string $errorFile, + int $errorLine + ) : self { + return new self( + sprintf( + 'Could not produce an instance of "%s" via un-serialization, since an error was triggered ' + . 'in file "%s" at line "%d"', + $reflectionClass->getName(), + $errorFile, + $errorLine + ), + 0, + new Exception($errorString, $errorCode) + ); + } +} diff --git a/lib/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php b/lib/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php new file mode 100644 index 0000000..4364190 --- /dev/null +++ b/lib/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php @@ -0,0 +1,198 @@ +buildAndCacheFromFactory($className); + } + + /** + * Builds the requested object and caches it in static properties for performance + * + * @return object + */ + private function buildAndCacheFromFactory(string $className) + { + $factory = self::$cachedInstantiators[$className] = $this->buildFactory($className); + $instance = $factory(); + + if ($this->isSafeToClone(new ReflectionClass($instance))) { + self::$cachedCloneables[$className] = clone $instance; + } + + return $instance; + } + + /** + * Builds a callable capable of instantiating the given $className without + * invoking its constructor. + * + * @throws InvalidArgumentException + * @throws UnexpectedValueException + * @throws ReflectionException + */ + private function buildFactory(string $className) : callable + { + $reflectionClass = $this->getReflectionClass($className); + + if ($this->isInstantiableViaReflection($reflectionClass)) { + return [$reflectionClass, 'newInstanceWithoutConstructor']; + } + + $serializedString = sprintf( + '%s:%d:"%s":0:{}', + self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER, + strlen($className), + $className + ); + + $this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString); + + return static function () use ($serializedString) { + return unserialize($serializedString); + }; + } + + /** + * @param string $className + * + * @throws InvalidArgumentException + * @throws ReflectionException + */ + private function getReflectionClass($className) : ReflectionClass + { + if (! class_exists($className)) { + throw InvalidArgumentException::fromNonExistingClass($className); + } + + $reflection = new ReflectionClass($className); + + if ($reflection->isAbstract()) { + throw InvalidArgumentException::fromAbstractClass($reflection); + } + + return $reflection; + } + + /** + * @throws UnexpectedValueException + */ + private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, string $serializedString) : void + { + set_error_handler(static function ($code, $message, $file, $line) use ($reflectionClass, & $error) : void { + $error = UnexpectedValueException::fromUncleanUnSerialization( + $reflectionClass, + $message, + $code, + $file, + $line + ); + }); + + try { + $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString); + } finally { + restore_error_handler(); + } + + if ($error) { + throw $error; + } + } + + /** + * @throws UnexpectedValueException + */ + private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, string $serializedString) : void + { + try { + unserialize($serializedString); + } catch (Exception $exception) { + throw UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception); + } + } + + private function isInstantiableViaReflection(ReflectionClass $reflectionClass) : bool + { + return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal()); + } + + /** + * Verifies whether the given class is to be considered internal + */ + private function hasInternalAncestors(ReflectionClass $reflectionClass) : bool + { + do { + if ($reflectionClass->isInternal()) { + return true; + } + + $reflectionClass = $reflectionClass->getParentClass(); + } while ($reflectionClass); + + return false; + } + + /** + * Checks if a class is cloneable + * + * Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects. + */ + private function isSafeToClone(ReflectionClass $reflection) : bool + { + return $reflection->isCloneable() && ! $reflection->hasMethod('__clone'); + } +} diff --git a/lib/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php b/lib/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php new file mode 100644 index 0000000..95299f4 --- /dev/null +++ b/lib/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php @@ -0,0 +1,20 @@ + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/lib/vendor/lexpress/doctrine1/UPGRADE_TO_1_2 b/lib/vendor/lexpress/doctrine1/UPGRADE_TO_1_2 new file mode 100644 index 0000000..ef78cbb --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/UPGRADE_TO_1_2 @@ -0,0 +1,983 @@ +# Upgrade from 1.1 to 1.2 + +This document details the changes made to Doctrine 1.2 to make it easier for you +to upgrade your projects to use this version. + +## Removed Attribute String Support + +The string support of `Doctrine_Configurable::getAttribute()` and +`Doctrine_Configurable::setAttribute()` have been removed. + +The reason is that the performance of this simple convenience feature is +significant and it is totally unneeded. + +The following code is no longer supported. + + [php] + $connection->setAttribute('use_native_enum', true); + +You must now always use the following code. + + [php] + $connection->setAttribute(Doctrine_Core::ATTR_USE_NATIVE_ENUM, true); + +## Removed all Deprecated Functions + +Removed all functions labeled `@deprecated` in the doc blocks. + +Affected Classes + +* Doctrine_Query +* Doctrine_Query_Abstract + +## Renamed Methods + +* Doctrine_Query_Abstract::getSql() to getSqlQuery() +* Doctrine_Search_Query::getSql() to getSqlQuery() +* Doctrine_Query_Abstract::*getCountQuery +* +* +* +* +* +() to getCountSqlQuery() +* Doctrine_RawSql::getCountQuery() to getCountSqlQuery() + +## Added ability to configure table class + +Added ability to specify the base `Doctrine_Table` class to use if no custom +`UserModelTable` class exists. + + [php] + $manager->setAttribute(Doctrine_Core::ATTR_TABLE_CLASS, 'MyTable'); + +Now just make sure the class exists somewhere and is loaded. + + [php] + class MyTable extends Doctrine_Table + { + + } + +This attribute value will be used for the following new option if you don't +specify it. + + [php] + $builder = new Doctrine_Import_Builder(); + $builder->setOption('baseTableClassName', 'MyBaseTable'); + +## Added ability to configure query class + +Before Doctrine 1.2 it was hard coded internally to always use the +`Doctrine_Query` class whenever you instantiate a new query. Now you can +configure which class this is to use by setting the `Doctrine_Core::ATTR_QUERY_CLASS` +attribute. + + [php] + class MyQuery extends Doctrine_Query + { + + } + + $manager->setAttribute(Doctrine_Core::ATTR_QUERY_CLASS, 'MyQuery'); + + $q = Doctrine_Query::create(); + + echo get_class($q); // MyQuery + +## Changed Doctrine_Parser_Xml::arrayToXml() to be static + +Now the `arrayToXml()` method can be called directly because it is static. + + [php] + $array = array( + 'key1' => 'value', + 'key2' => 'value' + ); + $xml = Doctrine_Parser_Xml::arrayToXml($array); + +## Refactored Migrations to better handle multiple connections + +Now when working with `Doctrine_Migration` instance you can specify as the +second argument to the constructor the connection instance to use for the +migrations. + +Migrations for different databases should be handled with a different set of +migration classes. + +Previous method of finding connection based on the table name is flawed since +databases could have the same table name multiple times. + + [php] + $conn = Doctrine_Manager::connection(); + $migration = new Doctrine_Migration('/path/to/migrations', $conn); + +## Added option for save cascading + +Added a new attribute to control whether cascading save operations are done by +default. Previous to Doctrine 1.2 they were always cascaded. + +As of 1.2 you have the option to disable cascading saves and will only cascade +if the record is dirty. The cost of this is that you can't cascade and save +records who are dirty that are more then one level deep in the hierarchy. + +See: http://trac.doctrine-project.org/ticket/1623 + +You can disable cascading saves with the following code. + + [php] + $manager->setAttribute(Doctrine_Core::ATTR_CASCADE_SAVES, false); + +Disabling this will increase performance significantly when saving objects. + +## Added Doctrine_Core::setPath() + +Now you can specify the path to your Doctrine libraries if Doctrine.php is +outside of the location of your libraries. + +So if `Doctrine.php` is located at `/path/to/Doctrine.php` and the actual +libraries are at `/path/to/the/doctrine/libs` you would need to do the +following. + + [php] + Doctrine_Core::setPath('/path/to/the/doctrine/libs'); + +## Ability to clear an individual reference + +Previously the `Doctrine_Record::clearRelated()` would only allow the clearing +of ALL references. It will now accept a relationship name and you can clear an +individual reference. + + [php] + $user->clearRelated('Phonenumber'); + +## Check related exists + +Often you want to check if a relationship exists in the database, but if it +doesn't exist you get a newly created blank relationship that will try to be +saved when you call save on the parent record. Use the new `relatedExists()` +method to check to avoid this behavior. + + [php] + if ($user->relatedExists('Profile')) { + // do something if the user has a profile + } + +## Reverse Engineered Columns + +If Doctrine does not recognize a column from a database when reverse engineering +a schema, instead of throwing an exception, it will default to a string. + +This allows custom column types or proprietary column types to be reverse +engineered without stopping the schema from being built completely. + +## Oracle Adapter Persistent Connections + +The `Doctrine_Adapter_Oracle` now will use persistent connections if specified. + + [php] + $info = array( + 'oracle:dbname=SID;charset=NLS_CHARACTERSET;persistent=true', + 'usr', + 'pass' + ); + + Doctrine_Manager::connection($info, 'conn_name'); + +## New Class/File Prefix Option for Model Builder + +You can now set a prefix for your generated models and choose to not have the +generated filename include that prefix as well. + + [php] + $builder = new Doctrine_Import_Builder(); + $builder->setOption('classPrefixFiles', false); + $builder->setOption('classPrefix', 'MyClassPrefix_'); + +Without the first option you'd get a file like `MyClassPrefix_ModelName.php` but +now you will get `ModelName.php` with a class named `MyClassPrefix_ModelName` +inside. + +## Expanded Magic Finders to Multiple Fields + +You can now `findBy` multiple fields and specify conditions between the fields. + + [php] + $user = $userTable->findOneByUsernameAndPassword('jwage', md5('changeme')); + +Or you could do something like the following and find admin users and moderator +users. + + [php] + $users = $userTable->findByIsAdminOrIsModerator(true, true); + +You can mix the conditions. + + [php] + $users = $userTable->findByIsAdminAndIsModeratorOrIsSuperAdmin(true, true, true); + +> **CAUTION** +> These are very limited magic finders and it is always recommended to expand +> your queries to be manually written DQL queries. These methods are meant for +> only quickly accessing single records, no relationships, and are good for +> prototyping code quickly. + +## Custom Collection Class + +You can now specify a custom child class to use for all collections inside +Doctrine. + + [php] + $manager->setAttribute(Doctrine_Core::ATTR_COLLECTION_CLASS, 'MyCollection'); + + $phonenumbers = $user->Phonenumbers; + echo get_class($phonenumbers); // MyCollection + +Now define the simple child class. + + [php] + class MyCollection extends Doctrine_Collection + { + + } + +This option can be set at the manager, connection and table levels. + +## Custom Hydrators + +As of Doctrine 1.2 it is now possible to register your own custom data +hydrators. The core hydration process has been decoupled to proper drivers and +now you can register your own to handle the hydration process. + +First lets register our custom hydrator class. + + [php] + $manager->registerHydrator('MyHydrator', 'Doctrine_Hydrator_MyHydrator'); + +So now we need to define a hydrator class named `MyHydrator` and it must +implement a method named `hydrateResultSet($stmt)` method which accepts a +query statement object. + + [php] + class Doctrine_Hydrator_MyHydrator extends Doctrine_Hydrator_Abstract + { + public function hydrateResultSet($stmt) + { + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + } + +Now you can run a query like the following which would use the new `MyHydrator`. + + [php] + $q->execute(array(), 'MyHydrator'); + +## Custom Connections + +You can now write and register your own custom Doctrine connection drivers and +adapters. + + [php] + class Doctrine_Connection_Test extends Doctrine_Connection_Common + { + } + + class Doctrine_Adapter_Test implements Doctrine_Adapter_Interface + { + // ... all the methods defined in the interface + } + +Now we can register this with Doctrine so we can utilize it as our connection. + + [php] + $manager->registerConnectionDriver('test', 'Doctrine_Connection_Test'); + +Now you can utilize that type of connection in your DSN when connecting. + + [php] + $conn = $manager->openConnection('test://username:password@localhost/dbname'); + +Now if we were to check what classes are used for the connection you will notice +that they are the classes we defined above. + + [php] + echo get_class($conn); // Doctrine_Connection_Test + echo get_class($conn->getDbh()); // Doctrine_Adapter_Test + +## Doctrine Extensions + +Doctrine now has support for creating, loading and testing extensions in to your +projects. + +First we need to simply tell `Doctrine` where the extensions are being loaded +from. + + [php] + Doctrine_Core::setExtensionsPath('/path/to/extensions'); + +Now we can check out one of the first available extensions in to our extensions +directory and then register it. + + $ svn co http://svn.doctrine-project.org/extensions/Sortable/branches/1.2-1.0/ /path/to/extensions/Sortable + +The directory structure of this extension looks like the following. + + Sortable/ + lib/ + Doctrine/ + Template/ + Listener/ + Sortable.php + Sortable.php + tests/ + run.php + Template/ + SortableTestCase.php + +You can even run the tests that come bundled with it. We just need to tell your +CLI where your Doctrine code is. + + $ export DOCTRINE_DIR=/path/to/doctrine + +> **NOTE** +> The above path to Doctrine must be the path to the main folder, not just the +> lib folder. In order to run the tests it must have access to the `tests` +> directory included with Doctrine. + +Now you can run the tests included. + + $ cd /path/to/extensions/Sortable/tests + $ php run.php + +It should output something like the following. + + Doctrine Unit Tests + =================== + Doctrine_Template_Sortable_TestCase.............................................passed + + Tested: 1 test cases. + Successes: 26 passes. + Failures: 0 fails. + Number of new Failures: 0 + Number of fixed Failures: 0 + + Tests ran in 1 seconds and used 13024.9414062 KB of memory + +Now if you want to use the extension in your project you will need register the +extension with Doctrine and setup the extension autoloading mechanism. + +First lets setup the extension autoloading. + + [php] + spl_autoload_register(array('Doctrine', 'extensionsAutoload')); + +Now you can register the extension and the classes inside that extension will be +autoloaded. + + [php] + $manager->registerExtension('Sortable'); + +> **NOTE** +> If you need to register an extension from a different location you can specify +> the full path to the extension directory as the second argument to the +> `registerExtension()` method. + +## Generator Cascading Delete Configuration + +It is now possible to configure the cascading delete operation of a +`Doctrine_Record_Generator`. For example you can now configure the `I18n` +behavior to use app level cascade deletes instead of database level. + + [yml] + Article: + actAs: + I18n: + fields: [title, body] + appLevelDelete: true + columns: + title: string(255) + body: clob + +You can also completely disable cascading deletes by using the `cascadeDelete` +option and setting it to `false.` + +## Column Aggregation Key Column + +The column aggregation key column is now automatically indexed. + + [yml] + User: + tableName: users + columns: + username: string(255) + password: string(255) + + Employee: + inheritance: + extends: User + type: column_aggregation + +The above schema would add a `type` column to the `User` model. This is a flag +tell Doctrine which subclass each record in the database belongs to. This column +is now automatically indexed where before it was not. + + [sql] + CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR(255), password VARCHAR(255), type VARCHAR(255)); + CREATE INDEX type_idx ON users (type); + +## On Demand Hydration + +You can now utilize a new hydration mode which utilizes much less memory. It only +hydrates one object in to memory at a time. So it uses less memory and is faster +for larger results. + + [php] + // Returns instance of Doctrine_Collection_OnDemand + $result = $q->execute(array(), Doctrine_Core::HYDRATE_ON_DEMAND); + foreach ($result as $obj) { + // ... + } + +`Doctrine_Collection_OnDemand` hydrates each object one at a time as you iterate +over it. + +## Aggregate Values Hydration + +Now aggregate/calculated values can only be found in the root component of your +queries. Previously they could be found in both the root component and the +relationship. This causes lots of problems, for example this query. + + [php] + $master = Doctrine_Query::create() + ->select('m.*, s.bar AS joe') + ->from('Ticket_DC24_Master m') + ->innerJoin('m.Ticket_DC24_Servant s') + ->where('m.id = 1') + ->fetchOne(); + +This produces a data structure like this. + + Array + ( + [id] => 1 + [foo] => 6 + [servant_id] => + [Ticket_DC24_Servant] => Array + ( + [id] => + [bar] => + [joe] => 6 + ) + + [joe] => 6 + ) + +Now we have a blank `Ticket_DC24_Servant` instance and if we were to try and call +`save()` like below we would get an error. + + [php] + $master->some_field = 'test'; + $master->save(); + +Now as of 1.2 the structure will only look like this. + + Array + ( + [id] => 1 + [foo] => 6 + [servant_id] => 1 + [joe] => 6 + ) + +## PEAR Style Model Loading and Generation + +Doctrine 1.2 now has the ability to generate PEAR style naming conventions for your +models and can autoload them. + +First we have a new method for setting the path to our models for the autoloader. + + [php] + Doctrine_Core::setModelsDirectory('/path/to/my/models'); + +Make sure you have registered the `modelsAutoload()` method: + + [php] + spl_autoload_register(array('Doctrine', 'modelsAutoload')); + +Now when you ask for a class named `My_Test_Model` it will try and autoload it +from `/path/to/my/models/My/Test/Model.php`. + +So now you can autoload PEAR style models, but what about generating them? For this +we had to add a new option to the model builder called `pearStyle`. When this option +is enabled it will string replace any `_` in the path to the file and replace it with the directory +separator `/` right before creating the directories and writing the file. + +Here I'll show an example how you can use the options to convert this schema and +what it would result in. + + [yml] + Article: + columns: + title: string(255) + content: clob + + Article_Category: + columns: + name: string(255) + +Now if we configure a schema importer like the following. + + [php] + $import = new Doctrine_Import_Schema(); + $import->setOptions(array( + 'pearStyle' => true, + 'baseClassesDirectory' => null, + 'baseClassPrefix' => 'Base_', + 'classPrefix' => 'MyProject_Models_', + 'classPrefixFiles' => true + )); + $import->importSchema('schema.yml', 'yml', 'lib'); + +This will result in some files and directories like the following. + + lib/ + MyProject/ + Models/ + Article/ + Category.php + Article.php + Base/ + Article/ + Category.php + Article.php + +So now you can easily use our autoloader or your own to load our models with the +PEAR style naming convention. + + [php] + spl_autoload_register(array('Doctrine', 'autoload')); + Doctrine_Core::setModelsDirectory('lib'); + +Now if we use this code. + + [php] + $article = MyProject_Models_Article(); + +It will autoload the file from `lib/MyProject/Models/Article.php` + +## Customizing Column Validators + +Often when you generate models from a database, you want to customize and improve +your models by overriding the `setTableDefinition()` and tweaking things. To make +this easier we added a new method to customize column options but not completely +override it. + + [php] + class User extends BaseUser + { + public function setTableDefinition() + { + parent::setTableDefinition(); + + $this->setColumnOptions('username', array('unique' => true)); + } + } + +## Resetting Manager Instances + +Sometimes when performing unit tests using Doctrine, you will want to reset +the static manager instance held in `Doctrine_Manager`. + +We've added a static method `resetInstance()` and a public method `reset()` +to help you with this. + + [php] + $manager1 = Doctrine_Manager::getInstance(); + Doctrine_Manager::resetInstance(); + $manager2 = Doctrine_Manager::getInstance(); + + // $manager1 !== $manager2 + +You can also simply reset an instance back to the state when it was first created. + + [php] + $manager->reset(); + +## Registering Custom CLI Tasks + +Thanks to Dan Bettles, he contributed some refactorings to the Doctrine 1 CLI +to allow us to register custom tasks with the `registerTask()` method. + + [php] + $cli = new Doctrine_Cli($config); + $cli->registerTask('/path/to/MyCustomTask', 'my-task'); + $cli->run($_SERVER['argv']); + +Now you can execute: + + $ php doctrine my-task + +Be sure to define the class like this. + + [php] + class MyCustomTask extends Doctrine_Task + { + public $description = 'My custom task', + $requiredArguments = array('arg1' => 'Required first argument.'), + $optionalArguments = array('arg2' => 'Optional second argument.'); + + public function execute() + { + $arg1 = $this->getArgument('arg1'); + $arg2 = $this->getArgument('arg2'); + } + } + +## Doctrine Nested Set Hierarchy Structure + +When working with the `NestedSet` behavior in Doctrine 1.2 it has some very nice +features that make working with hierarchical data very easy. One of the things +it has always missed is a way to hydrate that data in to a hierarchical structure. +With 1.2 this is now possible with some new hydration types. + + [php] + $categories = Doctrine_Core::getTable('Category') + ->createQuery('c') + ->execute(array(), Doctrine_Core::HYDRATE_RECORD_HIERARCHY); + +Now you can access the children of a record by accessing the mapped value property +named `__children`. It is named with the underscores prefixed to avoid any conflicts. + + [php] + foreach ($categories->getFirst()->get('__children') as $child) { + // ... + } + +You can also execute this structure using array hydration and get back the same +structure except as an array. + + [php] + $results = Doctrine_Core::getTable('NestedSetTest_SingleRootNode') + ->createQuery('n') + ->execute(array(), Doctrine_Core::HYDRATE_ARRAY_HIERARCHY); + +If you have an existing `Doctrine_Colletion` instance you can convert that to a +hierarchy as well. + + [php] + $hierarchy = $coll->toHierarchy(); + +The hierarchy a collection can be converted to an array as well. + + [php] + print_r($hierarchy->toArray()); + +## Moved Doctrine to Doctrine_Core + +For integration purposes we have deprecated the `Doctrine` class and moved it to +`Doctrine_Core`. The old class still exists and extends `Doctrine_Core` for BC. + +## Specify Relationship Foreign Key Name + +Up until now, Doctrine would always try and generate a foreign key name for you +for your relationships. Sometimes you may want to customize this name or Doctrine +generates a name that is too long for you. You can customize the foreign key name +now with the `foreignKeyName` option. + + [php] + public function setUp() + { + $this->hasOne('User', array( + 'local' => 'user_id', + 'foreign' => 'id', + 'foreignKeyName' => 'user_id_fk' + )); + } + +Or in YAML you can do the following. + + [yml] + Profile: + columns: + # ... + user_id: integer + relations: + User: + foreignKeyName: user_id_fk + +## Sluggable Provider Option + +You can now use a provider option to the `Sluggable` behavior so you can customize +the PHP code that is used to generate a slug for a record. + + [yml] + Article: + # ... + actAs: + Sluggable: + provider: [MyClass, provideSlug] + +Now you must have some PHP code like this. + + [php] + class MyClass + { + public static function provideSlug(Doctrine_Record $record) + { + // return something + } + } + +## Migrations Primary Key Convenience Methods + +To ease the process of creating and dropping primary keys in Doctrine when using +migrations we've implemented two convenience methods named `createPrimaryKey()` +and `dropPrimaryKey()`. + +You can use create primary keys like the following. + + [php] + $columns = array( + 'id' => array( + 'type' => 'integer', + 'autoincrement' => true + ) + ); + $this->createPrimaryKey('my_table', $columns); + +If you want to drop the primary key you can do the following. + + [php] + $this->dropPrimaryKey('my_table', array('id')); + +You can also use the automation helper with these methods. + + [php] + class MyMigration extends Doctrine_Migration_Base + { + public function migrate($direction) + { + $columns = array( + 'id' => array( + 'type' => 'integer', + 'autoincrement' => true + ) + ); + $this->primaryKey('my_table', $columns); + } + } + +The above migration will create the primary key when migrating up and drop it when +migrating down. + +## Fixed changeColumn() Argument Order in Migrations + +Previously the order of `changeColumn()` was not in the order you would expect. + + [php] + public function changeColumn($tableName, $columnName, $length = null, $type = null, array $options = array()) + +Notice how the `$length` is before `$type`. Everywhere else in Doctrine that's +how it is. So for this version we have fixed that. + + [php] + public function changeColumn($tableName, $columnName, $type = null, $length = null, array $options = array()) + +## Ordering Relationships + +It is now possible to set a default order by for your relationships. The order by +is automatically included in the final SQL when writing DQL queries or lazily +fetching relationships. + + [yml] + User: + columns: + username: string(255) + password: string(255) + relations: + Articles: + class: Article + local: id + foreign: user_id + type: many + foreignType: one + orderBy: title ASC + + Article: + columns: + title: string(255) + content: clob + user_id: integer + +Now if we were to do the following PHP we'll get the SQL with an order by. + + [php] + $q = Doctrine::getTable('User') + ->createQuery('u') + ->leftJoin('u.Articles a'); + + echo $q->getSqlQuery() . "\n\n"; + +Now you should see this SQL query. + + [sql] + SELECT u.id AS u__id, u.username AS u__username, u.password AS u__password, a.id AS a__id, a.title AS a__title, a.content AS a__content, a.user_id AS a__user_id FROM user u LEFT JOIN article a ON u.id = a.user_id ORDER BY a.title ASC + +Or if you lazily fetch the `Articles` they will be lazily loaded with the order by. + + [php] + $user = Doctrine::getTable('User')->find(1); + $articles = $user->Articles; + +This would execute the following SQL query. + + [sql] + SELECT a.id AS a__id, a.title AS a__title, a.content AS a__content, a.user_id AS a__user_id FROM article a WHERE (a.user_id IN (?)) ORDER BY a.title ASC + +You can also specify the default order by for a model itself instead of on the relationship. + + [yml] + Article: + options: + orderBy: title ASC + columns: + title: string(255) + +Now any query involving the `Article` model will have that order by. + +## Result Cache Improvements + +In Doctrine when you use result caching, it stores the results of a query in the +cache driver the first time it executes and retrieves it from the cache for all +subsequent requests. The key for this cache entry in the driver is automatically +generated so it is hard for you to identify a single entry and clear it manually. + +In Doctrine 1.2 we added the ability to set the result cache hash/key used. + + [php] + $q = Doctrine_Query::create() + ->from('User u') + ->useResultCache(true, 3600, 'user_list'); + +If you want to manually clear the item from the query object you can do. + + [php] + $q->clearResultCache(); + +Or if you have the cache driver you could delete it by the key. + + [php] + $cacheDriver->delete('user_list'); + +You can also use the `setResultCacheHash()` to set the key used to store the cache +entry. + + [php] + $q = Doctrine_Query::create() + ->from('User u') + ->useResultCache(true, 3600); + + $q->setResultCacheHash('user_list'); + +You can also now delete cache entries from the cache drivers using PHP regular +expressions. + + [php] + $cacheDriver = new Doctrine_Cache_Apc(); + + $cacheDriver->save('my_cache_one'); + $cacheDriver->save('my_cache_two'); + $cacheDriver->save('my_cache_three'); + + echo $cacheDriver->deleteByRegex('/my_cache_.*/'); // 3 + +If you're not a regular expression master and just want to simply delete with +some wild cards then you can use the `*` character with the normal `delete()` +method and we'll build the regular expression for you and call `deleteByRegex()`. + + [php] + echo $cacheDriver->delete('my_cache_*'); + +Since `preg_match()` is pretty slow the above example would not perform well +with lots of cache keys to compare to the regular expression so you can +alternatively use the `deleteByPrefix()` and `deleteBySuffix()` method if +that is sufficient enough for you. + + [php] + echo $cacheDriver->deleteByPrefix('my_cache_'); + +## BLOB and File Handle Resources + +It is now possible to provide the contents for a blob column through a file +handle resource. + + [php] + $file = new File(); + $file->binary_data = file('/path/to/file'); + $file->save(); + +## Symfony sfYaml External + +Doctrine is now using the Symfony Component `sfYaml` for our YAML parsing as an +SVN external. So it will always be up to date and receive bug fixes from Symfony. + +## Better replace() Support + +The `Doctrine_Record::replace()` had a lot of issues previously as it did not +behave the same as if you were to call `save()`, `update()`, or `insert()`. +Now when you call `replace()` all the same events will be triggered and the +saving of the graph will be triggered just as if you were using `save()`. + + [php] + $user = new User(); + $user->username = 'jonwage'; + $user->password = 'changeme2'; + $user->replace(); + +## Added hardDelete() method to SoftDelete + +Something missing from the `SoftDelete` behavior was the ability to force the +deletion of a record in the database. For this we have added a new `hardDelete()` +method. + + [php] + $user = new User(); + $user->username = 'jwage'; + $user->password = 'changeme'; + $user->save(); + $user->delete() // Doesn't actually delete, sets deleted_at flag + + $user->hardDelete(); // Will actually delete the record from the database. + +## Added MySQL SET Support + +Just like the `enum` type for MySQL we also now support the `set` type. It basically +very similar to `enum` but instead of being able to store only one value you can +store multiple of the possible values. + + [yml] + User: + columns: + username: string(255) + password: string(255) + permissions: + type: set + values: [admin, member, moderator, banned] + +Now you can do the following: + + [php] + $user = new User(); + $user->username = 'jwage'; + $user->password = 'changeme'; + $user->permissions = array('admin', 'member'); + +## Models Autoloading + +In Doctrine 1.2 the models autoloading was moved to a custom autoloader for more +flexibility and not forcing the models autoloading on users if they don't want to +use it. If you still wish to use the Doctrine model autoloading then you must +use the following code: + + [php] + spl_autoload_register(array('Doctrine_Core', 'modelsAutoload')); \ No newline at end of file diff --git a/lib/vendor/lexpress/doctrine1/build.properties.dev b/lib/vendor/lexpress/doctrine1/build.properties.dev new file mode 100644 index 0000000..e7f7082 --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/build.properties.dev @@ -0,0 +1,11 @@ +version=1.2.3 +stability=stable +build.dir=build +dist.dir=dist +report.dir=reports +log.archive.dir=logs +test.phpunit_configuration_file= +test.phpunit_generate_coverage=0 +test.pmd_reports=0 +test.pdepend_exec= +test.phpmd_exec= \ No newline at end of file diff --git a/lib/vendor/lexpress/doctrine1/build.xml b/lib/vendor/lexpress/doctrine1/build.xml new file mode 100644 index 0000000..5ff0aea --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/build.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Doctrine + PHP5 Database ORM + pear.doctrine-project.org + +Doctrine is an ORM (object relational mapper) for PHP 5.2.x+ that sits on top of +a powerful DBAL (database abstraction layer). One of its key features is the +ability to optionally write database queries in an OO (object oriented) +SQL-dialect called DQL inspired by Hibernates HQL. This provides developers with +a powerful alternative to SQL that maintains a maximum of flexibility without +requiring needless code duplication. + + + LGPL + + + - + + + + + + + + + \ No newline at end of file diff --git a/lib/vendor/lexpress/doctrine1/composer.json b/lib/vendor/lexpress/doctrine1/composer.json new file mode 100644 index 0000000..9471daa --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/composer.json @@ -0,0 +1,41 @@ +{ + "name": "friendsofsymfony1/doctrine1", + "type": "library", + "description": "PHP Database ORM for Symfony1. Do NOT use for new projects: please move to a newest Symfony release and Doctrine2", + "keywords": ["orm", "database", "symfony1", "doctrine1"], + "homepage": "http://www.doctrine-project.org", + "license": "LGPL-2.1-or-later", + "authors": [ + { + "name": "Konsta Vesterinen", + "email": "kvesteri@cc.hut.fi" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Doctrine1 Contributors", + "homepage": "https://github.com/FriendsOfSymfony1/doctrine1/graphs/contributors" + } + ], + "require": { + "php": ">=5.3", + "ext-mbstring": "*", + "ext-pdo": "*" + }, + "support": { + "issues": "https://github.com/FriendsOfSymfony1/doctrine1/issues", + "source": "https://github.com/FriendsOfSymfony1/doctrine1" + }, + "autoload": { + "psr-0": { + "Doctrine_": "lib/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + } +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Access.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Access.php similarity index 95% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Access.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Access.php index 9a0db8d..572ff7f 100644 --- a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Access.php +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Access.php @@ -114,6 +114,12 @@ public function offsetExists($offset) */ public function offsetGet($offset) { + // array notation with no index was causing 'undefined variable: $offset' notices in php7, + // for example: + // $record->Relations[]->name = 'test'; + if (!isset($offset)) { + return $this->get(null); + } return $this->get($offset); } diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Exception.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Interface.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Interface.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Interface.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Interface.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Mock.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Mock.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Mock.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Mock.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Oracle.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Oracle.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Oracle.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Oracle.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Statement.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Statement.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement/Interface.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Statement/Interface.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement/Interface.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Statement/Interface.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement/Mock.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Statement/Mock.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement/Mock.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Statement/Mock.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Statement/Oracle.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Statement/Oracle.php new file mode 100644 index 0000000..0198f78 --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Adapter/Statement/Oracle.php @@ -0,0 +1,600 @@ +. + */ + +/** + * Oracle connection adapter statement class. + * + * @package Doctrine + * @subpackage Adapter + * @author Konsta Vesterinen + * @author vadik56 + * @author Miloslav Kmet + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 1.0 + * @version $Rev$ + */ +class Doctrine_Adapter_Statement_Oracle implements Doctrine_Adapter_Statement_Interface +{ + /** + * @var string $queryString actual query string + */ + public $queryString; + + /** + * @var resource $connection OCI connection handler + */ + protected $connection; + + /** + * @var resource $statement OCI prepared statement + */ + protected $statement; + + /** + * @var integer $executeMode OCI statement execution mode + */ + protected $executeMode = OCI_COMMIT_ON_SUCCESS; + + /** + * @var array $bindParams Array of parameters bounded to a statement + */ + protected $bindParams = array(); + + /** + * @var array $attributes Array of attributes + */ + protected $attributes = array(); + + /** + * @var array $ociErrors Array of errors + */ + protected $ociErrors = array(); + + /** + * the constructor + * + * @param Doctrine_Adapter_Oracle $connection + * @param string $query Query string to be executed + * @param integer $executeMode OCI execute mode + */ + public function __construct( Doctrine_Adapter_Oracle $connection, $query, $executeMode) + { + $this->connection = $connection->getConnection(); + $this->queryString = $query; + $this->executeMode = $executeMode; + $this->attributes[Doctrine_Core::ATTR_ERRMODE] = $connection->getAttribute(Doctrine_Core::ATTR_ERRMODE); + + $this->parseQuery(); + } + + /** + * Bind a column to a PHP variable + * + * @param mixed $column Number of the column (1-indexed) or name of the column in the result set. + * If using the column name, be aware that the name should match + * the case of the column, as returned by the driver. + * @param string $param Name of the PHP variable to which the column will be bound. + * @param integer $type Data type of the parameter, specified by the Doctrine_Core::PARAM_* constants. + * @return boolean Returns TRUE on success or FALSE on failure + */ + public function bindColumn($column, $param, $type = null) + { + throw new Doctrine_Adapter_Exception("Unsupported"); + } + + /** + * Binds a value to a corresponding named or question mark + * placeholder in the SQL statement that was use to prepare the statement. + * + * @param mixed $param Parameter identifier. For a prepared statement using named placeholders, + * this will be a parameter name of the form :name. For a prepared statement + * using question mark placeholders, this will be the 1-indexed position of the parameter + * + * @param mixed $value The value to bind to the parameter. + * @param integer $type Explicit data type for the parameter using the Doctrine_Core::PARAM_* constants. + * + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function bindValue($param, $value, $type = null) + { + /** + * need to store the value internally since binding is done by reference + */ + $this->bindParams[] = $value; + $this->bindParam($param, $this->bindParams[count($this->bindParams) - 1], $type); + } + + /** + * Binds a PHP variable to a corresponding named or question mark placeholder in the + * SQL statement that was use to prepare the statement. Unlike Doctrine_Adapter_Statement_Interface->bindValue(), + * the variable is bound as a reference and will only be evaluated at the time + * that Doctrine_Adapter_Statement_Interface->execute() is called. + * + * Most parameters are input parameters, that is, parameters that are + * used in a read-only fashion to build up the query. Some drivers support the invocation + * of stored procedures that return data as output parameters, and some also as input/output + * parameters that both send in data and are updated to receive it. + * + * @param mixed $param Parameter identifier. For a prepared statement using named placeholders, + * this will be a parameter name of the form :name. For a prepared statement + * using question mark placeholders, this will be the 1-indexed position of the parameter + * + * @param mixed $variable Name of the PHP variable to bind to the SQL statement parameter. + * + * @param integer $type Explicit data type for the parameter using the Doctrine_Core::PARAM_* constants. To return + * an INOUT parameter from a stored procedure, use the bitwise OR operator to set the + * Doctrine_Core::PARAM_INPUT_OUTPUT bits for the data_type parameter. + * + * @param integer $length Length of the data type. To indicate that a parameter is an OUT parameter + * from a stored procedure, you must explicitly set the length. + * @param mixed $driverOptions + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function bindParam($column, &$variable, $type = null, $length = null, $driverOptions = array()) + { + if ($driverOptions || $length ) { + throw new Doctrine_Adapter_Exception('Unsupported parameters:$length, $driverOptions'); + } + + if ($length === null) { + $oci_length = -1; + } + $oci_type = SQLT_CHR; + + switch ($type) { + case Doctrine_Core::PARAM_STR: + $oci_type = SQLT_CHR; + break; + } + + if (is_integer($column)) { + $variable_name = ":oci_b_var_$column"; + } else { + $variable_name = $column; + } + //print "Binding $variable to $variable_name".PHP_EOL; + $status = @oci_bind_by_name($this->statement, $variable_name, $variable, $oci_length, $oci_type); + if ($status === false) { + $this->handleError(); + } + return $status; + } + + /** + * Closes the cursor, enabling the statement to be executed again. + * + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function closeCursor() + { + $this->bindParams = array(); + if (is_resource($this->statement)) { + return oci_free_statement($this->statement); + } + return true; + } + + /** + * Returns the number of columns in the result set + * + * @return integer Returns the number of columns in the result set represented + * by the Doctrine_Adapter_Statement_Interface object. If there is no result set, + * this method should return 0. + */ + public function columnCount() + { + return oci_num_fields ( $this->statement ); + } + + /** + * Fetch the SQLSTATE associated with the last operation on the statement handle + * + * @see Doctrine_Adapter_Interface::errorCode() + * @return string error code string + */ + public function errorCode() + { + $oci_error = $this->getOciError(); + return $oci_error['code']; + } + + /** + * Fetch extended error information associated with the last operation on the statement handle + * + * @see Doctrine_Adapter_Interface::errorInfo() + * @return array error info array + */ + public function errorInfo() + { + $oci_error = $this->getOciError(); + return $oci_error['message'] . " : " . $oci_error['sqltext']; + } + + private function getOciError() + { + if (is_resource($this->statement)) { + $oci_error = oci_error ($this->statement); + } else { + $oci_error = oci_error (); + } + + if ($oci_error) { + //store the error + $this->oci_errors[] = $oci_error; + } else if (count($this->ociErrors) > 0) { + $oci_error = $this->ociErrors[count($this->ociErrors)-1]; + } + return $oci_error; + } + + /** + * Executes a prepared statement + * + * If the prepared statement included parameter markers, you must either: + * call PDOStatement->bindParam() to bind PHP variables to the parameter markers: + * bound variables pass their value as input and receive the output value, + * if any, of their associated parameter markers or pass an array of input-only + * parameter values + * + * + * @param array $params An array of values with as many elements as there are + * bound parameters in the SQL statement being executed. + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function execute($params = null) + { + if (is_array($params)) { + foreach ($params as $var => $value) { + $this->bindValue($var+1, $value); + } + } + + $result = @oci_execute($this->statement , $this->executeMode ); + + if ($result === false) { + $this->handleError(); + return false; + } + return true; + } + + /** + * fetch + * + * @see Doctrine_Core::FETCH_* constants + * @param integer $fetchStyle Controls how the next row will be returned to the caller. + * This value must be one of the Doctrine_Core::FETCH_* constants, + * defaulting to Doctrine_Core::FETCH_BOTH + * + * @param integer $cursorOrientation For a PDOStatement object representing a scrollable cursor, + * this value determines which row will be returned to the caller. + * This value must be one of the Doctrine_Core::FETCH_ORI_* constants, defaulting to + * Doctrine_Core::FETCH_ORI_NEXT. To request a scrollable cursor for your + * Doctrine_Adapter_Statement_Interface object, + * you must set the Doctrine_Core::ATTR_CURSOR attribute to Doctrine_Core::CURSOR_SCROLL when you + * prepare the SQL statement with Doctrine_Adapter_Interface->prepare(). + * + * @param integer $cursorOffset For a Doctrine_Adapter_Statement_Interface object representing a scrollable cursor for which the + * $cursorOrientation parameter is set to Doctrine_Core::FETCH_ORI_ABS, this value specifies + * the absolute number of the row in the result set that shall be fetched. + * + * For a Doctrine_Adapter_Statement_Interface object representing a scrollable cursor for + * which the $cursorOrientation parameter is set to Doctrine_Core::FETCH_ORI_REL, this value + * specifies the row to fetch relative to the cursor position before + * Doctrine_Adapter_Statement_Interface->fetch() was called. + * + * @return mixed + */ + public function fetch($fetchStyle = Doctrine_Core::FETCH_BOTH, $cursorOrientation = Doctrine_Core::FETCH_ORI_NEXT, $cursorOffset = null) + { + switch ($fetchStyle) { + case Doctrine_Core::FETCH_BOTH : + return oci_fetch_array($this->statement, OCI_BOTH + OCI_RETURN_NULLS + OCI_RETURN_LOBS); + break; + case Doctrine_Core::FETCH_ASSOC : + return oci_fetch_array($this->statement, OCI_ASSOC + OCI_RETURN_NULLS + OCI_RETURN_LOBS); + break; + case Doctrine_Core::FETCH_NUM : + return oci_fetch_array($this->statement, OCI_NUM + OCI_RETURN_NULLS + OCI_RETURN_LOBS); + break; + case Doctrine_Core::FETCH_OBJ: + return oci_fetch_object($this->statement, OCI_NUM + OCI_RETURN_NULLS + OCI_RETURN_LOBS); + break; + default: + throw new Doctrine_Adapter_Exception("This type of fetch is not supported: ".$fetchStyle); +/* + case Doctrine_Core::FETCH_BOUND: + case Doctrine_Core::FETCH_CLASS: + case FETCH_CLASSTYPE: + case FETCH_COLUMN: + case FETCH_FUNC: + case FETCH_GROUP: + case FETCH_INTO: + case FETCH_LAZY: + case FETCH_NAMED: + case FETCH_SERIALIZE: + case FETCH_UNIQUE: + case FETCH_ORI_ABS: + case FETCH_ORI_FIRST: + case FETCH_ORI_LAST: + case FETCH_ORI_NEXT: + case FETCH_ORI_PRIOR: + case FETCH_ORI_REL: +*/ + } + } + + /** + * Returns an array containing all of the result set rows + * + * @param integer $fetchStyle Controls how the next row will be returned to the caller. + * This value must be one of the Doctrine_Core::FETCH_* constants, + * defaulting to Doctrine_Core::FETCH_BOTH + * + * @param integer $columnIndex Returns the indicated 0-indexed column when the value of $fetchStyle is + * Doctrine_Core::FETCH_COLUMN. Defaults to 0. + * + * @return array + */ + public function fetchAll($fetchStyle = Doctrine_Core::FETCH_BOTH, $colnum=0) + { + $fetchColumn = false; + $skip = 0; + $maxrows = -1; + $data = array(); + $flags = OCI_FETCHSTATEMENT_BY_ROW + OCI_ASSOC; + + $int = $fetchStyle & Doctrine_Core::FETCH_COLUMN; + + if ($fetchStyle == Doctrine_Core::FETCH_BOTH) { + $flags = OCI_BOTH; + $numberOfRows = @oci_fetch_all($this->statement, $data, $skip, $maxrows, OCI_FETCHSTATEMENT_BY_ROW + OCI_ASSOC + OCI_RETURN_LOBS); + } else if ($fetchStyle == Doctrine_Core::FETCH_ASSOC) { + $numberOfRows = @oci_fetch_all($this->statement, $data, $skip, $maxrows, OCI_FETCHSTATEMENT_BY_ROW + OCI_ASSOC + OCI_RETURN_LOBS); + } else if ($fetchStyle == Doctrine_Core::FETCH_NUM) { + $numberOfRows = @oci_fetch_all($this->statement, $data, $skip, $maxrows, OCI_FETCHSTATEMENT_BY_ROW + OCI_NUM + OCI_RETURN_LOBS); + } else if ($fetchStyle == Doctrine_Core::FETCH_COLUMN) { + while ($row = @oci_fetch_array ($this->statement, OCI_NUM+OCI_RETURN_LOBS)) { + $data[] = $row[$colnum]; + } + } else { + throw new Doctrine_Adapter_Exception("Unsupported mode: '" . $fetchStyle . "' "); + } + + return $data; + } + + /** + * Returns a single column from the next row of a + * result set or FALSE if there are no more rows. + * + * @param integer $columnIndex 0-indexed number of the column you wish to retrieve from the row. If no + * value is supplied, Doctrine_Adapter_Statement_Interface->fetchColumn() + * fetches the first column. + * + * @return string returns a single column in the next row of a result set. + */ + public function fetchColumn($columnIndex = 0) + { + if ( ! is_integer($columnIndex)) { + $this->handleError(array('message'=>"columnIndex parameter should be numeric")); + + return false; + } + $row = $this->fetch(Doctrine_Core::FETCH_NUM); + return isset($row[$columnIndex]) ? $row[$columnIndex] : false; + } + + /** + * Fetches the next row and returns it as an object. + * + * Fetches the next row and returns it as an object. This function is an alternative to + * Doctrine_Adapter_Statement_Interface->fetch() with Doctrine_Core::FETCH_CLASS or Doctrine_Core::FETCH_OBJ style. + * + * @param string $className Name of the created class, defaults to stdClass. + * @param array $args Elements of this array are passed to the constructor. + * + * @return mixed an instance of the required class with property names that correspond + * to the column names or FALSE in case of an error. + */ + public function fetchObject($className = 'stdClass', $args = array()) + { + $row = $this->fetch(Doctrine_Core::FETCH_ASSOC); + if ($row === false) { + return false; + } + + $instantiation_code = "\$object = new $className("; + $firstParam=true; + foreach ($args as $index=>$value) { + if ( ! $firstParam ) { + $instantiation_code = $instantiation_code . ","; + } else { + $firstParam= false; + } + if ( is_string($index)) { + $instantiation_code = $instantiation_code . " \$args['$index']"; + } else { + $instantiation_code = $instantiation_code . "\$args[$index]"; + } + } + + $instantiation_code = $instantiation_code . ");"; + + eval($instantiation_code); + + //initialize instance of $className class + foreach ($row as $col => $value) { + $object->$col = $value; + } + + return $object; + } + + /** + * Returns metadata for a column in a result set + * + * @param integer $column The 0-indexed column in the result set. + * + * @return array Associative meta data array with the following structure: + * + * native_type The PHP native type used to represent the column value. + * driver:decl_ type The SQL type used to represent the column value in the database. If the column in the result set is the result of a function, this value is not returned by PDOStatement->getColumnMeta(). + * flags Any flags set for this column. + * name The name of this column as returned by the database. + * len The length of this column. Normally -1 for types other than floating point decimals. + * precision The numeric precision of this column. Normally 0 for types other than floating point decimals. + * pdo_type The type of this column as represented by the PDO::PARAM_* constants. + */ + public function getColumnMeta($column) + { + if (is_integer($column)) { + $internal_column = $column +1; + } else { + $internal_column = $column; + } + + $data = array(); + $data['native_type'] = oci_field_type($this->statement, $internal_column); + $data['flags'] = ""; + $data['len'] = oci_field_size($this->statement, $internal_column); + $data['name'] = oci_field_name($this->statement, $internal_column); + $data['precision'] = oci_field_precision($this->statement, $internal_column); + + return $data; + } + + /** + * Advances to the next rowset in a multi-rowset statement handle + * + * Some database servers support stored procedures that return more than one rowset + * (also known as a result set). The nextRowset() method enables you to access the second + * and subsequent rowsets associated with a PDOStatement object. Each rowset can have a + * different set of columns from the preceding rowset. + * + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function nextRowset() + { + throw new Doctrine_Adapter_Exception("Unsupported"); + } + + /** + * rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement + * executed by the corresponding object. + * + * If the last SQL statement executed by the associated Statement object was a SELECT statement, + * some databases may return the number of rows returned by that statement. However, + * this behaviour is not guaranteed for all databases and should not be + * relied on for portable applications. + * + * @return integer Returns the number of rows. + */ + public function rowCount() + { + return @oci_num_rows($this->statement); + } + + /** + * Set a statement attribute + * + * @param integer $attribute + * @param mixed $value the value of given attribute + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function setAttribute($attribute, $value) + { + switch ($attribute) { + case Doctrine_Core::ATTR_ERRMODE; + break; + default: + throw new Doctrine_Adapter_Exception("Unsupported Attribute: $attribute"); + } + $this->attributes[$attribute] = $value; + } + + /** + * Retrieve a statement attribute + * + * @param integer $attribute + * @see Doctrine_Core::ATTR_* constants + * @return mixed the attribute value + */ + public function getAttribute($attribute) + { + return $this->attributes[$attribute]; + } + + /** + * Set the default fetch mode for this statement + * + * @param integer $mode The fetch mode must be one of the Doctrine_Core::FETCH_* constants. + * @return boolean Returns 1 on success or FALSE on failure. + */ + public function setFetchMode($mode, $arg1 = null, $arg2 = null) + { + throw new Doctrine_Adapter_Exception("Unsupported"); + } + + private function handleError($params=array()) + { + + switch ($this->attributes[Doctrine_Core::ATTR_ERRMODE]) { + case Doctrine_Core::ERRMODE_EXCEPTION: + if (isset($params['message'])) { + throw new Doctrine_Adapter_Exception($params['message']); + } else { + throw new Doctrine_Adapter_Exception($this->errorInfo()); + } + + break; + case Doctrine_Core::ERRMODE_WARNING: + case Doctrine_Core::ERRMODE_SILENT: + break; + } + } + + /** + * Parse actual query from queryString and returns OCI statement handler + * @param string Query string to parse, if NULL, $this->queryString is used + * + * @return resource OCI statement handler + */ + private function parseQuery($query=null) + { + if (is_null($query)) { + $query = $this->queryString; + } + $bind_index = 1; + // Replace ? bind-placeholders with :oci_b_var_ variables + $query = preg_replace_callback("/(\?)/", function($m) use(&$bind_index) { return ":oci_b_var_". $bind_index++; } , $query); + + $this->statement = @oci_parse($this->connection, $query); + + if ( $this->statement == false ) + { + throw new Doctrine_Adapter_Exception($this->getOciError()); + } + + return $this->statement; + } +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/AuditLog.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/AuditLog.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/AuditLog.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/AuditLog.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/AuditLog/Listener.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/AuditLog/Listener.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/AuditLog/Listener.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/AuditLog/Listener.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/AuditLog/Listener/Microtime.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/AuditLog/Listener/Microtime.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/AuditLog/Listener/Microtime.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/AuditLog/Listener/Microtime.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Builder.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Builder.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Builder.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Builder.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Apc.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Apc.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Apc.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Apc.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Array.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Array.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Array.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Array.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Db.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Db.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Db.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Db.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Driver.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Driver.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Driver.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Driver.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Exception.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Interface.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Interface.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Interface.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Interface.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Memcache.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Memcache.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Memcache.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Memcache.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Xcache.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Xcache.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Xcache.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Cache/Xcache.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cli.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cli.php new file mode 100644 index 0000000..f6cd3dd --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cli.php @@ -0,0 +1,679 @@ +. + */ + +/** + * Command line interface class + * + * Interface for easily executing Doctrine_Task classes from a command line interface + * + * @package Doctrine + * @subpackage Cli + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 1.0 + * @version $Revision: 2761 $ + * @author Jonathan H. Wage + */ +class Doctrine_Cli +{ + /** + * The name of the Doctrine Task base class + * + * @var string + */ + const TASK_BASE_CLASS = 'Doctrine_Task'; + + /** + * @var string + */ + protected $_scriptName = null; + + /** + * @var array + */ + private $_config; + + /** + * @var object Doctrine_Cli_Formatter + */ + private $_formatter; + + /** + * An array, keyed on class name, containing task instances + * + * @var array + */ + private $_registeredTask = array(); + + /** + * @var object Doctrine_Task + */ + private $_taskInstance; + + /** + * __construct + * + * @param array [$config=array()] + * @param object|null [$formatter=null] Doctrine_Cli_Formatter + */ + public function __construct(array $config = array(), Doctrine_Cli_Formatter $formatter = null) + { + $this->setConfig($config); + $this->setFormatter($formatter ? $formatter : new Doctrine_Cli_AnsiColorFormatter()); + $this->includeAndRegisterTaskClasses(); + } + + /** + * @param array $config + */ + public function setConfig(array $config) + { + $this->_config = $config; + } + + /** + * @return array + */ + public function getConfig() + { + return $this->_config; + } + + /** + * @param object $formatter Doctrine_Cli_Formatter + */ + public function setFormatter(Doctrine_Cli_Formatter $formatter) + { + $this->_formatter = $formatter; + } + + /** + * @return object Doctrine_Cli_Formatter + */ + public function getFormatter() + { + return $this->_formatter; + } + + /** + * Returns the specified value from the config, or the default value, if specified + * + * @param string $name + * @return mixed + * @throws OutOfBoundsException If the element does not exist in the config + */ + public function getConfigValue($name/*, $defaultValue*/) + { + if (! isset($this->_config[$name])) { + if (func_num_args() > 1) { + return func_get_arg(1); + } + + throw new OutOfBoundsException("The element \"{$name}\" does not exist in the config"); + } + + return $this->_config[$name]; + } + + /** + * Returns TRUE if the element in the config has the specified value, or FALSE otherwise + * + * If $value is not passed, this method will return TRUE if the specified element has _any_ value, or FALSE if the + * element is not set + * + * For strict checking, set $strict to TRUE - the default is FALSE + * + * @param string $name + * @param mixed [$value=null] + * @param bool [$strict=false] + * @return bool + */ + public function hasConfigValue($name, $value = null, $strict = false) + { + if (isset($this->_config[$name])) { + if (func_num_args() < 2) { + return true; + } + + if ($strict) { + return $this->_config[$name] === $value; + } + + return $this->_config[$name] == $value; + } + + return false; + } + + /** + * Sets the array of registered tasks + * + * @param array $registeredTask + */ + public function setRegisteredTasks(array $registeredTask) + { + $this->_registeredTask = $registeredTask; + } + + /** + * Returns an array containing the registered tasks + * + * @return array + */ + public function getRegisteredTasks() + { + return $this->_registeredTask; + } + + /** + * Returns TRUE if the specified Task-class is registered, or FALSE otherwise + * + * @param string $className + * @return bool + */ + public function taskClassIsRegistered($className) + { + return isset($this->_registeredTask[$className]); + } + + /** + * Returns TRUE if a task with the specified name is registered, or FALSE otherwise + * + * If a matching task is found, $className is set with the name of the implementing class + * + * @param string $taskName + * @param string|null [&$className=null] + * @return bool + */ + public function taskNameIsRegistered($taskName, &$className = null) + { + foreach ($this->getRegisteredTasks() as $currClassName => $task) { + if ($task->getTaskName() == $taskName) { + $className = $currClassName; + return true; + } + } + + return false; + } + + /** + * @param object $task Doctrine_Task + */ + public function setTaskInstance(Doctrine_Task $task) + { + $this->_taskInstance = $task; + } + + /** + * @return object Doctrine_Task + */ + public function getTaskInstance() + { + return $this->_taskInstance; + } + + /** + * Called by the constructor, this method includes and registers Doctrine core Tasks and then registers all other + * loaded Task classes + * + * The second round of registering will pick-up loaded custom Tasks. Methods are provided that will allow users to + * register Tasks loaded after creating an instance of Doctrine_Cli. + */ + protected function includeAndRegisterTaskClasses() + { + $this->includeAndRegisterDoctrineTaskClasses(); + + //Always autoregister custom tasks _unless_ we've been explicitly asked not to + if ($this->getConfigValue('autoregister_custom_tasks', true)) { + $this->registerIncludedTaskClasses(); + } + } + + /** + * Includes and registers Doctrine-style tasks from the specified directory / directories + * + * If no directory is given it looks in the default Doctrine/Task folder for the core tasks + * + * @param mixed [$directories=null] Can be a string path or array of paths + */ + protected function includeAndRegisterDoctrineTaskClasses($directories = null) + { + if (is_null($directories)) { + $directories = Doctrine_Core::getPath() . DIRECTORY_SEPARATOR . 'Doctrine' . DIRECTORY_SEPARATOR . 'Task'; + } + + foreach ((array) $directories as $directory) { + foreach ($this->includeDoctrineTaskClasses($directory) as $className) { + $this->registerTaskClass($className); + } + } + } + + /** + * Attempts to include Doctrine-style Task-classes from the specified directory - and nothing more besides + * + * Returns an array containing the names of Task classes included + * + * This method effectively makes two assumptions: + * - The directory contains only _Task_ class-files + * - The class files, and the class in each, follow the Doctrine naming conventions + * + * This means that a file called "Foo.php", say, will be expected to contain a Task class called + * "Doctrine_Task_Foo". Hence the method's name, "include*Doctrine*TaskClasses". + * + * @param string $directory + * @return array $taskClassesIncluded + * @throws InvalidArgumentException If the directory does not exist + */ + protected function includeDoctrineTaskClasses($directory) + { + if (! is_dir($directory)) { + throw new InvalidArgumentException("The directory \"{$directory}\" does not exist"); + } + + $taskClassesIncluded = array(); + + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($directory), + RecursiveIteratorIterator::LEAVES_ONLY + ); + + foreach ($iterator as $file) { + $baseName = $file->getFileName(); + + /* + * Class-files must start with an uppercase letter. This additional check will help prevent us + * accidentally running 'executable' scripts that may be mixed-in with the class files. + */ + $matched = (bool) preg_match('/^([A-Z].*?)\.php$/', $baseName, $matches); + + if ( ! ($matched && (strpos($baseName, '.inc') === false))) { + continue; + } + + $expectedClassName = self::TASK_BASE_CLASS . '_' . $matches[1]; + + if ( ! class_exists($expectedClassName)) { + require_once($file->getPathName()); + } + + //So was the expected class included, and is it a task? If so, we'll let the calling function know. + if (class_exists($expectedClassName, false) && $this->classIsTask($expectedClassName)) { + $taskClassesIncluded[] = $expectedClassName; + } + } + + return $taskClassesIncluded; + } + + /** + * Registers the specified _included_ task-class + * + * @param string $className + * @throws InvalidArgumentException If the class does not exist or the task-name is blank + * @throws DomainException If the class is not a Doctrine Task + */ + public function registerTaskClass($className) + { + //Simply ignore registered classes + if ($this->taskClassIsRegistered($className)) { + return; + } + + if ( ! class_exists($className/*, false*/)) { + throw new InvalidArgumentException("The task class \"{$className}\" does not exist"); + } + + if ( ! $this->classIsTask($className)) { + throw new DomainException("The class \"{$className}\" is not a Doctrine Task"); + } + + $this->_registeredTask[$className] = $this->createTaskInstance($className, $this); + } + + /** + * Returns TRUE if the specified class is a Task, or FALSE otherwise + * + * @param string $className + * @return bool + */ + protected function classIsTask($className) + { + $reflectionClass = new ReflectionClass($className); + return (bool) $reflectionClass->isSubclassOf(self::TASK_BASE_CLASS); + } + + /** + * Creates, and returns, a new instance of the specified Task class + * + * Displays a message, and returns FALSE, if there were problems instantiating the class + * + * @param string $className + * @param object $cli Doctrine_Cli + * @return object Doctrine_Task + */ + protected function createTaskInstance($className, Doctrine_Cli $cli) + { + return new $className($cli); + } + + /** + * Registers all loaded classes - by default - or the specified loaded Task classes + * + * This method will skip registered task classes, so it can be safely called many times over + */ + public function registerIncludedTaskClasses() + { + foreach (get_declared_classes() as $className) { + if ($this->classIsTask($className)) { + $this->registerTaskClass($className); + } + } + } + + /** + * Notify the formatter of a message + * + * @param string $notification The notification message + * @param string $style Style to format the notification with(INFO, ERROR) + * @return void + */ + public function notify($notification = null, $style = 'HEADER') + { + $formatter = $this->getFormatter(); + + echo( + $formatter->format($this->getTaskInstance()->getTaskName(), 'INFO') . ' - ' . + $formatter->format($notification, $style) . "\n" + ); + } + + /** + * Formats, and then returns, the message in the specified exception + * + * @param Exception $exception + * @return string + */ + protected function formatExceptionMessage(Exception $exception) + { + $message = $exception->getMessage(); + + if (Doctrine_Core::debug()) { + $message .= "\n" . $exception->getTraceAsString(); + } + + return $this->getFormatter()->format($message, 'ERROR') . "\n"; + } + + /** + * Notify the formatter of an exception + * + * N.B. This should really only be called by Doctrine_Cli::run(). Exceptions should be thrown when errors occur: + * it's up to Doctrine_Cli::run() to determine how those exceptions are reported. + * + * @param Exception $exception + * @return void + */ + protected function notifyException(Exception $exception) + { + echo $this->formatExceptionMessage($exception); + } + + /** + * Public function to run the loaded task with the passed arguments + * + * @param array $args + * @return void + * @throws Doctrine_Cli_Exception + * @todo Should know more about what we're attempting to run so feedback can be improved. Continue refactoring. + */ + public function run(array $args) + { + try { + $this->_run($args); + } catch (Exception $exception) { + //Do not rethrow exceptions by default + if ($this->getConfigValue('rethrow_exceptions', false)) { + throw new $exception($this->formatExceptionMessage($exception)); + } + + $this->notifyException($exception); + + //User error + if ($exception instanceof Doctrine_Cli_Exception) { + $this->printTasks(); + } + } + } + + /** + * Run the actual task execution with the passed arguments + * + * @param array $args Array of arguments for this task being executed + * @return void + * @throws Doctrine_Cli_Exception If the requested task has not been registered or if required arguments are missing + * @todo Continue refactoring for testing + */ + protected function _run(array $args) + { + $this->_scriptName = $args[0]; + + $requestedTaskName = isset($args[1]) ? $args[1] : null; + + if ( ! $requestedTaskName || $requestedTaskName == 'help') { + $this->printTasks(null, $requestedTaskName == 'help' ? true : false); + return; + } + + if ($requestedTaskName && isset($args[2]) && $args[2] === 'help') { + $this->printTasks($requestedTaskName, true); + return; + } + + if (! $this->taskNameIsRegistered($requestedTaskName, $taskClassName)) { + throw new Doctrine_Cli_Exception("The task \"{$requestedTaskName}\" has not been registered"); + } + + $taskInstance = $this->createTaskInstance($taskClassName, $this); + $this->setTaskInstance($taskInstance); + $this->executeTask($taskInstance, $this->prepareArgs(array_slice($args, 2))); + } + + /** + * Executes the task with the specified _prepared_ arguments + * + * @param object $task Doctrine_Task + * @param array $preparedArguments + * @throws Doctrine_Cli_Exception If required arguments are missing + */ + protected function executeTask(Doctrine_Task $task, array $preparedArguments) + { + $task->setArguments($preparedArguments); + + if (! $task->validate()) { + throw new Doctrine_Cli_Exception('Required arguments missing'); + } + + $task->execute(); + } + + /** + * Prepare the raw arguments for execution. Combines with the required and optional argument + * list in order to determine a complete array of arguments for the task + * + * @param array $args Array of raw arguments + * @return array $prepared Array of prepared arguments + * @todo Continue refactoring for testing + */ + protected function prepareArgs(array $args) + { + $taskInstance = $this->getTaskInstance(); + + $args = array_values($args); + + // First lets load populate an array with all the possible arguments. required and optional + $prepared = array(); + + $requiredArguments = $taskInstance->getRequiredArguments(); + foreach ($requiredArguments as $key => $arg) { + $prepared[$arg] = null; + } + + $optionalArguments = $taskInstance->getOptionalArguments(); + foreach ($optionalArguments as $key => $arg) { + $prepared[$arg] = null; + } + + // If we have a config array then lets try and fill some of the arguments with the config values + foreach ($this->getConfig() as $key => $value) { + if (array_key_exists($key, $prepared)) { + $prepared[$key] = $value; + } + } + + // Now lets fill in the entered arguments to the prepared array + $copy = $args; + foreach ($prepared as $key => $value) { + if ( ! $value && !empty($copy)) { + $prepared[$key] = $copy[0]; + unset($copy[0]); + $copy = array_values($copy); + } + } + + return $prepared; + } + + /** + * Prints an index of all the available tasks in the CLI instance + * + * @param string|null [$taskName=null] + * @param bool [$full=false] + * @todo Continue refactoring for testing + */ + public function printTasks($taskName = null, $full = false) + { + $formatter = $this->getFormatter(); + $config = $this->getConfig(); + + $taskIndex = $formatter->format('Doctrine Command Line Interface', 'HEADER') . "\n\n"; + + foreach ($this->getRegisteredTasks() as $task) { + if ($taskName && (strtolower($taskName) != strtolower($task->getTaskName()))) { + continue; + } + + $taskIndex .= $formatter->format($this->_scriptName . ' ' . $task->getTaskName(), 'INFO'); + + if ($full) { + $taskIndex .= ' - ' . $task->getDescription() . "\n"; + + $args = ''; + $args .= $this->assembleArgumentList($task->getRequiredArgumentsDescriptions(), $config, $formatter); + $args .= $this->assembleArgumentList($task->getOptionalArgumentsDescriptions(), $config, $formatter); + + if ($args) { + $taskIndex .= "\n" . $formatter->format('Arguments:', 'HEADER') . "\n" . $args; + } + } + + $taskIndex .= "\n"; + } + + echo $taskIndex; + } + + /** + * @param array $argumentsDescriptions + * @param array $config + * @param object $formatter Doctrine_Cli_Formatter + * @return string + */ + protected function assembleArgumentList(array $argumentsDescriptions, array $config, Doctrine_Cli_Formatter $formatter) + { + $argumentList = ''; + + foreach ($argumentsDescriptions as $name => $description) { + $argumentList .= $formatter->format($name, 'ERROR') . ' - '; + + if (isset($config[$name])) { + $argumentList .= $formatter->format($config[$name], 'COMMENT'); + } else { + $argumentList .= $description; + } + + $argumentList .= "\n"; + } + + return $argumentList; + } + + /** + * Used by Doctrine_Cli::loadTasks() and Doctrine_Cli::getLoadedTasks() to re-create their pre-refactoring behaviour + * + * @ignore + * @param array $registeredTask + * @return array + */ + private function createOldStyleTaskList(array $registeredTask) + { + $taskNames = array(); + + foreach ($registeredTask as $className => $task) { + $taskName = $task->getTaskName(); + $taskNames[$taskName] = $taskName; + } + + return $taskNames; + } + + /** + * Old method retained for backwards compatibility + * + * @deprecated + */ + public function loadTasks($directory = null) + { + $this->includeAndRegisterDoctrineTaskClasses($directory); + return $this->createOldStyleTaskList($this->getRegisteredTasks()); + } + + /** + * Old method retained for backwards compatibility + * + * @deprecated + */ + protected function _getTaskClassFromArgs(array $args) + { + return self::TASK_BASE_CLASS . '_' . Doctrine_Inflector::classify(str_replace('-', '_', $args[1])); + } + + /** + * Old method retained for backwards compatibility + * + * @deprecated + */ + public function getLoadedTasks() + { + return $this->createOldStyleTaskList($this->getRegisteredTasks()); + } +} \ No newline at end of file diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli/AnsiColorFormatter.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cli/AnsiColorFormatter.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli/AnsiColorFormatter.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Cli/AnsiColorFormatter.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cli/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Cli/Exception.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli/Formatter.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Cli/Formatter.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli/Formatter.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Cli/Formatter.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection.php similarity index 91% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection.php index b0bba35..38b5d85 100644 --- a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection.php +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection.php @@ -1,6 +1,6 @@ */ class Doctrine_Collection extends Doctrine_Access implements Countable, IteratorAggregate, Serializable @@ -137,7 +137,7 @@ public function getTable() * @param array $data * @return Doctrine_Collection */ - public function setData(array $data) + public function setData(array $data) { $this->data = $data; } @@ -152,7 +152,7 @@ public function serialize() $vars = get_object_vars($this); unset($vars['reference']); - unset($vars['reference_field']); + unset($vars['referenceField']); unset($vars['relation']); unset($vars['expandable']); unset($vars['expanded']); @@ -200,7 +200,7 @@ public function unserialize($serialized) public function setKeyColumn($column) { $this->keyColumn = $column; - + return $this; } @@ -264,6 +264,18 @@ public function key() return key($this->data); } + /** + * Sort by key + * + * @return Doctrine_Collection + */ + public function ksort() + { + ksort($this->data); + + return $this; + } + /** * Sets a reference pointer * @@ -274,7 +286,7 @@ public function setReference(Doctrine_Record $record, Doctrine_Relation $relatio $this->reference = $record; $this->relation = $relation; - if ($relation instanceof Doctrine_Relation_ForeignKey || + if ($relation instanceof Doctrine_Relation_ForeignKey || $relation instanceof Doctrine_Relation_LocalKey) { $this->referenceField = $relation->getForeignFieldName(); @@ -330,7 +342,7 @@ public function contains($key) /** * Search a Doctrine_Record instance * - * @param string $Doctrine_Record + * @param string $Doctrine_Record * @return void */ public function search(Doctrine_Record $record) @@ -371,7 +383,7 @@ public function get($key) if ($key === null) { $this->data[] = $record; } else { - $this->data[$key] = $record; + $this->data[$key] = $record; } if (isset($this->keyColumn)) { @@ -459,8 +471,8 @@ public function add($record, $key = null) } $relations = $this->relation['table']->getRelations(); foreach ($relations as $relation) { - if ($this->relation['class'] == $relation['localTable']->getOption('name') && $relation->getLocal() == $this->relation->getForeignFieldName()) { - $record->$relation['alias'] = $this->reference; + if ($this->relation['localTable']->getOption('name') == $relation['class'] && $relation->getLocal() == $this->relation->getForeignFieldName()) { + $record->{$relation['alias']} = $this->reference; break; } } @@ -496,10 +508,10 @@ public function add($record, $key = null) return true; } - + /** * Merges collection into $this and returns merged collection - * + * * @param Doctrine_Collection $coll * @return Doctrine_Collection */ @@ -507,15 +519,15 @@ public function merge(Doctrine_Collection $coll) { $localBase = $this->getTable()->getComponentName(); $otherBase = $coll->getTable()->getComponentName(); - + if ($otherBase != $localBase && !is_subclass_of($otherBase, $localBase) ) { throw new Doctrine_Collection_Exception("Can't merge collections with incompatible record types"); } - + foreach ($coll->getData() as $record) { $this->add($record); } - + return $this; } @@ -655,7 +667,7 @@ public function getNormalIterator() public function takeSnapshot() { $this->_snapshot = $this->data; - + return $this; } @@ -680,7 +692,7 @@ public function getSnapshot() * * @return Doctrine_Collection */ - public function processDiff() + public function processDiff() { foreach (array_udiff($this->_snapshot, $this->data, array($this, "compareRecords")) as $record) { $record->delete(); @@ -698,20 +710,20 @@ public function toArray($deep = true, $prefixKey = false) { $data = array(); foreach ($this as $key => $record) { - + $key = $prefixKey ? get_class($record) . '_' .$key:$key; - + $data[$key] = $record->toArray($deep, $prefixKey); } - + return $data; } /** * Build an array made up of the values from the 2 specified columns * - * @param string $key - * @param string $value + * @param string $key + * @param string $value * @return array $result */ public function toKeyValueArray($key, $value) @@ -728,8 +740,8 @@ public function toHierarchy() $collection = $this; $table = $collection->getTable(); - if ( ! $table->hasTemplate('NestedSet')) { - throw new Doctrine_Exception('Cannot hydrate model that does not have the NestedSet behavior enabled'); + if ( ! $table->isTree() || ! $table->hasColumn('level')) { + throw new Doctrine_Exception('Cannot hydrate model that does not implements Tree behavior with `level` column'); } // Trees mapped @@ -774,7 +786,7 @@ public function toHierarchy() /** * Populate a Doctrine_Collection from an array of data * - * @param string $array + * @param string $array * @return void */ public function fromArray($array, $deep = true) @@ -819,8 +831,8 @@ public function synchronizeFromArray(array $array) /** * Export a Doctrine_Collection to one of the supported Doctrine_Parser formats * - * @param string $type - * @param string $deep + * @param string $type + * @param string $deep * @return void */ public function exportTo($type, $deep = true) @@ -835,8 +847,8 @@ public function exportTo($type, $deep = true) /** * Import data to a Doctrine_Collection from one of the supported Doctrine_Parser formats * - * @param string $type - * @param string $data + * @param string $type + * @param string $data * @return void */ public function importFrom($type, $data) @@ -871,8 +883,8 @@ public function getInsertDiff() /** * Compares two records. To be used on _snapshot diffs using array_udiff * - * @param Doctrine_Record $a - * @param Doctrine_Record $b + * @param Doctrine_Record $a + * @param Doctrine_Record $b * @return integer */ protected function compareRecords($a, $b) @@ -880,12 +892,12 @@ protected function compareRecords($a, $b) if ($a->getOid() == $b->getOid()) { return 0; } - + return ($a->getOid() > $b->getOid()) ? 1 : -1; } /** - * Saves all records of this collection and processes the + * Saves all records of this collection and processes the * difference of the last snapshot and the current data * * @param Doctrine_Connection $conn optional connection parameter @@ -896,7 +908,7 @@ public function save(Doctrine_Connection $conn = null, $processDiff = true) if ($conn == null) { $conn = $this->_table->getConnection(); } - + try { $conn->beginInternalTransaction(); @@ -919,6 +931,41 @@ public function save(Doctrine_Connection $conn = null, $processDiff = true) return $this; } + /** + * Replaces all records of this collection and processes the + * difference of the last snapshot and the current data + * + * @param Doctrine_Connection $conn optional connection parameter + * @return Doctrine_Collection + */ + public function replace(Doctrine_Connection $conn = null, $processDiff = true) + { + if ($conn == null) { + $conn = $this->_table->getConnection(); + } + + try { + $conn->beginInternalTransaction(); + + $conn->transaction->addCollection($this); + + if ($processDiff) { + $this->processDiff(); + } + + foreach ($this->getData() as $key => $record) { + $record->replace($conn); + } + + $conn->commit(); + } catch (Exception $e) { + $conn->rollback(); + throw $e; + } + + return $this; + } + /** * Deletes all records from this collection * @@ -929,7 +976,7 @@ public function delete(Doctrine_Connection $conn = null, $clearColl = true) if ($conn == null) { $conn = $this->_table->getConnection(); } - + try { $conn->beginInternalTransaction(); $conn->transaction->addCollection($this); @@ -943,14 +990,14 @@ public function delete(Doctrine_Connection $conn = null, $clearColl = true) $conn->rollback(); throw $e; } - + if ($clearColl) { $this->clear(); } - + return $this; } - + /** * Clears the collection. * @@ -1004,7 +1051,7 @@ public function __toString() { return Doctrine_Lib::getCollectionAsString($this); } - + /** * Returns the relation object * @@ -1015,21 +1062,21 @@ public function getRelation() return $this->relation; } - /** - * checks if one of the containing records is modified - * returns true if modified, false otherwise - * - * @return boolean - */ - final public function isModified() { - $dirty = (count($this->getInsertDiff()) > 0 || count($this->getDeleteDiff()) > 0); - if ( ! $dirty) { - foreach($this as $record) { + /** + * checks if one of the containing records is modified + * returns true if modified, false otherwise + * + * @return boolean + */ + final public function isModified() { + $dirty = (count($this->getInsertDiff()) > 0 || count($this->getDeleteDiff()) > 0); + if ( ! $dirty) { + foreach($this as $record) { if ($dirty = $record->isModified()) { break; - } - } - } - return $dirty; + } + } + } + return $dirty; } -} \ No newline at end of file +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/Exception.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/Iterator.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/Iterator.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator/Expandable.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/Iterator/Expandable.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator/Expandable.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/Iterator/Expandable.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator/Normal.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/Iterator/Normal.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator/Normal.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/Iterator/Normal.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator/Offset.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/Iterator/Offset.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator/Offset.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/Iterator/Offset.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Offset.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/Offset.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Offset.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/Offset.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/OnDemand.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/OnDemand.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/OnDemand.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Collection/OnDemand.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Column.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Column.php new file mode 100644 index 0000000..18e081c --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Column.php @@ -0,0 +1,163 @@ +. + */ + +/** + * Doctrine_Column + * This class represents a database column + * + * @author Konsta Vesterinen + * @package Doctrine + * @subpackage Column + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version $Revision: 7663 $ + * @link www.doctrine-project.org + * @since 1.0 + */ +class Doctrine_Column extends Doctrine_Access implements IteratorAggregate, Countable +{ + /** + * @var array $_definition @see getDefinition() + */ + protected $_definition = array( + 'type' => null, + 'length' => 0, + ); + + /** + * @var array $definition @see getDefinition() + */ + public function __construct(array $definition = array()) + { + $this->_definition = $definition; + } + + /** + * Returns the definition of the column. + * + * Keys can be: + * string type, + * integer length, + * array values (only for enum fields, maps integer indexes to mixed values), + * @return array + */ + public function getDefinition() + { + return $this->_definition; + } + + /** + * contains + * + * @return boolean + */ + public function contains($name) + { + return isset($this->_definition[$name]); + } + + /** + * get + * + * @param string $name + * @return mixed + */ + public function get($name) + { + if ( ! isset($this->_definition[$name])) { + return null; + } + + return $this->_definition[$name]; + } + + /** + * set + * + * @param string $name + * @return void + */ + public function set($name, $value) + { + $this->_definition[$name] = $value; + } + + /** + * @param string $field + * @return array + */ + public function getEnumValues() + { + if (isset($this->_definition['values'])) { + return $this->_definition['values']; + } else { + return array(); + } + } + + /** + * Retrieves an enum value. + * + * @param integer $index + * @return string integer ($index) if not present + */ + public function enumValue($index) + { + if ($index instanceof Doctrine_Null) { + return false; + } + + return isset($this->_definition['values'][$index]) ? $this->_definition['values'][$index] : false; + } + + /** + * enumIndex + * + * @param string $field + * @param mixed $value + * @return mixed + */ + public function enumIndex($field, $value) + { + $values = $this->getEnumValues($field); + + return array_search($value, $values); + } + + /** + * count + * + * @return integer + */ + public function count() + { + return count($this->_definition); + } + + /** + * getIterator + * + * @return ArrayIterator + */ + public function getIterator() + { + return new ArrayIterator($this->_definition); + } +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Compiler.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Compiler.php similarity index 96% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Compiler.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Compiler.php index 7a7ba8c..9379316 100644 --- a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Compiler.php +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Compiler.php @@ -1,6 +1,6 @@ getFileName(), '.inc') === false) { + if (end($e) === 'php' && strpos($file->getFileName(), '.inc') === false + && strpos($file->getFileName(), 'sfYaml') === false) { require_once $file->getPathName(); } } diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Compiler/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Compiler/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Compiler/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Compiler/Exception.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Configurable.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Configurable.php similarity index 97% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Configurable.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Configurable.php index 0db5c1d..5a3493e 100644 --- a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Configurable.php +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Configurable.php @@ -1,6 +1,6 @@ */ abstract class Doctrine_Configurable extends Doctrine_Locator_Injectable @@ -49,7 +49,7 @@ abstract class Doctrine_Configurable extends Doctrine_Locator_Injectable * implementation classes */ protected $_impl = array(); - + /** * @var array $_params an array of user defined parameters */ @@ -87,6 +87,7 @@ public function setAttribute($attribute, $value) case Doctrine_Core::ATTR_CACHE: case Doctrine_Core::ATTR_RESULT_CACHE: case Doctrine_Core::ATTR_QUERY_CACHE: + case Doctrine_Core::ATTR_TABLE_CACHE: if ($value !== null) { if ( ! ($value instanceof Doctrine_Cache_Interface)) { throw new Doctrine_Exception('Cache driver should implement Doctrine_Cache_Interface'); @@ -121,43 +122,43 @@ public function getParams($namespace = null) if ($namespace == null) { $namespace = $this->getAttribute(Doctrine_Core::ATTR_DEFAULT_PARAM_NAMESPACE); } - + if ( ! isset($this->_params[$namespace])) { return null; } return $this->_params[$namespace]; } - + public function getParamNamespaces() { return array_keys($this->_params); } - public function setParam($name, $value, $namespace = null) + public function setParam($name, $value, $namespace = null) { if ($namespace == null) { $namespace = $this->getAttribute(Doctrine_Core::ATTR_DEFAULT_PARAM_NAMESPACE); } - + $this->_params[$namespace][$name] = $value; - + return $this; } - - public function getParam($name, $namespace = null) + + public function getParam($name, $namespace = null) { if ($namespace == null) { $namespace = $this->getAttribute(Doctrine_Core::ATTR_DEFAULT_PARAM_NAMESPACE); } - + if ( ! isset($this->_params[$namespace][$name])) { if (isset($this->parent)) { return $this->parent->getParam($name, $namespace); } return null; } - + return $this->_params[$namespace][$name]; } @@ -194,8 +195,8 @@ public function getImpl($template) } return $this->_impl[$template]; } - - + + public function hasImpl($template) { if ( ! isset($this->_impl[$template])) { @@ -331,7 +332,7 @@ public function getAttribute($attribute) if (isset($this->attributes[$attribute])) { return $this->attributes[$attribute]; } - + if (isset($this->parent)) { return $this->parent->getAttribute($attribute); } @@ -424,4 +425,4 @@ public function getParent() { return $this->parent; } -} \ No newline at end of file +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection.php similarity index 96% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection.php index e094bc0..a6703a2 100644 --- a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection.php +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection.php @@ -1,6 +1,6 @@ * @author Lukas Smith (MDB2 library) */ @@ -179,9 +179,15 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun * @var array $_userFkNames array of foreign key names that have been used */ protected $_usedNames = array( - 'foreign_keys' => array(), - 'indexes' => array() - ); + 'foreign_keys' => array(), + 'indexes' => array() + ); + + /** + * @var Doctrine_Cache_Interface The cache driver used for caching tables. + */ + protected $_tableCache; + protected $_tableCacheTTL; /** * the constructor @@ -219,6 +225,8 @@ public function __construct(Doctrine_Manager $manager, $adapter, $user = null, $ $this->setAttribute(Doctrine_Core::ATTR_ERRMODE, Doctrine_Core::ERRMODE_EXCEPTION); $this->getAttribute(Doctrine_Core::ATTR_LISTENER)->onOpen($this); + + $this->_tableCacheTTL = $this->getAttribute(Doctrine_Core::ATTR_TABLE_CACHE_LIFESPAN); } /** @@ -1116,6 +1124,20 @@ public function getTable($name) return $this->tables[$name]; } + $hasTableCache = $this->_tableCache !== false && ($this->_tableCache || $this->getAttribute(Doctrine_Core::ATTR_TABLE_CACHE)); + if ($hasTableCache) { + $tableCacheDriver = $this->getTableCacheDriver(); + $hash = md5($name . 'DOCTRINE_TABLE_CACHE_SALT'); + $cached = $tableCacheDriver->fetch($hash); + + if ($cached) { + $table = unserialize($cached); + $table->initializeFromCache($this); + + return $this->tables[$name] = $table; + } + } + $class = sprintf($this->getAttribute(Doctrine_Core::ATTR_TABLE_CLASS_FORMAT), $name); if (class_exists($class, $this->getAttribute(Doctrine_Core::ATTR_AUTOLOAD_TABLE_CLASSES)) && @@ -1126,6 +1148,11 @@ public function getTable($name) $table = new $tableClass($name, $this, true); } + if ($hasTableCache) { + // Save cached query + $tableCacheDriver->save($hash, serialize($table), $this->getTableCacheLifeSpan()); + } + return $table; } @@ -1181,6 +1208,7 @@ public function addTable(Doctrine_Table $table) return false; } $this->tables[$name] = $table; + return true; } @@ -1337,6 +1365,30 @@ public function getQueryCacheDriver() return $this->getAttribute(Doctrine_Core::ATTR_QUERY_CACHE); } + /** + * getQueryCacheDriver + * + * @return Doctrine_Cache_Interface + */ + public function getTableCacheDriver() + { + if ( ! $this->getAttribute(Doctrine_Core::ATTR_TABLE_CACHE)) { + throw new Doctrine_Exception('Query Cache driver not initialized.'); + } + + return $this->getAttribute(Doctrine_Core::ATTR_TABLE_CACHE); + } + + /** + * Gets the life span of the table cache the Query object is using. + * + * @return integer The life span in seconds. + */ + public function getTableCacheLifeSpan() + { + return $this->_tableCacheTTL; + } + /** * lastInsertId * @@ -1661,4 +1713,4 @@ protected function _generateUniqueName($type, $parts, $key, $format = '%s', $max return $name; } -} \ No newline at end of file +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Common.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Common.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Common.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Common.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Db2.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Db2.php similarity index 93% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Db2.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Db2.php index 92b381c..ad9d150 100644 --- a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Db2.php +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Db2.php @@ -46,7 +46,7 @@ public function modifyLimitQuery($query, $limit = false, $offset = false, $isMan return $query; if ($offset == 0) { - return $query . ' FETCH FIRST '. $limit .' ROWS ONLY'; + return $query . ' FETCH FIRST '. (int)$limit .' ROWS ONLY'; } else { $sqlPieces = explode('from', $query); $select = $sqlPieces[0]; @@ -56,8 +56,8 @@ public function modifyLimitQuery($query, $limit = false, $offset = false, $isMan $sql = 'WITH OFFSET AS(' . $select . ', ROW_NUMBER() ' . 'OVER(ORDER BY ' . $col[1] . ') AS doctrine_rownum FROM ' . $table . ')' . - $select . 'FROM OFFSET WHERE doctrine_rownum BETWEEN ' . $offset . - 'AND ' . ($offset + $limit - 1); + $select . 'FROM OFFSET WHERE doctrine_rownum BETWEEN ' . (int)$offset . + 'AND ' . ((int)$offset + (int)$limit - 1); return $sql; } } diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Exception.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mock.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Mock.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mock.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Mock.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Module.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Module.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Module.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Module.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Mssql.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Mssql.php new file mode 100644 index 0000000..ecce33f --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Mssql.php @@ -0,0 +1,383 @@ +. + */ + +/** + * Doctrine_Connection_Mssql + * + * @package Doctrine + * @subpackage Connection + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen + * @author Lukas Smith (PEAR MDB2 library) + * @version $Revision: 7690 $ + * @link www.doctrine-project.org + * @since 1.0 + */ +class Doctrine_Connection_Mssql extends Doctrine_Connection_Common +{ + /** + * @var string $driverName the name of this connection driver + */ + protected $driverName = 'Mssql'; + + /** + * the constructor + * + * @param Doctrine_Manager $manager + * @param PDO $pdo database handle + */ + public function __construct(Doctrine_Manager $manager, $adapter) + { + // initialize all driver options + $this->supported = array( + 'sequences' => 'emulated', + 'indexes' => true, + 'affected_rows' => true, + 'transactions' => true, + 'summary_functions' => true, + 'order_by_text' => true, + 'current_id' => 'emulated', + 'limit_queries' => 'emulated', + 'LOBs' => true, + 'replace' => 'emulated', + 'sub_selects' => true, + 'auto_increment' => true, + 'primary_key' => true, + 'result_introspection' => true, + 'prepared_statements' => 'emulated', + ); + + $this->properties['varchar_max_length'] = 8000; + + parent::__construct($manager, $adapter); + } + + /** + * quoteIdentifier + * Quote a string so it can be safely used as a table / column name + * + * Quoting style depends on which database driver is being used. + * + * @param string $identifier identifier name to be quoted + * @param bool $checkOption check the 'quote_identifier' option + * + * @return string quoted identifier string + */ + public function quoteIdentifier($identifier, $checkOption = false) + { + if ($checkOption && ! $this->getAttribute(Doctrine_Core::ATTR_QUOTE_IDENTIFIER)) { + return $identifier; + } + + if (strpos($identifier, '.') !== false) { + $parts = explode('.', $identifier); + $quotedParts = array(); + foreach ($parts as $p) { + $quotedParts[] = $this->quoteIdentifier($p); + } + + return implode('.', $quotedParts); + } + + return '[' . trim($identifier, '[]') . ']'; + } + + /** + * Adds an adapter-specific LIMIT clause to the SELECT statement. + * Inspired by Doctrine2 DBAL + * + * @param string $query + * @param mixed $limit + * @param mixed $offset + * @param boolean $isSubQuery + * @param Doctrine_Query $queryOrigin + * @link https://github.com/doctrine/dbal/blob/master/lib/Doctrine/DBAL/Platforms/MsSqlPlatform.php#L607 + * @link http://www.toosweettobesour.com/2010/09/16/doctrine-1-2-mssql-alternative-limitpaging/ + * @return string + */ + public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false, $isSubQuery = false, Doctrine_Query $queryOrigin = null) + { + if ($limit === false || !($limit > 0)) { + return $query; + } + + $orderby = stristr($query, 'ORDER BY'); + + if ($offset !== false && $orderby === false) { + throw new Doctrine_Connection_Exception("OFFSET cannot be used in MSSQL without ORDER BY due to emulation reasons."); + } + + $limit = intval($limit); + $offset = intval($offset); + + if ($offset < 0) { + throw new Doctrine_Connection_Exception("LIMIT argument offset=$offset is not valid"); + } + + if ($offset == 0) { + $query = preg_replace('/^SELECT( DISTINCT)?\s/i', 'SELECT\1 TOP ' . $limit . ' ', $query); + } else { + $over = stristr($query, 'ORDER BY'); + + if (!$over) { + $over = 'ORDER BY (SELECT 0)'; + } else { + // Remove ORDER BY clause from $query + $query = stristr($query, 'ORDER BY', true); + } + + // Remove the first SELECT from query + $query = substr($query, strlen('SELECT ')); + $select = 'SELECT'; + + if (0 === strpos($query, 'DISTINCT')) + { + $query = substr($query, strlen('DISTINCT ')); + $select .= ' DISTINCT'; + } + + $start = $offset + 1; + $end = $offset + $limit; + + $query = "SELECT * FROM ($select ROW_NUMBER() OVER ($over) AS [DOCTRINE_ROWNUM], $query) AS [doctrine_tbl] WHERE [DOCTRINE_ROWNUM] BETWEEN $start AND $end"; + } + + return $query; + } + + + /** + * Parse an OrderBy-Statement into chunks + * + * @param string $orderby + */ + private function parseOrderBy($orderby) + { + $matches = array(); + $chunks = array(); + $tokens = array(); + $parsed = str_ireplace('ORDER BY', '', $orderby); + + preg_match_all('/(\w+\(.+?\)\s+(ASC|DESC)),?/', $orderby, $matches); + + $matchesWithExpressions = $matches[1]; + + foreach ($matchesWithExpressions as $match) { + $chunks[] = $match; + $parsed = str_replace($match, '##' . (count($chunks) - 1) . '##', $parsed); + } + + $tokens = preg_split('/,/', $parsed); + + for ($i = 0, $iMax = count($tokens); $i < $iMax; $i++) { + $tokens[$i] = trim(preg_replace_callback('/##(\d+)##/', function($m) { return $chunks[$m[1]]; }, $tokens[$i])); + } + + return $tokens; + } + + /** + * Order and Group By are not possible on columns from type text. + * This method fix this issue by wrap the given term (column) into a CAST directive. + * + * @see DC-828 + * @param Doctrine_Table $table + * @param string $field + * @param string $term The term which will changed if it's necessary, depending to the field type. + * @return string + */ + public function modifyOrderByColumn(Doctrine_Table $table, $field, $term) + { + $def = $table->getDefinitionOf($field); + + if ($def['type'] == 'string' && $def['length'] === NULL) { + $term = 'CAST(' . $term . ' AS varchar(8000))'; + } + + return $term; + } + + /** + * Creates dbms specific LIMIT/OFFSET SQL for the subqueries that are used in the + * context of the limit-subquery algorithm. + * + * @return string + */ + public function modifyLimitSubquery(Doctrine_Table $rootTable, $query, $limit = false, $offset = false, $isManip = false) + { + return $this->modifyLimitQuery($query, $limit, $offset, $isManip, true); + } + + /** + * return version information about the server + * + * @param bool $native determines if the raw version string should be returned + * @return array version information + */ + public function getServerVersion($native = false) + { + if ($this->serverInfo) { + $serverInfo = $this->serverInfo; + } else { + $query = 'SELECT @@VERSION'; + $serverInfo = $this->fetchOne($query); + } + // cache server_info + $this->serverInfo = $serverInfo; + if ( ! $native) { + if (preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $serverInfo, $tmp)) { + $serverInfo = array( + 'major' => $tmp[1], + 'minor' => $tmp[2], + 'patch' => $tmp[3], + 'extra' => null, + 'native' => $serverInfo, + ); + } else { + $serverInfo = array( + 'major' => null, + 'minor' => null, + 'patch' => null, + 'extra' => null, + 'native' => $serverInfo, + ); + } + } + return $serverInfo; + } + + /** + * Checks if there's a sequence that exists. + * + * @param string $seq_name The sequence name to verify. + * @return boolean The value if the table exists or not + */ + public function checkSequence($seqName) + { + $query = 'SELECT * FROM ' . $seqName; + try { + $this->exec($query); + } catch(Doctrine_Connection_Exception $e) { + if ($e->getPortableCode() == Doctrine_Core::ERR_NOSUCHTABLE) { + return false; + } + + throw $e; + } + return true; + } + + /** + * execute + * @param string $query sql query + * @param array $params query parameters + * + * @return PDOStatement|Doctrine_Adapter_Statement + */ + public function execute($query, array $params = array()) + { + if(! empty($params)) { + $query = $this->replaceBoundParamsWithInlineValuesInQuery($query, $params); + } + + return parent::execute($query, array()); + } + + /** + * execute + * @param string $query sql query + * @param array $params query parameters + * + * @return PDOStatement|Doctrine_Adapter_Statement + */ + public function exec($query, array $params = array()) + { + if(! empty($params)) { + $query = $this->replaceBoundParamsWithInlineValuesInQuery($query, $params); + } + + return parent::exec($query, array()); + } + + /** + * Replaces bound parameters and their placeholders with explicit values. + * + * Workaround for http://bugs.php.net/36561 + * + * @param string $query + * @param array $params + */ + protected function replaceBoundParamsWithInlineValuesInQuery($query, array $params) + { + foreach($params as $key => $value) { + $re = '/(?<=WHERE|VALUES|SET|JOIN)(.*?)(\?)/'; + $query = preg_replace($re, "\\1##{$key}##", $query, 1); + } + + $self = $this; + $query = preg_replace_callback('/##(\d+)##/', function($m) use ($params, $self) { + return (null === $params[$m[1]]) ? 'NULL' : $self->quote($params[$m[1]]); + }, $query); + + return $query; + } + + /** + * Inserts a table row with specified data. + * + * @param Doctrine_Table $table The table to insert data into. + * @param array $values An associative array containing column-value pairs. + * Values can be strings or Doctrine_Expression instances. + * @return integer the number of affected rows. Boolean false if empty value array was given, + */ + public function insert(Doctrine_Table $table, array $fields) + { + $identifiers = $table->getIdentifierColumnNames(); + + $settingNullIdentifier = false; + $fields = array_change_key_case($fields); + foreach($identifiers as $identifier) { + $lcIdentifier = strtolower($identifier); + + if(array_key_exists($lcIdentifier, $fields)) { + if(is_null($fields[$lcIdentifier])) { + $settingNullIdentifier = true; + unset($fields[$lcIdentifier]); + } + } + } + + // MSSQL won't allow the setting of identifier columns to null, so insert a default record and then update it + if ($settingNullIdentifier) { + $count = $this->exec('INSERT INTO ' . $this->quoteIdentifier($table->getTableName()) . ' DEFAULT VALUES'); + + if(! $count) { + return $count; + } + + $id = $this->lastInsertId($table->getTableName()); + + return $this->update($table, $fields, array($id)); + } + + return parent::insert($table, $fields); + } +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mssql/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Mssql/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mssql/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Mssql/Exception.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mysql.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Mysql.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mysql.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Mysql.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mysql/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Mysql/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mysql/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Mysql/Exception.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Oracle.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Oracle.php new file mode 100644 index 0000000..6649abf --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Oracle.php @@ -0,0 +1,162 @@ +. + */ + +/** + * Doctrine_Connection_Oracle + * + * @package Doctrine + * @subpackage Connection + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 1.0 + * @version $Revision: 7664 $ + * @author Konsta Vesterinen + */ +class Doctrine_Connection_Oracle extends Doctrine_Connection_Common +{ + /** + * @var string $driverName the name of this connection driver + */ + protected $driverName = 'Oracle'; + + public function __construct(Doctrine_Manager $manager, $adapter) + { + $this->supported = array( + 'sequences' => true, + 'indexes' => true, + 'summary_functions' => true, + 'order_by_text' => true, + 'current_id' => true, + 'affected_rows' => true, + 'transactions' => true, + 'savepoints' => true, + 'limit_queries' => true, + 'LOBs' => true, + 'replace' => 'emulated', + 'sub_selects' => true, + 'auto_increment' => false, // implementation is broken + 'primary_key' => true, + 'result_introspection' => true, + 'prepared_statements' => true, + 'identifier_quoting' => true, + 'pattern_escaping' => true, + ); + + $this->properties['sql_file_delimiter'] = "\n/\n"; + $this->properties['number_max_precision'] = 38; + $this->properties['max_identifier_length'] = 30; + + parent::__construct($manager, $adapter); + + // moving properties to params to make them changeable by user + // VARCHAR2 allowed length is 4000 BYTE. For UTF8 strings is better to use 1000 CHAR + $this->setParam('varchar2_max_length', 4000); + // Oracle's default unit for char data types is BYTE. For UTF8 string it is better to use CHAR + $this->setParam('char_unit', null); + } + + /** + * Sets up the date/time format + * + */ + public function setDateFormat($format = 'YYYY-MM-DD HH24:MI:SS') + { + $this->exec('ALTER SESSION SET NLS_DATE_FORMAT = "' . $format . '"'); + } + + /** + * Adds an driver-specific LIMIT clause to the query + * + * @param string $query query to modify + * @param integer $limit limit the number of rows + * @param integer $offset start reading from given offset + * @return string the modified query + */ + public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false) + { + return $this->_createLimitSubquery($query, $limit, $offset); + } + + private function _createLimitSubquery($query, $limit, $offset, $column = null) + { + $limit = (int) $limit; + $offset = (int) $offset; + if (preg_match('/^\s*SELECT/i', $query)) { + if ( ! preg_match('/\sFROM\s/i', $query)) { + $query .= " FROM dual"; + } + if ($limit > 0) { + $max = $offset + $limit; + $column = $column === null ? '*' : $this->quoteIdentifier($column); + if ($offset > 0) { + $min = $offset + 1; + $query = 'SELECT '.$this->quoteIdentifier('b').'.'.$column.' FROM ( '. + 'SELECT '.$this->quoteIdentifier('a').'.*, ROWNUM AS doctrine_rownum FROM ( ' + . $query . ' ) ' . $this->quoteIdentifier('a') . ' '. + ' ) ' . $this->quoteIdentifier('b') . ' '. + 'WHERE doctrine_rownum BETWEEN ' . $min . ' AND ' . $max; + } else { + $query = 'SELECT a.'.$column.' FROM ( ' . $query .' ) a WHERE ROWNUM <= ' . $max; + } + } + } + return $query; + } + + /** + * Creates the SQL for Oracle that can be used in the subquery for the limit-subquery + * algorithm. + */ + public function modifyLimitSubquery(Doctrine_Table $rootTable, $query, $limit = false, + $offset = false, $isManip = false) + { + // NOTE: no composite key support + $columnNames = $rootTable->getIdentifierColumnNames(); + if (count($columnNames) > 1) { + throw new Doctrine_Connection_Exception("Composite keys in LIMIT queries are " + . "currently not supported."); + } + $column = $columnNames[0]; + return $this->_createLimitSubquery($query, $limit, $offset, $column); + } + + public function getTmpConnection($info) + { + return clone $this; + } + + /** + * Override quote behaviour for boolean to fix issues with quoting of + * boolean values. + */ + public function quote($input, $type = null) + { + if ($type === 'boolean') { + if ($input === null) { + return null; + } else { + return $input ? 1 : 0; + } + } else { + return parent::quote($input, $type); + } + } +} \ No newline at end of file diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Oracle/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Oracle/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Oracle/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Oracle/Exception.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Pgsql.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Pgsql.php new file mode 100644 index 0000000..2fbc19d --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Pgsql.php @@ -0,0 +1,246 @@ +. + */ + +/** + * Doctrine_Connection_Pgsql + * + * @package Doctrine + * @subpackage Connection + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen + * @author Lukas Smith (PEAR MDB2 library) + * @version $Revision: 7490 $ + * @link www.doctrine-project.org + * @since 1.0 + */ +class Doctrine_Connection_Pgsql extends Doctrine_Connection_Common +{ + /** + * @var string $driverName the name of this connection driver + */ + protected $driverName = 'Pgsql'; + + /** + * the constructor + * + * @param Doctrine_Manager $manager + * @param PDO $pdo database handle + */ + public function __construct(Doctrine_Manager $manager, $adapter) + { + // initialize all driver options + $this->supported = array( + 'sequences' => true, + 'indexes' => true, + 'affected_rows' => true, + 'summary_functions' => true, + 'order_by_text' => true, + 'transactions' => true, + 'savepoints' => true, + 'current_id' => true, + 'limit_queries' => true, + 'LOBs' => true, + 'replace' => 'emulated', + 'sub_selects' => true, + 'auto_increment' => 'emulated', + 'primary_key' => true, + 'result_introspection' => true, + 'prepared_statements' => true, + 'identifier_quoting' => true, + 'pattern_escaping' => true, + ); + + $this->properties['string_quoting'] = array('start' => "'", + 'end' => "'", + 'escape' => "'", + 'escape_pattern' => '\\'); + + $this->properties['identifier_quoting'] = array('start' => '"', + 'end' => '"', + 'escape' => '"'); + parent::__construct($manager, $adapter); + } + + /** + * Set the charset on the current connection + * + * @param string charset + * + * @return void + */ + public function setCharset($charset) + { + $query = 'SET NAMES '.$this->quote($charset); + $this->exec($query); + parent::setCharset($charset); + } + + /** + * convertBoolean + * some drivers need the boolean values to be converted into integers + * when using DQL API + * + * This method takes care of that conversion + * + * @param array $item + * @return void + */ + public function convertBooleans($item) + { + if (is_array($item)) { + foreach ($item as $key => $value) { + if (is_bool($value)) { + $item[$key] = ($value) ? 'true' : 'false'; + } + } + } else { + if (is_bool($item) || is_numeric($item)) { + $item = ($item) ? 'true' : 'false'; + } + } + return $item; + } + + /** + * Changes a query string for various DBMS specific reasons + * + * @param string $query query to modify + * @param integer $limit limit the number of rows + * @param integer $offset start reading from given offset + * @param boolean $isManip if the query is a DML query + * @return string modified query + */ + public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false) + { + if ($limit > 0) { + $query = rtrim($query); + + if (substr($query, -1) == ';') { + $query = substr($query, 0, -1); + } + + if ($isManip) { + $manip = preg_replace('/^(DELETE FROM|UPDATE).*$/', '\\1', $query); + $from = $match[2]; + $where = $match[3]; + $query = $manip . ' ' . $from . ' WHERE ctid=(SELECT ctid FROM ' + . $from . ' ' . $where . ' LIMIT ' . (int)$limit . ')'; + + } else { + if ( ! empty($limit)) { + $query .= ' LIMIT ' . (int)$limit; + } + if ( ! empty($offset)) { + $query .= ' OFFSET ' . (int)$offset; + } + } + } + return $query; + } + + /** + * return version information about the server + * + * @param string $native determines if the raw version string should be returned + * @return array|string an array or string with version information + */ + public function getServerVersion($native = false) + { + $query = 'SHOW SERVER_VERSION'; + + $serverInfo = $this->fetchOne($query); + + if ( ! $native) { + $tmp = explode('.', $serverInfo, 3); + + if (empty($tmp[2]) && isset($tmp[1]) + && preg_match('/(\d+)(.*)/', $tmp[1], $tmp2) + ) { + $serverInfo = array( + 'major' => $tmp[0], + 'minor' => $tmp2[1], + 'patch' => null, + 'extra' => $tmp2[2], + 'native' => $serverInfo, + ); + } else { + $serverInfo = array( + 'major' => isset($tmp[0]) ? $tmp[0] : null, + 'minor' => isset($tmp[1]) ? $tmp[1] : null, + 'patch' => isset($tmp[2]) ? $tmp[2] : null, + 'extra' => null, + 'native' => $serverInfo, + ); + } + } + return $serverInfo; + } + + /** + * Inserts a table row with specified data. + * + * @param Doctrine_Table $table The table to insert data into. + * @param array $values An associative array containing column-value pairs. + * Values can be strings or Doctrine_Expression instances. + * @return integer the number of affected rows. Boolean false if empty value array was given, + */ + public function insert(Doctrine_Table $table, array $fields) + { + $tableName = $table->getTableName(); + + // column names are specified as array keys + $cols = array(); + // the query VALUES will contain either expresions (eg 'NOW()') or ? + $a = array(); + + foreach ($fields as $fieldName => $value) { + if ($table->isIdentifier($fieldName) + && $table->isIdentifierAutoincrement() + && $value == null) { + // Autoincrement fields should not be added to the insert statement + // if their value is null + unset($fields[$fieldName]); + continue; + } + $cols[] = $this->quoteIdentifier($table->getColumnName($fieldName)); + if ($value instanceof Doctrine_Expression) { + $a[] = $value->getSql(); + unset($fields[$fieldName]); + } else { + $a[] = '?'; + } + } + + if (count($fields) == 0) { + // Real fix #1786 and #2327 (default values when table is just 'id' as PK) + return $this->exec('INSERT INTO ' . $this->quoteIdentifier($tableName) + . ' ' + . ' VALUES (DEFAULT)'); + } + + // build the statement + $query = 'INSERT INTO ' . $this->quoteIdentifier($tableName) + . ' (' . implode(', ', $cols) . ')' + . ' VALUES (' . implode(', ', $a) . ')'; + + return $this->exec($query, array_values($fields)); + } +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Pgsql/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Pgsql/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Pgsql/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Pgsql/Exception.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Profiler.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Profiler.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Profiler.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Profiler.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Profiler/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Profiler/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Profiler/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Profiler/Exception.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Sqlite.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Sqlite.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Sqlite.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Sqlite.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Sqlite/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Sqlite/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Sqlite/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Sqlite/Exception.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Statement.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Statement.php similarity index 96% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Statement.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Statement.php index ccbec13..7ad3215 100644 --- a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Statement.php +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/Statement.php @@ -59,7 +59,16 @@ public function __construct(Doctrine_Connection $conn, $stmt) throw new Doctrine_Exception('Unknown statement object given.'); } } - + /** + * destructor + * + * make sure that the cursor is closed + * + */ + public function __destruct() + { + $this->closeCursor(); + } /** * getConnection * returns the connection object this statement uses @@ -224,7 +233,7 @@ public function errorInfo() * bound parameters in the SQL statement being executed. * @return boolean Returns TRUE on success or FALSE on failure. */ - public function execute($params = null) + public function execute($params = array()) { try { $event = new Doctrine_Event($this, Doctrine_Event::STMT_EXECUTE, $this->getQuery(), $params); @@ -261,6 +270,14 @@ public function execute($params = null) $this->_conn->getListener()->postStmtExecute($event); + //fix a possible "ORA-01000: maximum open cursors exceeded" when many non-SELECTs are executed and the profiling is enabled + if ('Oracle' == $this->getConnection()->getDriverName()) { + $queryBeginningSubstring = strtoupper(substr(ltrim($this->_stmt->queryString), 0, 6)); + if ($queryBeginningSubstring != 'SELECT' && substr($queryBeginningSubstring, 0, 4) != 'WITH' ){ + $this->closeCursor(); + } + } + return $result; } catch (PDOException $e) { } catch (Doctrine_Adapter_Exception $e) { diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/UnitOfWork.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/UnitOfWork.php new file mode 100644 index 0000000..9627d6d --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Connection/UnitOfWork.php @@ -0,0 +1,960 @@ +. + */ + +/** + * Doctrine_Connection_UnitOfWork + * + * Note: This class does not have the semantics of a real "Unit of Work" in 0.10/1.0. + * Database operations are not queued. All changes to objects are immediately written + * to the database. You can think of it as a unit of work in auto-flush mode. + * + * Referential integrity is currently not always ensured. + * + * @package Doctrine + * @subpackage Connection + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 1.0 + * @version $Revision: 7684 $ + * @author Konsta Vesterinen + * @author Roman Borschel + */ +class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module +{ + /** + * Saves the given record and all associated records. + * (The save() operation is always cascaded in 0.10/1.0). + * + * @param Doctrine_Record $record + * @return void + */ + public function saveGraph(Doctrine_Record $record, $replace = false) + { + $record->assignInheritanceValues(); + + $conn = $this->getConnection(); + $conn->connect(); + + $state = $record->state(); + if ($state === Doctrine_Record::STATE_LOCKED || $state === Doctrine_Record::STATE_TLOCKED) { + return false; + } + + $record->state($record->exists() ? Doctrine_Record::STATE_LOCKED : Doctrine_Record::STATE_TLOCKED); + + try { + $conn->beginInternalTransaction(); + $record->state($state); + + $event = $record->invokeSaveHooks('pre', 'save'); + $state = $record->state(); + + $isValid = true; + + if ( ! $event->skipOperation) { + $this->saveRelatedLocalKeys($record); + + switch ($state) { + case Doctrine_Record::STATE_TDIRTY: + case Doctrine_Record::STATE_TCLEAN: + if ($replace) { + $isValid = $this->replace($record); + } else { + $isValid = $this->insert($record); + } + break; + case Doctrine_Record::STATE_DIRTY: + case Doctrine_Record::STATE_PROXY: + if ($replace) { + $isValid = $this->replace($record); + } else { + $isValid = $this->update($record); + } + break; + case Doctrine_Record::STATE_CLEAN: + // do nothing + break; + } + + $aliasesUnlinkInDb = array(); + + if ($isValid) { + // NOTE: what about referential integrity issues? + foreach ($record->getPendingDeletes() as $pendingDelete) { + $pendingDelete->delete(); + } + + foreach ($record->getPendingUnlinks() as $alias => $ids) { + if ($ids === false) { + $record->unlinkInDb($alias, array()); + $aliasesUnlinkInDb[] = $alias; + } else if ($ids) { + $record->unlinkInDb($alias, array_keys($ids)); + $aliasesUnlinkInDb[] = $alias; + } + } + $record->resetPendingUnlinks(); + + $record->invokeSaveHooks('post', 'save', $event); + } else { + $conn->transaction->addInvalid($record); + } + + $state = $record->state(); + + $record->state($record->exists() ? Doctrine_Record::STATE_LOCKED : Doctrine_Record::STATE_TLOCKED); + + if ($isValid) { + $saveLater = $this->saveRelatedForeignKeys($record); + foreach ($saveLater as $fk) { + $alias = $fk->getAlias(); + + if ($record->hasReference($alias)) { + $obj = $record->$alias; + + // check that the related object is not an instance of Doctrine_Null + if ($obj && ! ($obj instanceof Doctrine_Null)) { + $processDiff = !in_array($alias, $aliasesUnlinkInDb); + $obj->save($conn, $processDiff); + } + } + } + + // save the MANY-TO-MANY associations + $this->saveAssociations($record); + } + } + + $record->state($state); + + $conn->commit(); + } catch (Exception $e) { + // Make sure we roll back our internal transaction + //$record->state($state); + $conn->rollback(); + throw $e; + } + + $record->clearInvokedSaveHooks(); + + return true; + } + + /** + * Deletes the given record and all the related records that participate + * in an application-level delete cascade. + * + * this event can be listened by the onPreDelete and onDelete listeners + * + * @return boolean true on success, false on failure + */ + public function delete(Doctrine_Record $record) + { + $deletions = array(); + $this->_collectDeletions($record, $deletions); + return $this->_executeDeletions($deletions); + } + + /** + * Collects all records that need to be deleted by applying defined + * application-level delete cascades. + * + * @param array $deletions Map of the records to delete. Keys=Oids Values=Records. + */ + private function _collectDeletions(Doctrine_Record $record, array &$deletions) + { + if ( ! $record->exists()) { + return; + } + + $deletions[$record->getOid()] = $record; + $this->_cascadeDelete($record, $deletions); + } + + /** + * Executes the deletions for all collected records during a delete operation + * (usually triggered through $record->delete()). + * + * @param array $deletions Map of the records to delete. Keys=Oids Values=Records. + */ + private function _executeDeletions(array $deletions) + { + // collect class names + $classNames = array(); + foreach ($deletions as $record) { + $classNames[] = $record->getTable()->getComponentName(); + } + $classNames = array_unique($classNames); + + // order deletes + $executionOrder = $this->buildFlushTree($classNames); + + // execute + try { + $this->conn->beginInternalTransaction(); + + for ($i = count($executionOrder) - 1; $i >= 0; $i--) { + $className = $executionOrder[$i]; + $table = $this->conn->getTable($className); + + // collect identifiers + $identifierMaps = array(); + $deletedRecords = array(); + foreach ($deletions as $oid => $record) { + if ($record->getTable()->getComponentName() == $className) { + $veto = $this->_preDelete($record); + if ( ! $veto) { + $identifierMaps[] = $record->identifier(); + $deletedRecords[] = $record; + unset($deletions[$oid]); + } + } + } + + if (count($deletedRecords) < 1) { + continue; + } + + // extract query parameters (only the identifier values are of interest) + $params = array(); + $columnNames = array(); + foreach ($identifierMaps as $idMap) { + foreach($idMap as $fieldName => $value) { + $params[] = $value; + $columnNames[] = $table->getColumnName($fieldName); + } + } + $columnNames = array_unique($columnNames); + + // delete + $tableName = $table->getTableName(); + $sql = "DELETE FROM " . $this->conn->quoteIdentifier($tableName) . " WHERE "; + + if ($table->isIdentifierComposite()) { + $sql .= $this->_buildSqlCompositeKeyCondition($columnNames, count($identifierMaps)); + $this->conn->exec($sql, $params); + } else { + $sql .= $this->_buildSqlSingleKeyCondition($columnNames, count($params)); + $this->conn->exec($sql, $params); + } + + // adjust state, remove from identity map and inform postDelete listeners + foreach ($deletedRecords as $record) { + // currently just for bc! + $this->_deleteCTIParents($table, $record); + //-- + $record->state(Doctrine_Record::STATE_TCLEAN); + $record->getTable()->removeRecord($record); + $this->_postDelete($record); + } + } + + // trigger postDelete for records skipped during the deletion (veto!) + foreach ($deletions as $skippedRecord) { + $this->_postDelete($skippedRecord); + } + + $this->conn->commit(); + + return true; + } catch (Exception $e) { + $this->conn->rollback(); + throw $e; + } + } + + /** + * Builds the SQL condition to target multiple records who have a single-column + * primary key. + * + * @param Doctrine_Table $table The table from which the records are going to be deleted. + * @param integer $numRecords The number of records that are going to be deleted. + * @return string The SQL condition "pk = ? OR pk = ? OR pk = ? ..." + */ + private function _buildSqlSingleKeyCondition($columnNames, $numRecords) + { + $idColumn = $this->conn->quoteIdentifier($columnNames[0]); + return implode(' OR ', array_fill(0, $numRecords, "$idColumn = ?")); + } + + /** + * Builds the SQL condition to target multiple records who have a composite primary key. + * + * @param Doctrine_Table $table The table from which the records are going to be deleted. + * @param integer $numRecords The number of records that are going to be deleted. + * @return string The SQL condition "(pk1 = ? AND pk2 = ?) OR (pk1 = ? AND pk2 = ?) ..." + */ + private function _buildSqlCompositeKeyCondition($columnNames, $numRecords) + { + $singleCondition = ""; + foreach ($columnNames as $columnName) { + $columnName = $this->conn->quoteIdentifier($columnName); + if ($singleCondition === "") { + $singleCondition .= "($columnName = ?"; + } else { + $singleCondition .= " AND $columnName = ?"; + } + } + $singleCondition .= ")"; + $fullCondition = implode(' OR ', array_fill(0, $numRecords, $singleCondition)); + + return $fullCondition; + } + + /** + * Cascades an ongoing delete operation to related objects. Applies only on relations + * that have 'delete' in their cascade options. + * This is an application-level cascade. Related objects that participate in the + * cascade and are not yet loaded are fetched from the database. + * Exception: many-valued relations are always (re-)fetched from the database to + * make sure we have all of them. + * + * @param Doctrine_Record The record for which the delete operation will be cascaded. + * @throws PDOException If something went wrong at database level + * @return void + */ + protected function _cascadeDelete(Doctrine_Record $record, array &$deletions) + { + foreach ($record->getTable()->getRelations() as $relation) { + if ($relation->isCascadeDelete()) { + $fieldName = $relation->getAlias(); + // if it's a xToOne relation and the related object is already loaded + // we don't need to refresh. + if ( ! ($relation->getType() == Doctrine_Relation::ONE && isset($record->$fieldName))) { + $record->refreshRelated($relation->getAlias()); + } + $relatedObjects = $record->get($relation->getAlias()); + if ($relatedObjects instanceof Doctrine_Record && $relatedObjects->exists() + && ! isset($deletions[$relatedObjects->getOid()])) { + $this->_collectDeletions($relatedObjects, $deletions); + } else if ($relatedObjects instanceof Doctrine_Collection && count($relatedObjects) > 0) { + // cascade the delete to the other objects + foreach ($relatedObjects as $object) { + if ( ! isset($deletions[$object->getOid()])) { + $this->_collectDeletions($object, $deletions); + } + } + } + } + } + } + + /** + * saveRelatedForeignKeys + * saves all related (through ForeignKey) records to $record + * + * @throws PDOException if something went wrong at database level + * @param Doctrine_Record $record + */ + public function saveRelatedForeignKeys(Doctrine_Record $record) + { + $saveLater = array(); + foreach ($record->getReferences() as $k => $v) { + $rel = $record->getTable()->getRelation($k); + if ($rel instanceof Doctrine_Relation_ForeignKey) { + $saveLater[$k] = $rel; + } + } + + return $saveLater; + } + + /** + * saveRelatedLocalKeys + * saves all related (through LocalKey) records to $record + * + * @throws PDOException if something went wrong at database level + * @param Doctrine_Record $record + */ + public function saveRelatedLocalKeys(Doctrine_Record $record) + { + $state = $record->state(); + $record->state($record->exists() ? Doctrine_Record::STATE_LOCKED : Doctrine_Record::STATE_TLOCKED); + + foreach ($record->getReferences() as $k => $v) { + $rel = $record->getTable()->getRelation($k); + + $local = $rel->getLocal(); + $foreign = $rel->getForeign(); + + if ($rel instanceof Doctrine_Relation_LocalKey) { + // ONE-TO-ONE relationship + $obj = $record->get($rel->getAlias()); + + // Protection against infinite function recursion before attempting to save + if ($obj instanceof Doctrine_Record && $obj->isModified()) { + $obj->save($this->conn); + + $id = array_values($obj->identifier()); + + if ( ! empty($id)) { + foreach ((array) $rel->getLocal() as $k => $columnName) { + $field = $record->getTable()->getFieldName($columnName); + + if (isset($id[$k]) && $id[$k] && $record->getTable()->hasField($field)) { + $record->set($field, $id[$k]); + } + } + } + } + } + } + $record->state($state); + } + + /** + * saveAssociations + * + * this method takes a diff of one-to-many / many-to-many original and + * current collections and applies the changes + * + * for example if original many-to-many related collection has records with + * primary keys 1,2 and 3 and the new collection has records with primary keys + * 3, 4 and 5, this method would first destroy the associations to 1 and 2 and then + * save new associations to 4 and 5 + * + * @throws Doctrine_Connection_Exception if something went wrong at database level + * @param Doctrine_Record $record + * @return void + */ + public function saveAssociations(Doctrine_Record $record) + { + foreach ($record->getReferences() as $k => $v) { + $rel = $record->getTable()->getRelation($k); + + if ($rel instanceof Doctrine_Relation_Association) { + if ($this->conn->getAttribute(Doctrine_Core::ATTR_CASCADE_SAVES) || $v->isModified()) { + $v->save($this->conn, false); + } + + $assocTable = $rel->getAssociationTable(); + foreach ($v->getDeleteDiff() as $r) { + $query = 'DELETE FROM ' . $assocTable->getTableName() + . ' WHERE ' . $rel->getForeignRefColumnName() . ' = ?' + . ' AND ' . $rel->getLocalRefColumnName() . ' = ?'; + + $this->conn->execute($query, array($r->getIncremented(), $record->getIncremented())); + } + + foreach ($v->getInsertDiff() as $r) { + $assocRecord = $assocTable->create(); + $assocRecord->set($assocTable->getFieldName($rel->getForeign()), $r); + $assocRecord->set($assocTable->getFieldName($rel->getLocal()), $record); + $this->saveGraph($assocRecord); + } + // take snapshot of collection state, so that we know when its modified again + $v->takeSnapshot(); + } + } + } + + /** + * Invokes preDelete event listeners. + * + * @return boolean Whether a listener has used it's veto (don't delete!). + */ + private function _preDelete(Doctrine_Record $record) + { + $event = new Doctrine_Event($record, Doctrine_Event::RECORD_DELETE); + $record->preDelete($event); + $record->getTable()->getRecordListener()->preDelete($event); + + return $event->skipOperation; + } + + /** + * Invokes postDelete event listeners. + */ + private function _postDelete(Doctrine_Record $record) + { + $event = new Doctrine_Event($record, Doctrine_Event::RECORD_DELETE); + $record->postDelete($event); + $record->getTable()->getRecordListener()->postDelete($event); + } + + /** + * saveAll + * persists all the pending records from all tables + * + * @throws PDOException if something went wrong at database level + * @return void + */ + public function saveAll() + { + // get the flush tree + $tree = $this->buildFlushTree($this->conn->getTables()); + + // save all records + foreach ($tree as $name) { + $table = $this->conn->getTable($name); + foreach ($table->getRepository() as $record) { + $this->saveGraph($record); + } + } + } + + /** + * updates given record + * + * @param Doctrine_Record $record record to be updated + * @return boolean whether or not the update was successful + */ + public function update(Doctrine_Record $record) + { + $event = $record->invokeSaveHooks('pre', 'update'); + + if ($record->isValid(false, false)) { + $table = $record->getTable(); + if ( ! $event->skipOperation) { + $identifier = $record->identifier(); + if ($table->getOption('joinedParents')) { + // currrently just for bc! + $this->_updateCTIRecord($table, $record); + //-- + } else { + $array = $record->getPrepared(); + $this->conn->update($table, $array, $identifier); + } + $record->assignIdentifier(true); + } + + $record->invokeSaveHooks('post', 'update', $event); + + return true; + } + + return false; + } + + /** + * Inserts a record into database. + * + * This method inserts a transient record in the database, and adds it + * to the identity map of its correspondent table. It proxies to @see + * processSingleInsert(), trigger insert hooks and validation of data + * if required. + * + * @param Doctrine_Record $record + * @return boolean false if record is not valid + */ + public function insert(Doctrine_Record $record) + { + $event = $record->invokeSaveHooks('pre', 'insert'); + + if ($record->isValid(false, false)) { + $table = $record->getTable(); + + if ( ! $event->skipOperation) { + if ($table->getOption('joinedParents')) { + // just for bc! + $this->_insertCTIRecord($table, $record); + //-- + } else { + $this->processSingleInsert($record); + } + } + + $table->addRecord($record); + $record->invokeSaveHooks('post', 'insert', $event); + + return true; + } + + return false; + } + + /** + * Replaces a record into database. + * + * @param Doctrine_Record $record + * @return boolean false if record is not valid + */ + public function replace(Doctrine_Record $record) + { + if ($record->exists()) { + return $this->update($record); + } else { + if ($record->isValid()) { + $this->_assignSequence($record); + + $saveEvent = $record->invokeSaveHooks('pre', 'save'); + $insertEvent = $record->invokeSaveHooks('pre', 'insert'); + + $table = $record->getTable(); + $identifier = (array) $table->getIdentifier(); + $data = $record->getPrepared(); + + foreach ($data as $key => $value) { + if ($value instanceof Doctrine_Expression) { + $data[$key] = $value->getSql(); + } + } + + $result = $this->conn->replace($table, $data, $identifier); + + $record->invokeSaveHooks('post', 'insert', $insertEvent); + $record->invokeSaveHooks('post', 'save', $saveEvent); + + $this->_assignIdentifier($record); + + return true; + } else { + return false; + } + } + } + + /** + * Inserts a transient record in its table. + * + * This method inserts the data of a single record in its assigned table, + * assigning to it the autoincrement primary key (if any is defined). + * + * @param Doctrine_Record $record + * @return void + */ + public function processSingleInsert(Doctrine_Record $record) + { + $fields = $record->getPrepared(); + $table = $record->getTable(); + + // Populate fields with a blank array so that a blank records can be inserted + if (empty($fields)) { + foreach ($table->getFieldNames() as $field) { + $fields[$field] = null; + } + } + + $this->_assignSequence($record, $fields); + $this->conn->insert($table, $fields); + $this->_assignIdentifier($record); + } + + /** + * buildFlushTree + * builds a flush tree that is used in transactions + * + * The returned array has all the initialized components in + * 'correct' order. Basically this means that the records of those + * components can be saved safely in the order specified by the returned array. + * + * @param array $tables an array of Doctrine_Table objects or component names + * @return array an array of component names in flushing order + */ + public function buildFlushTree(array $tables) + { + // determine classes to order. only necessary because the $tables param + // can contain strings or table objects... + $classesToOrder = array(); + foreach ($tables as $table) { + if ( ! ($table instanceof Doctrine_Table)) { + $table = $this->conn->getTable($table, false); + } + $classesToOrder[] = $table->getComponentName(); + } + $classesToOrder = array_unique($classesToOrder); + + if (count($classesToOrder) < 2) { + return $classesToOrder; + } + + // build the correct order + $flushList = array(); + foreach ($classesToOrder as $class) { + $table = $this->conn->getTable($class, false); + $currentClass = $table->getComponentName(); + + $index = array_search($currentClass, $flushList); + + if ($index === false) { + //echo "adding $currentClass to flushlist"; + $flushList[] = $currentClass; + $index = max(array_keys($flushList)); + } + + $rels = $table->getRelations(); + + // move all foreignkey relations to the beginning + foreach ($rels as $key => $rel) { + if ($rel instanceof Doctrine_Relation_ForeignKey) { + unset($rels[$key]); + array_unshift($rels, $rel); + } + } + + foreach ($rels as $rel) { + $relatedClassName = $rel->getTable()->getComponentName(); + + if ( ! in_array($relatedClassName, $classesToOrder)) { + continue; + } + + $relatedCompIndex = array_search($relatedClassName, $flushList); + $type = $rel->getType(); + + // skip self-referenced relations + if ($relatedClassName === $currentClass) { + continue; + } + + if ($rel instanceof Doctrine_Relation_ForeignKey) { + // the related component needs to come after this component in + // the list (since it holds the fk) + + if ($relatedCompIndex !== false) { + // the component is already in the list + if ($relatedCompIndex >= $index) { + // it's already in the right place + continue; + } + + unset($flushList[$index]); + // the related comp has the fk. so put "this" comp immediately + // before it in the list + array_splice($flushList, $relatedCompIndex, 0, $currentClass); + $index = $relatedCompIndex; + } else { + $flushList[] = $relatedClassName; + } + + } else if ($rel instanceof Doctrine_Relation_LocalKey) { + // the related component needs to come before the current component + // in the list (since this component holds the fk). + + if ($relatedCompIndex !== false) { + // already in flush list + if ($relatedCompIndex <= $index) { + // it's in the right place + continue; + } + + unset($flushList[$relatedCompIndex]); + // "this" comp has the fk. so put the related comp before it + // in the list + array_splice($flushList, $index, 0, $relatedClassName); + } else { + array_unshift($flushList, $relatedClassName); + $index++; + } + } else if ($rel instanceof Doctrine_Relation_Association) { + // the association class needs to come after both classes + // that are connected through it in the list (since it holds + // both fks) + + $assocTable = $rel->getAssociationFactory(); + $assocClassName = $assocTable->getComponentName(); + + if ($relatedCompIndex !== false) { + unset($flushList[$relatedCompIndex]); + } + + array_splice($flushList, $index, 0, $relatedClassName); + $index++; + + $index3 = array_search($assocClassName, $flushList); + + if ($index3 !== false) { + if ($index3 >= $index) { + continue; + } + + unset($flushList[$index3]); + array_splice($flushList, $index - 1, 0, $assocClassName); + $index = $relatedCompIndex; + } else { + $flushList[] = $assocClassName; + } + } + } + } + + return array_values($flushList); + } + + + /* The following is all the Class Table Inheritance specific code. Support dropped + for 0.10/1.0. */ + + /** + * Class Table Inheritance code. + * Support dropped for 0.10/1.0. + * + * Note: This is flawed. We also need to delete from subclass tables. + */ + private function _deleteCTIParents(Doctrine_Table $table, $record) + { + if ($table->getOption('joinedParents')) { + foreach (array_reverse($table->getOption('joinedParents')) as $parent) { + $parentTable = $table->getConnection()->getTable($parent); + $this->conn->delete($parentTable, $record->identifier()); + } + } + } + + /** + * Class Table Inheritance code. + * Support dropped for 0.10/1.0. + */ + private function _insertCTIRecord(Doctrine_Table $table, Doctrine_Record $record) + { + $dataSet = $this->_formatDataSet($record); + $component = $table->getComponentName(); + + $classes = $table->getOption('joinedParents'); + $classes[] = $component; + + foreach ($classes as $k => $parent) { + if ($k === 0) { + $rootRecord = new $parent(); + $rootRecord->merge($dataSet[$parent]); + $this->processSingleInsert($rootRecord); + $record->assignIdentifier($rootRecord->identifier()); + } else { + foreach ((array) $rootRecord->identifier() as $id => $value) { + $dataSet[$parent][$id] = $value; + } + + $this->conn->insert($this->conn->getTable($parent), $dataSet[$parent]); + } + } + } + + /** + * Class Table Inheritance code. + * Support dropped for 0.10/1.0. + */ + private function _updateCTIRecord(Doctrine_Table $table, Doctrine_Record $record) + { + $identifier = $record->identifier(); + $dataSet = $this->_formatDataSet($record); + + $component = $table->getComponentName(); + + $classes = $table->getOption('joinedParents'); + $classes[] = $component; + + foreach ($record as $field => $value) { + if ($value instanceof Doctrine_Record) { + if ( ! $value->exists()) { + $value->save(); + } + $record->set($field, $value->getIncremented()); + } + } + + foreach ($classes as $class) { + $parentTable = $this->conn->getTable($class); + + if ( ! array_key_exists($class, $dataSet)) { + continue; + } + + $this->conn->update($this->conn->getTable($class), $dataSet[$class], $identifier); + } + } + + /** + * Class Table Inheritance code. + * Support dropped for 0.10/1.0. + */ + private function _formatDataSet(Doctrine_Record $record) + { + $table = $record->getTable(); + $dataSet = array(); + $component = $table->getComponentName(); + $array = $record->getPrepared(); + + foreach ($table->getColumns() as $columnName => $definition) { + if ( ! isset($dataSet[$component])) { + $dataSet[$component] = array(); + } + + if ( isset($definition['owner']) && ! isset($dataSet[$definition['owner']])) { + $dataSet[$definition['owner']] = array(); + } + + $fieldName = $table->getFieldName($columnName); + if (isset($definition['primary']) && $definition['primary']) { + continue; + } + + if ( ! array_key_exists($fieldName, $array)) { + continue; + } + + if (isset($definition['owner'])) { + $dataSet[$definition['owner']][$fieldName] = $array[$fieldName]; + } else { + $dataSet[$component][$fieldName] = $array[$fieldName]; + } + } + + return $dataSet; + } + + protected function _assignSequence(Doctrine_Record $record, &$fields = null) + { + $table = $record->getTable(); + $seq = $table->sequenceName; + + if ( ! empty($seq)) { + $id = $this->conn->sequence->nextId($seq); + $seqName = $table->getIdentifier(); + if ($fields) { + $fields[$seqName] = $id; + } + + $record->assignIdentifier($id); + + return $id; + } + } + + protected function _assignIdentifier(Doctrine_Record $record) + { + $table = $record->getTable(); + $identifier = $table->getIdentifier(); + $seq = $table->sequenceName; + + if (empty($seq) && !is_array($identifier) && + $table->getIdentifierType() != Doctrine_Core::IDENTIFIER_NATURAL) { + $id = false; + if ($record->$identifier == null) { + if (($driver = strtolower($this->conn->getDriverName())) == 'pgsql') { + $seq = $table->getTableName() . '_' . $table->getColumnName($identifier); + } elseif ($driver == 'oracle' || $driver == 'mssql') { + $seq = $table->getTableName(); + } + + $id = $this->conn->sequence->lastInsertId($seq); + } else { + $id = $record->$identifier; + } + + if ( ! $id) { + throw new Doctrine_Connection_Exception("Couldn't get last insert identifier."); + } + $record->assignIdentifier($id); + } else { + $record->assignIdentifier(true); + } + } +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Core.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Core.php similarity index 94% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Core.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Core.php index ef10b6e..382bf95 100644 --- a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Core.php +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Core.php @@ -1,6 +1,6 @@ getExtensionsClasses(); - } - /** * Load an individual model name and path in to the model loading registry * @@ -605,7 +605,7 @@ public static function loadModel($className, $path = null) * Set the directory where your models are located for PEAR style * naming convention autoloading. * - * @param string $directory + * @param string $directory * @return void */ public static function setModelsDirectory($directory) @@ -651,10 +651,10 @@ public static function loadModels($directory, $modelLoading = null, $classPrefix $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY); - + foreach ($it as $file) { $e = explode('.', $file->getFileName()); - + if (end($e) === 'php' && strpos($file->getFileName(), '.inc') === false) { if ($modelLoading == Doctrine_Core::MODEL_LOADING_PEAR) { $className = str_replace($dir . DIRECTORY_SEPARATOR, null, $file->getPathName()); @@ -664,7 +664,7 @@ public static function loadModels($directory, $modelLoading = null, $classPrefix $className = $e[0]; } - if ($classPrefix) { + if ($classPrefix && $classPrefix != substr($className, 0, strlen($classPrefix))) { $className = $classPrefix . $className; } @@ -677,10 +677,16 @@ public static function loadModels($directory, $modelLoading = null, $classPrefix $declaredBefore = get_declared_classes(); require_once($file->getPathName()); $declaredAfter = get_declared_classes(); - - // Using array_slice because array_diff is broken is some PHP versions - $foundClasses = array_slice($declaredAfter, count($declaredBefore)); - + + if (defined('HHVM_VERSION')) { + // on HHVM get_declared_classes() returns in a different order, array_diff() works, so we have to use it + $foundClasses = array_diff($declaredAfter, $declaredBefore); + } else { + // Using array_slice because array_diff is broken is some PHP versions + // https://bugs.php.net/bug.php?id=47643 + $foundClasses = array_slice($declaredAfter, count($declaredBefore)); + } + if ($foundClasses) { foreach ($foundClasses as $className) { if (self::isValidModelClass($className)) { @@ -690,7 +696,7 @@ public static function loadModels($directory, $modelLoading = null, $classPrefix } } } - + $previouslyLoaded = array_keys(self::$_loadedModelFiles, $file->getPathName()); if ( ! empty($previouslyLoaded)) { @@ -705,9 +711,9 @@ public static function loadModels($directory, $modelLoading = null, $classPrefix } } } - + asort($loadedModels); - + return $loadedModels; } @@ -748,8 +754,14 @@ public static function initializeModels($models) Doctrine_Core::getTable($model); $declaredAfter = get_declared_classes(); - // Using array_slice because array_diff is broken is some PHP versions - $foundClasses = array_slice($declaredAfter, count($declaredBefore) - 1); + if (defined('HHVM_VERSION')) { + // on HHVM get_declared_classes() returns in a different order, array_diff() works, so we have to use it + $foundClasses = array_diff($declaredAfter, $declaredBefore); + } else { + // Using array_slice because array_diff is broken is some PHP versions + // https://bugs.php.net/bug.php?id=47643 + $foundClasses = array_slice($declaredAfter, count($declaredBefore) - 1); + } foreach ($foundClasses as $class) { if (self::isValidModelClass($class)) { $models[] = $class; @@ -803,7 +815,7 @@ public static function isValidModelClass($class) // Skip the following classes // - abstract classes // - not a subclass of Doctrine_Record - if ( ! $class->isAbstract() && $class->isSubClassOf('Doctrine_Record')) { + if ( ! $class->isAbstract() && $class->isSubclassOf('Doctrine_Record')) { return true; } @@ -1004,11 +1016,11 @@ public static function dumpData($yamlPath, $individualFiles = false) * @param string $append Whether or not to append the data * @return void */ - public static function loadData($yamlPath, $append = false) + public static function loadData($yamlPath, $append = false, $charset = 'UTF-8') { $data = new Doctrine_Data(); - return $data->importData($yamlPath, 'yml', array(), $append); + return $data->importData($yamlPath, 'yml', array(), $append, $charset); } /** @@ -1125,7 +1137,7 @@ public static function autoload($className) return true; } - if (0 !== stripos($className, 'Doctrine_') || class_exists($className, false) || interface_exists($className, false)) { + if (0 !== stripos($className, 'Doctrine') || class_exists($className, false) || interface_exists($className, false)) { return false; } @@ -1230,4 +1242,4 @@ public static function dump($var, $output = true, $indent = "") return implode("\n", $ret); } -} \ No newline at end of file +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Data.php similarity index 85% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Data.php index 2fb2f69..b9bcd11 100644 --- a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data.php +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Data.php @@ -21,7 +21,7 @@ /** * Doctrine_Data - * + * * Base Doctrine_Data class for dumping and loading data to and from fixtures files. * Support formats are based on what formats are available in Doctrine_Parser such as yaml, xml, json, etc. * @@ -46,7 +46,7 @@ class Doctrine_Data /** * format - * + * * the default and current format we are working with * * @var string @@ -80,12 +80,14 @@ class Doctrine_Data */ protected $_exportIndividualFiles = false; + protected $_charset = 'UTF-8'; + /** * setFormat * * Set the current format we are working with - * - * @param string $format + * + * @param string $format * @return void */ public function setFormat($format) @@ -97,7 +99,7 @@ public function setFormat($format) * getFormat * * Get the current format we are working with - * + * * @return void */ public function getFormat() @@ -106,10 +108,10 @@ public function getFormat() } /** - * getFormats + * getFormats * * Get array of available formats - * + * * @return void */ public function getFormats() @@ -121,7 +123,7 @@ public function getFormats() * setDirectory * * Set the array/string of directories or yml file paths - * + * * @return void */ public function setDirectory($directory) @@ -133,7 +135,7 @@ public function setDirectory($directory) * getDirectory * * Get directory for dumping/loading data from and to - * + * * @return void */ public function getDirectory() @@ -145,8 +147,8 @@ public function getDirectory() * setModels * * Set the array of specified models to work with - * - * @param string $models + * + * @param string $models * @return void */ public function setModels($models) @@ -167,10 +169,10 @@ public function getModels() } /** - * _exportIndividualFiles + * _exportIndividualFiles * * Set/Get whether or not to export individual files - * + * * @return bool $_exportIndividualFiles */ public function exportIndividualFiles($bool = null) @@ -178,19 +180,29 @@ public function exportIndividualFiles($bool = null) if ($bool !== null) { $this->_exportIndividualFiles = $bool; } - + return $this->_exportIndividualFiles; } + public function setCharset($charset) + { + $this->_charset = $charset; + } + + public function getCharset() + { + return $this->_charset; + } + /** * exportData * * Interface for exporting data to fixtures files from Doctrine models * - * @param string $directory - * @param string $format - * @param string $models - * @param string $_exportIndividualFiles + * @param string $directory + * @param string $format + * @param string $models + * @param string $_exportIndividualFiles * @return void */ public function exportData($directory, $format = 'yml', $models = array(), $_exportIndividualFiles = false) @@ -199,7 +211,7 @@ public function exportData($directory, $format = 'yml', $models = array(), $_exp $export->setFormat($format); $export->setModels($models); $export->exportIndividualFiles($_exportIndividualFiles); - + return $export->doExport(); } @@ -208,17 +220,18 @@ public function exportData($directory, $format = 'yml', $models = array(), $_exp * * Interface for importing data from fixture files to Doctrine models * - * @param string $directory - * @param string $format - * @param string $models + * @param string $directory + * @param string $format + * @param string $models * @return void */ - public function importData($directory, $format = 'yml', $models = array(), $append = false) + public function importData($directory, $format = 'yml', $models = array(), $append = false, $charset = 'UTF-8') { $import = new Doctrine_Data_Import($directory); $import->setFormat($format); $import->setModels($models); - + $import->setCharset($charset); + return $import->doImport($append); } @@ -226,33 +239,33 @@ public function importData($directory, $format = 'yml', $models = array(), $appe * isRelation * * Check if a fieldName on a Doctrine_Record is a relation, if it is we return that relationData - * - * @param string $Doctrine_Record - * @param string $fieldName + * + * @param string $Doctrine_Record + * @param string $fieldName * @return void */ public function isRelation(Doctrine_Record $record, $fieldName) { $relations = $record->getTable()->getRelations(); - + foreach ($relations as $relation) { $relationData = $relation->toArray(); - + if ($relationData['local'] === $fieldName) { return $relationData; } - + } - + return false; } /** * purge - * + * * Purge all data for loaded models or for the passed array of Doctrine_Records * - * @param string $models + * @param string $models * @return void */ public function purge($models = null) @@ -269,11 +282,15 @@ public function purge($models = null) } foreach ($connections as $connection => $models) { - $models = Doctrine_Manager::getInstance()->getConnection($connection)->unitOfWork->buildFlushTree($models); - $models = array_reverse($models); + $conn = Doctrine_Manager::getInstance()->getConnection($connection); + $conn->beginTransaction(); + + $models = array_reverse($conn->unitOfWork->buildFlushTree($models)); foreach ($models as $model) { Doctrine_Core::getTable($model)->createQuery()->delete()->execute(); } + + $conn->commit(); } } -} \ No newline at end of file +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Data/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Data/Exception.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Data/Export.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Data/Export.php new file mode 100644 index 0000000..41dedfa --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Data/Export.php @@ -0,0 +1,213 @@ +. + */ + +/** + * Doctrine_Data_Export + * + * @package Doctrine + * @subpackage Data + * @author Jonathan H. Wage + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.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 + * + * FIXME: This function has ugly hacks in it for temporarily disabling INDEXBY query parts of tables + * to export. + * + * Update from jwage: I am not sure if their is any other better solution for this. It may be the correct + * solution to disable the indexBy settings for tables when exporting data fixtures. Maybe a better idea + * would be to extract this functionality to a pair of functions to enable/disable the index by settings + * so simply turn them on and off when they need to query for the translations standalone and don't need + * it to be indexed by the lang. + * + * @return void + */ + public function doExport() + { + $models = Doctrine_Core::getLoadedModels(); + $specifiedModels = $this->getModels(); + + $data = array(); + + // for situation when the $models array is empty, but the $specifiedModels array isn't + if (empty($models)) { + $models = $specifiedModels; + } + + $models = Doctrine_Core::initializeModels($models); + + // temporarily disable indexBy query parts of selected and related tables + $originalIndexBy = array(); + foreach ($models AS $name) { + $table = Doctrine_Core::getTable($name); + if ( !is_null($indexBy = $table->getBoundQueryPart('indexBy'))) { + $originalIndexBy[$name] = $indexBy; + $table->bindQueryPart('indexBy', null); + } + } + + foreach ($models AS $name) { + if ( ! empty($specifiedModels) AND ! in_array($name, $specifiedModels)) { + continue; + } + + $results = Doctrine_Core::getTable($name)->findAll(); + + if ($results->count() > 0) { + $data[$name] = $results; + } + } + + // Restore the temporarily disabled indexBy query parts + foreach($originalIndexBy AS $name => $indexBy) { + Doctrine_Core::getTable($name)->bindQueryPart('indexBy', $indexBy); + } + + $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) { + $preparedData[$className] = array(); + $keyType = $classData->getTable()->getIdentifierType(); + foreach ($classData as $record) { + $className = get_class($record); + $recordKey = $className . '_' . implode('_', $record->identifier()); + $preparedData[$className][$recordKey] = array(); + + // skip single primary keys, we need to maintain composite primary keys + $keys = $record->getTable()->getIdentifier(); + + $recordData = $record->toArray(false); + + foreach ($recordData as $key => $value) { + if ( ! is_array($keys)) { + $keys = array($keys); + } + + if ($keyType !== Doctrine_Core::IDENTIFIER_NATURAL && count($keys) <= 1 && in_array($key, $keys)) { + continue; + } + + if (is_object($record[$key])) { + // If the field is an object serialize it + $value = serialize($record[$key]); + } + + if ($relation = $this->isRelation($record, $key)) { + if ( ! $value) { + continue; + } + $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 if ($record->getTable()->hasField($key)) { + $preparedData[$className][$recordKey][$key] = $value; + } + } + } + } + + return $preparedData; + } +} \ No newline at end of file diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data/Import.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Data/Import.php similarity index 98% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data/Import.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Data/Import.php index 649acbf..23d0f60 100644 --- a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data/Import.php +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Data/Import.php @@ -78,12 +78,12 @@ public function doParsing() // If they specified a specific yml file if (end($e) == 'yml') { - $array = $mergeFunction($array, Doctrine_Parser::load($dir, $this->getFormat())); + $array = $mergeFunction($array, Doctrine_Parser::load($dir, $this->getFormat(), $this->getCharset())); // If they specified a directory } else if (is_dir($dir)) { $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY); - $filesOrdered = array(); + $filesOrdered = array(); foreach ($it as $file) { $filesOrdered[] = $file; } @@ -92,7 +92,7 @@ public function doParsing() foreach ($filesOrdered as $file) { $e = explode('.', $file->getFileName()); if (in_array(end($e), $this->getFormats())) { - $array = $mergeFunction($array, Doctrine_Parser::load($file->getPathName(), $this->getFormat())); + $array = $mergeFunction($array, Doctrine_Parser::load($file->getPathName(), $this->getFormat(), $this->getCharset())); } } } @@ -138,7 +138,7 @@ protected function _buildRows($className, $data) $rel = $table->getRelation($key); $relClassName = $rel->getTable()->getOption('name'); $relRowKey = $rowKey . '_' . $relClassName; - + if ($rel->getType() == Doctrine_Relation::ONE) { $val = array($relRowKey => $value); $this->_rows[$className][$rowKey][$key] = $relRowKey; @@ -146,7 +146,7 @@ protected function _buildRows($className, $data) $val = $value; $this->_rows[$className][$rowKey][$key] = array_keys($val); } - + $this->_buildRows($relClassName, $val); } } @@ -183,7 +183,7 @@ protected function _buildNestedSetRows($className, $data) */ protected function _getImportedObject($rowKey, Doctrine_Record $record, $relationName, $referringRowKey) { - $relation = $record->getTable()->getRelation($relationName); + $relation = $record->getTable()->getRelation($relationName); $rowKey = $this->_getRowKeyPrefix($relation->getTable()) . $rowKey; if ( ! isset($this->_importedObjects[$rowKey])) { @@ -338,6 +338,7 @@ protected function _loadData(array $array) foreach ($manager as $connection) { $tree = $connection->unitOfWork->buildFlushTree(array_keys($array)); + $connection->beginTransaction(); foreach ($tree as $model) { foreach ($this->_importedObjects as $obj) { @@ -346,8 +347,8 @@ protected function _loadData(array $array) } } } + $connection->commit(); } - } /** @@ -399,4 +400,4 @@ protected function _getRowKeyPrefix(Doctrine_Table $table) { return sprintf('(%s) ', $table->getTableName()); } -} \ No newline at end of file +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Exception.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Mssql.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Mssql.php new file mode 100644 index 0000000..59220b3 --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Mssql.php @@ -0,0 +1,273 @@ +. + */ + +/** + * @package Doctrine + * @subpackage DataDict + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen + * @author Lukas Smith (PEAR MDB2 library) + * @author Frank M. Kromann (PEAR MDB2 Mssql driver) + * @author David Coallier (PEAR MDB2 Mssql driver) + * @version $Revision: 7660 $ + * @link www.doctrine-project.org + * @since 1.0 + */ +class Doctrine_DataDict_Mssql extends Doctrine_DataDict +{ + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getNativeDeclaration($field) + { + if ( ! isset($field['type'])) { + throw new Doctrine_DataDict_Exception('Missing column type.'); + } + switch ($field['type']) { + case 'enum': + $field['length'] = isset($field['length']) && $field['length'] ? $field['length']:255; + case 'array': + case 'object': + case 'text': + case 'char': + case 'varchar': + case 'string': + case 'gzip': + $length = !empty($field['length']) + ? $field['length'] : false; + + $fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false; + + return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$this->conn->varchar_max_length.')') + : (($length && $length <= $this->conn->varchar_max_length) ? 'VARCHAR('.$length.')' : 'TEXT'); + case 'clob': + if ( ! empty($field['length'])) { + $length = $field['length']; + if ($length <= 8000) { + return 'VARCHAR('.$length.')'; + } + } + return 'TEXT'; + case 'blob': + if ( ! empty($field['length'])) { + $length = $field['length']; + if ($length <= 8000) { + return "VARBINARY($length)"; + } + } + return 'IMAGE'; + case 'integer': + case 'int': + return (isset($field['unsigned']) && $field['unsigned']) ? 'BIGINT' : 'INT'; + case 'boolean': + return 'BIT'; + case 'date': + return 'CHAR(' . strlen('YYYY-MM-DD') . ')'; + case 'time': + return 'CHAR(' . strlen('HH:MM:SS') . ')'; + case 'timestamp': + return 'CHAR(' . strlen('YYYY-MM-DD HH:MM:SS') . ')'; + case 'float': + return 'FLOAT'; + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + $scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine_Core::ATTR_DECIMAL_PLACES); + return 'DECIMAL('.$length.','.$scale.')'; + } + return $field['type'] . (isset($field['length']) ? '('.$field['length'].')':null); + } + + /** + * Maps a native array description of a field to a MDB2 datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + */ + public function getPortableDeclaration($field) + { + $db_type = preg_replace('/[\d\(\)]/','', strtolower($field['type']) ); + $length = (isset($field['length']) && $field['length'] > 0) ? $field['length'] : null; + + $type = array(); + // todo: unsigned handling seems to be missing + $unsigned = $fixed = null; + + if ( ! isset($field['name'])) + $field['name'] = ''; + + switch ($db_type) { + case 'bit': + $type[0] = 'boolean'; + break; + case 'tinyint': + case 'smallint': + case 'bigint': + case 'int': + $type[0] = 'integer'; + if ($length == 1) { + $type[] = 'boolean'; + } + break; + case 'date': + $type[0] = 'date'; + break; + case 'datetime': + case 'timestamp': + case 'smalldatetime': + $type[0] = 'timestamp'; + break; + case 'float': + case 'real': + case 'numeric': + $type[0] = 'float'; + break; + case 'decimal': + case 'money': + case 'smallmoney': + $type[0] = 'decimal'; + break; + case 'text': + case 'varchar': + case 'ntext': + case 'nvarchar': + $fixed = false; + case 'char': + case 'nchar': + $type[0] = 'string'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^[is|has]/', $field['name'])) { + $type = array_reverse($type); + } + } elseif (strstr($db_type, 'text')) { + $type[] = 'clob'; + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'image': + case 'varbinary': + $type[] = 'blob'; + $length = null; + break; + case 'uniqueidentifier': + $type[] = 'string'; + $length = 36; + break; + case 'sql_variant': + case 'sysname': + case 'binary': + $type[] = 'string'; + $length = null; + break; + default: + $type[] = $field['type']; + $length = isset($field['length']) ? $field['length']:null; + } + + return array('type' => $type, + 'length' => $length, + 'unsigned' => $unsigned, + 'fixed' => $fixed); + } + + /** + * Obtain DBMS specific SQL code portion needed to declare an integer type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param string $field associative array with the name of the properties + * of the field being declared as array indexes. + * Currently, the types of supported field + * properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field + * should be declared as unsigned integer if + * possible. + * + * default + * Integer value to be used as default for this + * field. + * + * notnull + * Boolean flag that indicates whether this field is + * constrained to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getIntegerDeclaration($name, $field) + { + $default = $autoinc = ''; + if ( ! empty($field['autoincrement'])) { + $autoinc = ' identity'; + } elseif (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) ? null : 0; + } + + $value = (is_null($field['default']) + ? 'NULL' + : $this->conn->quote($field['default'])); + + // Name the constraint if a name has been supplied + if (array_key_exists('defaultConstraintName', $field)) { + $default .= ' CONSTRAINT ' . $field['defaultConstraintName']; + } + + $default .= ' DEFAULT ' . $value; + } + + + $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ' NULL'; + //$unsigned = (isset($field['unsigned']) && $field['unsigned']) ? ' UNSIGNED' : ''; + // MSSQL does not support the UNSIGNED keyword + $unsigned = ''; + $comment = (isset($field['comment']) && $field['comment']) + ? " COMMENT " . $this->conn->quote($field['comment'], 'text') : ''; + + $name = $this->conn->quoteIdentifier($name, true); + + return $name . ' ' . $this->getNativeDeclaration($field) . $unsigned + . $default . $notnull . $autoinc . $comment; + } +} \ No newline at end of file diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Mysql.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Mysql.php new file mode 100644 index 0000000..3bb9d26 --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Mysql.php @@ -0,0 +1,514 @@ +. + */ + +/** + * @package Doctrine + * @subpackage DataDict + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen + * @author Lukas Smith (PEAR MDB2 library) + * @version $Revision: 7635 $ + * @link www.doctrine-project.org + * @since 1.0 + */ +class Doctrine_DataDict_Mysql extends Doctrine_DataDict +{ + protected $keywords = array( + 'ADD', 'ALL', 'ALTER', + 'ANALYZE', 'AND', 'AS', + 'ASC', 'ASENSITIVE', 'BEFORE', + 'BETWEEN', 'BIGINT', 'BINARY', + 'BLOB', 'BOTH', 'BY', 'BIT', + 'CALL', 'CASCADE', 'CASE', + 'CHANGE', 'CHAR', 'CHARACTER', + 'CHECK', 'COLLATE', 'COLUMN', + 'CONDITION', 'CONNECTION', 'CONSTRAINT', + 'CONTINUE', 'CONVERT', 'CREATE', + 'CROSS', 'CURRENT_DATE', 'CURRENT_TIME', + 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'CURSOR', + 'DATABASE', 'DATABASES', 'DAY_HOUR', + 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', + 'DEC', 'DECIMAL', 'DECLARE', + 'DEFAULT', 'DELAYED', 'DELETE', + 'DESC', 'DESCRIBE', 'DETERMINISTIC', + 'DISTINCT', 'DISTINCTROW', 'DIV', + 'DOUBLE', 'DROP', 'DUAL', + 'EACH', 'ELSE', 'ELSEIF', + 'ENCLOSED', 'ESCAPED', 'EXISTS', + 'EXIT', 'EXPLAIN', 'FALSE', + 'FETCH', 'FLOAT', 'FLOAT4', + 'FLOAT8', 'FOR', 'FORCE', + 'FOREIGN', 'FROM', 'FULLTEXT', + 'GRANT', 'GROUP', 'HAVING', + 'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE', + 'HOUR_SECOND', 'IF', 'IGNORE', + 'IN', 'INDEX', 'INFILE', + 'INNER', 'INOUT', 'INSENSITIVE', + 'INSERT', 'INT', 'INT1', + 'INT2', 'INT3', 'INT4', + 'INT8', 'INTEGER', 'INTERVAL', + 'INTO', 'IS', 'ITERATE', + 'JOIN', 'KEY', 'KEYS', + 'KILL', 'LEADING', 'LEAVE', + 'LEFT', 'LIKE', 'LIMIT', + 'LINES', 'LOAD', 'LOCALTIME', + 'LOCALTIMESTAMP', 'LOCK', 'LONG', + 'LONGBLOB', 'LONGTEXT', 'LOOP', + 'LOW_PRIORITY', 'MATCH', 'MEDIUMBLOB', + 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', + 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD', + 'MODIFIES', 'NATURAL', 'NOT', + 'NO_WRITE_TO_BINLOG', 'NULL', 'NUMERIC', + 'ON', 'OPTIMIZE', 'OPTION', + 'OPTIONALLY', 'OR', 'ORDER', + 'OUT', 'OUTER', 'OUTFILE', + 'PRECISION', 'PRIMARY', 'PROCEDURE', + 'PURGE', 'RAID0', 'READ', + 'READS', 'REAL', 'REFERENCES', + 'REGEXP', 'RELEASE', 'RENAME', + 'REPEAT', 'REPLACE', 'REQUIRE', + 'RESTRICT', 'RETURN', 'REVOKE', + 'RIGHT', 'RLIKE', 'SCHEMA', + 'SCHEMAS', 'SECOND_MICROSECOND', 'SELECT', + 'SENSITIVE', 'SEPARATOR', 'SET', + 'SHOW', 'SMALLINT', 'SONAME', + 'SPATIAL', 'SPECIFIC', 'SQL', + 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', + 'SQL_BIG_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT', + 'SSL', 'STARTING', 'STRAIGHT_JOIN', + 'TABLE', 'TERMINATED', 'THEN', + 'TINYBLOB', 'TINYINT', 'TINYTEXT', + 'TO', 'TRAILING', 'TRIGGER', + 'TRUE', 'UNDO', 'UNION', + 'UNIQUE', 'UNLOCK', 'UNSIGNED', + 'UPDATE', 'USAGE', 'USE', + 'USING', 'UTC_DATE', 'UTC_TIME', + 'UTC_TIMESTAMP', 'VALUES', 'VARBINARY', + 'VARCHAR', 'VARCHARACTER', 'VARYING', + 'WHEN', 'WHERE', 'WHILE', + 'WITH', 'WRITE', 'X509', + 'XOR', 'YEAR_MONTH', 'ZEROFILL' + ); + + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getNativeDeclaration($field) + { + if ( ! isset($field['type'])) { + throw new Doctrine_DataDict_Exception('Missing column type.'); + } + + switch ($field['type']) { + case 'char': + $length = ( ! empty($field['length'])) ? $field['length'] : false; + + return $length ? 'CHAR('.$length.')' : 'CHAR(255)'; + case 'enum': + if ($this->conn->getAttribute(Doctrine_Core::ATTR_USE_NATIVE_ENUM)) { + $values = array(); + foreach ($field['values'] as $value) { + $values[] = $this->conn->quote($value, 'varchar'); + } + return 'ENUM('.implode(', ', $values).')'; + } else { + $field['length'] = isset($field['length']) && $field['length'] ? $field['length']:255; + } + case 'set': + if ($this->conn->getAttribute(Doctrine_Core::ATTR_USE_NATIVE_SET)) { + $values = array(); + foreach ($field['values'] as $value) { + $values[] = $this->conn->quote($value, 'varchar'); + } + return 'SET('.implode(', ', $values).')'; + } else { + $field['length'] = isset($field['length']) && $field['length'] ? $field['length']:255; + } + case 'varchar': + case 'string': + case 'gzip': + if ( ! isset($field['length'])) { + if (array_key_exists('default', $field)) { + $field['length'] = $this->conn->varchar_max_length; + } else { + $field['length'] = false; + } + } + + $length = ($field['length'] <= $this->conn->varchar_max_length) ? $field['length'] : false; + $fixed = (isset($field['fixed'])) ? $field['fixed'] : false; + + return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') + : ($length ? 'VARCHAR(' . $length . ')' : 'TEXT'); + case 'array': + case 'object': + case 'clob': + if ( ! empty($field['length'])) { + $length = $field['length']; + if ($length <= 255) { + return 'TINYTEXT'; + } elseif ($length <= 65532) { + return 'TEXT'; + } elseif ($length <= 16777215) { + return 'MEDIUMTEXT'; + } + } + return 'LONGTEXT'; + case 'blob': + if ( ! empty($field['length'])) { + $length = $field['length']; + if ($length <= 255) { + return 'TINYBLOB'; + } elseif ($length <= 65532) { + return 'BLOB'; + } elseif ($length <= 16777215) { + return 'MEDIUMBLOB'; + } + } + return 'LONGBLOB'; + case 'integer': + case 'int': + if ( ! empty($field['length'])) { + $length = $field['length']; + if ($length <= 1) { + return 'TINYINT'; + } elseif ($length == 2) { + return 'SMALLINT'; + } elseif ($length == 3) { + return 'MEDIUMINT'; + } elseif ($length == 4) { + return 'INT'; + } elseif ($length > 4) { + return 'BIGINT'; + } + } + return 'INT'; + case 'boolean': + return 'TINYINT(1)'; + case 'date': + return 'DATE'; + case 'time': + return 'TIME'; + case 'timestamp': + return 'DATETIME'; + case 'float': + $length = !empty($field['length']) ? $field['length'] : 18; + $scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine_Core::ATTR_DECIMAL_PLACES); + return 'FLOAT('.$length.', '.$scale.')'; + case 'double': + $length = !empty($field['length']) ? $field['length'] : 18; + $scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine_Core::ATTR_DECIMAL_PLACES); + return 'DOUBLE('.$length.', '.$scale.')'; + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + $scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine_Core::ATTR_DECIMAL_PLACES); + return 'DECIMAL('.$length.', '.$scale.')'; + case 'bit': + return 'BIT'; + } + return $field['type'] . (isset($field['length']) ? '('.$field['length'].')':null); + } + + /** + * Maps a native array description of a field to a MDB2 datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + */ + public function getPortableDeclaration(array $field) + { + $dbType = strtolower($field['type']); + $dbType = strtok($dbType, '(), '); + if ($dbType == 'national') { + $dbType = strtok('(), '); + } + if (isset($field['length'])) { + $length = $field['length']; + $decimal = ''; + } else { + $length = strtok('(), '); + $decimal = strtok('(), '); + if ( ! $decimal ) { + $decimal = null; + } + } + $type = array(); + $unsigned = $fixed = null; + + if ( ! isset($field['name'])) { + $field['name'] = ''; + } + + $values = null; + $scale = null; + + switch ($dbType) { + case 'tinyint': + $type[] = 'integer'; + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 1; + break; + case 'smallint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 2; + break; + case 'mediumint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 3; + break; + case 'int': + case 'integer': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 4; + break; + case 'bigint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 8; + break; + case 'tinytext': + case 'mediumtext': + case 'longtext': + case 'text': + case 'text': + case 'varchar': + $fixed = false; + case 'string': + case 'char': + $type[] = 'string'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } elseif (strstr($dbType, 'text')) { + $type[] = 'clob'; + if ($decimal == 'binary') { + $type[] = 'blob'; + } + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'enum': + $type[] = 'enum'; + preg_match_all('/\'((?:\'\'|[^\'])*)\'/', $field['type'], $matches); + $length = 0; + $fixed = false; + if (is_array($matches)) { + foreach ($matches[1] as &$value) { + $value = str_replace('\'\'', '\'', $value); + $length = max($length, strlen($value)); + } + if ($length == '1' && count($matches[1]) == 2) { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + + $values = $matches[1]; + } + $type[] = 'integer'; + break; + case 'set': + $fixed = false; + $type[] = 'text'; + $type[] = 'integer'; + break; + case 'date': + $type[] = 'date'; + $length = null; + break; + case 'datetime': + case 'timestamp': + $type[] = 'timestamp'; + $length = null; + break; + case 'time': + $type[] = 'time'; + $length = null; + break; + case 'float': + case 'double': + case 'real': + $type[] = 'float'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + break; + case 'unknown': + case 'decimal': + if ($decimal !== null) { + $scale = $decimal; + } + case 'numeric': + $type[] = 'decimal'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + break; + case 'tinyblob': + case 'mediumblob': + case 'longblob': + case 'blob': + case 'binary': + case 'varbinary': + $type[] = 'blob'; + $length = null; + break; + case 'year': + $type[] = 'integer'; + $type[] = 'date'; + $length = null; + break; + case 'bit': + $type[] = 'bit'; + break; + case 'geometry': + case 'geometrycollection': + case 'point': + case 'multipoint': + case 'linestring': + case 'multilinestring': + case 'polygon': + case 'multipolygon': + $type[] = 'blob'; + $length = null; + break; + default: + $type[] = $field['type']; + $length = isset($field['length']) ? $field['length']:null; + } + + $length = ((int) $length == 0) ? null : (int) $length; + $def = array('type' => $type, 'length' => $length, 'unsigned' => $unsigned, 'fixed' => $fixed); + if ($values !== null) { + $def['values'] = $values; + } + if ($scale !== null) { + $def['scale'] = $scale; + } + return $def; + } + + /** + * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $charset name of the charset + * @return string DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration. + */ + public function getCharsetFieldDeclaration($charset) + { + return 'CHARACTER SET ' . $charset; + } + + /** + * Obtain DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $collation name of the collation + * @return string DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration. + */ + public function getCollationFieldDeclaration($collation) + { + return 'COLLATE ' . $collation; + } + + /** + * Obtain DBMS specific SQL code portion needed to declare an integer type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param string $field associative array with the name of the properties + * of the field being declared as array indexes. + * Currently, the types of supported field + * properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field + * should be declared as unsigned integer if + * possible. + * + * default + * Integer value to be used as default for this + * field. + * + * notnull + * Boolean flag that indicates whether this field is + * constrained to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getIntegerDeclaration($name, $field) + { + $unique = (isset($field['unique']) && $field['unique']) ? ' UNIQUE' : ''; + $default = $autoinc = ''; + if ( ! empty($field['autoincrement'])) { + $autoinc = ' AUTO_INCREMENT'; + } elseif (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) ? null : 0; + } + + $default = ' DEFAULT ' . (is_null($field['default']) + ? 'NULL' + : $this->conn->quote($field['default'])); + } + + $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ''; + $unsigned = (isset($field['unsigned']) && $field['unsigned']) ? ' UNSIGNED' : ''; + $comment = (isset($field['comment']) && $field['comment']) + ? " COMMENT " . $this->conn->quote($field['comment'], 'text') : ''; + + $name = $this->conn->quoteIdentifier($name, true); + + return $name . ' ' . $this->getNativeDeclaration($field) . $unsigned + . $default . $unique . $notnull . $autoinc . $comment; + } +} \ No newline at end of file diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Oracle.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Oracle.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Oracle.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Oracle.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Pgsql.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Pgsql.php new file mode 100644 index 0000000..da1cc9e --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Pgsql.php @@ -0,0 +1,686 @@ +. + */ + +/** + * @package Doctrine + * @subpackage DataDict + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen + * @author Paul Cooper + * @author Lukas Smith (PEAR MDB2 library) + * @version $Revision: 7641 $ + * @link www.doctrine-project.org + * @since 1.0 + */ +class Doctrine_DataDict_Pgsql extends Doctrine_DataDict +{ + /** + * @param array $reservedKeyWords an array of reserved keywords by pgsql + */ + protected static $reservedKeyWords = array( + 'abort', + 'absolute', + 'access', + 'action', + 'add', + 'after', + 'aggregate', + 'all', + 'alter', + 'analyse', + 'analyze', + 'and', + 'any', + 'as', + 'asc', + 'assertion', + 'assignment', + 'at', + 'authorization', + 'backward', + 'before', + 'begin', + 'between', + 'bigint', + 'binary', + 'bit', + 'boolean', + 'both', + 'by', + 'cache', + 'called', + 'cascade', + 'case', + 'cast', + 'chain', + 'char', + 'character', + 'characteristics', + 'check', + 'checkpoint', + 'class', + 'close', + 'cluster', + 'coalesce', + 'collate', + 'column', + 'comment', + 'commit', + 'committed', + 'constraint', + 'constraints', + 'conversion', + 'convert', + 'copy', + 'create', + 'createdb', + 'createuser', + 'cross', + 'current_date', + 'current_time', + 'current_timestamp', + 'current_user', + 'cursor', + 'cycle', + 'database', + 'day', + 'deallocate', + 'dec', + 'decimal', + 'declare', + 'default', + 'deferrable', + 'deferred', + 'definer', + 'delete', + 'delimiter', + 'delimiters', + 'desc', + 'distinct', + 'do', + 'domain', + 'double', + 'drop', + 'each', + 'else', + 'encoding', + 'encrypted', + 'end', + 'escape', + 'except', + 'exclusive', + 'execute', + 'exists', + 'explain', + 'external', + 'extract', + 'false', + 'fetch', + 'float', + 'for', + 'force', + 'foreign', + 'forward', + 'freeze', + 'from', + 'full', + 'function', + 'get', + 'global', + 'grant', + 'group', + 'handler', + 'having', + 'hour', + 'ilike', + 'immediate', + 'immutable', + 'implicit', + 'in', + 'increment', + 'index', + 'inherits', + 'initially', + 'inner', + 'inout', + 'input', + 'insensitive', + 'insert', + 'instead', + 'int', + 'integer', + 'intersect', + 'interval', + 'into', + 'invoker', + 'is', + 'isnull', + 'isolation', + 'join', + 'key', + 'lancompiler', + 'language', + 'leading', + 'left', + 'level', + 'like', + 'limit', + 'listen', + 'load', + 'local', + 'localtime', + 'localtimestamp', + 'location', + 'lock', + 'match', + 'maxvalue', + 'minute', + 'minvalue', + 'mode', + 'month', + 'move', + 'names', + 'national', + 'natural', + 'nchar', + 'new', + 'next', + 'no', + 'nocreatedb', + 'nocreateuser', + 'none', + 'not', + 'nothing', + 'notify', + 'notnull', + 'null', + 'nullif', + 'numeric', + 'of', + 'off', + 'offset', + 'oids', + 'old', + 'on', + 'only', + 'operator', + 'option', + 'or', + 'order', + 'out', + 'outer', + 'overlaps', + 'overlay', + 'owner', + 'partial', + 'password', + 'path', + 'pendant', + 'placing', + 'position', + 'precision', + 'prepare', + 'primary', + 'prior', + 'privileges', + 'procedural', + 'procedure', + 'read', + 'real', + 'recheck', + 'references', + 'reindex', + 'relative', + 'rename', + 'replace', + 'reset', + 'restrict', + 'returns', + 'revoke', + 'right', + 'rollback', + 'row', + 'rule', + 'schema', + 'scroll', + 'second', + 'security', + 'select', + 'sequence', + 'serializable', + 'session', + 'session_user', + 'set', + 'setof', + 'share', + 'show', + 'similar', + 'simple', + 'smallint', + 'some', + 'stable', + 'start', + 'statement', + 'statistics', + 'stdin', + 'stdout', + 'storage', + 'strict', + 'substring', + 'sysid', + 'table', + 'temp', + 'template', + 'temporary', + 'then', + 'time', + 'timestamp', + 'to', + 'toast', + 'trailing', + 'transaction', + 'treat', + 'trigger', + 'trim', + 'true', + 'truncate', + 'trusted', + 'type', + 'unencrypted', + 'union', + 'unique', + 'unknown', + 'unlisten', + 'until', + 'update', + 'usage', + 'user', + 'using', + 'vacuum', + 'valid', + 'validator', + 'values', + 'varchar', + 'varying', + 'verbose', + 'version', + 'view', + 'volatile', + 'when', + 'where', + 'with', + 'without', + 'work', + 'write', + 'year', + 'zone' + ); + + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getNativeDeclaration(array $field) + { + if ( ! isset($field['type'])) { + throw new Doctrine_DataDict_Exception('Missing column type.'); + } + + // Postgres enum type by name containing enum + if (strpos($field['type'], 'enum') !== false){ + $field['type'] = 'enum'; + } + + switch ($field['type']) { + case 'enum': + $field['length'] = isset($field['length']) && $field['length'] ? $field['length']:255; + case 'char': + case 'string': + case 'array': + case 'object': + case 'varchar': + case 'gzip': + // TODO: what is the maximum VARCHAR length in pgsql ? + $length = (isset($field['length']) && $field['length'] && $field['length'] < 10000) ? $field['length'] : null; + + $fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false; + + return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR('.$this->conn->varchar_max_length.')') + : ($length ? 'VARCHAR(' .$length . ')' : 'TEXT'); + + case 'clob': + return 'TEXT'; + case 'blob': + return 'BYTEA'; + case 'integer': + case 'int': + if ( ! empty($field['autoincrement'])) { + if ( ! empty($field['length'])) { + $length = $field['length']; + if ($length > 4) { + return 'BIGSERIAL'; + } + } + return 'SERIAL'; + } + if ( ! empty($field['length'])) { + $length = $field['length']; + if ($length <= 2) { + return 'SMALLINT'; + } elseif ($length == 3 || $length == 4) { + return 'INT'; + } elseif ($length > 4) { + return 'BIGINT'; + } + } + return 'INT'; + case 'inet': + return 'INET'; + case 'bit': + case 'varbit': + return 'VARBIT'; + case 'boolean': + return 'BOOLEAN'; + case 'date': + return 'DATE'; + case 'time': + return 'TIME'; + case 'timestamp': + return 'TIMESTAMP'; + case 'float': + case 'double': + return 'FLOAT'; + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + $scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine_Core::ATTR_DECIMAL_PLACES); + return 'NUMERIC('.$length.','.$scale.')'; + } + return $field['type'] . (isset($field['length']) ? '('.$field['length'].')':null); + } + + /** + * Maps a native array description of a field to a portable Doctrine datatype and length + * + * @param array $field native field description + * + * @return array containing the various possible types, length, sign, fixed + */ + public function getPortableDeclaration(array $field) + { + $length = (isset($field['length'])) ? $field['length'] : null; + if ($length == '-1' && isset($field['atttypmod'])) { + $length = $field['atttypmod'] - 4; + } + if ((int)$length <= 0) { + $length = null; + } + $type = array(); + $unsigned = $fixed = null; + + if ( ! isset($field['name'])) { + $field['name'] = ''; + } + + $dbType = strtolower($field['type']); + + // Default from field for enum support + $default = isset($field['default']) ? $field['default'] : null; + $enumName = null; + if (strpos($dbType, 'enum') !== false){ + $enumName = $dbType; + $dbType = 'enum'; + } + + switch ($dbType) { + case 'inet': + $type[] = 'inet'; + break; + case 'bit': + case 'varbit': + $type[] = 'bit'; + break; + case 'smallint': + case 'int2': + $type[] = 'integer'; + $unsigned = false; + $length = 2; + if ($length == '2') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + break; + case 'int': + case 'int4': + case 'integer': + case 'serial': + case 'serial4': + $type[] = 'integer'; + $unsigned = false; + $length = 4; + break; + case 'bigint': + case 'int8': + case 'bigserial': + case 'serial8': + $type[] = 'integer'; + $unsigned = false; + $length = 8; + break; + case 'bool': + case 'boolean': + $type[] = 'boolean'; + $length = 1; + break; + case 'text': + case 'varchar': + case 'interval': + case '_varchar': + $fixed = false; + case 'tsvector': + case 'unknown': + case 'char': + case 'character': + case 'bpchar': + $type[] = 'string'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } elseif (strstr($dbType, 'text')) { + $type[] = 'clob'; + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'enum': + $type[] = 'enum'; + $length = $length ? $length :255; + if($default) { + $default = preg_replace('/\'(\w+)\'.*/', '${1}', $default); + } + break; + case 'date': + $type[] = 'date'; + $length = null; + break; + case 'datetime': + case 'timestamp': + case 'timetz': + case 'timestamptz': + $type[] = 'timestamp'; + $length = null; + break; + case 'time': + $type[] = 'time'; + $length = null; + break; + case 'float': + case 'float4': + case 'float8': + case 'double': + case 'double precision': + case 'real': + $type[] = 'float'; + break; + case 'decimal': + case 'money': + case 'numeric': + $type[] = 'decimal'; + break; + case 'tinyblob': + case 'mediumblob': + case 'longblob': + case 'blob': + case 'bytea': + case 'geometry': + case 'geometrycollection': + case 'point': + case 'multipoint': + case 'linestring': + case 'multilinestring': + case 'polygon': + case 'multipolygon': + $type[] = 'blob'; + $length = null; + break; + case 'oid': + $type[] = 'blob'; + $type[] = 'clob'; + $length = null; + break; + case 'year': + $type[] = 'integer'; + $type[] = 'date'; + $length = null; + break; + default: + $type[] = $field['type']; + $length = isset($field['length']) ? $field['length']:null; + } + + $ret = array('type' => $type, + 'length' => $length, + 'unsigned' => $unsigned, + 'fixed' => $fixed); + + // If this is postgresql enum type we will have non-null values here + if ($default !== null) { + $ret['default'] = $default; + } + if ($enumName !== null) { + $ret['enumName'] = $enumName; + } + return $ret; + } + + /** + * Obtain DBMS specific SQL code portion needed to declare an integer type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field should be + * declared as unsigned integer if possible. + * + * default + * Integer value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getIntegerDeclaration($name, $field) + { + /** + if ( ! empty($field['unsigned'])) { + $this->conn->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer"; + } + */ + + if ( ! empty($field['autoincrement'])) { + $name = $this->conn->quoteIdentifier($name, true); + return $name . ' ' . $this->getNativeDeclaration($field); + } + + $default = ''; + if (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) ? null : 0; + } + + $default = ' DEFAULT ' . (is_null($field['default']) + ? 'NULL' + : $this->conn->quote($field['default'], $field['type'])); + } + /** + TODO: is this needed ? + elseif (empty($field['notnull'])) { + $default = ' DEFAULT NULL'; + } + */ + + $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; + $name = $this->conn->quoteIdentifier($name, true); + return $name . ' ' . $this->getNativeDeclaration($field) . $default . $notnull; + } + + /** + * parseBoolean + * parses a literal boolean value and returns + * proper sql equivalent + * + * @param string $value boolean value to be parsed + * @return string parsed boolean value + */ + public function parseBoolean($value) + { + return $value; + } +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Sqlite.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Sqlite.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Sqlite.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/DataDict/Sqlite.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Event.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Event.php new file mode 100644 index 0000000..408d8ba --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Event.php @@ -0,0 +1,375 @@ +. + */ + +/** + * Doctrine_Event + * + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @package Doctrine + * @subpackage Event + * @link www.doctrine-project.org + * @since 1.0 + * @version $Revision$ + */ +class Doctrine_Event +{ + /** + * CONNECTION EVENT CODES + */ + const CONN_QUERY = 1; + const CONN_EXEC = 2; + const CONN_PREPARE = 3; + const CONN_CONNECT = 4; + const CONN_CLOSE = 5; + const CONN_ERROR = 6; + + const STMT_EXECUTE = 10; + const STMT_FETCH = 11; + const STMT_FETCHALL = 12; + + const TX_BEGIN = 31; + const TX_COMMIT = 32; + const TX_ROLLBACK = 33; + const SAVEPOINT_CREATE = 34; + const SAVEPOINT_ROLLBACK = 35; + const SAVEPOINT_COMMIT = 36; + + const HYDRATE = 40; + + /* + * RECORD EVENT CODES + */ + const RECORD_DELETE = 21; + const RECORD_SAVE = 22; + const RECORD_UPDATE = 23; + const RECORD_INSERT = 24; + const RECORD_SERIALIZE = 25; + const RECORD_UNSERIALIZE = 26; + const RECORD_DQL_DELETE = 27; + const RECORD_DQL_SELECT = 28; + const RECORD_DQL_UPDATE = 29; + const RECORD_VALIDATE = 30; + + /** + * @var mixed $_nextSequence the sequence of the next event that will be created + */ + static protected $_nextSequence = 0; + + /** + * @var mixed $_sequence the sequence of this event + */ + protected $_sequence; + + /** + * @var mixed $_invoker the handler which invoked this event + */ + protected $_invoker; + + /** + * @var string $_query the sql query associated with this event (if any) + */ + protected $_query; + + /** + * @var string $_params the parameters associated with the query (if any) + */ + protected $_params; + + /** + * @see Doctrine_Event constants + * @var integer $_code the event code + */ + protected $_code; + + /** + * @var integer $_startedMicrotime the time point in which this event was started + */ + protected $_startedMicrotime; + + /** + * @var integer $_endedMicrotime the time point in which this event was ended + */ + protected $_endedMicrotime; + + /** + * @var array $_options an array of options + */ + protected $_options = array(); + + /** + * constructor + * + * @param Doctrine_Connection|Doctrine_Connection_Statement| + Doctrine_Connection_UnitOfWork|Doctrine_Transaction $invoker the handler which invoked this event + * @param integer $code the event code + * @param string $query the sql query associated with this event (if any) + */ + public function __construct($invoker, $code, $query = null, $params = array()) + { + $this->_sequence = self::$_nextSequence++; + $this->_invoker = $invoker; + $this->_code = $code; + $this->_query = $query; + $this->_params = $params; + } + + /** + * getQuery + * + * @return Doctrine_Query returns the query associated with this event (if any) + */ + public function getQuery() + { + return $this->_query; + } + + /** + * getName + * returns the name of this event + * + * @return string the name of this event + */ + public function getName() + { + switch ($this->_code) { + case self::CONN_QUERY: + return 'query'; + case self::CONN_EXEC: + return 'exec'; + case self::CONN_PREPARE: + return 'prepare'; + case self::CONN_CONNECT: + return 'connect'; + case self::CONN_CLOSE: + return 'close'; + case self::CONN_ERROR: + return 'error'; + + case self::STMT_EXECUTE: + return 'execute'; + case self::STMT_FETCH: + return 'fetch'; + case self::STMT_FETCHALL: + return 'fetch all'; + + case self::TX_BEGIN: + return 'begin'; + case self::TX_COMMIT: + return 'commit'; + case self::TX_ROLLBACK: + return 'rollback'; + + case self::SAVEPOINT_CREATE: + return 'create savepoint'; + case self::SAVEPOINT_ROLLBACK: + return 'rollback savepoint'; + case self::SAVEPOINT_COMMIT: + return 'commit savepoint'; + + case self::RECORD_DELETE: + return 'delete record'; + case self::RECORD_SAVE: + return 'save record'; + case self::RECORD_UPDATE: + return 'update record'; + case self::RECORD_INSERT: + return 'insert record'; + case self::RECORD_SERIALIZE: + return 'serialize record'; + case self::RECORD_UNSERIALIZE: + return 'unserialize record'; + case self::RECORD_DQL_SELECT: + return 'select records'; + case self::RECORD_DQL_DELETE: + return 'delete records'; + case self::RECORD_DQL_UPDATE: + return 'update records'; + case self::RECORD_VALIDATE: + return 'validate record'; + } + } + + /** + * getCode + * + * @return integer returns the code associated with this event + */ + public function getCode() + { + return $this->_code; + } + + /** + * getOption + * returns the value of an option + * + * @param string $option the name of the option + * @return mixed + */ + public function __get($option) + { + if ( ! isset($this->_options[$option])) { + return null; + } + + return $this->_options[$option]; + } + + /** + * skipOperation + * skips the next operation + * an alias for __set('skipOperation', true) + * + * @return Doctrine_Event this object + */ + public function skipOperation() + { + $this->_options['skipOperation'] = true; + + return $this; + } + + /** + * setOption + * sets the value of an option + * + * @param string $option the name of the option + * @param mixed $value the value of the given option + * @return Doctrine_Event this object + */ + public function __set($option, $value) + { + $this->_options[$option] = $value; + + return $this; + } + + /** + * setOption + * sets the value of an option by reference + * + * @param string $option the name of the option + * @param mixed $value the value of the given option + * @return Doctrine_Event this object + */ + public function set($option, &$value) + { + $this->_options[$option] =& $value; + + return $this; + } + + /** + * start + * starts the internal timer of this event + * + * @return Doctrine_Event this object + */ + public function start() + { + $this->_startedMicrotime = microtime(true); + } + + /** + * hasEnded + * whether or not this event has ended + * + * @return boolean + */ + public function hasEnded() + { + return ($this->_endedMicrotime != null); + } + + /** + * end + * ends the internal timer of this event + * + * @return Doctrine_Event this object + */ + public function end() + { + $this->_endedMicrotime = microtime(true); + + return $this; + } + + /** + * getSequence + * returns the sequence of this event + * + * @return integer + */ + public function getSequence() + { + return $this->_sequence; + } + + /** + * getInvoker + * returns the handler that invoked this event + * + * @return Doctrine_Record|Doctrine_Connection|Doctrine_Connection_Statement| + * Doctrine_Connection_UnitOfWork|Doctrine_Transaction the handler that invoked this event + */ + public function getInvoker() + { + return $this->_invoker; + } + + /** + * setInvoker + * Defines new invoker (used in Hydrator) + * + * @param mixed $invoker + * @return void + */ + public function setInvoker($invoker) + { + $this->_invoker = $invoker; + } + + /** + * getParams + * returns the parameters of the query + * + * @return array parameters of the query + */ + public function getParams() + { + return $this->_params; + } + + /** + * Get the elapsed time (in microseconds) that the event ran. If the event has + * not yet ended, return false. + * + * @return integer + */ + public function getElapsedSecs() + { + if (is_null($this->_endedMicrotime)) { + return false; + } + return ($this->_endedMicrotime - $this->_startedMicrotime); + } +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/EventListener.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/EventListener.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener/Chain.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/EventListener/Chain.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener/Chain.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/EventListener/Chain.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/EventListener/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/EventListener/Exception.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener/Interface.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/EventListener/Interface.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener/Interface.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/EventListener/Interface.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Exception.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export.php new file mode 100644 index 0000000..ab56d66 --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export.php @@ -0,0 +1,1389 @@ +. + */ + +/** + * Doctrine_Export + * + * @package Doctrine + * @subpackage Export + * @author Konsta Vesterinen + * @author Lukas Smith (PEAR MDB2 library) + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 1.0 + * @version $Revision: 7653 $ + */ +class Doctrine_Export extends Doctrine_Connection_Module +{ + protected $valid_default_values = array( + 'text' => '', + 'boolean' => true, + 'integer' => 0, + 'decimal' => 0.0, + 'float' => 0.0, + 'timestamp' => '1970-01-01 00:00:00', + 'time' => '00:00:00', + 'date' => '1970-01-01', + 'clob' => '', + 'blob' => '', + 'string' => '' + ); + + /** + * drop an existing database + * (this method is implemented by the drivers) + * + * @param string $name name of the database that should be dropped + * @return void + */ + public function dropDatabase($database) + { + foreach ((array) $this->dropDatabaseSql($database) as $query) { + $this->conn->execute($query); + } + } + + /** + * drop an existing database + * (this method is implemented by the drivers) + * + * @param string $name name of the database that should be dropped + * @return void + */ + public function dropDatabaseSql($database) + { + throw new Doctrine_Export_Exception('Drop database not supported by this driver.'); + } + + /** + * dropTableSql + * drop an existing table + * + * @param string $table name of table that should be dropped from the database + * @return string + */ + public function dropTableSql($table) + { + return 'DROP TABLE ' . $this->conn->quoteIdentifier($table); + } + + /** + * dropTable + * drop an existing table + * + * @param string $table name of table that should be dropped from the database + * @return void + */ + public function dropTable($table) + { + $this->conn->execute($this->dropTableSql($table)); + } + + /** + * drop existing index + * + * @param string $table name of table that should be used in method + * @param string $name name of the index to be dropped + * @return void + */ + public function dropIndex($table, $name) + { + return $this->conn->exec($this->dropIndexSql($table, $name)); + } + + /** + * dropIndexSql + * + * @param string $table name of table that should be used in method + * @param string $name name of the index to be dropped + * @return string SQL that is used for dropping an index + */ + public function dropIndexSql($table, $name) + { + $name = $this->conn->quoteIdentifier($this->conn->formatter->getIndexName($name)); + + return 'DROP INDEX ' . $name; + } + + /** + * drop existing constraint + * + * @param string $table name of table that should be used in method + * @param string $name name of the constraint to be dropped + * @param string $primary hint if the constraint is primary + * @return void + */ + public function dropConstraint($table, $name, $primary = false) + { + $table = $this->conn->quoteIdentifier($table); + $name = $this->conn->quoteIdentifier($name); + + return $this->conn->exec('ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $name); + } + + /** + * drop existing foreign key + * + * @param string $table name of table that should be used in method + * @param string $name name of the foreign key to be dropped + * @return void + */ + public function dropForeignKey($table, $name) + { + return $this->dropConstraint($table, $this->conn->formatter->getForeignKeyName($name)); + } + + /** + * dropSequenceSql + * drop existing sequence + * (this method is implemented by the drivers) + * + * @throws Doctrine_Connection_Exception if something fails at database level + * @param string $sequenceName name of the sequence to be dropped + * @return void + */ + public function dropSequence($sequenceName) + { + $this->conn->exec($this->dropSequenceSql($sequenceName)); + } + + /** + * dropSequenceSql + * drop existing sequence + * + * @throws Doctrine_Connection_Exception if something fails at database level + * @param string $sequenceName name of the sequence to be dropped + * @return void + */ + public function dropSequenceSql($sequenceName) + { + throw new Doctrine_Export_Exception('Drop sequence not supported by this driver.'); + } + + /** + * create a new database + * (this method is implemented by the drivers) + * + * @param string $name name of the database that should be created + * @return void + */ + public function createDatabase($database) + { + $this->conn->execute($this->createDatabaseSql($database)); + } + + /** + * create a new database + * (this method is implemented by the drivers) + * + * @param string $name name of the database that should be created + * @return string + */ + public function createDatabaseSql($database) + { + throw new Doctrine_Export_Exception('Create database not supported by this driver.'); + } + + /** + * create a new table + * + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * The indexes of the array entries are the names of the fields of the table an + * the array entry values are associative arrays like those that are meant to be + * passed with the field definitions to get[Type]Declaration() functions. + * array( + * 'id' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * 'notnull' => 1 + * 'default' => 0 + * ), + * 'name' => array( + * 'type' => 'text', + * 'length' => 12 + * ), + * 'password' => array( + * 'type' => 'text', + * 'length' => 12 + * ) + * ); + * @param array $options An associative array of table options: + * + * @return string + */ + public function createTableSql($name, array $fields, array $options = array()) + { + if ( ! $name) { + throw new Doctrine_Export_Exception('no valid table name specified'); + } + + if (empty($fields)) { + throw new Doctrine_Export_Exception('no fields specified for table ' . $name); + } + + $queryFields = $this->getFieldDeclarationList($fields); + + + if (isset($options['primary']) && ! empty($options['primary'])) { + $primaryKeys = array_map(array($this->conn, 'quoteIdentifier'), array_values($options['primary'])); + $queryFields .= ', PRIMARY KEY(' . implode(', ', $primaryKeys) . ')'; + } + + if (isset($options['indexes']) && ! empty($options['indexes'])) { + foreach($options['indexes'] as $index => $definition) { + $indexDeclaration = $this->getIndexDeclaration($index, $definition); + // append only created index declarations + if ( ! is_null($indexDeclaration)) { + $queryFields .= ', '.$indexDeclaration; + } + } + } + + $query = 'CREATE TABLE ' . $this->conn->quoteIdentifier($name, true) . ' (' . $queryFields; + + $check = $this->getCheckDeclaration($fields); + + if ( ! empty($check)) { + $query .= ', ' . $check; + } + + $query .= ')'; + + $sql[] = $query; + + if (isset($options['foreignKeys'])) { + + foreach ((array) $options['foreignKeys'] as $k => $definition) { + if (is_array($definition)) { + $sql[] = $this->createForeignKeySql($name, $definition); + } + } + } + return $sql; + } + + /** + * create a new table + * + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * @param array $options An associative array of table options: + * @see Doctrine_Export::createTableSql() + * + * @return void + */ + public function createTable($name, array $fields, array $options = array()) + { + // Build array of the primary keys if any of the individual field definitions + // specify primary => true + $count = 0; + foreach ($fields as $fieldName => $field) { + if (isset($field['primary']) && $field['primary']) { + if ($count == 0) { + $options['primary'] = array(); + } + $count++; + $options['primary'][] = $fieldName; + } + } + + $sql = (array) $this->createTableSql($name, $fields, $options); + + foreach ($sql as $query) { + $this->conn->execute($query); + } + } + + /** + * create sequence + * + * @throws Doctrine_Connection_Exception if something fails at database level + * @param string $seqName name of the sequence to be created + * @param string $start start value of the sequence; default is 1 + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'charset' => 'utf8', + * 'collate' => 'utf8_unicode_ci', + * ); + * @return void + */ + public function createSequence($seqName, $start = 1, array $options = array()) + { + return $this->conn->execute($this->createSequenceSql($seqName, $start = 1, $options)); + } + + /** + * return RDBMS specific create sequence statement + * (this method is implemented by the drivers) + * + * @throws Doctrine_Connection_Exception if something fails at database level + * @param string $seqName name of the sequence to be created + * @param string $start start value of the sequence; default is 1 + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'charset' => 'utf8', + * 'collate' => 'utf8_unicode_ci', + * ); + * @return string + */ + public function createSequenceSql($seqName, $start = 1, array $options = array()) + { + throw new Doctrine_Export_Exception('Create sequence not supported by this driver.'); + } + + /** + * create a constraint on a table + * + * @param string $table name of the table on which the constraint is to be created + * @param string $name name of the constraint to be created + * @param array $definition associative array that defines properties of the constraint to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the constraint fields as array + * constraints. Each entry of this array is set to another type of associative + * array that specifies properties of the constraint that are specific to + * each field. + * + * Example + * array( + * 'fields' => array( + * 'user_name' => array(), + * 'last_login' => array() + * ) + * ) + * @return void + */ + public function createConstraint($table, $name, $definition) + { + $sql = $this->createConstraintSql($table, $name, $definition); + + return $this->conn->exec($sql); + } + + /** + * create a constraint on a table + * + * @param string $table name of the table on which the constraint is to be created + * @param string $name name of the constraint to be created + * @param array $definition associative array that defines properties of the constraint to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the constraint fields as array + * constraints. Each entry of this array is set to another type of associative + * array that specifies properties of the constraint that are specific to + * each field. + * + * Example + * array( + * 'fields' => array( + * 'user_name' => array(), + * 'last_login' => array() + * ) + * ) + * @return void + */ + public function createConstraintSql($table, $name, $definition) + { + $table = $this->conn->quoteIdentifier($table); + $name = $this->conn->quoteIdentifier($this->conn->formatter->getIndexName($name)); + $query = 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $name; + + if (isset($definition['primary']) && $definition['primary']) { + $query .= ' PRIMARY KEY'; + } elseif (isset($definition['unique']) && $definition['unique']) { + $query .= ' UNIQUE'; + } + + $fields = array(); + foreach (array_keys($definition['fields']) as $field) { + $fields[] = $this->conn->quoteIdentifier($field, true); + } + $query .= ' ('. implode(', ', $fields) . ')'; + + return $query; + } + + /** + * Get the stucture of a field into an array + * + * @param string $table name of the table on which the index is to be created + * @param string $name name of the index to be created + * @param array $definition associative array that defines properties of the index to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the index fields as array + * indexes. Each entry of this array is set to another type of associative + * array that specifies properties of the index that are specific to + * each field. + * + * Currently, only the sorting property is supported. It should be used + * to define the sorting direction of the index. It may be set to either + * ascending or descending. + * + * Not all DBMS support index sorting direction configuration. The DBMS + * drivers of those that do not support it ignore this property. Use the + * function supports() to determine whether the DBMS driver can manage indexes. + * + * Example + * array( + * 'fields' => array( + * 'user_name' => array( + * 'sorting' => 'ascending' + * ), + * 'last_login' => array() + * ) + * ) + * @return void + */ + public function createIndex($table, $name, array $definition) + { + return $this->conn->execute($this->createIndexSql($table, $name, $definition)); + } + + /** + * Get the stucture of a field into an array + * + * @param string $table name of the table on which the index is to be created + * @param string $name name of the index to be created + * @param array $definition associative array that defines properties of the index to be created. + * @see Doctrine_Export::createIndex() + * @return string + */ + public function createIndexSql($table, $name, array $definition) + { + $table = $this->conn->quoteIdentifier($table); + $name = $this->conn->quoteIdentifier($name); + $type = ''; + + if (isset($definition['type'])) { + switch (strtolower($definition['type'])) { + case 'unique': + $type = strtoupper($definition['type']) . ' '; + break; + default: + throw new Doctrine_Export_Exception( + 'Unknown type ' . $definition['type'] . ' for index ' . $name . ' in table ' . $table + ); + } + } + + $query = 'CREATE ' . $type . 'INDEX ' . $name . ' ON ' . $table; + + $fields = array(); + foreach ($definition['fields'] as $field) { + $fields[] = $this->conn->quoteIdentifier($field); + } + $query .= ' (' . implode(', ', $fields) . ')'; + + return $query; + } + /** + * createForeignKeySql + * + * @param string $table name of the table on which the foreign key is to be created + * @param array $definition associative array that defines properties of the foreign key to be created. + * @return string + */ + public function createForeignKeySql($table, array $definition) + { + $table = $this->conn->quoteIdentifier($table); + $query = 'ALTER TABLE ' . $table . ' ADD ' . $this->getForeignKeyDeclaration($definition); + + return $query; + } + + /** + * createForeignKey + * + * @param string $table name of the table on which the foreign key is to be created + * @param array $definition associative array that defines properties of the foreign key to be created. + * @return string + */ + public function createForeignKey($table, array $definition) + { + $sql = $this->createForeignKeySql($table, $definition); + + return $this->conn->execute($sql); + } + + /** + * alter an existing table + * (this method is implemented by the drivers) + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type + * of change that is intended to be performed. The types of + * changes that are currently supported are defined as follows: + * + * name + * + * New name for the table. + * + * add + * + * Associative array with the names of fields to be added as + * indexes of the array. The value of each entry of the array + * should be set to another associative array with the properties + * of the fields to be added. The properties of the fields should + * be the same as defined by the MDB2 parser. + * + * + * remove + * + * Associative array with the names of fields to be removed as indexes + * of the array. Currently the values assigned to each entry are ignored. + * An empty array should be used for future compatibility. + * + * rename + * + * Associative array with the names of fields to be renamed as indexes + * of the array. The value of each entry of the array should be set to + * another associative array with the entry named name with the new + * field name and the entry named Declaration that is expected to contain + * the portion of the field declaration already in DBMS specific SQL code + * as it is used in the CREATE TABLE statement. + * + * change + * + * Associative array with the names of the fields to be changed as indexes + * of the array. Keep in mind that if it is intended to change either the + * name of a field and any other properties, the change array entries + * should have the new names of the fields as array indexes. + * + * The value of each entry of the array should be set to another associative + * array with the properties of the fields to that are meant to be changed as + * array entries. These entries should be assigned to the new values of the + * respective properties. The properties of the fields should be the same + * as defined by the MDB2 parser. + * + * Example + * array( + * 'name' => 'userlist', + * 'add' => array( + * 'quota' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * ) + * ), + * 'remove' => array( + * 'file_limit' => array(), + * 'time_limit' => array() + * ), + * 'change' => array( + * 'name' => array( + * 'length' => '20', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 20, + * ), + * ) + * ), + * 'rename' => array( + * 'sex' => array( + * 'name' => 'gender', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 1, + * 'default' => 'M', + * ), + * ) + * ) + * ) + * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * @return void + */ + public function alterTable($name, array $changes, $check = false) + { + $sql = $this->alterTableSql($name, $changes, $check); + + if (is_string($sql) && $sql) { + $this->conn->execute($sql); + } + } + + /** + * generates the sql for altering an existing table + * (this method is implemented by the drivers) + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * @see Doctrine_Export::alterTable() + * @return string + */ + public function alterTableSql($name, array $changes, $check = false) + { + throw new Doctrine_Export_Exception('Alter table not supported by this driver.'); + } + + /** + * Get declaration of a number of field in bulk + * + * @param array $fields a multidimensional associative array. + * The first dimension determines the field name, while the second + * dimension is keyed with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * charset + * Text value with the default CHARACTER SET for this field. + * collation + * Text value with the default COLLATION for this field. + * unique + * unique constraint + * + * @return string + */ + public function getFieldDeclarationList(array $fields) + { + foreach ($fields as $fieldName => $field) { + $query = $this->getDeclaration($fieldName, $field); + + $queryFields[] = $query; + } + return implode(', ', $queryFields); + } + + /** + * Obtain DBMS specific SQL code portion needed to declare a generic type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * + * charset + * Text value with the default CHARACTER SET for this field. + * + * collation + * Text value with the default COLLATION for this field. + * + * unique + * unique constraint + * + * check + * column check constraint + * + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getDeclaration($name, array $field) + { + + $default = $this->getDefaultFieldDeclaration($field); + + $charset = (isset($field['charset']) && $field['charset']) ? + ' ' . $this->getCharsetFieldDeclaration($field['charset']) : ''; + + $collation = (isset($field['collation']) && $field['collation']) ? + ' ' . $this->getCollationFieldDeclaration($field['collation']) : ''; + + $notnull = $this->getNotNullFieldDeclaration($field); + + $unique = (isset($field['unique']) && $field['unique']) ? + ' ' . $this->getUniqueFieldDeclaration() : ''; + + $check = (isset($field['check']) && $field['check']) ? + ' ' . $field['check'] : ''; + + $method = 'get' . $field['type'] . 'Declaration'; + + try { + if (method_exists($this->conn->dataDict, $method)) { + return $this->conn->dataDict->$method($name, $field); + } else { + $dec = $this->conn->dataDict->getNativeDeclaration($field); + } + + return $this->conn->quoteIdentifier($name, true) + . ' ' . $dec . $charset . $default . $notnull . $unique . $check . $collation; + } catch (Exception $e) { + throw new Doctrine_Exception('Around field ' . $name . ': ' . $e->getMessage()); + } + + } + + /** + * getDefaultDeclaration + * Obtain DBMS specific SQL code portion needed to set a default value + * declaration to be used in statements like CREATE TABLE. + * + * @param array $field field definition array + * @return string DBMS specific SQL code portion needed to set a default value + */ + public function getDefaultFieldDeclaration($field) + { + $default = ''; + + if (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) + ? null : $this->valid_default_values[$field['type']]; + + if ($field['default'] === '' && + ($this->conn->getAttribute(Doctrine_Core::ATTR_PORTABILITY) & Doctrine_Core::PORTABILITY_EMPTY_TO_NULL)) { + $field['default'] = null; + } + } + + if ($field['type'] === 'boolean') { + $field['default'] = $this->conn->convertBooleans($field['default']); + } + $default = ' DEFAULT ' . (is_null($field['default']) + ? 'NULL' + : $this->conn->quote($field['default'], $field['type'])); + } + + return $default; + } + + + /** + * getNotNullFieldDeclaration + * Obtain DBMS specific SQL code portion needed to set a NOT NULL + * declaration to be used in statements like CREATE TABLE. + * + * @param array $field field definition array + * @return string DBMS specific SQL code portion needed to set a default value + */ + public function getNotNullFieldDeclaration(array $definition) + { + return (isset($definition['notnull']) && $definition['notnull']) ? ' NOT NULL' : ''; + } + + + /** + * Obtain DBMS specific SQL code portion needed to set a CHECK constraint + * declaration to be used in statements like CREATE TABLE. + * + * @param array $definition check definition + * @return string DBMS specific SQL code portion needed to set a CHECK constraint + */ + public function getCheckDeclaration(array $definition) + { + $constraints = array(); + foreach ($definition as $field => $def) { + if (is_string($def)) { + $constraints[] = 'CHECK (' . $def . ')'; + } else { + if (isset($def['min'])) { + $constraints[] = 'CHECK (' . $field . ' >= ' . $def['min'] . ')'; + } + + if (isset($def['max'])) { + $constraints[] = 'CHECK (' . $field . ' <= ' . $def['max'] . ')'; + } + } + } + + return implode(', ', $constraints); + } + + /** + * Obtain DBMS specific SQL code portion needed to set an index + * declaration to be used in statements like CREATE TABLE. + * + * @param string $name name of the index + * @param array $definition index definition + * @return string DBMS specific SQL code portion needed to set an index + */ + public function getIndexDeclaration($name, array $definition) + { + $name = $this->conn->quoteIdentifier($name); + $type = ''; + + if (isset($definition['type'])) { + if (strtolower($definition['type']) == 'unique') { + $type = strtoupper($definition['type']) . ' '; + } else { + throw new Doctrine_Export_Exception( + 'Unknown type ' . $definition['type'] . ' for index ' . $name + ); + } + } + + if ( ! isset($definition['fields']) || ! is_array($definition['fields'])) { + throw new Doctrine_Export_Exception('No columns given for index ' . $name); + } + + $query = $type . 'INDEX ' . $name; + + $query .= ' (' . $this->getIndexFieldDeclarationList($definition['fields']) . ')'; + + return $query; + } + + /** + * getIndexFieldDeclarationList + * Obtain DBMS specific SQL code portion needed to set an index + * declaration to be used in statements like CREATE TABLE. + * + * @return string + */ + public function getIndexFieldDeclarationList(array $fields) + { + $ret = array(); + foreach ($fields as $field => $definition) { + if (is_array($definition)) { + $ret[] = $this->conn->quoteIdentifier($field); + } else { + $ret[] = $this->conn->quoteIdentifier($definition); + } + } + return implode(', ', $ret); + } + + /** + * A method to return the required SQL string that fits between CREATE ... TABLE + * to create the table as a temporary table. + * + * Should be overridden in driver classes to return the correct string for the + * specific database type. + * + * The default is to return the string "TEMPORARY" - this will result in a + * SQL error for any database that does not support temporary tables, or that + * requires a different SQL command from "CREATE TEMPORARY TABLE". + * + * @return string The string required to be placed between "CREATE" and "TABLE" + * to generate a temporary table, if possible. + */ + public function getTemporaryTableQuery() + { + return 'TEMPORARY'; + } + + /** + * getForeignKeyDeclaration + * Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param array $definition an associative array with the following structure: + * name optional constraint name + * + * local the local field(s) + * + * foreign the foreign reference field(s) + * + * foreignTable the name of the foreign table + * + * onDelete referential delete action + * + * onUpdate referential update action + * + * deferred deferred constraint checking + * + * The onDelete and onUpdate keys accept the following values: + * + * CASCADE: Delete or update the row from the parent table and automatically delete or + * update the matching rows in the child table. Both ON DELETE CASCADE and ON UPDATE CASCADE are supported. + * Between two tables, you should not define several ON UPDATE CASCADE clauses that act on the same column + * in the parent table or in the child table. + * + * SET NULL: Delete or update the row from the parent table and set the foreign key column or columns in the + * child table to NULL. This is valid only if the foreign key columns do not have the NOT NULL qualifier + * specified. Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported. + * + * NO ACTION: In standard SQL, NO ACTION means no action in the sense that an attempt to delete or update a primary + * key value is not allowed to proceed if there is a related foreign key value in the referenced table. + * + * RESTRICT: Rejects the delete or update operation for the parent table. NO ACTION and RESTRICT are the same as + * omitting the ON DELETE or ON UPDATE clause. + * + * SET DEFAULT + * + * @return string DBMS specific SQL code portion needed to set the FOREIGN KEY constraint + * of a field declaration. + */ + public function getForeignKeyDeclaration(array $definition) + { + $sql = $this->getForeignKeyBaseDeclaration($definition); + $sql .= $this->getAdvancedForeignKeyOptions($definition); + + return $sql; + } + + /** + * getAdvancedForeignKeyOptions + * Return the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param array $definition foreign key definition + * @return string + */ + public function getAdvancedForeignKeyOptions(array $definition) + { + $query = ''; + if ( ! empty($definition['onUpdate'])) { + $query .= ' ON UPDATE ' . $this->getForeignKeyReferentialAction($definition['onUpdate']); + } + if ( ! empty($definition['onDelete'])) { + $query .= ' ON DELETE ' . $this->getForeignKeyReferentialAction($definition['onDelete']); + } + return $query; + } + + /** + * getForeignKeyReferentialAction + * + * returns given referential action in uppercase if valid, otherwise throws + * an exception + * + * @throws Doctrine_Exception_Exception if unknown referential action given + * @param string $action foreign key referential action + * @param string foreign key referential action in uppercase + */ + public function getForeignKeyReferentialAction($action) + { + $upper = strtoupper($action); + switch ($upper) { + case 'CASCADE': + case 'SET NULL': + case 'NO ACTION': + case 'RESTRICT': + case 'SET DEFAULT': + return $upper; + break; + default: + throw new Doctrine_Export_Exception('Unknown foreign key referential action \'' . $upper . '\' given.'); + } + } + + /** + * getForeignKeyBaseDeclaration + * Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param array $definition + * @return string + */ + public function getForeignKeyBaseDeclaration(array $definition) + { + $sql = ''; + if (isset($definition['name'])) { + $sql .= 'CONSTRAINT ' . $this->conn->quoteIdentifier($this->conn->formatter->getForeignKeyName($definition['name'])) . ' '; + } + $sql .= 'FOREIGN KEY ('; + + if ( ! isset($definition['local'])) { + throw new Doctrine_Export_Exception('Local reference field missing from definition.'); + } + if ( ! isset($definition['foreign'])) { + throw new Doctrine_Export_Exception('Foreign reference field missing from definition.'); + } + if ( ! isset($definition['foreignTable'])) { + throw new Doctrine_Export_Exception('Foreign reference table missing from definition.'); + } + + if ( ! is_array($definition['local'])) { + $definition['local'] = array($definition['local']); + } + if ( ! is_array($definition['foreign'])) { + $definition['foreign'] = array($definition['foreign']); + } + + $sql .= implode(', ', array_map(array($this->conn, 'quoteIdentifier'), $definition['local'])) + . ') REFERENCES ' + . $this->conn->quoteIdentifier($definition['foreignTable']) . '(' + . implode(', ', array_map(array($this->conn, 'quoteIdentifier'), $definition['foreign'])) . ')'; + + return $sql; + } + + /** + * Obtain DBMS specific SQL code portion needed to set the UNIQUE constraint + * of a field declaration to be used in statements like CREATE TABLE. + * + * @return string DBMS specific SQL code portion needed to set the UNIQUE constraint + * of a field declaration. + */ + public function getUniqueFieldDeclaration() + { + return 'UNIQUE'; + } + + /** + * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $charset name of the charset + * @return string DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration. + */ + public function getCharsetFieldDeclaration($charset) + { + return ''; + } + + /** + * Obtain DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $collation name of the collation + * @return string DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration. + */ + public function getCollationFieldDeclaration($collation) + { + return ''; + } + + /** + * exportSchema + * method for exporting Doctrine_Record classes to a schema + * + * if the directory parameter is given this method first iterates + * recursively trhough the given directory in order to find any model classes + * + * Then it iterates through all declared classes and creates tables for the ones + * that extend Doctrine_Record and are not abstract classes + * + * @throws Doctrine_Connection_Exception if some error other than Doctrine_Core::ERR_ALREADY_EXISTS + * occurred during the create table operation + * @param string $directory optional directory parameter + * @return void + */ + public function exportSchema($directory = null) + { + if ($directory !== null) { + $models = Doctrine_Core::filterInvalidModels(Doctrine_Core::loadModels($directory)); + } else { + $models = Doctrine_Core::getLoadedModels(); + } + + $this->exportClasses($models); + } + + public function exportSortedClassesSql($classes, $groupByConnection = true) + { + $connections = array(); + foreach ($classes as $class) { + $connection = Doctrine_Manager::getInstance()->getConnectionForComponent($class); + $connectionName = $connection->getName(); + + if ( ! isset($connections[$connectionName])) { + $connections[$connectionName] = array( + 'create_tables' => array(), + 'create_sequences' => array(), + 'create_indexes' => array(), + 'alters' => array(), + 'create_triggers' => array(), + ); + } + + $sql = $connection->export->exportClassesSql(array($class)); + + // Build array of all the creates + // We need these to happen first + foreach ($sql as $key => $query) { + // If create table statement + if (substr($query, 0, strlen('CREATE TABLE')) == 'CREATE TABLE') { + $connections[$connectionName]['create_tables'][] = $query; + + unset($sql[$key]); + continue; + } + + // If create sequence statement + if (substr($query, 0, strlen('CREATE SEQUENCE')) == 'CREATE SEQUENCE') { + $connections[$connectionName]['create_sequences'][] = $query; + + unset($sql[$key]); + continue; + } + + // If create index statement + if (preg_grep("/CREATE ([^ ]* )?INDEX/", array($query))) { + $connections[$connectionName]['create_indexes'][] = $query; + + unset($sql[$key]); + continue; + } + + // If alter table statement or oracle anonymous block enclosing alter + if (substr($query, 0, strlen('ALTER TABLE')) == 'ALTER TABLE' + || substr($query, 0, strlen('DECLARE')) == 'DECLARE') { + $connections[$connectionName]['alters'][] = $query; + + unset($sql[$key]); + continue; + } + + // If create trgger statement + if (substr($query, 0, strlen('CREATE TRIGGER')) == 'CREATE TRIGGER') { + $connections[$connectionName]['create_triggers'][] = $query; + + unset($sql[$key]); + continue; + } + + // If comment statement + if (substr($query, 0, strlen('COMMENT ON')) == 'COMMENT ON') { + $connections[$connectionName]['comments'][] = $query; + + unset($sql[$key]); + continue; + } + } + } + + // Loop over all the sql again to merge everything together so it is in the correct order + $build = array(); + foreach ($connections as $connectionName => $sql) { + $build[$connectionName] = array_unique(array_merge($sql['create_tables'], $sql['create_sequences'], $sql['create_indexes'], $sql['alters'], $sql['create_triggers'])); + } + + if ( ! $groupByConnection) { + $new = array(); + foreach($build as $connectionname => $sql) { + $new = array_unique(array_merge($new, $sql)); + } + $build = $new; + } + return $build; + } + + /** + * exportClasses + * method for exporting Doctrine_Record classes to a schema + * + * FIXME: This function has ugly hacks in it to make sure sql is inserted in the correct order. + * + * @throws Doctrine_Connection_Exception if some error other than Doctrine_Core::ERR_ALREADY_EXISTS + * occurred during the create table operation + * @param array $classes + * @return void + */ + public function exportClasses(array $classes) + { + $queries = $this->exportSortedClassesSql($classes); + + foreach ($queries as $connectionName => $sql) { + $connection = Doctrine_Manager::getInstance()->getConnection($connectionName); + + $connection->beginTransaction(); + + foreach ($sql as $query) { + try { + $connection->exec($query); + } catch (Doctrine_Connection_Exception $e) { + // we only want to silence table already exists errors + if ($e->getPortableCode() !== Doctrine_Core::ERR_ALREADY_EXISTS) { + $connection->rollback(); + throw new Doctrine_Export_Exception($e->getMessage() . '. Failing Query: ' . $query); + } + } + } + + $connection->commit(); + } + } + + /** + * exportClassesSql + * method for exporting Doctrine_Record classes to a schema + * + * @throws Doctrine_Connection_Exception if some error other than Doctrine_Core::ERR_ALREADY_EXISTS + * occurred during the create table operation + * @param array $classes + * @return void + */ + public function exportClassesSql(array $classes) + { + $models = Doctrine_Core::filterInvalidModels($classes); + + $sql = array(); + + foreach ($models as $name) { + $record = new $name(); + $table = $record->getTable(); + $parents = $table->getOption('joinedParents'); + + foreach ($parents as $parent) { + $data = $table->getConnection()->getTable($parent)->getExportableFormat(); + + $query = $this->conn->export->createTableSql($data['tableName'], $data['columns'], $data['options']); + + $sql = array_merge($sql, (array) $query); + } + + // Don't export the tables with attribute EXPORT_NONE' + if ($table->getAttribute(Doctrine_Core::ATTR_EXPORT) === Doctrine_Core::EXPORT_NONE) { + continue; + } + + $data = $table->getExportableFormat(); + + $query = $this->conn->export->createTableSql($data['tableName'], $data['columns'], $data['options']); + + if (is_array($query)) { + $sql = array_merge($sql, $query); + } else { + $sql[] = $query; + } + + if ($table->getAttribute(Doctrine_Core::ATTR_EXPORT) & Doctrine_Core::EXPORT_PLUGINS) { + $sql = array_merge($sql, $this->exportGeneratorsSql($table)); + } + + // DC-474: Remove dummy $record from repository to not pollute it during export + $table->getRepository()->evict($record->getOid()); + unset($record); + } + + $sql = array_unique($sql); + + rsort($sql); + + return $sql; + } + + /** + * fetches all generators recursively for given table + * + * @param Doctrine_Table $table table object to retrieve the generators from + * @return array an array of Doctrine_Record_Generator objects + */ + public function getAllGenerators(Doctrine_Table $table) + { + $generators = array(); + + foreach ($table->getGenerators() as $name => $generator) { + if ($generator === null) { + continue; + } + + $generators[] = $generator; + + $generatorTable = $generator->getTable(); + + if ($generatorTable instanceof Doctrine_Table) { + $generators = array_merge($generators, $this->getAllGenerators($generatorTable)); + } + } + + return $generators; + } + + /** + * exportGeneratorsSql + * exports plugin tables for given table + * + * @param Doctrine_Table $table the table in which the generators belong to + * @return array an array of sql strings + */ + public function exportGeneratorsSql(Doctrine_Table $table) + { + $sql = array(); + + foreach ($this->getAllGenerators($table) as $name => $generator) { + $table = $generator->getTable(); + + // Make sure plugin has a valid table + if ($table instanceof Doctrine_Table) { + $data = $table->getExportableFormat(); + + $query = $this->conn->export->createTableSql($data['tableName'], $data['columns'], $data['options']); + + $sql = array_merge($sql, (array) $query); + } + } + + return $sql; + } + + /** + * exportSql + * returns the sql for exporting Doctrine_Record classes to a schema + * + * if the directory parameter is given this method first iterates + * recursively trhough the given directory in order to find any model classes + * + * Then it iterates through all declared classes and creates tables for the ones + * that extend Doctrine_Record and are not abstract classes + * + * @throws Doctrine_Connection_Exception if some error other than Doctrine_Core::ERR_ALREADY_EXISTS + * occurred during the create table operation + * @param string $directory optional directory parameter + * @return void + */ + public function exportSql($directory = null) + { + if ($directory !== null) { + $models = Doctrine_Core::filterInvalidModels(Doctrine_Core::loadModels($directory)); + } else { + $models = Doctrine_Core::getLoadedModels(); + } + + return $this->exportSortedClassesSql($models, false); + } + + /** + * exportTable + * exports given table into database based on column and option definitions + * + * @throws Doctrine_Connection_Exception if some error other than Doctrine_Core::ERR_ALREADY_EXISTS + * occurred during the create table operation + * @return boolean whether or not the export operation was successful + * false if table already existed in the database + */ + public function exportTable(Doctrine_Table $table) + { + try { + $data = $table->getExportableFormat(); + + $this->conn->export->createTable($data['tableName'], $data['columns'], $data['options']); + } catch(Doctrine_Connection_Exception $e) { + // we only want to silence table already exists errors + if ($e->getPortableCode() !== Doctrine_Core::ERR_ALREADY_EXISTS) { + throw $e; + } + } + } +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Exception.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Mssql.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Mssql.php new file mode 100644 index 0000000..30db562 --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Mssql.php @@ -0,0 +1,524 @@ +. + */ + +/** + * Doctrine_Export_Mssql + * + * @package Doctrine + * @subpackage Export + * @author Konsta Vesterinen + * @author Lukas Smith (PEAR MDB2 library) + * @author Frank M. Kromann (PEAR MDB2 Mssql driver) + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 1.0 + * @version $Revision: 7660 $ + */ +class Doctrine_Export_Mssql extends Doctrine_Export +{ + /** + * create a new database + * + * @param string $name name of the database that should be created + * @return void + */ + public function createDatabase($name) + { + $name = $this->conn->quoteIdentifier($name, true); + $query = "CREATE DATABASE $name"; + $options = $this->conn->getOptions(); + if (isset($options['database_device']) && $options['database_device']) { + $query.= ' ON '.$this->conn->options['database_device']; + $query.= $this->conn->options['database_size'] ? '=' . + $this->conn->options['database_size'] : ''; + } + return $this->conn->standaloneQuery($query, array(), true); + } + + /** + * drop an existing database + * + * @param string $name name of the database that should be dropped + * @return void + */ + public function dropDatabase($name) + { + $name = $this->conn->quoteIdentifier($name, true); + return $this->conn->standaloneQuery('DROP DATABASE ' . $name, array(), true); + } + + /** + * Override the parent method. + * + * @return string The string required to be placed between "CREATE" and "TABLE" + * to generate a temporary table, if possible. + */ + public function getTemporaryTableQuery() + { + return ''; + } + + public function dropIndexSql($table, $name) + { + $name = $this->conn->quoteIdentifier($this->conn->formatter->getIndexName($name)); + $table = $this->conn->quoteIdentifier($table); + + return 'DROP INDEX ' . $name . ' ON ' . $table; + } + + /** + * alter an existing table + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type + * of change that is intended to be performed. The types of + * changes that are currently supported are defined as follows: + * + * name + * + * New name for the table. + * + * add + * + * Associative array with the names of fields to be added as + * indexes of the array. The value of each entry of the array + * should be set to another associative array with the properties + * of the fields to be added. The properties of the fields should + * be the same as defined by the Metabase parser. + * + * + * remove + * + * Associative array with the names of fields to be removed as indexes + * of the array. Currently the values assigned to each entry are ignored. + * An empty array should be used for future compatibility. + * + * rename + * + * Associative array with the names of fields to be renamed as indexes + * of the array. The value of each entry of the array should be set to + * another associative array with the entry named name with the new + * field name and the entry named Declaration that is expected to contain + * the portion of the field declaration already in DBMS specific SQL code + * as it is used in the CREATE TABLE statement. + * + * change + * + * Associative array with the names of the fields to be changed as indexes + * of the array. Keep in mind that if it is intended to change either the + * name of a field and any other properties, the change array entries + * should have the new names of the fields as array indexes. + * + * The value of each entry of the array should be set to another associative + * array with the properties of the fields to that are meant to be changed as + * array entries. These entries should be assigned to the new values of the + * respective properties. The properties of the fields should be the same + * as defined by the Metabase parser. + * + * Example + * array( + * 'name' => 'userlist', + * 'add' => array( + * 'quota' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * ) + * ), + * 'remove' => array( + * 'file_limit' => array(), + * 'time_limit' => array() + * ), + * 'change' => array( + * 'name' => array( + * 'length' => '20', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 20, + * ), + * ) + * ), + * 'rename' => array( + * 'sex' => array( + * 'name' => 'gender', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 1, + * 'default' => 'M', + * ), + * ) + * ) + * ) + * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * @return void + */ + public function alterTable($name, array $changes, $check = false) + { + if ( !$name ) { + throw new Doctrine_Export_Exception('no valid table name specified'); + } + + foreach ($changes as $changeName => $change) { + switch ($changeName) { + case 'add': + case 'remove': + case 'name': + case 'rename': + case 'change': + break; + default: + throw new Doctrine_Export_Exception('alterTable: change type "' . $changeName . '" not yet supported'); + } + } + + if ($check) { + return true; + } + + + $query = ''; + $postQueries = ''; //SQL Server uses a stored procedure to rename objects + + if ( ! empty($changes['name'])) { + $changeName = $this->conn->quoteIdentifier($changes['name'], true); + + $postQueries .= sprintf( + "EXECUTE sp_RENAME '%s', '%s';", + $this->conn->quoteIdentifier($name), + $changeName + ); + } + + //ADD TABLE + if ( ! empty($changes['add']) && is_array($changes['add'])) { + foreach ($changes['add'] as $fieldName => $field) { + if ($query) { + $query .= ', '; + } + $query .= 'ADD ' . $this->getDeclaration($fieldName, $field); + } + } + + //REMOVE TABLE + if ( ! empty($changes['remove']) && is_array($changes['remove'])) { + if ($query) { + $query .= ', '; + } + $query .= 'DROP COLUMN '; + + $dropped = array(); + foreach ($changes['remove'] as $fieldName => $field) { + + $fieldName = $this->conn->quoteIdentifier($fieldName, true); + $dropped[] = $fieldName; + } + + $query .= implode(', ', $dropped) . ' '; + } + + $rename = array(); + if ( ! empty($changes['rename']) && is_array($changes['rename'])) { + foreach ($changes['rename'] as $fieldName => $field) { + $rename[$field['name']] = $fieldName; + } + } + + //CHANGE (COLUMN DEFINITION) + if ( ! empty($changes['change']) && is_array($changes['change'])) { + if ($query) { + $query.= ', '; + } + + $query .= "ALTER COLUMN "; + + $altered = array(); + foreach ($changes['change'] as $fieldName => $field) { + if (isset($rename[$fieldName])) { + $oldFieldName = $rename[$fieldName]; + unset($rename[$fieldName]); + } else { + $oldFieldName = $fieldName; + } + $oldFieldName = $this->conn->quoteIdentifier($oldFieldName, true); + + $declaration = $this->getDeclaration($fieldName, $field['definition']); + + if (preg_match('/(CONSTRAINT\s+([^\s]*)\s+DEFAULT\s+([^\s]*)\s*)|(DEFAULT\s+([^\s]*)\s*)/', $declaration, $matches)) { + // Remove the default constraint declaration from the statement + $altered[] = str_replace($matches[0], '', $declaration); + + if (count($matches) === 6) { + // No constraint name provided. Try to make sure it's unique + $defaultName = 'DF__' . $name . '__' . $fieldName . '__' . mt_rand(); + $defaultValue = $matches[5]; + } else { + $defaultName = $matches[2]; + $defaultValue = $matches[3]; + } + + $postQueries .= sprintf( + ' ALTER TABLE %s ADD CONSTRAINT %s DEFAULT (%s) FOR %s', + $name, + $defaultName, + $defaultValue, + $fieldName + ); + } else { + $altered[] = $declaration; + } + } + + $query .= implode(sprintf( + "; ALTER TABLE %s ALTER COLUMN ", + $this->conn->quoteIdentifier($name, true) + ), $altered) . ' '; + } + + //RENAME (COLUMN) + if ( ! empty($rename) && is_array($rename)) { + foreach ($rename as $renameName => $renamedField) { + + $field = $changes['rename'][$renamedField]; + $renamedField = $this->conn->quoteIdentifier($renamedField); + + $postQueries .= sprintf( + "EXECUTE sp_RENAME '%s.%s', '%s', 'COLUMN';", + $this->conn->quoteIdentifier($name), + $renamedField, + $this->conn->quoteIdentifier($field['name'], true) + ); + } + } + + if ( ! $query && ! $postQueries) { + return false; + } + + $name = $this->conn->quoteIdentifier($name, true); + + $finalQuery = ''; + if ($query) { + $finalQuery .= 'ALTER TABLE ' . $name . ' ' . trim($query) . ';'; + } + + if ($postQueries) { + $finalQuery .= $postQueries; + } + + return $this->conn->exec($finalQuery); + } + + /** + * create sequence + * + * @param string $seqName name of the sequence to be created + * @param string $start start value of the sequence; default is 1 + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'charset' => 'utf8', + * 'collate' => 'utf8_unicode_ci', + * ); + * @return string + */ + public function createSequence($seqName, $start = 1, array $options = array()) + { + $sequenceName = $this->conn->quoteIdentifier($this->conn->getSequenceName($seqName), true); + $seqcolName = $this->conn->quoteIdentifier($this->conn->options['seqcol_name'], true); + $query = 'CREATE TABLE ' . $sequenceName . ' (' . $seqcolName . + ' INT PRIMARY KEY CLUSTERED IDENTITY(' . $start . ', 1) NOT NULL)'; + + $res = $this->conn->exec($query); + + if ($start == 1) { + return true; + } + + try { + $query = 'SET IDENTITY_INSERT ' . $sequenceName . ' ON ' . + 'INSERT INTO ' . $sequenceName . ' (' . $seqcolName . ') VALUES ( ' . $start . ')'; + $res = $this->conn->exec($query); + } catch (Exception $e) { + $result = $this->conn->exec('DROP TABLE ' . $sequenceName); + } + return true; + } + + /** + * This function drops an existing sequence + * + * @param string $seqName name of the sequence to be dropped + * @return void + */ + public function dropSequenceSql($seqName) + { + $sequenceName = $this->conn->quoteIdentifier($this->conn->getSequenceName($seqName), true); + return 'DROP TABLE ' . $sequenceName; + } + + /** + * create a new table + * + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * The indexes of the array entries are the names of the fields of the table an + * the array entry values are associative arrays like those that are meant to be + * passed with the field definitions to get[Type]Declaration() functions. + * array( + * 'id' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * 'notnull' => 1 + * 'default' => 0 + * ), + * 'name' => array( + * 'type' => 'text', + * 'length' => 12 + * ), + * 'password' => array( + * 'type' => 'text', + * 'length' => 12 + * ) + * ); + * @param array $options An associative array of table options: + * + * @return string + */ + public function createTableSql($name, array $fields, array $options = array()) + { + if ( ! $name) { + throw new Doctrine_Export_Exception('no valid table name specified'); + } + + if (empty($fields)) { + throw new Doctrine_Export_Exception('no fields specified for table ' . $name); + } + + // Use field declaration of primary if the primary option not set + if ( ! isset($options['primary'])) { + foreach ($fields as $fieldName => $fieldData) { + if (isset($fieldData['primary']) && $fieldData['primary']) { + $options['primary'][$fieldName] = $fieldName; + } + } + } + + if (isset($options['primary'])) { + foreach ($options['primary'] as $fieldName) { + if (isset($fields[$fieldName])) { + $fields[$fieldName]['notnull'] = true; //Silently forcing NOT NULL as MSSQL will kill a query that has a nullable PK + } + } + } + + $queryFields = $this->getFieldDeclarationList($fields); + + if (isset($options['primary']) && ! empty($options['primary'])) { + $primaryKeys = array_map(array($this->conn, 'quoteIdentifier'), array_values($options['primary'])); + $queryFields .= ', PRIMARY KEY(' . implode(', ', $primaryKeys) . ')'; + } + + $query = 'CREATE TABLE ' . $this->conn->quoteIdentifier($name, true) . ' (' . $queryFields; + + $check = $this->getCheckDeclaration($fields); + + if ( ! empty($check)) { + $query .= ', ' . $check; + } + + $query .= ')'; + + $sql[] = $query; + + if (isset($options['indexes']) && ! empty($options['indexes'])) { + foreach($options['indexes'] as $index => $definition) { + if (is_array($definition)) { + $sql[] = $this->createIndexSql($name,$index, $definition); + } + } + } + + if (isset($options['foreignKeys'])) { + foreach ((array) $options['foreignKeys'] as $k => $definition) { + if (is_array($definition)) { + $sql[] = $this->createForeignKeySql($name, $definition); + } + } + } + + return $sql; + } + + /** + * getNotNullFieldDeclaration + * Obtain DBMS specific SQL code portion needed to set a NOT NULL + * declaration to be used in statements like CREATE TABLE. + * + * @param array $field field definition array + * @return string DBMS specific SQL code portion needed to set a default value + */ + public function getNotNullFieldDeclaration(array $definition) + { + return ( + (isset($definition['notnull']) && $definition['notnull']) || + (isset($definition['primary']) && $definition['primary']) + ) ? ' NOT NULL' : ' NULL'; + } + + /** + * @see Doctrine_Export::getDefaultFieldDeclaration + * + * @param array $field field definition array + * @return string DBMS specific SQL code portion needed to set a default value + */ + public function getDefaultFieldDeclaration($field) + { + $default = ''; + + if (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) + ? null : $this->valid_default_values[$field['type']]; + + if ($field['default'] === '' && + ($this->conn->getAttribute(Doctrine_Core::ATTR_PORTABILITY) & Doctrine_Core::PORTABILITY_EMPTY_TO_NULL)) { + $field['default'] = null; + } + } + + if ($field['type'] === 'boolean') { + $field['default'] = $this->conn->convertBooleans($field['default']); + } + + if (array_key_exists('defaultConstraintName', $field)) { + $default .= ' CONSTRAINT ' . $field['defaultConstraintName']; + } + + $default .= ' DEFAULT ' . (is_null($field['default']) + ? 'NULL' + : $this->conn->quote($field['default'], $field['type'])); + } + + return $default; + } +} \ No newline at end of file diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Mysql.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Mysql.php new file mode 100644 index 0000000..afa3b9b --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Mysql.php @@ -0,0 +1,819 @@ +. + */ + +/** + * Doctrine_Export_Mysql + * + * @package Doctrine + * @subpackage Export + * @author Konsta Vesterinen + * @author Lukas Smith (PEAR MDB2 library) + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 1.0 + * @version $Revision: 7653 $ + */ +class Doctrine_Export_Mysql extends Doctrine_Export +{ + /** + * drop existing constraint + * + * @param string $table name of table that should be used in method + * @param string $name name of the constraint to be dropped + * @param string $primary hint if the constraint is primary + * @return void + */ + public function dropConstraint($table, $name, $primary = false) + { + $table = $this->conn->quoteIdentifier($table); + + if ( ! $primary) { + $name = 'CONSTRAINT ' . $this->conn->quoteIdentifier($name); + } else { + $name = 'PRIMARY KEY'; + } + + return $this->conn->exec('ALTER TABLE ' . $table . ' DROP ' . $name); + } + + /** + * createDatabaseSql + * + * @param string $name + * @return void + */ + public function createDatabaseSql($name) + { + return 'CREATE DATABASE ' . $this->conn->quoteIdentifier($name, true); + } + + /** + * drop an existing database + * + * @param string $name name of the database that should be dropped + * @return string + */ + public function dropDatabaseSql($name) + { + return array( + 'SET FOREIGN_KEY_CHECKS = 0', + 'DROP DATABASE ' . $this->conn->quoteIdentifier($name), + 'SET FOREIGN_KEY_CHECKS = 1' + ); + } + + /** + * create a new table + * + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * The indexes of the array entries are the names of the fields of the table an + * the array entry values are associative arrays like those that are meant to be + * passed with the field definitions to get[Type]Declaration() functions. + * array( + * 'id' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * 'notnull' => 1 + * 'default' => 0 + * ), + * 'name' => array( + * 'type' => 'text', + * 'length' => 12 + * ), + * 'password' => array( + * 'type' => 'text', + * 'length' => 12 + * ) + * ); + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'charset' => 'utf8', + * 'collate' => 'utf8_unicode_ci', + * 'type' => 'innodb', + * ); + * + * @return void + */ + public function createTableSql($name, array $fields, array $options = array()) + { + if ( ! $name) + throw new Doctrine_Export_Exception('no valid table name specified'); + + if (empty($fields)) { + throw new Doctrine_Export_Exception('no fields specified for table "'.$name.'"'); + } + $queryFields = $this->getFieldDeclarationList($fields); + + // build indexes for all foreign key fields (needed in MySQL!!) + if (isset($options['foreignKeys'])) { + foreach ($options['foreignKeys'] as $fk) { + $local = $fk['local']; + $found = false; + if (isset($options['indexes'])) { + foreach ($options['indexes'] as $definition) { + if (is_string($definition['fields'])) { + // Check if index already exists on the column + $found = $found || ($local == $definition['fields']); + } else if (in_array($local, $definition['fields']) && count($definition['fields']) === 1) { + // Index already exists on the column + $found = true; + } + } + } + if (isset($options['primary']) && !empty($options['primary']) && + in_array($local, $options['primary'])) { + // field is part of the PK and therefore already indexed + $found = true; + } + + if ( ! $found) { + if (is_array($local)) { + foreach($local as $localidx) { + $options['indexes'][$localidx] = array('fields' => array($localidx => array())); + } + } else { + $options['indexes'][$local] = array('fields' => array($local => array())); + } + } + } + } + + // add all indexes + if (isset($options['indexes']) && ! empty($options['indexes'])) { + // Case Insensitive checking for duplicate indexes... + $dupes = array(); + foreach ($options['indexes'] as $key => $index) { + if (in_array(strtolower($key), $dupes)) { + unset($options['indexes'][$key]); + } else { + $dupes[] = strtolower($key); + } + } + unset($dupes); + + foreach($options['indexes'] as $index => $definition) { + $queryFields .= ', ' . $this->getIndexDeclaration($index, $definition); + } + } + + // attach all primary keys + if (isset($options['primary']) && ! empty($options['primary'])) { + $keyColumns = array_values($options['primary']); + $keyColumns = array_map(array($this->conn, 'quoteIdentifier'), $keyColumns); + $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; + } + + $query = 'CREATE TABLE ' . $this->conn->quoteIdentifier($name, true) . ' (' . $queryFields . ')'; + + $optionStrings = array(); + + if (isset($options['comment'])) { + $optionStrings['comment'] = 'COMMENT = ' . $this->conn->quote($options['comment'], 'text'); + } + if (isset($options['charset'])) { + $optionStrings['charset'] = 'DEFAULT CHARACTER SET ' . $options['charset']; + } + if (isset($options['collate'])) { + $optionStrings['collate'] = 'COLLATE ' . $options['collate']; + } + + $type = false; + + // get the type of the table + if (isset($options['type'])) { + $type = $options['type']; + } else { + $type = $this->conn->getAttribute(Doctrine_Core::ATTR_DEFAULT_TABLE_TYPE); + } + + if ($type) { + $optionStrings[] = 'ENGINE = ' . $type; + } + + if ( ! empty($optionStrings)) { + $query.= ' '.implode(' ', $optionStrings); + } + $sql[] = $query; + + if (isset($options['foreignKeys'])) { + + foreach ((array) $options['foreignKeys'] as $k => $definition) { + if (is_array($definition)) { + $sql[] = $this->createForeignKeySql($name, $definition); + } + } + } + return $sql; + } + + /** + * Obtain DBMS specific SQL code portion needed to declare a generic type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * charset + * Text value with the default CHARACTER SET for this field. + * collation + * Text value with the default COLLATION for this field. + * unique + * unique constraint + * check + * column check constraint + * + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getDeclaration($name, array $field) + { + + $default = $this->getDefaultFieldDeclaration($field); + + $charset = (isset($field['charset']) && $field['charset']) ? + ' ' . $this->getCharsetFieldDeclaration($field['charset']) : ''; + + $collation = (isset($field['collation']) && $field['collation']) ? + ' ' . $this->getCollationFieldDeclaration($field['collation']) : ''; + + $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ''; + + $unique = (isset($field['unique']) && $field['unique']) ? + ' ' . $this->getUniqueFieldDeclaration() : ''; + + $check = (isset($field['check']) && $field['check']) ? + ' ' . $field['check'] : ''; + + $comment = (isset($field['comment']) && $field['comment']) ? + " COMMENT " . $this->conn->quote($field['comment'], 'text') : ''; + + $method = 'get' . $field['type'] . 'Declaration'; + + try { + if (method_exists($this->conn->dataDict, $method)) { + return $this->conn->dataDict->$method($name, $field); + } else { + $dec = $this->conn->dataDict->getNativeDeclaration($field); + } + + return $this->conn->quoteIdentifier($name, true) + . ' ' . $dec . $charset . $default . $notnull . $comment . $unique . $check . $collation; + } catch (Exception $e) { + throw new Doctrine_Exception('Around field ' . $name . ': ' . $e->getMessage() . "\n\n" . $e->getTraceAsString() . "\n\n"); + } + } + + /** + * alter an existing table + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type + * of change that is intended to be performed. The types of + * changes that are currently supported are defined as follows: + * + * name + * + * New name for the table. + * + * add + * + * Associative array with the names of fields to be added as + * indexes of the array. The value of each entry of the array + * should be set to another associative array with the properties + * of the fields to be added. The properties of the fields should + * be the same as defined by the Metabase parser. + * + * + * remove + * + * Associative array with the names of fields to be removed as indexes + * of the array. Currently the values assigned to each entry are ignored. + * An empty array should be used for future compatibility. + * + * rename + * + * Associative array with the names of fields to be renamed as indexes + * of the array. The value of each entry of the array should be set to + * another associative array with the entry named name with the new + * field name and the entry named Declaration that is expected to contain + * the portion of the field declaration already in DBMS specific SQL code + * as it is used in the CREATE TABLE statement. + * + * change + * + * Associative array with the names of the fields to be changed as indexes + * of the array. Keep in mind that if it is intended to change either the + * name of a field and any other properties, the change array entries + * should have the new names of the fields as array indexes. + * + * The value of each entry of the array should be set to another associative + * array with the properties of the fields to that are meant to be changed as + * array entries. These entries should be assigned to the new values of the + * respective properties. The properties of the fields should be the same + * as defined by the Metabase parser. + * + * Example + * array( + * 'name' => 'userlist', + * 'add' => array( + * 'quota' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * ) + * ), + * 'remove' => array( + * 'file_limit' => array(), + * 'time_limit' => array() + * ), + * 'change' => array( + * 'name' => array( + * 'length' => '20', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 20, + * ), + * ) + * ), + * 'rename' => array( + * 'sex' => array( + * 'name' => 'gender', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 1, + * 'default' => 'M', + * ), + * ) + * ) + * ) + * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * @return boolean + */ + public function alterTableSql($name, array $changes, $check = false) + { + if ( ! $name) { + throw new Doctrine_Export_Exception('no valid table name specified'); + } + foreach ($changes as $changeName => $change) { + switch ($changeName) { + case 'add': + case 'remove': + case 'change': + case 'rename': + case 'name': + break; + default: + throw new Doctrine_Export_Exception('change type "' . $changeName . '" not yet supported'); + } + } + + if ($check) { + return true; + } + + $query = ''; + if ( ! empty($changes['name'])) { + $change_name = $this->conn->quoteIdentifier($changes['name']); + $query .= 'RENAME TO ' . $change_name; + } + + if ( ! empty($changes['add']) && is_array($changes['add'])) { + foreach ($changes['add'] as $fieldName => $field) { + if ($query) { + $query.= ', '; + } + $query.= 'ADD ' . $this->getDeclaration($fieldName, $field); + } + } + + if ( ! empty($changes['remove']) && is_array($changes['remove'])) { + foreach ($changes['remove'] as $fieldName => $field) { + if ($query) { + $query .= ', '; + } + $fieldName = $this->conn->quoteIdentifier($fieldName); + $query .= 'DROP ' . $fieldName; + } + } + + $rename = array(); + if ( ! empty($changes['rename']) && is_array($changes['rename'])) { + foreach ($changes['rename'] as $fieldName => $field) { + $rename[$field['name']] = $fieldName; + } + } + + if ( ! empty($changes['change']) && is_array($changes['change'])) { + foreach ($changes['change'] as $fieldName => $field) { + if ($query) { + $query.= ', '; + } + if (isset($rename[$fieldName])) { + $oldFieldName = $rename[$fieldName]; + unset($rename[$fieldName]); + } else { + $oldFieldName = $fieldName; + } + $oldFieldName = $this->conn->quoteIdentifier($oldFieldName, true); + $query .= 'CHANGE ' . $oldFieldName . ' ' + . $this->getDeclaration($fieldName, $field['definition']); + } + } + + if ( ! empty($rename) && is_array($rename)) { + foreach ($rename as $renameName => $renamedField) { + if ($query) { + $query.= ', '; + } + $field = $changes['rename'][$renamedField]; + $renamedField = $this->conn->quoteIdentifier($renamedField, true); + $query .= 'CHANGE ' . $renamedField . ' ' + . $this->getDeclaration($field['name'], $field['definition']); + } + } + + if ( ! $query) { + return false; + } + + $name = $this->conn->quoteIdentifier($name, true); + + return 'ALTER TABLE ' . $name . ' ' . $query; + } + + /** + * create sequence + * + * @param string $sequenceName name of the sequence to be created + * @param string $start start value of the sequence; default is 1 + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'charset' => 'utf8', + * 'collate' => 'utf8_unicode_ci', + * 'type' => 'innodb', + * ); + * @return boolean + */ + public function createSequence($sequenceName, $start = 1, array $options = array()) + { + $sequenceName = $this->conn->quoteIdentifier($sequenceName, true); + $seqcolName = $this->conn->quoteIdentifier($this->conn->getAttribute(Doctrine_Core::ATTR_SEQCOL_NAME), true); + + $optionsStrings = array(); + + if (isset($options['comment']) && ! empty($options['comment'])) { + $optionsStrings['comment'] = 'COMMENT = ' . $this->conn->quote($options['comment'], 'string'); + } + + if (isset($options['charset']) && ! empty($options['charset'])) { + $optionsStrings['charset'] = 'DEFAULT CHARACTER SET ' . $options['charset']; + + if (isset($options['collate'])) { + $optionsStrings['charset'] .= ' COLLATE ' . $options['collate']; + } + } + + $type = false; + + if (isset($options['type'])) { + $type = $options['type']; + } else { + $type = $this->conn->getAttribute(Doctrine_Core::ATTR_DEFAULT_TABLE_TYPE); + } + if ($type) { + $optionsStrings[] = 'ENGINE = ' . $type; + } + + + try { + $query = 'CREATE TABLE ' . $sequenceName + . ' (' . $seqcolName . ' BIGINT NOT NULL AUTO_INCREMENT, PRIMARY KEY (' + . $seqcolName . ')) ' . implode($optionsStrings, ' '); + + $res = $this->conn->exec($query); + } catch(Doctrine_Connection_Exception $e) { + throw new Doctrine_Export_Exception('could not create sequence table'); + } + + if ($start == 1 && $res == 1) + return true; + + $query = 'INSERT INTO ' . $sequenceName + . ' (' . $seqcolName . ') VALUES (' . ($start - 1) . ')'; + + $res = $this->conn->exec($query); + + if ($res == 1) + return true; + + // Handle error + try { + $result = $this->conn->exec('DROP TABLE ' . $sequenceName); + } catch(Doctrine_Connection_Exception $e) { + throw new Doctrine_Export_Exception('could not drop inconsistent sequence table'); + } + + + } + + /** + * Get the stucture of a field into an array + * + * @author Leoncx + * @param string $table name of the table on which the index is to be created + * @param string $name name of the index to be created + * @param array $definition associative array that defines properties of the index to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the index fields as array + * indexes. Each entry of this array is set to another type of associative + * array that specifies properties of the index that are specific to + * each field. + * + * Currently, only the sorting property is supported. It should be used + * to define the sorting direction of the index. It may be set to either + * ascending or descending. + * + * Not all DBMS support index sorting direction configuration. The DBMS + * drivers of those that do not support it ignore this property. Use the + * function supports() to determine whether the DBMS driver can manage indexes. + * + * Example + * array( + * 'fields' => array( + * 'user_name' => array( + * 'sorting' => 'ASC' + * 'length' => 10 + * ), + * 'last_login' => array() + * ) + * ) + * @throws PDOException + * @return void + */ + public function createIndexSql($table, $name, array $definition) + { + $table = $table; + $table = $this->conn->quoteIdentifier($table, true); + + $name = $this->conn->formatter->getIndexName($name); + $name = $this->conn->quoteIdentifier($name); + $type = ''; + if (isset($definition['type'])) { + switch (strtolower($definition['type'])) { + case 'fulltext': + case 'unique': + $type = strtoupper($definition['type']) . ' '; + break; + default: + throw new Doctrine_Export_Exception( + 'Unknown type ' . $definition['type'] . ' for index ' . $name . ' in table ' . $table + ); + } + } + $query = 'CREATE ' . $type . 'INDEX ' . $name . ' ON ' . $table; + $query .= ' (' . $this->getIndexFieldDeclarationList($definition['fields']) . ')'; + + return $query; + } + + /** + * getDefaultDeclaration + * Obtain DBMS specific SQL code portion needed to set a default value + * declaration to be used in statements like CREATE TABLE. + * + * @param array $field field definition array + * @return string DBMS specific SQL code portion needed to set a default value + */ + public function getDefaultFieldDeclaration($field) + { + $default = ''; + if (isset($field['default']) && ( ! isset($field['length']) || $field['length'] <= 255)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) + ? null : $this->valid_default_values[$field['type']]; + + if ($field['default'] === '' + && ($this->conn->getAttribute(Doctrine_Core::ATTR_PORTABILITY) & Doctrine_Core::PORTABILITY_EMPTY_TO_NULL) + ) { + $field['default'] = ' '; + } + } + + // Proposed patch: + if ($field['type'] == 'enum' && $this->conn->getAttribute(Doctrine_Core::ATTR_USE_NATIVE_ENUM)) { + $fieldType = 'varchar'; + } else { + $fieldType = $field['type']; + } + + $default = ' DEFAULT ' . (is_null($field['default']) + ? 'NULL' + : $this->conn->quote($field['default'], $fieldType)); + //$default = ' DEFAULT ' . $this->conn->quote($field['default'], $field['type']); + } + + return $default; + } + + /** + * Obtain DBMS specific SQL code portion needed to set an index + * declaration to be used in statements like CREATE TABLE. + * + * @param string $charset name of the index + * @param array $definition index definition + * @return string DBMS specific SQL code portion needed to set an index + */ + public function getIndexDeclaration($name, array $definition) + { + $name = $this->conn->formatter->getIndexName($name); + $type = ''; + if (isset($definition['type'])) { + switch (strtolower($definition['type'])) { + case 'fulltext': + case 'unique': + $type = strtoupper($definition['type']) . ' '; + break; + default: + throw new Doctrine_Export_Exception( + 'Unknown type ' . $definition['type'] . ' for index ' . $name + ); + } + } + + if ( ! isset($definition['fields'])) { + throw new Doctrine_Export_Exception('No columns given for index ' . $name); + } + if ( ! is_array($definition['fields'])) { + $definition['fields'] = array($definition['fields']); + } + + $query = $type . 'INDEX ' . $this->conn->quoteIdentifier($name); + + $query .= ' (' . $this->getIndexFieldDeclarationList($definition['fields']) . ')'; + + return $query; + } + + /** + * getIndexFieldDeclarationList + * Obtain DBMS specific SQL code portion needed to set an index + * declaration to be used in statements like CREATE TABLE. + * + * @return string + */ + public function getIndexFieldDeclarationList(array $fields) + { + $declFields = array(); + + foreach ($fields as $fieldName => $field) { + $fieldString = $this->conn->quoteIdentifier($fieldName); + + if (is_array($field)) { + if (isset($field['length'])) { + $fieldString .= '(' . $field['length'] . ')'; + } + + if (isset($field['sorting'])) { + $sort = strtoupper($field['sorting']); + switch ($sort) { + case 'ASC': + case 'DESC': + $fieldString .= ' ' . $sort; + break; + default: + throw new Doctrine_Export_Exception('Unknown index sorting option given.'); + } + } + } else { + $fieldString = $this->conn->quoteIdentifier($field); + } + $declFields[] = $fieldString; + } + return implode(', ', $declFields); + } + + /** + * Returns a character set declaration. + * + * @param string $charset A character set + * + * @return string A character set declaration + */ + public function getCharsetFieldDeclaration($charset) + { + return $this->conn->dataDict->getCharsetFieldDeclaration($charset); + } + + /** + * Returns a collation declaration. + * + * @param string $collation A collation + * + * @return string A collation declaration + */ + public function getCollationFieldDeclaration($collation) + { + return $this->conn->dataDict->getCollationFieldDeclaration($collation); + } + + /** + * getAdvancedForeignKeyOptions + * Return the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param array $definition + * @return string + */ + public function getAdvancedForeignKeyOptions(array $definition) + { + $query = ''; + if ( ! empty($definition['match'])) { + $query .= ' MATCH ' . $definition['match']; + } + if ( ! empty($definition['onUpdate'])) { + $query .= ' ON UPDATE ' . $this->getForeignKeyReferentialAction($definition['onUpdate']); + } + if ( ! empty($definition['onDelete'])) { + $query .= ' ON DELETE ' . $this->getForeignKeyReferentialAction($definition['onDelete']); + } + return $query; + } + + /** + * drop existing index + * + * @param string $table name of table that should be used in method + * @param string $name name of the index to be dropped + * @return void + */ + public function dropIndexSql($table, $name) + { + $table = $this->conn->quoteIdentifier($table, true); + $name = $this->conn->quoteIdentifier($this->conn->formatter->getIndexName($name), true); + return 'DROP INDEX ' . $name . ' ON ' . $table; + } + + /** + * dropTable + * + * @param string $table name of table that should be dropped from the database + * @throws PDOException + * @return void + */ + public function dropTableSql($table) + { + $table = $this->conn->quoteIdentifier($table, true); + return 'DROP TABLE ' . $table; + } + + /** + * drop existing foreign key + * + * @param string $table name of table that should be used in method + * @param string $name name of the foreign key to be dropped + * @return void + */ + public function dropForeignKey($table, $name) + { + $table = $this->conn->quoteIdentifier($table); + $name = $this->conn->quoteIdentifier($this->conn->formatter->getForeignKeyName($name)); + + return $this->conn->exec('ALTER TABLE ' . $table . ' DROP FOREIGN KEY ' . $name); + } +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Oracle.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Oracle.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Oracle.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Oracle.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Pgsql.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Pgsql.php new file mode 100644 index 0000000..6f1b106 --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Pgsql.php @@ -0,0 +1,393 @@ +. + */ + +/** + * Doctrine_Export_Pgsql + * + * @package Doctrine + * @subpackage Export + * @author Konsta Vesterinen + * @author Lukas Smith (PEAR MDB2 library) + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 1.0 + * @version $Revision: 7680 $ + */ +class Doctrine_Export_Pgsql extends Doctrine_Export +{ + public $tmpConnectionDatabase = 'postgres'; + + /** + * createDatabaseSql + * + * @param string $name + * @return void + */ + public function createDatabaseSql($name) + { + $query = 'CREATE DATABASE ' . $this->conn->quoteIdentifier($name); + + return $query; + } + + /** + * drop an existing database + * + * @param string $name name of the database that should be dropped + * @throws PDOException + * @access public + */ + public function dropDatabaseSql($name) + { + $query = 'DROP DATABASE ' . $this->conn->quoteIdentifier($name); + + return $query; + } + + /** + * getAdvancedForeignKeyOptions + * Return the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param array $definition foreign key definition + * @return string + * @access protected + */ + public function getAdvancedForeignKeyOptions(array $definition) + { + $query = ''; + if (isset($definition['match'])) { + $query .= ' MATCH ' . $definition['match']; + } + if (isset($definition['onUpdate'])) { + $query .= ' ON UPDATE ' . $definition['onUpdate']; + } + if (isset($definition['onDelete'])) { + $query .= ' ON DELETE ' . $definition['onDelete']; + } + if (isset($definition['deferrable'])) { + $query .= ' DEFERRABLE'; + } else { + $query .= ' NOT DEFERRABLE'; + } + if (isset($definition['deferred'])) { + $query .= ' INITIALLY DEFERRED'; + } else { + $query .= ' INITIALLY IMMEDIATE'; + } + return $query; + } + + /** + * generates the sql for altering an existing table on postgresql + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * @see Doctrine_Export::alterTable() + * @return array + */ + public function alterTableSql($name, array $changes, $check = false) + { + foreach ($changes as $changeName => $change) { + switch ($changeName) { + case 'add': + case 'remove': + case 'change': + case 'name': + case 'rename': + break; + default: + throw new Doctrine_Export_Exception('change type "' . $changeName . '\" not yet supported'); + } + } + + if ($check) { + return true; + } + + $sql = array(); + + if (isset($changes['add']) && is_array($changes['add'])) { + foreach ($changes['add'] as $fieldName => $field) { + $query = 'ADD ' . $this->getDeclaration($fieldName, $field); + $sql[] = 'ALTER TABLE ' . $this->conn->quoteIdentifier($name, true) . ' ' . $query; + } + } + + if (isset($changes['remove']) && is_array($changes['remove'])) { + foreach ($changes['remove'] as $fieldName => $field) { + $fieldName = $this->conn->quoteIdentifier($fieldName, true); + $query = 'DROP ' . $fieldName; + $sql[] = 'ALTER TABLE ' . $this->conn->quoteIdentifier($name, true) . ' ' . $query; + } + } + + if (isset($changes['change']) && is_array($changes['change'])) { + foreach ($changes['change'] as $fieldName => $field) { + $fieldName = $this->conn->quoteIdentifier($fieldName, true); + if (isset($field['definition']['type'])) { + $serverInfo = $this->conn->getServerVersion(); + + if (is_array($serverInfo) && $serverInfo['major'] < 8) { + throw new Doctrine_Export_Exception('changing column type for "'.$field['type'].'\" requires PostgreSQL 8.0 or above'); + } + $query = 'ALTER ' . $fieldName . ' TYPE ' . $this->conn->dataDict->getNativeDeclaration($field['definition']); + $sql[] = 'ALTER TABLE ' . $this->conn->quoteIdentifier($name, true) . ' ' . $query; + } + if (array_key_exists('default', $field['definition'])) { + $query = 'ALTER ' . $fieldName . ' SET DEFAULT ' . $this->conn->quote($field['definition']['default'], $field['definition']['type']); + $sql[] = 'ALTER TABLE ' . $this->conn->quoteIdentifier($name, true) . ' ' . $query; + } + if ( isset($field['definition']['notnull'])) { + $query = 'ALTER ' . $fieldName . ' ' . ($field['definition']['notnull'] ? 'SET' : 'DROP') . ' NOT NULL'; + $sql[] = 'ALTER TABLE ' . $this->conn->quoteIdentifier($name, true) . ' ' . $query; + } + } + } + + if (isset($changes['rename']) && is_array($changes['rename'])) { + foreach ($changes['rename'] as $fieldName => $field) { + $fieldName = $this->conn->quoteIdentifier($fieldName, true); + $sql[] = 'ALTER TABLE ' . $this->conn->quoteIdentifier($name, true) . ' RENAME COLUMN ' . $fieldName . ' TO ' . $this->conn->quoteIdentifier($field['name'], true); + } + } + + $name = $this->conn->quoteIdentifier($name, true); + if (isset($changes['name'])) { + $changeName = $this->conn->quoteIdentifier($changes['name'], true); + $sql[] = 'ALTER TABLE ' . $this->conn->quoteIdentifier($name, true) . ' RENAME TO ' . $changeName; + } + + return $sql; + } + + /** + * alter an existing table + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type + * of change that is intended to be performed. The types of + * changes that are currently supported are defined as follows: + * + * name + * + * New name for the table. + * + * add + * + * Associative array with the names of fields to be added as + * indexes of the array. The value of each entry of the array + * should be set to another associative array with the properties + * of the fields to be added. The properties of the fields should + * be the same as defined by the Metabase parser. + * + * + * remove + * + * Associative array with the names of fields to be removed as indexes + * of the array. Currently the values assigned to each entry are ignored. + * An empty array should be used for future compatibility. + * + * rename + * + * Associative array with the names of fields to be renamed as indexes + * of the array. The value of each entry of the array should be set to + * another associative array with the entry named name with the new + * field name and the entry named Declaration that is expected to contain + * the portion of the field declaration already in DBMS specific SQL code + * as it is used in the CREATE TABLE statement. + * + * change + * + * Associative array with the names of the fields to be changed as indexes + * of the array. Keep in mind that if it is intended to change either the + * name of a field and any other properties, the change array entries + * should have the new names of the fields as array indexes. + * + * The value of each entry of the array should be set to another associative + * array with the properties of the fields to that are meant to be changed as + * array entries. These entries should be assigned to the new values of the + * respective properties. The properties of the fields should be the same + * as defined by the Metabase parser. + * + * Example + * array( + * 'name' => 'userlist', + * 'add' => array( + * 'quota' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * ) + * ), + * 'remove' => array( + * 'file_limit' => array(), + * 'time_limit' => array() + * ), + * 'change' => array( + * 'name' => array( + * 'length' => '20', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 20, + * ), + * ) + * ), + * 'rename' => array( + * 'sex' => array( + * 'name' => 'gender', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 1, + * 'default' => 'M', + * ), + * ) + * ) + * ) + * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * @throws Doctrine_Connection_Exception + * @return boolean + */ + public function alterTable($name, array $changes, $check = false) + { + $sql = $this->alterTableSql($name, $changes, $check); + foreach ($sql as $query) { + $this->conn->exec($query); + } + return true; + } + + /** + * return RDBMS specific create sequence statement + * + * @throws Doctrine_Connection_Exception if something fails at database level + * @param string $seqName name of the sequence to be created + * @param string $start start value of the sequence; default is 1 + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'charset' => 'utf8', + * 'collate' => 'utf8_unicode_ci', + * ); + * @return string + */ + public function createSequenceSql($sequenceName, $start = 1, array $options = array()) + { + $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($sequenceName), true); + return 'CREATE SEQUENCE ' . $sequenceName . ' INCREMENT 1' . + ($start < 1 ? ' MINVALUE ' . $start : '') . ' START ' . $start; + } + + /** + * drop existing sequence + * + * @param string $sequenceName name of the sequence to be dropped + */ + public function dropSequenceSql($sequenceName) + { + $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($sequenceName), true); + return 'DROP SEQUENCE ' . $sequenceName; + } + + /** + * Creates a table. + * + * @param unknown_type $name + * @param array $fields + * @param array $options + * @return unknown + */ + public function createTableSql($name, array $fields, array $options = array()) + { + if ( ! $name) { + throw new Doctrine_Export_Exception('no valid table name specified'); + } + + if (empty($fields)) { + throw new Doctrine_Export_Exception('no fields specified for table ' . $name); + } + + $queryFields = $this->getFieldDeclarationList($fields); + + + if (isset($options['primary']) && ! empty($options['primary'])) { + $keyColumns = array_values($options['primary']); + $keyColumns = array_map(array($this->conn, 'quoteIdentifier'), $keyColumns); + $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; + } + + $query = 'CREATE TABLE ' . $this->conn->quoteIdentifier($name, true) . ' (' . $queryFields; + + if ($check = $this->getCheckDeclaration($fields)) { + $query .= ', ' . $check; + } + + if (isset($options['checks']) && $check = $this->getCheckDeclaration($options['checks'])) { + $query .= ', ' . $check; + } + + $query .= ')'; + + $sql[] = $query; + + if (isset($options['indexes']) && ! empty($options['indexes'])) { + foreach($options['indexes'] as $index => $definition) { + $sql[] = $this->createIndexSql($name, $index, $definition); + } + } + + if (isset($options['foreignKeys'])) { + + foreach ((array) $options['foreignKeys'] as $k => $definition) { + if (is_array($definition)) { + $sql[] = $this->createForeignKeySql($name, $definition); + } + } + } + if (isset($options['sequenceName'])) { + $sql[] = $this->createSequenceSql($options['sequenceName']); + } + return $sql; + } + + /** + * Get the stucture of a field into an array. + * + * @param string $table name of the table on which the index is to be created + * @param string $name name of the index to be created + * @param array $definition associative array that defines properties of the index to be created. + * @see Doctrine_Export::createIndex() + * @return string + */ + public function createIndexSql($table, $name, array $definition) + { + $query = parent::createIndexSql($table, $name, $definition); + if (isset($definition['where'])) { + return $query . ' WHERE ' . $definition['where']; + } + return $query; + } +} \ No newline at end of file diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Reporter.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Reporter.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Reporter.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Reporter.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Schema.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Schema.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Schema.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Schema.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Sqlite.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Sqlite.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Sqlite.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Export/Sqlite.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Driver.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Driver.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Driver.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Driver.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Exception.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Exception.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Exception.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Exception.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Mock.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Mock.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Mock.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Mock.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Mssql.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Mssql.php new file mode 100644 index 0000000..dc4f494 --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Mssql.php @@ -0,0 +1,135 @@ +. + */ + +/** + * Doctrine_Expression_Mssql + * + * @package Doctrine + * @subpackage Expression + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 1.0 + * @version $Revision: 7490 $ + * @author Konsta Vesterinen + */ +class Doctrine_Expression_Mssql extends Doctrine_Expression_Driver +{ + /** + * Return string to call a variable with the current timestamp inside an SQL statement + * There are three special variables for current date and time: + * - CURRENT_TIMESTAMP (date and time, TIMESTAMP type) + * - CURRENT_DATE (date, DATE type) + * - CURRENT_TIME (time, TIME type) + * + * @return string to call a variable with the current timestamp + * @access public + */ + public function now($type = 'timestamp') + { + switch ($type) { + case 'time': + case 'date': + case 'timestamp': + default: + return 'GETDATE()'; + } + } + + /** + * return string to call a function to get a substring inside an SQL statement + * + * @return string to call a function to get a substring + */ + public function substring($value, $position, $length = null) + { + if ( ! is_null($length)) { + return 'SUBSTRING(' . $value . ', ' . $position . ', ' . $length . ')'; + } + return 'SUBSTRING(' . $value . ', ' . $position . ', LEN(' . $value . ') - ' . $position . ' + 1)'; + } + + /** + * Returns string to concatenate two or more string parameters + * + * @param string $arg1 + * @param string $arg2 + * @param string $values... + * @return string to concatenate two strings + */ + public function concat() + { + $args = func_get_args(); + return '(' . implode(' + ', $args) . ')'; + } + + /** + * Returns global unique identifier + * + * @return string to get global unique identifier + */ + public function guid() + { + return 'NEWID()'; + } + + /** + * Returns the length of a text field + * + * @param string $column + * + * @return string + */ + public function length($column) + { + return 'LEN (' . $column . ')'; + } + + /** + * Returns an integer representing the specified datepart of the specified date. + * + * datepart + * + * Is the parameter that specifies the part of the date to return. The table lists dateparts and abbreviations recognized by Microsoft¨ SQL Serverª. + * + * Datepart Abbreviations + * year yy, yyyy + * quarter qq, q + * month mm, m + * dayofyear dy, y + * day dd, d + * week wk, ww + * weekday dw + * hour hh + * minute mi, n + * second ss, s + * millisecond ms + * + * @param $datepart + * @param $date + */ + public function date_part($datepart, $date) + { + // remove ' and " from datepart for dblib + $datepart = str_replace(array('\'', '"'), '', $datepart); + + return 'DATEPART(' . $datepart . ', ' . $date . ')'; + } +} diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Mysql.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Mysql.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Mysql.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Mysql.php diff --git a/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Oracle.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Oracle.php similarity index 100% rename from lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Oracle.php rename to lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Oracle.php diff --git a/lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Pgsql.php b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Pgsql.php new file mode 100644 index 0000000..f447b1e --- /dev/null +++ b/lib/vendor/lexpress/doctrine1/lib/Doctrine/Expression/Pgsql.php @@ -0,0 +1,260 @@ +. + */ + +/** + * Doctrine_Expression_Pgsql + * + * @package Doctrine + * @subpackage Expression + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 1.0 + * @version $Revision: 7685 $ + * @author Konsta Vesterinen + */ +class Doctrine_Expression_Pgsql extends Doctrine_Expression_Driver +{ + /** + * Returns the md5 sum of a field. + * + * Note: Not SQL92, but common functionality + * + * md5() works with the default PostgreSQL 8 versions. + * + * If you are using PostgreSQL 7.x or older you need + * to make sure that the digest procedure is installed. + * If you use RPMS (Redhat and Mandrake) install the postgresql-contrib + * package. You must then install the procedure by running this shell command: + * + * psql [dbname] < /usr/share/pgsql/contrib/pgcrypto.sql + * + * You should make sure you run this as the postgres user. + * + * @return string + */ + public function md5($column) + { + $column = $this->getIdentifier($column); + + return 'MD5(' . $column . ')'; + } + + /** + * Returns part of a string. + * + * Note: Not SQL92, but common functionality. + * + * @param string $value the target $value the string or the string column. + * @param int $from extract from this characeter. + * @param int $len extract this amount of characters. + * @return string sql that extracts part of a string. + */ + public function substring($value, $from, $len = null) + { + $value = $this->getIdentifier($value); + + if ($len === null) { + $len = $this->getIdentifier($len); + return 'SUBSTR(' . $value . ', ' . $from . ')'; + } else { + return 'SUBSTR(' . $value . ', ' . $from . ', ' . $len . ')'; + } + } + + /** + * Returns a series of strings concatinated + * + * concat() accepts an arbitrary number of parameters. Each parameter + * must contain an expression or an array with expressions. + * + * @param string|array(string) strings that will be concatinated. + * @return string + */ + + + /** + * PostgreSQLs AGE( [, ]) function. + * + * @param string $timestamp1 timestamp to subtract from NOW() + * @param string $timestamp2 optional; if given: subtract arguments + * @return string + */ + public function age($timestamp1, $timestamp2 = null) { + if ( $timestamp2 == null ) { + return 'AGE(' . $timestamp1 . ')'; + } + return 'AGE(' . $timestamp1 . ', ' . $timestamp2 . ')'; + } + + /** + * PostgreSQLs DATE_PART( ,