finish project configuration
authorymh <ymh.work@gmail.com>
Mon, 05 Oct 2009 16:58:06 +0200
changeset 10 d17aa71a58e0
parent 9 42c8da096ceb
child 11 cba6648bf1fe
finish project configuration
.hgignore
web/thdProject/config/ProjectConfiguration.class.php
web/thdProject/config/databases.yml
web/thdProject/config/propel.ini
web/thdProject/config/schema.yml
web/thdProject/log/.keepme
web/thdProject/web/sfDoctrinePlugin/LICENSE
web/thdProject/web/sfDoctrinePlugin/config/autoload.yml
web/thdProject/web/sfDoctrinePlugin/config/config.php
web/thdProject/web/sfDoctrinePlugin/config/sfDoctrinePluginConfiguration.class.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineForm/default/template/sfDoctrineFormBaseTemplate.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineForm/default/template/sfDoctrineFormGeneratedTemplate.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineForm/default/template/sfDoctrineFormPluginTemplate.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineForm/default/template/sfDoctrineFormTemplate.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineForm/default/template/sfDoctrinePluginFormTemplate.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineFormFilter/default/template/sfDoctrineFormFilterBaseTemplate.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineFormFilter/default/template/sfDoctrineFormFilterGeneratedTemplate.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineFormFilter/default/template/sfDoctrineFormFilterPluginTemplate.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineFormFilter/default/template/sfDoctrineFormFilterTemplate.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineFormFilter/default/template/sfDoctrinePluginFormFilterTemplate.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/actionsConfiguration.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/batchAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/configuration.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/createAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/deleteAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/editAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/fieldsConfiguration.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/filterAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/filtersAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/filtersConfiguration.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/indexAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/newAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/paginationAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/paginationConfiguration.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/processFormAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/sortingAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/sortingConfiguration.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/updateAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/skeleton/actions/actions.class.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/skeleton/config/generator.yml
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/skeleton/lib/configuration.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/skeleton/lib/helper.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/skeleton/templates/.sf
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/actions/actions.class.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/lib/helper.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_assets.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_filters.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_filters_field.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_flashes.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_form.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_form_actions.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_form_field.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_form_fieldset.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_form_footer.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_form_header.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_actions.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_batch_actions.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_field_boolean.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_footer.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_header.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_td_actions.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_td_batch_actions.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_td_stacked.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_td_tabular.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_th_stacked.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_th_tabular.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_pagination.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/editSuccess.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/indexSuccess.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/newSuccess.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/createAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/deleteAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/editAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/indexAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/newAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/processFormAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/showAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/updateAction.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/skeleton/actions/actions.class.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/skeleton/config/generator.yml
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/skeleton/templates/.sf
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/template/actions/actions.class.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/template/templates/_form.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/template/templates/editSuccess.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/template/templates/indexSuccess.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/template/templates/newSuccess.php
web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/template/templates/showSuccess.php
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.ar.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.bg.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.ca.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.cs.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.da.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.de.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.el.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.es.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.es_AR.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.eu.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.fi.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.fr.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.hr.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.hu.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.id.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.it.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.ja.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.lt.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.lv.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.nl.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.no.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.pl.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.pt.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.pt_BR.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.ro.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.ru.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.sk.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.sv.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.tr.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.uk.xml
web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.zh_CN.xml
web/thdProject/web/sfDoctrinePlugin/lib/cli/sfDoctrineCli.class.php
web/thdProject/web/sfDoctrinePlugin/lib/database/sfDoctrineConnectionListener.class.php
web/thdProject/web/sfDoctrinePlugin/lib/database/sfDoctrineDataRetriever.class.php
web/thdProject/web/sfDoctrinePlugin/lib/database/sfDoctrineDatabase.class.php
web/thdProject/web/sfDoctrinePlugin/lib/debug/sfWebDebugPanelDoctrine.class.php
web/thdProject/web/sfDoctrinePlugin/lib/form/sfFormDoctrine.class.php
web/thdProject/web/sfDoctrinePlugin/lib/form/sfFormFilterDoctrine.class.php
web/thdProject/web/sfDoctrinePlugin/lib/generator/sfDoctrineColumn.class.php
web/thdProject/web/sfDoctrinePlugin/lib/generator/sfDoctrineFormFilterGenerator.class.php
web/thdProject/web/sfDoctrinePlugin/lib/generator/sfDoctrineFormGenerator.class.php
web/thdProject/web/sfDoctrinePlugin/lib/generator/sfDoctrineGenerator.class.php
web/thdProject/web/sfDoctrinePlugin/lib/helper/ObjectDoctrineAdminHelper.php
web/thdProject/web/sfDoctrinePlugin/lib/log/sfDoctrineLogger.class.php
web/thdProject/web/sfDoctrinePlugin/lib/pager/sfDoctrinePager.class.php
web/thdProject/web/sfDoctrinePlugin/lib/record/sfDoctrineRecord.class.php
web/thdProject/web/sfDoctrinePlugin/lib/record/sfDoctrineRecordI18nFilter.class.php
web/thdProject/web/sfDoctrinePlugin/lib/record/sfDoctrineRecordListener.class.php
web/thdProject/web/sfDoctrinePlugin/lib/routing/sfDoctrineRoute.class.php
web/thdProject/web/sfDoctrinePlugin/lib/routing/sfDoctrineRouteCollection.class.php
web/thdProject/web/sfDoctrinePlugin/lib/sfDoctrineException.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBaseTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildAllLoadTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildAllReloadTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildAllReloadTestAllTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildAllTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildDbTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildFiltersTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildFormsTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildModelTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildSchemaTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildSqlTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineDataDumpTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineDataLoadTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineDqlTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineDropDbTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineGenerateAdminTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineGenerateMigrationTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineGenerateMigrationsDbTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineGenerateMigrationsModelsTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineGenerateModuleForRouteTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineGenerateModuleTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineInsertSqlTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineMigrateTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineRebuildDbTask.class.php
web/thdProject/web/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php
web/thdProject/web/sfDoctrinePlugin/lib/validator/sfDoctrineUniqueValidator.class.php
web/thdProject/web/sfDoctrinePlugin/lib/validator/sfValidatorDoctrineChoice.class.php
web/thdProject/web/sfDoctrinePlugin/lib/validator/sfValidatorDoctrineChoiceMany.class.php
web/thdProject/web/sfDoctrinePlugin/lib/validator/sfValidatorDoctrineUnique.class.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Access.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Db2.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Interface.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Mock.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Mysqli.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Oracle.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement/Interface.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement/Mock.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement/Oracle.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/AuditLog.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/AuditLog/Listener.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Builder.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Apc.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Array.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Db.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Driver.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Interface.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Memcache.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Xcache.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli/AnsiColorFormatter.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli/Formatter.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator/Expandable.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator/Normal.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator/Offset.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Offset.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Column.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Compiler.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Compiler/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Configurable.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Common.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Db2.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Firebird.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Firebird/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Informix.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Informix/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mock.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Module.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mssql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mssql/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mysql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mysql/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Oracle.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Oracle/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Pgsql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Pgsql/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Profiler.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Profiler/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Sqlite.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Sqlite/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Statement.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/UnitOfWork.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data/Export.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data/Import.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Firebird.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Informix.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Mssql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Mysql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Oracle.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Pgsql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Sqlite.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataType.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Event.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener/Chain.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener/Interface.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Firebird.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Frontbase.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Informix.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Mssql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Mysql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Oracle.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Pgsql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Reporter.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Schema.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Sqlite.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Driver.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Firebird.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Informix.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Mock.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Mssql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Mysql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Oracle.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Pgsql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Sqlite.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/File.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/File/Index.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Formatter.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hook.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hook/Equal.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hook/Integer.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hook/Parser.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hook/Parser/Complex.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hook/WordLike.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hydrator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hydrator/Abstract.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hydrator/ArrayDriver.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hydrator/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hydrator/RecordDriver.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/I18n.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/I18n/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Builder.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Builder/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Firebird.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Informix.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Mssql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Mysql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Oracle.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Pgsql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Schema.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Sqlite.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Inflector.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/IntegrityMapper.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Lib.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Locator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Locator/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Locator/Injectable.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Locking/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Locking/Manager/Pessimistic.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Manager.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Manager/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Migration.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Migration/Builder.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Migration/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Migration/IrreversibleMigrationException.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Migration/Process.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/AdjacencyList.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/AdjacencyList/LevelOrderIterator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/AdjacencyList/PostOrderIterator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/AdjacencyList/PreOrderIterator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/Interface.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/MaterializedPath.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/MaterializedPath/LevelOrderIterator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/MaterializedPath/PostOrderIterator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/MaterializedPath/PreOrderIterator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/NestedSet.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/NestedSet/LevelOrderIterator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/NestedSet/PostOrderIterator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/NestedSet/PreOrderIterator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Null.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Overloadable.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Pager.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Pager/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Pager/Layout.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Pager/Range.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Pager/Range/Jumping.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Pager/Range/Sliding.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Json.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Serialize.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Spyc.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Spyc/YamlNode.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Xml.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/YamlSf.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/YamlSf/Dumper.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/YamlSf/Inline.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/YamlSf/Parser.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Yml.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Abstract.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Check.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Condition.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Filter.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Filter/Chain.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Filter/Interface.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Forupdate.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/From.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Groupby.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Having.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/JoinCondition.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Limit.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Offset.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Orderby.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Parser.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Part.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Registry.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Registry/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Select.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Set.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Tokenizer.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Tokenizer/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Where.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/RawSql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/RawSql/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Abstract.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Filter.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Filter/Compound.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Filter/Standard.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Generator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Iterator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Listener.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Listener/Chain.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Listener/Interface.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/State/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/UnknownPropertyException.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/Association.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/Association/Self.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/ForeignKey.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/LocalKey.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/Nest.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/Parser.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/Parser/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Analyzer.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Analyzer/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Analyzer/Interface.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Analyzer/Standard.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/File.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Indexer.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Indexer/Dir.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Indexer/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Listener.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Parser.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Query.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Record.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Db2.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Firebird.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Informix.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Mssql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Mysql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Oracle.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Pgsql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Sqlite.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Table.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Table/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Table/Repository.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Table/Repository/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/BuildAll.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/BuildAllLoad.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/BuildAllReload.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/Compile.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/CreateDb.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/CreateTables.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/Dql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/DropDb.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/DumpData.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateMigration.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateMigrationsDb.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateMigrationsModels.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateModelsDb.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateModelsYaml.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateSql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateYamlDb.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateYamlModels.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/LoadData.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/Migrate.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/RebuildDb.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Geographical.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/I18n.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Listener/Sluggable.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Listener/SoftDelete.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Listener/Timestampable.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/NestedSet.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Searchable.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Sluggable.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/SoftDelete.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Timestampable.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Versionable.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Firebird.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Informix.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Mock.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Mssql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Mysql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Oracle.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Pgsql.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Sqlite.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Tree.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Tree/AdjacencyList.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Tree/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Tree/Interface.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Tree/MaterializedPath.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Tree/NestedSet.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Util.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Country.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Creditcard.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Date.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Driver.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Email.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/ErrorStack.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Future.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Htmlcolor.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Ip.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Minlength.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Nospace.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Notblank.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Notnull.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Past.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Range.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Readonly.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Regexp.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Time.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Timestamp.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Unique.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Unsigned.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Usstate.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/View.php
web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/View/Exception.php
web/thdProject/web/sfDoctrinePlugin/lib/widget/sfWidgetFormDoctrineChoice.class.php
web/thdProject/web/sfDoctrinePlugin/lib/widget/sfWidgetFormDoctrineChoiceMany.class.php
web/thdProject/web/sfDoctrinePlugin/lib/widget/sfWidgetFormDoctrineSelect.class.php
web/thdProject/web/sfDoctrinePlugin/lib/widget/sfWidgetFormDoctrineSelectMany.class.php
web/thdProject/web/sfDoctrinePlugin/test/bin/coverage.php
web/thdProject/web/sfDoctrinePlugin/test/bin/prove.php
web/thdProject/web/sfDoctrinePlugin/test/bootstrap/functional.php
web/thdProject/web/sfDoctrinePlugin/test/bootstrap/unit.php
web/thdProject/web/sfDoctrinePlugin/test/functional/EnvironmentSetupTest.php
web/thdProject/web/sfDoctrinePlugin/test/functional/FormTest.php
web/thdProject/web/sfDoctrinePlugin/test/functional/I18nTest.php
web/thdProject/web/sfDoctrinePlugin/test/functional/PagerTest.php
web/thdProject/web/sfDoctrinePlugin/test/functional/Ticket/5269Test.php
web/thdProject/web/sfDoctrinePlugin/test/functional/UniqueTest.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/app.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/backendConfiguration.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/cache.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/factories.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/filters.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/routing.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/security.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/settings.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/view.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/lib/myUser.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/modules/doctrine_route_test/actions/actions.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/modules/doctrine_route_test/templates/indexSuccess.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/modules/my_articles/actions/actions.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/modules/my_articles/config/generator.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/modules/my_articles/lib/my_articlesGeneratorConfiguration.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/modules/my_articles/lib/my_articlesGeneratorHelper.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/templates/layout.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/app.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/cache.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/factories.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/filters.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/frontendConfiguration.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/routing.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/security.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/settings.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/view.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/lib/myUser.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/modules/articles/actions/actions.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/modules/articles/templates/editSuccess.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/modules/articles/templates/indexSuccess.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/templates/layout.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/config/ProjectConfiguration.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/config/databases.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/config/doctrine/schema.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/config/propel.ini
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/config/properties.ini
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/config/rsync_exclude.txt
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/config/schema.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/data/fixtures/fixtures.yml
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/data/sql/schema.sql
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/ArticleFormFilter.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/ArticleTranslationFormFilter.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/AuthorFormFilter.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/BaseFormFilterDoctrine.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/GroupFormFilter.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/GroupPermissionFormFilter.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/PermissionFormFilter.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/ProfileFormFilter.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/SubscriptionFormFilter.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/UniqueTestFormFilter.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/UserFormFilter.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/UserGroupFormFilter.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/UserPermissionFormFilter.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/myDoctrineRecordFormFilter.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/ArticleForm.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/ArticleTranslationForm.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/AuthorForm.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/BaseFormDoctrine.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/GroupForm.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/GroupPermissionForm.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/PermissionForm.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/ProfileForm.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/SubscriptionForm.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/UniqueTestForm.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/UserForm.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/UserGroupForm.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/UserPermissionForm.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/myDoctrineRecordForm.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/Article.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/ArticleTable.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/Author.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/AuthorTable.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/Group.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/GroupPermission.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/GroupPermissionTable.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/GroupTable.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/Permission.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/PermissionTable.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/Profile.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/ProfileTable.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/Subscription.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/SubscriptionTable.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UniqueTest.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UniqueTestTable.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/User.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UserGroup.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UserGroupTable.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UserPermission.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UserPermissionTable.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UserTable.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/myDoctrineRecord.class.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/symfony
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/test/bootstrap/functional.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/test/bootstrap/unit.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/.htaccess
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/backend.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/backend_dev.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/css/main.css
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/frontend.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/frontend_dev.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/index.php
web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/robots.txt
web/thdProject/web/sfDoctrinePlugin/test/functional/sfDoctrineRecordTest.php
web/thdProject/web/sfDoctrinePlugin/test/unit/sfDoctrineColumnTest.php
web/thdProject/web/sfDoctrinePlugin/test/unit/sfDoctrineDatabaseTest.php
web/thdProject/web/sfDoctrinePlugin/web/css/default.css
web/thdProject/web/sfDoctrinePlugin/web/css/global.css
web/thdProject/web/sfDoctrinePlugin/web/images/asc.png
web/thdProject/web/sfDoctrinePlugin/web/images/default.png
web/thdProject/web/sfDoctrinePlugin/web/images/delete.png
web/thdProject/web/sfDoctrinePlugin/web/images/desc.png
web/thdProject/web/sfDoctrinePlugin/web/images/edit.png
web/thdProject/web/sfDoctrinePlugin/web/images/error.png
web/thdProject/web/sfDoctrinePlugin/web/images/first.png
web/thdProject/web/sfDoctrinePlugin/web/images/last.png
web/thdProject/web/sfDoctrinePlugin/web/images/list.png
web/thdProject/web/sfDoctrinePlugin/web/images/new.png
web/thdProject/web/sfDoctrinePlugin/web/images/next.png
web/thdProject/web/sfDoctrinePlugin/web/images/previous.png
web/thdProject/web/sfDoctrinePlugin/web/images/tick.png
web/thdProject/web/sfProtoculousPlugin/LICENSE
web/thdProject/web/sfProtoculousPlugin/LICENSE.prototype
web/thdProject/web/sfProtoculousPlugin/LICENSE.script.aculo.us
web/thdProject/web/sfProtoculousPlugin/config/settings.yml
web/thdProject/web/sfProtoculousPlugin/lib/helper/JavascriptHelper.php
web/thdProject/web/sfProtoculousPlugin/web/css/input_auto_complete_tag.css
web/thdProject/web/sfProtoculousPlugin/web/js/builder.js
web/thdProject/web/sfProtoculousPlugin/web/js/controls.js
web/thdProject/web/sfProtoculousPlugin/web/js/dragdrop.js
web/thdProject/web/sfProtoculousPlugin/web/js/effects.js
web/thdProject/web/sfProtoculousPlugin/web/js/index.html
web/thdProject/web/sfProtoculousPlugin/web/js/prototype.js
web/thdProject/web/sfProtoculousPlugin/web/js/scriptaculous.js
web/thdProject/web/sfProtoculousPlugin/web/js/slider.js
web/thdProject/web/sfProtoculousPlugin/web/js/sound.js
web/thdProject/web/sfProtoculousPlugin/web/js/unittest.js
--- a/.hgignore	Mon Oct 05 16:05:28 2009 +0200
+++ b/.hgignore	Mon Oct 05 16:58:06 2009 +0200
@@ -1,6 +1,11 @@
 
 syntax: regexp
 ^web/tagging/xxy\.f4v$
+^web/thdProject/cache/.*$
+^web/thdProject/cache$
+^web/thdProject/web/phpinfo.php$
+^web/thdProject/log/.*$
 
 syntax: glob
 .DS_Store
+*.swp
--- a/web/thdProject/config/ProjectConfiguration.class.php	Mon Oct 05 16:05:28 2009 +0200
+++ b/web/thdProject/config/ProjectConfiguration.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -7,7 +7,7 @@
 
 
 define('SF_ENVIRONMENT', 'dev');
-require_once '/Users/gautierthibault/SRV/symfony-1.2.8/lib/autoload/sfCoreAutoload.class.php';
+require_once dirname(__FILE__).'/../lib/vendor/symfony/lib/autoload/sfCoreAutoload.class.php';
 sfCoreAutoload::register();
 
 class ProjectConfiguration extends sfProjectConfiguration
--- a/web/thdProject/config/databases.yml	Mon Oct 05 16:05:28 2009 +0200
+++ b/web/thdProject/config/databases.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -2,6 +2,6 @@
   doctrine:
     class: sfDoctrineDatabase
     param:
-      dsn:      mysql:host=localhost;dbname=thd
-      username: thd
-      password: helsinki
+      dsn: 'mysql:host=localhost;dbname=thd'
+      username: root
+      password: null
--- a/web/thdProject/config/propel.ini	Mon Oct 05 16:05:28 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-propel.targetPackage       = lib.model
-propel.packageObjectModel  = true
-propel.project             = thd
-propel.database            = mysql
-propel.database.driver     = mysql
-propel.database.url        = mysql:dbname=thd;host=localhost
-propel.database.creole.url = ${propel.database.url}
-propel.database.user       = root
-propel.database.password   = 
-propel.database.encoding   = utf8
-
-; mysql options
-propel.mysql.tableType     = InnoDB
-
-propel.addVendorInfo       = true
-propel.addGenericAccessors = true
-propel.addGenericMutators  = true
-propel.addTimeStamp        = true
-propel.addValidators       = false
-
-propel.useDateTimeClass       = true
-propel.defaultTimeStampFormat = Y-m-d H:i:s
-propel.defaultTimeFormat      = H:i:s
-propel.defaultDateFormat      = Y-m-d
-
-propel.schema.validate        = false
-propel.samePhpName            = false
-propel.disableIdentifierQuoting     = false
-propel.emulateForeignKeyConstraints = true
-
-; directories
-propel.home                    = .
-propel.output.dir              = /Users/gautierthibault/Sites/thd
-propel.schema.dir              = ${propel.output.dir}/config
-propel.conf.dir                = ${propel.output.dir}/config
-propel.phpconf.dir             = ${propel.output.dir}/config
-propel.sql.dir                 = ${propel.output.dir}/data/sql
-propel.runtime.conf.file       = runtime-conf.xml
-propel.php.dir                 = ${propel.output.dir}
-propel.default.schema.basename = schema
-propel.datadump.mapper.from    = *schema.xml
-propel.datadump.mapper.to      = *data.xml
-
-; builder settings
-propel.builder.peer.class              = plugins.sfPropelPlugin.lib.builder.SfPeerBuilder
-propel.builder.object.class            = plugins.sfPropelPlugin.lib.builder.SfObjectBuilder
-propel.builder.objectstub.class        = plugins.sfPropelPlugin.lib.builder.SfExtensionObjectBuilder
-propel.builder.peerstub.class          = plugins.sfPropelPlugin.lib.builder.SfExtensionPeerBuilder
-propel.builder.objectmultiextend.class = plugins.sfPropelPlugin.lib.builder.SfMultiExtendObjectBuilder
-propel.builder.mapbuilder.class        = plugins.sfPropelPlugin.lib.builder.SfMapBuilderBuilder
-
-propel.builder.addIncludes  = false
-propel.builder.addComments  = true
-propel.builder.addBehaviors = true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/LICENSE	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,7 @@
+Copyright (c) 2006-2008 Jonathan H. Wage
+
+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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/config/autoload.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,6 @@
+autoload:
+  sfDoctrinePlugin_lib:
+    name:       sfDoctrinePlugin lib
+    path:       %SF_SYMFONY_LIB_DIR%/plugins/sfDoctrinePlugin/lib
+    recursive:  true
+    exclude:    [doctrine]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/config/config.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,31 @@
+<?php
+
+sfConfig::set('sf_orm', 'doctrine');
+if (!sfConfig::get('sf_admin_module_web_dir'))
+{
+  sfConfig::set('sf_admin_module_web_dir', '/sfDoctrinePlugin');
+}
+
+if (sfConfig::get('sf_web_debug'))
+{
+  require_once dirname(__FILE__).'/../lib/debug/sfWebDebugPanelDoctrine.class.php';
+
+  $this->dispatcher->connect('debug.web.load_panels', array('sfWebDebugPanelDoctrine', 'listenToAddPanelEvent'));
+}
+
+require_once sfConfig::get('sfDoctrinePlugin_doctrine_lib_path', dirname(__FILE__).'/../lib/vendor/doctrine/Doctrine.php');
+spl_autoload_register(array('Doctrine', 'autoload'));
+
+$manager = Doctrine_Manager::getInstance();
+$manager->setAttribute('export', 'all');
+$manager->setAttribute('validate', 'all');
+$manager->setAttribute('recursive_merge_fixtures', true);
+$manager->setAttribute('auto_accessor_override', true);
+$manager->setAttribute('autoload_table_classes', true);
+
+$configuration = sfProjectConfiguration::getActive();
+
+if (method_exists($configuration, 'configureDoctrine'))
+{
+  $configuration->configureDoctrine($manager);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/config/sfDoctrinePluginConfiguration.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfDoctrinePluginConfiguration Class
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineConnectionListener.class.php 11878 2008-09-30 20:14:40Z Jonathan.Wage $
+ */
+class sfDoctrinePluginConfiguration extends sfPluginConfiguration
+{
+  public function initialize()
+  {
+    require_once dirname(__FILE__) . '/config.php';
+
+    return true;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineForm/default/template/sfDoctrineFormBaseTemplate.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,14 @@
+[?php
+
+/**
+ * Project form base class.
+ *
+ * @package    form
+ * @version    SVN: $Id: sfDoctrineFormBaseTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+abstract class BaseFormDoctrine extends sfFormDoctrine
+{
+  public function setup()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineForm/default/template/sfDoctrineFormGeneratedTemplate.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,123 @@
+[?php
+
+/**
+ * <?php echo $this->modelName ?> form base class.
+ *
+ * @package    form
+ * @subpackage <?php echo $this->underscore($this->modelName) ?>
+
+ * @version    SVN: $Id: sfDoctrineFormGeneratedTemplate.php 8508 2008-04-17 17:39:15Z fabien $
+ */
+class Base<?php echo $this->modelName ?>Form extends BaseFormDoctrine
+{
+  public function setup()
+  {
+    $this->setWidgets(array(
+<?php foreach ($this->getColumns() as $column): ?>
+      '<?php echo $column->getFieldName() ?>'<?php echo str_repeat(' ', $this->getColumnNameMaxLength() - strlen($column->getFieldName())) ?> => new <?php echo $this->getWidgetClassForColumn($column) ?>(<?php echo $this->getWidgetOptionsForColumn($column) ?>),
+<?php endforeach; ?>
+<?php foreach ($this->getManyToManyRelations() as $relation): ?>
+      '<?php echo $this->underscore($relation['alias']) ?>_list'<?php echo str_repeat(' ', $this->getColumnNameMaxLength() - strlen($this->underscore($relation['alias']).'_list')) ?> => new sfWidgetFormDoctrineChoiceMany(array('model' => '<?php echo $relation['table']->getOption('name') ?>')),
+<?php endforeach; ?>
+    ));
+
+    $this->setValidators(array(
+<?php foreach ($this->getColumns() as $column): ?>
+      '<?php echo $column->getFieldName() ?>'<?php echo str_repeat(' ', $this->getColumnNameMaxLength() - strlen($column->getFieldName())) ?> => new <?php echo $this->getValidatorClassForColumn($column) ?>(<?php echo $this->getValidatorOptionsForColumn($column) ?>),
+<?php endforeach; ?>
+<?php foreach ($this->getManyToManyRelations() as $relation): ?>
+      '<?php echo $this->underscore($relation['alias']) ?>_list'<?php echo str_repeat(' ', $this->getColumnNameMaxLength() - strlen($this->underscore($relation['alias']).'_list')) ?> => new sfValidatorDoctrineChoiceMany(array('model' => '<?php echo $relation['table']->getOption('name') ?>', 'required' => false)),
+<?php endforeach; ?>
+    ));
+
+<?php if ($uniqueColumns = $this->getUniqueColumnNames()): ?>
+    $this->validatorSchema->setPostValidator(
+<?php if (count($uniqueColumns) > 1): ?>
+      new sfValidatorAnd(array(
+<?php foreach ($uniqueColumns as $uniqueColumn): ?>
+        new sfValidatorDoctrineUnique(array('model' => '<?php echo $this->table->getOption('name') ?>', 'column' => array('<?php echo implode("', '", $uniqueColumn) ?>'))),
+<?php endforeach; ?>
+      ))
+<?php else: ?>
+      new sfValidatorDoctrineUnique(array('model' => '<?php echo $this->table->getOption('name') ?>', 'column' => array('<?php echo implode("', '", $uniqueColumns[0]) ?>')))
+<?php endif; ?>
+    );
+
+<?php endif; ?>
+    $this->widgetSchema->setNameFormat('<?php echo $this->underscore($this->modelName) ?>[%s]');
+
+    $this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema);
+
+    parent::setup();
+  }
+
+  public function getModelName()
+  {
+    return '<?php echo $this->modelName ?>';
+  }
+
+<?php if ($this->getManyToManyRelations()): ?>
+  public function updateDefaultsFromObject()
+  {
+    parent::updateDefaultsFromObject();
+
+<?php foreach ($this->getManyToManyRelations() as $relation): ?>
+    if (isset($this->widgetSchema['<?php echo $this->underscore($relation['alias']) ?>_list']))
+    {
+      $this->setDefault('<?php echo $this->underscore($relation['alias']) ?>_list', $this->object-><?php echo $relation['alias']; ?>->getPrimaryKeys());
+    }
+
+<?php endforeach; ?>
+  }
+
+  protected function doSave($con = null)
+  {
+    parent::doSave($con);
+
+<?php foreach ($this->getManyToManyRelations() as $relation): ?>
+    $this->save<?php echo $relation['alias'] ?>List($con);
+<?php endforeach; ?>
+  }
+
+<?php foreach ($this->getManyToManyRelations() as $relation): ?>
+  public function save<?php echo $relation['alias'] ?>List($con = null)
+  {
+    if (!$this->isValid())
+    {
+      throw $this->getErrorSchema();
+    }
+
+    if (!isset($this->widgetSchema['<?php echo $this->underscore($relation['alias']) ?>_list']))
+    {
+      // somebody has unset this widget
+      return;
+    }
+
+    if (is_null($con))
+    {
+      $con = $this->getConnection();
+    }
+
+    $existing = $this->object-><?php echo $relation['alias']; ?>->getPrimaryKeys();
+    $values = $this->getValue('<?php echo $this->underscore($relation['alias']) ?>_list');
+    if (!is_array($values))
+    {
+      $values = array();
+    }
+
+    $unlink = array_diff($existing, $values);
+    if (count($unlink))
+    {
+      $this->object->unlink('<?php echo $relation['alias'] ?>', array_values($unlink));
+    }
+
+    $link = array_diff($values, $existing);
+    if (count($link))
+    {
+      $this->object->link('<?php echo $relation['alias'] ?>', array_values($link));
+    }
+  }
+
+<?php endforeach; ?>
+<?php endif; ?>
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineForm/default/template/sfDoctrineFormPluginTemplate.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,13 @@
+[?php
+
+/**
+ * Plugin<?php echo $this->table->getOption('name') ?> form.
+ *
+ * @package    form
+ * @subpackage <?php echo $this->table->getOption('name') ?>
+
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+abstract class Plugin<?php echo $this->table->getOption('name') ?>Form extends Base<?php echo $this->table->getOption('name') ?>Form
+{
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineForm/default/template/sfDoctrineFormTemplate.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,16 @@
+[?php
+
+/**
+ * <?php echo $this->table->getOption('name') ?> form.
+ *
+ * @package    form
+ * @subpackage <?php echo $this->table->getOption('name') ?>
+
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class <?php echo $this->table->getOption('name') ?>Form extends Base<?php echo $this->table->getOption('name') ?>Form
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineForm/default/template/sfDoctrinePluginFormTemplate.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,16 @@
+[?php
+
+/**
+ * <?php echo $this->table->getOption('name') ?> form.
+ *
+ * @package    form
+ * @subpackage <?php echo $this->table->getOption('name') ?>
+
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class <?php echo $this->table->getOption('name') ?>Form extends Plugin<?php echo $this->table->getOption('name') ?>Form
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineFormFilter/default/template/sfDoctrineFormFilterBaseTemplate.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+[?php
+
+/**
+ * Project filter form base class.
+ *
+ * @package    filters
+ *
+ * @version    SVN: $Id: sfDoctrineFormFilterBaseTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+abstract class BaseFormFilterDoctrine extends sfFormFilterDoctrine
+{
+  public function setup()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineFormFilter/default/template/sfDoctrineFormFilterGeneratedTemplate.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,78 @@
+[?php
+
+require_once(sfConfig::get('sf_lib_dir').'/filter/doctrine/BaseFormFilterDoctrine.class.php');
+
+/**
+ * <?php echo $this->table->getOption('name') ?> filter form base class.
+ *
+ * @package    filters
+ * @subpackage <?php echo $this->table->getOption('name') ?>
+ *
+ * @version    SVN: $Id: sfDoctrineFormFilterGeneratedTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class Base<?php echo $this->table->getOption('name') ?>FormFilter extends BaseFormFilterDoctrine
+{
+  public function setup()
+  {
+    $this->setWidgets(array(
+<?php foreach ($this->getColumns() as $column): ?>
+<?php if ($column->isPrimaryKey()) continue ?>
+      '<?php echo $column->getFieldName() ?>'<?php echo str_repeat(' ', $this->getColumnNameMaxLength() - strlen($column->getFieldName())) ?> => new <?php echo $this->getWidgetClassForColumn($column) ?>(<?php echo $this->getWidgetOptionsForColumn($column) ?>),
+<?php endforeach; ?>
+<?php foreach ($this->getManyToManyRelations() as $relation): ?>
+      '<?php echo $this->underscore($relation['alias']) ?>_list'<?php echo str_repeat(' ', $this->getColumnNameMaxLength() - strlen($this->underscore($relation['alias']).'_list')) ?> => new sfWidgetFormDoctrineChoiceMany(array('model' => '<?php echo $relation['table']->getOption('name') ?>')),
+<?php endforeach; ?>
+    ));
+
+    $this->setValidators(array(
+<?php foreach ($this->getColumns() as $column): ?>
+<?php if ($column->isPrimaryKey()) continue ?>
+      '<?php echo $column->getFieldName() ?>'<?php echo str_repeat(' ', $this->getColumnNameMaxLength() - strlen($column->getFieldName())) ?> => <?php echo $this->getValidatorForColumn($column) ?>,
+<?php endforeach; ?>
+<?php foreach ($this->getManyToManyRelations() as $relation): ?>
+      '<?php echo $this->underscore($relation['alias']) ?>_list'<?php echo str_repeat(' ', $this->getColumnNameMaxLength() - strlen($this->underscore($relation['alias']).'_list')) ?> => new sfValidatorDoctrineChoiceMany(array('model' => '<?php echo $relation['table']->getOption('name') ?>', 'required' => false)),
+<?php endforeach; ?>
+    ));
+
+    $this->widgetSchema->setNameFormat('<?php echo $this->underscore($this->modelName) ?>_filters[%s]');
+
+    $this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema);
+
+    parent::setup();
+  }
+
+<?php foreach ($this->getManyToManyRelations() as $relation): ?>
+  public function add<?php echo sfInflector::camelize($relation['alias']) ?>ListColumnQuery(Doctrine_Query $query, $field, $values)
+  {
+    if (!is_array($values))
+    {
+      $values = array($values);
+    }
+
+    if (!count($values))
+    {
+      return;
+    }
+
+    $query->leftJoin('r.<?php echo $relation['refTable']->getOption('name') ?> <?php echo $relation['refTable']->getOption('name') ?>')
+          ->andWhereIn('<?php echo $relation['refTable']->getOption('name') ?>.<?php echo $relation->getForeignFieldName() ?>', $values);
+  }
+
+<?php endforeach; ?>
+  public function getModelName()
+  {
+    return '<?php echo $this->modelName ?>';
+  }
+
+  public function getFields()
+  {
+    return array(
+<?php foreach ($this->getColumns() as $column): ?>
+      '<?php echo $column->getFieldName() ?>'<?php echo str_repeat(' ', $this->getColumnNameMaxLength() - strlen($column->getFieldName())) ?> => '<?php echo $this->getType($column) ?>',
+<?php endforeach; ?>
+<?php foreach ($this->getManyToManyRelations() as $relation): ?>
+      '<?php echo $this->underscore($relation['alias']) ?>_list'<?php echo str_repeat(' ', $this->getColumnNameMaxLength() - strlen($this->underscore($relation['alias']).'_list')) ?> => 'ManyKey',
+<?php endforeach; ?>
+    );
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineFormFilter/default/template/sfDoctrineFormFilterPluginTemplate.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,13 @@
+[?php
+
+/**
+ * Plugin<?php echo $this->table->getOption('name') ?> form.
+ *
+ * @package    filters
+ * @subpackage <?php echo $this->table->getOption('name') ?>
+ *
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+abstract class Plugin<?php echo $this->table->getOption('name') ?>FormFilter extends Base<?php echo $this->table->getOption('name') ?>FormFilter
+{
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineFormFilter/default/template/sfDoctrineFormFilterTemplate.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,16 @@
+[?php
+
+/**
+ * <?php echo $this->table->getOption('name') ?> filter form.
+ *
+ * @package    filters
+ * @subpackage <?php echo $this->table->getOption('name') ?>
+ *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class <?php echo $this->table->getOption('name') ?>FormFilter extends Base<?php echo $this->table->getOption('name') ?>FormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineFormFilter/default/template/sfDoctrinePluginFormFilterTemplate.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,16 @@
+[?php
+
+/**
+ * <?php echo $this->table->getOption('name') ?> filter form.
+ *
+ * @package    filters
+ * @subpackage <?php echo $this->table->getOption('name') ?>
+ *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class <?php echo $this->table->getOption('name') ?>FormFilter extends Plugin<?php echo $this->table->getOption('name') ?>FormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/actionsConfiguration.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,51 @@
+  public function getCredentials($action)
+  {
+    if (0 === strpos($action, '_'))
+    {
+      $action = substr($action, 1);
+    }
+
+    return isset($this->configuration['credentials'][$action]) ? $this->configuration['credentials'][$action] : array();
+  }
+
+  public function getActionsDefault()
+  {
+    return <?php echo $this->asPhp(isset($this->config['actions']) ? $this->config['actions'] : array()) ?>;
+<?php unset($this->config['actions']) ?>
+  }
+
+  public function getFormActions()
+  {
+    return <?php echo $this->asPhp(isset($this->config['form']['actions']) ? $this->config['form']['actions'] : array('_delete' => null, '_list' => null, '_save' => null, '_save_and_add' => null)) ?>;
+<?php unset($this->config['form']['actions']) ?>
+  }
+
+  public function getNewActions()
+  {
+    return <?php echo $this->asPhp(isset($this->config['new']['actions']) ? $this->config['new']['actions'] : array()) ?>;
+<?php unset($this->config['new']['actions']) ?>
+  }
+
+  public function getEditActions()
+  {
+    return <?php echo $this->asPhp(isset($this->config['edit']['actions']) ? $this->config['edit']['actions'] : array()) ?>;
+<?php unset($this->config['edit']['actions']) ?>
+  }
+
+  public function getListObjectActions()
+  {
+    return <?php echo $this->asPhp(isset($this->config['list']['object_actions']) ? $this->config['list']['object_actions'] : array('_edit' => null, '_delete' => null)) ?>;
+<?php unset($this->config['list']['object_actions']) ?>
+  }
+
+  public function getListActions()
+  {
+    return <?php echo $this->asPhp(isset($this->config['list']['actions']) ? $this->config['list']['actions'] : array('_new' => null)) ?>;
+<?php unset($this->config['list']['actions']) ?>
+  }
+
+  public function getListBatchActions()
+  {
+    return <?php echo $this->asPhp(isset($this->config['list']['batch_actions']) ? $this->config['list']['batch_actions'] : array('_delete' => null)) ?>;
+<?php unset($this->config['list']['batch_actions']) ?>
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/batchAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,66 @@
+  public function executeBatch(sfWebRequest $request)
+  {
+    $request->checkCSRFProtection();
+
+    if (!$ids = $request->getParameter('ids'))
+    {
+      $this->getUser()->setFlash('error', 'You must at least select one item.');
+
+      $this->redirect('@<?php echo $this->getUrlForAction('list') ?>');
+    }
+
+    if (!$action = $request->getParameter('batch_action'))
+    {
+      $this->getUser()->setFlash('error', 'You must select an action to execute on the selected items.');
+
+      $this->redirect('@<?php echo $this->getUrlForAction('list') ?>');
+    }
+
+    if (!method_exists($this, $method = 'execute'.ucfirst($action)))
+    {
+      throw new InvalidArgumentException(sprintf('You must create a "%s" method for action "%s"', $method, $action));
+    }
+
+    if (!$this->getUser()->hasCredential($this->configuration->getCredentials($action)))
+    {
+      $this->forward(sfConfig::get('sf_secure_module'), sfConfig::get('sf_secure_action'));
+    }
+
+    $validator = new sfValidatorDoctrineChoiceMany(array('model' => '<?php echo $this->getModelClass() ?>'));
+    try
+    {
+      // validate ids
+      $ids = $validator->clean($ids);
+
+      // execute batch
+      $this->$method($request);
+    }
+    catch (sfValidatorError $e)
+    {
+      $this->getUser()->setFlash('error', 'A problem occurs when deleting the selected items as some items do not exist anymore.');
+    }
+
+    $this->redirect('@<?php echo $this->getUrlForAction('list') ?>');
+  }
+
+  protected function executeBatchDelete(sfWebRequest $request)
+  {
+    $ids = $request->getParameter('ids');
+
+    $count = Doctrine_Query::create()
+      ->delete()
+      ->from('<?php echo $this->getModelClass() ?>')
+      ->whereIn('<?php echo $this->getPrimaryKeys(true) ?>', $ids)
+      ->execute();
+
+    if ($count >= count($ids))
+    {
+      $this->getUser()->setFlash('notice', 'The selected items have been deleted successfully.');
+    }
+    else
+    {
+      $this->getUser()->setFlash('error', 'A problem occurs when deleting the selected items.');
+    }
+
+    $this->redirect('@<?php echo $this->getUrlForAction('list') ?>');
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/configuration.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,85 @@
+[?php
+
+/**
+ * <?php echo $this->getModuleName() ?> module configuration.
+ *
+ * @package    ##PROJECT_NAME##
+ * @subpackage <?php echo $this->getModuleName()."\n" ?>
+ * @author     ##AUTHOR_NAME##
+ * @version    SVN: $Id: configuration.php 12474 2008-10-31 10:41:27Z fabien $
+ */
+class Base<?php echo ucfirst($this->getModuleName()) ?>GeneratorConfiguration extends sfModelGeneratorConfiguration
+{
+<?php include dirname(__FILE__).'/actionsConfiguration.php' ?>
+
+<?php include dirname(__FILE__).'/fieldsConfiguration.php' ?>
+
+  /**
+   * Gets a new form object.
+   *
+   * @param  mixed $object
+   *
+   * @return sfForm
+   */
+  public function getForm($object = null)
+  {
+    $class = $this->getFormClass();
+
+    return new $class($object, $this->getFormOptions());
+  }
+
+  /**
+   * Gets the form class name.
+   *
+   * @return string The form class name
+   */
+  public function getFormClass()
+  {
+    return '<?php echo isset($this->config['form']['class']) ? $this->config['form']['class'] : $this->getModelClass().'Form' ?>';
+<?php unset($this->config['form']['class']) ?>
+  }
+
+  public function getFormOptions()
+  {
+    return array();
+  }
+
+  public function hasFilterForm()
+  {
+    return <?php echo !isset($this->config['filter']['class']) || false !== $this->config['filter']['class'] ? 'true' : 'false' ?>;
+  }
+
+  /**
+   * Gets the filter form class name
+   *
+   * @return string The filter form class name associated with this generator
+   */
+  public function getFilterFormClass()
+  {
+    return '<?php echo isset($this->config['filter']['class']) && !in_array($this->config['filter']['class'], array(null, true, false), true) ? $this->config['filter']['class'] : $this->getModelClass().'FormFilter' ?>';
+<?php unset($this->config['filter']['class']) ?>
+  }
+
+<?php include dirname(__FILE__).'/filtersConfiguration.php' ?>
+
+<?php include dirname(__FILE__).'/paginationConfiguration.php' ?>
+
+<?php include dirname(__FILE__).'/sortingConfiguration.php' ?>
+
+  public function getTableMethod()
+  {
+    return '<?php echo isset($this->config['list']['table_method']) ? $this->config['list']['table_method'] : null ?>';
+<?php unset($this->config['list']['table_method']) ?>
+  }
+
+  public function getTableCountMethod()
+  {
+    return '<?php echo isset($this->config['list']['table_count_method']) ? $this->config['list']['table_count_method'] : null ?>';
+<?php unset($this->config['list']['table_count_method']) ?>
+  }
+
+  public function getConnection()
+  {
+    return null;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/createAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+  public function executeCreate(sfWebRequest $request)
+  {
+    $this->form = $this->configuration->getForm();
+    $this-><?php echo $this->getSingularName() ?> = $this->form->getObject();
+
+    $this->processForm($request, $this->form);
+
+    $this->setTemplate('new');
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/deleteAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,12 @@
+  public function executeDelete(sfWebRequest $request)
+  {
+    $request->checkCSRFProtection();
+
+    $this->dispatcher->notify(new sfEvent($this, 'admin.delete_object', array('object' => $this->getRoute()->getObject())));
+
+    $this->getRoute()->getObject()->delete();
+
+    $this->getUser()->setFlash('notice', 'The item was deleted successfully.');
+
+    $this->redirect('@<?php echo $this->getUrlForAction('list') ?>');
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/editAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,5 @@
+  public function executeEdit(sfWebRequest $request)
+  {
+    $this-><?php echo $this->getSingularName() ?> = $this->getRoute()->getObject();
+    $this->form = $this->configuration->getForm($this-><?php echo $this->getSingularName() ?>);
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/fieldsConfiguration.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,86 @@
+  public function getListParams()
+  {
+    return <?php echo $this->asPhp(isset($this->config['list']['params']) ? $this->config['list']['params'] : '%%'.implode('%% - %%', isset($this->config['list']['display']) ? $this->config['list']['display'] : $this->getAllFieldNames(false)).'%%') ?>;
+<?php unset($this->config['list']['params']) ?>
+  }
+
+  public function getListLayout()
+  {
+    return '<?php echo isset($this->config['list']['layout']) ? $this->config['list']['layout'] : 'tabular' ?>';
+<?php unset($this->config['list']['layout']) ?>
+  }
+
+  public function getListTitle()
+  {
+    return '<?php echo $this->escapeString(isset($this->config['list']['title']) ? $this->config['list']['title'] : sfInflector::humanize($this->getModuleName()).' List') ?>';
+<?php unset($this->config['list']['title']) ?>
+  }
+
+  public function getEditTitle()
+  {
+    return '<?php echo $this->escapeString(isset($this->config['edit']['title']) ? $this->config['edit']['title'] : 'Edit '.sfInflector::humanize($this->getModuleName())) ?>';
+<?php unset($this->config['edit']['title']) ?>
+  }
+
+  public function getNewTitle()
+  {
+    return '<?php echo $this->escapeString(isset($this->config['new']['title']) ? $this->config['new']['title'] : 'New '.sfInflector::humanize($this->getModuleName())) ?>';
+<?php unset($this->config['new']['title']) ?>
+  }
+
+  public function getFilterDisplay()
+  {
+    return <?php echo $this->asPhp(isset($this->config['filter']['display']) ? $this->config['filter']['display'] : array()) ?>;
+<?php unset($this->config['filter']['display']) ?>
+  }
+
+  public function getFormDisplay()
+  {
+    return <?php echo $this->asPhp(isset($this->config['form']['display']) ? $this->config['form']['display'] : array()) ?>;
+<?php unset($this->config['form']['display']) ?>
+  }
+
+  public function getEditDisplay()
+  {
+    return <?php echo $this->asPhp(isset($this->config['edit']['display']) ? $this->config['edit']['display'] : array()) ?>;
+<?php unset($this->config['edit']['display']) ?>
+  }
+
+  public function getNewDisplay()
+  {
+    return <?php echo $this->asPhp(isset($this->config['new']['display']) ? $this->config['new']['display'] : array()) ?>;
+<?php unset($this->config['new']['display']) ?>
+  }
+
+  public function getListDisplay()
+  {
+<?php if (isset($this->config['list']['display'])): ?>
+    return <?php echo $this->asPhp($this->config['list']['display']) ?>;
+<?php elseif (isset($this->config['list']['hide'])): ?>
+    return <?php echo $this->asPhp(array_diff($this->getAllFieldNames(false), $this->config['list']['hide'])) ?>;
+<?php else: ?>
+    return <?php echo $this->asPhp($this->getAllFieldNames(false)) ?>;
+<?php endif; ?>
+<?php unset($this->config['list']['display'], $this->config['list']['hide']) ?>
+  }
+
+  public function getFieldsDefault()
+  {
+    return array(
+<?php foreach ($this->getDefaultFieldsConfiguration() as $name => $params): ?>
+      '<?php echo $name ?>' => <?php echo $this->asPhp($params) ?>,
+<?php endforeach; ?>
+    );
+  }
+
+<?php foreach (array('list', 'filter', 'form', 'edit', 'new') as $context): ?>
+  public function getFields<?php echo ucfirst($context) ?>()
+  {
+    return array(
+<?php foreach ($this->getFieldsConfiguration($context) as $name => $params): ?>
+      '<?php echo $name ?>' => <?php echo $this->asPhp($params) ?>,
+<?php endforeach; ?>
+    );
+  }
+
+<?php endforeach; ?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/filterAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,26 @@
+  public function executeFilter(sfWebRequest $request)
+  {
+    $this->setPage(1);
+
+    if ($request->hasParameter('_reset'))
+    {
+      $this->setFilters($this->configuration->getFilterDefaults());
+
+      $this->redirect('@<?php echo $this->getUrlForAction('list') ?>');
+    }
+
+    $this->filters = $this->configuration->getFilterForm($this->getFilters());
+
+    $this->filters->bind($request->getParameter($this->filters->getName()));
+    if ($this->filters->isValid())
+    {
+      $this->setFilters($this->filters->getValues());
+
+      $this->redirect('@<?php echo $this->getUrlForAction('list') ?>');
+    }
+
+    $this->pager = $this->getPager();
+    $this->sort = $this->getSort();
+
+    $this->setTemplate('index');
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/filtersAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+  protected function getFilters()
+  {
+    return $this->getUser()->getAttribute('<?php echo $this->getModuleName() ?>.filters', $this->configuration->getFilterDefaults(), 'admin_module');
+  }
+
+  protected function setFilters(array $filters)
+  {
+    return $this->getUser()->setAttribute('<?php echo $this->getModuleName() ?>.filters', $filters, 'admin_module');
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/filtersConfiguration.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,16 @@
+  public function getFilterForm($filters)
+  {
+    $class = $this->getFilterFormClass();
+
+    return new $class($filters, $this->getFilterFormOptions());
+  }
+
+  public function getFilterFormOptions()
+  {
+    return array();
+  }
+
+  public function getFilterDefaults()
+  {
+    return array();
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/indexAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,17 @@
+  public function executeIndex(sfWebRequest $request)
+  {
+    // sorting
+    if ($request->getParameter('sort'))
+    {
+      $this->setSort(array($request->getParameter('sort'), $request->getParameter('sort_type')));
+    }
+
+    // pager
+    if ($request->getParameter('page'))
+    {
+      $this->setPage($request->getParameter('page'));
+    }
+
+    $this->pager = $this->getPager();
+    $this->sort = $this->getSort();
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/newAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,5 @@
+  public function executeNew(sfWebRequest $request)
+  {
+    $this->form = $this->configuration->getForm();
+    $this-><?php echo $this->getSingularName() ?> = $this->form->getObject();
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/paginationAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,49 @@
+  protected function getPager()
+  {
+    $pager = $this->configuration->getPager('<?php echo $this->getModelClass() ?>');
+    $pager->setQuery($this->buildQuery());
+    $pager->setPage($this->getPage());
+    $pager->init();
+
+    return $pager;
+  }
+
+  protected function setPage($page)
+  {
+    $this->getUser()->setAttribute('<?php echo $this->getModuleName() ?>.page', $page, 'admin_module');
+  }
+
+  protected function getPage()
+  {
+    return $this->getUser()->getAttribute('<?php echo $this->getModuleName() ?>.page', 1, 'admin_module');
+  }
+
+  protected function buildQuery()
+  {
+    $tableMethod = $this->configuration->getTableMethod();
+<?php if ($this->configuration->hasFilterForm()): ?>
+    if (is_null($this->filters))
+    {
+      $this->filters = $this->configuration->getFilterForm($this->getFilters());
+    }
+
+    $this->filters->setTableMethod($tableMethod);
+
+    $query = $this->filters->buildQuery($this->getFilters());
+<?php else: ?>
+    $query = Doctrine::getTable('<?php echo $this->getModelClass() ?>')
+      ->createQuery('a');
+
+    if ($tableMethod)
+    {
+      $query = Doctrine::getTable('<?php echo $this->getModelClass() ?>')->$tableMethod($query);
+    }
+<?php endif; ?>
+
+    $this->addSortQuery($query);
+
+    $event = $this->dispatcher->filter(new sfEvent($this, 'admin.build_query'), $query);
+    $query = $event->getReturnValue();
+
+    return $query;
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/paginationConfiguration.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,18 @@
+  public function getPager($model)
+  {
+    $class = $this->getPagerClass();
+
+    return new $class($model, $this->getPagerMaxPerPage());
+  }
+
+  public function getPagerClass()
+  {
+    return '<?php echo isset($this->config['list']['pager_class']) ? $this->config['list']['pager_class'] : 'sfDoctrinePager' ?>';
+<?php unset($this->config['list']['pager_class']) ?>
+  }
+
+  public function getPagerMaxPerPage()
+  {
+    return <?php echo isset($this->config['list']['max_per_page']) ? (integer) $this->config['list']['max_per_page'] : 20 ?>;
+<?php unset($this->config['list']['max_per_page']) ?>
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/processFormAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,29 @@
+  protected function processForm(sfWebRequest $request, sfForm $form)
+  {
+    $form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
+    if ($form->isValid())
+    {
+      $notice = $form->getObject()->isNew() ? 'The item was created successfully.' : 'The item was updated successfully.';
+
+      $<?php echo $this->getSingularName() ?> = $form->save();
+
+      $this->dispatcher->notify(new sfEvent($this, 'admin.save_object', array('object' => $<?php echo $this->getSingularName() ?>)));
+
+      if ($request->hasParameter('_save_and_add'))
+      {
+        $this->getUser()->setFlash('notice', $notice.' You can add another one below.');
+
+        $this->redirect('@<?php echo $this->getUrlForAction('new') ?>');
+      }
+      else
+      {
+        $this->getUser()->setFlash('notice', $notice);
+
+        $this->redirect(array('sf_route' => '<?php echo $this->getUrlForAction('edit') ?>', 'sf_subject' => $<?php echo $this->getSingularName() ?>));
+      }
+    }
+    else
+    {
+      $this->getUser()->setFlash('error', 'The item has not been saved due to some errors.', false);
+    }
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/sortingAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,31 @@
+  protected function addSortQuery($query)
+  {
+    if (array(null, null) == ($sort = $this->getSort()))
+    {
+      return;
+    }
+
+    $query->addOrderBy($sort[0] . ' ' . $sort[1]);
+  }
+
+  protected function getSort()
+  {
+    if (!is_null($sort = $this->getUser()->getAttribute('<?php echo $this->getModuleName() ?>.sort', null, 'admin_module')))
+    {
+      return $sort;
+    }
+
+    $this->setSort($this->configuration->getDefaultSort());
+
+    return $this->getUser()->getAttribute('<?php echo $this->getModuleName() ?>.sort', null, 'admin_module');
+  }
+
+  protected function setSort(array $sort)
+  {
+    if (!is_null($sort[0]) && is_null($sort[1]))
+    {
+      $sort[1] = 'asc';
+    }
+
+    $this->getUser()->setAttribute('<?php echo $this->getModuleName() ?>.sort', $sort, 'admin_module');
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/sortingConfiguration.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,10 @@
+  public function getDefaultSort()
+  {
+<?php if ($sort = (isset($this->config['list']['sort']) ? $this->config['list']['sort'] : false)): ?>
+<?php if (!is_array($sort)) $sort = array($sort, 'asc'); ?>
+    return array('<?php echo $sort[0] ?>', '<?php echo isset($sort[1]) ? $sort[1] : 'asc' ?>');
+<?php else: ?>
+    return array(null, null);
+<?php endif; ?>
+<?php unset($this->config['list']['sort']) ?>
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/parts/updateAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+  public function executeUpdate(sfWebRequest $request)
+  {
+    $this-><?php echo $this->getSingularName() ?> = $this->getRoute()->getObject();
+    $this->form = $this->configuration->getForm($this-><?php echo $this->getSingularName() ?>);
+
+    $this->processForm($request, $this->form);
+
+    $this->setTemplate('edit');
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/skeleton/actions/actions.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,16 @@
+<?php
+
+require_once dirname(__FILE__).'/../lib/##MODULE_NAME##GeneratorConfiguration.class.php';
+require_once dirname(__FILE__).'/../lib/##MODULE_NAME##GeneratorHelper.class.php';
+
+/**
+ * ##MODULE_NAME## actions.
+ *
+ * @package    ##PROJECT_NAME##
+ * @subpackage ##MODULE_NAME##
+ * @author     ##AUTHOR_NAME##
+ * @version    SVN: $Id: actions.class.php 12474 2008-10-31 10:41:27Z fabien $
+ */
+class ##MODULE_NAME##Actions extends auto##UC_MODULE_NAME##Actions
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/skeleton/config/generator.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,13 @@
+generator:
+  class: sfDoctrineGenerator
+  param:
+##CONFIG##
+
+    config:
+      actions: ~
+      fields:  ~
+      list:    ~
+      filter:  ~
+      form:    ~
+      edit:    ~
+      new:     ~
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/skeleton/lib/configuration.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * ##MODULE_NAME## module configuration.
+ *
+ * @package    ##PROJECT_NAME##
+ * @subpackage ##MODULE_NAME##
+ * @author     ##AUTHOR_NAME##
+ * @version    SVN: $Id: configuration.php 12474 2008-10-31 10:41:27Z fabien $
+ */
+class ##MODULE_NAME##GeneratorConfiguration extends Base##UC_MODULE_NAME##GeneratorConfiguration
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/skeleton/lib/helper.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * ##MODULE_NAME## module helper.
+ *
+ * @package    ##PROJECT_NAME##
+ * @subpackage ##MODULE_NAME##
+ * @author     ##AUTHOR_NAME##
+ * @version    SVN: $Id: helper.php 12474 2008-10-31 10:41:27Z fabien $
+ */
+class ##MODULE_NAME##GeneratorHelper extends Base##UC_MODULE_NAME##GeneratorHelper
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/actions/actions.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,59 @@
+[?php
+
+require_once(dirname(__FILE__).'/../lib/Base<?php echo ucfirst($this->moduleName) ?>GeneratorConfiguration.class.php');
+require_once(dirname(__FILE__).'/../lib/Base<?php echo ucfirst($this->moduleName) ?>GeneratorHelper.class.php');
+
+/**
+ * <?php echo $this->getModuleName() ?> actions.
+ *
+ * @package    ##PROJECT_NAME##
+ * @subpackage <?php echo $this->getModuleName()."\n" ?>
+ * @author     ##AUTHOR_NAME##
+ * @version    SVN: $Id: actions.class.php 12493 2008-10-31 14:43:26Z fabien $
+ */
+class <?php echo $this->getGeneratedModuleName() ?>Actions extends sfActions
+{
+  public function preExecute()
+  {
+    $this->configuration = new <?php echo $this->getModuleName() ?>GeneratorConfiguration();
+
+    if (!$this->getUser()->hasCredential($this->configuration->getCredentials($this->getActionName())))
+    {
+      $this->forward(sfConfig::get('sf_secure_module'), sfConfig::get('sf_secure_action'));
+    }
+
+    $this->dispatcher->notify(new sfEvent($this, 'admin.pre_execute', array('configuration' => $this->configuration)));
+
+    $this->helper = new <?php echo $this->getModuleName() ?>GeneratorHelper();
+  }
+
+<?php include dirname(__FILE__).'/../../parts/indexAction.php' ?>
+
+<?php if ($this->configuration->hasFilterForm()): ?>
+<?php include dirname(__FILE__).'/../../parts/filterAction.php' ?>
+<?php endif; ?>
+
+<?php include dirname(__FILE__).'/../../parts/newAction.php' ?>
+
+<?php include dirname(__FILE__).'/../../parts/createAction.php' ?>
+
+<?php include dirname(__FILE__).'/../../parts/editAction.php' ?>
+
+<?php include dirname(__FILE__).'/../../parts/updateAction.php' ?>
+
+<?php include dirname(__FILE__).'/../../parts/deleteAction.php' ?>
+
+<?php if ($this->configuration->getValue('list.batch_actions')): ?>
+<?php include dirname(__FILE__).'/../../parts/batchAction.php' ?>
+<?php endif; ?>
+
+<?php include dirname(__FILE__).'/../../parts/processFormAction.php' ?>
+
+<?php if ($this->configuration->hasFilterForm()): ?>
+<?php include dirname(__FILE__).'/../../parts/filtersAction.php' ?>
+<?php endif; ?>
+
+<?php include dirname(__FILE__).'/../../parts/paginationAction.php' ?>
+
+<?php include dirname(__FILE__).'/../../parts/sortingAction.php' ?>
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/lib/helper.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,57 @@
+[?php
+
+/**
+ * <?php echo $this->getModuleName() ?> module configuration.
+ *
+ * @package    ##PROJECT_NAME##
+ * @subpackage <?php echo $this->getModuleName()."\n" ?>
+ * @author     ##AUTHOR_NAME##
+ * @version    SVN: $Id: helper.php 12482 2008-10-31 11:13:22Z fabien $
+ */
+class Base<?php echo ucfirst($this->getModuleName()) ?>GeneratorHelper extends sfModelGeneratorHelper
+{
+  public function linkToNew($params)
+  {
+    return '<li class="sf_admin_action_new">'.link_to(__($params['label'], array(), 'sf_admin'), '@'.$this->getUrlForAction('new')).'</li>';
+  }
+
+  public function linkToEdit($object, $params)
+  {
+    return '<li class="sf_admin_action_edit">'.link_to(__($params['label'], array(), 'sf_admin'), $this->getUrlForAction('edit'), $object).'</li>';
+  }
+
+  public function linkToDelete($object, $params)
+  {
+    if ($object->isNew())
+    {
+      return '';
+    }
+
+    return '<li class="sf_admin_action_delete">'.link_to(__($params['label'], array(), 'sf_admin'), $this->getUrlForAction('delete'), $object, array('method' => 'delete', 'confirm' => !empty($params['confirm']) ? __($params['confirm'], array(), 'sf_admin') : $params['confirm'])).'</li>';
+  }
+
+  public function linkToList($params)
+  {
+    return '<li class="sf_admin_action_list">'.link_to(__($params['label'], array(), 'sf_admin'), '@'.$this->getUrlForAction('list')).'</li>';
+  }
+
+  public function linkToSave($object, $params)
+  {
+    return '<li class="sf_admin_action_save"><input type="submit" value="'.__($params['label'], array(), 'sf_admin').'" /></li>';
+  }
+
+  public function linkToSaveAndAdd($object, $params)
+  {
+    if (!$object->isNew())
+    {
+      return '';
+    }
+
+    return '<li class="sf_admin_action_save_and_add"><input type="submit" value="'.__($params['label'], array(), 'sf_admin').'" name="_save_and_add" /></li>';
+  }
+
+  public function getUrlForAction($action)
+  {
+    return 'list' == $action ? '<?php echo $this->params['route_prefix'] ?>' : '<?php echo $this->params['route_prefix'] ?>_'.$action;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_assets.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,6 @@
+<?php if (isset($this->params['css'])): ?> 
+[?php use_stylesheet('<?php echo $this->params['css'] ?>', 'first') ?] 
+<?php else: ?> 
+[?php use_stylesheet('<?php echo sfConfig::get('sf_admin_module_web_dir').'/css/global.css' ?>', 'first') ?] 
+[?php use_stylesheet('<?php echo sfConfig::get('sf_admin_module_web_dir').'/css/default.css' ?>', 'first') ?] 
+<?php endif; ?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_filters.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,36 @@
+[?php include_stylesheets_for_form($form) ?]
+[?php include_javascripts_for_form($form) ?]
+
+<div class="sf_admin_filter">
+  [?php if ($form->hasGlobalErrors()): ?]
+    [?php echo $form->renderGlobalErrors() ?]
+  [?php endif; ?]
+
+  <form action="[?php echo url_for('<?php echo $this->getUrlForAction('collection') ?>', array('action' => 'filter')) ?]" method="post">
+    <table cellspacing="0">
+      <tfoot>
+        <tr>
+          <td colspan="2">
+            [?php echo $form->renderHiddenFields() ?]
+            [?php echo link_to(__('Reset', array(), 'sf_admin'), '<?php echo $this->getUrlForAction('collection') ?>', array('action' => 'filter'), array('query_string' => '_reset', 'method' => 'post')) ?]
+            <input type="submit" value="[?php echo __('Filter', array(), 'sf_admin') ?]" />
+          </td>
+        </tr>
+      </tfoot>
+      <tbody>
+        [?php foreach ($configuration->getFormFilterFields($form) as $name => $field): ?]
+        [?php if ((isset($form[$name]) && $form[$name]->isHidden()) || (!isset($form[$name]) && $field->isReal())) continue ?]
+          [?php include_partial('<?php echo $this->getModuleName() ?>/filters_field', array(
+            'name'       => $name,
+            'attributes' => $field->getConfig('attributes', array()),
+            'label'      => $field->getConfig('label'),
+            'help'       => $field->getConfig('help'),
+            'form'       => $form,
+            'field'      => $field,
+            'class'      => 'sf_admin_form_row sf_admin_'.strtolower($field->getType()).' sf_admin_filter_field_'.$name,
+          )) ?]
+        [?php endforeach; ?]
+      </tbody>
+    </table>
+  </form>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_filters_field.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,20 @@
+[?php if ($field->isPartial()): ?]
+  [?php include_partial('<?php echo $this->getModuleName() ?>/'.$name, array('type' => 'filter', 'form' => $form, 'attributes' => $attributes instanceof sfOutputEscaper ? $attributes->getRawValue() : $attributes)) ?]
+[?php elseif ($field->isComponent()): ?]
+  [?php include_component('<?php echo $this->getModuleName() ?>', $name, array('type' => 'filter', 'form' => $form, 'attributes' => $attributes instanceof sfOutputEscaper ? $attributes->getRawValue() : $attributes)) ?]
+[?php else: ?]
+  <tr class="[?php echo $class ?]">
+    <td>
+      [?php echo $form[$name]->renderLabel($label) ?]
+    </td>
+    <td>
+      [?php echo $form[$name]->renderError() ?]
+
+      [?php echo $form[$name]->render($attributes instanceof sfOutputEscaper ? $attributes->getRawValue() : $attributes) ?]
+
+      [?php if ($help || $help = $form[$name]->renderHelp()): ?]
+        <div class="help">[?php echo __($help, array(), '<?php echo $this->getI18nCatalogue() ?>') ?]</div>
+      [?php endif; ?]
+    </td>
+  </tr>
+[?php endif; ?]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_flashes.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,7 @@
+[?php if ($sf_user->hasFlash('notice')): ?]
+  <div class="notice">[?php echo __($sf_user->getFlash('notice'), array(), 'sf_admin') ?]</div>
+[?php endif; ?]
+
+[?php if ($sf_user->hasFlash('error')): ?]
+  <div class="error">[?php echo __($sf_user->getFlash('error'), array(), 'sf_admin') ?]</div>
+[?php endif; ?]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_form.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,18 @@
+[?php include_stylesheets_for_form($form) ?]
+[?php include_javascripts_for_form($form) ?]
+
+<div class="sf_admin_form">
+  [?php echo form_tag_for($form, '@<?php echo $this->params['route_prefix'] ?>') ?]
+    [?php echo $form->renderHiddenFields() ?]
+
+    [?php if ($form->hasGlobalErrors()): ?]
+      [?php echo $form->renderGlobalErrors() ?]
+    [?php endif; ?]
+
+    [?php foreach ($configuration->getFormFields($form, $form->isNew() ? 'new' : 'edit') as $fieldset => $fields): ?]
+      [?php include_partial('<?php echo $this->getModuleName() ?>/form_fieldset', array('<?php echo $this->getSingularName() ?>' => $<?php echo $this->getSingularName() ?>, 'form' => $form, 'fields' => $fields, 'fieldset' => $fieldset)) ?]
+    [?php endforeach; ?]
+
+    [?php include_partial('<?php echo $this->getModuleName() ?>/form_actions', array('<?php echo $this->getSingularName() ?>' => $<?php echo $this->getSingularName() ?>, 'form' => $form, 'configuration' => $configuration, 'helper' => $helper)) ?]
+  </form>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_form_actions.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,35 @@
+<ul class="sf_admin_actions">
+<?php foreach (array('new', 'edit') as $action): ?>
+<?php if ('new' == $action): ?>
+[?php if ($form->isNew()): ?]
+<?php else: ?>
+[?php else: ?]
+<?php endif; ?>
+<?php foreach ($this->configuration->getValue($action.'.actions') as $name => $params): ?>
+<?php if ('_delete' == $name): ?>
+  <?php echo $this->addCredentialCondition('[?php echo $helper->linkToDelete($form->getObject(), '.$this->asPhp($params).') ?]', $params) ?>
+
+<?php elseif ('_list' == $name): ?>
+  <?php echo $this->addCredentialCondition('[?php echo $helper->linkToList('.$this->asPhp($params).') ?]', $params) ?>
+
+<?php elseif ('_save' == $name): ?>
+  <?php echo $this->addCredentialCondition('[?php echo $helper->linkToSave($form->getObject(), '.$this->asPhp($params).') ?]', $params) ?>
+
+<?php elseif ('_save_and_add' == $name): ?>
+  <?php echo $this->addCredentialCondition('[?php echo $helper->linkToSaveAndAdd($form->getObject(), '.$this->asPhp($params).') ?]', $params) ?>
+
+<?php else: ?>
+  <li class="sf_admin_action_<?php echo $params['class_suffix'] ?>">
+[?php if (method_exists($helper, 'linkTo<?php echo $method = ucfirst(sfInflector::camelize($name)) ?>')): ?]
+  <?php echo $this->addCredentialCondition('[?php echo $helper->linkTo'.$method.'($form->getObject(), '.$this->asPhp($params).') ?]', $params) ?>
+
+[?php else: ?]
+  <?php echo $this->addCredentialCondition($this->getLinkToAction($name, $params, true), $params) ?>
+
+[?php endif; ?]
+  </li>
+<?php endif; ?>
+<?php endforeach; ?>
+<?php endforeach; ?>
+[?php endif; ?]
+</ul>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_form_field.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,18 @@
+[?php if ($field->isPartial()): ?]
+  [?php include_partial('<?php echo $this->getModuleName() ?>/'.$name, array('form' => $form, 'attributes' => $attributes instanceof sfOutputEscaper ? $attributes->getRawValue() : $attributes)) ?]
+[?php elseif ($field->isComponent()): ?]
+  [?php include_component('<?php echo $this->getModuleName() ?>', $name, array('form' => $form, 'attributes' => $attributes instanceof sfOutputEscaper ? $attributes->getRawValue() : $attributes)) ?]
+[?php else: ?]
+  <div class="[?php echo $class ?][?php $form[$name]->hasError() and print ' errors' ?]">
+    [?php echo $form[$name]->renderError() ?]
+    <div>
+      [?php echo $form[$name]->renderLabel($label) ?]
+
+      [?php echo $form[$name]->render($attributes instanceof sfOutputEscaper ? $attributes->getRawValue() : $attributes) ?]
+
+      [?php if ($help || $help = $form[$name]->renderHelp()): ?]
+        <div class="help">[?php echo __($help, array(), '<?php echo $this->getI18nCatalogue() ?>') ?]</div>
+      [?php endif; ?]
+    </div>
+  </div>
+[?php endif; ?]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_form_fieldset.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,18 @@
+<fieldset id="sf_fieldset_[?php echo preg_replace('/[^a-z0-9_]/', '_', strtolower($fieldset)) ?]">
+  [?php if ('NONE' != $fieldset): ?]
+    <h2>[?php echo __($fieldset, array(), '<?php echo $this->getI18nCatalogue() ?>') ?]</h2>
+  [?php endif; ?]
+
+  [?php foreach ($fields as $name => $field): ?]
+    [?php if ((isset($form[$name]) && $form[$name]->isHidden()) || (!isset($form[$name]) && $field->isReal())) continue ?]
+    [?php include_partial('<?php echo $this->getModuleName() ?>/form_field', array(
+      'name'       => $name,
+      'attributes' => $field->getConfig('attributes', array()),
+      'label'      => $field->getConfig('label'),
+      'help'       => $field->getConfig('help'),
+      'form'       => $form,
+      'field'      => $field,
+      'class'      => 'sf_admin_form_row sf_admin_'.strtolower($field->getType()).' sf_admin_form_field_'.$name,
+    )) ?]
+  [?php endforeach; ?]
+</fieldset>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,54 @@
+<div class="sf_admin_list">
+  [?php if (!$pager->getNbResults()): ?]
+    <p>[?php echo __('No result', array(), 'sf_admin') ?]</p>
+  [?php else: ?]
+    <table cellspacing="0">
+      <thead>
+        <tr>
+<?php if ($this->configuration->getValue('list.batch_actions')): ?>
+          <th id="sf_admin_list_batch_actions"><input id="sf_admin_list_batch_checkbox" type="checkbox" onclick="checkAll();" /></th>
+<?php endif; ?>
+          [?php include_partial('<?php echo $this->getModuleName() ?>/list_th_<?php echo $this->configuration->getValue('list.layout') ?>', array('sort' => $sort)) ?]
+<?php if ($this->configuration->getValue('list.object_actions')): ?>
+          <th id="sf_admin_list_th_actions">[?php echo __('Actions', array(), 'sf_admin') ?]</th>
+<?php endif; ?>
+        </tr>
+      </thead>
+      <tfoot>
+        <tr>
+          <th colspan="<?php echo count($this->configuration->getValue('list.display')) + ($this->configuration->getValue('list.object_actions') ? 1 : 0) + ($this->configuration->getValue('list.batch_actions') ? 1 : 0) ?>">
+            [?php if ($pager->haveToPaginate()): ?]
+              [?php include_partial('<?php echo $this->getModuleName() ?>/pagination', array('pager' => $pager)) ?]
+            [?php endif; ?]
+
+            [?php echo format_number_choice('[0] no result|[1] 1 result|(1,+Inf] %1% results', array('%1%' => $pager->getNbResults()), $pager->getNbResults(), 'sf_admin') ?]
+            [?php if ($pager->haveToPaginate()): ?]
+              [?php echo __('(page %%page%%/%%nb_pages%%)', array('%%page%%' => $pager->getPage(), '%%nb_pages%%' => $pager->getLastPage()), 'sf_admin') ?]
+            [?php endif; ?]
+          </th>
+        </tr>
+      </tfoot>
+      <tbody>
+        [?php foreach ($pager->getResults() as $i => $<?php echo $this->getSingularName() ?>): $odd = fmod(++$i, 2) ? 'odd' : 'even' ?]
+          <tr class="sf_admin_row [?php echo $odd ?]">
+<?php if ($this->configuration->getValue('list.batch_actions')): ?>
+            [?php include_partial('<?php echo $this->getModuleName() ?>/list_td_batch_actions', array('<?php echo $this->getSingularName() ?>' => $<?php echo $this->getSingularName() ?>, 'helper' => $helper)) ?]
+<?php endif; ?>
+            [?php include_partial('<?php echo $this->getModuleName() ?>/list_td_<?php echo $this->configuration->getValue('list.layout') ?>', array('<?php echo $this->getSingularName() ?>' => $<?php echo $this->getSingularName() ?>)) ?]
+<?php if ($this->configuration->getValue('list.object_actions')): ?>
+            [?php include_partial('<?php echo $this->getModuleName() ?>/list_td_actions', array('<?php echo $this->getSingularName() ?>' => $<?php echo $this->getSingularName() ?>, 'helper' => $helper)) ?]
+<?php endif; ?>
+          </tr>
+        [?php endforeach; ?]
+      </tbody>
+    </table>
+  [?php endif; ?]
+</div>
+<script type="text/javascript">
+/* <![CDATA[ */
+function checkAll()
+{
+  var boxes = document.getElementsByTagName('input'); for(var index = 0; index < boxes.length; index++) { box = boxes[index]; if (box.type == 'checkbox' && box.className == 'sf_admin_batch_checkbox') box.checked = document.getElementById('sf_admin_list_batch_checkbox').checked } return true;
+}
+/* ]]> */
+</script>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_actions.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,11 @@
+<?php if ($actions = $this->configuration->getValue('list.actions')): ?>
+<?php foreach ($actions as $name => $params): ?>
+<?php if ('_new' == $name): ?>
+<?php echo $this->addCredentialCondition('[?php echo $helper->linkToNew('.$this->asPhp($params).') ?]', $params)."\n" ?>
+<?php else: ?>
+<li class="sf_admin_action_<?php echo $params['class_suffix'] ?>">
+  <?php echo $this->addCredentialCondition($this->getLinkToAction($name, $params, false), $params)."\n" ?>
+</li>
+<?php endif; ?>
+<?php endforeach; ?>
+<?php endif; ?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_batch_actions.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php if ($listActions = $this->configuration->getValue('list.batch_actions')): ?>
+<li class="sf_admin_batch_actions_choice">
+  <select name="batch_action">
+    <option value="">[?php echo __('Choose an action', array(), 'sf_admin') ?]</option>
+<?php foreach ((array) $listActions as $action => $params): ?>
+    <?php echo $this->addCredentialCondition('<option value="'.$action.'">[?php echo __(\''.$params['label'].'\', array(), \'sf_admin\') ?]</option>', $params) ?>
+
+<?php endforeach; ?>
+  </select>
+  [?php $form = new sfForm(); if ($form->isCSRFProtected()): ?]
+    <input type="hidden" name="[?php echo $form->getCSRFFieldName() ?]" value="[?php echo $form->getCSRFToken() ?]" />
+  [?php endif; ?]
+  <input type="submit" value="[?php echo __('go', array(), 'sf_admin') ?]" />
+</li>
+<?php endif; ?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_field_boolean.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,5 @@
+[?php if ($value): ?]
+  [?php echo image_tag(sfConfig::get('sf_admin_module_web_dir').'/images/tick.png', array('alt' => __('Checked', array(), 'sf_admin'), 'title' => __('Checked', array(), 'sf_admin'))) ?]
+[?php else: ?]
+  &nbsp;
+[?php endif; ?]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_td_actions.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,18 @@
+<td>
+  <ul class="sf_admin_td_actions">
+<?php foreach ($this->configuration->getValue('list.object_actions') as $name => $params): ?>
+<?php if ('_delete' == $name): ?>
+    <?php echo $this->addCredentialCondition('[?php echo $helper->linkToDelete($'.$this->getSingularName().', '.$this->asPhp($params).') ?]', $params) ?>
+
+<?php elseif ('_edit' == $name): ?>
+    <?php echo $this->addCredentialCondition('[?php echo $helper->linkToEdit($'.$this->getSingularName().', '.$this->asPhp($params).') ?]', $params) ?>
+
+<?php else: ?>
+    <li class="sf_admin_action_<?php echo $params['class_suffix'] ?>">
+      <?php echo $this->addCredentialCondition($this->getLinkToAction($name, $params, true), $params) ?>
+
+    </li>
+<?php endif; ?>
+<?php endforeach; ?>
+  </ul>
+</td>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_td_batch_actions.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,3 @@
+<td>
+  <input type="checkbox" name="ids[]" value="[?php echo $<?php echo $this->getSingularName() ?>->getPrimaryKey() ?]" class="sf_admin_batch_checkbox" />
+</td>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_td_stacked.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,3 @@
+<td colspan="<?php echo count($this->configuration->getValue('list.display'))  ?>">
+  [?php echo <?php echo $this->getI18NString('list.params') ?> ?]
+</td>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_td_tabular.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+<?php foreach ($this->configuration->getValue('list.display') as $name => $field): ?>
+<?php echo $this->addCredentialCondition(sprintf(<<<EOF
+<td class="sf_admin_%s sf_admin_list_td_%s">
+  [?php echo %s ?]
+</td>
+
+EOF
+, strtolower($field->getType()), $name, $this->renderField($field)), $field->getConfig()) ?>
+<?php endforeach; ?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_th_stacked.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,1 @@
+[?php include_partial('<?php echo $this->getModuleName() ?>/list_th_tabular', array('sort' => $sort)) ?]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_list_th_tabular.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,17 @@
+<?php foreach ($this->configuration->getValue('list.display') as $name => $field): ?>
+[?php slot('sf_admin.current_header') ?]
+<th class="sf_admin_<?php echo strtolower($field->getType()) ?> sf_admin_list_th_<?php echo $name ?>">
+<?php if ($field->isReal()): ?>
+  [?php if ('<?php echo $name ?>' == $sort[0]): ?]
+    [?php echo link_to(__('<?php echo $field->getConfig('label', '', true) ?>', array(), '<?php echo $this->getI18nCatalogue() ?>'), '@<?php echo $this->getUrlForAction('list') ?>?sort=<?php echo $name ?>&sort_type='.($sort[1] == 'asc' ? 'desc' : 'asc')) ?]
+    [?php echo image_tag(sfConfig::get('sf_admin_module_web_dir').'/images/'.$sort[1].'.png', array('alt' => __($sort[1], array(), 'sf_admin'), 'title' => __($sort[1], array(), 'sf_admin'))) ?]
+  [?php else: ?]
+    [?php echo link_to(__('<?php echo $field->getConfig('label', '', true) ?>', array(), '<?php echo $this->getI18nCatalogue() ?>'), '@<?php echo $this->getUrlForAction('list') ?>?sort=<?php echo $name ?>&sort_type=asc') ?]
+  [?php endif; ?]
+<?php else: ?>
+  [?php echo __('<?php echo $field->getConfig('label', '', true) ?>', array(), '<?php echo $this->getI18nCatalogue() ?>') ?]
+<?php endif; ?>
+</th>
+[?php end_slot(); ?]
+<?php echo $this->addCredentialCondition("[?php include_slot('sf_admin.current_header') ?]", $field->getConfig()) ?>
+<?php endforeach; ?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/_pagination.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,25 @@
+<div class="sf_admin_pagination">
+  <a href="[?php echo url_for('@<?php echo $this->getUrlForAction('list') ?>') ?]?page=1">
+    [?php echo image_tag(sfConfig::get('sf_admin_module_web_dir').'/images/first.png', array('alt' => __('First page', array(), 'sf_admin'), 'title' => __('First page', array(), 'sf_admin'))) ?]
+  </a>
+
+  <a href="[?php echo url_for('@<?php echo $this->getUrlForAction('list') ?>') ?]?page=[?php echo $pager->getPreviousPage() ?]">
+    [?php echo image_tag(sfConfig::get('sf_admin_module_web_dir').'/images/previous.png', array('alt' => __('Previous page', array(), 'sf_admin'), 'title' => __('Previous page', array(), 'sf_admin'))) ?]
+  </a>
+
+  [?php foreach ($pager->getLinks() as $page): ?]
+    [?php if ($page == $pager->getPage()): ?]
+      [?php echo $page ?]
+    [?php else: ?]
+      <a href="[?php echo url_for('@<?php echo $this->getUrlForAction('list') ?>') ?]?page=[?php echo $page ?]">[?php echo $page ?]</a>
+    [?php endif; ?]
+  [?php endforeach; ?]
+
+  <a href="[?php echo url_for('@<?php echo $this->getUrlForAction('list') ?>') ?]?page=[?php echo $pager->getNextPage() ?]">
+    [?php echo image_tag(sfConfig::get('sf_admin_module_web_dir').'/images/next.png', array('alt' => __('Next page', array(), 'sf_admin'), 'title' => __('Next page', array(), 'sf_admin'))) ?]
+  </a>
+
+  <a href="[?php echo url_for('@<?php echo $this->getUrlForAction('list') ?>') ?]?page=[?php echo $pager->getLastPage() ?]">
+    [?php echo image_tag(sfConfig::get('sf_admin_module_web_dir').'/images/last.png', array('alt' => __('Last page', array(), 'sf_admin'), 'title' => __('Last page', array(), 'sf_admin'))) ?]
+  </a>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/editSuccess.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,20 @@
+[?php use_helper('I18N', 'Date') ?]
+[?php include_partial('<?php echo $this->getModuleName() ?>/assets') ?]
+
+<div id="sf_admin_container">
+  <h1>[?php echo <?php echo $this->getI18NString('edit.title') ?> ?]</h1>
+
+  [?php include_partial('<?php echo $this->getModuleName() ?>/flashes') ?]
+
+  <div id="sf_admin_header">
+    [?php include_partial('<?php echo $this->getModuleName() ?>/form_header', array('<?php echo $this->getSingularName() ?>' => $<?php echo $this->getSingularName() ?>, 'form' => $form, 'configuration' => $configuration)) ?]
+  </div>
+
+  <div id="sf_admin_content">
+    [?php include_partial('<?php echo $this->getModuleName() ?>/form', array('<?php echo $this->getSingularName() ?>' => $<?php echo $this->getSingularName() ?>, 'form' => $form, 'configuration' => $configuration, 'helper' => $helper)) ?]
+  </div>
+
+  <div id="sf_admin_footer">
+    [?php include_partial('<?php echo $this->getModuleName() ?>/form_footer', array('<?php echo $this->getSingularName() ?>' => $<?php echo $this->getSingularName() ?>, 'form' => $form, 'configuration' => $configuration)) ?]
+  </div>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/indexSuccess.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,36 @@
+[?php use_helper('I18N', 'Date') ?]
+[?php include_partial('<?php echo $this->getModuleName() ?>/assets') ?]
+
+<div id="sf_admin_container">
+  <h1>[?php echo <?php echo $this->getI18NString('list.title') ?> ?]</h1>
+
+  [?php include_partial('<?php echo $this->getModuleName() ?>/flashes') ?]
+
+  <div id="sf_admin_header">
+    [?php include_partial('<?php echo $this->getModuleName() ?>/list_header', array('pager' => $pager)) ?]
+  </div>
+
+<?php if ($this->configuration->hasFilterForm()): ?>
+  <div id="sf_admin_bar">
+    [?php include_partial('<?php echo $this->getModuleName() ?>/filters', array('form' => $filters, 'configuration' => $configuration)) ?]
+  </div>
+<?php endif; ?>
+
+  <div id="sf_admin_content">
+<?php if ($this->configuration->getValue('list.batch_actions')): ?>
+    <form action="[?php echo url_for('<?php echo $this->getUrlForAction('collection') ?>', array('action' => 'batch')) ?]" method="post">
+<?php endif; ?>
+    [?php include_partial('<?php echo $this->getModuleName() ?>/list', array('pager' => $pager, 'sort' => $sort, 'helper' => $helper)) ?]
+    <ul class="sf_admin_actions">
+      [?php include_partial('<?php echo $this->getModuleName() ?>/list_batch_actions', array('helper' => $helper)) ?]
+      [?php include_partial('<?php echo $this->getModuleName() ?>/list_actions', array('helper' => $helper)) ?]
+    </ul>
+<?php if ($this->configuration->getValue('list.batch_actions')): ?>
+    </form>
+<?php endif; ?>
+  </div>
+
+  <div id="sf_admin_footer">
+    [?php include_partial('<?php echo $this->getModuleName() ?>/list_footer', array('pager' => $pager)) ?]
+  </div>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/admin/template/templates/newSuccess.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,20 @@
+[?php use_helper('I18N', 'Date') ?]
+[?php include_partial('<?php echo $this->getModuleName() ?>/assets') ?]
+
+<div id="sf_admin_container">
+  <h1>[?php echo <?php echo $this->getI18NString('new.title') ?> ?]</h1>
+
+  [?php include_partial('<?php echo $this->getModuleName() ?>/flashes') ?]
+
+  <div id="sf_admin_header">
+    [?php include_partial('<?php echo $this->getModuleName() ?>/form_header', array('<?php echo $this->getSingularName() ?>' => $<?php echo $this->getSingularName() ?>, 'form' => $form, 'configuration' => $configuration)) ?]
+  </div>
+
+  <div id="sf_admin_content">
+    [?php include_partial('<?php echo $this->getModuleName() ?>/form', array('<?php echo $this->getSingularName() ?>' => $<?php echo $this->getSingularName() ?>, 'form' => $form, 'configuration' => $configuration, 'helper' => $helper)) ?]
+  </div>
+
+  <div id="sf_admin_footer">
+    [?php include_partial('<?php echo $this->getModuleName() ?>/form_footer', array('<?php echo $this->getSingularName() ?>' => $<?php echo $this->getSingularName() ?>, 'form' => $form, 'configuration' => $configuration)) ?]
+  </div>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/createAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,13 @@
+  public function executeCreate(sfWebRequest $request)
+  {
+<?php if (isset($this->params['with_doctrine_route']) && $this->params['with_doctrine_route']): ?>
+<?php else: ?>
+    $this->forward404Unless($request->isMethod('post'));
+
+<?php endif; ?>
+    $this->form = new <?php echo $this->getModelClass().'Form' ?>();
+
+    $this->processForm($request, $this->form);
+
+    $this->setTemplate('new');
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/deleteAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,17 @@
+  public function executeDelete(sfWebRequest $request)
+  {
+    $request->checkCSRFProtection();
+
+<?php if (isset($this->params['with_doctrine_route']) && $this->params['with_doctrine_route']): ?>
+    $this->getRoute()->getObject()->delete();
+<?php else: ?>
+    $this->forward404Unless($<?php echo $this->getSingularName() ?> = Doctrine::getTable('<?php echo $this->getModelClass() ?>')->find(<?php echo $this->getRetrieveByPkParamsForAction(43) ?>), sprintf('Object <?php echo $this->getSingularName() ?> does not exist (%s).', <?php echo $this->getRetrieveByPkParamsForAction(43) ?>));
+    $<?php echo $this->getSingularName() ?>->delete();
+<?php endif; ?>
+
+<?php if (isset($this->params['route_prefix']) && $this->params['route_prefix']): ?>
+    $this->redirect('@<?php echo $this->getUrlForAction('list') ?>');
+<?php else: ?>
+    $this->redirect('<?php echo $this->getModuleName() ?>/index');
+<?php endif; ?>
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/editAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+  public function executeEdit(sfWebRequest $request)
+  {
+<?php if (isset($this->params['with_doctrine_route']) && $this->params['with_doctrine_route']): ?>
+    $this->form = new <?php echo $this->getModelClass().'Form' ?>($this->getRoute()->getObject());
+<?php else: ?>
+    $this->forward404Unless($<?php echo $this->getSingularName() ?> = Doctrine::getTable('<?php echo $this->getModelClass() ?>')->find(<?php echo $this->getRetrieveByPkParamsForAction(43) ?>), sprintf('Object <?php echo $this->getSingularName() ?> does not exist (%s).', <?php echo $this->getRetrieveByPkParamsForAction(43) ?>));
+    $this->form = new <?php echo $this->getModelClass().'Form' ?>($<?php echo $this->getSingularName() ?>);
+<?php endif; ?>
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/indexAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,10 @@
+  public function executeIndex(sfWebRequest $request)
+  {
+<?php if (isset($this->params['with_doctrine_route']) && $this->params['with_doctrine_route']): ?>
+    $this-><?php echo $this->getPluralName() ?> = $this->getRoute()->getObjects();
+<?php else: ?>
+    $this-><?php echo $this->getPluralName() ?> = Doctrine::getTable('<?php echo $this->getModelClass() ?>')
+      ->createQuery('a')
+      ->execute();
+<?php endif; ?>
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/newAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,4 @@
+  public function executeNew(sfWebRequest $request)
+  {
+    $this->form = new <?php echo $this->getModelClass().'Form' ?>();
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/processFormAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,14 @@
+  protected function processForm(sfWebRequest $request, sfForm $form)
+  {
+    $form->bind($request->getParameter($form->getName()));
+    if ($form->isValid())
+    {
+      $<?php echo $this->getSingularName() ?> = $form->save();
+
+<?php if (isset($this->params['route_prefix']) && $this->params['route_prefix']): ?>
+      $this->redirect('@<?php echo $this->getUrlForAction('edit') ?>?<?php echo $this->getPrimaryKeyUrlParams() ?>);
+<?php else: ?>
+      $this->redirect('<?php echo $this->getModuleName() ?>/edit?<?php echo $this->getPrimaryKeyUrlParams() ?>);
+<?php endif; ?>
+    }
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/showAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+  public function executeShow(sfWebRequest $request)
+  {
+<?php if (isset($this->params['with_doctrine_route']) && $this->params['with_doctrine_route']): ?>
+    $this-><?php echo $this->getSingularName() ?> = $this->getRoute()->getObject();
+<?php else: ?>
+    $this-><?php echo $this->getSingularName() ?> = Doctrine::getTable('<?php echo $this->getModelClass() ?>')->find(<?php echo $this->getRetrieveByPkParamsForAction(65) ?>);
+    $this->forward404Unless($this-><?php echo $this->getSingularName() ?>);
+<?php endif; ?>
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/parts/updateAction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,14 @@
+  public function executeUpdate(sfWebRequest $request)
+  {
+<?php if (isset($this->params['with_doctrine_route']) && $this->params['with_doctrine_route']): ?>
+    $this->form = new <?php echo $this->getModelClass().'Form' ?>($this->getRoute()->getObject());
+<?php else: ?>
+    $this->forward404Unless($request->isMethod('post') || $request->isMethod('put'));
+    $this->forward404Unless($<?php echo $this->getSingularName() ?> = Doctrine::getTable('<?php echo $this->getModelClass() ?>')->find(<?php echo $this->getRetrieveByPkParamsForAction(43) ?>), sprintf('Object <?php echo $this->getSingularName() ?> does not exist (%s).', <?php echo $this->getRetrieveByPkParamsForAction(43) ?>));
+    $this->form = new <?php echo $this->getModelClass().'Form' ?>($<?php echo $this->getSingularName() ?>);
+<?php endif; ?>
+
+    $this->processForm($request, $this->form);
+
+    $this->setTemplate('edit');
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/skeleton/actions/actions.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * ##MODULE_NAME## actions.
+ *
+ * @package    ##PROJECT_NAME##
+ * @subpackage ##MODULE_NAME##
+ * @author     ##AUTHOR_NAME##
+ * @version    SVN: $Id: actions.class.php 12474 2008-10-31 10:41:27Z fabien $
+ */
+class ##MODULE_NAME##Actions extends auto##MODULE_NAME##Actions
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/skeleton/config/generator.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,4 @@
+generator:
+  class: sfDoctrineGenerator
+  param:
+##CONFIG##
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/template/actions/actions.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,30 @@
+[?php
+
+/**
+ * <?php echo $this->getModuleName() ?> actions.
+ *
+ * @package    ##PROJECT_NAME##
+ * @subpackage <?php echo $this->getModuleName()."\n" ?>
+ * @author     ##AUTHOR_NAME##
+ * @version    SVN: $Id: actions.class.php 12474 2008-10-31 10:41:27Z fabien $
+ */
+class <?php echo $this->getGeneratedModuleName() ?>Actions extends sfActions
+{
+<?php include dirname(__FILE__).'/../../parts/indexAction.php' ?>
+
+<?php if (isset($this->params['with_show']) && $this->params['with_show']): ?>
+<?php include dirname(__FILE__).'/../../parts/showAction.php' ?>
+
+<?php endif; ?>
+<?php include dirname(__FILE__).'/../../parts/newAction.php' ?>
+
+<?php include dirname(__FILE__).'/../../parts/createAction.php' ?>
+
+<?php include dirname(__FILE__).'/../../parts/editAction.php' ?>
+
+<?php include dirname(__FILE__).'/../../parts/updateAction.php' ?>
+
+<?php include dirname(__FILE__).'/../../parts/deleteAction.php' ?>
+
+<?php include dirname(__FILE__).'/../../parts/processFormAction.php' ?>
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/template/templates/_form.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,53 @@
+[?php include_stylesheets_for_form($form) ?]
+[?php include_javascripts_for_form($form) ?]
+
+<?php $form = $this->getFormObject() ?>
+<?php if (isset($this->params['route_prefix']) && $this->params['route_prefix']): ?>
+[?php echo form_tag_for($form, '@<?php echo $this->params['route_prefix'] ?>') ?]
+<?php else: ?>
+<form action="[?php echo url_for('<?php echo $this->getModuleName() ?>/'.($form->getObject()->isNew() ? 'create' : 'update').(!$form->getObject()->isNew() ? '?<?php echo $this->getPrimaryKeyUrlParams('$form->getObject()', true) ?> : '')) ?]" method="post" [?php $form->isMultipart() and print 'enctype="multipart/form-data" ' ?]>
+[?php if (!$form->getObject()->isNew()): ?]
+<input type="hidden" name="sf_method" value="put" />
+[?php endif; ?]
+<?php endif;?>
+  <table>
+    <tfoot>
+      <tr>
+        <td colspan="2">
+<?php if (!isset($this->params['non_verbose_templates']) || !$this->params['non_verbose_templates']): ?>
+          [?php echo $form->renderHiddenFields() ?]
+<?php endif; ?>
+<?php if (isset($this->params['route_prefix']) && $this->params['route_prefix']): ?>
+          &nbsp;<a href="[?php echo url_for('<?php echo $this->getUrlForAction('list') ?>') ?]">Cancel</a>
+<?php else: ?>
+          &nbsp;<a href="[?php echo url_for('<?php echo $this->getModuleName() ?>/index') ?]">Cancel</a>
+<?php endif; ?>
+          [?php if (!$form->getObject()->isNew()): ?]
+<?php if (isset($this->params['route_prefix']) && $this->params['route_prefix']): ?>
+            &nbsp;[?php echo link_to('Delete', '<?php echo $this->getUrlForAction('delete') ?>', $form->getObject(), array('method' => 'delete', 'confirm' => 'Are you sure?')) ?]
+<?php else: ?>
+            &nbsp;[?php echo link_to('Delete', '<?php echo $this->getModuleName() ?>/delete?<?php echo $this->getPrimaryKeyUrlParams('$form->getObject()', true) ?>, array('method' => 'delete', 'confirm' => 'Are you sure?')) ?]
+<?php endif; ?>
+          [?php endif; ?]
+          <input type="submit" value="Save" />
+        </td>
+      </tr>
+    </tfoot>
+    <tbody>
+<?php if (isset($this->params['non_verbose_templates']) && $this->params['non_verbose_templates']): ?>
+      [?php echo $form ?]
+<?php else: ?>
+      [?php echo $form->renderGlobalErrors() ?]
+<?php foreach ($form as $name => $field): if ($field->isHidden()) continue ?>
+      <tr>
+        <th>[?php echo $form['<?php echo $name ?>']->renderLabel() ?]</th>
+        <td>
+          [?php echo $form['<?php echo $name ?>']->renderError() ?]
+          [?php echo $form['<?php echo $name ?>'] ?]
+        </td>
+      </tr>
+<?php endforeach; ?>
+<?php endif; ?>
+    </tbody>
+  </table>
+</form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/template/templates/editSuccess.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,3 @@
+<h1>Edit <?php echo sfInflector::humanize($this->getModuleName()) ?></h1>
+
+[?php include_partial('form', array('form' => $form)) ?]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/template/templates/indexSuccess.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,35 @@
+<?php $form = $this->getFormObject() ?>
+<h1><?php echo sfInflector::humanize($this->getModuleName()) ?> List</h1>
+
+<table>
+  <thead>
+    <tr>
+<?php foreach ($this->getColumns() as $column): ?>
+      <th><?php echo sfInflector::humanize(sfInflector::underscore($column->getPhpName())) ?></th>
+<?php endforeach; ?>
+    </tr>
+  </thead>
+  <tbody>
+    [?php foreach ($<?php echo $this->getPluralName() ?> as $<?php echo $this->getSingularName() ?>): ?]
+    <tr>
+<?php foreach ($this->getColumns() as $column): ?>
+<?php if ($column->isPrimaryKey()): ?>
+<?php if (isset($this->params['route_prefix']) && $this->params['route_prefix']): ?>
+      <td><a href="[?php echo url_for('<?php echo $this->getUrlForAction(isset($this->params['with_show']) && $this->params['with_show'] ? 'show' : 'edit') ?>', $<?php echo $this->getSingularName() ?>) ?]">[?php echo $<?php echo $this->getSingularName() ?>->get<?php echo sfInflector::camelize($column->getPhpName()) ?>() ?]</a></td>
+<?php else: ?>
+      <td><a href="[?php echo url_for('<?php echo $this->getModuleName() ?>/<?php echo isset($this->params['with_show']) && $this->params['with_show'] ? 'show' : 'edit' ?>?<?php echo $this->getPrimaryKeyUrlParams() ?>) ?]">[?php echo $<?php echo $this->getSingularName() ?>->get<?php echo sfInflector::camelize($column->getPhpName()) ?>() ?]</a></td>
+<?php endif; ?>
+<?php else: ?>
+      <td>[?php echo $<?php echo $this->getSingularName() ?>->get<?php echo sfInflector::camelize($column->getPhpName()) ?>() ?]</td>
+<?php endif; ?>
+<?php endforeach; ?>
+    </tr>
+    [?php endforeach; ?]
+  </tbody>
+</table>
+
+<?php if (isset($this->params['route_prefix']) && $this->params['route_prefix']): ?>
+  <a href="[?php echo url_for('<?php echo $this->getUrlForAction('new') ?>') ?]">New</a>
+<?php else: ?>
+  <a href="[?php echo url_for('<?php echo $this->getModuleName() ?>/new') ?]">New</a>
+<?php endif; ?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/template/templates/newSuccess.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,3 @@
+<h1>New <?php echo sfInflector::humanize($this->getModuleName()) ?></h1>
+
+[?php include_partial('form', array('form' => $form)) ?]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/template/templates/showSuccess.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,22 @@
+<table>
+  <tbody>
+<?php foreach ($this->getColumns() as $column): ?>
+    <tr>
+      <th><?php echo sfInflector::humanize(sfInflector::underscore($column->getPhpName())) ?>:</th>
+      <td>[?= $<?php echo $this->getSingularName() ?>->get<?php echo $column->getPhpName() ?>() ?]</td>
+    </tr>
+<?php endforeach; ?>
+  </tbody>
+</table>
+
+<hr />
+
+<?php if (isset($this->params['route_prefix']) && $this->params['route_prefix']): ?>
+<a href="[?php echo url_for('<?php echo $this->getUrlForAction('edit') ?>', $<?php echo $this->getSingularName() ?>) ?]">Edit</a>
+&nbsp;
+<a href="[?php echo url_for('<?php echo $this->getUrlForAction('list') ?>') ?]">List</a>
+<?php else: ?>
+<a href="[?php echo url_for('<?php echo $this->getModuleName() ?>/edit?<?php echo $this->getPrimaryKeyUrlParams() ?>) ?]">Edit</a>
+&nbsp;
+<a href="[?php echo url_for('<?php echo $this->getModuleName() ?>/index') ?]">List</a>
+<?php endif; ?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.ar.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>جديد</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>تحديث</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>حذÙ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>لائحة</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+         <target>Ø­ÙØ¸</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Ø­ÙØ¸ Ùˆ Ø¥Ø¶Ø§ÙØ©</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>إلغاء</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>مسح</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>ÙØ±Ø²</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>لا توجد نتائج</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>إجراءات</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(%%nb_pages%%/%%page%% ØµÙØ­Ø©)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>تصاعدي</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>تنازلي</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>الأولى</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Ø§Ù„ØµÙØ­Ø© السابقة</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Ø§Ù„ØµÙØ­Ø© الاحقة</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>الاخيرة</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>.تمت Ø§Ù„Ø¥Ø¶Ø§ÙØ© بنجاح</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+       <target>.تم التحديث بنجاح</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>.تمت Ø§Ù„Ø¥Ø¶Ø§ÙØ© بنجاح. يمكنك Ø¥Ø¶Ø§ÙØ© آخر</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>.تم التحديث بنجاح. يمكنك Ø¥Ø¶Ø§ÙØ© آخر</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>.لم يتم التحديث</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>.تم الحذ٠بنجاح</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>.يجب اختيار عنصر واحد على الأقل</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>.يجب اختيار عمل للتنÙيذ ضمن العناصر المختارة</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>.حال مشكل دون عملية الحذ٠للعناصر المختارة لأن بعضها غير موجود</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>.تم حذ٠العناصر المختارة بنجاح</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>.حال مشكل أثناء عملية الحذ٠للعناصر المختارة</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.bg.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Ðов</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>РедакциÑ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Изтриване</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>СпиÑък</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>СъхранÑване</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>СъхранÑване и ДобавÑне</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Отказ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Choose an action</source>
+        <target>Избери дейÑтвие</target>
+      </trans-unit>
+      <trans-unit>
+        <source>go</source>
+        <target>ок</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Ðулиране</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Филтър</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>ÐÑма резултати</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>ДейÑтвиÑ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(Ñтраница %%page%% от %%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>възходÑщ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>низходÑщ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>[0] no result|[1] 1 result|(1,+Inf] %1% results</source>
+        <target>[0] нÑма резултати|[1] 1 резултат|(1,+Inf] %1% резултата</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Първа Ñтраница</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Предишна Ñтраница</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Следваща Ñтраница</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>ПоÑледна Ñтраница</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>ЗапиÑÑŠÑ‚ беше Ñъздаден уÑпешно.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>ЗапиÑÑŠÑ‚ беше уÑпешно обновен.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>ЗапиÑÑŠÑ‚ беше Ñъздаден уÑпешно. Можете да добавите друг.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>ЗапиÑÑŠÑ‚ беше уÑпешно обновен. Можете да добавите друг.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>ЗапиÑÑŠÑ‚ не беше запазен поради грешки.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>ЗапиÑÑŠÑ‚ беше уÑпешно изтрит.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.ca.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Nou</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Edita</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Esborrar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Llista</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Salvar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Desar i afegir</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Cancelar</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Restablir</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrar</target>
+      </trans-unit>
+
+      <!-- List -->
+            <trans-unit>
+        <source>No result</source>
+        <target>Cap resultat</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Accions</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(pàgina %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>asc</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>desc</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Choose an action</source>
+        <target>Tria una opció</target>
+      </trans-unit>
+      <trans-unit>
+        <source>go</source>
+        <target>executa</target>
+      </trans-unit>
+      <trans-unit>
+        <source>[0] no result|[1] 1 result|(1,+Inf] %1% results</source>
+        <target>[0] cap resultat|[1] 1 resultat|(1,+Inf] %1% resultats</target>
+      </trans-unit>
+      
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Primera pàgina</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Pàgina anterior</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Pàgina següent</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Última pàgina</target>
+      </trans-unit>
+      
+      
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>El tema s&#39;ha creat amb èxit.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>El tema s&#39;ha actualitzat amb èxit.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>El tema s&#39;ha creat amb èxit. Podeu afegir una altra més endavant.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>El tema s&#39;ha actualitzat amb èxit. Podeu afegir una altra més endavant.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>El tema no s&#39;ha desat degut a alguns errors.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>El tema s&#39;ha eliminat amb èxit.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Has de seleccionar almenys un element.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Has de triar l'acció que vols executar sobre els elements seleccionats.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>S'ha produït un error a l'esborrar els elements seleccionats perquè almenys un d'ells ja no existeix.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Els elements seleccionats s'han esborrat correctament.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>S'ha produït un error a l'esborrar els elements seleccionats.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.cs.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Vytvořit</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Upravit</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Odstranit</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Výpis</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Uložit</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Uložit a přidat</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Zrušit</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Zrušit</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrovat</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Žádné položky</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Akce</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(stránka %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>vzestupnÄ›</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>sestupnÄ›</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>První stránka</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Předchozí stránka</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Další stránka</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Poslední stránka</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Položka byla úspešně vytvořena.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Položka byla úspešně upravena.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Položka byla úspešně vytvořena. Můžete přidat další.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Položka byla úspešne upravena. Můžete přidat další.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Položka nebyla uložena kvůli chybám.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Položka byla úspešně odstraněna.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Zvolte alespoň jednu položku.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Zvolte si akci, která se provede se zvolenými položkami.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Došlo k chybě při odstraňování zvolených položek, některé z nich již neexistují.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Zvolené položky byly úspěšně odstraněny.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Došlo k chybě při odstraňování zvolených položek.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.da.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Ny</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Rediger</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Slet</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Liste</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Gem</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Gem og tilføj</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Annuler</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Nulstil</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrer</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Intet resultat</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Handlinger</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(side %%page%% af %%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>stigende</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>faldende</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Første side</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Forrige side</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Næste side</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Sidste side</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Elementet er blevet tilføjet.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Elementet er blevet opdateret.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Elementet er blevet tilføjet, du kan tilføje endnu et element herunder.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Elementet er blevet opdateret, du kan tilføje endnu et herunder.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Elementet er ikke blevet tilføjet, pga. fejl.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Elementet er blevet slettet.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Du skal vælge mindst et element.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Du skal vælge en handling, at udføre på de valgte elementer.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Et problem opstod ved sletning af de valgte elementer, da nogen af disse ikke eksisterer mere.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>De valgte elementer er blevet slettet.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Der var et problem, med at slette de valgte elementer.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.de.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Neu</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Bearbeiten</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Löschen</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Liste</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Speichern</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Speichern und hinzufügen</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Abbrechen</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Choose an action</source>
+        <target>Eine Aktion wählen</target>
+      </trans-unit>
+      <trans-unit>
+        <source>go</source>
+        <target>ok</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Zurücksetzen</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtern</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Keine Ergebnisse</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Aktionen</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(Seite %%page%% von %%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>aufsteigend</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>absteigend</target>
+      </trans-unit>
+      <trans-unit>
+        <source>[0] no result|[1] 1 result|(1,+Inf] %1% results</source>
+        <target>[0] kein Ergebnis|[1] 1 Ergebnis|(1,+Inf] %1% Ergebnisse</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Erste Seite</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Vorherige Seite</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Nächste Seite</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Letzte Seite</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Das Objekt wurde erfolgreich erstellt.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Das Objekt wurde erfolgreich aktualisiert.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Das Objekt wurde erfolgreich erstellt. Weitere können unten erstellt werden.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Das Objekt wurde erfolgreich aktualisiert. Weitere können unten erstellt werden.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Das Objekt konnte wegen Fehlern nicht gespeichert werden.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Das Objekt wurde erfolgreich gelöscht.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.el.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Îέο</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>ΕπεξεÏγασία</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>ΔιαγÏαφή</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>ΑπαÏίθμηση</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Αποθήκευση</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Αποθήκευση και ΠÏοσθήκη</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>ΑκÏÏωση</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>ΚαθαÏισμός</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>ΦίλτÏο</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Κανένα Αποτέλεσμα.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>ΕνέÏγειες</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(Σελίδα %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>αυξ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>φθι</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>ΠÏώτη Σελίδα</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>ΠÏοηγοÏμενη Σελίδα</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Επόμενη Σελίδα</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Τελευταία Σελίδα</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Το αντικείμενο δημιουÏγήθηκε επιτυχώς.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Το αντικείμενο ενημεÏώθηκε επιτυχώς.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Το αντικείμενο δημιουÏγήθηκε επιτυχώς. ΜποÏείτε να Ï€Ïοσθέσετε ένα καινοÏÏιο παÏακάτω.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Το αντικείμενο ενημεÏώθηκε επιτυχώς. ΜποÏείτε να Ï€Ïοσθέσετε ένα καινοÏÏιο παÏακάτω.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Το αντικείμενο δεν αποθηκεÏθηκε λόγω κάποιων σφαλμάτων.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Το αντικείμενο διαγÏάφηκε επιτυχώς.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>ΠÏέπει να επιλέξετε τουλάχιστον ένα αντικείμενο.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>ΠÏέπει να επιλέξετε κάποια ενέÏγεια να εκτελεστεί στα επιλεγμένα αντικείμενα.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Κάποιο Ï€Ïόβλημα σημειώθηκε κατά την διαγÏαφή των επιλεγμένων αντικειμένων καθώς μεÏικά αντικείμενα δεν υπάÏχουν πια.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Τα επιλεγμένα αντικείμενα διαγÏάφηκαν επιτυχώς.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Κάποιο Ï€Ïόβλημα σημειώθηκε κατά την διαγÏαφή των επιλεγμένων αντικειμένων.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.es.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Nuevo</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Editar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Borrar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Listado</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Guardar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Guardar y crear otro</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Cancelar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Choose an action</source>
+        <target>Selecciona una acción</target>
+      </trans-unit>
+      <trans-unit>
+        <source>go</source>
+        <target>ok</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Restablecer</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrar</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Sin resultados</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Acciones</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(página %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>asc</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>desc</target>
+      </trans-unit>
+      <trans-unit>
+        <source>[0] no result|[1] 1 result|(1,+Inf] %1% results</source>
+        <target>[0] sin resultados|[1] 1 resultado|(1,+Inf] %1% resultados</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Primera página</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Página anterior</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Página siguiente</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Última página</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>El elemento se ha creado correctamente.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>El elemento se ha actualizado correctamente.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>El elemento se ha creado correctamente y ahora puedes crear otro elemento.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>El elemento se ha actualizado correctamente y ahora puedes crear otro elemento.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>El elemento no se ha guardado porque se ha producido algún error.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>El elemento se ha borrado correctamente.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Debes seleccionar al menos un elemento.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Selecciona la acción que quieres ejecutar sobre los elementos seleccionados.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Se ha producido un error al borrar los elementos seleccionados porque al menos uno de ellos ya no existe.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Los elementos seleccionados se han borrado correctamente.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Se ha producido un error al borrar los elementos seleccionados.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.es_AR.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Nuevo</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Editar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Borrar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Listar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Guardar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Guardar y agregar otro</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Cancelar</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Reiniciar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrar</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Sin resultados</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Acciones</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(página %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>asc</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>desc</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Primera página</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Página anterior</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Siguiente página</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Ultima página</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>El elemento fue creado satisfactoriamente.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>El elemento fue actualizado satisfactoriamente.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>El elemento fue creado satisfactoriamente. Podés agregar otro abajo.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>El elemento fue actualizado satisfactoriamente. Podés agregar otro abajo.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>El elemento no fue guardado debido a algunos errores.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>El elemento fue borrado satisfactoriamente.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.eu.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Berria</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Aldatu</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Ezabatu</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Zerrendatu</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Gorde</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Gorde eta berria</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Ezeztatu</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Choose an action</source>
+        <target>Ekintza bat aukeratu</target>
+      </trans-unit>
+      <trans-unit>
+        <source>go</source>
+        <target>ok</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Garbitu</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Mugatu</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Emaitzarik ez</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Ekintzak</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(%%page%%/%%nb_pages%% orria)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>gora</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>behera</target>
+      </trans-unit>
+      <trans-unit>
+        <source>[0] no result|[1] 1 result|(1,+Inf] %1% results</source>
+        <target>[0] emaitzarik ez|[1] emaitza bat|(1,+Inf] %1% emaitzak</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Lehen orria</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Aurreko orria</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Hurrengo orria</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Azken orria</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Elementua egoki sortu da.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Elementua egoki eguneratu da.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Elementua egoki sortu da eta orain beste elementu bat sor dezakezu.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Elementua egoki eguneratu da eta orain beste elementu bat sor dezakezu.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Elementua ez da gorde errakuntzaren bat gertatu delako.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Elementua egoki ezabatu da.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Gutxienez, elementu bat aukeratu behar duzu.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Aukeratutako elementuen artean, exekutatu nahi duzun ekintza aukeratu.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Aukeratutako elementuak ezabatzerakoan errakuntza bat gertatu da, horietako bat, gutxienez, existitzen ez delako.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Aukeratutako elementuak egoki ezabatu dira.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Errakuntza bat gertatu da, aukeratutako elementuak ezabatzerakoan.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.fi.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Uusi</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Muokkaa</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Poista</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Näytä lista</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Tallenna</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Tallenna ja lisää</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Peruuta</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Tyhjennä</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Suodata</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Ei tuloksia</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Toiminnot</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(sivu %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>kasvava</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>madaltuva</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Ensimmäinen sivu</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Edellinen sivu</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Seuraava sivu</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Viimeinen sivu</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Merkinnän luonti onnistui.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Merkinnän päivittäminen onnistui.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Merkinnän luonti onnistui. Voit lisätä sen alle seuraavan.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Merkinnän päivitys onnistui. Voit lisätä sen alle seuraavan.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Merkintää ei tallennettu virheiden takia.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Merkinnän poistaminen onnistui.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Valitse vähintään yksi merkintä.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Valitse toiminto, joka suoritetaan valituille merkinnöille.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Valittujen merkintöjen poistamisessa esiintyi virhe, koska jotkut merkinnät eivät enää olleet olemassa.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Valittujen merkintöjen poistaminen onnistui.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Valittujen merkintöjen poistamisessa esiintyi virhe.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.fr.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Nouveau</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Modifier</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Supprimer</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Liste</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Mettre à jour</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Mettre à jour et ajouter</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Annuler</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Choose an action</source>
+        <target>Choisir une action</target>
+      </trans-unit>
+      <trans-unit>
+        <source>go</source>
+        <target>ok</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Effacer</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrer</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Aucun résultat.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Actions</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(page %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>asc</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>desc</target>
+      </trans-unit>
+      <trans-unit>
+        <source>[0] no result|[1] 1 result|(1,+Inf] %1% results</source>
+        <target>[0] aucun résultat|[1] 1 résultat|(1,+Inf] %1% résultats</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Are you sure?</source>
+        <target>Êtes-vous sûr ?</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Checked</source>
+        <target>Activé</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Première page</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Page précédente</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Page suivante</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Dernière page</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>L'objet a été ajouté avec succès.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>L'objet a été mis à jour avec succès.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>L'objet a été ajouté avec succès. Vous pouvez en ajouter un autre.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>L'objet a été mis à jour avec succès. Vous pouvez en ajouter un autre.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>L'objet n'a pu être mis à jour.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>L'objet a été supprimé avec succès.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Vous devez au moins sélectionner un objet.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Vous devez sélectionner une action à executer sur les objets sélectionnés.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Un problème est survenu lors de la suppression des objets sélectionnés car certains objets n'existent plus.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Les objets sélectionnés ont été supprimés avec succès.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Un problème est survenu lors de la suppression des objets sélectionnés.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.hr.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Novo</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Uredi</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Obriši</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Lista</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Spremi</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Spremi i dodaj</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Odustani</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Poništi</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtriraj</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Nema rezultata</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Akcije</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(stranica %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>rastuće</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>padajuće</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Prva stranica</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Prethodna stranica</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Sljedeća stranica</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Zadnja stranica</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Stavka je uspješno kreirana.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Izmjene su spremljene.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Stavka uspješno kreirana. Možete dodati sljedeću.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Izmjene su spremljene. Možete dodati sljedeću stavku.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Stavka nije spremljena zbog greške.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Stavka uspješno izbrisana.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Morate izabrati barem jednu stavku.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Morate izabrati akciju koja će se izvršiti na izabranim stavkama.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Ne mogu izbrisati izabrane stavke jer neke više ne postoje.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Izabrane stavke su uspješno obrisane.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Ne mogu izbrisati izabrane stavke zbog greške.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.hu.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Új</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Szerkesztés</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Törlés</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Lista</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Mentés</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Mentés és új elem</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Mégsem</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Alapértelmezett</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Szűrés</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Nincs találat.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Műveletek</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(oldal %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>növekvő</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>csökkenő</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Első oldal</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Előző oldal</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Következő oldal</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Utolsó oldal</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Az elem létrehozása sikeres volt.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Az elem mentése sikeres volt.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Az elem létrehozása sikeres volt. Újabb létrehozása az alábbi adatlapon.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Az elem mentése sikeres volt. Újabb létrehozása az alábbi adatlapon.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Az elem mentése hiba miatt sikertelen volt.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Az elem törlése sikeres volt.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Legalább egy elemet ki kell választani.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Válassza ki a kiválasztott elemeken végrehajtandó műveletet.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Probléma lépett fel a kiválasztott elemek törlése közben, valamely elem már eleve nem létezett.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>A kiválasztott elemek törlése sikeres volt.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Probléma lépett fel a kiválasztott elemek törlése közben.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.id.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Buat Baru</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Sunting</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Hapus</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Indeks</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Simpan</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Simpan dan tambah baru</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Batalkan</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Kembalikan seperti semula</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filter</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Tak ada hasil</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Aksi</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(halaman %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>asc</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>desc</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Halaman pertama</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Halaman sebelumnya</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Halaman berikut</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Halaman terakhir</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Data telah berhasil dibuat.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Data telah berhasil diperbaharui.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Data telah berhasil dibuat. Anda dapat menambahkan data baru di bawah ini.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Data telah berhasil diperbaharui. Anda dapat menambahkan data baru di bawah ini.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Data gagal disimpan karena adanya kesalahan.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Data telah berhasil dihapus.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Anda harus memilih paling tidak satu data.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Anda harus memilih sebuah aksi pada data yang telah terpilih.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Terjadi masalah pada saat akan menghapus data yang terpilih karena beberapa data tidak lagi tersedia.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Data yang terpilih telah berhasil dihapus.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Terjadi masalah pada saat akan menghapus data yang terpilih.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.it.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Nuovo</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Modifica</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Cancella</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Lista</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Salva</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Salva e aggiungi</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Annulla</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Choose an action</source>
+        <target>Scegli un'azione</target>
+      </trans-unit>
+      <trans-unit>
+        <source>go</source>
+        <target>ok</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Reset</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtra</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Nessun risultato</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Azioni</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(pagina %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>asc</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>disc</target>
+      </trans-unit>
+      <trans-unit>
+        <source>[0] no result|[1] 1 result|(1,+Inf] %1% results</source>
+        <target>[0] nessun risultato|[1] 1 risultato|(1,+Inf] %1% risultati</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Prima pagina</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Pagina precedente</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Pagina seguente</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Ultima pagina</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>L'elemento è stato creato con successo.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>L'elemento è stato aggiornato con successo.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>L'elemento è stato creato con successo. Puoi aggiungerne un altro di seguito.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>L'elemento è stato aggiornato con successo. Puoi aggiungerne un altro di seguito.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>L'elemento non è stato salvato a causa di qualche errore.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>L'elemento è stato cancellato con successo.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Selezionare almeno un elemento.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Selezionare un'azione da eseguire sugli elementi selezionati.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Si è verificato un problema durante la cancellazione degli elementi selezionati, alcuni elementi non esistono più.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Gli elementi selezionati sono stati cancellati.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Si è verificato un problema durante la cancellazione degli elementi selezionati.</target>
+      </trans-unit>
+   </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.ja.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>æ–°è¦ä½œæˆ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>編集</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>削除</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>一覧</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>ä¿å­˜</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>ä¿å­˜ã—ã¦æ›´ã«è¿½åŠ </target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>キャンセル</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>リセット</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>検索</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>データãŒã‚りã¾ã›ã‚“</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>æ“作</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(ページ %%page%%%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>é™é †</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>昇順</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>最åˆã®ãƒšãƒ¼ã‚¸</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>å‰ã®ãƒšãƒ¼ã‚¸</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>次ã®ãƒšãƒ¼ã‚¸</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>最後ã®ãƒšãƒ¼ã‚¸</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>アイテムを作æˆã—ã¾ã—ãŸ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>アイテムを更新ã—ã¾ã—ãŸ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>アイテムを作æˆã—ã¾ã—ãŸã€‚以下ã§åˆ¥ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’追加ã§ãã¾ã™ã€‚</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>アイテムを更新ã—ã¾ã—ãŸã€‚以下ã§åˆ¥ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’追加ã§ãã¾ã™ã€‚</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>エラーã®ãŸã‚アイテムをä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>アイテムを削除ã—ã¾ã—ãŸ</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.lt.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Naujas</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Redaguoti</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Å alinti</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Sąrašas</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Išsaugoti</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Išsaugoti ir pridėti</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Atšaukti</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Atstatyti</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtruoti</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Rezultatų nerasta</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Veiksmai</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(puslapis %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>didÄ—janÄiai</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>mažėjanÄiai</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Pirmas puslapis</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Ankstesnis puslapis</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Kitas puslapis</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Paskutinis puslapis</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Sukurta sÄ—kmingai.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Atnaujinta sÄ—kmingai.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Sukurta sėkmingai. Naują galite pridėti žemiau.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Ataujinta sėkmingai. Naują galite pridėti žemiau.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>IÅ¡saugoti nepavyko dÄ—l esanÄių klaidų.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Pašalinta sėkmingai.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Turite pasirinkti bent vienÄ… elementÄ….</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Turite pasirinkti veiksmą, kurį norite atlikti su pasirinktais elementais.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Nepavyko pašalinti pasirinktų elementų, kadangi kai kurie elementai jau nebeegzistuoja.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Pasirinkti elementai pašalinti sėkmingai.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Nepavyko pašalinti pasirinktų elementų.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.lv.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Jauns</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Rediģēt</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Dzēst</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Saraksts</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>SaglabÄt</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>SaglabÄt un pievienot</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Atcelt</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Atiestatīt</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrēt</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Nav datu</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Darbības</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(lapa %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>augoši</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>dilstoši</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>PirmÄ lapa</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>IepriekÅ¡ejÄ lapa</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>NÄkamÄ lapa</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>PÄ“dÄ“jÄ lapa</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Izveide sekmīga.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Rediģēšana sekmīga.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Izveide sekmÄ«ga, lai pievienotu vÄ“l vienu, lietojiet zemÄk esoÅ¡o formu.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Rediģēšana sekmÄ«ga, lai pievienotu vÄ“l vienu, lietojiet zemÄk esoÅ¡o formu.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>NeizdevÄs saglabÄt kļūdu dēļ.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Dzēšana sekmīga.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>JÄiezÄ«mÄ“ vismaz viena vienÄ«ba.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>JÄnorÄda darbÄ«ba, kura veicama ar iezÄ«mÄ“tajÄm vienÄ«bÄm.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Problēma dzēsot - visas vienības vairs neeksistē.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>AtzÄ«mÄ“tÄs vienÄ«bas sekmÄ«gi izdzÄ“stas.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>DzÄ“sot atzÄ«mÄ“tÄs vienÄ«bas notiek kļūda.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.nl.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Nieuw</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Wijzig</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Verwijder</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Lijst</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Opslaan</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Opslaan en Doorgaan</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Annuleren</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Choose an action</source>
+        <target>Kies een optie</target>
+      </trans-unit>
+      <trans-unit>
+        <source>go</source>
+        <target>ok</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Herstellen</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filteren</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Geen resultaat</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Acties</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(pagina %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>opl</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>afl</target>
+      </trans-unit>
+      <trans-unit>
+        <source>[0] no result|[1] 1 result|(1,+Inf] %1% results</source> 
+        <target>[0] geen resultaat|[1] 1 resultaat|(1,+Inf] %1% resultaten</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Eerste pagina</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Vorige pagina</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Volgende pagina</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Laatste pagina</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Het item is succesvol aangemaakt.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Het item is succesvol gewijzigd.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Het items is succesvol aangemaakt. Hieronder kan je nog een item toevoegen.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Het item is succesvol gewijzigd. Hieronder kan je nog een item toevoegen.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Het item is niet opgeslagen vanwege fouten.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Het item is succesvol verwijderd</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.no.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Ny</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Rediger</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Slett</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Liste</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Lagre</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Lagre og opprett ny</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Avbryt</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Tilbakestill</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrer</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Ingen resultater</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Handlinger</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(side %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>stigende</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>synkende</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Første side</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Forrige side</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Neste side</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Siste side</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Nytt objekt opprettet.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Objekt oppdatert.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Objektet ble opprettet, du kan opprette et nytt nedenfor.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Objekt oppdatert, du kan opprette et nytt nedenfor.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Objektet ble ikke lagret, grunnet noen feil.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Objekt slettet.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.pl.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Nowy</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Edytuj</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Skasuj</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Lista</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Zapisz</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Zapisz i dodaj</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Anuluj</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Choose an action</source>
+        <target>Wybierz akcjÄ™</target>
+      </trans-unit>
+      <trans-unit>
+        <source>go</source>
+        <target>ok</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Wyczyść</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Szukaj</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Brak wyników.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Akcje</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(strona %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>rosnÄ…co</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>malejÄ…co</target>
+      </trans-unit>
+      <trans-unit>
+        <source>[0] no result|[1] 1 result|(1,+Inf] %1% results</source>
+        <target>[0] brak wyników|[1,+Inf] wyników: %1%</target> 
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Pierwsza strona</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Poprzednia strona</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Następna strona</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Ostatnia strona</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Obiekt został poprawnie utworzony.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Obiekt został poprawnie zaktualizowany.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Obiekt został poprawnie utworzony. Możesz teraz dodać kolejny.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Obiekt został poprawnie zaktualizowany. Możesz teraz dodać kolejny.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Z powodu błędów obiekt nie został zapisany.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Obiekt został poprawnie skasowany.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Musisz wybrać co najmniej jeden obiekt.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Musisz wybrać akcję do wykonania na wybranych obiektach.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Wystąpił błąd podczas usuwania wybranych obiektów, ponieważ niektóre już nie istnieją.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Wybrane obiekty zostały skasowane.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Wystąpił błąd podczas usuwania wybranych obiektów.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.pt.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Novo</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Editar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Apagar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Listar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Gravar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Gravar e adicionar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Cancelar</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Eliminar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrar</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Nenhum resultado.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Acções</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(página %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>asc</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>desc</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Primeira página</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Página anterior</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Próxima página</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Última página</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>O objecto foi criado com sucesso.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>O objecto foi actualizado com sucesso.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>O objecto foi criado com sucesso. Poderá adicionar outro de seguida.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>O objecto foi actualizado com sucesso. Poderá adicionar outro de seguida.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>O objecto não foi guardado devido a erros.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>O objecto foi apagado com sucesso.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Deverá seleccionar pelo menos um objecto.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Deverá selecionar uma acção para executar nos objectos seleccionados.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Um problema ocorreu ao apagar os objectos seleccionados devido à sua inexistência.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Os objectos seleccionados foram apagados com sucesso..</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Ocorreu um erro ao apagar os objectos seleccionados.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.pt_BR.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Novo</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Editar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Remover</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Listar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Salvar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Salvar e Adicionar outro</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Cancelar</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Limpar</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrar</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Nenhum resultado.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Ações</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(página %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>asc</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>desc</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Primeira página</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Página anterior</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Próxima página</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Última página</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Item adicionado com sucesso.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Item atualizado com sucesso.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Item adicionado com sucesso. Você pode adicionar outro abaixo.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Item atualizado com sucesso. Você pode adicionar outro abaixo.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Item não atualizado devido a erros.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Item removido com sucesso.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Ãtem excluído com sucesso.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Você deve selecionar pelo menos um ítem.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Você deve selecionar uma ação a ser executada nos ítens selecionados.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Ocorreu um problema ao excluir os ítens selecionados pois alguns deles não existem mais.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Os ítens selecionados foram excluídos com sucesso.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Ocorreu um problema ao deletar os ítens selecionados.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.ro.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+  <!-- This file uses ş and ţ (cedilla below) insted of ș and ț (comma below) for compatibility. -->
+  <!-- Acest fişier foloseşte ş şi ţ (sedilă dedesubt) în loc de ș şi ț (virgulă dedesubt) pentru compatibilitate. -->
+  <!-- ref: http://en.wikipedia.org/wiki/Romanian_alphabet#Comma-below_.28.C8.99_and_.C8.9B.29_versus_cedilla_.28.C5.9F_and_.C5.A3.29 -->
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Nou</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Editare</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Åžtergere</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Listare</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Salvare</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Salvare şi adăugare</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Anulare</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Resetare</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrare</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Nici un rezultat.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Acţiuni</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(pagina %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>asc</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>desc</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Prima pagină</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Pagina precedentă</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Pagina următoare</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Ultima pagină</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Obiectul a fost creat cu succes.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Obiectul a fost actualizat cu succes.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Obiectul a fost creat cu succes. Puteţi să mai adăugaţi unul mai jos.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Obiectul a fost actualizat cu succes. Puteţi să mai adăugaţi unul mai jos.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Obiectul n-a putut fi salvat.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Obiectul a fost ÅŸters cu succes.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Trebuie să selectaţi cel puţin un obiect.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Trebuie să selectaţi o acţiune ce va fi executată asupra obiectelor selectate.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>A survenit o problemă la ştergerea obiectelor selectate deoarece o parte din acestea nu mai există.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Obiectele selectate au fost ÅŸterse cu succes.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>A survenit o problemă la ştergerea obiectelor selectate.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.ru.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Создать</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Редактировать</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Удалить</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>СпиÑок</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Сохранить</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Сохранить и добавить</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Отмена</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>ОчиÑтить</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Фильтр</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Ðет результатов</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>ДейÑтвиÑ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(Ñтраница %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>По возраÑтанию</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>По убыванию</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>ÐŸÐµÑ€Ð²Ð°Ñ Ñтраница</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ñтраница</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ñтраница</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>ПоÑледнÑÑ Ñтраница</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Объект уÑпешно Ñоздан.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Объект уÑпешно изменен.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Объект уÑпешно Ñоздан. Ð’Ñ‹ можете добавить еще один.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Объект уÑпешно обновлен. Ð’Ñ‹ можете добавить еще один.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Объект не Ñохранен из-за некоторых ошибок.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Объект уÑпешно удален.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Вы должны выделить как-минимум один объект.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Ð’Ñ‹ должны выбрать дейÑтвие, которое будет выполнено Ñ Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð½Ñ‹Ð¼Ð¸ объектами.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Возникла проблемма при удалении выделенных объектов, так как некоторые объекты больше не ÑущеÑтвуют.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Выделенные объекты уÑпешно удалены.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Возникла проблемма при удалении выделенных объектов.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.sk.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Vytvoriť</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Upraviť</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Vymazať</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Výpis</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Uložiť</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Uložiť a pridať</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Zrušiť</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Zrušiť</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrovať</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Žiaden výsledok.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Akcie</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(stránka %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>vzostupne</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>zostupne</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Prvá stránka</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Predchádzajúca stránka</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Nasledujúca stránka</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Posledná stránka</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Položka bola úspešne vytvorená.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Položka bola úspešne upravená.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Položka bola úspeÅ¡ne vytvorená. Môžete pridaÅ¥ ÄalÅ¡iu.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Položka bola úspeÅ¡ne upravená. Môžete pridaÅ¥ ÄalÅ¡iu.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Položka nebola uložená kôli niekoľkým chybám.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Položka bola úspešne vymazaná.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Prosím zvoľte si aspoň jednu položku.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Prosím zvoľte si akciu na vykonanie s týmito položkami.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Vyskytol sa problem pri mazaní viacerých položiek, keÄže niektore z nich už neexistujú.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Vybrané položky boli úspešne vymazané.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Vyskytol sa problem pri mazaní zvolených položiek.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.sv.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Ny</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Redigera</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Radera</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Lista</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Spara</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Spara och skapa ny</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Avbryt</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Choose an action</source>
+        <target>Välj en åtgärd</target>
+      </trans-unit>
+      <trans-unit>
+        <source>go</source>
+        <target>ok</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Nollställ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrera</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Inga resultat</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Åtgärder</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(sida %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>stigande</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>fallande</target>
+      </trans-unit>
+      <trans-unit>
+        <source>[0] no result|[1] 1 result|(1,+Inf] %1% results</source>
+        <target>[0] inget resultat|[1] 1 resultat|(1,+Inf] %1% resultat</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Första sidan</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Föregående sida</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Näste sida</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Sista sidan</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Objekt skapades.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Objekt uppdaterat.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Objektet skapades. Du kan skapa ett nytt nedanför.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Objektet uppdaterades. Du kan skapa ett nytt nedanför.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Objektet kunde inte sparas på grund av vissa fel.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Objektet raderades.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Du måste välja minst ett objekt</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Du måste välja en åtgärd att utföra på det valda objektet.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Ett problem uppstod när de valda objekten skulle raderas då vissa objekt inte existerar längre.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>De valda objekten har raderats.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Ett problem uppstod när de valda objekten raderades.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.tr.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Yeni</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Düzenle</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Sil</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>Liste</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Kaydet</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Kaydet ve ekle</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Vazgeç</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Temizle</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Filtrele</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Kayıt yok.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Eylemler</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(sayfa %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>artan</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>azalan</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>İlk sayfa</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>Önceki sayfa</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>Sonraki sayfa</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>Son sayfa</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Kayıt başarıyla oluşturuldu.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Kayıt başarıyla güncellendi.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Kayıt başarıyla oluşturuldu. Aşağıdan yeni bir tane ekleyebilirsiniz.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Kayıt başarıyla güncellendi. Aşağıdan yeni bir tane ekleyebilirsiniz.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Bazı hatalar nedeniyle kayıt oluşturulamadı.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Kayıt başarıyla silindi.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>En az bir kayıt seçmelisiniz.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Seçilmiş kayıtlar üzerinde çalıştırılmak üzere bir eylem seçmelisiniz.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>Seçilmiş kayıtlar silinirken bir sorun oluştu, bazı kayıtlar artık bulunmuyor.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Seçilmiş kayıtlar başarıyla silindi.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>Seçilmiş kayıtlar silinirken bir sorun oluştu.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.uk.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>Ðовий запиÑ</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>Редагувати</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>Видалити</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>СпиÑок</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>Зберегти</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>Зберегти і додати</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>Відмінити</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>Скинути</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>Фільтрувати</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>Результат відÑутній</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>Дії</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(Ñторінка %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>(Ð-Я)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>(Я-Ð)</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>Перша Ñторінка</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ Ñторінка</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>ÐаÑтупна Ñторінка</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>ОÑÑ‚Ð°Ð½Ð½Ñ Ñторінка</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>Ð—Ð°Ð¿Ð¸Ñ Ñтворено уÑпішно.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>Ð—Ð°Ð¿Ð¸Ñ Ð·Ð¼Ñ–Ð½ÐµÐ½Ð¾ уÑпішно.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>Ð—Ð°Ð¿Ð¸Ñ Ñтворено уÑпішно. Можете додати наÑтупний.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>Ð—Ð°Ð¿Ð¸Ñ Ð·Ð¼Ñ–Ð½ÐµÐ½Ð¾ уÑпішно. Можете додати наÑтупний.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>Ð—Ð°Ð¿Ð¸Ñ Ð½Ðµ було збережено через помилки.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>Ð—Ð°Ð¿Ð¸Ñ Ð·Ð½Ð¸Ñ‰ÐµÐ½Ð¾ уÑпішно.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>Ви повинні вибрати принаймні один запиÑ.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>Ви повинні вибрати дію, що буде виконана над позначеними запиÑами.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>ДеÑкі запиÑи Ñеред вибраних Ð´Ð»Ñ Ð·Ð½Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð²Ð¶Ðµ відÑутні.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>Позначені запиÑи знищено уÑпішно.</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>При видаленні позначених запиÑів виникла помилка.</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/i18n/sf_admin.zh_CN.xml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd" >
+<xliff version="1.0">
+  <file original="global" source-language="en" datatype="plaintext">
+    <header />
+    <body>
+      <!-- Actions -->
+      <trans-unit>
+        <source>New</source>
+        <target>新建</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Edit</source>
+        <target>编辑</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Delete</source>
+        <target>删除</target>
+      </trans-unit>
+      <trans-unit>
+        <source>List</source>
+        <target>列表</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save</source>
+        <target>ä¿å­˜</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Save and add</source>
+        <target>ä¿å­˜å¹¶ç»§ç»­æ·»åŠ </target>
+      </trans-unit>
+      <trans-unit>
+        <source>Cancel</source>
+        <target>返回</target>
+      </trans-unit>
+
+      <!-- Filters -->
+      <trans-unit>
+        <source>Reset</source>
+        <target>é‡è®¾</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Filter</source>
+        <target>过滤器</target>
+      </trans-unit>
+
+      <!-- List -->
+      <trans-unit>
+        <source>No result</source>
+        <target>没有数æ®</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Actions</source>
+        <target>æ“作</target>
+      </trans-unit>
+      <trans-unit>
+        <source>(page %%page%%/%%nb_pages%%)</source>
+        <target>(é¡µç  %%page%%/%%nb_pages%%)</target>
+      </trans-unit>
+      <trans-unit>
+        <source>asc</source>
+        <target>顺åº</target>
+      </trans-unit>
+      <trans-unit>
+        <source>desc</source>
+        <target>逆åº</target>
+      </trans-unit>
+
+      <!-- Pagination -->
+      <trans-unit>
+        <source>First page</source>
+        <target>首页</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Previous page</source>
+        <target>上一页</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Next page</source>
+        <target>下一页</target>
+      </trans-unit>
+      <trans-unit>
+        <source>Last page</source>
+        <target>尾页</target>
+      </trans-unit>
+
+      <!-- Form -->
+      <trans-unit>
+        <source>The item was created successfully.</source>
+        <target>内容创建æˆåŠŸã€‚</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully.</source>
+        <target>内容已更新。</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was created successfully. You can add another one below.</source>
+        <target>内容已创建,将继续创建新内容。</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was updated successfully. You can add another one below.</source>
+        <target>内容已更新,将继续创建新内容。</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item has not been saved due to some errors.</source>
+        <target>有错误,内容ä¿å­˜å¤±è´¥ã€‚</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The item was deleted successfully.</source>
+        <target>内容已删除。</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must at least select one item.</source>
+        <target>至少è¦é€‰æ‹©ä¸€é¡¹ã€‚</target>
+      </trans-unit>
+      <trans-unit>
+        <source>You must select an action to execute on the selected items.</source>
+        <target>请选å–一个针对该æ¡ç›®çš„æ“ä½œã€‚</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items as some items do not exist anymore.</source>
+        <target>ä¸èƒ½åˆ é™¤ä¸å­˜åœ¨çš„æ¡ç›®ã€‚</target>
+      </trans-unit>
+      <trans-unit>
+        <source>The selected items have been deleted successfully.</source>
+        <target>选定的æ¡ç›®å·²åˆ é™¤ã€‚</target>
+      </trans-unit>
+      <trans-unit>
+        <source>A problem occurs when deleting the selected items.</source>
+        <target>在删除过程中å‘生错误。</target>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/cli/sfDoctrineCli.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,71 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfDoctrineCli
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineCli.class.php 13851 2008-12-08 22:54:16Z Jonathan.Wage $
+ */
+class sfDoctrineCli extends Doctrine_Cli
+{
+  protected $dispatcher,
+            $formatter;
+
+  /**
+   * Set the dispatcher of the cli instance
+   *
+   * @param object $dispatcher
+   * @return void
+   */
+  public function setDispatcher($dispatcher)
+  {
+    $this->dispatcher = $dispatcher;
+  }
+
+  /**
+   * Set the formatter to use for the cli
+   *
+   * @param object $formatter
+   * @return void
+   */
+  public function setFormatter($formatter)
+  {
+    $this->formatter = $formatter;
+  }
+
+  /**
+   * Notify the dispatcher of a message. We silent the messages from the Doctrine cli.
+   *
+   * @param string $notification
+   * @param string $style
+   * @return false
+   */
+  public function notify($notification = null, $style = 'HEADER')
+  {
+    $this->dispatcher->notify(new sfEvent($this, 'command.log', array($this->formatter->formatSection('doctrine', $notification))));
+  }
+
+  /**
+   * Notify symfony of an exception thrown by the Doctrine cli
+   *
+   * @param Doctrine_Exception $exception
+   * @return void
+   * @throws sfException
+   */
+  public function notifyException($exception)
+  {
+    throw new sfException($exception->getMessage());
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/database/sfDoctrineConnectionListener.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Standard connection listener
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineConnectionListener.class.php 11878 2008-09-30 20:14:40Z Jonathan.Wage $
+ */
+class sfDoctrineConnectionListener extends Doctrine_EventListener
+{
+  public function __construct($connection, $encoding)
+  {
+    $this->connection = $connection;
+    $this->encoding = $encoding;
+  }
+
+  public function postConnect(Doctrine_Event $event)
+  {
+    $this->connection->setCharset($this->encoding);
+    $this->connection->setDateFormat();
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/database/sfDoctrineDataRetriever.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,41 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Doctrine data retriever. Used to assist helpers with retrieving data for
+ * selector options.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineDataRetriever.class.php 12089 2008-10-08 20:23:25Z Jonathan.Wage $
+ */
+class sfDoctrineDataRetriever
+{
+  /**
+   * Used internally by symfony for retrieving objects for selector helper options.
+   *
+   * @param string $model       Name of the model to retrieve the objects from.
+   * @param string $peerMethod  Name of the peer method to invoke on the Doctrine_Table instance for the model.
+   */
+  static public function retrieveObjects($class, $peerMethod = 'findAll')
+  {
+    if (!$peerMethod)
+    {
+      $peerMethod = 'findAll';
+    }
+
+    $table = Doctrine::getTable($class);
+
+    return call_user_func(array($table, $peerMethod));
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/database/sfDoctrineDatabase.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,130 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A symfony database driver for Doctrine.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineDatabase.class.php 14977 2009-01-26 23:11:38Z Jonathan.Wage $
+ */
+class sfDoctrineDatabase extends sfDatabase
+{
+  /**
+   * Instance of the Doctrine_Connection for this instance of sfDoctrineDatabase.
+   * Connection can be accessed by the getDoctrineConnection() accessor method.
+   *
+   * @var Doctrine_Connection $_doctrineConnection
+   */
+  protected $_doctrineConnection = null;
+
+  /**
+   * Initialize a sfDoctrineDatabase connection with the given parameters.
+   *
+   * <code>
+   * $parameters = array(
+   *    'name'       => 'doctrine',
+   *    'dsn'        => 'sqlite:////path/to/sqlite/db');
+   *
+   * $p = new sfDoctrineDatabase($parameters);
+   * </code>
+   *
+   * @param array $parameters  Array of parameters used to initialize the database connection
+   * @return void
+   */
+  public function initialize($parameters = array())
+  {
+    parent::initialize($parameters);
+
+    if (!is_null($this->_doctrineConnection))
+    {
+      return;
+    }
+
+    $dsn = $this->getParameter('dsn');
+    $name = $this->getParameter('name');
+
+    // Make sure we pass non-PEAR style DSNs as an array
+    if ( !strpos($dsn, '://'))
+    {
+      $dsn = array($dsn, $this->getParameter('username'), $this->getParameter('password'));
+    }
+
+    // Make the Doctrine connection for $dsn and $name
+    $this->_doctrineConnection = Doctrine_Manager::connection($dsn, $name);
+    $attributes = $this->getParameter('attributes', array());
+    foreach ($attributes as $name => $value)
+    {
+      $this->_doctrineConnection->setAttribute($name, $value);
+    }
+
+    $encoding = $this->getParameter('encoding', 'UTF8'); 
+    $eventListener = new sfDoctrineConnectionListener($this->_doctrineConnection, $encoding); 
+    $this->_doctrineConnection->addListener($eventListener);
+
+    // Load Query Logger Listener
+    if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled'))
+    {
+      $this->_doctrineConnection->addListener(new sfDoctrineLogger());
+    }
+
+    // Invoke the configuration methods for the connection if they exist
+    $configuration = sfProjectConfiguration::getActive();
+
+    $method = sprintf('configureDoctrineConnection%s', ucwords($this->_doctrineConnection->getName()));
+    
+    if (method_exists($configuration, 'configureDoctrineConnection') && ! method_exists($configuration, $method))
+    {
+      $configuration->configureDoctrineConnection($this->_doctrineConnection);
+    }
+
+    if (method_exists($configuration, $method))
+    {
+      $configuration->$method($this->_doctrineConnection);
+    }
+  }
+
+  /**
+   * Get the Doctrine_Connection instance.
+   *
+   * @return Doctrine_Connection $conn
+   */
+  public function getDoctrineConnection()
+  {
+    return $this->_doctrineConnection;
+  }
+
+  /**
+   * Initializes the connection and sets it to object.
+   *
+   * @return void
+   */
+  public function connect()
+  {
+    $this->connection = $this->_doctrineConnection->getDbh();
+  }
+
+  /**
+   * Execute the shutdown procedure.
+   *
+   * @return void
+   */
+  public function shutdown()
+  {
+    if ($this->connection !== null)
+    {
+      $this->connection = null;
+      $this->_doctrineConnection = null;
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/debug/sfWebDebugPanelDoctrine.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,168 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfWebDebugPanelDoctrine adds a panel to the web debug toolbar with Doctrine information.
+ *
+ * @package    symfony
+ * @subpackage debug
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfWebDebugPanelDoctrine.class.php 11205 2008-08-27 16:24:17Z fabien $
+ */
+class sfWebDebugPanelDoctrine extends sfWebDebugPanel
+{
+  /**
+   * Constructor.
+   *
+   * @param sfWebDebug $webDebug The web debut toolbar instance
+   */
+  public function __construct(sfWebDebug $webDebug)
+  {
+    parent::__construct($webDebug);
+
+    $this->webDebug->getEventDispatcher()->connect('debug.web.filter_logs', array($this, 'filterLogs'));
+  }
+
+  /**
+   * Get the title/icon for the panel
+   *
+   * @return string $html
+   */
+  public function getTitle()
+  {
+    if ($sqlLogs = $this->getSqlLogs())
+    {
+      return '<img src="'.$this->webDebug->getOption('image_root_path').'/database.png" alt="SQL queries" /> '.count($sqlLogs);
+    }
+  }
+
+  /**
+   * Get the verbal title of the panel
+   *
+   * @return string $title
+   */
+  public function getPanelTitle()
+  {
+    return 'SQL queries';
+  }
+
+  /**
+   * Get the html content of the panel
+   *
+   * @return string $html
+   */
+  public function getPanelContent()
+  {
+    return '
+      <div id="sfWebDebugDatabaseLogs">
+      <ol><li>'.implode("</li>\n<li>", $this->getSqlLogs()).'</li></ol>
+      </div>
+    ';
+  }
+  
+  /**
+   * Filter the logs to only include the entries from sfDoctrineLogger
+   *
+   * @param sfEvent $event
+   * @param array $Logs
+   * @return array $newLogs
+   */
+  public function filterLogs(sfEvent $event, $newSqlogs)
+  {
+    $newLogs = array();
+    foreach ($newSqlogs as $newSqlog)
+    {
+      if ('sfDoctrineLogger' != $newSqlog['type'])
+      {
+        $newLogs[] = $newSqlog;
+      }
+    }
+
+    return $newLogs;
+  }
+
+  /**
+   * Hook to allow the loading of the Doctrine webdebug toolbar with the rest of the panels
+   *
+   * @param sfEvent $event 
+   * @return void
+   */
+  static public function listenToAddPanelEvent(sfEvent $event)
+  {
+    $event->getSubject()->setPanel('db', new self($event->getSubject()));
+  }
+
+  /**
+   * Build the sql logs and return them as an array
+   *
+   * @return array $newSqlogs
+   */
+  protected function getSqlLogs()
+  {
+    $logs = array();
+    $bindings = array();
+    $i = 0;
+    foreach ($this->webDebug->getLogger()->getLogs() as $log)
+    {
+      if ('sfDoctrineLogger' != $log['type'])
+      {
+        continue;
+      }
+
+      if (preg_match('/^.*?(\b(?:SELECT|INSERT|UPDATE|DELETE)\b.*)$/', $log['message'], $match))
+      {
+        $logs[$i++] = self::formatSql($match[1]);
+        $bindings[$i - 1] = array();
+      }
+      else if (preg_match('/Binding (.*) at position (.+?) w\//', $log['message'], $match))
+      {
+        $bindings[$i - 1][] = $match[2].' = '.$match[1];
+      }
+    }
+
+    foreach ($logs as $i => $log)
+    {
+      if (count($bindings[$i]))
+      {
+        $logs[$i] .= sprintf(' (%s)', implode(', ', $bindings[$i]));
+      }
+    }
+
+    return $logs;
+  }
+
+  /**
+   * Format a SQL with some colors on SQL keywords to make it more readable
+   *
+   * @param  string $sql    SQL string to format
+   * @return string $newSql The new formatted SQL string
+   */
+  static protected function formatSql($sql)
+  {
+    $color = "#990099";
+    $newSql = $sql;
+    $newSql = str_replace("SELECT ", "<span style=\"color: $color;\"><b>SELECT </b></span>  ",$newSql);
+    $newSql = str_replace("FROM ", "<span style=\"color: $color;\"><b>FROM </b></span>",$newSql);
+    $newSql = str_replace(" LEFT JOIN ", "<span style=\"color: $color;\"><b> LEFT JOIN </b></span>",$newSql);
+    $newSql = str_replace(" INNER JOIN ", "<span style=\"color: $color;\"><b> INNER JOIN </b></span>",$newSql);
+    $newSql = str_replace(" WHERE ", "<span style=\"color: $color;\"><b> WHERE </b></span>",$newSql);
+    $newSql = str_replace(" GROUP BY ", "<span style=\"color: $color;\"><b> GROUP BY </b></span>",$newSql);
+    $newSql = str_replace(" HAVING ", "<span style=\"color: $color;\"><b> HAVING </b></span>",$newSql);
+    $newSql = str_replace(" AS ", "<span style=\"color: $color;\"><b> AS </b></span>  ",$newSql);
+    $newSql = str_replace(" ON ", "<span style=\"color: $color;\"><b> ON </b></span>",$newSql);
+    $newSql = str_replace(" ORDER BY ", "<span style=\"color: $color;\"><b> ORDER BY </b></span>",$newSql);
+    $newSql = str_replace(" LIMIT ", "<span style=\"color: $color;\"><b> LIMIT </b></span>",$newSql);
+    $newSql = str_replace(" OFFSET ", "<span style=\"color: $color;\"><b> OFFSET </b></span>",$newSql);
+
+    return $newSql;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/form/sfFormDoctrine.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,531 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfFormDoctrine.class.php 7845 2008-03-12 22:36:14Z fabien $
+ */
+
+/**
+ * sfFormDoctrine is the base class for forms based on Doctrine objects.
+ *
+ * @package    symfony
+ * @subpackage form
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfFormDoctrine.class.php 7845 2008-03-12 22:36:14Z fabien $
+ */
+abstract class sfFormDoctrine extends sfForm
+{
+  protected
+    $isNew  = true,
+    $object = null;
+
+  /**
+   * Constructor.
+   *
+   * @param BaseObject A Doctrine object used to initialize default values
+   * @param array      An array of options
+   * @param string     A CSRF secret (false to disable CSRF protection, null to use the global CSRF secret)
+   *
+   * @see sfForm
+   */
+  public function __construct($object = null, $options = array(), $CSRFSecret = null)
+  {
+    $class = $this->getModelName();
+    if (!$object)
+    {
+      $this->object = new $class();
+    }
+    else
+    {
+      if (!$object instanceof $class)
+      {
+        throw new sfException(sprintf('The "%s" form only accepts a "%s" object.', get_class($this), $class));
+      }
+
+      $this->object = $object;
+      $this->isNew = !$this->object->exists();
+    }
+
+    parent::__construct(array(), $options, $CSRFSecret);
+
+    $this->updateDefaultsFromObject();
+  }
+
+  /**
+   * Returns the default connection for the current model.
+   *
+   * @return Connection A database connection
+   */
+  public function getConnection()
+  {
+    return Doctrine_Manager::getInstance()->getConnectionForComponent($this->getModelName());
+  }
+
+  /**
+   * Returns the current model name.
+   */
+  abstract public function getModelName();
+
+  /**
+   * Returns true if the current form embeds a new object.
+   *
+   * @return Boolean true if the current form embeds a new object, false otherwise
+   */
+  public function isNew()
+  {
+    $this->isNew = !$this->object->exists();
+
+    return $this->isNew;
+  }
+
+  /**
+   * Embeds i18n objects into the current form.
+   *
+   * @param array   $cultures   An array of cultures
+   * @param string  $decorator  A HTML decorator for the embedded form
+   */
+  public function embedI18n($cultures, $decorator = null)
+  {
+    if (!$this->isI18n())
+    {
+      throw new sfException(sprintf('The model "%s" is not internationalized.', $this->getModelName()));
+    }
+
+    $class = $this->getI18nFormClass();
+    foreach ($cultures as $culture)
+    {
+      $i18nObject = $this->object->Translation[$culture];
+      $i18n = new $class($i18nObject);
+      unset($i18n['id'], $i18n['lang']);
+
+      $this->embedForm($culture, $i18n, $decorator);
+    }
+  }
+
+  /**
+   * Returns the current object for this form.
+   *
+   * @return BaseObject The current object.
+   */
+  public function getObject()
+  {
+    return $this->object;
+  }
+
+  /**
+   * Binds the current form and save the to the database in one step.
+   *
+   * @param  array      An array of tainted values to use to bind the form
+   * @param  array      An array of uploaded files (in the $_FILES or $_GET format)
+   * @param  Connection An optional Doctrine Connection object
+   *
+   * @return Boolean    true if the form is valid, false otherwise
+   */
+  public function bindAndSave($taintedValues, $taintedFiles = null, $con = null)
+  {
+    $this->bind($taintedValues, $taintedFiles);
+    if ($this->isValid())
+    {
+      $this->save($con);
+
+      return true;
+    }
+
+    return false;
+  }
+
+  /**
+   * Saves the current object to the database.
+   *
+   * The object saving is done in a transaction and handled by the doSave() method.
+   *
+   * If the form is not valid, it throws an sfValidatorError.
+   *
+   * @param Connection An optional Connection object
+   *
+   * @return BaseObject The current saved object
+   *
+   * @see doSave()
+   */
+  public function save($con = null)
+  {
+    if (!$this->isValid())
+    {
+      throw $this->getErrorSchema();
+    }
+
+    if (is_null($con))
+    {
+      $con = $this->getConnection();
+    }
+
+    try
+    {
+      $con->beginTransaction();
+
+      $this->doSave($con);
+
+      $con->commit();
+    }
+    catch (Exception $e)
+    {
+      $con->rollback();
+
+      throw $e;
+    }
+
+    return $this->object;
+  }
+
+  /**
+   * Updates the values of the object with the cleaned up values.
+   *
+   * @param  array $values An array of values
+   *
+   * @return BaseObject The current updated object
+   */
+  public function updateObject($values = null)
+  {
+    if (is_null($values))
+    {
+      $values = $this->values;
+    }
+
+    $values = $this->processValues($values);
+
+    $this->object->fromArray($values);
+
+    // embedded forms
+    $this->updateObjectEmbeddedForms($values);
+
+    return $this->object;
+  }
+
+  /**
+   * Updates the values of the objects in embedded forms.
+   *
+   * @param array $values An array of values
+   * @param array $forms  An array of forms
+   */
+  public function updateObjectEmbeddedForms($values, $forms = null)
+  {
+    if (is_null($forms))
+    {
+      $forms = $this->embeddedForms;
+    }
+
+    foreach ($forms as $name => $form)
+    {
+      if (!isset($values[$name]) || !is_array($values[$name]))
+      {
+        continue;
+      }
+
+      if ($form instanceof sfFormDoctrine)
+      {
+        $form->updateObject($values[$name]);
+      }
+      else
+      {
+        $this->updateObjectEmbeddedForms($values[$name], $form->getEmbeddedForms());
+      }
+    }
+  }
+
+  /**
+   * Processes cleaned up values with user defined methods.
+   *
+   * To process a value before it is used by the updateObject() method,
+   * you need to define an updateXXXColumn() method where XXX is the PHP name
+   * of the column.
+   *
+   * The method must return the processed value or false to remove the value
+   * from the array of cleaned up values.
+   *
+   * @return array An array of cleaned up values processed by the user defined methods
+   */
+  public function processValues($values = null)
+  {
+    // see if the user has overridden some column setter
+    $valuesToProcess = $values;
+    foreach ($valuesToProcess as $field => $value)
+    {
+      $method = sprintf('update%sColumn', self::camelize($field));
+
+      if (method_exists($this, $method))
+      {
+        if (false === $ret = $this->$method($value))
+        {
+          unset($values[$field]);
+        }
+        else
+        {
+          $values[$field] = $ret;
+        }
+      }
+      else
+      {
+        // save files
+        if ($this->validatorSchema[$field] instanceof sfValidatorFile)
+        {
+          $values[$field] = $this->processUploadedFile($field, null, $valuesToProcess);
+        }
+      }
+    }
+
+    return $values;
+  }
+
+  /**
+   * Returns true if the current form has some associated i18n objects.
+   *
+   * @return Boolean true if the current form has some associated i18n objects, false otherwise
+   */
+  public function isI18n()
+  {
+    return $this->getObject()->getTable()->hasTemplate('Doctrine_Template_I18n');
+  }
+
+  /**
+   * Returns the name of the i18n model.
+   *
+   * @return string The name of the i18n model
+   */
+  public function getI18nModelName()
+  {
+    return $this->getObject()->getTable()->getTemplate('Doctrine_Template_I18n')->getI18n()->getOption('className');
+  }
+
+  /**
+   * Returns the name of the i18n form class.
+   *
+   * @return string The name of the i18n form class
+   */
+  public function getI18nFormClass()
+  {
+    return $this->getI18nModelName() . 'Form';
+  }
+
+  /**
+   * Renders a form tag suitable for the related Doctrine object.
+   *
+   * The method is automatically guessed based on the Doctrine object:
+   *
+   *  * if the object is new, the method is POST
+   *  * if the object already exists, the method is PUT
+   *
+   * @param  string $url         The URL for the action
+   * @param  array  $attributes  An array of HTML attributes
+   *
+   * @return string An HTML representation of the opening form tag
+   *
+   * @see sfForm
+   */
+  public function renderFormTag($url, array $attributes = array())
+  {
+    if (!isset($attributes['method']))
+    {
+      $attributes['method'] = $this->isNew() ? 'post' : 'put';
+    }
+
+    return parent::renderFormTag($url, $attributes);
+  }
+
+  /**
+   * Updates and saves the current object.
+   *
+   * If you want to add some logic before saving or save other associated objects,
+   * this is the method to override.
+   *
+   * @param Connection An optional Connection object
+   */
+  protected function doSave($con = null)
+  {
+    if (is_null($con))
+    {
+      $con = $this->getConnection();
+    }
+
+    $this->updateObject();
+
+    $this->object->save($con);
+
+    // embedded forms
+    $this->saveEmbeddedForms($con);
+  }
+
+  /**
+   * Saves embedded form objects.
+   *
+   * @param Connection $con   An optional Connection object
+   * @param array      $forms An array of forms
+   */
+  public function saveEmbeddedForms($con = null, $forms = null)
+  {
+    if (is_null($con))
+    {
+      $con = $this->getConnection();
+    }
+
+    if (is_null($forms))
+    {
+      $forms = $this->embeddedForms;
+    }
+
+    foreach ($forms as $form)
+    {
+      if ($form instanceof sfFormDoctrine)
+      {
+        $form->getObject()->save($con);
+        $form->saveEmbeddedForms($con);
+      }
+      else
+      {
+        $this->saveEmbeddedForms($con, $form->getEmbeddedForms());
+      }
+    }
+  }
+
+  /**
+   * Updates the default values of the form with the current values of the current object.
+   */
+  protected function updateDefaultsFromObject()
+  {
+    // update defaults for the main object
+    if ($this->isNew())
+    {
+      $this->setDefaults(array_merge($this->object->toArray(false), $this->getDefaults()));
+    }
+    else
+    {
+      $this->setDefaults(array_merge($this->getDefaults(), $this->object->toArray(false)));
+    }
+
+    $defaults = $this->getDefaults();
+    foreach ($this->embeddedForms as $name => $form)
+    {
+      if ($form instanceof sfFormDoctrine)
+      {
+        $form->updateDefaultsFromObject();
+        $defaults[$name] = $form->getDefaults();
+      }
+    }
+    $this->setDefaults($defaults);
+  }
+
+  /**
+   * Saves the uploaded file for the given field.
+   *
+   * @param  string $field The field name
+   * @param  string $filename The file name of the file to save
+   * @param  array  $values An array of values
+   *
+   * @return string The filename used to save the file
+   */
+  protected function processUploadedFile($field, $filename = null, $values = null)
+  {
+    if (!$this->validatorSchema[$field] instanceof sfValidatorFile)
+    {
+      throw new LogicException(sprintf('You cannot save the current file for field "%s" as the field is not a file.', $field));
+    }
+
+    if (is_null($values))
+    {
+      $values = $this->values;
+    }
+
+    if (isset($values[$field.'_delete']) && $values[$field.'_delete'])
+    {
+      $this->removeFile($field);
+
+      return '';
+    }
+
+    if (!$values[$field])
+    {
+      return $this->object->$field;
+    }
+
+    // we need the base directory
+    if (!$this->validatorSchema[$field]->getOption('path'))
+    {
+      return $values[$field];
+    }
+
+    $this->removeFile($field);
+
+    return $this->saveFile($field, $filename, $values[$field]);
+  }
+
+  /**
+   * Removes the current file for the field.
+   *
+   * @param string $field The field name
+   */
+  protected function removeFile($field)
+  {
+    if (!$this->validatorSchema[$field] instanceof sfValidatorFile)
+    {
+      throw new LogicException(sprintf('You cannot remove the current file for field "%s" as the field is not a file.', $field));
+    }
+
+    if (($directory = $this->validatorSchema[$field]->getOption('path')) && is_file($directory.$this->object->$field))
+    {
+      unlink($directory.$this->object->$field);
+    }
+  }
+
+  /**
+   * Saves the current file for the field.
+   *
+   * @param  string          $field    The field name
+   * @param  string          $filename The file name of the file to save
+   * @param  sfValidatedFile $file     The validated file to save
+   *
+   * @return string The filename used to save the file
+   */
+  protected function saveFile($field, $filename = null, sfValidatedFile $file = null)
+  {
+    if (!$this->validatorSchema[$field] instanceof sfValidatorFile)
+    {
+      throw new LogicException(sprintf('You cannot save the current file for field "%s" as the field is not a file.', $field));
+    }
+    if (is_null($file))
+    {
+      $file = $this->getValue($field);
+    }
+
+    $method = sprintf('generate%sFilename', $field);
+
+    if (!is_null($filename))
+    {
+      return $file->save($filename);
+    }
+    else if (method_exists($this->object, $method))
+    {
+      return $file->save($this->object->$method($file));
+    }
+    else
+    {
+      return $file->save();
+    }
+  }
+
+  protected function camelize($text)
+  {
+    return sfToolkit::pregtr($text, array('#/(.?)#e' => "'::'.strtoupper('\\1')", '/(^|_|-)+(.)/e' => "strtoupper('\\2')"));
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/form/sfFormFilterDoctrine.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,278 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfFormFilterDoctrine is the base class for filter forms based on Doctrine objects.
+ *
+ * @package    symfony
+ * @subpackage form
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfFormFilterDoctrine.class.php 11690 2008-09-20 19:50:03Z fabien $
+ */
+abstract class sfFormFilterDoctrine extends sfFormFilter
+{
+  protected
+    $tableMethodName       = null;
+
+  /**
+   * Returns the current model name.
+   *
+   * @return string The model class name
+   */
+  abstract public function getModelName();
+
+  /**
+   * Returns the fields and their filter type.
+   *
+   * @return array An array of fields with their filter type
+   */
+  abstract public function getFields();
+
+  /**
+   * Get the name of the table method used to retrieve the query object for the filter
+   *
+   * @return string $tableMethodName
+   */
+  public function getTableMethod()
+  {
+    return $this->tableMethodName;
+  }
+
+  /**
+   * Set the name of the table method used to retrieve the query object for the filter
+   *
+   * @param string $tableMethodName 
+   * @return void
+   */
+  public function setTableMethod($tableMethodName)
+  {
+    $this->tableMethodName = $tableMethodName;
+  }
+
+  /**
+   * Returns a Doctrine Query based on the current values form the form.
+   *
+   * @return Query A Doctrine Query object
+   */
+  public function getQuery()
+  {
+    if (!$this->isValid())
+    {
+      throw $this->getErrorSchema();
+    }
+
+    return $this->buildQuery($this->getValues());
+  }
+
+  /**
+   * Processes cleaned up values with user defined methods.
+   *
+   * To process a value before it is used by the buildQuery() method,
+   * you need to define an convertXXXValue() method where XXX is the PHP name
+   * of the column.
+   *
+   * The method must return the processed value or false to remove the value
+   * from the array of cleaned up values.
+   *
+   * @param  array An array of cleaned up values to process
+   *
+   * @return array An array of cleaned up values processed by the user defined methods
+   */
+  public function processValues($values)
+  {
+    // see if the user has overridden some column setter
+    $originalValues = $values;
+    foreach ($originalValues as $field => $value)
+    {
+      try
+      {
+        $method = sprintf('convert%sValue', self::camelize($field));
+      }
+      catch (Exception $e)
+      {
+        // no a "real" column of this object
+        continue;
+      }
+
+      if (method_exists($this, $method))
+      {
+        if (false === $ret = $this->$method($value))
+        {
+          unset($values[$field]);
+        }
+        else
+        {
+          $values[$field] = $ret;
+        }
+      }
+    }
+
+    return $values;
+  }
+
+  /**
+   * Builds a Doctrine Query based on the passed values.
+   *
+   * @param  array    An array of parameters to build the Query object
+   *
+   * @return Query A Doctrine Query object
+   */
+  public function buildQuery(array $values)
+  {
+    $values = $this->processValues($values);
+
+    $query = Doctrine::getTable($this->getModelName())->createQuery('r');
+
+    if ($this->tableMethodName)
+    {
+      $method = $this->tableMethodName;
+      $query = Doctrine::getTable($this->getModelName())->$method($query);
+    }
+
+    foreach ($this->getFields() as $field => $type)
+    {
+      if (!isset($values[$field]) || is_null($values[$field]) || '' === $values[$field])
+      {
+        continue;
+      }
+
+      if ($this->getTable()->hasField($field))
+      {
+        $method = sprintf('add%sColumnQuery', self::camelize($this->getFieldName($field)));
+      } else {
+        // not a "real" column
+        if (!method_exists($this, $method = sprintf('add%sColumnQuery', self::camelize($field))))
+        {
+          throw new LogicException(sprintf('You must define a "%s" method to be able to filter with the "%s" field.', $method, $field));
+        }  
+      }
+
+      if (method_exists($this, $method))
+      {
+        $this->$method($query, $field, $values[$field]);
+      }
+      else
+      {
+        if (!method_exists($this, $method = sprintf('add%sQuery', $type)))
+        {
+          throw new LogicException(sprintf('Unable to filter for the "%s" type.', $type));
+        }
+
+        $this->$method($query, $field, $values[$field]);
+      }
+    }
+
+    return $query;
+  }
+
+  protected function addForeignKeyQuery(Doctrine_Query $query, $field, $value)
+  {
+    $fieldName = $this->getFieldName($field);
+
+    if (is_array($value))
+    {
+      $query->orWhereIn('r.' . $fieldName, $value);
+    }
+    else
+    {
+      $query->addWhere('r.' . $fieldName . ' = ?', $value);
+    }
+  }
+
+  protected function addEnumQuery(Doctrine_Query $query, $field, $value)
+  {
+    $fieldName = $this->getFieldName($field);
+
+    $query->addWhere('r.' . $fieldName . ' = ?', $value);
+  }
+
+  protected function addTextQuery(Doctrine_Query $query, $field, $values)
+  {
+    $fieldName = $this->getFieldName($field);
+
+    if (is_array($values) && isset($values['is_empty']) && $values['is_empty'])
+    {
+      $query->addWhere('r.' . $fieldName . ' IS NULL');
+    }
+    else if (is_array($values) && isset($values['text']) && '' != $values['text'])
+    {
+      $query->addWhere('r.' . $fieldName . ' LIKE ?', '%' . $values['text'] . '%');
+    }
+  }
+
+  protected function addNumberQuery(Doctrine_Query $query, $field, $values)
+  {
+    $fieldName = $this->getFieldName($field);
+
+    if (is_array($values) && isset($values['is_empty']) && $values['is_empty'])
+    {
+      $query->addWhere('r.' . $fieldName . ' IS NULL');
+    }
+    else if (is_array($values) && isset($values['text']) && '' != $values['text'])
+    {
+      $query->addWhere('r.' . $fieldName . ' = ?', $values['text']);
+    }
+  }
+
+  protected function addBooleanQuery(Doctrine_Query $query, $field, $value)
+  {
+    $fieldName = $this->getFieldName($field);
+    $query->addWhere('r.' . $fieldName . ' = ?', $value);
+  }
+
+  protected function addDateQuery(Doctrine_Query $query, $field, $values)
+  {
+    $fieldName = $this->getFieldName($field);
+
+    if (isset($values['is_empty']) && $values['is_empty'])
+    {
+      $query->addWhere('r.' . $fieldName . ' IS NULL');
+    }
+    else
+    {
+      $criterion = null;
+      if (!is_null($values['from']) && !is_null($values['to']))
+      {
+        $query->andWhere('r.' . $fieldName . ' >= ?', $values['from']);
+        $query->andWhere('r.' . $fieldName . ' <= ?', $values['to']);
+      }
+      else if (!is_null($values['from']))
+      {
+        $query->andWhere('r.' . $fieldName . ' >= ?', $values['from']);
+      }
+      else if (!is_null($values['to']))
+      {
+        $query->andWhere('r.' . $fieldName . ' <= ?', $values['to']);
+      }
+    }
+  }
+
+  protected function getColName($field)
+  {
+    return $this->getTable()->getColumnName($field);
+  }
+
+  protected function getFieldName($colName)
+  {
+    return $this->getTable()->getFieldName($colName);
+  }
+
+  protected function camelize($text)
+  {
+    return sfToolkit::pregtr($text, array('#/(.?)#e' => "'::'.strtoupper('\\1')", '/(^|_|-)+(.)/e' => "strtoupper('\\2')"));
+  }
+
+  protected function getTable()
+  {
+    return Doctrine::getTable($this->getModelName());
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/generator/sfDoctrineColumn.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,309 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a Doctrine column
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineAdminColumn.class.php 12356 2008-10-23 21:54:50Z Jonathan.Wage $
+ */
+class sfDoctrineColumn implements ArrayAccess
+{
+  /**
+   * Array mapping Doctrine column types to the native symfony type
+   */
+  static $doctrineToSymfony = array(
+    'boolean'   => 'BOOLEAN',
+    'string'    => 'LONGVARCHAR',
+    'integer'   => 'INTEGER',
+    'date'      => 'DATE',
+    'timestamp' => 'TIMESTAMP',
+    'time'      => 'TIME',
+    'enum'      => 'LONGVARCHAR',
+    'float'     => 'FLOAT',
+    'double'    => 'DOUBLE',
+    'clob'      => 'CLOB',
+    'blob'      => 'BLOB',
+    'object'    => 'LONGVARCHAR',
+    'array'     => 'LONGVARCHAR',
+    'decimal'   => 'DECIMAL',
+  );
+
+  /**
+   * Store the name of the related class for this column if it is
+   * a foreign key
+   *
+   * @var string
+   */
+  protected $foreignClassName = null;
+
+  /**
+   * Doctrine_Table instance this column belongs to
+   *
+   * @var Doctrine_Table $table
+   */
+  protected $table = null;
+
+  /**
+   * Field name of the column
+   *
+   * @var string
+   */
+  protected $name = null;
+
+  /**
+   * Definition of the column
+   *
+   * @var array $definition
+   */
+  protected $definition = array();
+
+  public function __construct($name, Doctrine_Table $table)
+  {
+    $this->name = $name;
+    $this->table = $table;
+    $this->definition = $table->getDefinitionOf($name);
+  }
+
+  /**
+   * Get the name of the column
+   *
+   * @return string $name
+   */
+  public function getName()
+  {
+    return $this->table->getColumnName($this->name);
+  }
+
+  /**
+   * Get the alias/field name
+   *
+   * @return string $fieldName
+   */
+  public function getFieldName()
+  {
+    return $this->table->getFieldName($this->getName());
+  }
+
+  /**
+   * Get php name. Exists for backwards compatibility with propel orm
+   *
+   * @return string $fieldName
+   */
+  public function getPhpName()
+  {
+    return $this->getFieldName();
+  }
+
+  /**
+   * Get the Doctrine type of the column
+   *
+   * @return void
+   */
+  public function getDoctrineType()
+  {
+    return isset($this->definition['type']) ? $this->definition['type']:null;
+  }
+
+  /**
+   * Get symfony type of the column
+   *
+   * @return void
+   */
+  public function getType()
+  {
+    $doctrineType = $this->getDoctrineType();
+
+    // we simulate the CHAR/VARCHAR types to generate input_tags
+    if(($doctrineType == 'string') and ($this->getSize() < 256))
+    {
+      return 'VARCHAR';
+    }
+
+    return $doctrineType ? self::$doctrineToSymfony[$doctrineType]:'VARCHAR';
+  }
+
+  /**
+   * Get size/length of the column
+   *
+   * @return void
+   */
+  public function getSize()
+  {
+    return $this->definition['length'];
+  }
+
+  public function getLength()
+  {
+    return $this->getSize();
+  }
+
+  /**
+   * Check if the column definition has a certain key
+   *
+   * @param string $key
+   * @return bool
+   */
+  public function hasDefinitionKey($key)
+  {
+    return isset($this->definition[$key]) ? true:false;
+  }
+
+  /**
+   * Get the value of a column definition key
+   *
+   * @param string $key
+   * @return array $definition
+   */
+  public function getDefinitionKey($key)
+  {
+    if ($this->hasDefinitionKey($key))
+    {
+      return $this->definition[$key];
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * Returns true of the column is not null and false if it is null
+   *
+   * @return boolean
+   */
+  public function isNotNull()
+  {
+    if (isset($this->definition['notnull']))
+    {
+      return $this->definition['notnull'];
+    }
+    if (isset($this->definition['notblank']))
+    {
+      return $this->definition['notblank'];
+    }
+    return false;
+  }
+
+  /**
+   * Returns true if the column is a primary key and false if it is not
+   *
+   * @return void
+   */
+  public function isPrimaryKey()
+  {
+    if (isset($this->definition['primary']))
+    {
+      return $this->definition['primary'];
+    }
+    return false;
+  }
+
+  /**
+   * Returns true if this column is a foreign key and false if it is not
+   *
+   * @return boolean $isForeignKey
+   */
+  public function isForeignKey()
+  {
+    if (isset($this->foreignClassName))
+    {
+      return true;
+    }
+
+    if ($this->isPrimaryKey())
+    {
+      return false;
+    }
+
+    foreach ($this->table->getRelations() as $relation)
+    {
+      if (strtolower($relation['local']) == strtolower($this->name))
+      {
+        $this->foreignClassName = $relation['class'];
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Get the name of the related class for this column foreign key.
+   *
+   * @return string $foreignClassName
+   */
+  public function getForeignClassName()
+  {
+    if ($this->isForeignKey())
+    {
+      return $this->foreignClassName;
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * If foreign key get the related Doctrine_Table object
+   *
+   * @return Doctrine_Table $table
+   */
+  public function getForeignTable()
+  {
+    if ($this->isForeignKey())
+    {
+      return Doctrine::getTable($this->foreignClassName);
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * Set the Doctrine_Table object this column belongs to
+   *
+   * @param Doctrine_Table $table
+   * @return void
+   */
+  public function setTable(Doctrine_Table $table)
+  {
+    $this->table = $table;
+  }
+
+  /**
+   * Get the Doctrine_Table object this column belongs to
+   *
+   * @return Doctrine_Table $table
+   */
+  public function getTable()
+  {
+    return $this->table;
+  }
+
+  public function offsetExists($offset)
+  {
+    return isset($this->definition[$offset]);
+  }
+
+  public function offsetSet($offset, $value)
+  {
+    $this->definition[$offset] = $value;
+  }
+
+  public function offsetGet($offset)
+  {
+    return $this->definition[$offset];
+  }
+
+  public function offsetUnset($offset)
+  {
+    unset($this->definition[$offset]);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/generator/sfDoctrineFormFilterGenerator.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,334 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Doctrine filter form generator.
+ *
+ * This class generates a Doctrine filter forms.
+ *
+ * @package    symfony
+ * @subpackage generator
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: sfDoctrineFormFilterGenerator.class.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class sfDoctrineFormFilterGenerator extends sfDoctrineFormGenerator
+{
+  /**
+   * Initializes the current sfGenerator instance.
+   *
+   * @param sfGeneratorManager $generatorManager A sfGeneratorManager instance
+   */
+  public function initialize(sfGeneratorManager $generatorManager)
+  {
+    parent::initialize($generatorManager);
+
+    $this->setGeneratorClass('sfDoctrineFormFilter');
+  }
+
+  /**
+   * Generates classes and templates in cache.
+   *
+   * @param array $params The parameters
+   *
+   * @return string The data to put in configuration cache
+   */
+  public function generate($params = array())
+  {
+    $this->params = $params;
+
+    if (!isset($this->params['connection']))
+    {
+      throw new sfParseException('You must specify a "connection" parameter.');
+    }
+
+    if (!isset($this->params['model_dir_name']))
+    {
+      $this->params['model_dir_name'] = 'model';
+    }
+
+    if (!isset($this->params['filter_dir_name']))
+    {
+      $this->params['filter_dir_name'] = 'filter';
+    }
+
+    $models = $this->loadModels();
+
+    // create the project base class for all forms
+    $file = sfConfig::get('sf_lib_dir').'/filter/doctrine/BaseFormFilterDoctrine.class.php';
+    if (!file_exists($file))
+    {
+      if (!is_dir(sfConfig::get('sf_lib_dir').'/filter/doctrine/base'))
+      {
+        mkdir(sfConfig::get('sf_lib_dir').'/filter/doctrine/base', 0777, true);
+      }
+
+      file_put_contents($file, $this->evalTemplate('sfDoctrineFormFilterBaseTemplate.php'));
+    }
+
+    $pluginPaths = $this->generatorManager->getConfiguration()->getAllPluginPaths();
+
+    // create a form class for every Doctrine class
+    foreach ($models as $model)
+    {
+      $this->table = Doctrine::getTable($model);
+      $this->modelName = $model;
+
+      $baseDir = sfConfig::get('sf_lib_dir') . '/filter/doctrine';
+
+      $isPluginModel = $this->isPluginModel($model);
+      if ($isPluginModel)
+      {
+        $pluginName = $this->getPluginNameForModel($model);
+        $baseDir .= '/' . $pluginName;
+      }
+
+      if (!is_dir($baseDir.'/base'))
+      {
+        mkdir($baseDir.'/base', 0777, true);
+      }
+
+      file_put_contents($baseDir.'/base/Base'.$model.'FormFilter.class.php', $this->evalTemplate('sfDoctrineFormFilterGeneratedTemplate.php'));
+      if ($isPluginModel)
+      {
+        $pluginBaseDir = $pluginPaths[$pluginName].'/lib/filter/doctrine';
+        if (!file_exists($classFile = $pluginBaseDir.'/Plugin'.$model.'FormFilter.class.php'))
+        {
+            if (!is_dir($pluginBaseDir))
+            {
+              mkdir($pluginBaseDir, 0777, true);
+            }
+            file_put_contents($classFile, $this->evalTemplate('sfDoctrineFormFilterPluginTemplate.php'));
+        }
+      }
+      if (!file_exists($classFile = $baseDir.'/'.$model.'FormFilter.class.php'))
+      {
+        if ($isPluginModel)
+        {
+           file_put_contents($classFile, $this->evalTemplate('sfDoctrinePluginFormFilterTemplate.php'));
+        } else {
+           file_put_contents($classFile, $this->evalTemplate('sfDoctrineFormFilterTemplate.php'));
+        }
+      }
+    }
+  }
+
+  /**
+   * Returns a sfWidgetForm class name for a given column.
+   *
+   * @param  sfDoctrineColumn $column
+   * @return string    The name of a subclass of sfWidgetForm
+   */
+  public function getWidgetClassForColumn($column)
+  {
+    switch ($column->getDoctrineType())
+    {
+      case 'boolean':
+        $name = 'Choice';
+        break;
+      case 'date':
+      case 'datetime':
+      case 'timestamp':
+        $name = 'FilterDate';
+        break;
+      case 'enum':
+        $name = 'Choice';
+        break;
+      default:
+        $name = 'FilterInput';
+    }
+
+    if ($column->isForeignKey())
+    {
+      $name = 'DoctrineChoice';
+    }
+
+    return sprintf('sfWidgetForm%s', $name);
+  }
+
+  /**
+   * Returns a PHP string representing options to pass to a widget for a given column.
+   *
+   * @param  sfDoctrineColumn $column
+   * @return string    The options to pass to the widget as a PHP string
+   */
+  public function getWidgetOptionsForColumn($column)
+  {
+    $options = array();
+
+    $withEmpty = sprintf('\'with_empty\' => %s', $column->isNotNull() ? 'false' : 'true');
+    switch ($column->getDoctrineType())
+    {
+      case 'boolean':
+        $options[] = "'choices' => array('' => 'yes or no', 1 => 'yes', 0 => 'no')";
+        break;
+      case 'date':
+      case 'datetime':
+      case 'timestamp':
+        $options[] = "'from_date' => new sfWidgetFormDate(), 'to_date' => new sfWidgetFormDate()";
+        $options[] = $withEmpty;
+        break;
+      case 'enum':
+        $values = array('' => '');
+        $values = array_merge($values, $column['values']);
+        $values = array_combine($values, $values);
+        $options[] = "'choices' => " . str_replace("\n", '', $this->arrayExport($values));
+        break;
+    }
+
+    if ($column->isForeignKey())
+    {
+      $options[] = sprintf('\'model\' => \'%s\', \'add_empty\' => true', $column->getForeignTable()->getOption('name'));
+    }
+
+    return count($options) ? sprintf('array(%s)', implode(', ', $options)) : '';
+  }
+
+  /**
+   * Returns a sfValidator class name for a given column.
+   *
+   * @param  sfDoctrineColumn $column
+   * @return string    The name of a subclass of sfValidator
+   */
+  public function getValidatorClassForColumn($column)
+  {
+    switch ($column->getDoctrineType())
+    {
+      case 'boolean':
+        $name = 'Choice';
+        break;
+      case 'float':
+      case 'decimal':
+        $name = 'Number';
+        break;
+      case 'integer':
+        $name = 'Integer';
+        break;
+      case 'date':
+      case 'datetime':
+      case 'timestamp':
+        $name = 'DateRange';
+        break;
+      case 'enum':
+        $name = 'Choice';
+        break;
+      default:
+        $name = 'Pass';
+    }
+
+    if ($column->isPrimarykey() || $column->isForeignKey())
+    {
+      $name = 'DoctrineChoice';
+    }
+
+    return sprintf('sfValidator%s', $name);
+  }
+
+  /**
+   * Returns a PHP string representing options to pass to a validator for a given column.
+   *
+   * @param  sfDoctrineColumn $column
+   * @return string    The options to pass to the validator as a PHP string
+   */
+  public function getValidatorOptionsForColumn($column)
+  {
+    $options = array('\'required\' => false');
+
+    if ($column->isForeignKey())
+    {
+      $columns = $column->getForeignTable()->getColumns();
+      foreach ($columns as $name => $col)
+      {
+        if (isset($col['primary']) && $col['primary'])
+        {
+          break;
+        }
+      }
+
+      $options[] = sprintf('\'model\' => \'%s\', \'column\' => \'%s\'', $column->getForeignTable()->getOption('name'), $column->getForeignTable()->getFieldName($name));
+    }
+    else if ($column->isPrimaryKey())
+    {
+      $options[] = sprintf('\'model\' => \'%s\', \'column\' => \'%s\'', $this->table->getOption('name'), $this->table->getFieldName($columnName));
+    }
+    else
+    {
+      switch ($column->getDoctrineType())
+      {
+        case 'boolean':
+          $options[] = "'choices' => array('', 1, 0)";
+          break;
+        case 'date':
+        case 'datetime':
+        case 'timestamp':
+          $options[] = "'from_date' => new sfValidatorDate(array('required' => false)), 'to_date' => new sfValidatorDate(array('required' => false))";
+          break;
+        case 'enum':
+          $values = array_combine($column['values'], $column['values']);
+          $options[] = "'choices' => " . str_replace("\n", '', $this->arrayExport($values));
+          break;
+      }
+    }
+
+    return count($options) ? sprintf('array(%s)', implode(', ', $options)) : '';
+  }
+
+  public function getValidatorForColumn($column)
+  {
+    $format = 'new %s(%s)';
+    if (in_array($class = $this->getValidatorClassForColumn($column), array('sfValidatorInteger', 'sfValidatorNumber')))
+    {
+      $format = 'new sfValidatorSchemaFilter(\'text\', new %s(%s))';
+    }
+
+    return sprintf($format, $class, $this->getValidatorOptionsForColumn($column));
+  }
+
+  public function getType($column)
+  {
+    if ($column->isForeignKey())
+    {
+      return 'ForeignKey';
+    }
+
+    switch ($column->getDoctrineType())
+    {
+      case 'enum':
+        return 'Enum';
+      case 'boolean':
+        return 'Boolean';
+      case 'date':
+      case 'datetime':
+      case 'timestamp':
+        return 'Date';
+      case 'integer':
+      case 'decimal':
+      case 'float':
+        return 'Number';
+      default:
+        return 'Text';
+    }
+  }
+
+  /**
+   * Array export. Export array to formatted php code
+   *
+   * @param array $values
+   * @return string $php
+   */
+  protected function arrayExport($values)
+  {
+    $php = var_export($values, true);
+    $php = str_replace("\n", '', $php);
+    $php = str_replace('array (  ', 'array(', $php);
+    $php = str_replace(',)', ')', $php);
+    $php = str_replace('  ', ' ', $php);
+    return $php;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/generator/sfDoctrineFormGenerator.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,624 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Doctrine form generator.
+ *
+ * This class generates a Doctrine forms.
+ *
+ * @package    symfony
+ * @subpackage generator
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineFormGenerator.class.php 8512 2008-04-17 18:06:12Z fabien $
+ */
+class sfDoctrineFormGenerator extends sfGenerator
+{
+  /**
+   * Array of all the loaded models
+   *
+   * @var array
+   */
+  public $models = array();
+
+  /**
+   * Array of all plugin models
+   *
+   * @var array
+   */
+  public $pluginModels = array();
+
+  /**
+   * Initializes the current sfGenerator instance.
+   *
+   * @param sfGeneratorManager A sfGeneratorManager instance
+   */
+  public function initialize(sfGeneratorManager $generatorManager)
+  {
+    parent::initialize($generatorManager);
+
+    $this->getPluginModels();
+    $this->setGeneratorClass('sfDoctrineForm');
+  }
+
+  /**
+   * Generates classes and templates in cache.
+   *
+   * @param array The parameters
+   *
+   * @return string The data to put in configuration cache
+   */
+  public function generate($params = array())
+  {
+    $this->params = $params;
+
+    if (!isset($this->params['connection']))
+    {
+      throw new sfParseException('You must specify a "connection" parameter.');
+    }
+
+    if (!isset($this->params['model_dir_name']))
+    {
+      $this->params['model_dir_name'] = 'model';
+    }
+
+    if (!isset($this->params['form_dir_name']))
+    {
+      $this->params['form_dir_name'] = 'form';
+    }
+
+    $models = $this->loadModels();
+
+    // create the project base class for all forms
+    $file = sfConfig::get('sf_lib_dir').'/form/doctrine/BaseFormDoctrine.class.php';
+    if (!file_exists($file))
+    {
+      if (!is_dir(sfConfig::get('sf_lib_dir').'/form/doctrine/base'))
+      {
+        mkdir(sfConfig::get('sf_lib_dir').'/form/doctrine/base', 0777, true);
+      }
+
+      file_put_contents($file, $this->evalTemplate('sfDoctrineFormBaseTemplate.php'));
+    }
+
+    $pluginPaths = $this->generatorManager->getConfiguration()->getAllPluginPaths();
+
+    // create a form class for every Doctrine class
+    foreach ($models as $model)
+    {
+      $this->table = Doctrine::getTable($model);
+      $this->modelName = $model;
+
+      $baseDir = sfConfig::get('sf_lib_dir') . '/form/doctrine';
+
+      $isPluginModel = $this->isPluginModel($model);
+      if ($isPluginModel)
+      {
+        $pluginName = $this->getPluginNameForModel($model);
+        $baseDir .= '/' . $pluginName;
+      }
+
+      if (!is_dir($baseDir.'/base'))
+      {
+        mkdir($baseDir.'/base', 0777, true);
+      }
+
+      file_put_contents($baseDir.'/base/Base'.$model.'Form.class.php', $this->evalTemplate('sfDoctrineFormGeneratedTemplate.php'));
+      if ($isPluginModel)
+      {
+        $pluginBaseDir = $pluginPaths[$pluginName].'/lib/form/doctrine';
+        if (!file_exists($classFile = $pluginBaseDir.'/Plugin'.$model.'Form.class.php'))
+        {
+            if (!is_dir($pluginBaseDir))
+            {
+              mkdir($pluginBaseDir, 0777, true);
+            }
+            file_put_contents($classFile, $this->evalTemplate('sfDoctrineFormPluginTemplate.php'));
+        }
+      }
+      if (!file_exists($classFile = $baseDir.'/'.$model.'Form.class.php'))
+      {
+        if ($isPluginModel)
+        {
+           file_put_contents($classFile, $this->evalTemplate('sfDoctrinePluginFormTemplate.php'));
+        } else {
+           file_put_contents($classFile, $this->evalTemplate('sfDoctrineFormTemplate.php'));
+        }
+      }
+    }
+  }
+
+  /**
+   * Get all the models which are a part of a plugin and the name of the plugin.
+   * The array format is modelName => pluginName
+   *
+   * @todo This method is ugly and is a very weird way of finding the models which 
+   *       belong to plugins. If we could come up with a better way that'd be great
+   * @return array $pluginModels
+   */
+  public function getPluginModels()
+  {
+    if (!$this->pluginModels)
+    {
+      $plugins     = $this->generatorManager->getConfiguration()->getPlugins();
+      $pluginPaths = $this->generatorManager->getConfiguration()->getAllPluginPaths();
+
+      foreach ($pluginPaths as $pluginName => $path)
+      {
+        if (!in_array($pluginName, $plugins))
+        {
+          continue;
+        }
+
+        foreach (sfFinder::type('file')->name('*.php')->in($path.'/lib/model/doctrine') as $path)
+        {
+          $info = pathinfo($path);
+          $e = explode('.', $info['filename']);
+          $modelName = substr($e[0], 6, strlen($e[0]));
+
+          if (class_exists($e[0]) && class_exists($modelName))
+          {
+            $parent = new ReflectionClass('Doctrine_Record');
+            $reflection = new ReflectionClass($modelName);
+            if ($reflection->isSubClassOf($parent))
+            {
+              $this->pluginModels[$modelName] = $pluginName;
+              $generators = Doctrine::getTable($modelName)->getGenerators();
+              foreach ($generators as $generator)
+              {
+                $this->pluginModels[$generator->getOption('className')] = $pluginName;
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return $this->pluginModels;
+  }
+
+  /**
+   * Check to see if a model is part of a plugin
+   *
+   * @param string $modelName 
+   * @return boolean $bool
+   */
+  public function isPluginModel($modelName)
+  {
+    return isset($this->pluginModels[$modelName]) ? true:false;
+  }
+
+  /**
+   * Get the name of the plugin a model belongs to
+   *
+   * @param string $modelName 
+   * @return string $pluginName
+   */
+  public function getPluginNameForModel($modelName)
+  {
+    if ($this->isPluginModel($modelName))
+    {
+      return $this->pluginModels[$modelName];
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * Returns an array of relations that represents a many to many relationship.
+   *
+   * A table is considered to be a m2m table if it has 2 foreign keys that are also primary keys.
+   *
+   * @return array An array of relations.
+   */
+  public function getManyToManyRelations()
+  {
+    $relations = array();
+    foreach ($this->table->getRelations() as $relation)
+    {
+      if ($relation->getType() === Doctrine_Relation::MANY && isset($relation['refTable']))
+      {
+        $relations[] = $relation;
+      }
+    }
+    return $relations;
+  }
+
+  /**
+   * Returns PHP names for all foreign keys of the current table.
+   *
+   * This method does not returns foreign keys that are also primary keys.
+   *
+   * @return array An array composed of: 
+   *                 * The foreign table PHP name
+   *                 * The foreign key PHP name
+   *                 * A Boolean to indicate whether the column is required or not
+   *                 * A Boolean to indicate whether the column is a many to many relationship or not
+   */
+  public function getForeignKeyNames()
+  {
+    $names = array();
+    foreach ($this->table->getRelations() as $relation)
+    {
+      if ($relation->getType() === Doctrine_Relation::ONE)
+      {
+        $foreignDef = $relation->getTable()->getDefinitionOf($relation->getForeignFieldName());
+        $names[] = array($relation['table']->getOption('name'), $relation->getForeignFieldName(), $this->isColumnNotNull($relation->getForeignFieldName(), $foreignDef), false);
+      }
+    }
+
+    foreach ($this->getManyToManyRelations() as $relation)
+    {
+      $names[] = array($relation['table']->getOption('name'), $relation['alias'], false, true);
+    }
+
+    return $names;
+  }
+
+  /**
+   * Returns the first primary key column of the current table.
+   *
+   * @param ColumnMap A ColumnMap object
+   */
+  public function getPrimaryKey()
+  {
+    foreach ($this->getColumns() as $column)
+    {
+      if ($column->isPrimaryKey())
+      {
+        return $column;
+      }
+    }
+  }
+
+  /**
+   * Returns a sfWidgetForm class name for a given column.
+   *
+   * @param  sfDoctrineColumn $column
+   * @return string    The name of a subclass of sfWidgetForm
+   */
+  public function getWidgetClassForColumn($column)
+  {
+    switch ($column->getDoctrineType())
+    {
+      case 'string':
+        if ($column->getLength() > 255)
+        {
+          $widgetSubclass = 'Textarea';
+        } else {
+          $widgetSubclass = 'Input';
+        }
+        break;
+      case 'boolean':
+        $widgetSubclass = 'InputCheckbox';
+        break;
+      case 'blob':
+      case 'clob':
+        $widgetSubclass = 'Textarea';
+        break;
+      case 'date':
+        $widgetSubclass = 'Date';
+        break;
+      case 'time':
+        $widgetSubclass = 'Time';
+        break;
+      case 'timestamp':
+        $widgetSubclass = 'DateTime';
+        break;
+      case 'enum':
+        $widgetSubclass = 'Choice';
+        break;
+      default:
+        $widgetSubclass = 'Input';
+    }
+
+    if ($column->isPrimaryKey())
+    {
+      $widgetSubclass = 'InputHidden';
+    }
+    else if ($column->isForeignKey())
+    {
+      $widgetSubclass = 'DoctrineChoice';
+    }
+
+    return sprintf('sfWidgetForm%s', $widgetSubclass);
+  }
+
+  /**
+   * Returns a PHP string representing options to pass to a widget for a given column.
+   *
+   * @param  sfDoctrineColumn $column
+   * @return string    The options to pass to the widget as a PHP string
+   */
+  public function getWidgetOptionsForColumn($column)
+  {
+    $options = array();
+
+    if ($column->isForeignKey())
+    {
+      $options[] = sprintf('\'model\' => \'%s\', \'add_empty\' => %s', $column->getForeignTable()->getOption('name'), $column->isNotNull() ? 'false' : 'true');
+    }
+    else
+    {
+      switch ($column->getDoctrineType())
+      {
+        case 'enum':
+          $values = $column->getDefinitionKey('values');
+          $values = array_combine($values, $values);
+          $options[] = "'choices' => " . str_replace("\n", '', $this->arrayExport($values));
+          break;
+      }
+    }
+
+    return count($options) ? sprintf('array(%s)', implode(', ', $options)) : '';
+  }
+
+  /**
+   * Returns a sfValidator class name for a given column.
+   *
+   * @param sfDoctrineColumn $column
+   * @return string    The name of a subclass of sfValidator
+   */
+  public function getValidatorClassForColumn($column)
+  {
+    switch ($column->getDoctrineType())
+    {
+      case 'boolean':
+        $validatorSubclass = 'Boolean';
+        break;
+      case 'string':
+    		if ($column->getDefinitionKey('email'))
+    		{
+    		  $validatorSubclass = 'Email';
+    		}
+    		else if ($column->getDefinitionKey('regexp'))
+    		{
+    		  $validatorSubclass = 'Regex';
+    		}
+    		else
+    		{
+    		  $validatorSubclass = 'String';
+    		}
+        break;
+      case 'clob':
+      case 'blob':
+        $validatorSubclass = 'String';
+        break;
+      case 'float':
+      case 'decimal':
+        $validatorSubclass = 'Number';
+        break;
+      case 'integer':
+        $validatorSubclass = 'Integer';
+        break;
+      case 'date':
+        $validatorSubclass = 'Date';
+        break;
+      case 'time':
+        $validatorSubclass = 'Time';
+        break;
+      case 'timestamp':
+        $validatorSubclass = 'DateTime';
+        break;
+      case 'enum':
+        $validatorSubclass = 'Choice';
+        break;
+      default:
+        $validatorSubclass = 'Pass';
+    }
+
+    if ($column->isPrimaryKey() || $column->isForeignKey())
+    {
+      $validatorSubclass = 'DoctrineChoice';
+    }
+
+    return sprintf('sfValidator%s', $validatorSubclass);
+  }
+
+  /**
+   * Returns a PHP string representing options to pass to a validator for a given column.
+   *
+   * @param sfDoctrineColumn $column
+   * @return string    The options to pass to the validator as a PHP string
+   */
+  public function getValidatorOptionsForColumn($column)
+  {
+    $options = array();
+
+    if ($column->isForeignKey())
+    {
+      $options[] = sprintf('\'model\' => \'%s\'', $column->getForeignTable()->getOption('name'));
+    }
+    else if ($column->isPrimaryKey())
+    {
+      $options[] = sprintf('\'model\' => \'%s\', \'column\' => \'%s\'', $this->modelName, $column->getName());
+    }
+    else
+    {
+      switch ($column->getDoctrineType())
+      {
+        case 'string':
+          if ($column['length'])
+          {
+            $options[] = sprintf('\'max_length\' => %s', $column['length']);
+          }
+          if (isset($column['minlength']))
+          {
+            $options[] = sprintf('\'min_length\' => %s', $column['minlength']);
+          }
+          if (isset($column['regexp']))
+          {
+            $options[] = sprintf('\'pattern\' => \'%s\'', $column['regexp']);
+          }
+          break;
+        case 'enum':
+          $values = array_combine($column['values'], $column['values']);
+          $options[] = "'choices' => " . str_replace("\n", '', $this->arrayExport($values));
+          break;
+      }
+    }
+
+    if (!$column->isNotNull() || $column->isPrimaryKey())
+    {
+      $options[] = '\'required\' => false';
+    }
+
+    return count($options) ? sprintf('array(%s)', implode(', ', $options)) : '';
+  }
+
+  /**
+   * Returns the maximum length for a column name.
+   *
+   * @return integer The length of the longer column name
+   */
+  public function getColumnNameMaxLength()
+  {
+    $max = 0;
+    foreach ($this->getColumns() as $column)
+    {
+      if (($m = strlen($column->getFieldName())) > $max)
+      {
+        $max = $m;
+      }
+    }
+
+    foreach ($this->getManyToManyRelations() as $relation)
+    {
+      if (($m = strlen($this->underscore($relation['alias']).'_list')) > $max)
+      {
+        $max = $m;
+      }
+    }
+
+    return $max;
+  }
+
+  /**
+   * Returns an array of primary key column names.
+   *
+   * @return array An array of primary key column names
+   */
+  public function getPrimaryKeyColumNames()
+  {
+    return $this->table->getIdentifierColumnNames();
+  }
+
+  /**
+   * Returns a PHP string representation for the array of all primary key column names.
+   *
+   * @return string A PHP string representation for the array of all primary key column names
+   *
+   * @see getPrimaryKeyColumNames()
+   */
+  public function getPrimaryKeyColumNamesAsString()
+  {
+    return sprintf('array(\'%s\')', implode('\', \'', $this->getPrimaryKeyColumNames()));
+  }
+
+  /**
+   * Returns true if the current table is internationalized.
+   *
+   * @return Boolean true if the current table is internationalized, false otherwise
+   */
+  public function isI18n()
+  {
+    return $this->table->hasRelation('Translation');
+  }
+
+  /**
+   * Returns the i18n model name for the current table.
+   *
+   * @return string The model class name
+   */
+  public function getI18nModel()
+  {
+    return $this->table->getRelation('Translation')->getTable()->create();
+  }
+
+  public function underscore($name)
+  {
+    return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), '\\1_\\2', $name));
+  }
+
+  /**
+   * Get array of sfDoctrineColumn objects
+   *
+   * @return array $columns
+   */
+  public function getColumns()
+  {
+    foreach (array_keys($this->table->getColumns()) as $name)
+    {
+      $columns[] = new sfDoctrineColumn($name, $this->table);
+    }
+
+    return $columns;
+  }
+
+  public function getUniqueColumnNames()
+  {
+    $uniqueColumns = array();
+
+    foreach ($this->getColumns() as $column)
+    {
+      if ($column->getDefinitionKey('unique'))
+      {
+        $uniqueColumns[] = array($column->getName());
+      }
+    }
+
+    $indexes = $this->table->getOption('indexes');
+    foreach ($indexes as $name => $index)
+    {
+      if (isset($index['type']) && $index['type'] == 'unique')
+      {
+        $tmp = $index['fields'];
+        if (is_array(array_shift($tmp)))
+        {
+          $uniqueColumns[] = array_keys($index['fields']);
+        } else {
+          $uniqueColumns[] = $index['fields'];
+        }
+      }
+    }
+
+    return $uniqueColumns;
+  }
+
+  /**
+   * Loads all Doctrine builders.
+   */
+  protected function loadModels()
+  {
+    Doctrine::loadModels($this->generatorManager->getConfiguration()->getModelDirs(),
+                                   Doctrine::MODEL_LOADING_CONSERVATIVE);
+    $models = Doctrine::getLoadedModels();
+    $models =  Doctrine::initializeModels($models);
+    $this->models = Doctrine::filterInvalidModels($models);
+    return $this->models;
+  }
+
+  /**
+   * Array export. Export array to formatted php code
+   *
+   * @param array $values
+   * @return string $php
+   */
+  protected function arrayExport($values)
+  {
+    $php = var_export($values, true);
+    $php = str_replace("\n", '', $php);
+    $php = str_replace('array (  ', 'array(', $php);
+    $php = str_replace(',)', ')', $php);
+    $php = str_replace('  ', ' ', $php);
+    return $php;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/generator/sfDoctrineGenerator.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,282 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Doctrine generator.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: sfDoctrineGenerator.class.php 12507 2008-10-31 18:26:58Z fabien $
+ */
+class sfDoctrineGenerator extends sfModelGenerator
+{
+  protected
+    $table = null;
+
+  /**
+   * Initializes the current sfGenerator instance.
+   *
+   * @param sfGeneratorManager $generatorManager A sfGeneratorManager instance
+   */
+  public function initialize(sfGeneratorManager $generatorManager)
+  {
+    parent::initialize($generatorManager);
+
+    $this->setGeneratorClass('sfDoctrineModule');
+  }
+
+  /** 
+   * Configures this generator.
+   */
+  public function configure()
+  {
+    $this->table = Doctrine::getTable($this->modelClass);
+
+    // load all primary keys
+    $this->loadPrimaryKeys();
+  }
+
+  /**
+   * Returns an array of tables that represents a many to many relationship.
+   *
+   * A table is considered to be a m2m table if it has 2 foreign keys that are also primary keys.
+   *
+   * @return array An array of tables.
+   */
+  public function getManyToManyTables()
+  {
+    $relations = array();
+    foreach ($this->table->getRelations() as $relation)
+    {
+      if ($relation->getType() === Doctrine_Relation::MANY && isset($relation['refTable']))
+      {
+        $relations[] = $relation;
+      }
+    }
+    return $relations;
+  }
+
+  /**
+   * Loads primary keys.
+   *
+   * @throws sfException
+   */
+  protected function loadPrimaryKeys()
+  {
+    $this->primaryKey = array();
+    foreach ($this->getColumns() as $name => $column)
+    {
+      if ($column->isPrimaryKey())
+      {
+        $this->primaryKey[] = $name;
+      }
+    }
+
+    if (!count($this->primaryKey))
+    {
+      throw new sfException(sprintf('Cannot generate a module for a model without a primary key (%s)', $this->modelClass));
+    }
+  }
+
+  /**
+   * Returns the getter either non-developped: 'getFoo' or developped: '$class->getFoo()'.
+   *
+   * @param string  $column     The column name
+   * @param boolean $developed  true if you want developped method names, false otherwise
+   * @param string  $prefix     The prefix value
+   *
+   * @return string PHP code
+   */
+  public function getColumnGetter($column, $developed = false, $prefix = '')
+  {
+    $getter = 'get'.sfInflector::camelize($column);
+    if ($developed)
+    {
+      $getter = sprintf('$%s%s->%s()', $prefix, $this->getSingularName(), $getter);
+    }
+
+    return $getter;
+  }
+
+  /**
+   * Returns the type of a column.
+   *
+   * @param  object $column A column object
+   *
+   * @return string The column type
+   */
+  public function getType($column)
+  {
+    if ($column->isForeignKey())
+    {
+      return 'ForeignKey';
+    }
+
+    switch ($column->getDoctrineType())
+    {
+      case 'enum':
+        return 'Enum';
+      case 'boolean':
+        return 'Boolean';
+      case 'date':
+      case 'timestamp':
+        return 'Date';
+      case 'time':
+        return 'Time';
+      default:
+        return 'Text';
+    }
+  }
+
+  /**
+   * Returns the default configuration for fields.
+   *
+   * @return array An array of default configuration for all fields
+   */
+  public function getDefaultFieldsConfiguration()
+  {
+    $fields = array();
+
+    $names = array();
+    foreach ($this->getColumns() as $name => $column)
+    {
+      $names[] = $name;
+      $fields[$name] = array_merge(array(
+        'is_link'      => (Boolean) $column->isPrimaryKey(),
+        'is_real'      => true,
+        'is_partial'   => false,
+        'is_component' => false,
+        'type'         => $this->getType($column),
+      ), isset($this->config['fields'][$name]) ? $this->config['fields'][$name] : array());
+    }
+
+    foreach ($this->getManyToManyTables() as $tables)
+    {
+      $name = sfInflector::underscore($tables['alias']).'_list';
+      $names[] = $name;
+      $fields[$name] = array_merge(array(
+        'is_link'      => false,
+        'is_real'      => false,
+        'is_partial'   => false,
+        'is_component' => false,
+        'type'         => 'Text',
+      ), isset($this->config['fields'][$name]) ? $this->config['fields'][$name] : array());
+    }
+
+    if (isset($this->config['fields']))
+    {
+      foreach ($this->config['fields'] as $name => $params)
+      {
+        if (in_array($name, $names))
+        {
+          continue;
+        }
+
+        $fields[$name] = array_merge(array(
+          'is_link'      => false,
+          'is_real'      => false,
+          'is_partial'   => false,
+          'is_component' => false,
+          'type'         => 'Text',
+        ), is_array($params) ? $params : array());
+      }
+    }
+
+    unset($this->config['fields']);
+
+    return $fields;
+  }
+
+  /**
+   * Returns the configuration for fields in a given context.
+   *
+   * @param  string $context The Context
+   *
+   * @return array An array of configuration for all the fields in a given context 
+   */
+  public function getFieldsConfiguration($context)
+  {
+    $fields = array();
+
+    $names = array();
+    foreach ($this->getColumns() as $name => $column)
+    {
+      $names[] = $name;
+      $fields[$name] = isset($this->config[$context]['fields'][$name]) ? $this->config[$context]['fields'][$name] : array();
+    }
+
+    foreach ($this->getManyToManyTables() as $tables)
+    {
+      $name = sfInflector::underscore($tables['alias']).'_list';
+      $names[] = $name;
+      $fields[$name] = isset($this->config[$context]['fields'][$name]) ? $this->config[$context]['fields'][$name] : array();
+    }
+
+    if (isset($this->config[$context]['fields']))
+    {
+      foreach ($this->config[$context]['fields'] as $name => $params)
+      {
+        if (in_array($name, $names))
+        {
+          continue;
+        }
+
+        $fields[$name] = is_array($params) ? $params : array();
+      }
+    }
+
+    unset($this->config[$context]['fields']);
+
+    return $fields;
+  }
+
+  /**
+   * Gets all the fields for the current model.
+   *
+   * @param  Boolean $withM2M Whether to include m2m fields or not
+   *
+   * @return array   An array of field names
+   */
+  public function getAllFieldNames($withM2M = true)
+  {
+    $names = array();
+    foreach ($this->getColumns() as $name => $column)
+    {
+      $names[] = $name;
+    }
+
+    if ($withM2M)
+    {
+      foreach ($this->getManyToManyTables() as $tables)
+      {
+        $names[] = sfInflector::underscore($tables['alias']).'_list';
+      }
+    }
+
+    return $names;
+  }
+
+  /**
+   * Get array of sfDoctrineAdminColumn objects
+   *
+   * @return array $columns
+   */
+  public function getColumns()
+  {
+    foreach (array_keys($this->table->getColumns()) as $name)
+    {
+      $name = $this->table->getFieldName($name);
+      $columns[$name] = new sfDoctrineColumn($name, $this->table);
+    }
+
+    return $columns;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/helper/ObjectDoctrineAdminHelper.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,122 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * ObjectHelper for doctrine admin generator.
+ *
+ * @package    sfDoctrinePlugin
+ * @subpackage helper
+ * @author     Olivier Verdier <Olivier.Verdier@gmail.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: ObjectDoctrineAdminHelper.php 12089 2008-10-08 20:23:25Z Jonathan.Wage $
+ */
+
+sfLoader::loadHelpers(array('ObjectAdmin'));
+
+/**
+ * object_doctrine_admin_double_list
+ *
+ * @param string $object 
+ * @param string $method 
+ * @param string $options 
+ * @return void
+ */
+function object_doctrine_admin_double_list($object, $method, $options = array())
+{
+  return object_admin_double_list($object, $method, $options, '_get_doctrine_object_list');
+}
+
+/**
+ * object_doctrine_admin_select_list
+ *
+ * @param string $object 
+ * @param string $method 
+ * @param string $options 
+ * @return void
+ */
+function object_doctrine_admin_select_list($object, $method, $options = array())
+{
+  return object_admin_select_list($object, $method, $options, '_get_doctrine_object_list');
+}
+
+/**
+ * object_doctrine_admin_check_list
+ *
+ * @param string $object 
+ * @param string $method 
+ * @param string $options 
+ * @return void
+ */
+function object_doctrine_admin_check_list($object, $method, $options = array())
+{
+  return object_admin_check_list($object, $method, $options, '_get_doctrine_object_list');
+}
+
+/**
+ * _get_doctrine_object_list
+ *
+ * @param string $object 
+ * @param string $method 
+ * @param string $options 
+ * @return void
+ */
+function _get_doctrine_object_list($object, $method, $options)
+{
+  $foreignTable = $object->getTable()->getRelation($method[1][0])->getTable();
+  $foreignClass = $foreignTable->getComponentName();
+
+  if (isset($options['dql']))
+  {
+    $dql = $options['dql'];
+    unset($options['dql']); # Otherwise it will show up in the html
+
+    $allObjects = $foreignTable->findByDQL($dql);
+  } else if (isset($options['table_method'])) {
+    $throughTable = $object->getTable()->getRelation($options['through_class'])->getTable();
+    $peerMethod = $options['table_method'];
+    $allObjects = $throughTable->$peerMethod();
+  } else {
+    $allObjects = $foreignTable->findAll();
+  }
+
+  $associatedObjects = $object->get($method[1][0]);
+  
+  $ids = array();
+  foreach ($associatedObjects as $associatedObject)
+  {
+    $ids[] = $associatedObject->identifier();
+  }
+
+  if ($associatedObjects instanceof Doctrine_Collection && $associatedObjects->count() === 0)
+  {
+    $associatedObjects = null;
+  }
+ 
+  return array($allObjects, $associatedObjects, $ids);
+}
+
+/**
+ * object_enum_tag
+ *
+ * @param string $object 
+ * @param string $method 
+ * @param string $options 
+ * @return void
+ */
+function object_enum_tag($object, $method, $options)
+{
+  $enumValues = _get_option($options, 'enumValues', array());
+  $currentValue = _get_object_value($object, $method);
+  $enumValues = array_combine($enumValues, $enumValues);
+  
+  return select_tag(_convert_method_to_name($method, $options), options_for_select($enumValues, $currentValue), $options);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/log/sfDoctrineLogger.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,146 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Logs queries to file and web debug toolbar
+ *
+ * @package    symfony
+ * @package    doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineLogger.class.php 8938 2008-05-14 01:52:35Z Jonathan.Wage $
+ */
+class sfDoctrineLogger extends Doctrine_EventListener
+{
+  protected $connection = null,
+            $encoding = 'UTF8';
+
+  /**
+   * Log a query before it is executed
+   *
+   * @param Doctrine_Event $event
+   * @return void
+   */
+  public function preExecute(Doctrine_Event $event)
+  {
+    $this->sfLogQuery('executeQuery : ', $event);
+  }
+
+  /**
+   * Add the time after a query is executed
+   *
+   * @param Doctrine_Event $event
+   * @return void
+   */
+  public function postExecute(Doctrine_Event $event)
+  {
+    $this->sfAddTime();
+  }
+
+  /**
+   * Add the time after a query is prepared
+   *
+   * @param Doctrine_Event $event
+   * @return void
+   */
+  public function postPrepare(Doctrine_Event $event)
+  {
+    $this->sfAddTime();
+  }
+
+  /**
+   * Before a query statement is executed log it
+   *
+   * @param Doctrine_Event $event
+   * @return void
+   */
+  public function preStmtExecute(Doctrine_Event $event)
+  {
+    $this->sfLogQuery('executeQuery : ', $event);
+  }
+
+  /**
+   * postStmtExecute
+   *
+   * @param Doctrine_Event $event
+   * @return void
+   */
+  public function postStmtExecute(Doctrine_Event $event)
+  {
+    $this->sfAddTime();
+  }
+
+  /**
+   * Log a query before it is executed
+   *
+   * @param Doctrine_Event $event
+   * @return void
+   */
+  public function preQuery(Doctrine_Event $event)
+  {
+    $this->sfLogQuery('executeQuery : ', $event);
+  }
+
+  /**
+   * Post query add the time
+   *
+   * @param string $Doctrine_Event
+   * @return void
+   */
+  public function postQuery(Doctrine_Event $event)
+  {
+    $this->sfAddTime();
+  }
+
+  /**
+   * Log a Doctrine_Query
+   *
+   * @param string $message
+   * @param string $event
+   * @return void
+   */
+  protected function sfLogQuery($message, $event)
+  {
+    $message .= $event->getQuery();
+
+    if ($params = $event->getParams())
+    {
+      foreach ($params as $key => $param)
+      {
+        if (strlen($param) >= 255)
+        {
+          $len = strlen($param);
+          $kb = '[' . number_format($len / 1024, 2) . 'Kb]';
+          $params[$key] = $kb; 
+        }
+      }
+      $message .= ' - ('.implode(', ', $params) . ' )';
+    }
+
+    $message = '{sfDoctrineLogger} ' . $message;
+    if (sfContext::hasInstance())
+    {
+      sfContext::getInstance()->getLogger()->log($message);
+    }
+
+    $sqlTimer = sfTimerManager::getTimer('Database (Doctrine)');
+  }
+
+  /**
+   * Add the time to the log
+   *
+   * @return void
+   */
+  protected function sfAddTime()
+  {
+    sfTimerManager::getTimer('Database (Doctrine)')->addTime();
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/pager/sfDoctrinePager.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,177 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfDoctrine pager class
+ *
+ * @package    sfDoctrinePlugin
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrinePager.class.php 19265 2009-06-15 10:13:34Z Jonathan.Wage $
+ */
+class sfDoctrinePager extends sfPager implements Serializable
+{
+  protected
+    $query                 = null,
+    $tableMethodName       = null,
+    $tableMethodCalled     = false;
+
+  /**
+   * Get the name of the table method used to retrieve the query object for the pager
+   *
+   * @return string $tableMethodName
+   */
+  public function getTableMethod()
+  {
+    return $this->tableMethodName;
+  }
+
+  /**
+   * Set the name of the table method used to retrieve the query object for the pager
+   *
+   * @param string $tableMethodName 
+   * @return void
+   */
+  public function setTableMethod($tableMethodName)
+  {
+    $this->tableMethodName = $tableMethodName;
+  }
+
+  /**
+   * Serialize the pager object
+   *
+   * @return string $serialized
+   */
+  public function serialize()
+  {
+    $vars = get_object_vars($this);
+    unset($vars['query']);
+    return serialize($vars);
+  }
+
+  /**
+   * Unserialize a pager object
+   *
+   * @param string $serialized 
+   * @return void
+   */
+  public function unserialize($serialized)
+  {
+    $array = unserialize($serialized);
+
+    foreach($array as $name => $values)
+    {
+      $this->$name = $values;
+    }
+  }
+
+  public function getCountQuery()
+  {
+    $q = clone $this->getQuery()
+      ->offset(0)
+      ->limit(0);
+
+    return $q;
+  }
+
+  /**
+   * Initialize the pager instance and prepare it to be used for rendering
+   *
+   * @return void
+   */
+  public function init()
+  {
+    $countQuery = $this->getCountQuery();
+    $count = $countQuery->count();
+
+    $this->setNbResults($count);
+
+    $p = $this->getQuery();
+    $p->offset(0);
+    $p->limit(0);
+    if ($this->getPage() == 0 || $this->getMaxPerPage() == 0 || $this->getNbResults() == 0)
+    {
+      $this->setLastPage(0);
+    }
+    else
+    {
+      $offset = ($this->getPage() - 1) * $this->getMaxPerPage();
+
+      $this->setLastPage(ceil($this->getNbResults() / $this->getMaxPerPage()));
+
+      $p->offset($offset);
+      $p->limit($this->getMaxPerPage());
+    }
+  }
+
+  /**
+   * Get the query for the pager
+   *
+   * @return Doctrine_Query $query
+   */
+  public function getQuery()
+  {
+    if (!$this->tableMethodCalled && $this->tableMethodName)
+    {
+      $method = $this->tableMethodName;
+      $this->query = Doctrine::getTable($this->getClass())->$method($this->query);
+      $this->tableMethodCalled = true;
+    } else if (!$this->query) {
+      $this->query = Doctrine::getTable($this->getClass())->createQuery();
+    }
+    return $this->query;
+  }
+
+  /**
+   * Set query object for the pager
+   *
+   * @param Doctrine_Query $query
+   * @return void
+   */
+  public function setQuery($query)
+  {
+    $this->query = $query;
+  }
+
+  /**
+   * Retrieve the object for a certain offset
+   *
+   * @param integer $offset 
+   * @return Doctrine_Record $record
+   */
+  protected function retrieveObject($offset)
+  {
+    $cForRetrieve = clone $this->getQuery();
+    $cForRetrieve->offset($offset - 1);
+    $cForRetrieve->limit(1);
+
+    $results = $cForRetrieve->execute();
+
+    return $results[0];
+  }
+
+  /**
+   * Get all the results for the pager instance
+   *
+   * @param integer $hydrationMode Doctrine::HYDRATE_* constants
+   * @return mixed Doctrine_Collection/array
+   */
+  public function getResults($hydrationMode = Doctrine::HYDRATE_RECORD)
+  {
+    $p = $this->getQuery();
+
+    if ($hydrationMode == 'array')
+    {
+      $hydrationMode = Doctrine::HYDRATE_ARRAY;
+    }
+
+    return $p->execute(array(), $hydrationMode);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/record/sfDoctrineRecord.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,212 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Base sfDoctrineRecord extends the base Doctrine_Record in Doctrine to provide some
+ * symfony specific functionality to Doctrine_Records
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineRecord.class.php 19987 2009-07-07 20:31:36Z Jonathan.Wage $
+ */
+abstract class sfDoctrineRecord extends Doctrine_Record
+{
+  static protected
+    $_initialized    = false,
+    $_defaultCulture = 'en';
+
+  /**
+   * Custom Doctrine_Record constructor.
+   * Used to initialize I18n to make sure the culture is set from symfony
+   *
+   * @return void
+   */
+  public function construct()
+  {
+    self::initializeI18n();
+
+    if ($this->getTable()->hasRelation('Translation'))
+    {
+      $this->unshiftFilter(new sfDoctrineRecordI18nFilter());
+    }
+  }
+
+  /**
+   * Initialize I18n culture from symfony sfUser instance
+   * Add event listener to change default culture whenever the user changes culture
+   *
+   * @return void
+   */
+  public static function initializeI18n()
+  {
+    if (!self::$_initialized)
+    {
+      if (!self::$_initialized && class_exists('sfProjectConfiguration', false))
+      {
+        $dispatcher = sfProjectConfiguration::getActive()->getEventDispatcher();
+        $dispatcher->connect('user.change_culture', array('sfDoctrineRecord', 'listenToChangeCultureEvent'));
+      }
+
+      if (class_exists('sfContext', false) && sfContext::hasInstance() && $user = sfContext::getInstance()->getUser())
+      {
+        self::$_defaultCulture = $user->getCulture();
+      }
+      self::$_initialized = true;
+    }
+  }
+
+  /**
+   * Listens to the user.change_culture event.
+   *
+   * @param sfEvent An sfEvent instance
+   */
+  public static function listenToChangeCultureEvent(sfEvent $event)
+  {
+    self::$_defaultCulture = $event['culture'];
+  }
+
+  /**
+   * Sets the default culture
+   *
+   * @param string $culture
+   */
+  static public function setDefaultCulture($culture)
+  {
+    self::$_defaultCulture = $culture;
+  }
+
+  /**
+   * Return the default culture
+   *
+   * @return string the default culture
+   */
+  static public function getDefaultCulture()
+  {
+    self::initializeI18n();
+
+    if (!self::$_defaultCulture)
+    {
+      throw new sfException('The default culture has not been set');
+    }
+    return self::$_defaultCulture;
+  }
+
+  /**
+   * Get the primary key of a Doctrine_Record.
+   * This a proxy method to Doctrine_Record::identifier() for Propel BC
+   *
+   * @return mixed $identifier Array for composite primary keys and string for single primary key
+   */
+  public function getPrimaryKey()
+  {
+    $identifier = (array) $this->identifier();
+    return end($identifier);
+  }
+
+  /**
+   * Function require by symfony >= 1.2 admin generators
+   *
+   * @return boolean
+   */
+  public function isNew()
+  {
+    return ! $this->exists();
+  }
+
+  /**
+   * Returns a string representation of the record.
+   *
+   * @return string A string representation of the record.
+   */
+  public function __toString()
+  {
+    $guesses = array('name',
+                     'title',
+                     'description',
+                     'subject',
+                     'keywords',
+                     'id');
+
+    // we try to guess a column which would give a good description of the object
+    foreach ($guesses as $descriptionColumn)
+    {
+      try
+      {
+        return (string) $this->get($descriptionColumn);
+      } catch (Exception $e) {}
+    }
+
+    return sprintf('No description for object of class "%s"', $this->getTable()->getComponentName());
+  }
+
+  /*
+   * Provide accessors with setters and getters to Doctrine models.
+   *
+   * @param  string $method     The method name.
+   * @param  array  $arguments  The method arguments.
+   * @return mixed The returned value of the called method.
+   */
+  public function __call($method, $arguments)
+  {
+    try {
+      if (in_array($verb = substr($method, 0, 3), array('set', 'get')))
+      {
+        $name = substr($method, 3);
+
+        $table = $this->getTable();
+        if ($table->hasRelation($name))
+        {
+          $entityName = $name;
+        }
+        else if ($table->hasField($fieldName = $table->getFieldName($name)))
+        {
+          $entityNameLower = strtolower($fieldName);
+          if ($table->hasField($entityNameLower) || $table->hasRelation($entityNameLower))
+          {
+            $entityName = $entityNameLower;
+          } else {
+            $entityName = $fieldName;
+          }
+        }
+        else
+        {
+          $underScored = $table->getFieldName(sfInflector::underscore($name));
+          if ($table->hasField($underScored) || $table->hasRelation($underScored))
+          {
+            $entityName = $underScored;
+          } else if ($table->hasField(strtolower($name)) || $table->hasRelation(strtolower($name))) {
+            $entityName = strtolower($name);
+          } else {
+            $camelCase = $table->getFieldName(sfInflector::camelize($name));
+            $camelCase = strtolower($camelCase[0]).substr($camelCase, 1, strlen($camelCase));
+            if ($table->hasField($camelCase) || $table->hasRelation($camelCase))
+            {
+              $entityName = $camelCase;
+            } else {
+              $entityName = $underScored;
+            }
+          }
+        }
+
+        return call_user_func_array(
+          array($this, $verb),
+          array_merge(array($entityName), $arguments)
+        );
+      } else {
+        return parent::__call($method, $arguments);
+      }
+    } catch(Exception $e) {
+      return parent::__call($method, $arguments);
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/record/sfDoctrineRecordI18nFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfDoctrineRecordI18nFilter implements access to the translated properties for
+ * the current culture from the internationalized model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineRecordI18nFilter.class.php 11878 2008-09-30 20:14:40Z Jonathan.Wage $
+ */
+class sfDoctrineRecordI18nFilter extends Doctrine_Record_Filter
+{
+  public function init()
+  {
+  }
+
+  /**
+   * Implementation of filterSet() to call set on Translation relationship to allow
+   * access to I18n properties from the main object.
+   *
+   * @param Doctrine_Record $record
+   * @param string $name Name of the property
+   * @param string $value Value of the property
+   * @return void
+   */
+  public function filterSet(Doctrine_Record $record, $name, $value)
+  {
+    return $record['Translation'][sfDoctrineRecord::getDefaultCulture()][$name] = $value;
+  }
+
+  /**
+   * Implementation of filterGet() to call get on Translation relationship to allow
+   * access to I18n properties from the main object.
+   *
+   * @param Doctrine_Record $record
+   * @param string $name Name of the property
+   * @param string $value Value of the property
+   * @return void
+   */
+  public function filterGet(Doctrine_Record $record, $name)
+  {
+    $culture = sfDoctrineRecord::getDefaultCulture();
+    if (isset($record['Translation'][$culture]))
+    {
+      return $record['Translation'][$culture][$name];
+    } else {
+      $defaultCulture = sfConfig::get('sf_default_culture');
+      return $record['Translation'][$defaultCulture][$name];
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/record/sfDoctrineRecordListener.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Default Doctrine_Record listener
+ * 
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineRecordListener.class.php 11878 2008-09-30 20:14:40Z Jonathan.Wage $
+ */
+class sfDoctrineRecordListener extends Doctrine_Record_Listener
+{
+  /**
+   * preInsert
+   *
+   * @param string $Doctrine_Event 
+   * @return void
+   */
+  public function preInsert(Doctrine_Event $event)
+  {
+    if ($event->getInvoker()->getTable()->hasColumn('created_at'))
+    {
+      $event->getInvoker()->created_at = date('Y-m-d H:i:s', time());
+    }
+    
+    if ($event->getInvoker()->getTable()->hasColumn('updated_at'))
+    {
+      $event->getInvoker()->updated_at = date('Y-m-d H:i:s', time());
+    }
+  }
+  
+  /**
+   * preUpdate
+   *
+   * @param string $Doctrine_Event 
+   * @return void
+   */
+  public function preUpdate(Doctrine_Event $event)
+  {
+    if ($event->getInvoker()->getTable()->hasColumn('updated_at'))
+    {
+      $event->getInvoker()->updated_at = date('Y-m-d H:i:s', time());
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/routing/sfDoctrineRoute.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,163 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfDoctrineRoute represents a route that is bound to a Doctrine class.
+ *
+ * A Doctrine route can represent a single Doctrine object or a list of objects.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineRoute.class.php 11475 2008-09-12 11:07:23Z fabien $
+ */
+class sfDoctrineRoute extends sfObjectRoute
+{
+  protected
+    $query = null;
+
+  /**
+   * Constructor.
+   *
+   * @param string $pattern       The pattern to match
+   * @param array  $defaults      An array of default parameter values
+   * @param array  $requirements  An array of requirements for parameters (regexes)
+   * @param array  $options       An array of options
+   *
+   * @see sfObjectRoute
+   */
+  public function __construct($pattern, array $defaults = array(), array $requirements = array(), array $options = array())
+  {
+    parent::__construct($pattern, $defaults, $requirements, $options);
+
+    $this->options['object_model'] = $this->options['model'];
+  }
+
+  public function setListQuery(Doctrine_Query $query)
+  {
+    if (!$this->isBound())
+    {
+      throw new LogicException('The route is not bound.');
+    }
+
+    $this->query = $query;
+  }
+
+  protected function getObjectForParameters($parameters)
+  {
+    $results = $this->getObjectsForParameters($parameters);
+
+    // If query returned Doctrine_Collection with results inside then we
+    // need to return the first Doctrine_Record
+    if ($results instanceof Doctrine_Collection)
+    {
+      if (count($results))
+      {
+        $results = $results->getFirst();
+      } else {
+        $results = null;
+      }
+    }
+    // If an object is returned then lets return it otherwise return null
+    else if(!is_object($results))
+    {
+      $results = null;
+    }
+
+    return $results;
+  }
+
+  protected function getObjectsForParameters($parameters)
+  {
+    $this->options['model'] = Doctrine::getTable($this->options['model']);
+
+    $variables = array();
+    $values = array();
+    foreach($this->getRealVariables() as $variable)
+    {
+      if($this->options['model']->hasColumn($this->options['model']->getColumnName($variable)))
+      {
+        $variables[] = $variable;
+        $values[$variable] = $parameters[$variable];
+      }
+    }
+
+    if (!isset($this->options['method']))
+    {
+      if (is_null($this->query))
+      {
+        $q = $this->options['model']->createQuery('a');
+        foreach ($values as $variable => $value)
+        {
+          $fieldName = $this->options['model']->getFieldName($variable);
+          $q->andWhere('a.'. $fieldName . ' = ?', $parameters[$variable]);
+        }
+      }
+      else
+      {
+        $q = $this->query;
+      }
+      if (isset($this->options['method_for_query']))
+      {
+        $method = $this->options['method_for_query'];
+        $results = $this->options['model']->$method($q);
+      }
+      else
+      {
+        $results = $q->execute();
+      }
+    }
+    else
+    {
+      $method = $this->options['method'];
+      $results = $this->options['model']->$method($this->filterParameters($parameters));
+    }
+
+    // If query returned a Doctrine_Record instance instead of a 
+    // Doctrine_Collection then we need to create a new Doctrine_Collection with
+    // one element inside and return that
+    if ($results instanceof Doctrine_Record)
+    {
+      $obj = $results;
+      $results = new Doctrine_Collection($obj->getTable());
+      $results[] = $obj;
+    }
+
+    return $results;
+  }
+
+  protected function doConvertObjectToArray($object)
+  {
+    if (isset($this->options['convert']) || method_exists($object, 'toParams'))
+    {
+      return parent::doConvertObjectToArray($object);
+    }
+
+    $className = $this->options['model'];
+
+    $parameters = array();
+
+    foreach ($this->getRealVariables() as $variable)
+    {
+      try {
+        $parameters[$variable] = $object->$variable;
+      } catch (Exception $e) {
+        try {
+          $method = 'get'.sfInflector::camelize($variable);
+          $parameters[$variable] = $object->$method;
+        } catch (Exception $e) {}
+      }
+    }
+
+    return $parameters;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/routing/sfDoctrineRouteCollection.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfObjectRouteCollection represents a collection of routes bound to Doctrine objects.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineRouteCollection.class.php 11475 2008-09-12 11:07:23Z fabien $
+ */
+class sfDoctrineRouteCollection extends sfObjectRouteCollection
+{
+  protected
+    $routeClass = 'sfDoctrineRoute';
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/sfDoctrineException.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfDoctrine exception class
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineException.class.php 11629 2008-09-17 22:22:25Z Jonathan.Wage $
+ */
+class sfDoctrineException extends sfException
+{
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBaseTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,114 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Base class for all symfony Doctrine tasks.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineBaseTask.class.php 15865 2009-02-28 03:34:26Z Jonathan.Wage $
+ */
+abstract class sfDoctrineBaseTask extends sfBaseTask
+{
+  static protected $done = false;
+
+  public function initialize(sfEventDispatcher $dispatcher, sfFormatter $formatter)
+  {
+    parent::initialize($dispatcher, $formatter);
+    self::$done = true;
+  }
+
+  protected function createConfiguration($application, $env)
+  {
+    $configuration = parent::createConfiguration($application, $env);
+
+    $autoloader = sfSimpleAutoload::getInstance();
+    $config = new sfAutoloadConfigHandler();
+    $mapping = $config->evaluate($configuration->getConfigPaths('config/autoload.yml'));
+    foreach ($mapping as $class => $file)
+    {
+      $autoloader->setClassPath($class, $file);
+    }
+    $autoloader->register();
+
+    return $configuration;
+  }
+  /**
+   * Get array of configuration variables for the Doctrine cli
+   *
+   * @return array $config
+   */
+  public function getCliConfig()
+  {
+    $fixtures = array();
+    $fixtures[] = sfConfig::get('sf_root_dir').'/data/fixtures';
+    $pluginPaths = $this->configuration->getPluginPaths();
+    foreach ($pluginPaths as $pluginPath)
+    {
+      if (is_dir($dir = $pluginPath.'/data/fixtures'))
+      {
+        $fixtures[] = $dir;
+      }
+    }
+    $models = sfConfig::get('sf_lib_dir') . DIRECTORY_SEPARATOR . 'model' . DIRECTORY_SEPARATOR . 'doctrine';
+    $migrations = sfConfig::get('sf_lib_dir') . DIRECTORY_SEPARATOR . 'migration' . DIRECTORY_SEPARATOR . 'doctrine';
+    $sql = sfConfig::get('sf_data_dir') . DIRECTORY_SEPARATOR . 'sql';
+    $yaml = sfConfig::get('sf_config_dir') . DIRECTORY_SEPARATOR . 'doctrine';
+
+    $config = array('data_fixtures_path'  =>  $fixtures,
+                    'models_path'         =>  $models,
+                    'migrations_path'     =>  $migrations,
+                    'sql_path'            =>  $sql,
+                    'yaml_schema_path'    =>  $yaml);
+
+    foreach ($config as $dir)
+    {
+      $dirs = (array) $dir;
+      foreach ($dirs as $dir)
+      {
+        Doctrine_Lib::makeDirectories($dir);
+      }
+    }
+
+    return $config;
+  }
+
+  /**
+   * Call a command from the Doctrine CLI
+   *
+   * @param string $task Name of the Doctrine task to call
+   * @param string $args Arguments for the task
+   * @return void
+   */
+  public function callDoctrineCli($task, $args = array())
+  {
+    $config = $this->getCliConfig();
+
+    $arguments = array('./symfony', $task);
+
+    foreach ($args as $key => $arg)
+    {
+      if (isset($config[$key]))
+      {
+        $config[$key] = $arg;
+      } else {
+        $arguments[] = $arg;
+      }
+    }
+
+    $cli = new sfDoctrineCli($config);
+    $cli->setDispatcher($this->dispatcher);
+    $cli->setFormatter($this->formatter);
+    $cli->run($arguments);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildAllLoadTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,109 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Creates Databases, Generates Doctrine model, SQL, initializes database, and load data.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineBuildAllLoadTask.class.php 18971 2009-06-05 15:44:44Z Jonathan.Wage $
+ */
+class sfDoctrineBuildAllLoadTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+      new sfCommandOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'doctrine'),
+      new sfCommandOption('no-confirmation', null, sfCommandOption::PARAMETER_NONE, 'Do not ask for confirmation'),
+      new sfCommandOption('skip-forms', 'F', sfCommandOption::PARAMETER_NONE, 'Skip generating forms'),
+      new sfCommandOption('dir', null, sfCommandOption::PARAMETER_REQUIRED | sfCommandOption::IS_ARRAY, 'The directories to look for fixtures'),
+    ));
+
+    $this->aliases = array('doctrine-build-all-load');
+    $this->namespace = 'doctrine';
+    $this->name = 'build-all-load';
+    $this->briefDescription = 'Generates Doctrine model, SQL, initializes database, and loads fixtures data';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:build-all-load|INFO] task is a shortcut for two other tasks:
+
+  [./symfony doctrine:build-all-load|INFO]
+
+The task is equivalent to:
+
+  [./symfony doctrine:build-all|INFO]
+  [./symfony doctrine:data-load|INFO]
+
+The task takes an application argument because of the [doctrine:data-load|COMMENT]
+task. See [doctrine:data-load|COMMENT] help page for more information.
+
+To bypass the confirmation, you can pass the [no-confirmation|COMMENT]
+option:
+
+  [./symfony doctrine:build-all-load --no-confirmation|INFO]
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $databaseManager = new sfDatabaseManager($this->configuration);
+
+    $buildAll = new sfDoctrineBuildAllTask($this->dispatcher, $this->formatter);
+    $buildAll->setCommandApplication($this->commandApplication);
+
+    $buildAllOptions = array();
+    if ($options['skip-forms'])
+    {
+      $buildAllOptions[] = '--skip-forms';
+    }
+    if ($options['no-confirmation'])
+    {
+      $buildAllOptions[] = '--no-confirmation';
+    }
+    if (isset($options['application']) && $options['application'])
+    {
+      $buildAllOptions[] = '--application=' . $options['application'];
+    }
+    $ret = $buildAll->run(array(), $buildAllOptions);
+
+    if (0 == $ret)
+    {
+      $loadData = new sfDoctrineLoadDataTask($this->dispatcher, $this->formatter);
+      $loadData->setCommandApplication($this->commandApplication);
+
+      $loadDataOptions = array('--env='.$options['env'], '--connection='.$options['connection']);
+      if (isset($options['application']))
+      {
+        $loadDataOptions[] = '--application='.$options['application'];
+      }
+      if (!empty($options['dir']))
+      {
+        $loadDataOptions[] = '--dir=' . implode(' --dir=', $options['dir']);
+      }
+
+      $loadData->run(array(), $loadDataOptions);
+    }
+
+    return $ret;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildAllReloadTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,107 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Drops Databases, Creates Databases, Generates Doctrine model, SQL, initializes database, and load data.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineBuildAllReloadTask.class.php 15823 2009-02-26 19:16:05Z Jonathan.Wage $
+ */
+class sfDoctrineBuildAllReloadTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+      new sfCommandOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'doctrine'),
+      new sfCommandOption('no-confirmation', null, sfCommandOption::PARAMETER_NONE, 'Do not ask for confirmation'),
+      new sfCommandOption('skip-forms', 'F', sfCommandOption::PARAMETER_NONE, 'Skip generating forms'),
+      new sfCommandOption('dir', null, sfCommandOption::PARAMETER_REQUIRED | sfCommandOption::IS_ARRAY, 'The directories to look for fixtures'),
+    ));
+
+    $this->aliases = array('doctrine-build-all-reload');
+    $this->namespace = 'doctrine';
+    $this->name = 'build-all-reload';
+    $this->briefDescription = 'Generates Doctrine model, SQL, initializes database, and load data';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:build-all-reload|INFO] task is a shortcut for five other tasks:
+
+  [./symfony doctrine:build-all-reload|INFO]
+
+The task is equivalent to:
+
+  [./symfony doctrine:drop-db|INFO]
+  [./symfony doctrine:build-db|INFO]
+  [./symfony doctrine:build-model|INFO]
+  [./symfony doctrine:insert-sql|INFO]
+  [./symfony doctrine:data-load|INFO]
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $dropDb = new sfDoctrineDropDbTask($this->dispatcher, $this->formatter);
+    $dropDb->setCommandApplication($this->commandApplication);
+
+    $dropDbOptions = array();
+    $dropDbOptions[] = '--env='.$options['env'];
+    if (isset($options['no-confirmation']) && $options['no-confirmation'])
+    {
+      $dropDbOptions[] = '--no-confirmation';
+    }
+    if (isset($options['application']) && $options['application'])
+    {
+      $dropDbOptions[] = '--application=' . $options['application'];
+    }
+    $ret = $dropDb->run(array(), $dropDbOptions);
+
+    if ($ret)
+    {
+      return $ret;
+    }
+
+    $buildAllLoad = new sfDoctrineBuildAllLoadTask($this->dispatcher, $this->formatter);
+    $buildAllLoad->setCommandApplication($this->commandApplication);
+
+    $buildAllLoadOptions = array();
+    $buildAllLoadOptions[] = '--env='.$options['env'];
+    if (!empty($options['dir']))
+    {
+      $buildAllLoadOptions[] = '--dir=' . implode(' --dir=', $options['dir']);
+    }
+    if (isset($options['append']) && $options['append'])
+    {
+      $buildAllLoadOptions[] = '--append';
+    }
+    if (isset($options['application']) && $options['application'])
+    {
+      $buildAllLoadOptions[] = '--application=' . $options['application'];
+    }
+    if (isset($options['skip-forms']) && $options['skip-forms'])
+    {
+      $buildAllLoadOptions[] = '--skip-forms';
+    }
+    $buildAllLoad->run(array(), $buildAllLoadOptions);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildAllReloadTestAllTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,102 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Drops Databases, Creates Databases, Generates Doctrine model, SQL, initializes database, load data and run 
+ * all test suites
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineBuildAllReloadTask.class.php 8743 2008-05-03 05:02:39Z Jonathan.Wage $
+ */
+class sfDoctrineBuildAllReloadTestAllTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+      new sfCommandOption('append', null, sfCommandOption::PARAMETER_NONE, 'Don\'t delete current data in the database'),
+      new sfCommandOption('dir', null, sfCommandOption::PARAMETER_REQUIRED | sfCommandOption::IS_ARRAY, 'The directories to look for fixtures'),
+      new sfCommandOption('force', null, sfCommandOption::PARAMETER_NONE, 'Whether to force dropping of the database'),
+    ));
+
+    $this->aliases = array('doctrine-build-all-reload-test-all');
+    $this->namespace = 'doctrine';
+    $this->name = 'build-all-reload-test-all';
+    $this->briefDescription = 'Generates Doctrine model, SQL, initializes database, load data and run all tests';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:build-all-reload|INFO] task is a shortcut for four other tasks:
+
+  [./symfony doctrine:build-all-reload-test-all frontend|INFO]
+
+The task is equivalent to:
+  
+  [./symfony doctrine:drop-db|INFO]
+  [./symfony doctrine:build-db|INFO]
+  [./symfony doctrine:build-model|INFO]
+  [./symfony doctrine:insert-sql|INFO]
+  [./symfony doctrine:data-load|INFO]
+  [./symfony test-all|INFO]
+
+The task takes an application argument because of the [doctrine:data-load|COMMENT]
+task. See [doctrine:data-load|COMMENT] help page for more information.
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $buildAllReload = new sfDoctrineBuildAllReloadTask($this->dispatcher, $this->formatter);
+    $buildAllReload->setCommandApplication($this->commandApplication);
+
+    $buildAllReloadOptions = array();
+    if (!empty($options['application']))
+    {
+      $buildAllReloadOptions[] = '--application=' . $options['application'];
+    }
+    $buildAllReloadOptions[] = '--env='.$options['env'];
+    if (!empty($options['dir']))
+    {
+      $buildAllReloadOptions[] = '--dir=' . implode(' --dir=', $options['dir']);
+    }
+    if (isset($options['append']) && $options['append'])
+    {
+      $buildAllReloadOptions[] = '--append';
+    }
+    if (isset($options['no-confirmation']) && $options['no-confirmation'])
+    {
+      $buildAllReloadOptions[] = '--no-confirmation';
+    }
+    $ret = $buildAllReload->run(array(), $buildAllReloadOptions);
+
+    if ($ret)
+    {
+      return $ret;
+    }
+
+    $this->logSection('doctrine', 'running test suite');
+    
+    $testAll = new sfTestAllTask($this->dispatcher, $this->formatter);
+    $testAll->setCommandApplication($this->commandApplication);
+    $testAll->run();
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildAllTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,127 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Generates Doctrine model, SQL and initializes the database.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineBuildAllTask.class.php 16087 2009-03-07 22:08:50Z Kris.Wallsmith $
+ */
+class sfDoctrineBuildAllTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->aliases = array('doctrine-build-all');
+    $this->namespace = 'doctrine';
+    $this->name = 'build-all';
+    $this->briefDescription = 'Generates Doctrine model, SQL and initializes the database';
+
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+      new sfCommandOption('no-confirmation', null, sfCommandOption::PARAMETER_NONE, 'Do not ask for confirmation'),
+      new sfCommandOption('skip-forms', 'F', sfCommandOption::PARAMETER_NONE, 'Skip generating forms')
+    ));
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:build-all|INFO] task is a shortcut for three other tasks:
+
+  [./symfony doctrine:build-all|INFO]
+
+The task is equivalent to:
+
+  [./symfony doctrine:build-model|INFO]
+  [./symfony doctrine:build-sql|INFO]
+  [./symfony doctrine:build-forms|INFO]
+  [./symfony doctrine:insert-sql|INFO]
+
+See those three tasks help page for more information.
+
+To bypass the confirmation, you can pass the [no-confirmation|COMMENT]
+option:
+
+  [./symfony doctrine:buil-all-load --no-confirmation|INFO]
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $baseOptions = $this->configuration instanceof sfApplicationConfiguration ? array(
+      '--application='.$this->configuration->getApplication(),
+      '--env='.$options['env'],
+    ) : array();
+
+    $buildDb = new sfDoctrineBuildDbTask($this->dispatcher, $this->formatter);
+    $buildDb->setCommandApplication($this->commandApplication);
+    $ret = $buildDb->run(array(), $baseOptions);
+
+    if ($ret)
+    {
+      return $ret;
+    }
+
+    $buildModel = new sfDoctrineBuildModelTask($this->dispatcher, $this->formatter);
+    $buildModel->setCommandApplication($this->commandApplication);
+    $ret = $buildModel->run(array(), $baseOptions);
+
+    if ($ret)
+    {
+      return $ret;
+    }
+
+    $buildSql = new sfDoctrineBuildSqlTask($this->dispatcher, $this->formatter);
+    $buildSql->setCommandApplication($this->commandApplication);
+    $ret = $buildSql->run(array(), $baseOptions);
+
+    if ($ret)
+    {
+      return $ret;
+    }
+
+    if (!$options['skip-forms'])
+    {
+      $buildForms = new sfDoctrineBuildFormsTask($this->dispatcher, $this->formatter);
+      $buildForms->setCommandApplication($this->commandApplication);
+      $ret = $buildForms->run(array(), $baseOptions);
+
+      if ($ret)
+      {
+        return $ret;
+      }
+
+      $buildFilters = new sfDoctrineBuildFiltersTask($this->dispatcher, $this->formatter);
+      $buildFilters->setCommandApplication($this->commandApplication);
+      $ret = $buildFilters->run(array(), $baseOptions);
+
+      if ($ret)
+      {
+        return $ret;
+      }
+    }
+
+    $insertSql = new sfDoctrineInsertSqlTask($this->dispatcher, $this->formatter);
+    $insertSql->setCommandApplication($this->commandApplication);
+    $ret = $insertSql->run(array(), $baseOptions);
+
+    return $ret;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildDbTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Creates database for current model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineBuildDbTask.class.php 14213 2008-12-19 21:03:13Z Jonathan.Wage $
+ */
+class sfDoctrineBuildDbTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->aliases = array('doctrine-build-db');
+    $this->namespace = 'doctrine';
+    $this->name = 'build-db';
+    $this->briefDescription = 'Creates database for current model';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:build-db|INFO] task creates the database:
+
+  [./symfony doctrine:build-db|INFO]
+
+The task read connection information in [config/doctrine/databases.yml|COMMENT]:
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $this->logSection('doctrine', 'creating databases');
+
+    $databaseManager = new sfDatabaseManager($this->configuration);
+    $this->callDoctrineCli('create-db');
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildFiltersTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,85 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license informationation, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Create filter form classes for the current model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: sfDoctrineBuildFiltersTask.class.php 12537 2008-11-01 14:43:27Z fabien $
+ */
+class sfDoctrineBuildFiltersTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'doctrine'),
+      new sfCommandOption('model-dir-name', null, sfCommandOption::PARAMETER_REQUIRED, 'The model dir name', 'model'),
+      new sfCommandOption('filter-dir-name', null, sfCommandOption::PARAMETER_REQUIRED, 'The filter form dir name', 'filter'),
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->namespace = 'doctrine';
+    $this->name = 'build-filters';
+    $this->briefDescription = 'Creates filter form classes for the current model';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:build-filters|INFO] task creates filter form classes from the schema:
+
+  [./symfony doctrine:build-filters|INFO]
+
+The task read the schema information in [config/*schema.xml|COMMENT] and/or
+[config/*schema.yml|COMMENT] from the project and all installed plugins.
+
+The task use the [doctrine|COMMENT] connection as defined in [config/databases.yml|COMMENT].
+You can use another connection by using the [--connection|COMMENT] option:
+
+  [./symfony doctrine:build-filters --connection="name"|INFO]
+
+The model filter form classes files are created in [lib/filter|COMMENT].
+
+This task never overrides custom classes in [lib/filter|COMMENT].
+It only replaces base classes generated in [lib/filter/base|COMMENT].
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $this->logSection('doctrine', 'generating filter form classes');
+    $databaseManager = new sfDatabaseManager($this->configuration);
+    $generatorManager = new sfGeneratorManager($this->configuration);
+    $generatorManager->generate('sfDoctrineFormFilterGenerator', array(
+      'connection'     => $options['connection'],
+      'model_dir_name' => $options['model-dir-name'],
+      'filter_dir_name'  => $options['filter-dir-name'],
+    ));
+
+    $properties = parse_ini_file(sfConfig::get('sf_config_dir').DIRECTORY_SEPARATOR.'properties.ini', true);
+
+    $constants = array(
+      'PROJECT_NAME' => isset($properties['symfony']['name']) ? $properties['symfony']['name'] : 'symfony',
+      'AUTHOR_NAME'  => isset($properties['symfony']['author']) ? $properties['symfony']['author'] : 'Your name here'
+    );
+
+    // customize php and yml files
+    $finder = sfFinder::type('file')->name('*.php');
+    $this->getFilesystem()->replaceTokens($finder->in(sfConfig::get('sf_lib_dir').'/filter/'), '##', '##', $constants);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildFormsTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,85 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Create form classes for the current model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: sfDoctrineBuildFormsTask.class.php 12537 2008-11-01 14:43:27Z fabien $
+ */
+class sfDoctrineBuildFormsTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'doctrine'),
+      new sfCommandOption('model-dir-name', null, sfCommandOption::PARAMETER_REQUIRED, 'The model dir name', 'model'),
+      new sfCommandOption('form-dir-name', null, sfCommandOption::PARAMETER_REQUIRED, 'The form dir name', 'form'),
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->namespace = 'doctrine';
+    $this->name = 'build-forms';
+    $this->briefDescription = 'Creates form classes for the current model';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:build-forms|INFO] task creates form classes from the schema:
+
+  [./symfony doctrine:build-forms|INFO]
+
+The task read the schema information in [config/*schema.xml|COMMENT] and/or
+[config/*schema.yml|COMMENT] from the project and all installed plugins.
+
+The task use the [doctrine|COMMENT] connection as defined in [config/databases.yml|COMMENT].
+You can use another connection by using the [--connection|COMMENT] option:
+
+  [./symfony doctrine:build-forms --connection="name"|INFO]
+
+The model form classes files are created in [lib/form|COMMENT].
+
+This task never overrides custom classes in [lib/form|COMMENT].
+It only replaces base classes generated in [lib/form/base|COMMENT].
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $this->logSection('doctrine', 'generating form classes');
+    $databaseManager = new sfDatabaseManager($this->configuration);
+    $generatorManager = new sfGeneratorManager($this->configuration);
+    $generatorManager->generate('sfDoctrineFormGenerator', array(
+      'connection'     => $options['connection'],
+      'model_dir_name' => $options['model-dir-name'],
+      'form_dir_name'  => $options['form-dir-name'],
+    ));
+
+    $properties = parse_ini_file(sfConfig::get('sf_config_dir').DIRECTORY_SEPARATOR.'properties.ini', true);
+
+    $constants = array(
+      'PROJECT_NAME' => isset($properties['symfony']['name']) ? $properties['symfony']['name'] : 'symfony',
+      'AUTHOR_NAME'  => isset($properties['symfony']['author']) ? $properties['symfony']['author'] : 'Your name here'
+    );
+
+    // customize php and yml files
+    $finder = sfFinder::type('file')->name('*.php');
+    $this->getFilesystem()->replaceTokens($finder->in(sfConfig::get('sf_lib_dir').'/form/'), '##', '##', $constants);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildModelTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,137 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Create classes for the current model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineBuildModelTask.class.php 14213 2008-12-19 21:03:13Z Jonathan.Wage $
+ */
+class sfDoctrineBuildModelTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->aliases = array('doctrine-build-model');
+    $this->namespace = 'doctrine';
+    $this->name = 'build-model';
+    $this->briefDescription = 'Creates classes for the current model';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:build-model|INFO] task creates model classes from the schema:
+
+  [./symfony doctrine:build-model|INFO]
+
+The task read the schema information in [config/doctrine/*.yml|COMMENT]
+from the project and all installed plugins.
+
+The model classes files are created in [lib/model/doctrine|COMMENT].
+
+This task never overrides custom classes in [lib/model/doctrine|COMMENT].
+It only replaces files in [lib/model/doctrine/base|COMMENT].
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $this->logSection('doctrine', 'generating model classes');
+
+    $config = $this->getCliConfig();
+
+    $this->_checkForPackageParameter($config['yaml_schema_path']);
+
+    $tmpPath = sfConfig::get('sf_cache_dir').DIRECTORY_SEPARATOR.'tmp';
+
+    if (!file_exists($tmpPath))
+    {
+      Doctrine_Lib::makeDirectories($tmpPath);
+    }
+
+    $plugins = $this->configuration->getPlugins();
+    foreach ($this->configuration->getAllPluginPaths() as $plugin => $path)
+    {
+      if (!in_array($plugin, $plugins))
+      {
+        continue;
+      }
+      $schemas = sfFinder::type('file')->name('*.yml')->in($path.'/config/doctrine');
+      foreach ($schemas as $schema)
+      {
+        $tmpSchemaPath = $tmpPath.DIRECTORY_SEPARATOR.$plugin.'-'.basename($schema);
+
+        $models = Doctrine_Parser::load($schema, 'yml');
+        if (!isset($models['package']))
+        {
+          $models['package'] = $plugin.'.lib.model.doctrine';
+          $models['package_custom_path'] = $path.'/lib/model/doctrine';
+        }
+        Doctrine_Parser::dump($models, 'yml', $tmpSchemaPath);
+      }
+    }
+
+    $options = array('generateBaseClasses'  => true,
+                     'generateTableClasses' => true,
+                     'packagesPath'         => sfConfig::get('sf_plugins_dir'),
+                     'packagesPrefix'       => 'Plugin',
+                     'suffix'               => '.class.php',
+                     'baseClassesDirectory' => 'base',
+                     'baseClassName'        => 'sfDoctrineRecord');
+    $options = array_merge($options, sfConfig::get('doctrine_model_builder_options', array()));
+
+    $import = new Doctrine_Import_Schema();
+    $import->setOptions($options);
+    $import->importSchema(array($tmpPath, $config['yaml_schema_path']), 'yml', $config['models_path']);
+  }
+
+  /**
+   * Check for package parameter in main schema files.
+   * sfDoctrinePlugin uses the package feature of Doctrine
+   * for plugins and cannot be used by the user
+   *
+   * @param string $path
+   * @return void
+   */
+  protected function _checkForPackageParameter($path)
+  {
+    $files = sfFinder::type('file')->name('*.yml')->in($path);
+    foreach ($files as $file)
+    {
+      $array = sfYaml::load($file);
+      if (is_array($array) AND !empty($array))
+      {
+        foreach ($array as $key => $value)
+        {
+          if ($key == 'package' || (is_array($value) && isset($value['package'])))
+          {
+            throw new sfDoctrineException(
+              sprintf('Cannot use package parameter in symfony Doctrine schema files. Found in "%s"', $file)
+            );
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildSchemaTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Creates a schema.xml from an existing database.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineBuildSchemaTask.class.php 14213 2008-12-19 21:03:13Z Jonathan.Wage $
+ */
+class sfDoctrineBuildSchemaTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->aliases = array('doctrine-build-schema');
+    $this->namespace = 'doctrine';
+    $this->name = 'build-schema';
+    $this->briefDescription = 'Creates a schema from an existing database';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:build-schema|INFO] task introspects a database to create a schema:
+
+  [./symfony doctrine:build-schema|INFO]
+
+The task creates a yml file in [config/doctrine|COMMENT]
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $this->logSection('doctrine', 'generating yaml schema from database');
+
+    $databaseManager = new sfDatabaseManager($this->configuration);
+    $this->callDoctrineCli('generate-yaml-db');
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineBuildSqlTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Create SQL for the current model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineBuildSqlTask.class.php 14213 2008-12-19 21:03:13Z Jonathan.Wage $
+ */
+class sfDoctrineBuildSqlTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->aliases = array('doctrine-build-sql');
+    $this->namespace = 'doctrine';
+    $this->name = 'build-sql';
+    $this->briefDescription = 'Creates SQL for the current model';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:build-sql|INFO] task creates SQL statements for table creation:
+
+  [./symfony doctrine:build-sql|INFO]
+
+The generated SQL is optimized for the database configured in [config/databases.yml|COMMENT]:
+
+  [doctrine.database = mysql|INFO]
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $this->logSection('doctrine', 'generating sql for models');
+
+    $databaseManager = new sfDatabaseManager($this->configuration);
+    $this->callDoctrineCli('generate-sql');
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineDataDumpTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,89 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Dumps data to the fixtures directory.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineDataDumpTask.class.php 14213 2008-12-19 21:03:13Z Jonathan.Wage $
+ */
+class sfDoctrineDumpDataTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addArguments(array(
+      new sfCommandArgument('target', sfCommandArgument::OPTIONAL, 'The target filename'),
+    ));
+
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->aliases = array('doctrine-dump-data');
+    $this->namespace = 'doctrine';
+    $this->name = 'data-dump';
+    $this->briefDescription = 'Dumps data to the fixtures directory';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:data-dump|INFO] task dumps database data:
+
+  [./symfony doctrine:data-dump|INFO]
+
+The task dumps the database data in [data/fixtures/%target%|COMMENT].
+
+The dump file is in the YML format and can be reimported by using
+the [doctrine:data-load|INFO] task.
+
+  [./symfony doctrine:data-load frontend|INFO]
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $databaseManager = new sfDatabaseManager($this->configuration);
+
+    $config = $this->getCliConfig();
+    $dir = sfConfig::get('sf_data_dir') . DIRECTORY_SEPARATOR . 'fixtures';
+    Doctrine_Lib::makeDirectories($dir);
+
+    $args = array();
+    if (isset($arguments['target']))
+    {
+      $filename = $arguments['target'];
+
+      if (!sfToolkit::isPathAbsolute($filename))
+      {
+        $filename = $dir . DIRECTORY_SEPARATOR . $filename;
+      }
+
+      Doctrine_Lib::makeDirectories(dirname($filename));
+
+      $args = array('data_fixtures_path' => array($filename));
+      $this->logSection('doctrine', sprintf('dumping data to fixtures to "%s"', $filename));
+    } else {
+      $this->logSection('doctrine', sprintf('dumping data to fixtures to "%s"', $config['data_fixtures_path'][0]));
+    }
+
+    $this->callDoctrineCli('dump-data', $args);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineDataLoadTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,89 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Loads data from fixtures directory.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineDataLoadTask.class.php 14213 2008-12-19 21:03:13Z Jonathan.Wage $
+ */
+class sfDoctrineLoadDataTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+      new sfCommandOption('append', null, sfCommandOption::PARAMETER_NONE, 'Don\'t delete current data in the database'),
+      new sfCommandOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'doctrine'),
+      new sfCommandOption('dir', null, sfCommandOption::PARAMETER_REQUIRED | sfCommandOption::IS_ARRAY, 'The directories to look for fixtures'),
+    ));
+
+    $this->aliases = array('doctrine-load-data');
+    $this->namespace = 'doctrine';
+    $this->name = 'data-load';
+    $this->briefDescription = 'Loads data from fixtures directory';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:data-load|INFO] task loads data fixtures into the database:
+
+  [./symfony doctrine:data-load frontend|INFO]
+
+The task loads data from all the files found in [data/fixtures/|COMMENT].
+
+If you want to load data from other directories, you can use
+the [--dir|COMMENT] option:
+
+  [./symfony doctrine:data-load --dir="data/fixtures" --dir="data/data" frontend|INFO]
+
+If you don't want the task to remove existing data in the database,
+use the [--append|COMMENT] option:
+
+  [./symfony doctrine:data-load --append frontend|INFO]
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $databaseManager = new sfDatabaseManager($this->configuration);
+
+    $arguments = array();
+    if (isset($options['append']) && $options['append'])
+    {
+      $arguments['append'] = $options['append'];
+    }
+
+    if (isset($options['dir']) && $options['dir'])
+    {
+      $arguments['data_fixtures_path'] = $options['dir'];
+      foreach ($options['dir'] as $dir)
+      {
+        $this->logSection('doctrine', sprintf('loading data fixtures from "%s"', $dir));
+      }
+    } else {
+      $config = $this->getCliConfig();
+      $this->logSection('doctrine', sprintf('loading data fixtures from "%s"', $config['data_fixtures_path'][0]));
+    }
+
+    $this->callDoctrineCli('load-data', $arguments);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineDqlTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,93 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Creates database for current model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineDqlTask.class.php 14213 2008-12-19 21:03:13Z Jonathan.Wage $
+ */
+class sfDoctrineDqlTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addArguments(array(
+      new sfCommandArgument('dql_query', sfCommandArgument::REQUIRED, 'The DQL query to execute', null),
+    ));
+
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+      new sfCommandOption('show-sql', null, sfCommandOption::PARAMETER_NONE, 'Show the sql that would be executed'),
+    ));
+
+    $this->aliases = array('doctrine-dql');
+    $this->namespace = 'doctrine';
+    $this->name = 'dql';
+    $this->briefDescription = 'Execute a DQL query and view the results';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:data-dql|INFO] task executes a DQL query and display the formatted results:
+
+  [./symfony doctrine:dql "FROM User u"|INFO]
+
+You can show the SQL that would be executed by using the [--dir|COMMENT] option:
+
+  [./symfony doctrine:dql --show-sql "FROM User u"|INFO]
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $databaseManager = new sfDatabaseManager($this->configuration);
+
+    $dql = $arguments['dql_query'];
+
+    $q = Doctrine_Query::create()
+      ->parseQuery($dql);
+
+    $this->logSection('doctrine', 'executing dql query');
+
+    echo sprintf('DQL: %s', $dql) . "\n";
+
+    if ($options['show-sql']) {
+      echo sprintf('SQL: %s', $q->getSql()) . "\n";
+    }
+
+    $count = $q->count();
+
+    if ($count)
+    {
+      echo sprintf('found %s results', $count) . "\n";
+
+      $results = $q->fetchArray();
+      $yaml = sfYaml::dump($results, 4);
+      $lines = explode("\n", $yaml);
+      foreach ($lines as $line)
+      {
+        echo $line . "\n";
+      }
+    } else {
+      $this->logSection('doctrine', 'no results found');
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineDropDbTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,71 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Drops database for current model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineDropDbTask.class.php 14213 2008-12-19 21:03:13Z Jonathan.Wage $
+ */
+class sfDoctrineDropDbTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+      new sfCommandOption('no-confirmation', null, sfCommandOption::PARAMETER_NONE, 'Whether to force dropping of the database')
+    ));
+
+    $this->aliases = array('doctrine-drop-db');
+    $this->namespace = 'doctrine';
+    $this->name = 'drop-db';
+    $this->briefDescription = 'Drops database for current model';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:drop-db|INFO] task drops the database:
+
+  [./symfony doctrine:drop-db|INFO]
+
+The task read connection information in [config/doctrine/databases.yml|COMMENT]:
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    if (
+      !$options['no-confirmation']
+      &&
+      !$this->askConfirmation(array('This command will remove all data in your database.', 'Are you sure you want to proceed? (y/N)'), null, false)
+    )
+    {
+      $this->logSection('doctrine', 'task aborted');
+
+      return 1;
+    }
+
+    $this->logSection('doctrine', 'dropping databases');
+
+    $databaseManager = new sfDatabaseManager($this->configuration);
+    $this->callDoctrineCli('drop-db', array('force' => true));
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineGenerateAdminTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,188 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Generates a Doctrine admin module.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: sfDoctrineGenerateAdminTask.class.php 12474 2008-10-31 10:41:27Z fabien $
+ */
+class sfDoctrineGenerateAdminTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addArguments(array(
+      new sfCommandArgument('application', sfCommandArgument::REQUIRED, 'The application name'),
+      new sfCommandArgument('route_or_model', sfCommandArgument::REQUIRED, 'The route name or the model class'),
+    ));
+
+    $this->addOptions(array(
+      new sfCommandOption('module', null, sfCommandOption::PARAMETER_REQUIRED, 'The module name', null),
+      new sfCommandOption('theme', null, sfCommandOption::PARAMETER_REQUIRED, 'The theme name', 'admin'),
+      new sfCommandOption('singular', null, sfCommandOption::PARAMETER_REQUIRED, 'The singular name', null),
+      new sfCommandOption('plural', null, sfCommandOption::PARAMETER_REQUIRED, 'The plural name', null),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->namespace = 'doctrine';
+    $this->name = 'generate-admin';
+    $this->briefDescription = 'Generates a Doctrine admin module';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:generate-admin|INFO] task generates a Doctrine admin module:
+
+  [./symfony doctrine:generate-admin frontend Article|INFO]
+
+The task creates a module in the [%frontend%|COMMENT] application for the
+[%Article%|COMMENT] model.
+
+The task creates a route for you in the application [routing.yml|COMMENT].
+
+You can also generate a Doctrine admin module by passing a route name:
+
+  [./symfony doctrine:generate-admin frontend article|INFO]
+
+The task creates a module in the [%frontend%|COMMENT] application for the
+[%article%|COMMENT] route definition found in [routing.yml|COMMENT].
+
+For the filters and batch actions to work properly, you need to add
+the [wildcard|COMMENT] option to the route:
+
+  article:
+    class: sfDoctrineRouteCollection
+    options:
+      model:              Article
+      with_wildcard_routes:   true
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    // get configuration for the given route
+    if (false !== ($route = $this->getRouteFromName($arguments['route_or_model'])))
+    {
+      $arguments['route'] = $route;
+      $arguments['route_name'] = $arguments['route_or_model'];
+
+      return $this->generateForRoute($arguments, $options);
+    }
+
+    // is it a model class name
+    if (!class_exists($arguments['route_or_model']))
+    {
+      throw new sfCommandException(sprintf('The route "%s" does not exist and there is no "%s" class.', $arguments['route_or_model'], $arguments['route_or_model']));
+    }
+
+    $r = new ReflectionClass($arguments['route_or_model']);
+    if (!$r->isSubclassOf('Doctrine_Record'))
+    {
+      throw new sfCommandException(sprintf('"%s" is not a Doctrine class.', $arguments['route_or_model']));
+    }
+
+    // create a route
+    $model = $arguments['route_or_model'];
+    $name = strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), '\\1_\\2', $model));
+    $name = $options['module'] ? $name . '_' . $options['module'] : $name;
+
+    $routing = sfConfig::get('sf_app_config_dir').'/routing.yml';
+    $content = file_get_contents($routing);
+    $routesArray = sfYaml::load($content);
+
+    if (!isset($routesArray[$name]))
+    {
+      $databaseManager = new sfDatabaseManager($this->configuration);
+      $primaryKey = Doctrine::getTable($model)->getIdentifier();
+      $module = $options['module'] ? $options['module'] : $name;
+      $content = sprintf(<<<EOF
+%s:
+  class: sfDoctrineRouteCollection
+  options:
+    model:                %s
+    module:               %s
+    prefix_path:          %s
+    column:               %s
+    with_wildcard_routes: true
+
+
+EOF
+      , $name, $model, $module, $module, $primaryKey).$content;
+
+      file_put_contents($routing, $content);
+    }
+
+    $arguments['route'] = $this->getRouteFromName($name);
+    $arguments['route_name'] = $name;
+
+    return $this->generateForRoute($arguments, $options);
+  }
+
+  protected function generateForRoute($arguments, $options)
+  {
+    $routeOptions = $arguments['route']->getOptions();
+
+    if (!$arguments['route'] instanceof sfDoctrineRouteCollection)
+    {
+      throw new sfCommandException(sprintf('The route "%s" is not a Doctrine collection route.', $arguments['route_name']));
+    }
+
+    $module = $routeOptions['module'];
+    $model = $routeOptions['model'];
+
+    // execute the doctrine:generate-module task
+    $task = new sfDoctrineGenerateModuleTask($this->dispatcher, $this->formatter);
+    $task->setCommandApplication($this->commandApplication);
+
+    $taskOptions = array(
+      '--theme='.$options['theme'],
+      '--env='.$options['env'],
+      '--route-prefix='.$routeOptions['name'],
+      '--with-doctrine-route',
+      '--generate-in-cache',
+      '--non-verbose-templates',
+    );
+
+    if (!is_null($options['singular']))
+    {
+      $taskOptions[] = '--singular='.$options['singular'];
+    }
+
+    if (!is_null($options['plural']))
+    {
+      $taskOptions[] = '--plural='.$options['plural'];
+    }
+
+    $this->logSection('app', sprintf('Generating admin module "%s" for model "%s"', $module, $model));
+
+    return $task->run(array($arguments['application'], $module, $model), $taskOptions);
+  }
+
+  protected function getRouteFromName($name)
+  {
+    $config = new sfRoutingConfigHandler();
+    $routes = $config->evaluate($this->configuration->getConfigPaths('config/routing.yml'));
+
+    if (isset($routes[$name]))
+    {
+      return $routes[$name];
+    }
+
+    return false;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineGenerateMigrationTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Inserts SQL for current model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineGenerateMigrationTask.class.php 14213 2008-12-19 21:03:13Z Jonathan.Wage $
+ */
+class sfDoctrineGenerateMigrationTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addArguments(array(
+      new sfCommandArgument('name', sfCommandArgument::REQUIRED, 'The name of the migration'),
+    ));
+
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->aliases = array('doctrine-generate-migration');
+    $this->namespace = 'doctrine';
+    $this->name = 'generate-migration';
+    $this->briefDescription = 'Generate migration class';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:generate-migration|INFO] task generates migration template
+
+  [./symfony doctrine:generate-migration|INFO]
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $this->logSection('doctrine', sprintf('generating migration class named "%s"', $arguments['name']));
+
+    $databaseManager = new sfDatabaseManager($this->configuration);
+    $this->callDoctrineCli('generate-migration', array('name' => $arguments['name']));
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineGenerateMigrationsDbTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Generate migrations from database
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineGenerateMigrationsDbTask.class.php 14213 2008-12-19 21:03:13Z Jonathan.Wage $
+ */
+class sfDoctrineGenerateMigrationsDbTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->aliases = array('doctrine-generate-migrations-db', 'doctrine-gen-migrations-from-db');
+    $this->namespace = 'doctrine';
+    $this->name = 'generate-migrations-db';
+    $this->briefDescription = 'Generate migration classes from existing database connections';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:generate-migration|INFO] task generates migration classes from existing database connections
+
+  [./symfony doctrine:generate-migration|INFO]
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $this->logSection('doctrine', 'generating migration classes from database');
+
+    $databaseManager = new sfDatabaseManager($this->configuration);
+    $this->callDoctrineCli('generate-migrations-db');
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineGenerateMigrationsModelsTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Inserts SQL for current model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineGenerateMigrationsModelsTask.class.php 14213 2008-12-19 21:03:13Z Jonathan.Wage $
+ */
+class sfDoctrineGenerateMigrationsModelsTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->aliases = array('doctrine-generate-migrations-models', 'doctrine-gen-migrations-from-models');
+    $this->namespace = 'doctrine';
+    $this->name = 'generate-migrations-models';
+    $this->briefDescription = 'Generate migration classes from an existing set of models';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:generate-migration|INFO] task generates migration classes from an existing set of models
+
+  [./symfony doctrine:generate-migration|INFO]
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $this->logSection('doctrine', 'generating migration classes from models');
+
+    $databaseManager = new sfDatabaseManager($this->configuration);
+    $this->callDoctrineCli('generate-migrations-models');
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineGenerateModuleForRouteTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,114 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Generates a Doctrine module for a route definition.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: sfDoctrineGenerateModuleForRouteTask.class.php 12161 2008-10-13 07:42:25Z fabien $
+ */
+class sfDoctrineGenerateModuleForRouteTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addArguments(array(
+      new sfCommandArgument('application', sfCommandArgument::REQUIRED, 'The application name'),
+      new sfCommandArgument('route', sfCommandArgument::REQUIRED, 'The route name'),
+    ));
+
+    $this->addOptions(array(
+      new sfCommandOption('theme', null, sfCommandOption::PARAMETER_REQUIRED, 'The theme name', 'default'),
+      new sfCommandOption('non-verbose-templates', null, sfCommandOption::PARAMETER_NONE, 'Generate non verbose templates'),
+      new sfCommandOption('singular', null, sfCommandOption::PARAMETER_REQUIRED, 'The singular name', null),
+      new sfCommandOption('plural', null, sfCommandOption::PARAMETER_REQUIRED, 'The plural name', null),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->namespace = 'doctrine';
+    $this->name = 'generate-module-for-route';
+    $this->briefDescription = 'Generates a Doctrine module for a route definition';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:generate-module-for-route|INFO] task generates a Doctrine module for a route definition:
+
+  [./symfony doctrine:generate-module-for-route frontend article|INFO]
+
+The task creates a module in the [%frontend%|COMMENT] application for the
+[%article%|COMMENT] route definition found in [routing.yml|COMMENT].
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    // get configuration for the given route
+    $config = new sfRoutingConfigHandler();
+    $routes = $config->evaluate($this->configuration->getConfigPaths('config/routing.yml'));
+
+    if (!isset($routes[$arguments['route']]))
+    {
+      throw new sfCommandException(sprintf('The route "%s" does not exist.', $arguments['route']));
+    }
+
+    $routeOptions = $routes[$arguments['route']]->getOptions();
+
+    if (!$routes[$arguments['route']] instanceof sfDoctrineRouteCollection)
+    {
+      throw new sfCommandException(sprintf('The route "%s" is not a Doctrine collection route.', $arguments['route']));
+    }
+
+    $module = $routeOptions['module'];
+    $model = $routeOptions['model'];
+
+    // execute the doctrine:generate-module task
+    $task = new sfDoctrineGenerateModuleTask($this->dispatcher, $this->formatter);
+    $task->setCommandApplication($this->commandApplication);
+
+    $taskOptions = array(
+      '--theme='.$options['theme'],
+      '--env='.$options['env'],
+      '--route-prefix='.$routeOptions['name'],
+      '--with-doctrine-route',
+    );
+
+    if ($routeOptions['with_show'])
+    {
+      $taskOptions[] = '--with-show';
+    }
+
+    if ($options['non-verbose-templates'])
+    {
+      $taskOptions[] = '--non-verbose-templates';
+    }
+
+    if (!is_null($options['singular']))
+    {
+      $taskOptions[] = '--singular='.$options['singular'];
+    }
+
+    if (!is_null($options['plural']))
+    {
+      $taskOptions[] = '--plural='.$options['plural'];
+    }
+
+    $this->logSection('app', sprintf('Generating module "%s" for model "%s"', $module, $model));
+
+    return $task->run(array($arguments['application'], $module, $model), $taskOptions);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineGenerateModuleTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,214 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Generates a Doctrine module.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: sfDoctrineGenerateModuleTask.class.php 12474 2008-10-31 10:41:27Z fabien $
+ */
+class sfDoctrineGenerateModuleTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addArguments(array(
+      new sfCommandArgument('application', sfCommandArgument::REQUIRED, 'The application name'),
+      new sfCommandArgument('module', sfCommandArgument::REQUIRED, 'The module name'),
+      new sfCommandArgument('model', sfCommandArgument::REQUIRED, 'The model class name'),
+    ));
+
+    $this->addOptions(array(
+      new sfCommandOption('theme', null, sfCommandOption::PARAMETER_REQUIRED, 'The theme name', 'default'),
+      new sfCommandOption('generate-in-cache', null, sfCommandOption::PARAMETER_NONE, 'Generate the module in cache'),
+      new sfCommandOption('non-verbose-templates', null, sfCommandOption::PARAMETER_NONE, 'Generate non verbose templates'),
+      new sfCommandOption('with-show', null, sfCommandOption::PARAMETER_NONE, 'Generate a show method'),
+      new sfCommandOption('singular', null, sfCommandOption::PARAMETER_REQUIRED, 'The singular name', null),
+      new sfCommandOption('plural', null, sfCommandOption::PARAMETER_REQUIRED, 'The plural name', null),
+      new sfCommandOption('route-prefix', null, sfCommandOption::PARAMETER_REQUIRED, 'The route prefix', null),
+      new sfCommandOption('with-doctrine-route', null, sfCommandOption::PARAMETER_NONE, 'Whether you will use a Doctrine route'),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->aliases = array('doctrine-generate-crud', 'doctrine:generate-crud');
+    $this->namespace = 'doctrine';
+    $this->name = 'generate-module';
+    $this->briefDescription = 'Generates a Doctrine module';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:generate-module|INFO] task generates a Doctrine module:
+
+  [./symfony doctrine:generate-module frontend article Article|INFO]
+
+The task creates a [%module%|COMMENT] module in the [%application%|COMMENT] application
+for the model class [%model%|COMMENT].
+
+You can also create an empty module that inherits its actions and templates from
+a runtime generated module in [%sf_app_cache_dir%/modules/auto%module%|COMMENT] by
+using the [--generate-in-cache|COMMENT] option:
+
+  [./symfony doctrine:generate-module --generate-in-cache frontend article Article|INFO]
+
+The generator can use a customized theme by using the [--theme|COMMENT] option:
+
+  [./symfony doctrine:generate-module --theme="custom" frontend article Article|INFO]
+
+This way, you can create your very own module generator with your own conventions.
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $databaseManager = new sfDatabaseManager($this->configuration);
+    
+    $properties = parse_ini_file(sfConfig::get('sf_config_dir').'/properties.ini', true);
+
+    $this->constants = array(
+      'PROJECT_NAME'   => isset($properties['symfony']['name']) ? $properties['symfony']['name'] : 'symfony',
+      'APP_NAME'       => $arguments['application'],
+      'MODULE_NAME'    => $arguments['module'],
+      'UC_MODULE_NAME' => ucfirst($arguments['module']),
+      'MODEL_CLASS'    => $arguments['model'],
+      'AUTHOR_NAME'    => isset($properties['symfony']['author']) ? $properties['symfony']['author'] : 'Your name here',
+    );
+
+    $method = $options['generate-in-cache'] ? 'executeInit' : 'executeGenerate';
+
+    $this->$method($arguments, $options);
+  }
+
+  protected function executeGenerate($arguments = array(), $options = array())
+  {
+    // generate module
+    $tmpDir = sfConfig::get('sf_cache_dir').DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.md5(uniqid(rand(), true));
+    $generatorManager = new sfGeneratorManager($this->configuration, $tmpDir);
+    $generatorManager->generate('sfDoctrineGenerator', array(
+      'model_class'           => $arguments['model'],
+      'moduleName'            => $arguments['module'],
+      'theme'                 => $options['theme'],
+      'non_verbose_templates' => $options['non-verbose-templates'],
+      'with_show'             => $options['with-show'],
+      'singular'              => $options['singular'],
+      'plural'                => $options['plural'],
+      'route_prefix'          => $options['route-prefix'],
+      'with_doctrine_route'     => $options['with-doctrine-route'],
+    ));
+
+    $moduleDir = sfConfig::get('sf_app_module_dir').'/'.$arguments['module'];
+
+    // copy our generated module
+    $this->getFilesystem()->mirror($tmpDir.DIRECTORY_SEPARATOR.'auto'.ucfirst($arguments['module']), $moduleDir, sfFinder::type('any'));
+
+    if (!$options['with-show'])
+    {
+      $this->getFilesystem()->remove($moduleDir.'/templates/showSuccess.php');
+    }
+
+    // change module name
+    $finder = sfFinder::type('file')->name('*.php');
+    $this->getFilesystem()->replaceTokens($finder->in($moduleDir), '', '', array('auto'.ucfirst($arguments['module']) => $arguments['module']));
+
+    // customize php and yml files
+    $finder = sfFinder::type('file')->name('*.php', '*.yml');
+    $this->getFilesystem()->replaceTokens($finder->in($moduleDir), '##', '##', $this->constants);
+
+    // create basic test
+    $this->getFilesystem()->copy(sfConfig::get('sf_symfony_lib_dir').DIRECTORY_SEPARATOR.'task'.DIRECTORY_SEPARATOR.'generator'.DIRECTORY_SEPARATOR.'skeleton'.DIRECTORY_SEPARATOR.'module'.DIRECTORY_SEPARATOR.'test'.DIRECTORY_SEPARATOR.'actionsTest.php', sfConfig::get('sf_test_dir').DIRECTORY_SEPARATOR.'functional'.DIRECTORY_SEPARATOR.$arguments['application'].DIRECTORY_SEPARATOR.$arguments['module'].'ActionsTest.php');
+
+    // customize test file
+    $this->getFilesystem()->replaceTokens(sfConfig::get('sf_test_dir').DIRECTORY_SEPARATOR.'functional'.DIRECTORY_SEPARATOR.$arguments['application'].DIRECTORY_SEPARATOR.$arguments['module'].'ActionsTest.php', '##', '##', $this->constants);
+
+    // delete temp files
+    $this->getFilesystem()->remove(sfFinder::type('any')->in($tmpDir));
+  }
+
+  protected function executeInit($arguments = array(), $options = array())
+  {
+    $moduleDir = sfConfig::get('sf_app_module_dir').'/'.$arguments['module'];
+
+    // create basic application structure
+    $finder = sfFinder::type('any')->discard('.sf');
+    $dirs = $this->configuration->getGeneratorSkeletonDirs('sfDoctrineModule', $options['theme']);
+
+    foreach ($dirs as $dir)
+    {
+      if (is_dir($dir))
+      {
+        $this->getFilesystem()->mirror($dir, $moduleDir, $finder);
+        break;
+      }
+    }
+
+    // move configuration file
+    if (file_exists($config = $moduleDir.'/lib/configuration.php'))
+    {
+      if (file_exists($target = $moduleDir.'/lib/'.$arguments['module'].'GeneratorConfiguration.class.php'))
+      {
+        $this->getFilesystem()->remove($config);
+      }
+      else
+      {
+        $this->getFilesystem()->rename($config, $target);
+      }
+    }
+
+    // move helper file
+    if (file_exists($config = $moduleDir.'/lib/helper.php'))
+    {
+      if (file_exists($target = $moduleDir.'/lib/'.$arguments['module'].'GeneratorHelper.class.php'))
+      {
+        $this->getFilesystem()->remove($config);
+      }
+      else
+      {
+        $this->getFilesystem()->rename($config, $target);
+      }
+    }
+
+    // create basic test
+    $this->getFilesystem()->copy(sfConfig::get('sf_symfony_lib_dir').DIRECTORY_SEPARATOR.'task'.DIRECTORY_SEPARATOR.'generator'.DIRECTORY_SEPARATOR.'skeleton'.DIRECTORY_SEPARATOR.'module'.DIRECTORY_SEPARATOR.'test'.DIRECTORY_SEPARATOR.'actionsTest.php', sfConfig::get('sf_test_dir').DIRECTORY_SEPARATOR.'functional'.DIRECTORY_SEPARATOR.$arguments['application'].DIRECTORY_SEPARATOR.$arguments['module'].'ActionsTest.php');
+
+    // customize test file
+    $this->getFilesystem()->replaceTokens(sfConfig::get('sf_test_dir').DIRECTORY_SEPARATOR.'functional'.DIRECTORY_SEPARATOR.$arguments['application'].DIRECTORY_SEPARATOR.$arguments['module'].'ActionsTest.php', '##', '##', $this->constants);
+
+    // customize php and yml files
+    $finder = sfFinder::type('file')->name('*.php', '*.yml');
+    $this->constants['CONFIG'] = sprintf(<<<EOF
+    model_class:           %s
+    theme:                 %s
+    non_verbose_templates: %s
+    with_show:             %s
+    singular:              %s
+    plural:                %s
+    route_prefix:          %s
+    with_doctrine_route:     %s
+EOF
+    ,
+      $arguments['model'],
+      $options['theme'],
+      $options['non-verbose-templates'] ? 'true' : 'false',
+      $options['with-show'] ? 'true' : 'false',
+      $options['singular'] ? $options['singular'] : '~',
+      $options['plural'] ? $options['plural'] : '~',
+      $options['route-prefix'] ? $options['route-prefix'] : '~',
+      $options['with-doctrine-route'] ? $options['with-doctrine-route'] : 'false'
+    );
+    $this->getFilesystem()->replaceTokens($finder->in($moduleDir), '##', '##', $this->constants);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineInsertSqlTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Inserts SQL for current model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineInsertSqlTask.class.php 14255 2008-12-22 19:41:42Z Jonathan.Wage $
+ */
+class sfDoctrineInsertSqlTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->aliases = array('doctrine-insert-sql');
+    $this->namespace = 'doctrine';
+    $this->name = 'insert-sql';
+    $this->briefDescription = 'Inserts SQL for current model';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:insert-sql|INFO] task creates database tables:
+
+  [./symfony doctrine:insert-sql|INFO]
+
+The task connects to the database and creates tables for all the
+[lib/model/doctrine/*.php|COMMENT] files.
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $this->logSection('doctrine', 'created tables successfully');
+
+    $databaseManager = new sfDatabaseManager($this->configuration);
+    Doctrine::loadModels(sfConfig::get('sf_lib_dir') . '/model/doctrine', Doctrine::MODEL_LOADING_CONSERVATIVE);
+    Doctrine::createTablesFromArray(Doctrine::getLoadedModels());
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineMigrateTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Inserts SQL for current model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineMigrateTask.class.php 14213 2008-12-19 21:03:13Z Jonathan.Wage $
+ */
+class sfDoctrineMigrateTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addArguments(array(
+      new sfCommandArgument('version', sfCommandArgument::OPTIONAL, 'The version to migrate to', null),
+    ));
+
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+    ));
+
+    $this->aliases = array('doctrine-migrate');
+    $this->namespace = 'doctrine';
+    $this->name = 'migrate';
+    $this->briefDescription = 'Migrates database to current/specified version';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:migrate|INFO] task migrates database to current/specified version
+
+  [./symfony doctrine:migrate|INFO]
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $databaseManager = new sfDatabaseManager($this->configuration);
+
+    $this->callDoctrineCli('migrate', array('version' => $arguments['version']));
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/task/sfDoctrineRebuildDbTask.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfDoctrineBaseTask.class.php');
+
+/**
+ * Creates database for current model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineRebuildDbTask.class.php 16087 2009-03-07 22:08:50Z Kris.Wallsmith $
+ */
+class sfDoctrineRebuildDbTask extends sfDoctrineBaseTask
+{
+  /**
+   * @see sfTask
+   */
+  protected function configure()
+  {
+    $this->addOptions(array(
+      new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+      new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
+      new sfCommandOption('no-confirmation', null, sfCommandOption::PARAMETER_NONE, 'Whether to no-confirmation dropping of the database')
+    ));
+
+    $this->aliases = array('doctrine-rebuild-db');
+    $this->namespace = 'doctrine';
+    $this->name = 'rebuild-db';
+    $this->briefDescription = 'Creates database for current model';
+
+    $this->detailedDescription = <<<EOF
+The [doctrine:rebuild-db|INFO] task creates the database:
+
+  [./symfony doctrine:rebuild-db|INFO]
+
+The task read connection information in [config/doctrine/databases.yml|COMMENT]:
+EOF;
+  }
+
+  /**
+   * @see sfTask
+   */
+  protected function execute($arguments = array(), $options = array())
+  {
+    $baseOptions = $this->configuration instanceof sfApplicationConfiguration ? array(
+      '--application='.$this->configuration->getApplication(),
+      '--env='.$options['env'],
+    ) : array();
+
+    $dropDbOptions = $baseOptions;
+    if (isset($options['no-confirmation']) && $options['no-confirmation'])
+    {
+      $dropDbOptions[] = '--no-confirmation';
+    }
+
+    $dropDb = new sfDoctrineDropDbTask($this->dispatcher, $this->formatter);
+    $dropDb->setCommandApplication($this->commandApplication);
+    $dropDb->run(array(), $dropDbOptions);
+
+    $buildAll = new sfDoctrineBuildAllTask($this->dispatcher, $this->formatter);
+    $buildAll->setCommandApplication($this->commandApplication);
+    $buildAll->run(array(), $baseOptions);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/test/sfTesterDoctrine.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,103 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfTesterDoctrine implements tests for Doctrine classes.
+ *
+ * @package    symfony
+ * @subpackage test
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: sfTesterDoctrine.class.php 12237 2008-10-17 22:25:25Z Kris.Wallsmith $
+ */
+class sfTesterDoctrine extends sfTester
+{
+  /**
+   * Prepares the tester.
+   */
+  public function prepare()
+  {
+  }
+
+  /**
+   * Initializes the tester.
+   */
+  public function initialize()
+  {
+  }
+
+  /**
+   * Tests a model.
+   *
+   * @param string         $model    The model class name
+   * @param array|Doctrine_Query $query A Doctrine_Query object or an array of conditions
+   * @param string         $value    The value to test
+   *
+   * @return sfTestFunctionalBase|sfTester
+   */
+  public function check($model, $query, $value = true)
+  {
+    if (is_null($query))
+    {
+      $query = Doctrine::getTable($model)
+        ->createQuery('a');
+    }
+
+    if (is_array($query))
+    {
+      $conditions = $query;
+      $query = $query = Doctrine::getTable($model)
+        ->createQuery('a');
+      foreach ($conditions as $column => $condition)
+      {
+        $column = Doctrine::getTable($model)->getFieldName($column);
+
+        if (is_null($condition))
+        {
+          $query->andWhere('a.'.$column.' IS NULL');
+          continue;
+        }
+
+        $operator = '=';
+        if ('!' == $condition[0])
+        {
+          $operator = false !== strpos($condition, '%') ? 'NOT LIKE' : '!=';
+          $condition = substr($condition, 1);
+        }
+        else if (false !== strpos($condition, '%'))
+        {
+          $operator = 'LIKE';
+        }
+
+        $query->andWhere('a.' . $column . ' ' . $operator . ' ?', $condition);
+      }
+    }
+
+    $objects = $query->execute();
+
+    if (false === $value)
+    {
+      $this->tester->is(count($objects), 0, sprintf('no %s object that matches the criteria has been found', $model));
+    }
+    else if (true === $value)
+    {
+      $this->tester->cmp_ok(count($objects), '>', 0, sprintf('%s objects that matches the criteria have been found', $model));
+    }
+    else if (is_int($value))
+    {
+      $this->tester->is(count($objects), $value, sprintf('"%s" %s objects have been found', $value, $model));
+    }
+    else
+    {
+      throw new InvalidArgumentException('The "check()" method does not takes this kind of argument.');
+    }
+
+    return $this->getObjectToReturn();
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/validator/sfDoctrineUniqueValidator.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,114 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfDoctrineUniqueValidator validates that the value does not already exists
+ *
+ * <b>Required parameters:</b>
+ *
+ * # <b>class</b>         - [none]               - Doctrine class name.
+ * # <b>column</b>        - [none]               - Doctrine column name.
+ *
+ * <b>Optional parameters:</b>
+ *
+ * # <b>unique_error</b>  - [Uniqueness error]   - An error message to use when
+ *                                                the value for this column already
+ *                                                exists in the database.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfDoctrineUniqueValidator.class.php 11629 2008-09-17 22:22:25Z Jonathan.Wage $
+ */
+class sfDoctrineUniqueValidator extends sfValidator
+{
+  /**
+   * execute
+   *
+   * @param string $value
+   * @param string $error
+   * @return void
+   */
+  public function execute(&$value, &$error)
+  {
+    $className  = $this->getParameter('class');
+    $columnName = $className.'.'.$this->getParameter('column');
+
+    $primaryKeys = Doctrine::getTable($className)->getIdentifier();
+    if (!is_array($primaryKeys))
+    {
+      $primaryKeys = array($primaryKeys);
+    }
+
+    // implied assumption: the is at least one primary key
+    foreach ($primaryKeys as $primaryKey)
+    {
+      if (is_null($primaryKeyValue = $this->getContext()->getRequest()->getParameter($primaryKey)))
+      {
+        break;
+      }
+    }
+
+    $query = Doctrine_Query::create()
+              ->from($className);
+
+    if ($primaryKeyValue == null)
+    {
+      $query->where($columnName.' = ?');
+      $res = $query->execute(array($value));
+    } else {
+      $query->where($columnName.' = ? AND '.$primaryKey.' != ?');
+      $res = $query->execute(array($value, $primaryKeyValue));
+    }
+
+    if ($res->count())
+    {
+      $error = $this->getParameterHolder()->get('unique_error');
+
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * Initialize this validator.
+   *
+   * @param sfContext The current application context.
+   * @param array   An associative array of initialization parameters.
+   *
+   * @return bool true, if initialization completes successfully, otherwise false.
+   */
+  public function initialize($context, $parameters = null)
+  {
+    // initialize parent
+    parent::initialize($context);
+
+    // set defaults
+    $this->setParameter('unique_error', 'Uniqueness error');
+
+    $this->getParameterHolder()->add($parameters);
+
+    // check parameters
+    if (!$this->getParameter('class'))
+    {
+      throw new sfValidatorException('The "class" parameter is mandatory for the sfDoctrineUniqueValidator validator.');
+    }
+
+    if (!$this->getParameter('column'))
+    {
+      throw new sfValidatorException('The "column" parameter is mandatory for the sfDoctrineUniqueValidator validator.');
+    }
+
+    return true;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/validator/sfValidatorDoctrineChoice.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,87 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfValidatorDoctrineChoice validates that the value is one of the rows of a table.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfValidatorDoctrineChoice.class.php 8804 2008-05-06 12:11:10Z fabien $
+ */
+class sfValidatorDoctrineChoice extends sfValidatorBase
+{
+  /**
+   * Configures the current validator.
+   *
+   * Available options:
+   *
+   *  * model:      The model class (required)
+   *  * alias:      The alias of the root component used in the query
+   *  * query:      A query to use when retrieving objects
+   *  * column:     The column name (null by default which means we use the primary key)
+   *                must be in field name format
+   *  * connection: The Doctrine connection to use (null by default)
+   *
+   * @see sfValidatorBase
+   */
+  protected function configure($options = array(), $messages = array())
+  {
+    $this->addRequiredOption('model');
+    $this->addOption('alias', 'a');
+    $this->addOption('query', null);
+    $this->addOption('column', null);
+    $this->addOption('connection', null);
+  }
+
+  /**
+   * @see sfValidatorBase
+   */
+  protected function doClean($value)
+  {
+    $a = ($q = $this->getOption('query')) ? $q->getRootAlias():$this->getOption('alias');
+    $q = is_null($this->getOption('query')) ? Doctrine_Query::create()->from($this->getOption('model') . ' ' . $a) : $this->getOption('query');
+    $q->addWhere($a . '.' . $this->getColumn() . ' = ?', $value);
+
+    $object = $q->fetchOne();
+    
+    if (!$object)
+    {
+      throw new sfValidatorError($this, 'invalid', array('value' => $value));
+    }
+
+    return $value;
+  }
+
+  /**
+   * Returns the column to use for comparison.
+   *
+   * The primary key is used by default.
+   *
+   * @return string The column name
+   */
+  protected function getColumn()
+  {
+    $table = Doctrine::getTable($this->getOption('model'));
+    if ($this->getOption('column'))
+    {
+      $columnName = $this->getOption('column');
+    }
+    else
+    {
+      $identifier = (array) $table->getIdentifier();
+      $columnName = current($identifier);
+    }
+
+    return $table->getColumnName($columnName);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/validator/sfValidatorDoctrineChoiceMany.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfValidatorDoctrineChoiceMany validates than an array of values is in the array of the existing rows of a table.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfValidatorDoctrineChoiceMany.class.php 7902 2008-03-15 13:17:33Z fabien $
+ */
+class sfValidatorDoctrineChoiceMany extends sfValidatorDoctrineChoice
+{
+  /**
+   * @see sfValidatorBase
+   */
+  protected function doClean($values)
+  {
+    if (!is_array($values))
+    {
+      $values = array($values);
+    }
+
+    if(isset($values[0]) && !$values[0])
+    {
+      unset($values[0]);
+    }
+
+    $a = $this->getOption('alias');
+    $q = is_null($this->getOption('query')) ? Doctrine_Query::create()->from($this->getOption('model') . ' ' . $a) : $this->getOption('query');
+    $q = $q->andWhereIn($a . '.' . $this->getColumn(), $values);
+
+    $objects = $q->execute();
+
+    if (count($objects) != count($values))
+    {
+      throw new sfValidatorError($this, 'invalid', array('value' => $values));
+    }
+
+    return $values;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/validator/sfValidatorDoctrineUnique.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,163 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfValidatorDoctrineUnique validates that the uniqueness of a column.
+ *
+ * Warning: sfValidatorDoctrineUnique is susceptible to race conditions.
+ * To avoid this issue, wrap the validation process and the model saving
+ * inside a transaction.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfValidatorDoctrineUnique.class.php 8807 2008-05-06 14:12:28Z fabien $
+ */
+class sfValidatorDoctrineUnique extends sfValidatorSchema
+{
+  /**
+   * Constructor.
+   *
+   * @param array  An array of options
+   * @param array  An array of error messages
+   *
+   * @see sfValidatorSchema
+   */
+  public function __construct($options = array(), $messages = array())
+  {
+    parent::__construct(null, $options, $messages);
+  }
+
+  /**
+   * Configures the current validator.
+   *
+   * Available options:
+   *
+   *  * model:              The model class (required)
+   *  * column:             The unique column name in Doctrine field name format (required)
+   *                        If the uniquess is for several columns, you can pass an array of field names
+   *  * primary_key:        The primary key column name in Doctrine field name format (optional, will be introspected if not provided)
+   *                        You can also pass an array if the table has several primary keys
+   *  * connection:         The Doctrine connection to use (null by default)
+   *  * throw_global_error: Whether to throw a global error (true by default) or an error tied to the first field related to the column option array
+   *
+   * @see sfValidatorBase
+   */
+  protected function configure($options = array(), $messages = array())
+  {
+    $this->addRequiredOption('model');
+    $this->addRequiredOption('column');
+    $this->addOption('primary_key', null);
+    $this->addOption('connection', null);
+    $this->addOption('throw_global_error', true);
+
+    $this->setMessage('invalid', 'An object with the same "%column%" already exist.');
+  }
+
+  /**
+   * @see sfValidatorBase
+   */
+  protected function doClean($values)
+  {
+    $originalValues = $values;
+    $table = Doctrine::getTable($this->getOption('model'));
+    if (!is_array($this->getOption('column')))
+    {
+      $this->setOption('column', array($this->getOption('column')));
+    }
+
+    //if $values isn't an array, make it one
+    if (!is_array($values))
+    {
+      //use first column for key
+      $columns = $this->getOption('column');
+      $values = array($columns[0] => $values);
+    }
+
+    $q = Doctrine_Query::create()
+          ->from($this->getOption('model') . ' a');
+
+    foreach ($this->getOption('column') as $column)
+    {
+      $colName = $table->getColumnName($column);
+      if (!array_key_exists($column, $values))
+      {
+        // one of the column has be removed from the form
+        return $originalValues;
+      }
+
+      $q->addWhere('a.' . $colName . ' = ?', $values[$column]);
+    }
+
+    $object = $q->fetchOne();
+
+    // if no object or if we're updating the object, it's ok
+    if (!$object || $this->isUpdate($object, $values))
+    {
+      return $originalValues;
+    }
+
+    $error = new sfValidatorError($this, 'invalid', array('column' => implode(', ', $this->getOption('column'))));
+
+    if ($this->getOption('throw_global_error'))
+    {
+      throw $error;
+    }
+
+    $columns = $this->getOption('column');
+
+    throw new sfValidatorErrorSchema($this, array($columns[0] => $error));
+  }
+
+  /**
+   * Returns whether the object is being updated.
+   *
+   * @param BaseObject  A Doctrine object
+   * @param array       An array of values
+   *
+   * @param Boolean     true if the object is being updated, false otherwise
+   */
+  protected function isUpdate(Doctrine_Record $object, $values)
+  {
+    // check each primary key column
+    foreach ($this->getPrimaryKeys() as $column)
+    {
+      if (!isset($values[$column]) || $object->$column != $values[$column])
+      {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * Returns the primary keys for the model.
+   *
+   * @return array An array of primary keys
+   */
+  protected function getPrimaryKeys()
+  {
+    if (is_null($this->getOption('primary_key')))
+    {
+      $primaryKeys = Doctrine::getTable($this->getOption('model'))->getIdentifier();
+      $this->setOption('primary_key', $primaryKeys);
+    }
+
+    if (!is_array($this->getOption('primary_key')))
+    {
+      $this->setOption('primary_key', array($this->getOption('primary_key')));
+    }
+
+    return $this->getOption('primary_key');
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,1003 @@
+<?php
+/*
+ *  $Id: Doctrine.php 5885 2009-06-15 06:48:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine
+ * the base class of Doctrine framework
+ *
+ * @package     Doctrine
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5885 $
+ */
+final class Doctrine
+{
+    /**
+     * VERSION
+     */
+    const VERSION                   = '1.0.10';
+
+    /**
+     * ERROR CONSTANTS
+     */
+    const ERR                       = -1;
+    const ERR_SYNTAX                = -2;
+    const ERR_CONSTRAINT            = -3;
+    const ERR_NOT_FOUND             = -4;
+    const ERR_ALREADY_EXISTS        = -5;
+    const ERR_UNSUPPORTED           = -6;
+    const ERR_MISMATCH              = -7;
+    const ERR_INVALID               = -8;
+    const ERR_NOT_CAPABLE           = -9;
+    const ERR_TRUNCATED             = -10;
+    const ERR_INVALID_NUMBER        = -11;
+    const ERR_INVALID_DATE          = -12;
+    const ERR_DIVZERO               = -13;
+    const ERR_NODBSELECTED          = -14;
+    const ERR_CANNOT_CREATE         = -15;
+    const ERR_CANNOT_DELETE         = -16;
+    const ERR_CANNOT_DROP           = -17;
+    const ERR_NOSUCHTABLE           = -18;
+    const ERR_NOSUCHFIELD           = -19;
+    const ERR_NEED_MORE_DATA        = -20;
+    const ERR_NOT_LOCKED            = -21;
+    const ERR_VALUE_COUNT_ON_ROW    = -22;
+    const ERR_INVALID_DSN           = -23;
+    const ERR_CONNECT_FAILED        = -24;
+    const ERR_EXTENSION_NOT_FOUND   = -25;
+    const ERR_NOSUCHDB              = -26;
+    const ERR_ACCESS_VIOLATION      = -27;
+    const ERR_CANNOT_REPLACE        = -28;
+    const ERR_CONSTRAINT_NOT_NULL   = -29;
+    const ERR_DEADLOCK              = -30;
+    const ERR_CANNOT_ALTER          = -31;
+    const ERR_MANAGER               = -32;
+    const ERR_MANAGER_PARSE         = -33;
+    const ERR_LOADMODULE            = -34;
+    const ERR_INSUFFICIENT_DATA     = -35;
+    const ERR_CLASS_NAME            = -36;
+
+    /**
+     * PDO derived constants
+     */
+    const CASE_LOWER = 2;
+    const CASE_NATURAL = 0;
+    const CASE_UPPER = 1;
+    const CURSOR_FWDONLY = 0;
+    const CURSOR_SCROLL = 1;
+    const ERRMODE_EXCEPTION = 2;
+    const ERRMODE_SILENT = 0;
+    const ERRMODE_WARNING = 1;
+    const FETCH_ASSOC = 2;
+    const FETCH_BOTH = 4;
+    const FETCH_BOUND = 6;
+    const FETCH_CLASS = 8;
+    const FETCH_CLASSTYPE = 262144;
+    const FETCH_COLUMN = 7;
+    const FETCH_FUNC = 10;
+    const FETCH_GROUP = 65536;
+    const FETCH_INTO = 9;
+    const FETCH_LAZY = 1;
+    const FETCH_NAMED = 11;
+    const FETCH_NUM = 3;
+    const FETCH_OBJ = 5;
+    const FETCH_ORI_ABS = 4;
+    const FETCH_ORI_FIRST = 2;
+    const FETCH_ORI_LAST = 3;
+    const FETCH_ORI_NEXT = 0;
+    const FETCH_ORI_PRIOR = 1;
+    const FETCH_ORI_REL = 5;
+    const FETCH_SERIALIZE = 524288;
+    const FETCH_UNIQUE = 196608;
+    const NULL_EMPTY_STRING = 1;
+    const NULL_NATURAL = 0;
+    const NULL_TO_STRING         = NULL;
+    const PARAM_BOOL = 5;
+    const PARAM_INPUT_OUTPUT = -2147483648;
+    const PARAM_INT = 1;
+    const PARAM_LOB = 3;
+    const PARAM_NULL = 0;
+    const PARAM_STMT = 4;
+    const PARAM_STR = 2;
+
+    /**
+     * ATTRIBUTE CONSTANTS
+     */
+
+    /**
+     * PDO derived attributes
+     */
+    const ATTR_AUTOCOMMIT           = 0;
+    const ATTR_PREFETCH             = 1;
+    const ATTR_TIMEOUT              = 2;
+    const ATTR_ERRMODE              = 3;
+    const ATTR_SERVER_VERSION       = 4;
+    const ATTR_CLIENT_VERSION       = 5;
+    const ATTR_SERVER_INFO          = 6;
+    const ATTR_CONNECTION_STATUS    = 7;
+    const ATTR_CASE                 = 8;
+    const ATTR_CURSOR_NAME          = 9;
+    const ATTR_CURSOR               = 10;
+    const ATTR_ORACLE_NULLS         = 11;
+    const ATTR_PERSISTENT           = 12;
+    const ATTR_STATEMENT_CLASS      = 13;
+    const ATTR_FETCH_TABLE_NAMES    = 14;
+    const ATTR_FETCH_CATALOG_NAMES  = 15;
+    const ATTR_DRIVER_NAME          = 16;
+    const ATTR_STRINGIFY_FETCHES    = 17;
+    const ATTR_MAX_COLUMN_LEN       = 18;
+
+    /**
+     * Doctrine constants
+     */
+    const ATTR_LISTENER             = 100;
+    const ATTR_QUOTE_IDENTIFIER     = 101;
+    const ATTR_FIELD_CASE           = 102;
+    const ATTR_IDXNAME_FORMAT       = 103;
+    const ATTR_SEQNAME_FORMAT       = 104;
+    const ATTR_SEQCOL_NAME          = 105;
+    const ATTR_CMPNAME_FORMAT       = 118;
+    const ATTR_DBNAME_FORMAT        = 117;
+    const ATTR_TBLCLASS_FORMAT      = 119;
+    const ATTR_TBLNAME_FORMAT       = 120;
+    const ATTR_EXPORT               = 140;
+    const ATTR_DECIMAL_PLACES       = 141;
+
+    const ATTR_PORTABILITY          = 106;
+    const ATTR_VALIDATE             = 107;
+    const ATTR_COLL_KEY             = 108;
+    const ATTR_QUERY_LIMIT          = 109;
+    const ATTR_DEFAULT_TABLE_TYPE   = 112;
+    const ATTR_DEF_TEXT_LENGTH      = 113;
+    const ATTR_DEF_VARCHAR_LENGTH   = 114;
+    const ATTR_DEF_TABLESPACE       = 115;
+    const ATTR_EMULATE_DATABASE     = 116;
+    const ATTR_USE_NATIVE_ENUM      = 117;
+    const ATTR_DEFAULT_SEQUENCE     = 133;
+
+    const ATTR_FETCHMODE                = 118;
+    const ATTR_NAME_PREFIX              = 121;
+    const ATTR_CREATE_TABLES            = 122;
+    const ATTR_COLL_LIMIT               = 123;
+
+    const ATTR_CACHE                    = 150;
+    const ATTR_RESULT_CACHE             = 150;
+    const ATTR_CACHE_LIFESPAN           = 151;
+    const ATTR_RESULT_CACHE_LIFESPAN    = 151;
+    const ATTR_LOAD_REFERENCES          = 153;
+    const ATTR_RECORD_LISTENER          = 154;
+    const ATTR_THROW_EXCEPTIONS         = 155;
+    const ATTR_DEFAULT_PARAM_NAMESPACE  = 156;
+    const ATTR_QUERY_CACHE              = 157;
+    const ATTR_QUERY_CACHE_LIFESPAN     = 158;
+    const ATTR_AUTOLOAD_TABLE_CLASSES   = 160;
+    const ATTR_MODEL_LOADING            = 161;
+    const ATTR_RECURSIVE_MERGE_FIXTURES = 162;
+    const ATTR_USE_DQL_CALLBACKS        = 164;
+    const ATTR_AUTO_ACCESSOR_OVERRIDE   = 165;
+    const ATTR_HYDRATE_OVERWRITE        = 166;
+
+    /**
+     * LIMIT CONSTANTS
+     */
+
+    /**
+     * constant for row limiting
+     */
+    const LIMIT_ROWS       = 1;
+    const QUERY_LIMIT_ROWS = 1;
+
+    /**
+     * constant for record limiting
+     */
+    const LIMIT_RECORDS       = 2;
+    const QUERY_LIMIT_RECORDS = 2;
+
+    /**
+     * FETCHMODE CONSTANTS
+     */
+
+
+    /**
+     * PORTABILITY CONSTANTS
+     */
+
+    /**
+     * Portability: turn off all portability features.
+     * @see self::ATTR_PORTABILITY
+     */
+    const PORTABILITY_NONE          = 0;
+
+    /**
+     * Portability: convert names of tables and fields to case defined in the
+     * "field_case" option when using the query*(), fetch*() methods.
+     * @see self::ATTR_PORTABILITY
+     */
+    const PORTABILITY_FIX_CASE      = 1;
+
+    /**
+     * Portability: right trim the data output by query*() and fetch*().
+     * @see self::ATTR_PORTABILITY
+     */
+    const PORTABILITY_RTRIM         = 2;
+
+    /**
+     * Portability: force reporting the number of rows deleted.
+     * @see self::ATTR_PORTABILITY
+     */
+    const PORTABILITY_DELETE_COUNT  = 4;
+
+    /**
+     * Portability: convert empty values to null strings in data output by
+     * query*() and fetch*().
+     * @see self::ATTR_PORTABILITY
+     */
+    const PORTABILITY_EMPTY_TO_NULL = 8;
+
+    /**
+     * Portability: removes database/table qualifiers from associative indexes
+     * @see self::ATTR_PORTABILITY
+     */
+    const PORTABILITY_FIX_ASSOC_FIELD_NAMES = 16;
+
+    /**
+     * Portability: makes Doctrine_Expression throw exception for unportable RDBMS expressions
+     * @see self::ATTR_PORTABILITY
+     */
+    const PORTABILITY_EXPR          = 32;
+
+    /**
+     * Portability: turn on all portability features.
+     * @see self::ATTR_PORTABILITY
+     */
+    const PORTABILITY_ALL           = 63;
+
+    /**
+     * LOCKMODE CONSTANTS
+     */
+
+    /**
+     * mode for optimistic locking
+     */
+    const LOCK_OPTIMISTIC       = 0;
+
+    /**
+     * mode for pessimistic locking
+     */
+    const LOCK_PESSIMISTIC      = 1;
+
+    /**
+     * EXPORT CONSTANTS
+     */
+
+    /**
+     * EXPORT_NONE
+     */
+    const EXPORT_NONE               = 0;
+
+    /**
+     * EXPORT_TABLES
+     */
+    const EXPORT_TABLES             = 1;
+
+    /**
+     * EXPORT_CONSTRAINTS
+     */
+    const EXPORT_CONSTRAINTS        = 2;
+
+    /**
+     * EXPORT_PLUGINS
+     */
+    const EXPORT_PLUGINS            = 4;
+
+    /**
+     * EXPORT_ALL
+     */
+    const EXPORT_ALL                = 7;
+
+    /**
+     * HYDRATION CONSTANTS
+     */
+    const HYDRATE_RECORD            = 2;
+
+    /**
+     * HYDRATE_ARRAY
+     */
+    const HYDRATE_ARRAY             = 3;
+
+    /**
+     * HYDRATE_NONE
+     */
+    const HYDRATE_NONE              = 4;
+
+    /**
+     * VALIDATION CONSTANTS
+     */
+    const VALIDATE_NONE             = 0;
+
+    /**
+     * VALIDATE_LENGTHS
+     */
+    const VALIDATE_LENGTHS          = 1;
+
+    /**
+     * VALIDATE_TYPES
+     */
+    const VALIDATE_TYPES            = 2;
+
+    /**
+     * VALIDATE_CONSTRAINTS
+     */
+    const VALIDATE_CONSTRAINTS      = 4;
+
+    /**
+     * VALIDATE_ALL
+     */
+    const VALIDATE_ALL              = 7;
+
+    /**
+     * IDENTIFIER_AUTOINC
+     *
+     * constant for auto_increment identifier
+     */
+    const IDENTIFIER_AUTOINC        = 1;
+
+    /**
+     * IDENTIFIER_SEQUENCE
+     *
+     * constant for sequence identifier
+     */
+    const IDENTIFIER_SEQUENCE       = 2;
+
+    /**
+     * IDENTIFIER_NATURAL
+     *
+     * constant for normal identifier
+     */
+    const IDENTIFIER_NATURAL        = 3;
+
+    /**
+     * IDENTIFIER_COMPOSITE
+     *
+     * constant for composite identifier
+     */
+    const IDENTIFIER_COMPOSITE      = 4;
+
+    /**
+     * MODEL_LOADING_AGGRESSIVE
+     *
+     * Constant for agressive model loading
+     * Will require_once() all found model files
+     */
+    const MODEL_LOADING_AGGRESSIVE   = 1;
+
+    /**
+     * MODEL_LOADING_CONSERVATIVE
+     *
+     * Constant for conservative model loading
+     * Will not require_once() found model files inititally instead it will build an array
+     * and reference it in autoload() when a class is needed it will require_once() it
+     */
+    const MODEL_LOADING_CONSERVATIVE= 2;
+
+    /**
+     * Path to Doctrine root
+     *
+     * @var string $path            doctrine root directory
+     */
+    private static $_path;
+
+    /**
+     * Debug bool true/false option
+     *
+     * @var boolean $_debug
+     */
+    private static $_debug = false;
+
+    /**
+     * Array of all the loaded models and the path to each one for autoloading
+     *
+     * @var array
+     */
+    private static $_loadedModelFiles = array();
+
+    /**
+     * Array of all the loaded validators
+     *
+     * @var array
+     */
+    private static $_validators = array();
+
+    /**
+     * __construct
+     *
+     * @return void
+     * @throws Doctrine_Exception
+     */
+    public function __construct()
+    {
+        throw new Doctrine_Exception('Doctrine is static class. No instances can be created.');
+    }
+
+    /**
+     * Returns an array of all the loaded models and the path where each of them exists
+     *
+     * @return array
+     */
+    public static function getLoadedModelFiles()
+    {
+        return self::$_loadedModelFiles;
+    }
+
+    /**
+     * Turn on/off the debugging setting
+     *
+     * @param string $bool
+     * @return void
+     */
+    public static function debug($bool = null)
+    {
+        if ($bool !== null) {
+            self::$_debug = (bool) $bool;
+        }
+
+        return self::$_debug;
+    }
+
+    /**
+     * Get the root path to Doctrine
+     *
+     * @return string
+     */
+    public static function getPath()
+    {
+        if ( ! self::$_path) {
+            self::$_path = dirname(__FILE__);
+        }
+
+        return self::$_path;
+    }
+
+    /**
+     * Load an individual model name and path in to the model loading registry
+     *
+     * @return null
+     */
+    public static function loadModel($className, $path = null)
+    {
+        self::$_loadedModelFiles[$className] = $path;
+    }
+
+    /**
+     * Recursively load all models from a directory or array of directories
+     *
+     * @param  string   $directory      Path to directory of models or array of directory paths
+     * @param  integer  $modelLoading   Pass value of Doctrine::ATTR_MODEL_LOADING to force a certain style of model loading
+     *                                  Allowed Doctrine::MODEL_LOADING_AGGRESSIVE(default) or Doctrine::MODEL_LOADING_CONSERVATIVE
+     */
+    public static function loadModels($directory, $modelLoading = null)
+    {
+        $manager = Doctrine_Manager::getInstance();
+
+        $modelLoading = $modelLoading === null ? $manager->getAttribute(Doctrine::ATTR_MODEL_LOADING):$modelLoading;
+
+        $loadedModels = array();
+
+        if ($directory !== null) {
+            foreach ((array) $directory as $dir) {
+                if ( ! is_dir($dir)) {
+                    throw new Doctrine_Exception('You must pass a valid path to a directory containing Doctrine models');
+                }
+
+                $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) {
+                        $className = $e[0];
+
+                        if ($modelLoading == Doctrine::MODEL_LOADING_CONSERVATIVE) {
+                            self::loadModel($className, $file->getPathName());
+
+                            $loadedModels[$className] = $className;
+                        } else {
+                            $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) - 1);
+                            if ($foundClasses) {
+                                foreach ($foundClasses as $className) {
+                                    if (self::isValidModelClass($className)) {
+                                        $loadedModels[$className] = $className;
+
+                                        self::loadModel($className, $file->getPathName());
+                                    }
+                                }
+                            }
+                            $previouslyLoaded = array_keys(self::$_loadedModelFiles, $file->getPathName());
+                            if ( ! empty($previouslyLoaded)) {
+                                $previouslyLoaded = array_combine(array_values($previouslyLoaded), array_values($previouslyLoaded));
+                                $loadedModels = array_merge($loadedModels, $previouslyLoaded);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return $loadedModels;
+    }
+
+    /**
+     * Get all the loaded models, you can provide an array of classes or it will use get_declared_classes()
+     *
+     * Will filter through an array of classes and return the Doctrine_Records out of them.
+     * If you do not specify $classes it will return all of the currently loaded Doctrine_Records
+     *
+     * @param classes  Array of classes to filter through, otherwise uses get_declared_classes()
+     * @return array   $loadedModels
+     */
+    public static function getLoadedModels($classes = null)
+    {
+        if ($classes === null) {
+            $classes = get_declared_classes();
+            $classes = array_merge($classes, array_keys(self::$_loadedModelFiles));
+        }
+
+        return self::filterInvalidModels($classes);
+    }
+
+    /**
+     * Initialize all models so everything is present and loaded in to memory
+     * This will also inheritently initialize any model behaviors and add
+     * the models generated by Doctrine generators and add them to the $models
+     * array
+     *
+     * @param string $models
+     * @return array $models
+     */
+    public static function initializeModels($models)
+    {
+        $models = self::filterInvalidModels($models);
+
+        foreach ($models as $model) {
+            $declaredBefore = get_declared_classes();
+            Doctrine::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);
+            foreach ($foundClasses as $class) {
+                if (self::isValidModelClass($class)) {
+                    $models[] = $class;
+                }
+            }
+        }
+
+        $models = self::filterInvalidModels($models);
+
+        return $models;
+    }
+
+    /**
+     * Filter through an array of classes and return all the classes that are valid models.
+     * This will inflect the class, causing it to be loaded in to memory.
+     *
+     * @param classes  Array of classes to filter through, otherwise uses get_declared_classes()
+     * @return array   $loadedModels
+     */
+    public static function filterInvalidModels($classes)
+    {
+        $validModels = array();
+
+        foreach ((array) $classes as $name) {
+            if (self::isValidModelClass($name) && ! in_array($name, $validModels)) {
+                $validModels[] = $name;
+            }
+        }
+
+        return $validModels;
+    }
+
+    /**
+     * Checks if what is passed is a valid Doctrine_Record
+     * Will load class in to memory in order to inflect it and find out information about the class
+     *
+     * @param   mixed   $class Can be a string named after the class, an instance of the class, or an instance of the class reflected
+     * @return  boolean
+     */
+    public static function isValidModelClass($class)
+    {
+        if ($class instanceof Doctrine_Record) {
+            $class = get_class($class);
+        }
+
+        if (is_string($class) && class_exists($class)) {
+            $class = new ReflectionClass($class);
+        }
+
+        if ($class instanceof ReflectionClass) {
+            // Skip the following classes
+            // - abstract classes
+            // - not a subclass of Doctrine_Record
+            if ( ! $class->isAbstract() && $class->isSubClassOf('Doctrine_Record')) {
+
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Get the connection object for a table by the actual table name
+     * FIXME: I think this method is flawed because a individual connections could have the same table name
+     *
+     * @param string $tableName
+     * @return Doctrine_Connection
+     */
+    public static function getConnectionByTableName($tableName)
+    {
+        $loadedModels = self::getLoadedModels();
+
+        foreach ($loadedModels as $name) {
+            $table = Doctrine::getTable($name);
+
+            if ($table->getTableName() == $tableName) {
+               return $table->getConnection();
+            }
+        }
+
+        return Doctrine_Manager::connection();
+    }
+
+    /**
+     * Method for importing existing schema to Doctrine_Record classes
+     *
+     * @param string $directory Directory to write your models to
+     * @param array $databases Array of databases to generate models for
+     * @param array $options Array of options
+     * @return boolean
+     * @throws Exception
+     */
+    public static function generateModelsFromDb($directory, array $databases = array(), array $options = array())
+    {
+        return Doctrine_Manager::connection()->import->importSchema($directory, $databases, $options);
+    }
+
+    /**
+     * Generates models from database to temporary location then uses those models to generate a yaml schema file.
+     * This should probably be fixed. We should write something to generate a yaml schema file directly from the database.
+     *
+     * @param string $yamlPath Path to write oyur yaml schema file to
+     * @param array  $options Array of options
+     * @return void
+     */
+    public static function generateYamlFromDb($yamlPath, array $databases = array(), array $options = array())
+    {
+        $directory = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'tmp_doctrine_models';
+
+        $options['generateBaseClasses'] = isset($options['generateBaseClasses']) ? $options['generateBaseClasses']:false;
+        $result = Doctrine::generateModelsFromDb($directory, $databases, $options);
+
+        if ( empty($result) && ! is_dir($directory)) {
+            throw new Doctrine_Exception('No models generated from your databases');
+        }
+
+        $export = new Doctrine_Export_Schema();
+
+        $result = $export->exportSchema($yamlPath, 'yml', $directory);
+
+        Doctrine_Lib::removeDirectories($directory);
+
+        return $result;
+    }
+
+    /**
+     * Generate a yaml schema file from an existing directory of models
+     *
+     * @param string $yamlPath Path to your yaml schema files
+     * @param string $directory Directory to generate your models in
+     * @param array  $options Array of options to pass to the schema importer
+     * @return void
+     */
+    public static function generateModelsFromYaml($yamlPath, $directory, $options = array())
+    {
+        $import = new Doctrine_Import_Schema();
+        $import->setOptions($options);
+
+        return $import->importSchema($yamlPath, 'yml', $directory);
+    }
+
+    /**
+     * Creates database tables for the models in the specified directory
+     *
+     * @param string $directory Directory containing your models
+     * @return void
+     */
+    public static function createTablesFromModels($directory = null)
+    {
+        return Doctrine_Manager::connection()->export->exportSchema($directory);
+    }
+
+    /**
+     * Creates database tables for the models in the supplied array
+     *
+     * @param array $array An array of models to be exported
+     * @return void
+     */
+    public static function createTablesFromArray($array)
+    {
+        return Doctrine_Manager::connection()->export->exportClasses($array);
+    }
+
+    /**
+     * Generate a array of sql for the passed array of models
+     *
+     * @param  array $array
+     * @return array $sql
+     */
+    public static function generateSqlFromArray($array)
+    {
+        return Doctrine_Manager::connection()->export->exportClassesSql($array);
+    }
+
+    /**
+     * Generate a sql string to create the tables from all loaded models
+     * or the models found in the passed directory.
+     *
+     * @param  string $directory
+     * @return string $build  String of sql queries. One query per line
+     */
+    public static function generateSqlFromModels($directory = null)
+    {
+        $conn = Doctrine_Manager::connection();
+        $sql = $conn->export->exportSql($directory);
+
+        $build = '';
+        foreach ($sql as $query) {
+            $build .= $query.$conn->sql_file_delimiter;
+        }
+
+        return $build;
+    }
+
+    /**
+     * Generate yaml schema file for the models in the specified directory
+     *
+     * @param string $yamlPath Path to your yaml schema files
+     * @param string $directory Directory to generate your models in
+     * @return void
+     */
+    public static function generateYamlFromModels($yamlPath, $directory)
+    {
+        $export = new Doctrine_Export_Schema();
+
+        return $export->exportSchema($yamlPath, 'yml', $directory);
+    }
+
+    /**
+     * Creates databases for connections
+     *
+     * @param string $specifiedConnections Array of connections you wish to create the database for
+     * @return void
+     */
+    public static function createDatabases($specifiedConnections = array())
+    {
+        return Doctrine_Manager::getInstance()->createDatabases($specifiedConnections);
+    }
+
+    /**
+     * Drops databases for connections
+     *
+     * @param string $specifiedConnections Array of connections you wish to drop the database for
+     * @return void
+     */
+    public static function dropDatabases($specifiedConnections = array())
+    {
+        return Doctrine_Manager::getInstance()->dropDatabases($specifiedConnections);
+    }
+
+    /**
+     * Dump data to a yaml fixtures file
+     *
+     * @param string $yamlPath Path to write the yaml data fixtures to
+     * @param string $individualFiles Whether or not to dump data to individual fixtures files
+     * @return void
+     */
+    public static function dumpData($yamlPath, $individualFiles = false)
+    {
+        $data = new Doctrine_Data();
+
+        return $data->exportData($yamlPath, 'yml', array(), $individualFiles);
+    }
+
+    /**
+     * Load data from a yaml fixtures file.
+     * The output of dumpData can be fed to loadData
+     *
+     * @param string $yamlPath Path to your yaml data fixtures
+     * @param string $append Whether or not to append the data
+     * @return void
+     */
+    public static function loadData($yamlPath, $append = false)
+    {
+        $data = new Doctrine_Data();
+
+        return $data->importData($yamlPath, 'yml', array(), $append);
+    }
+
+    /**
+     * Migrate database to specified $to version. Migrates from current to latest if you do not specify.
+     *
+     * @param string $migrationsPath Path to migrations directory which contains your migration classes
+     * @param string $to Version you wish to migrate to.
+     * @return bool true
+     * @throws new Doctrine_Migration_Exception
+     */
+    public static function migrate($migrationsPath, $to = null)
+    {
+        $migration = new Doctrine_Migration($migrationsPath);
+
+        return $migration->migrate($to);
+    }
+
+    /**
+     * Generate new migration class skeleton
+     *
+     * @param string $className Name of the Migration class to generate
+     * @param string $migrationsPath Path to directory which contains your migration classes
+     */
+    public static function generateMigrationClass($className, $migrationsPath)
+    {
+        $builder = new Doctrine_Migration_Builder($migrationsPath);
+
+        return $builder->generateMigrationClass($className);
+    }
+
+    /**
+     * Generate a set of migration classes from an existing database
+     *
+     * @param string $migrationsPath
+     * @return void
+     * @throws new Doctrine_Migration_Exception
+     */
+    public static function generateMigrationsFromDb($migrationsPath)
+    {
+        $builder = new Doctrine_Migration_Builder($migrationsPath);
+
+        return $builder->generateMigrationsFromDb();
+    }
+
+    /**
+     * Generate a set of migration classes from an existing set of models
+     *
+     * @param string  $migrationsPath Path to your Doctrine migration classes
+     * @param string  $modelsPath     Path to your Doctrine model classes
+     * @param integer $modelLoading   Style of model loading to use for loading the models in order to generate migrations
+     * @return void
+     */
+    public static function generateMigrationsFromModels($migrationsPath, $modelsPath = null, $modelLoading = null)
+    {
+        $builder = new Doctrine_Migration_Builder($migrationsPath);
+
+        return $builder->generateMigrationsFromModels($modelsPath, $modelLoading);
+    }
+
+    /**
+     * Get the Doctrine_Table object for the passed model
+     *
+     * @param string $componentName
+     * @return Doctrine_Table
+     */
+    public static function getTable($componentName)
+    {
+        return Doctrine_Manager::getInstance()->getConnectionForComponent($componentName)->getTable($componentName);
+    }
+
+    /**
+     * Method for making a single file of most used doctrine runtime components
+     * including the compiled file instead of multiple files (in worst
+     * cases dozens of files) can improve performance by an order of magnitude
+     *
+     * @param string $target
+     * @param array  $includedDrivers
+     * @throws Doctrine_Exception
+     * @return void
+     */
+    public static function compile($target = null, $includedDrivers = array())
+    {
+        return Doctrine_Compiler::compile($target, $includedDrivers);
+    }
+
+    /**
+     * simple autoload function
+     * returns true if the class was loaded, otherwise false
+     *
+     * @param string $classname
+     * @return boolean
+     */
+    public static function autoload($className)
+    {
+        if (class_exists($className, false) || interface_exists($className, false)) {
+            return false;
+        }
+
+        $class = self::getPath() . DIRECTORY_SEPARATOR . str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
+
+        if (file_exists($class)) {
+            require $class;
+
+            return true;
+        }
+
+        $loadedModels = self::$_loadedModelFiles;
+
+        if (isset($loadedModels[$className]) && file_exists($loadedModels[$className])) {
+            require $loadedModels[$className];
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * dumps a given variable
+     *
+     * @param mixed $var        a variable of any type
+     * @param boolean $output   whether to output the content
+     * @param string $indent    indention string
+     * @return void|string
+     */
+    public static function dump($var, $output = true, $indent = "")
+    {
+        $ret = array();
+        switch (gettype($var)) {
+            case 'array':
+                $ret[] = 'Array(';
+                $indent .= "    ";
+                foreach ($var as $k => $v) {
+
+                    $ret[] = $indent . $k . ' : ' . self::dump($v, false, $indent);
+                }
+                $indent = substr($indent,0, -4);
+                $ret[] = $indent . ")";
+                break;
+            case 'object':
+                $ret[] = 'Object(' . get_class($var) . ')';
+                break;
+            default:
+                $ret[] = var_export($var, true);
+        }
+
+        if ($output) {
+            print implode("\n", $ret);
+        }
+
+        return implode("\n", $ret);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Access.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,203 @@
+<?php
+/*
+ *  $Id: Access.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Provides array access and property overload interface for Doctrine subclasses
+ *
+ * @package     Doctrine
+ * @subpackage  Access
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+abstract class Doctrine_Access extends Doctrine_Locator_Injectable implements ArrayAccess
+{
+    /**
+     * Set an entire aray to the data
+     *
+     * @param   array $array An array of key => value pairs
+     * @return  Doctrine_Access
+     */
+    public function setArray(array $array)
+    {
+        foreach ($array as $k => $v) {
+            $this->set($k, $v);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Set key and value to data
+     *
+     * @see     set, offsetSet
+     * @param   $name
+     * @param   $value
+     * @return  void
+     */
+    public function __set($name, $value)
+    {
+        $this->set($name, $value);
+    }
+
+    /**
+     * Get key from data
+     *
+     * @see     get, offsetGet
+     * @param   mixed $name
+     * @return  mixed
+     */
+    public function __get($name)
+    {
+        return $this->get($name);
+    }
+
+    /**
+     * Check if key exists in data
+     *
+     * @param   string $name
+     * @return  boolean whether or not this object contains $name
+     */
+    public function __isset($name)
+    {
+        return $this->contains($name);
+    }
+
+    /**
+     * Remove key from data
+     *
+     * @param   string $name
+     * @return  void
+     */
+    public function __unset($name)
+    {
+        return $this->remove($name);
+    }
+
+    /**
+     * Check if an offset axists
+     *
+     * @param   mixed $offset
+     * @return  boolean Whether or not this object contains $offset
+     */
+    public function offsetExists($offset)
+    {
+        return $this->contains($offset);
+    }
+
+    /**
+     * An alias of get()
+     *
+     * @see     get, __get
+     * @param   mixed $offset
+     * @return  mixed
+     */
+    public function offsetGet($offset)
+    {
+        return $this->get($offset);
+    }
+
+    /**
+     * Sets $offset to $value
+     *
+     * @see     set, __set
+     * @param   mixed $offset
+     * @param   mixed $value
+     * @return  void
+     */
+    public function offsetSet($offset, $value)
+    {
+        if ( ! isset($offset)) {
+            $this->add($value);
+        } else {
+            $this->set($offset, $value);
+        }
+    }
+
+    /**
+     * Unset a given offset
+     *
+     * @see   set, offsetSet, __set
+     * @param mixed $offset
+     */
+    public function offsetUnset($offset)
+    {
+        return $this->remove($offset);
+    }
+
+    /**
+     * Remove the element with the specified offset
+     *
+     * @param mixed $offset The offset to remove
+     * @return boolean True if removed otherwise false
+     */
+    public function remove($offset)
+    {
+        throw new Doctrine_Exception('Remove is not supported for ' . get_class($this));
+    }
+
+    /**
+     * Return the element with the specified offset
+     *
+     * @param mixed $offset The offset to return
+     * @return mixed The value of the return object 
+     */
+    public function get($offset)
+    {
+        throw new Doctrine_Exception('Get is not supported for ' . get_class($this));
+    }
+
+    /**
+     * Set the offset to the value
+     *
+     * @param mixed $offset The offset to set
+     * @param mixed $value The value to set the offset to
+     *
+     */
+    public function set($offset, $value)
+    {
+        throw new Doctrine_Exception('Set is not supported for ' . get_class($this));
+    }
+
+    /**
+     * Check if the specified offset exists 
+     * 
+     * @param mixed $offset The offset to check
+     * @return boolean True if exists otherwise false
+     */
+    public function contains($offset)
+    {
+        throw new Doctrine_Exception('Contains is not supported for ' . get_class($this));
+    }
+
+    /**
+     * Add the value  
+     * 
+     * @param mixed $value The value to add 
+     * @return void
+     */
+    public function add($value)
+    {
+        throw new Doctrine_Exception('Add is not supported for ' . get_class($this));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,108 @@
+<?php
+/*
+ *  $Id: Adapter.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ *
+ * Doctrine_Adapter
+ *
+ * @package     Doctrine
+ * @subpackage  Adapter
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Adapter
+{
+    /**
+     * Adapter constant
+     */
+    const ATTR_AUTOCOMMIT = 0;
+    const ATTR_CASE = 8;
+    const ATTR_CLIENT_VERSION = 5;
+    const ATTR_CONNECTION_STATUS = 7;
+    const ATTR_CURSOR = 10;
+    const ATTR_CURSOR_NAME = 9;
+    const ATTR_DRIVER_NAME = 16;
+    const ATTR_ERRMODE = 3;
+    const ATTR_FETCH_CATALOG_NAMES = 15;
+    const ATTR_FETCH_TABLE_NAMES = 14;
+    const ATTR_MAX_COLUMN_LEN = 18;
+    const ATTR_ORACLE_NULLS = 11;
+    const ATTR_PERSISTENT = 12;
+    const ATTR_PREFETCH = 1;
+    const ATTR_SERVER_INFO = 6;
+    const ATTR_SERVER_VERSION = 4;
+    const ATTR_STATEMENT_CLASS = 13;
+    const ATTR_STRINGIFY_FETCHES = 17;
+    const ATTR_TIMEOUT = 2;
+    const CASE_LOWER = 2;
+    const CASE_NATURAL = 0;
+    const CASE_UPPER = 1;
+    const CURSOR_FWDONLY = 0;
+    const CURSOR_SCROLL = 1;
+    const ERR_ALREADY_EXISTS = NULL;
+    const ERR_CANT_MAP = NULL;
+    const ERR_CONSTRAINT = NULL;
+    const ERR_DISCONNECTED = NULL;
+    const ERR_MISMATCH = NULL;
+    const ERR_NO_PERM = NULL;
+    const ERR_NONE = '00000';
+    const ERR_NOT_FOUND = NULL;
+    const ERR_NOT_IMPLEMENTED = NULL;
+    const ERR_SYNTAX = NULL;
+    const ERR_TRUNCATED = NULL;
+    const ERRMODE_EXCEPTION = 2;
+    const ERRMODE_SILENT = 0;
+    const ERRMODE_WARNING = 1;
+    const FETCH_ASSOC = 2;
+    const FETCH_BOTH = 4;
+    const FETCH_BOUND = 6;
+    const FETCH_CLASS = 8;
+    const FETCH_CLASSTYPE = 262144;
+    const FETCH_COLUMN = 7;
+    const FETCH_FUNC = 10;
+    const FETCH_GROUP = 65536;
+    const FETCH_INTO = 9;
+    const FETCH_LAZY = 1;
+    const FETCH_NAMED = 11;
+    const FETCH_NUM = 3;
+    const FETCH_OBJ = 5;
+    const FETCH_ORI_ABS = 4;
+    const FETCH_ORI_FIRST = 2;
+    const FETCH_ORI_LAST = 3;
+    const FETCH_ORI_NEXT = 0;
+    const FETCH_ORI_PRIOR = 1;
+    const FETCH_ORI_REL = 5;
+    const FETCH_SERIALIZE = 524288;
+    const FETCH_UNIQUE = 196608;
+    const NULL_EMPTY_STRING = 1;
+    const NULL_NATURAL = 0;
+    const NULL_TO_STRING = NULL;
+    const PARAM_BOOL = 5;
+    const PARAM_INPUT_OUTPUT = -2147483648;
+    const PARAM_INT = 1;
+    const PARAM_LOB = 3;
+    const PARAM_NULL = 0;
+    const PARAM_STMT = 4;
+    const PARAM_STR = 2;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Db2.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,325 @@
+<?php
+/*
+ *  $Id: Mock.php 1080 2007-02-10 18:17:08Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * IBM DB2 Adapter. This class was ported from the Zend Framework
+ *
+ * @package     Doctrine
+ * @subpackage  Adapter
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ */
+class Doctrine_Adapter_Db2 extends Doctrine_Adapter
+{
+    /**
+     * User-provided configuration.
+     *
+     * Basic keys are:
+     *
+     * username   => (string)  Connect to the database as this username.
+     * password   => (string)  Password associated with the username.
+     * host       => (string)  What host to connect to (default 127.0.0.1)
+     * dbname     => (string)  The name of the database to user
+     * protocol   => (string)  Protocol to use, defaults to "TCPIP"
+     * port       => (integer) Port number to use for TCP/IP if protocol is "TCPIP"
+     * persistent => (boolean) Set TRUE to use a persistent connection (db2_pconnect)
+     *
+     * @var array
+     */
+    protected $_config = array(
+        'dbname'       => null,
+        'username'     => null,
+        'password'     => null,
+        'host'         => 'localhost',
+        'port'         => '50000',
+        'protocol'     => 'TCPIP',
+        'persistent'   => false
+    );
+
+    /**
+     * Stores the execution mode
+     *
+     * Possible values DB2_AUTOCOMMIT_ON or DB2_AUTOCOMMIT_OFF
+     *
+     * @var int execution flag (DB2_AUTOCOMMIT_ON or DB2_AUTOCOMMIT_OFF)
+     */
+    protected $_executeMode = DB2_AUTOCOMMIT_ON;
+
+    /**
+     * Table name of the last accessed table for an insert operation
+     * This is a DB2-Adapter-specific member variable with the utmost
+     * probability you might not find it in other adapters...
+     *
+     * @var string
+     */
+    protected $_lastInsertTable = null;
+
+     /**
+     * $config is an array of key/value pairs containing configuration
+     * options.  These options are common to most adapters:
+     *
+     * dbname         => (string) The name of the database to user
+     * username       => (string) Connect to the database as this username.
+     * password       => (string) Password associated with the username.
+     * host           => (string) What host to connect to, defaults to localhost
+     * port           => (string) The port of the database, defaults to 50000
+     * persistent     => (boolean) Whether to use a persistent connection or not, defaults to false
+     * protocol       => (string) The network protocol, defaults to TCPIP
+     * options        => (array)  Other database options such as autocommit, case, and cursor options
+     *
+     * @param array $config An array of configuration keys.
+     */
+    public function __construct(array $config)
+    {
+        if ( ! isset($config['password'])) {
+            throw new Doctrine_Adapter_Exception("Configuration array must have a key for 'password' for login credentials.");
+        }
+
+        if ( ! isset($config['username'])) {
+            throw new Doctrine_Adapter_Exception("Configuration array must have a key for 'username' for login credentials.");
+        }
+
+        if ( ! isset($config['dbname'])) {
+            throw new Doctrine_Adapter_Exception("Configuration array must have a key for 'dbname' that names the database instance.");
+        }
+
+        // keep the config
+        $this->_config = array_merge($this->_config, (array) $config);
+    }
+
+    /**
+     * Creates the connection resource
+     *
+     * @return void
+     */
+    protected function _connect()
+    {
+        if (is_resource($this->_connection)) {
+            // connection already exists
+            return;
+        }
+
+        if ( ! extension_loaded('ibm_db2')) {
+            throw new Doctrine_Adapter_Exception('The IBM DB2 extension is required for this adapter but not loaded');
+        }
+
+        if ($this->_config['persistent']) {
+            // use persistent connection
+            $conn_func_name = 'db2_pconnect';
+        } else {
+            // use "normal" connection
+            $conn_func_name = 'db2_connect';
+        }
+
+        if ( ! isset($this->_config['options'])) {
+            // config options were not set, so set it to an empty array
+            $this->_config['options'] = array();
+        }
+
+        if ( ! isset($this->_config['options']['autocommit'])) {
+            // set execution mode
+            $this->_config['options']['autocommit'] = &$this->_executeMode;
+        }
+
+        if ($this->_config['host'] !== 'localhost') {
+            // if the host isn't localhost, use extended connection params
+            $dbname = 'DRIVER={IBM DB2 ODBC DRIVER}' .
+                     ';DATABASE=' . $this->_config['dbname'] .
+                     ';HOSTNAME=' . $this->_config['host'] .
+                     ';PORT='     . $this->_config['port'] .
+                     ';PROTOCOL=' . $this->_config['protocol'] .
+                     ';UID='      . $this->_config['username'] .
+                     ';PWD='      . $this->_config['password'] .';';
+            $this->_connection = $conn_func_name(
+                $dbname,
+                null,
+                null,
+                $this->_config['options']
+            );
+        } else {
+            // host is localhost, so use standard connection params
+            $this->_connection = $conn_func_name(
+                $this->_config['dbname'],
+                $this->_config['username'],
+                $this->_config['password'],
+                $this->_config['options']
+            );
+        }
+
+        // check the connection
+        if ( ! $this->_connection) {
+            throw new Doctrine_Adapter_Exception(db2_conn_errormsg(), db2_conn_error());
+        }
+    }
+
+    /**
+     * Close the connection resource
+     *
+     * @return void
+     */
+    public function closeConnection()
+    {
+        db2_close($this->_connection);
+        $this->_connection = null;
+    }
+
+    /**
+     * Prepare a sql statement and return it
+     *
+     * @param   string $sql The SQL statement with placeholders.
+     * @return  Doctrine_Statement_Db2
+     */
+    public function prepare($sql)
+    {
+        $this->_connect();
+        $stmt = new Doctrine_Statement_Db2($this, $sql);
+        $stmt->setFetchMode($this->_fetchMode);
+        return $stmt;
+    }
+
+    /**
+     * Get the current execution mode
+     *
+     * @return int the execution mode (DB2_AUTOCOMMIT_ON or DB2_AUTOCOMMIT_OFF)
+     */
+    public function _getExecuteMode()
+    {
+        return $this->_executeMode;
+    }
+
+    /**
+     * Set the current execution mode
+     *
+     * @param   integer $mode
+     * @return  void
+     */
+    public function _setExecuteMode($mode)
+    {
+        switch ($mode) {
+            case DB2_AUTOCOMMIT_OFF:
+            case DB2_AUTOCOMMIT_ON:
+                $this->_executeMode = $mode;
+                db2_autocommit($this->_connection, $mode);
+                break;
+            default:
+                throw new Doctrine_Adapter_Exception("execution mode not supported");
+                break;
+        }
+    }
+
+    /**
+     * Quote a raw string.
+     *
+     * @param   string $value Raw string
+     * @return  string Quoted string
+     */
+    protected function _quote($value)
+    {
+        /**
+         * Some releases of the IBM DB2 extension appear
+         * to be missing the db2_escape_string() method.
+         * The method was added in ibm_db2.c revision 1.53
+         * according to cvs.php.net.  But the function is
+         * not present in my build of PHP 5.2.1.
+         */
+        if (function_exists('db2_escape_string')) {
+            return db2_escape_string($value);
+        }
+        return parent::_quote($value);
+    }
+
+    /**
+     * Get the symbol used for identifier quoting
+     *
+     * @return string
+     */
+    public function getQuoteIdentifierSymbol()
+    {
+        $info = db2_server_info($this->_connection);
+        $identQuote = $info->IDENTIFIER_QUOTE_CHAR;
+        return $identQuote;
+    }
+
+    /**
+     * Begin a transaction.
+     *
+     * @return void
+     */
+    protected function _beginTransaction()
+    {
+        $this->_setExecuteMode(DB2_AUTOCOMMIT_OFF);
+    }
+
+    /**
+     * Commit a transaction.
+     *
+     * @return void
+     */
+    protected function _commit()
+    {
+        if ( ! db2_commit($this->_connection)) {
+            throw new Doctrine_Adapter_Exception(
+                db2_conn_errormsg($this->_connection),
+                db2_conn_error($this->_connection));
+        }
+
+        $this->_setExecuteMode(DB2_AUTOCOMMIT_ON);
+    }
+
+    /**
+     * Rollback a transaction.
+     *
+     * @return void
+     */
+    protected function _rollBack()
+    {
+        if ( ! db2_rollback($this->_connection)) {
+            throw new Doctrine_Adapter_Exception(
+                db2_conn_errormsg($this->_connection),
+                db2_conn_error($this->_connection));
+        }
+        $this->_setExecuteMode(DB2_AUTOCOMMIT_ON);
+    }
+
+    /**
+     * Set the fetch mode.
+     *
+     * @param  integer $mode
+     * @return void
+     */
+    public function setFetchMode($mode)
+    {
+        switch ($mode) {
+            case Doctrine::FETCH_NUM:   // seq array
+            case Doctrine::FETCH_ASSOC: // assoc array
+            case Doctrine::FETCH_BOTH:  // seq+assoc array
+            case Doctrine::FETCH_OBJ:   // object
+                $this->_fetchMode = $mode;
+                break;
+            default:
+                throw new Doctrine_Adapter_Exception('Invalid fetch mode specified');
+                break;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Adapter exception class
+ *
+ * @package     Doctrine
+ * @subpackage  Adapter
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Adapter_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Interface.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: Interface.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * This adapter interface should be implemented by all custom adapters
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @package     Doctrine
+ * @subpackage  Adapter
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+interface Doctrine_Adapter_Interface
+{
+    public function prepare($prepareString);
+    public function query($queryString);
+    public function quote($input);
+    public function exec($statement);
+    public function lastInsertId();
+    public function beginTransaction();
+    public function commit();
+    public function rollBack();
+    public function errorCode();
+    public function errorInfo();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Mock.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,294 @@
+<?php
+/*
+ *  $Id: Mock.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine mock connection adapter. This class is used for special testing purposes.
+ *
+ * @package     Doctrine
+ * @subpackage  Adapter
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Adapter_Mock implements Doctrine_Adapter_Interface, Countable
+{
+    /**
+     * Name of the dbms to mock
+     *
+     * @var string
+     */
+    private $_name;
+
+    /**
+     * Array of queries executed through this instance of the mock adapter
+     *
+     * @var array $queries
+     */
+    private $_queries = array();
+
+    /**
+     * Array of exceptions thrown
+     *
+     * @var array $exceptions
+     */
+    private $_exception = array();
+
+    /**
+     * Bool true/false variable for whether or not the last insert failed
+     *
+     * @var boolean $lastInsertIdFail
+     */
+    private $_lastInsertIdFail = false;
+
+    /**
+     * Doctrine mock adapter constructor
+     *
+     * <code>
+     * $conn = new Doctrine_Adapter_Mock('mysql');
+     * </code>
+     *
+     * @param string $name 
+     * @return void
+     */
+    public function __construct($name = null)
+    {
+        $this->_name = $name;
+    }
+
+    /**
+     * Get the name of the dbms used in this instance of the mock adapter
+     *
+     * @return string $name Name of the dbms
+     */
+    public function getName()
+    {
+        return $this->_name;
+    }
+
+    /**
+     * Pop the last executed query from the array of executed queries and return it
+     *
+     * @return string $sql Last executed sql string
+     */
+    public function pop()
+    {
+        return array_pop($this->_queries);
+    }
+
+    /**
+     * Force an exception in to the array of exceptions
+     *
+     * @param string $name     Name of exception
+     * @param string $message  Message for the exception
+     * @param integer $code    Code of the exception
+     * @return void
+     */
+    public function forceException($name, $message = '', $code = 0)
+    {
+        $this->_exception = array($name, $message, $code);
+    }
+
+    /**
+     * Prepare a query statement
+     *
+     * @param string $query   Query to prepare
+     * @return Doctrine_Adapter_Statement_Mock $mock Mock prepared statement
+     */
+    public function prepare($query)
+    {
+        $mock = new Doctrine_Adapter_Statement_Mock($this, $query);
+        $mock->queryString = $query;
+
+        return $mock;
+    }
+
+    /**
+     * Add query to the stack of executed queries
+     *
+     * @param string $query 
+     * @return void
+     */
+    public function addQuery($query)
+    {
+        $this->_queries[] = $query;
+    }
+
+    /**
+     * Fake the execution of query and add it to the stack of executed queries
+     *
+     * @param string $query 
+     * @return Doctrine_Adapter_Statement_Mock $stmt
+     */
+    public function query($query)
+    {
+        $this->_queries[] = $query;
+
+        $e    = $this->_exception;
+
+        if ( ! empty($e)) {
+            $name = $e[0];
+
+            $this->_exception = array();
+
+            throw new $name($e[1], $e[2]);
+        }
+
+        $stmt = new Doctrine_Adapter_Statement_Mock($this, $query);
+        $stmt->queryString = $query;
+
+        return $stmt;
+    }
+
+    /**
+     * Get all the executed queries
+     *
+     * @return array $queries Array of all executed queries
+     */
+    public function getAll()
+    {
+        return $this->_queries;
+    }
+
+    /**
+     * Quote a value for the dbms
+     *
+     * @param string $input 
+     * @return string $quoted
+     */
+    public function quote($input)
+    {
+        return "'" . addslashes($input) . "'";
+    }
+
+    /**
+     * Execute a raw sql statement
+     *
+     * @param string $statement 
+     * @return void
+     */
+    public function exec($statement)
+    {
+        $this->_queries[] = $statement;
+
+        $e    = $this->_exception;
+
+        if ( ! empty($e)) {
+            $name = $e[0];
+
+            $this->_exception = array();
+
+            throw new $name($e[1], $e[2]);
+        }
+
+        return 0;
+    }
+
+    /**
+     * Force last insert to be failed
+     *
+     * @param boolean $fail
+     * @return void
+     */
+    public function forceLastInsertIdFail($fail = true)
+    {
+        if ($fail) {
+            $this->_lastInsertIdFail = true;
+        } else {
+            $this->_lastInsertIdFail = false;
+        }
+    }
+
+    /**
+     * Get the id of the last inserted record
+     *
+     * @return integer $id
+     */
+    public function lastInsertId()
+    {
+        $this->_queries[] = 'LAST_INSERT_ID()';
+        if ($this->_lastInsertIdFail) {
+            return null;
+        } else {
+            return 1;
+        }
+    }
+
+    /**
+     * Get the number of queries executed
+     *
+     * @return integer $count
+     */
+    public function count()
+    {
+        return count($this->_queries);
+    }
+
+    /**
+     * Begin a transaction
+     *
+     * @return void
+     */
+    public function beginTransaction()
+    {
+        $this->_queries[] = 'BEGIN TRANSACTION';
+    }
+
+    /**
+     * Commit a transaction
+     *
+     * @return void
+     */
+    public function commit()
+    {
+        $this->_queries[] = 'COMMIT';
+    }
+
+    /**
+     * Rollback a transaction
+     *
+     * @return void
+     */
+    public function rollBack()
+    {
+        $this->_queries[] = 'ROLLBACK';
+    }
+
+    public function getAttribute($attribute)
+    {
+        if ($attribute == Doctrine::ATTR_DRIVER_NAME) {
+            return strtolower($this->_name);
+        }
+    }
+
+    public function errorCode()
+    { }
+
+    public function errorInfo()
+    { }
+
+    public function setAttribute($attribute, $value)
+    { }
+
+    public function sqliteCreateFunction()
+    { }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Mysqli.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,142 @@
+<?php
+/*
+ *  $Id: Mock.php 1080 2007-02-10 18:17:08Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Custom Doctrine connection adapter for mysqli
+ *
+ * @package     Doctrine
+ * @subpackage  Adapter
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ */
+class Doctrine_Adapter_Mysqli extends Doctrine_Adapter
+{
+    /**
+     * Creates a connection to the database.
+     *
+     * @return void
+     * @throws Doctrine_Adapter_Exception
+     */
+    protected function _connect()
+    {
+        if ($this->_connection) {
+            return;
+        }
+        // Suppress connection warnings here.
+        // Throw an exception instead.
+        @$this->_connection = new mysqli(
+            $this->_config['host'],
+            $this->_config['username'],
+            $this->_config['password'],
+            $this->_config['dbname']
+        );
+        if ($this->_connection === false || mysqli_connect_errno()) {
+            throw new Doctrine_Adapter_Exception(mysqli_connect_error());
+        }
+    }
+
+    /**
+     * Force the connection to close.
+     *
+     * @return void
+     */
+    public function closeConnection()
+    {
+        $this->_connection->close();
+        $this->_connection = null;
+    }
+
+    /**
+     * Prepare a statement and return a PDOStatement-like object.
+     *
+     * @param  string  $sql  SQL query
+     * @return Doctrine_Statement_Mysqli
+     */
+    public function prepare($sql)
+    {
+        $this->_connect();
+        $stmt = new Doctrine_Statement_Mysqli($this, $sql);
+        $stmt->setFetchMode($this->_fetchMode);
+        return $stmt;
+    }
+
+    /**
+     * lastInsertId
+     *
+     * Gets the last ID generated automatically by an IDENTITY/AUTOINCREMENT column.
+     *
+     * As a convention, on RDBMS brands that support sequences
+     * (e.g. Oracle, PostgreSQL, DB2), this method forms the name of a sequence
+     * from the arguments and returns the last id generated by that sequence.
+     * On RDBMS brands that support IDENTITY/AUTOINCREMENT columns, this method
+     * returns the last value generated for such a column, and the table name
+     * argument is disregarded.
+     *
+     * MySQL does not support sequences, so $tableName and $primaryKey are ignored.
+     *
+     * @param string $tableName   OPTIONAL Name of table.
+     * @param string $primaryKey  OPTIONAL Name of primary key column.
+     * @return integer
+     */
+    public function lastInsertId($tableName = null, $primaryKey = null)
+    {
+        $mysqli = $this->_connection;
+        return $mysqli->insert_id;
+    }
+
+    /**
+     * Begin a transaction.
+     *
+     * @return void
+     */
+    protected function _beginTransaction()
+    {
+        $this->_connect();
+        $this->_connection->autocommit(false);
+    }
+
+    /**
+     * Commit a transaction.
+     *
+     * @return void
+     */
+    protected function _commit()
+    {
+        $this->_connect();
+        $this->_connection->commit();
+        $this->_connection->autocommit(true);
+    }
+
+    /**
+     * Roll-back a transaction.
+     *
+     * @return void
+     */
+    protected function _rollBack()
+    {
+        $this->_connect();
+        $this->_connection->rollback();
+        $this->_connection->autocommit(true);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Oracle.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,287 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Custom Doctrine connection adapter for oracle
+ *
+ * @package     Doctrine
+ * @subpackage  Adapter
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      vadik56
+ * @author      Miloslav Kmet <adrive-nospam@hip-hop.sk>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ */
+
+class Doctrine_Adapter_Oracle implements Doctrine_Adapter_Interface{
+    /**
+     *    execution mode
+     */
+    protected $executeMode = OCI_COMMIT_ON_SUCCESS;
+
+    /**
+     * Resource representing connection to database
+     */
+    protected $connection = false;
+
+
+    protected $attributes = array(Doctrine::ATTR_DRIVER_NAME    => "oci8",
+                                  Doctrine::ATTR_ERRMODE        => Doctrine::ERRMODE_SILENT);
+
+    /**
+     * User-provided configuration.
+     *
+     * Basic keys are:
+     *
+     * username => (string) Connect to the database as this username.
+     * password => (string) Password associated with the username.
+     * dbname   => Either the name of the local Oracle instance, or the
+     *             name of the entry in tnsnames.ora to which you want to connect.
+     *
+     * @var array
+     */
+    protected $config = array('dbname'   => null,
+                              'username' => null,
+                              'password' => null,
+                              'charset'  => null);
+
+    /**
+     * Doctrine Oracle adapter constructor
+     *
+     * <code>
+     * $conn = new Doctrine_Adapter_Oracle(array('dbname'=>'db','username'=>'usr','password'=>'pass'));
+     * </code>
+     *
+     * or
+     *
+     * <code>
+     * Doctrine_Manager::connection(array('oracle:dbname=SID;charset=NLS_CHARACTERSET','usr', 'pass'),"doctrine_connection_name")
+     * </code>
+     *
+     * @param string $name
+     * @return void
+     */
+    public function __construct($config = array(), $username = null, $password = null)
+    {
+        if (is_string($config))
+        {
+            $config = str_replace("oracle:","",$config);
+            $parts = explode(";", $config);
+            foreach($parts as $part) {
+                list($var, $value)=explode("=", $part);
+                switch($var)
+                {
+                    case 'dbname':
+                        $this->config['dbname'] = $value;
+                        break;
+                    case 'charset':
+                        $this->config['charset'] = $value;
+                        break;
+                }
+            }
+
+            $this->config['username'] = $username;
+            $this->config['password'] = $password;
+        } else {
+            if ( ! isset($config['password']) || ! isset($config['username'])) {
+                throw new Doctrine_Adapter_Exception('config array must have at least a username and a password');
+            }
+
+            $this->config['username'] = $config['username'];
+            $this->config['password'] = $config['password'];
+            $this->config['dbname']   = $config['dbname'];
+            $this->config['charset']  = $config['charset'];
+        }
+
+        $this->connection = @oci_connect($this->config['username'], $this->config['password'],
+                                             $this->config['dbname'], $this->config['charset']);
+
+        if ($this->connection === false) {
+            throw new Doctrine_Adapter_Exception(sprintf("Unable to Connect to :'%s' as '%s'", $this->config['dbname'], $this->config['username']));
+        }
+    }
+
+    /**
+     * Prepare a query statement
+     *
+     * @param string $query Query to prepare
+     * @return Doctrine_Adapter_Statement_Oracle $stmt prepared statement
+     */
+    public function prepare($query)
+    {
+        $stmt = new Doctrine_Adapter_Statement_Oracle($this, $query, $this->executeMode);
+
+        return $stmt;
+    }
+
+    /**
+     * Execute query and return results as statement object
+     *
+     * @param string $query
+     * @return Doctrine_Adapter_Statement_Oracle $stmt
+     */
+    public function query($query)
+    {
+        $stmt = new Doctrine_Adapter_Statement_Oracle($this, $query, $this->executeMode);
+        $stmt->execute();
+
+        return $stmt;
+    }
+
+    /**
+     * Quote a value for the dbms
+     *
+     * @param string $input
+     * @return string $quoted
+     */
+    public function quote($input)
+    {
+        return "'" . str_replace("'","''",$input) . "'";
+    }
+
+    /**
+     * Execute a raw sql statement
+     *
+     * @param string $statement
+     * @return void
+     */
+    public function exec($statement)
+    {
+        $stmt = new Doctrine_Adapter_Statement_Oracle($this, $statement, $this->executeMode);
+        $stmt->execute();
+        $count = $stmt->rowCount();
+
+        return $count;
+    }
+
+    /**
+     * Get the id of the last inserted record
+     *
+     * @return integer $id
+     */
+    public function lastInsertId()
+    {
+        throw new Exception("unsupported");
+    }
+
+    /**
+     * Begin a transaction
+     *
+     * @return boolean
+     */
+    public function beginTransaction()
+    {
+       $this->executeMode = OCI_DEFAULT;
+       return true;
+    }
+
+    /**
+     * Commit a transaction
+     *
+     * @return void
+     */
+    public function commit()
+    {
+        return @oci_commit($this->connection);
+    }
+
+    /**
+     * Rollback a transaction
+     *
+     * @return boolean
+     */
+    public function rollBack()
+    {
+        return @oci_rollback($this->connection);
+    }
+
+    /**
+     * Set connection 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::ATTR_DRIVER_NAME:
+                //TODO throw an error since driver name can not be changed
+            case Doctrine::ATTR_ERRMODE:
+            break;
+            case Doctrine::ATTR_CASE:
+                if ($value == Doctrine::CASE_NATURAL) {
+                    break;
+                } else {
+                    throw new Doctrine_Adapter_Exception("Unsupported Option for ATTR_CASE: $value");
+                }
+            default:
+                throw new Doctrine_Adapter_Exception("Unsupported Attribute: $attribute");
+                return false;
+        }
+        $this->attributes[$attribute] = $value;
+        return true;
+    }
+
+    /**
+     * Retrieve a statement attribute
+     *
+     * @param integer $attribute
+     * @see Doctrine::ATTR_* constants
+     * @return mixed                        the attribute value
+     */
+    public function getAttribute($attribute)
+    {
+        return $this->attributes[$attribute];
+    }
+
+    /**
+     * Returns established OCI connection handler
+     *
+     * @return resource OCI connection handler
+     */
+    public function getConnection()
+    {
+        return $this->connection;
+    }
+
+    public function errorCode()
+    {
+        if (is_resource($this->connection)) {
+            $error = @oci_error($this->connection);
+        } else {
+            $error = @oci_error();
+        }
+        return $error['code'];
+    }
+
+    public function errorInfo()
+    {
+        if (is_resource($this->connection)) {
+            $error = @oci_error($this->connection);
+        } else {
+            $error = @oci_error();
+        }
+        return $error['message'];
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,131 @@
+<?php
+/*
+ *  $Id: Statement.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Adapter_Statement
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @package     Doctrine
+ * @subpackage  Adapter
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+abstract class Doctrine_Adapter_Statement
+{
+    /**
+     * bindValue
+     *
+     * @param string $no 
+     * @param string $value 
+     * @return void
+     */
+    public function bindValue($no, $value)
+    { }
+
+    /**
+     * fetch
+     *
+     * @see Doctrine::FETCH_* constants
+     * @param integer $fetchStyle           Controls how the next row will be returned to the caller.
+     *                                      This value must be one of the Doctrine::FETCH_* constants,
+     *                                      defaulting to Doctrine::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::FETCH_ORI_* constants, defaulting to
+     *                                      Doctrine::FETCH_ORI_NEXT. To request a scrollable cursor for your 
+     *                                      Doctrine_Adapter_Statement_Interface object,
+     *                                      you must set the Doctrine::ATTR_CURSOR attribute to Doctrine::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::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::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()
+    { }
+
+    /**
+     * nextRowSet
+     *
+     * @return void
+     */
+    public function nextRowset()
+    { }
+
+    /**
+     * execute()
+     *
+     * @return void
+     */
+    public function execute()
+    { }
+
+    /**
+     * errorCode
+     *
+     * @return void
+     */
+    public function errorCode()
+    { }
+
+    /**
+     * errorInfo
+     *
+     * @return void
+     */
+    public function errorInfo()
+    { }
+
+    /**
+     * rowCount
+     *
+     * @return void
+     */
+    public function rowCount()
+    { }
+
+    /**
+     * setFetchMode
+     *
+     * @param string $mode 
+     * @return void
+     */
+    public function setFetchMode($mode)
+    { }
+
+    /**
+     * columnCount
+     *
+     * @return void
+     */
+    public function columnCount()
+    { }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement/Interface.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,276 @@
+<?php
+/*
+ *  $Id: Interface.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Interface for Doctrine adapter statements
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @package     Doctrine
+ * @subpackage  Adapter
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+interface Doctrine_Adapter_Statement_Interface
+{
+    /**
+     * 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::PARAM_* constants.
+     * @return boolean              Returns TRUE on success or FALSE on failure
+     */
+    public function bindColumn($column, $param, $type = null);
+
+    /**
+     * 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::PARAM_* constants.
+     *
+     * @return boolean              Returns TRUE on success or FALSE on failure.
+     */
+    public function bindValue($param, $value, $type = null);
+
+    /**
+     * 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::PARAM_* constants. To return
+     *                              an INOUT parameter from a stored procedure, use the bitwise OR operator to set the
+     *                              Doctrine::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());
+
+    /**
+     * Closes the cursor, enabling the statement to be executed again.
+     *
+     * @return boolean              Returns TRUE on success or FALSE on failure.
+     */
+    public function closeCursor();
+
+    /** 
+     * 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();
+
+    /**
+     * 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();
+
+    /**
+     * 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();
+
+    /**
+     * 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);
+
+    /**
+     * fetch
+     *
+     * @see Doctrine::FETCH_* constants
+     * @param integer $fetchStyle           Controls how the next row will be returned to the caller.
+     *                                      This value must be one of the Doctrine::FETCH_* constants,
+     *                                      defaulting to Doctrine::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::FETCH_ORI_* constants, defaulting to
+     *                                      Doctrine::FETCH_ORI_NEXT. To request a scrollable cursor for your 
+     *                                      Doctrine_Adapter_Statement_Interface object,
+     *                                      you must set the Doctrine::ATTR_CURSOR attribute to Doctrine::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::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::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::FETCH_BOTH,
+                          $cursorOrientation = Doctrine::FETCH_ORI_NEXT,
+                          $cursorOffset = null);
+
+    /**
+     * 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::FETCH_* constants,
+     *                                      defaulting to Doctrine::FETCH_BOTH
+     *
+     * @param integer $columnIndex          Returns the indicated 0-indexed column when the value of $fetchStyle is
+     *                                      Doctrine::FETCH_COLUMN. Defaults to 0.
+     *
+     * @return array
+     */
+    public function fetchAll($fetchStyle = Doctrine::FETCH_BOTH);
+
+    /**
+     * 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);
+
+    /**
+     * 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::FETCH_CLASS or Doctrine::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());
+
+    /**
+     * Retrieve a statement attribute 
+     *
+     * @param integer $attribute
+     * @see Doctrine::ATTR_* constants
+     * @return mixed                        the attribute value
+     */
+    public function getAttribute($attribute);
+
+    /**
+     * 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);
+
+    /**
+     * 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();
+
+    /**
+     * 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();
+
+    /**
+     * 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);
+
+    /**
+     * Set the default fetch mode for this statement 
+     *
+     * @param integer $mode                 The fetch mode must be one of the Doctrine::FETCH_* constants.
+     * @return boolean                      Returns 1 on success or FALSE on failure.
+     */
+    public function setFetchMode($mode, $arg1 = null, $arg2 = null);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement/Mock.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,379 @@
+<?php
+/*
+ *  $Id: Mock.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Mock connection adapter statement class. Used for special testing purposes
+ *
+ * @package     Doctrine
+ * @subpackage  Adapter
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Adapter_Statement_Mock implements Doctrine_Adapter_Statement_Interface
+{
+    /**
+     * Variable which stores instance of Doctrine_Adapter_Mock
+     *
+     * @var Doctrine_Adapter_Mock
+     */
+    private $_mock;
+
+    /**
+     * queryString
+     *
+     * @var string
+     */
+    public $queryString;
+
+    /**
+     * Constructor for mock adapter statements. Accepts instance of Doctrine_Adapter_Mock
+     *
+     * @param Doctrine_Adapter_Mock $mock
+     */
+    public function __construct($mock)
+    {
+        $this->_mock  = $mock;
+    }
+
+    /**
+     * bindColumn
+     *
+     * 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::PARAM_* constants.
+     * @return boolean              Returns TRUE on success or FALSE on failure
+     */
+    public function bindColumn($column, $param, $type = null)
+    { }
+
+    /**
+     * bindValue
+     *
+     * 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::PARAM_* constants.
+     *
+     * @return boolean              Returns TRUE on success or FALSE on failure.
+     */
+    public function bindValue($param, $value, $type = null)
+    { }
+
+    /**
+     * bindParam
+     *
+     * 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::PARAM_* constants. To return
+     *                              an INOUT parameter from a stored procedure, use the bitwise OR operator to set the
+     *                              Doctrine::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())
+    {
+
+    }
+
+    /**
+     * closeCursor
+     *
+     * Closes the cursor, enabling the statement to be executed again.
+     *
+     * @return boolean              Returns TRUE on success or FALSE on failure.
+     */
+    public function closeCursor()
+    {
+        return true;
+    }
+
+    /**
+     * columnCount
+     *
+     * 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 0;
+    }
+
+    /**
+     * errorCode
+     *
+     * 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()
+    {
+        return array();
+    }
+
+    /**
+     * errorInfo
+     *
+     * 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()
+    {
+        return array();
+    }
+
+    /**
+     * fetch
+     *
+     * @see Doctrine::FETCH_* constants
+     * @param integer $fetchStyle           Controls how the next row will be returned to the caller.
+     *                                      This value must be one of the Doctrine::FETCH_* constants,
+     *                                      defaulting to Doctrine::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::FETCH_ORI_* constants, defaulting to
+     *                                      Doctrine::FETCH_ORI_NEXT. To request a scrollable cursor for your
+     *                                      Doctrine_Adapter_Statement_Interface object,
+     *                                      you must set the Doctrine::ATTR_CURSOR attribute to Doctrine::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::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::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::FETCH_BOTH,
+                          $cursorOrientation = Doctrine::FETCH_ORI_NEXT,
+                          $cursorOffset = null)
+    {
+        return array();
+    }
+
+    /**
+     * fetchAll
+     *
+     * 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::FETCH_* constants,
+     *                                      defaulting to Doctrine::FETCH_BOTH
+     *
+     * @param integer $columnIndex          Returns the indicated 0-indexed column when the value of $fetchStyle is
+     *                                      Doctrine::FETCH_COLUMN. Defaults to 0.
+     *
+     * @return array
+     */
+    public function fetchAll($fetchMode = Doctrine::FETCH_BOTH)
+    {
+        return array();
+    }
+
+    /**
+     * execute
+     *
+     * 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_object($this->_mock)) {
+            $this->_mock->addQuery($this->queryString);
+        }
+        return true;
+    }
+
+    /**
+     * fetchColumn
+     *
+     * 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)
+    {
+        return 0;
+    }
+
+    /**
+     * fetchObject
+     *
+     * 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::FETCH_CLASS or Doctrine::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())
+    {
+        return new $className();
+    }
+
+    /**
+     * nextRowset
+     *
+     * 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()
+    {
+        return true;
+    }
+
+    /**
+     * rowCount
+     *
+     * 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 0;
+    }
+
+    /**
+     * getColumnMeta
+     *
+     * 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)
+    { }
+
+    /**
+     * getAttribute
+     *
+     * Retrieve a statement attribute
+     *
+     * @param integer $attribute
+     * @see Doctrine::ATTR_* constants
+     * @return mixed                        the attribute value
+     */
+    public function getAttribute($attribute)
+    { }
+
+    /**
+     * setAttribute
+     *
+     * 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)
+    { }
+
+    /**
+     * setFetchMode
+     *
+     * Set the default fetch mode for this statement
+     *
+     * @param integer $mode                 The fetch mode must be one of the Doctrine::FETCH_* constants.
+     * @return boolean                      Returns 1 on success or FALSE on failure.
+     */
+    public function setFetchMode($mode, $arg1 = null, $arg2 = null)
+    { }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Adapter/Statement/Oracle.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,586 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Oracle connection adapter statement class.
+ *
+ * @package     Doctrine
+ * @subpackage  Adapter
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      vadik56
+ * @author      Miloslav Kmet <adrive-nospam@hip-hop.sk>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.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 $bind_params          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::ATTR_ERRMODE] = $connection->getAttribute(Doctrine::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::PARAM_* constants.
+     * @return boolean              Returns TRUE on success or FALSE on failure
+     */
+    public function bindColumn($column, $param, $type = null)
+    {
+        throw new 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::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::PARAM_* constants. To return
+     *                              an INOUT parameter from a stored procedure, use the bitwise OR operator to set the
+     *                              Doctrine::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::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->bind_params = array();
+        return oci_free_statement($this->statement);
+    }
+
+    /** 
+     * 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, $value);
+            }
+        }
+
+        $result = @oci_execute($this->statement , $this->executeMode );
+
+        if ($result === false) {
+            $this->handleError();
+            return false;
+         }
+        return true;
+    }
+
+    /**
+     * fetch
+     *
+     * @see Doctrine::FETCH_* constants
+     * @param integer $fetchStyle           Controls how the next row will be returned to the caller.
+     *                                      This value must be one of the Doctrine::FETCH_* constants,
+     *                                      defaulting to Doctrine::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::FETCH_ORI_* constants, defaulting to
+     *                                      Doctrine::FETCH_ORI_NEXT. To request a scrollable cursor for your 
+     *                                      Doctrine_Adapter_Statement_Interface object,
+     *                                      you must set the Doctrine::ATTR_CURSOR attribute to Doctrine::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::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::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::FETCH_BOTH, $cursorOrientation = Doctrine::FETCH_ORI_NEXT, $cursorOffset = null)
+    {
+        switch ($fetchStyle) {
+            case Doctrine::FETCH_BOTH :
+                return oci_fetch_array($this->statement, OCI_BOTH + OCI_RETURN_NULLS + OCI_RETURN_LOBS);
+            break;
+            case Doctrine::FETCH_ASSOC :
+                return oci_fetch_array($this->statement, OCI_ASSOC + OCI_RETURN_NULLS + OCI_RETURN_LOBS);
+            break;
+            case Doctrine::FETCH_NUM :
+                return oci_fetch_array($this->statement, OCI_NUM + OCI_RETURN_NULLS + OCI_RETURN_LOBS);
+            break;
+            case 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::FETCH_BOUND:
+            case Doctrine::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::FETCH_* constants,
+     *                                      defaulting to Doctrine::FETCH_BOTH
+     *
+     * @param integer $columnIndex          Returns the indicated 0-indexed column when the value of $fetchStyle is
+     *                                      Doctrine::FETCH_COLUMN. Defaults to 0.
+     *
+     * @return array
+     */
+    public function fetchAll($fetchStyle = Doctrine::FETCH_BOTH, $colnum=0)
+    {
+        $fetchColumn = false;
+        $skip = 0;
+        $maxrows = -1;
+        $data = array();
+        $flags = OCI_FETCHSTATEMENT_BY_ROW + OCI_ASSOC;
+
+        $int = $fetchStyle & Doctrine::FETCH_COLUMN;
+
+        if ($fetchStyle == Doctrine::FETCH_BOTH) {
+            $flags = OCI_BOTH;
+        } else if ($fetchStyle == Doctrine::FETCH_ASSOC) {
+            $numberOfRows = @oci_fetch_all($this->statement, $data, $skip, $maxrows, OCI_FETCHSTATEMENT_BY_ROW + OCI_ASSOC + OCI_RETURN_LOBS);
+        } else if ($fetchStyle == Doctrine::FETCH_NUM) {
+            $numberOfRows = @oci_fetch_all($this->statement, $data, $skip, $maxrows, OCI_FETCHSTATEMENT_BY_ROW + OCI_NUM + OCI_RETURN_LOBS);
+        } else if ($fetchStyle == Doctrine::FETCH_COLUMN) {
+            while ($row = @oci_fetch_array ($this->statement, OCI_NUM+OCI_RETURN_LOBS)) {
+                $data[] = $row[$colnum];
+            }
+        } else {
+            throw new 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"));
+        }
+        $row = $this->fetch(Doctrine::FETCH_NUM);
+        return $row[$columnIndex];
+    }
+
+    /**
+     * 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::FETCH_CLASS or Doctrine::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::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 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::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::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::FETCH_* constants.
+     * @return boolean                      Returns 1 on success or FALSE on failure.
+     */
+    public function setFetchMode($mode, $arg1 = null, $arg2 = null)
+    {
+        throw new Exception("Unsupported");
+    }
+
+    private function handleError($params=array())
+    {
+
+        switch ($this->attributes[Doctrine::ATTR_ERRMODE]) {
+            case Doctrine::ERRMODE_EXCEPTION:
+                if (isset($params['message'])) {
+                    throw new Doctrine_Adapter_Exception($params['message']);
+                } else {
+                    throw new Doctrine_Adapter_Exception($this->errorInfo());
+                }
+
+            break;
+            case Doctrine::ERRMODE_WARNING:
+            case Doctrine::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 = 0;
+        // Replace ? bind-placeholders with :oci_b_var_ variables
+        $query = preg_replace("/(\?)/e", '":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;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/AuditLog.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,146 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_AuditLog
+ *
+ * @package     Doctrine
+ * @subpackage  AuditLog
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_AuditLog extends Doctrine_Record_Generator
+{
+    /**
+     * Array of AuditLog Options
+     *
+     * @var string
+     */
+    protected $_options = array(
+                            'className'     => '%CLASS%Version',
+                            'versionColumn' => 'version',
+                            'tableName'     => false,
+                            'generateFiles' => false,
+                            'table'         => false,
+                            'pluginTable'   => false,
+                            'children'      => array(),
+                            'auditLog'      => true,
+                            );
+
+    /**
+     * Accepts array of options to configure the AuditLog
+     *
+     * @param   array $options An array of options
+     * @return  void
+     */
+    public function __construct(array $options = array())
+    {
+        $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
+    }
+
+    /**
+     * Set the table definition for the audit log table
+     *
+     * @return  void
+     */
+    public function setTableDefinition()
+    {
+        $name = $this->_options['table']->getComponentName();
+        $columns = $this->_options['table']->getColumns();
+
+        // remove all sequence, autoincrement and unique constraint definitions and add to the behavior model
+        foreach ($columns as $column => $definition) {
+            unset($definition['autoincrement']);
+            unset($definition['sequence']);
+            unset($definition['unique']);
+
+            $fieldName = $this->_options['table']->getFieldName($column);
+            if ($fieldName != $column) {
+                $name = $column . ' as ' . $fieldName;
+            } else {
+                $name = $fieldName;
+            }
+
+            $this->hasColumn($name, $definition['type'], $definition['length'], $definition);
+        }
+
+        // the version column should be part of the primary key definition
+        $this->hasColumn($this->_options['versionColumn'], 'integer', 8, array('primary' => true));
+    }
+
+    /**
+     * Get array of information for the passed record and the specified version
+     *
+     * @param   Doctrine_Record $record
+     * @param   integer         $version
+     * @return  array           An array with version information
+     */
+    public function getVersion(Doctrine_Record $record, $version)
+    {
+        $className = $this->_options['className'];
+
+        $q = new Doctrine_Query();
+
+        $values = array();
+        foreach ((array) $this->_options['table']->getIdentifier() as $id) {
+            $conditions[] = $className . '.' . $id . ' = ?';
+            $values[] = $record->get($id);
+        }
+
+        $where = implode(' AND ', $conditions) . ' AND ' . $className . '.' . $this->_options['versionColumn'] . ' = ?';
+
+        $values[] = $version;
+
+        $q->from($className)
+          ->where($where);
+
+        return $q->execute($values, Doctrine::HYDRATE_ARRAY);
+    }
+
+    /**
+     * Get the max version number for a given Doctrine_Record
+     *
+     * @param Doctrine_Record $record
+     * @return Integer $versionnumber
+     */
+    public function getMaxVersion(Doctrine_Record $record)
+    {
+        $className = $this->_options['className'];
+        $select = 'MAX(' . $className . '.' . $this->_options['versionColumn'] . ') max_version';
+
+        foreach ((array) $this->_options['table']->getIdentifier() as $id) {
+            $conditions[] = $className . '.' . $id . ' = ?';
+            $values[] = $record->get($id);
+        }
+
+        $q = Doctrine_Query::create()
+                ->select($select)
+                ->from($className)
+                ->where(implode(' AND ',$conditions));
+
+        $result = $q->execute($values, Doctrine::HYDRATE_ARRAY);
+
+        return isset($result[0]['max_version']) ? $result[0]['max_version']:0;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/AuditLog/Listener.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,147 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_AuditLog_Listener
+ *
+ * @package     Doctrine
+ * @subpackage  AuditLog
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_AuditLog_Listener extends Doctrine_Record_Listener
+{
+    /**
+     * Instance of Doctrine_Auditlog
+     *
+     * @var Doctrine_AuditLog
+     */
+    protected $_auditLog;
+
+    /**
+     * Instantiate AuditLog listener and set the Doctrine_AuditLog instance to the class
+     *
+     * @param   Doctrine_AuditLog $auditLog 
+     * @return  void
+     */
+    public function __construct(Doctrine_AuditLog $auditLog) 
+    {
+        $this->_auditLog = $auditLog;
+    }
+
+    /**
+     * Pre insert event hook for incrementing version number
+     *
+     * @param   Doctrine_Event $event
+     * @return  void
+     */
+    public function preInsert(Doctrine_Event $event)
+    {
+        $versionColumn = $this->_auditLog->getOption('versionColumn');
+
+        $event->getInvoker()->set($versionColumn, 1);
+    }
+
+    /**
+     * Post insert event hook which creates the new version record
+     * This will only insert a version record if the auditLog is enabled
+     *
+     * @param   Doctrine_Event $event 
+     * @return  void
+     */
+    public function postInsert(Doctrine_Event $event) 
+    {
+        if ($this->_auditLog->getOption('auditLog')) {
+            $class = $this->_auditLog->getOption('className');
+
+            $record  = $event->getInvoker();
+            $version = new $class();
+            $version->merge($record->toArray());
+            $version->save();
+        }
+    }
+
+    /**
+     * Pre delete event hook deletes all related versions
+     * This will only delete version records if the auditLog is enabled
+     *
+     * @param   Doctrine_Event $event
+     * @return  void
+     */
+    public function preDelete(Doctrine_Event $event)
+    {
+        if ($this->_auditLog->getOption('auditLog')) {
+	        $className = $this->_auditLog->getOption('className');
+	        $versionColumn = $this->_auditLog->getOption('versionColumn');
+	        $event->getInvoker()->set($versionColumn, null);
+
+	        $q = Doctrine_Query::create();
+	        foreach ((array) $this->_auditLog->getOption('table')->getIdentifier() as $id) {
+	            $conditions[] = 'obj.' . $id . ' = ?';
+	            $values[] = $event->getInvoker()->get($id);
+	        }
+
+	        $rows = $q->delete($className)
+					  ->from($className.' obj')
+					  ->where(implode(' AND ', $conditions))
+					  ->execute($values);
+        }
+    }
+  
+    /**
+     * Pre update event hook for inserting new version record
+     * This will only insert a version record if the auditLog is enabled
+     *
+     * @param  Doctrine_Event $event
+     * @return void
+     */
+    public function preUpdate(Doctrine_Event $event)
+    {
+        if ($this->_auditLog->getOption('auditLog')) {
+            $class  = $this->_auditLog->getOption('className');
+            $record = $event->getInvoker();
+
+            $versionColumn = $this->_auditLog->getOption('versionColumn');
+
+            $record->set($versionColumn, $this->_getNextVersion($record));
+
+            $version = new $class();
+            $version->merge($record->toArray());
+            $version->save();
+        }
+    }
+
+    /**
+     * Get the next version number for the audit log
+     *
+     * @param Doctrine_Record $record 
+     * @return integer $nextVersion
+     */
+    protected function _getNextVersion(Doctrine_Record $record)
+    {
+      if ($this->_auditLog->getOption('auditLog')) {
+          return ($this->_auditLog->getMaxVersion($record) + 1);
+      }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Builder.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,56 @@
+<?php
+/*
+ *  $Id: Builder.php 4593 2008-06-29 03:24:50Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Base class for any code builders/generators for Doctrine
+ *
+ * @package     Doctrine
+ * @subpackage  Builder
+ * @link        www.phpdoctrine.org
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @since       1.0
+ * @version     $Revision: 4593 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Builder
+{
+    /**
+     * Special function for var_export()
+     * The normal code which is returned is malformed and does not follow Doctrine standards
+     * So we do some string replacing to clean it up
+     *
+     * @param string $var
+     * @return void
+     */
+    public function varExport($var)
+    {
+        $export = var_export($var, true);
+        $export = str_replace("\n", PHP_EOL . str_repeat(' ', 50), $export);
+        $export = str_replace('  ', ' ', $export);
+        $export = str_replace('array (', 'array(', $export);
+        $export = str_replace('array( ', 'array(', $export);
+        $export = str_replace(',)', ')', $export);
+        $export = str_replace(', )', ')', $export);
+        $export = str_replace('  ', ' ', $export);
+
+        return $export;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,416 @@
+<?php
+/*
+ *  $Id: Cache.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Cache
+ *
+ * @package     Doctrine
+ * @subpackage  Cache
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Cache extends Doctrine_EventListener implements Countable, IteratorAggregate
+{
+    /**
+     * @var array $_options                         an array of general caching options
+     */
+    protected $_options = array('size'                  => 1000,
+        'lifeTime'              => 3600,
+        'addStatsPropability'   => 0.25,
+        'savePropability'       => 0.10,
+        'cleanPropability'      => 0.01,
+        'statsFile'             => '../data/stats.cache',
+    );
+
+    /**
+     * @var array $_queries                         query stack
+     */
+    protected $_queries = array();
+
+    /**
+     * @var Doctrine_Cache_Interface $_driver       the cache driver object
+     */
+    protected $_driver;
+
+    /**
+     * @var array $data                             current cache data array
+     */
+    protected $_data = array();
+
+    /**
+     * @var boolean $success                        the success of last operation
+     */
+    protected $_success = false;
+
+    /**
+     * constructor
+     *
+     * @param Doctrine_Cache_Interface|string $driver       cache driver name or a driver object
+     * @param array $options                                cache driver options
+     */
+    public function __construct($driver, $options = array())
+    {
+        if (is_object($driver)) {
+            if ( ! ($driver instanceof Doctrine_Cache_Interface)) {
+                throw new Doctrine_Cache_Exception('Driver should implement Doctrine_Cache_Interface.');
+            }
+
+            $this->_driver = $driver;
+            $this->_driver->setOptions($options);
+        } else {
+            $class = 'Doctrine_Cache_' . ucwords(strtolower($driver));
+
+            if ( ! class_exists($class)) {
+                throw new Doctrine_Cache_Exception('Cache driver ' . $driver . ' could not be found.');
+            }
+
+            $this->_driver = new $class($options);
+        }
+    }
+
+    /**
+     * Get the current cache driver instance
+     *
+     * @return Doctrine_Cache_Driver $driver
+     */
+    public function getDriver()
+    {
+        return $this->_driver;
+    }
+
+    /**
+     * Set option name and value
+     *
+     * @param mixed $option     the option name
+     * @param mixed $value      option value
+     * @return boolean          TRUE on success, FALSE on failure
+     */
+    public function setOption($option, $value)
+    {
+        // sanity check (we need this since we are using isset() instead of array_key_exists())
+        if ($value === null) {
+            throw new Doctrine_Cache_Exception('Null values not accepted for options.');
+        }
+
+        if (isset($this->_options[$option])) {
+            $this->_options[$option] = $value;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Get value of option name
+     * 
+     * @param mixed $option     the option name
+     * @return mixed            option value
+     */
+    public function getOption($option)
+    {
+        if ( ! isset($this->_options[$option])) {
+            throw new Doctrine_Cache_Exception('Unknown option ' . $option);
+        }
+
+        return $this->_options[$option];
+    }
+
+    /**
+     * Adds a query to internal query stack
+     *
+     * @param string|array $query           sql query string
+     * @param string $namespace             connection namespace
+     * @return void
+     */
+    public function add($query, $namespace = null)
+    {
+        if (isset($namespace)) {
+            $this->_queries[$namespace][] = $query;
+        } else {
+            $this->_queries[] = $query;
+        }
+    }
+
+    /**
+     * Get array of all executed queries
+     *
+     * @param string $namespace     optional query namespace
+     * @return array                an array of sql query strings
+     */
+    public function getAll($namespace = null)
+    {
+        if (isset($namespace)) {
+            if ( ! isset($this->_queries[$namespace])) {
+                return array();
+            }
+
+            return $this->_queries[$namespace];
+        }
+
+        return $this->_queries;
+    }
+
+    /**
+     * Pops a query from the stack
+     *
+     * @return string $query
+     */
+    public function pop()
+    {
+        return array_pop($this->_queries);
+    }
+
+    /**
+     * Removes all queries from the query stack
+     *
+     * @return void
+     */
+    public function reset()
+    {
+        $this->_queries = array();
+    }
+
+    /**
+     * Count the number of queries on the stack
+     *
+     * @return integer          the number of queries in the stack
+     */
+    public function count() 
+    {
+        return count($this->_queries);
+    }
+
+    /**
+     * Get queries iterator
+     *
+     * @return ArrayIterator    an iterator that iterates through the query stack
+     */
+    public function getIterator()
+    {
+        return new ArrayIterator($this->_queries);
+    }
+
+    /**
+     * Check whether or not the last cache opration was successful or not
+     *
+     * @return boolean          whether or not the last cache operation was successful
+     */
+    public function isSuccessful() 
+    {
+        return $this->_success;
+    }
+
+    /**
+     * Delete all cache
+     *
+     * @return void
+     */
+    public function clean()
+    {
+        $rand = (mt_rand() / mt_getrandmax());
+
+        if ($rand <= $this->_options['cleanPropability']) {
+            $queries = $this->readStats();
+
+            $stats   = array();
+
+            foreach ($queries as $query) {
+                if (isset($stats[$query])) {
+                    $stats[$query]++;
+                } else {
+                    $stats[$query] = 1;
+                }
+            }
+            sort($stats);
+
+            $i = $this->_options['size'];
+
+            while ($i--) {
+                $element = next($stats);
+                $query   = key($stats);
+
+                $hash = md5($query);
+
+                $this->_driver->delete($hash);
+            }
+        }
+    }
+
+    /**
+     * Read stats file from disk
+     *
+     * @return array $stats
+     */
+    public function readStats() 
+    {
+        if ($this->_options['statsFile'] !== false) {
+            $content = file_get_contents($this->_options['statsFile']);
+
+            $e = explode("\n", $content);
+
+            return array_map('unserialize', $e);
+        }
+        return array();
+    }
+
+    /**
+     * Append all queries to stats file
+     * @return void
+     */
+    public function appendStats()
+    {
+        if ($this->_options['statsFile'] !== false) {
+
+            if ( ! file_exists($this->_options['statsFile'])) {
+                throw new Doctrine_Cache_Exception("Couldn't save cache statistics. Cache statistics file doesn't exists!");
+            }
+
+            $rand = (mt_rand() / mt_getrandmax());
+
+            if ($rand <= $this->_options['addStatsPropability']) {
+                file_put_contents($this->_options['statsFile'], implode("\n", array_map('serialize', $this->_queries)));
+            }
+        }
+    }
+
+    /**
+     * Listens on the Doctrine_Event preQuery event
+     *
+     * adds the issued query to internal query stack
+     * and checks if cached element exists
+     *
+     * @return boolean
+     */
+    public function preQuery(Doctrine_Event $event)
+    {
+        $query = $event->getQuery();
+
+        $data  = false;
+        // only process SELECT statements
+        if (strtoupper(substr(ltrim($query), 0, 6)) != 'SELECT') {
+            return false;
+        }
+
+        $this->add($query, $event->getInvoker()->getName());
+
+        $data = $this->_driver->fetch(md5(serialize($query)));
+
+        $this->success = ($data) ? true : false;
+
+        if ( ! $data) {
+            $rand = (mt_rand() / mt_getrandmax());
+
+            if ($rand < $this->_options['savePropability']) {
+                $stmt = $event->getInvoker()->getAdapter()->query($query);
+
+                $data = $stmt->fetchAll(Doctrine::FETCH_ASSOC);
+
+                $this->success = true;
+
+                $this->_driver->save(md5(serialize($query)), $data);
+            }
+        }
+        if ($this->success)
+        {
+            $this->_data = $data;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Listens the preFetch event of Doctrine_Connection_Statement
+     *
+     * advances the internal pointer of cached data and returns 
+     * the current element
+     *
+     * @return array
+     */
+    public function preFetch(Doctrine_Event $event)
+    {
+        $ret = current($this->_data);
+        next($this->_data);
+        return $ret;
+    }
+
+    /**
+     * Listens the preFetchAll event of Doctrine_Connection_Statement
+     *
+     * returns the current cache data array
+     *
+     * @return array
+     */
+    public function preFetchAll(Doctrine_Event $event)
+    {
+        return $this->_data;
+    }
+
+    /**
+     * Listens the preExecute event of Doctrine_Connection_Statement
+     *
+     * adds the issued query to internal query stack
+     * and checks if cached element exists
+     *
+     * @return boolean
+     */
+    public function preExecute(Doctrine_Event $event)
+    {
+        $query = $event->getQuery();
+
+        $data  = false;
+
+        // only process SELECT statements
+        if (strtoupper(substr(ltrim($query), 0, 6)) != 'SELECT') {
+            return false;
+        }
+
+        $this->add($query, $event->getInvoker()->getDbh()->getName());
+
+        $data = $this->_driver->fetch(md5(serialize(array($query, $event->getParams()))));
+
+        $this->success = ($data) ? true : false;
+
+        if ( ! $data) {
+            $rand = (mt_rand() / mt_getrandmax());
+
+            if ($rand <= $this->_options['savePropability']) {
+
+                $stmt = $event->getInvoker()->getStatement();
+
+                $stmt->execute($event->getParams());
+
+                $data = $stmt->fetchAll(Doctrine::FETCH_ASSOC);
+
+                $this->success = true;
+
+                $this->_driver->save(md5(serialize(array($query, $event->getParams()))), $data);
+            }
+        }
+        if ($this->success)
+        {
+            $this->_data = $data;
+            return true;
+        }
+        return false;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Apc.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,98 @@
+<?php
+/*
+ *  $Id: Apc.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * APC Cache Driver
+ *
+ * @package     Doctrine
+ * @subpackage  Cache
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Cache_Apc extends Doctrine_Cache_Driver
+{
+    /**
+     * constructor
+     * 
+     * @param array $options    associative array of cache driver options
+     */
+    public function __construct($options = array())
+    {      
+        if ( ! extension_loaded('apc')) {
+            throw new Doctrine_Cache_Exception('The apc extension must be loaded for using this backend !');
+        }
+        parent::__construct($options);
+    }
+
+    /**
+     * Test if a cache is available for the given id and (if yes) return it (false else).
+     * 
+     * @param string $id cache id
+     * @param boolean $testCacheValidity        if set to false, the cache validity won't be tested
+     * @return mixed The stored variable on success. FALSE on failure.
+     */
+    public function fetch($id, $testCacheValidity = true) 
+    {
+        $results = apc_fetch($id);
+        $results = (array) $results;
+        return $results[0];
+    }
+
+    /**
+     * Test if a cache is available or not (for the given id)
+     *
+     * @param string $id cache id
+     * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
+     */
+    public function contains($id) 
+    {
+        return apc_fetch($id) === false ? false : true;
+    }
+
+    /**
+     * Save some string datas into a cache record
+     *
+     * Note : $data is always saved as a string
+     *
+     * @param string $data      data to cache
+     * @param string $id        cache id
+     * @param int $lifeTime     if != false, set a specific lifetime for this cache record (null => infinite lifeTime)
+     * @return boolean true if no problem
+     */
+    public function save($id, $data, $lifeTime = false)
+    {
+        return (bool) apc_store($id, $data, $lifeTime);
+    }
+
+    /**
+     * Remove a cache record
+     * 
+     * @param string $id cache id
+     * @return boolean true if no problem
+     */
+    public function delete($id) 
+    {
+        return apc_delete($id);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Array.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,113 @@
+<?php
+/*
+ *  $Id: Array.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Array cache driver
+ *
+ * @package     Doctrine
+ * @subpackage  Cache
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Cache_Array implements Countable, Doctrine_Cache_Interface
+{
+    /**
+     * @var array $data         an array of cached data
+     */
+    protected $data;
+
+    /**
+     * Test if a cache is available for the given id and (if yes) return it (false else)
+     * 
+     * Note : return value is always "string" (unserialization is done by the core not by the backend)
+     * 
+     * @param string $id cache id
+     * @param boolean $testCacheValidity        if set to false, the cache validity won't be tested
+     * @return string cached datas (or false)
+     */
+    public function fetch($id, $testCacheValidity = true) 
+    {
+        if (isset($this->data[$id])) {
+            return $this->data[$id];
+        }
+        return false;
+    }
+
+    /**
+     * Test if a cache is available or not (for the given id)
+     *
+     * @param string $id cache id
+     * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
+     */
+    public function contains($id)
+    {
+        return isset($this->data[$id]);
+    }
+
+    /**
+     * Save some string datas into a cache record
+     *
+     * Note : $data is always saved as a string
+     *
+     * @param string $data      data to cache
+     * @param string $id        cache id
+     * @param int $lifeTime     if != false, set a specific lifetime for this cache record (null => infinite lifeTime)
+     * @return boolean true if no problem
+     */
+    public function save($id, $data, $lifeTime = false)
+    {
+        $this->data[$id] = $data;
+    }
+
+    /**
+     * Remove a cache record
+     * 
+     * @param string $id cache id
+     * @return boolean true if no problem
+     */
+    public function delete($id)
+    {
+        unset($this->data[$id]);
+    }
+
+    /**
+     * Remove all cache record
+     * 
+     * @return boolean true if no problem
+     */
+    public function deleteAll()
+    {
+        $this->data = array();
+    }
+
+    /**
+     * count
+     *
+     * @return integer
+     */
+    public function count() 
+    {
+        return count($this->data);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Db.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,234 @@
+<?php
+/*
+ *  $Id: Db.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Database cache driver
+ *
+ * @package     Doctrine
+ * @subpackage  Cache
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Cache_Db extends Doctrine_Cache_Driver implements Countable
+{
+    /**
+     * Configure Database cache driver. Specify instance of Doctrine_Connection
+     * and tableName to store cache in
+     *
+     * @param array $_options      an array of options
+     */
+    public function __construct($options) 
+    {
+        if ( ! isset($options['connection']) || 
+             ! ($options['connection'] instanceof Doctrine_Connection)) {
+
+            throw new Doctrine_Cache_Exception('Connection option not set.');
+        }
+        
+        if ( ! isset($options['tableName']) ||
+             ! is_string($options['tableName'])) {
+             
+             throw new Doctrine_Cache_Exception('Table name option not set.');
+        }
+        
+
+        $this->_options = $options;
+    }
+
+    /**
+     * Get the connection object associated with this cache driver
+     *
+     * @return Doctrine_Connection $connection
+     */
+    public function getConnection() 
+    {
+        return $this->_options['connection'];
+    }
+
+    /**
+     * Test if a cache is available for the given id and (if yes) return it (false else).
+     *
+     * @param string $id cache id
+     * @param boolean $testCacheValidity        if set to false, the cache validity won't be tested
+     * @return string cached datas (or false)
+     */
+    public function fetch($id, $testCacheValidity = true)
+    {
+        $sql = 'SELECT data, expire FROM ' . $this->_options['tableName']
+             . ' WHERE id = ?';
+
+        if ($testCacheValidity) {
+            $sql .= " AND (expire is null OR expire > '" . date('Y-m-d H:i:s') . "')";
+        }
+
+        $result = $this->getConnection()->execute($sql, array($id))->fetchAll(Doctrine::FETCH_NUM);
+        
+        if ( ! isset($result[0])) {
+            return false;
+        }
+
+        return unserialize($this->_hex2Bin($result[0][0]));
+    }
+
+    protected function _hex2bin($hex)
+    {
+      if ( ! is_string($hex)) {
+          return null;
+      }
+  
+      $bin = '';
+      for ($a = 0; $a < strlen($hex); $a += 2) {
+          $bin .= chr(hexdec($hex{$a} . $hex{($a + 1)}));
+      }
+
+      return $bin;
+    }
+
+    /**
+     * Test if a cache is available or not (for the given id)
+     *
+     * @param string $id cache id
+     * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
+     */
+    public function contains($id) 
+    {
+        $sql = 'SELECT id, expire FROM ' . $this->_options['tableName']
+             . ' WHERE id = ?';
+
+        $result = $this->getConnection()->fetchOne($sql, array($id));
+
+        if(isset($result[0] )){
+        	return time();
+        }
+        return false;
+    }
+
+    /**
+     * Save some string datas into a cache record
+     *
+     * Note : $data is always saved as a string
+     *
+     * @param string $id        cache id
+     * @param string $data      data to cache
+     * @param int $lifeTime     if != false, set a specific lifetime for this cache record (null => infinite lifeTime)
+     * @return boolean true if no problem
+     */
+    public function save($id, $data, $lifeTime = false)
+    {
+    	if ($this->contains($id)){
+    		//record is in database, do update
+    		$sql = 'UPDATE ' . $this->_options['tableName']
+    			   . ' SET data=?, expire=? '
+             . ' WHERE id = ?';
+        
+        if ($lifeTime) {
+            $expire = date('Y-m-d H:i:s',time() + $lifeTime);
+        } else {
+            $expire = NULL;
+        }
+        $params = array(bin2hex(serialize($data)), $expire, $id);	
+    	} else {
+    		//record is not in database, do insert
+    		 $sql = 'INSERT INTO ' . $this->_options['tableName']
+             . ' (id, data, expire) VALUES (?, ?, ?)';
+
+        if ($lifeTime) {
+            $expire = date('Y-m-d H:i:s', time() + $lifeTime);
+        } else {
+            $expire = NULL;
+        }
+
+        $params = array($id, bin2hex(serialize($data)), $expire);	
+      }
+
+      return (bool) $this->getConnection()->exec($sql, $params);
+    }
+
+    /**
+     * Remove a cache record
+     * 
+     * @param string $id cache id
+     * @return boolean true if no problem
+     */
+    public function delete($id) 
+    {
+        $sql = 'DELETE FROM ' . $this->_options['tableName'] . ' WHERE id = ?';
+
+        return (bool) $this->getConnection()->exec($sql, array($id));
+    }
+
+    /**
+     * Removes all cache records
+     *
+     * $return bool true on success, false on failure
+     */
+    public function deleteAll()
+    {
+        $sql = 'DELETE FROM ' . $this->_options['tableName'];
+        
+        return (bool) $this->getConnection()->exec($sql);
+    }
+
+    /**
+     * count
+     * returns the number of cached elements
+     *
+     * @return integer
+     */
+    public function count()
+    {
+        $sql = 'SELECT COUNT(*) FROM ' . $this->_options['tableName'];
+        
+        return (int) $this->getConnection()->fetchOne($sql);
+    }
+
+    /**
+     * Create the cache table
+     *
+     * @return void
+     */
+    public function createTable()
+    {
+        $name = $this->_options['tableName'];
+        
+        $fields = array(
+            'id' => array(
+                'type'   => 'string',
+                'length' => 255
+            ),
+            'data' => array(
+                'type'    => 'blob'
+            ),
+            'expire' => array(
+                'type'    => 'timestamp'
+            )
+        );
+        
+        $options = array(
+            'primary' => array('id')
+        );
+        
+        $this->getConnection()->export->createTable($name, $fields, $options);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Driver.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,80 @@
+<?php
+/*
+ *  $Id: Driver.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Abstract cache driver class
+ *
+ * @package     Doctrine
+ * @subpackage  Cache
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+abstract class Doctrine_Cache_Driver implements Doctrine_Cache_Interface
+{
+    /**
+     * @var array $_options      an array of options
+     */
+    protected $_options = array();
+
+    /**
+     * Configure cache driver with an array of options
+     *
+     * @param array $_options      an array of options
+     */
+    public function __construct($options) 
+    {
+        $this->_options = $options;
+    }
+
+    /**
+     * Set option name and value
+     *
+     * @param mixed $option     the option name
+     * @param mixed $value      option value
+     * @return boolean          TRUE on success, FALSE on failure
+     */
+    public function setOption($option, $value)
+    {
+        if (isset($this->_options[$option])) {
+            $this->_options[$option] = $value;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Get value of option
+     * 
+     * @param mixed $option     the option name
+     * @return mixed            option value
+     */
+    public function getOption($option)
+    {
+        if ( ! isset($this->_options[$option])) {
+            return null;
+        }
+
+        return $this->_options[$option];
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine cache exception class
+ *
+ * @package     Doctrine
+ * @subpackage  Cache
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Cache_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Interface.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,73 @@
+<?php
+/*
+ *  $Id: Interface.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine cache driver interface
+ *
+ * @package     Doctrine
+ * @subpackage  Cache
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+interface Doctrine_Cache_Interface 
+{
+    /**
+     * Test if a cache is available for the given id and (if yes) return it (false else)
+     * 
+     * Note : return value is always "string" (unserialization is done by the core not by the backend)
+     * 
+     * @param string $id cache id
+     * @param boolean $testCacheValidity        if set to false, the cache validity won't be tested
+     * @return string cached datas (or false)
+     */
+    public function fetch($id, $testCacheValidity = true);
+
+    /**
+     * Test if a cache is available or not (for the given id)
+     *
+     * @param string $id cache id
+     * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
+     */
+    public function contains($id);
+
+    /**
+     * Save some string datas into a cache record
+     *
+     * Note : $data is always saved as a string
+     *
+     * @param string $id        cache id
+     * @param string $data      data to cache
+     * @param int $lifeTime     if != false, set a specific lifetime for this cache record (null => infinite lifeTime)
+     * @return boolean true if no problem
+     */
+    public function save($id, $data, $lifeTime = false);
+
+    /**
+     * Remove a cache record
+     * 
+     * @param string $id cache id
+     * @return boolean true if no problem
+     */
+    public function delete($id);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Memcache.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,128 @@
+<?php
+/*
+ *  $Id: Memcache.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Memcache cache driver
+ *
+ * @package     Doctrine
+ * @subpackage  Cache
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Cache_Memcache extends Doctrine_Cache_Driver
+{
+    /**
+     * @var Memcache $_memcache     memcache object
+     */
+    protected $_memcache = null;
+
+    /**
+     * constructor
+     * 
+     * @param array $options        associative array of cache driver options
+     */
+    public function __construct($options = array())
+    {      
+        if ( ! extension_loaded('memcache')) {
+            throw new Doctrine_Cache_Exception('In order to use Memcache driver, the memcache extension must be loaded.');
+        }
+        parent::__construct($options);
+
+        if (isset($options['servers'])) {
+            $value= $options['servers'];
+            if (isset($value['host'])) {
+                // in this case, $value seems to be a simple associative array (one server only)
+                $value = array(0 => $value); // let's transform it into a classical array of associative arrays
+            }
+            $this->setOption('servers', $value);
+        }
+        
+        $this->_memcache = new Memcache;
+
+        foreach ($this->_options['servers'] as $server) {
+            if ( ! array_key_exists('persistent', $server)) {
+                $server['persistent'] = true;
+            }
+            if ( ! array_key_exists('port', $server)) {
+                $server['port'] = 11211;
+            }
+            $this->_memcache->addServer($server['host'], $server['port'], $server['persistent']);
+        }
+    }
+
+    /**
+     * Test if a cache is available for the given id and (if yes) return it (false else)
+     * 
+     * @param string $id cache id
+     * @param boolean $testCacheValidity        if set to false, the cache validity won't be tested
+     * @return mixed The stored variable on success. FALSE on failure.
+     */
+    public function fetch($id, $testCacheValidity = true) 
+    {
+        return $this->_memcache->get($id);
+    }
+
+    /**
+     * Test if a cache is available or not (for the given id)
+     *
+     * @param string $id cache id
+     * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
+     */
+    public function contains($id) 
+    {
+        return (bool) $this->_memcache->get($id);
+    }
+
+    /**
+     * Save some string datas into a cache record
+     *
+     * Note : $data is always saved as a string
+     *
+     * @param string $data      data to cache
+     * @param string $id        cache id
+     * @param int $lifeTime     if != false, set a specific lifetime for this cache record (null => infinite lifeTime)
+     * @return boolean true if no problem
+     */
+    public function save($id, $data, $lifeTime = false)
+    {
+        if ($this->_options['compression']) {
+            $flag = MEMCACHE_COMPRESSED;
+        } else {
+            $flag = 0;
+        }
+
+        $result = $this->_memcache->set($id, $data, $flag, $lifeTime);
+    }
+
+    /**
+     * Remove a cache record
+     * 
+     * @param string $id cache id
+     * @return boolean true if no problem
+     */
+    public function delete($id) 
+    {
+        return $this->_memcache->delete($id);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cache/Xcache.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,97 @@
+<?php
+/*
+ *  $Id: Xcache.php  2007-11-19 14:47:59Z demongloom $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Xcache cache driver
+ *
+ * @package     Doctrine
+ * @subpackage  Cache
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: $
+ * @author      Dmitry Bakaleinik (dima@snaiper.net)
+ */
+class Doctrine_Cache_Xcache extends Doctrine_Cache_Driver
+{
+    /**
+     * constructor
+     * 
+     * @param array $options        associative array of cache driver options
+     */
+    public function __construct($options = array())
+    {      
+        if ( ! extension_loaded('xcache') ) {
+            throw new Doctrine_Cache_Exception('In order to use Xcache driver, the xcache extension must be loaded.');
+        }
+        
+        parent::__construct($options);
+    }
+
+    /**
+     * Test if a cache is available for the given id and (if yes) return it (false else).
+     * 
+     * @param string $id cache id
+     * @param boolean $testCacheValidity        if set to false, the cache validity won't be tested
+     * @return string cached datas (or false)
+     */
+    public function fetch($id, $testCacheValidity = true) 
+    {
+        return $this->contains($id) ? xcache_get($id) : false;
+    }
+
+    /**
+     * Test if a cache is available or not (for the given id)
+     *
+     * @param string $id cache id
+     * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
+     */
+    public function contains($id) 
+    {
+        return xcache_isset($id);
+    }
+
+    /**
+     * Save some string datas into a cache record
+     *
+     * Note : $data is always saved as a string
+     *
+     * @param string $data      data to cache
+     * @param string $id        cache id
+     * @param int $lifeTime     if != false, set a specific lifetime for this cache record (null => infinite lifeTime)
+     * @return boolean true if no problem
+     */
+    public function save($id, $data, $lifeTime = false)
+    {
+        return xcache_set($id, $data, $lifeTime);
+    }
+
+    /**
+     * Remove a cache record
+     * 
+     * @param string $id cache id
+     * @return boolean true if no problem
+     */
+    public function delete($id) 
+    {
+        return xcache_unset($id);       
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,356 @@
+<?php
+/*
+ *  $Id: Cli.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * 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.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Cli
+{
+    protected $_tasks        = array(),
+              $_taskInstance = null,
+              $_formatter    = null,
+              $_scriptName   = null,
+              $_message      = null,
+              $_config       = array();
+
+    /**
+     * __construct
+     *
+     * @param string $config 
+     * @return void
+     */
+    public function __construct($config = array())
+    {
+        $this->_config = $config;
+        $this->_formatter = new Doctrine_Cli_AnsiColorFormatter();
+        
+        $this->loadTasks();
+    }
+
+    /**
+     * 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')
+    {
+        echo $this->_formatter->format($this->_taskInstance->getTaskName(), 'INFO') . ' - ' . $this->_formatter->format($notification, $style) . "\n";
+    }
+
+    /**
+     * Notify the formatter of an exception
+     *
+     * @param  Exception $exception
+     * @return void
+     */
+    public function notifyException($exception)
+    {
+        echo $this->_formatter->format($exception->getMessage(), 'ERROR') . "\n";
+    }
+
+    /**
+     * Public function to run the loaded task with the passed arguments
+     *
+     * @param  array $args
+     * @return void
+     * @throws new Doctrine_Cli_Exception
+     */
+    public function run($args)
+    {
+        try {
+            $this->_run($args);
+        } catch (Exception $exception) {
+            $this->notifyException($exception);
+        }
+    }
+
+    /**
+     * Get the name of the task class based on the first argument
+     * which is always the task name. Do some inflection to determine the class name
+     *
+     * @param  array $args       Array of arguments from the cli
+     * @return string $taskClass Task class name
+     */
+    protected function _getTaskClassFromArgs($args)
+    {
+        $taskName = str_replace('-', '_', $args[1]);
+        $taskClass = 'Doctrine_Task_' . Doctrine_Inflector::classify($taskName);
+        
+        return $taskClass;
+    }
+
+    /**
+     * 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 $e
+     */
+    protected function _run($args)
+    {        
+        $this->_scriptName = $args[0];
+        
+        $arg1 = isset($args[1]) ? $args[1]:null;
+        
+        if ( ! $arg1 || $arg1 == 'help') {
+            echo $this->printTasks(null, $arg1 == 'help' ? true:false);
+            return;
+        }
+        
+        if (isset($args[1]) && isset($args[2]) && $args[2] === 'help') {
+            echo $this->printTasks($args[1], true);
+            return;
+        }
+        
+        $taskClass = $this->_getTaskClassFromArgs($args);
+        
+        if ( ! class_exists($taskClass)) {
+            throw new Doctrine_Cli_Exception('Cli task could not be found: ' . $taskClass);
+        }
+        
+        unset($args[0]);
+        unset($args[1]);
+        
+        $this->_taskInstance = new $taskClass($this);
+        
+        $args = $this->prepareArgs($args);
+        
+        $this->_taskInstance->setArguments($args);
+        
+        try {
+            if ($this->_taskInstance->validate()) {
+                $this->_taskInstance->execute();
+            } else {
+                echo $this->_formatter->format('Requires arguments missing!!', 'ERROR') . "\n\n";
+                echo $this->printTasks($arg1, true);
+            }
+        } catch (Exception $e) {
+            throw new Doctrine_Cli_Exception($e->getMessage());
+        }
+    }
+
+    /**
+     * 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
+     */
+    protected function prepareArgs($args)
+    {
+        $taskInstance = $this->_taskInstance;
+        
+        $args = array_values($args);
+        
+        // First lets load populate an array with all the possible arguments. required and optional
+        $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
+        if (is_array($this->_config) && !empty($this->_config)) {
+            foreach ($this->_config 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
+     * 
+     * @return void
+     */
+    public function printTasks($task = null, $full = false)
+    {
+        $task = Doctrine_Inflector::classify(str_replace('-', '_', $task));
+        
+        $tasks = $this->getLoadedTasks();
+        
+        echo $this->_formatter->format("Doctrine Command Line Interface", 'HEADER') . "\n\n";
+        
+        foreach ($tasks as $taskName)
+        {
+            if ($task != null && strtolower($task) != strtolower($taskName)) {
+                continue;
+            }
+            
+            $className = 'Doctrine_Task_' . $taskName;
+            $taskInstance = new $className();
+            $taskInstance->taskName = str_replace('_', '-', Doctrine_Inflector::tableize($taskName));         
+            
+            $syntax = $this->_scriptName . ' ' . $taskInstance->getTaskName();
+            
+            echo $this->_formatter->format($syntax, 'INFO'); 
+            
+            if ($full) {
+                echo " - " . $taskInstance->getDescription() . "\n";  
+                
+                $args = null;
+                
+                $requiredArguments = $taskInstance->getRequiredArgumentsDescriptions();
+                
+                if ( ! empty($requiredArguments)) {
+                    foreach ($requiredArguments as $name => $description) {
+                        $args .= $this->_formatter->format($name, "ERROR");
+                        
+                        if (isset($this->_config[$name])) {
+                            $args .= " - " . $this->_formatter->format($this->_config[$name], 'COMMENT');
+                        } else {
+                            $args .= " - " . $description;
+                        }
+                        
+                        $args .= "\n";
+                    }
+                }
+            
+                $optionalArguments = $taskInstance->getOptionalArgumentsDescriptions();
+                
+                if ( ! empty($optionalArguments)) {
+                    foreach ($optionalArguments as $name => $description) {
+                        $args .= $name . ' - ' . $description."\n";
+                    }
+                }
+            
+                if ($args) {
+                    echo "\n" . $this->_formatter->format('Arguments:', 'HEADER') . "\n" . $args;
+                }
+            }
+            
+            echo "\n";
+        }
+    }
+
+    /**
+     * Load tasks from the passed directory. If no directory is given it looks in the default
+     * Doctrine/Task folder for the core tasks.
+     *
+     * @param  mixed $directory   Can be a string path or array of paths
+     * @return array $loadedTasks Array of tasks loaded
+     */
+    public function loadTasks($directory = null)
+    {
+        if ($directory === null) {
+            $directory = Doctrine::getPath() . DIRECTORY_SEPARATOR . 'Doctrine' . DIRECTORY_SEPARATOR . 'Task';
+        }
+        
+        $parent = new ReflectionClass('Doctrine_Task');
+        
+        $tasks = array();
+        
+        if (is_dir($directory)) {
+            foreach ((array) $directory as $dir) {
+                $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) {
+                    
+                        $className = 'Doctrine_Task_' . $e[0];
+                    
+                        if ( ! class_exists($className)) {
+                            require_once($file->getPathName());
+                    
+                            $class = new ReflectionClass($className);
+                    
+                            if ($class->isSubClassOf($parent)) {
+                                $tasks[$e[0]] = $e[0];
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        $classes = get_declared_classes();
+        foreach ($classes as $className) {
+            $class = new Reflectionclass($className);
+            if ($class->isSubClassOf($parent)) {
+                $task = str_replace('Doctrine_Task_', '', $className);
+                $tasks[$task] = $task;
+            }
+        }
+
+        $this->_tasks = array_merge($this->_tasks, $tasks);
+        
+        return $this->_tasks;
+    }
+
+    /**
+     * Get array of all the Doctrine_Task child classes that are loaded
+     *
+     * @return array $tasks
+     */
+    public function getLoadedTasks()
+    {
+        $parent = new ReflectionClass('Doctrine_Task');
+        
+        $classes = get_declared_classes();
+        
+        $tasks = array();
+        
+        foreach ($classes as $className) {
+            $class = new ReflectionClass($className);
+        
+            if ($class->isSubClassOf($parent)) {
+                $task = str_replace('Doctrine_Task_', '', $className);
+                
+                $tasks[$task] = $task;
+            }
+        }
+        
+        return array_merge($this->_tasks, $tasks);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli/AnsiColorFormatter.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,160 @@
+<?php
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ *  $Id: AnsiColorFormatter.php 2702 2007-10-03 21:43:22Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_AnsiColorFormatter provides methods to colorize text to be displayed on a console.
+ * This class was taken from the symfony-project source
+ *
+ * @package    Doctrine
+ * @subpackage Cli
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 4252 $
+ */
+class Doctrine_Cli_AnsiColorFormatter extends Doctrine_Cli_Formatter
+{
+    protected
+        $_styles = array(
+            'HEADER'  => array('fg' => 'black', 'bold' => true),
+            'ERROR'   => array('bg' => 'red', 'fg' => 'white', 'bold' => true),
+            'INFO'    => array('fg' => 'green', 'bold' => true),
+            'COMMENT' => array('fg' => 'yellow'),
+            ),
+        $_options    = array('bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8),
+        $_foreground = array('black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37),
+        $_background = array('black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47);
+
+    /**
+     * Sets a new style.
+     *
+     * @param string The style name
+     * @param array  An array of options
+     */
+    public function setStyle($name, $options = array())
+    {
+        $this->_styles[$name] = $options;
+    }
+
+    /**
+     * Formats a text according to the given style or parameters.
+     *
+     * @param  string The test to style
+     * @param  mixed  An array of options or a style name
+     *
+     * @return string The styled text
+     */
+    public function format($text = '', $parameters = array(), $stream = STDOUT)
+    {
+        if ( ! $this->supportsColors($stream)) {
+            return $text;
+        }
+
+        if ( ! is_array($parameters) && 'NONE' == $parameters) {
+            return $text;
+        }
+
+        if ( ! is_array($parameters) && isset($this->_styles[$parameters])) {
+            $parameters = $this->_styles[$parameters];
+        }
+
+        $codes = array();
+        if (isset($parameters['fg'])) {
+            $codes[] = $this->_foreground[$parameters['fg']];
+        }
+        
+        if (isset($parameters['bg'])) {
+            $codes[] = $this->_background[$parameters['bg']];
+        }
+        
+        foreach ($this->_options as $option => $value) {
+            if (isset($parameters[$option]) && $parameters[$option]) {
+                $codes[] = $value;
+            }
+        }
+
+        return "\033[".implode(';', $codes).'m'.$text."\033[0m";
+    }
+
+    /**
+     * Formats a message within a section.
+     *
+     * @param string  The section name
+     * @param string  The text message
+     * @param integer The maximum size allowed for a line (65 by default)
+     */
+    public function formatSection($section, $text, $size = null)
+    {
+        $width = 9 + strlen($this->format('', 'INFO'));
+
+        return sprintf(">> %-${width}s %s", $this->format($section, 'INFO'), $this->excerpt($text, $size));
+    }
+
+    /**
+     * Truncates a line.
+     *
+     * @param string  The text
+     * @param integer The maximum size of the returned string (65 by default)
+     *
+     * @return string The truncated string
+     */
+    public function excerpt($text, $size = null)
+    {
+        if ( ! $size) {
+            $size = $this->size;
+        }
+
+        if (strlen($text) < $size) {
+            return $text;
+        }
+
+        $subsize = floor(($size - 3) / 2);
+
+        return substr($text, 0, $subsize) . $this->format('...', 'INFO').substr($text, -$subsize);
+    }
+
+    /**
+     * Returns true if the stream supports colorization.
+     *
+     * Colorization is disabled if not supported by the stream:
+     *
+     *  -  windows
+     *  -  non tty consoles
+     *
+     * @param  mixed A stream
+     *
+     * @return Boolean true if the stream supports colorization, false otherwise
+     */
+    public function supportsColors($stream)
+    {
+        return DIRECTORY_SEPARATOR != '\\' && function_exists('posix_isatty') && @posix_isatty($stream);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Cli exception class
+ *
+ * @package     Doctrine
+ * @subpackage  Cli
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Cli_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Cli/Formatter.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,116 @@
+<?php
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ *  $Id: Formatter.php 2702 2007-10-03 21:43:22Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Cli_Formatter provides methods to format text to be displayed on a console.
+ * This class was taken from the symfony-project source
+ *
+ * @package     Doctrine
+ * @subpackage  Cli
+ * @author      Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author      Jonathan H. Wage <jonwage@gmail.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ */
+class Doctrine_Cli_Formatter
+{
+    protected $_size = 65;
+
+    /**
+     * __construct
+     *
+     * @param string $maxLineSize 
+     * @return void
+     */
+    function __construct($maxLineSize = 65)
+    {
+        $this->_size = $maxLineSize;
+    }
+
+    /**
+     * Formats a text according to the given parameters.
+     *
+     * @param  string The test to style
+     * @param  mixed  An array of parameters
+     * @param  stream A stream (default to STDOUT)
+     *
+     * @return string The formatted text
+     */
+    public function format($text = '', $parameters = array(), $stream = STDOUT)
+    {
+        return $text;
+    }
+
+    /**
+     * Formats a message within a section.
+     *
+     * @param string  The section name
+     * @param string  The text message
+     * @param integer The maximum size allowed for a line (65 by default)
+     */
+    public function formatSection($section, $text, $size = null)
+    {
+        return sprintf(">> %-$9s %s", $section, $this->excerpt($text, $size));
+    }
+
+    /**
+     * Truncates a line.
+     *
+     * @param string  The text
+     * @param integer The maximum size of the returned string (65 by default)
+     *
+     * @return string The truncated string
+     */
+    public function excerpt($text, $size = null)
+    {
+        if ( ! $size) {
+            $size = $this->_size;
+        }
+
+        if (strlen($text) < $size) {
+            return $text;
+        }
+
+        $subsize = floor(($size - 3) / 2);
+
+        return substr($text, 0, $subsize).'...'.substr($text, -$subsize);
+    }
+
+    /**
+     * Sets the maximum line size.
+     *
+     * @param integer The maximum line size for a message
+     */
+    public function setMaxLineSize($size)
+    {
+        $this->_size = $size;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,934 @@
+<?php
+/*
+ *  $Id: Collection.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Collection
+ * Collection of Doctrine_Record objects.
+ *
+ * @package     Doctrine
+ * @subpackage  Collection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Collection extends Doctrine_Access implements Countable, IteratorAggregate, Serializable
+{
+    /**
+     * @var array $data                     an array containing the records of this collection
+     */
+    protected $data = array();
+
+    /**
+     * @var Doctrine_Table $table           each collection has only records of specified table
+     */
+    protected $_table;
+
+    /**
+     * @var array $_snapshot                a snapshot of the fetched data
+     */
+    protected $_snapshot = array();
+
+    /**
+     * @var Doctrine_Record $reference      collection can belong to a record
+     */
+    protected $reference;
+
+    /**
+     * @var string $referenceField         the reference field of the collection
+     */
+    protected $referenceField;
+
+    /**
+     * @var Doctrine_Relation               the record this collection is related to, if any
+     */
+    protected $relation;
+
+    /**
+     * @var string $keyColumn               the name of the column that is used for collection key mapping
+     */
+    protected $keyColumn;
+
+    /**
+     * @var Doctrine_Null $null             used for extremely fast null value testing
+     */
+    protected static $null;
+
+    /**
+     * constructor
+     *
+     * @param Doctrine_Table|string $table
+     */
+    public function __construct($table, $keyColumn = null)
+    {
+        if ( ! ($table instanceof Doctrine_Table)) {
+            $table = Doctrine::getTable($table);
+        }
+
+        $this->_table = $table;
+
+        if ($keyColumn === null) {
+            $keyColumn = $table->getBoundQueryPart('indexBy');
+        }
+
+        if ($keyColumn === null) {
+        	$keyColumn = $table->getAttribute(Doctrine::ATTR_COLL_KEY);
+        }
+
+        if ($keyColumn !== null) {
+            $this->keyColumn = $keyColumn;
+        }
+    }
+
+    /**
+     * Initializes the null object for this collection
+     *
+     * @return void
+     */
+    public static function initNullObject(Doctrine_Null $null)
+    {
+        self::$null = $null;
+    }
+
+    /**
+     * Get the table this collection belongs to
+     *
+     * @return Doctrine_Table
+     */
+    public function getTable()
+    {
+        return $this->_table;
+    }
+
+    /**
+     * Set the data for the Doctrin_Collection instance
+     *
+     * @param array $data
+     * @return Doctrine_Collection
+     */
+    public function setData(array $data) 
+    {
+        $this->data = $data;
+    }
+
+    /**
+     * This method is automatically called when this Doctrine_Collection is serialized
+     *
+     * @return array
+     */
+    public function serialize()
+    {
+        $vars = get_object_vars($this);
+
+        unset($vars['reference']);
+        unset($vars['reference_field']);
+        unset($vars['relation']);
+        unset($vars['expandable']);
+        unset($vars['expanded']);
+        unset($vars['generator']);
+
+        $vars['_table'] = $vars['_table']->getComponentName();
+
+        return serialize($vars);
+    }
+
+    /**
+     * This method is automatically called everytime a Doctrine_Collection object is unserialized
+     *
+     * @return void
+     */
+    public function unserialize($serialized)
+    {
+        $manager    = Doctrine_Manager::getInstance();
+        $connection    = $manager->getCurrentConnection();
+
+        $array = unserialize($serialized);
+
+        foreach ($array as $name => $values) {
+            $this->$name = $values;
+        }
+
+        $this->_table = $connection->getTable($this->_table);
+
+        $keyColumn = isset($array['keyColumn']) ? $array['keyColumn'] : null;
+        if ($keyColumn === null) {
+            $keyColumn = $this->_table->getBoundQueryPart('indexBy');
+        }
+
+        if ($keyColumn !== null) {
+            $this->keyColumn = $keyColumn;
+        }
+    }
+
+    /**
+     * Sets the key column for this collection
+     *
+     * @param string $column
+     * @return Doctrine_Collection $this
+     */
+    public function setKeyColumn($column)
+    {
+        $this->keyColumn = $column;
+        
+        return $this;
+    }
+
+    /**
+     * Get the name of the key column
+     *
+     * @return string
+     */
+    public function getKeyColumn()
+    {
+        return $this->keyColumn;
+    }
+
+    /**
+     * Get all the records as an array
+     *
+     * @return array
+     */
+    public function getData()
+    {
+        return $this->data;
+    }
+
+    /**
+     * Get the first record in the collection
+     *
+     * @return mixed
+     */
+    public function getFirst()
+    {
+        return reset($this->data);
+    }
+
+    /**
+     * Get the last record in the collection
+     *
+     * @return mixed
+     */
+    public function getLast()
+    {
+        return end($this->data);
+    }
+
+    /**
+     * Get the last record in the collection
+     *
+     * @return mixed
+     */
+    public function end()
+    {
+        return end($this->data);
+    }
+
+    /**
+     * Get the current key
+     *
+     * @return mixed
+     */
+    public function key()
+    {
+        return key($this->data);
+    }
+
+    /**
+     * Sets a reference pointer
+     *
+     * @return void
+     */
+    public function setReference(Doctrine_Record $record, Doctrine_Relation $relation)
+    {
+        $this->reference = $record;
+        $this->relation  = $relation;
+
+        if ($relation instanceof Doctrine_Relation_ForeignKey || 
+                $relation instanceof Doctrine_Relation_LocalKey) {
+            $this->referenceField = $relation->getForeignFieldName();
+
+            $value = $record->get($relation->getLocalFieldName());
+
+            foreach ($this->data as $record) {
+                if ($value !== null) {
+                    $record->set($this->referenceField, $value, false);
+                } else {
+                    $record->set($this->referenceField, $this->reference, false);
+                }
+            }
+        } elseif ($relation instanceof Doctrine_Relation_Association) {
+
+        }
+    }
+
+    /**
+     * Get reference to Doctrine_Record instance
+     *
+     * @return Doctrine_Record $reference
+     */
+    public function getReference()
+    {
+        return $this->reference;
+    }
+
+    /**
+     * Removes a specified collection element
+     *
+     * @param mixed $key
+     * @return boolean
+     */
+    public function remove($key)
+    {
+        $removed = $this->data[$key];
+
+        unset($this->data[$key]);
+        return $removed;
+    }
+
+    /**
+     * Whether or not this collection contains a specified element
+     *
+     * @param mixed $key                    the key of the element
+     * @return boolean
+     */
+    public function contains($key)
+    {
+        return isset($this->data[$key]);
+    }
+
+    /**
+     * Search a Doctrine_Record instance
+     *
+     * @param string $Doctrine_Record 
+     * @return void
+     */
+    public function search(Doctrine_Record $record)
+    {
+        return array_search($record, $this->data, true);
+    }
+
+    /**
+     * Gets a record for given key
+     *
+     * There are two special cases:
+     *
+     * 1. if null is given as a key a new record is created and attached
+     * at the end of the collection
+     *
+     * 2. if given key does not exist, then a new record is create and attached
+     * to the given key
+     *
+     * Collection also maps referential information to newly created records
+     *
+     * @param mixed $key                    the key of the element
+     * @return Doctrine_Record              return a specified record
+     */
+    public function get($key)
+    {
+        if ( ! isset($this->data[$key])) {
+            $record = $this->_table->create();
+
+            if (isset($this->referenceField)) {
+                $value = $this->reference->get($this->relation->getLocalFieldName());
+
+                if ($value !== null) {
+                    $record->set($this->referenceField, $value, false);
+                } else {
+                    $record->set($this->referenceField, $this->reference, false);
+                }
+            }
+            if ($key === null) {
+                $this->data[] = $record;
+            } else {
+                $this->data[$key] = $record;      	
+            }
+
+            if (isset($this->keyColumn)) {
+                $record->set($this->keyColumn, $key);
+            }
+
+            return $record;
+        }
+
+        return $this->data[$key];
+    }
+
+    /**
+     * Get array of primary keys for all the records in the collection
+     *
+     * @return array                an array containing all primary keys
+     */
+    public function getPrimaryKeys()
+    {
+        $list = array();
+        $name = $this->_table->getIdentifier();
+
+        foreach ($this->data as $record) {
+            if (is_array($record) && isset($record[$name])) {
+                $list[] = $record[$name];
+            } else {
+                $list[] = $record->getIncremented();
+            }
+        }
+        return $list;
+    }
+
+    /**
+     * Get all keys of the data in the collection
+     *
+     * @return array
+     */
+    public function getKeys()
+    {
+        return array_keys($this->data);
+    }
+
+    /**
+     * Gets the number of records in this collection
+     * This class implements interface countable
+     *
+     * @return integer
+     */
+    public function count()
+    {
+        return count($this->data);
+    }
+
+    /**
+     * Set a Doctrine_Record instance to the collection
+     *
+     * @param integer $key
+     * @param Doctrine_Record $record
+     * @return void
+     */
+    public function set($key, $record)
+    {
+        if (isset($this->referenceField)) {
+            $record->set($this->referenceField, $this->reference, false);
+        }
+
+        $this->data[$key] = $record;
+    }
+
+    /**
+     * Adds a record to collection
+     *
+     * @param Doctrine_Record $record              record to be added
+     * @param string $key                          optional key for the record
+     * @return boolean
+     */
+    public function add($record, $key = null)
+    {
+        if (isset($this->referenceField)) {
+            $value = $this->reference->get($this->relation->getLocalFieldName());
+            if ($value !== null) {
+                $record->set($this->referenceField, $value, false);
+            } else {
+                $record->set($this->referenceField, $this->reference, false);
+            }
+            $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;
+                    break;
+                }
+            }
+        }
+        /**
+         * for some weird reason in_array cannot be used here (php bug ?)
+         *
+         * if used it results in fatal error : [ nesting level too deep ]
+         */
+        foreach ($this->data as $val) {
+            if ($val === $record) {
+                return false;
+            }
+        }
+
+        if (isset($key)) {
+            if (isset($this->data[$key])) {
+                return false;
+            }
+            $this->data[$key] = $record;
+            return true;
+        }
+
+        if (isset($this->keyColumn)) {
+            $value = $record->get($this->keyColumn);
+            if ($value === null) {
+                throw new Doctrine_Collection_Exception("Couldn't create collection index. Record field '".$this->keyColumn."' was null.");
+            }
+            $this->data[$value] = $record;
+        } else {
+            $this->data[] = $record;
+        }
+
+        return true;
+    }
+    
+    /**
+     * Merges collection into $this and returns merged collection
+     * 
+     * @param Doctrine_Collection $coll
+     * @return Doctrine_Collection
+     */
+    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;
+    }
+
+    /**
+     * Load all relationships or the named relationship passed
+     *
+     * @param mixed $name
+     * @return boolean
+     */
+    public function loadRelated($name = null)
+    {
+        $list = array();
+        $query   = new Doctrine_Query($this->_table->getConnection());
+
+        if ( ! isset($name)) {
+            foreach ($this->data as $record) {
+                $value = $record->getIncremented();
+                if ($value !== null) {
+                    $list[] = $value;
+                }
+            }
+            $query->from($this->_table->getComponentName());
+            $query->where($this->_table->getComponentName() . '.id IN (' . substr(str_repeat("?, ", count($list)),0,-2) . ')');
+
+            return $query;
+        }
+
+        $rel     = $this->_table->getRelation($name);
+
+        if ($rel instanceof Doctrine_Relation_LocalKey || $rel instanceof Doctrine_Relation_ForeignKey) {
+            foreach ($this->data as $record) {
+                $list[] = $record[$rel->getLocal()];
+            }
+        } else {
+            foreach ($this->data as $record) {
+                $value = $record->getIncremented();
+                if ($value !== null) {
+                    $list[] = $value;
+                }
+            }
+        }
+
+        $dql     = $rel->getRelationDql(count($list), 'collection');
+
+        $coll    = $query->query($dql, $list);
+
+        $this->populateRelated($name, $coll);
+    }
+
+    /**
+     * Populate the relationship $name for all records in the passed collection
+     *
+     * @param string $name
+     * @param Doctrine_Collection $coll
+     * @return void
+     */
+    public function populateRelated($name, Doctrine_Collection $coll)
+    {
+        $rel     = $this->_table->getRelation($name);
+        $table   = $rel->getTable();
+        $foreign = $rel->getForeign();
+        $local   = $rel->getLocal();
+
+        if ($rel instanceof Doctrine_Relation_LocalKey) {
+            foreach ($this->data as $key => $record) {
+                foreach ($coll as $k => $related) {
+                    if ($related[$foreign] == $record[$local]) {
+                        $this->data[$key]->setRelated($name, $related);
+                    }
+                }
+            }
+        } elseif ($rel instanceof Doctrine_Relation_ForeignKey) {
+            foreach ($this->data as $key => $record) {
+                if ( ! $record->exists()) {
+                    continue;
+                }
+                $sub = new Doctrine_Collection($table);
+
+                foreach ($coll as $k => $related) {
+                    if ($related[$foreign] == $record[$local]) {
+                        $sub->add($related);
+                        $coll->remove($k);
+                    }
+                }
+
+                $this->data[$key]->setRelated($name, $sub);
+            }
+        } elseif ($rel instanceof Doctrine_Relation_Association) {
+            $identifier = $this->_table->getIdentifier();
+            $asf        = $rel->getAssociationFactory();
+            $name       = $table->getComponentName();
+
+            foreach ($this->data as $key => $record) {
+                if ( ! $record->exists()) {
+                    continue;
+                }
+                $sub = new Doctrine_Collection($table);
+                foreach ($coll as $k => $related) {
+                    if ($related->get($local) == $record[$identifier]) {
+                        $sub->add($related->get($name));
+                    }
+                }
+                $this->data[$key]->setRelated($name, $sub);
+
+            }
+        }
+    }
+
+    /**
+     * Get normal iterator - an iterator that will not expand this collection
+     *
+     * @return Doctrine_Iterator_Normal $iterator
+     */
+    public function getNormalIterator()
+    {
+        return new Doctrine_Collection_Iterator_Normal($this);
+    }
+
+    /**
+     * Takes a snapshot from this collection
+     *
+     * snapshots are used for diff processing, for example
+     * when a fetched collection has three elements, then two of those
+     * are being removed the diff would contain one element
+     *
+     * Doctrine_Collection::save() attaches the diff with the help of last
+     * snapshot.
+     *
+     * @return Doctrine_Collection
+     */
+    public function takeSnapshot()
+    {
+        $this->_snapshot = $this->data;
+        
+        return $this;
+    }
+
+    /**
+     * Gets the data of the last snapshot
+     *
+     * @return array    returns the data in last snapshot
+     */
+    public function getSnapshot()
+    {
+        return $this->_snapshot;
+    }
+
+    /**
+     * Processes the difference of the last snapshot and the current data
+     *
+     * an example:
+     * Snapshot with the objects 1, 2 and 4
+     * Current data with objects 2, 3 and 5
+     *
+     * The process would remove object 4
+     *
+     * @return Doctrine_Collection
+     */
+    public function processDiff() 
+    {
+        foreach (array_udiff($this->_snapshot, $this->data, array($this, "compareRecords")) as $record) {
+            $record->delete();
+        }
+
+        return $this;
+    }
+
+    /**
+     * Mimics the result of a $query->execute(array(), Doctrine::HYDRATE_ARRAY);
+     *
+     * @param boolean $deep
+     */
+    public function toArray($deep = false, $prefixKey = false)
+    {
+        $data = array();
+        foreach ($this as $key => $record) {
+            
+            $key = $prefixKey ? get_class($record) . '_' .$key:$key;
+            
+            $data[$key] = $record->toArray($deep, $prefixKey);
+        }
+        
+        return $data;
+    }
+
+    /**
+     * Populate a Doctrine_Collection from an array of data
+     *
+     * @param string $array 
+     * @return void
+     */
+    public function fromArray($array, $deep = true)
+    {
+        $data = array();
+        foreach ($array as $rowKey => $row) {
+            $this[$rowKey]->fromArray($row, $deep);
+        }
+    }
+
+    /**
+     * synchronizes a Doctrine_Collection with data from an array
+     *
+     * it expects an array representation of a Doctrine_Collection similar to the return
+     * value of the toArray() method. It will create Dectrine_Records that don't exist
+     * on the collection, update the ones that do and remove the ones missing in the $array
+     *
+     * @param array $array representation of a Doctrine_Collection
+     */
+    public function synchronizeWithArray(array $array)
+    {
+        foreach ($this as $key => $record) {
+            if (isset($array[$key])) {
+                $record->synchronizeWithArray($array[$key]);
+                unset($array[$key]);
+            } else {
+                // remove records that don't exist in the array
+                $this->remove($key);
+            }
+        }
+        // create new records for each new row in the array
+        foreach ($array as $rowKey => $row) {
+            $this[$rowKey]->fromArray($row);
+        }
+    }
+    public function synchronizeFromArray(array $array)
+    {
+        return $this->synchronizeWithArray($array);
+    }
+
+    /**
+     * Export a Doctrine_Collection to one of the supported Doctrine_Parser formats
+     *
+     * @param string $type 
+     * @param string $deep 
+     * @return void
+     */
+    public function exportTo($type, $deep = false)
+    {
+        if ($type == 'array') {
+            return $this->toArray($deep);
+        } else {
+            return Doctrine_Parser::dump($this->toArray($deep, true), $type);
+        }
+    }
+
+    /**
+     * Import data to a Doctrine_Collection from one of the supported Doctrine_Parser formats
+     *
+     * @param string $type 
+     * @param string $data 
+     * @return void
+     */
+    public function importFrom($type, $data)
+    {
+        if ($type == 'array') {
+            return $this->fromArray($data);
+        } else {
+            return $this->fromArray(Doctrine_Parser::load($data, $type));
+        }
+    }
+
+    /**
+     * Perform a delete diff between the last snapshot and the current data
+     *
+     * @return array $diff
+     */
+    public function getDeleteDiff()
+    {
+        return array_udiff($this->_snapshot, $this->data, array($this, 'compareRecords'));
+    }
+
+    /**
+     * Perform a insert diff between the last snapshot and the current data
+     *
+     * @return array $diff
+     */
+    public function getInsertDiff()
+    {
+        return array_udiff($this->data, $this->_snapshot, array($this, "compareRecords"));
+    }
+
+    /**
+     * Compares two records. To be used on _snapshot diffs using array_udiff
+     *
+     * @param Doctrine_Record $a 
+     * @param Doctrine_Record $b 
+     * @return integer
+     */
+    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 
+     * difference of the last snapshot and the current data
+     *
+     * @param Doctrine_Connection $conn     optional connection parameter
+     * @return Doctrine_Collection
+     */
+    public function save(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->save($conn);
+            }
+
+            $conn->commit();
+        } catch (Exception $e) {
+            $conn->rollback();
+            throw $e;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Deletes all records from this collection
+     *
+     * @return Doctrine_Collection
+     */
+    public function delete(Doctrine_Connection $conn = null, $clearColl = true)
+    {
+        if ($conn == null) {
+            $conn = $this->_table->getConnection();
+        }
+        
+        try {
+            $conn->beginInternalTransaction();
+            $conn->transaction->addCollection($this);
+
+            foreach ($this as $key => $record) {
+                $record->delete($conn);
+            }
+
+            $conn->commit();
+        } catch (Exception $e) {
+            $conn->rollback();
+            throw $e;
+        }
+        
+        if ($clearColl) {
+            $this->clear();
+        }
+        
+        return $this;
+    }
+    
+    /**
+     * Clears the collection.
+     *
+     * @return void
+     */
+    public function clear()
+    {
+        $this->data = array();
+    }
+
+    /**
+     * Frees the resources used by the collection.
+     * WARNING: After invoking free() the collection is no longer considered to
+     * be in a useable state. Subsequent usage may result in unexpected behavior.
+     *
+     * @return void
+     */
+    public function free($deep = false)
+    {
+        foreach ($this->getData() as $key => $record) {
+            if ( ! ($record instanceof Doctrine_Null)) {
+                $record->free($deep);
+            }
+        }
+
+        $this->data = array();
+
+        if ($this->reference) {
+            $this->reference->free($deep);
+            $this->reference = null;
+        }
+    }
+
+    /**
+     * Get collection data iterator
+     *
+     * @return object ArrayIterator
+     */
+    public function getIterator()
+    {
+        $data = $this->data;
+        return new ArrayIterator($data);
+    }
+
+    /**
+     * Returns a string representation of this object
+     *
+     * @return string $string
+     */
+    public function __toString()
+    {
+        return Doctrine_Lib::getCollectionAsString($this);
+    }
+    
+    /**
+     * Returns the relation object
+     *
+     * @return object Doctrine_Relation
+     */
+    public function getRelation()
+    {
+        return $this->relation;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Collection exception class
+ *
+ * @package     Doctrine
+ * @subpackage  Collection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Collection_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,119 @@
+<?php
+/*
+ *  $Id: Iterator.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Collection_Iterator
+ * iterates through Doctrine_Collection
+ *
+ * @package     Doctrine
+ * @subpackage  Collection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+abstract class Doctrine_Collection_Iterator implements Iterator
+{
+    /**
+     * @var Doctrine_Collection $collection
+     */
+    protected $collection;
+
+    /**
+     * @var array $keys
+     */
+    protected $keys;
+
+    /**
+     * @var mixed $key
+     */
+    protected $key;
+
+    /**
+     * @var integer $index
+     */
+    protected $index;
+
+    /**
+     * @var integer $count
+     */
+    protected $count;
+
+    /**
+     * constructor
+     * @var Doctrine_Collection $collection
+     */
+    public function __construct($collection)
+    {
+        $this->collection = $collection;
+        $this->keys       = $this->collection->getKeys();
+        $this->count      = $this->collection->count();
+    }
+
+    /**
+     * rewinds the iterator
+     *
+     * @return void
+     */
+    public function rewind()
+    {
+        $this->index = 0;
+        $i = $this->index;
+        if (isset($this->keys[$i])) {
+            $this->key   = $this->keys[$i];
+        }
+    }
+
+    /**
+     * returns the current key
+     *
+     * @return integer
+     */
+    public function key()
+    {
+        return $this->key;
+    }
+
+    /**
+     * returns the current record
+     *
+     * @return Doctrine_Record
+     */
+    public function current()
+    {
+        return $this->collection->get($this->key);
+    }
+
+    /**
+     * advances the internal pointer
+     *
+     * @return void
+     */
+    public function next()
+    {
+        $this->index++;
+        $i = $this->index;
+        if (isset($this->keys[$i])) {
+            $this->key   = $this->keys[$i];
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator/Expandable.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,54 @@
+<?php
+/*
+ *  $Id: Expandable.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Expandable collection iterator class
+ *
+ * @package     Doctrine
+ * @subpackage  Collection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Collection_Iterator_Expandable extends Doctrine_Collection_Iterator
+{
+    public function valid()
+    {
+        if ($this->index < $this->count) {
+            return true;
+        } elseif ($this->index == $this->count) {
+            $coll  = $this->collection->expand($this->index);
+
+            if ($coll instanceof Doctrine_Collection) {
+                $count = count($coll);
+                if ($count > 0) {
+                    $this->keys   = array_merge($this->keys, $coll->getKeys());
+                    $this->count += $count;
+                    return true;
+                }
+            }
+
+            return false;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator/Normal.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,42 @@
+<?php
+/*
+ *  $Id: Normal.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Collection_Iterator_Normal
+ *
+ * @package     Doctrine
+ * @subpackage  Collection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Collection_Iterator_Normal extends Doctrine_Collection_Iterator
+{
+    /**
+     * @return boolean                          whether or not the iteration will continue
+     */
+    public function valid()
+    {
+        return ($this->index < $this->count);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Iterator/Offset.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,37 @@
+<?php
+/*
+ *  $Id: Offset.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Collection_Iterator_Normal
+ *
+ * @package     Doctrine
+ * @subpackage  Collection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Collection_Iterator_Offset extends Doctrine_Collection_Iterator
+{
+    public function valid()
+    { }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Collection/Offset.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,65 @@
+<?php
+/*
+ *  $Id: Offset.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Collection_Offset
+ * Collection of Doctrine_Record objects.
+ *
+ * @package     Doctrine
+ * @subpackage  Collection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Collection_Offset extends Doctrine_Collection
+{
+    /**
+     * @var integer $limit
+     */
+    private $limit;
+
+    /**
+     * @param Doctrine_Table $table
+     */
+    public function __construct(Doctrine_Table $table)
+    {
+        parent::__construct($table);
+        $this->limit = $table->getAttribute(Doctrine::ATTR_COLL_LIMIT);
+    }
+
+    /**
+     * @return integer
+     */
+    public function getLimit()
+    {
+        return $this->limit;
+    }
+
+    /**
+     * @return Doctrine_Collection_Iterator_Expandable
+     */
+    public function getIterator()
+    {
+        return new Doctrine_Collection_Iterator_Expandable($this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Column.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,158 @@
+<?php
+/*
+ *  $Id: Column.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Column
+ * This class represents a database column
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @package     Doctrine
+ * @subpackage  Column
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Column extends Doctrine_Access implements IteratorAggregate, Countable
+{
+    /**
+     * @var array $definition
+     */
+    protected $_definition = array(
+                                'type'    => null,
+                                'length'  => 0,
+                                );
+
+    /**
+     * @var array $definition
+     */
+    public function __construct(array $definition = array())
+    {
+        $this->_definition = $definition;
+    }
+
+    /**
+     * @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 mixed
+     */
+    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();
+        }
+    }
+
+    /**
+     * enumValue
+     *
+     * @param string $field
+     * @param integer $index
+     * @return mixed
+     */
+    public function enumValue($index)
+    {
+        if ($index instanceof Doctrine_Null) {
+            return $index;
+        }
+
+        return isset($this->_definition['values'][$index]) ? $this->_definition['values'][$index] : $index;
+    }
+
+    /**
+     * 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);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Compiler.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,139 @@
+<?php
+/*
+ *  $Id: Compiler.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Compiler
+ * This class can be used for compiling the entire Doctrine framework into a single file
+ *
+ * @package     Doctrine
+ * @subpackage  Compiler
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpllicense.php LGPL
+ * @link        www.phpdoctrine.
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Compiler
+{
+    /**
+     * method for making a single file of most used doctrine runtime components
+     * including the compiled file instead of multiple files (in worst
+     * cases dozens of files) can improve performance by an order of magnitude
+     *
+     * @throws Doctrine_Compiler_Exception      if something went wrong during the compile operation
+     * @return $target Path the compiled file was written to
+     */
+    public static function compile($target = null, $includedDrivers = array())
+    {
+        if ( ! is_array($includedDrivers)) {
+            $includedDrivers = array($includedDrivers);
+        }
+        
+        $excludedDrivers = array();
+        
+        // If we have an array of specified drivers then lets determine which drivers we should exclude
+        if ( ! empty($includedDrivers)) {
+            $drivers = array('db2',
+                             'firebird',
+                             'informix',
+                             'mssql',
+                             'mysql',
+                             'oracle',
+                             'pgsql',
+                             'sqlite');
+            
+            $excludedDrivers = array_diff($drivers, $includedDrivers);
+        }
+        
+        $path = Doctrine::getPath();
+        $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::LEAVES_ONLY);
+
+        foreach ($it as $file) {
+            $e = explode('.', $file->getFileName());
+            
+            //@todo what is a versioning file? do we have these anymore? None 
+            //exists in my version of doctrine from svn.
+            // we don't want to require versioning files
+            if (end($e) === 'php' && strpos($file->getFileName(), '.inc') === false) {
+                require_once $file->getPathName();
+            }
+        }
+
+        $classes = array_merge(get_declared_classes(), get_declared_interfaces());
+
+        $ret     = array();
+
+        foreach ($classes as $class) {
+            $e = explode('_', $class);
+
+            if ($e[0] !== 'Doctrine') {
+                continue;
+            }
+            
+            // Exclude drivers
+            if ( ! empty($excludedDrivers)) {
+                foreach ($excludedDrivers as $excludedDriver) {
+                    $excludedDriver = ucfirst($excludedDriver);
+                    
+                    if (in_array($excludedDriver, $e)) {
+                        continue(2);
+                    }
+                }
+            }
+            
+            $refl  = new ReflectionClass($class);
+            $file  = $refl->getFileName();
+            
+            $lines = file($file);
+
+            $start = $refl->getStartLine() - 1;
+            $end   = $refl->getEndLine();
+
+            $ret = array_merge($ret, array_slice($lines, $start, ($end - $start)));
+        }
+
+        if ($target == null) {
+            $target = $path . DIRECTORY_SEPARATOR . 'Doctrine.compiled.php';
+        }
+
+        // first write the 'compiled' data to a text file, so
+        // that we can use php_strip_whitespace (which only works on files)
+        $fp = @fopen($target, 'w');
+
+        if ($fp === false) {
+            throw new Doctrine_Compiler_Exception("Couldn't write compiled data. Failed to open $target");
+        }
+        
+        fwrite($fp, "<?php ". implode('', $ret));
+        fclose($fp);
+
+        $stripped = php_strip_whitespace($target);
+        $fp = @fopen($target, 'w');
+        if ($fp === false) {
+            throw new Doctrine_Compiler_Exception("Couldn't write compiled data. Failed to open $file");
+        }
+        
+        fwrite($fp, $stripped);
+        fclose($fp);
+
+        return $target;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Compiler/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Compiler_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Compiler
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Compiler_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Configurable.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,485 @@
+<?php
+/*
+ *  $Id: Configurable.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Configurable
+ * the base for Doctrine_Table, Doctrine_Manager and Doctrine_Connection
+ *
+ * @package     Doctrine
+ * @subpackage  Configurable
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+abstract class Doctrine_Configurable extends Doctrine_Locator_Injectable
+{
+    /**
+     * @var array $attributes               an array of containing all attributes
+     */
+    protected $attributes = array();
+
+    /**
+     * @var Doctrine_Configurable $parent   the parent of this component
+     */
+    protected $parent;
+
+    /**
+     * @var array $_impl                    an array containing concrete implementations for class templates
+     *                                      keys as template names and values as names of the concrete
+     *                                      implementation classes
+     */
+    protected $_impl = array();
+    
+    /**
+     * @var array $_params                  an array of user defined parameters
+     */
+    protected $_params = array();
+
+    /**
+     * getAttributeFromString
+     *
+     * Will accept the name of an attribute and return the attribute value
+     * Example: ->getAttributeFromString('portability') will be converted to Doctrine::ATTR_PORTABILITY
+     * and returned
+     *
+     * @param string $stringAttributeName 
+     * @return void
+     */
+    public function getAttributeFromString($stringAttributeName)
+    {
+      if (is_string($stringAttributeName)) {
+          $upper = strtoupper($stringAttributeName);
+
+          $const = 'Doctrine::ATTR_' . $upper; 
+
+          if (defined($const)) {
+              return constant($const);
+          } else {
+              throw new Doctrine_Exception('Unknown attribute: "' . $stringAttributeName . '"');
+          }
+      } else {
+        return false;
+      }
+    }
+
+    /**
+     * getAttributeValueFromString
+     *
+     * Will get the value for an attribute by the string name
+     * Example: ->getAttributeFromString('portability', 'all') will return Doctrine::PORTABILITY_ALL
+     *
+     * @param string $stringAttributeName 
+     * @param string $stringAttributeValueName 
+     * @return void
+     */
+    public function getAttributeValueFromString($stringAttributeName, $stringAttributeValueName)
+    {
+        $const = 'Doctrine::' . strtoupper($stringAttributeName) . '_' . strtoupper($stringAttributeValueName);
+
+        if (defined($const)) {
+            return constant($const);
+        } else {
+            throw new Doctrine_Exception('Unknown attribute value: "' . $const . '"');
+        }
+    }
+
+    /**
+     * setAttribute
+     * sets a given attribute
+     *
+     * <code>
+     * $manager->setAttribute(Doctrine::ATTR_PORTABILITY, Doctrine::PORTABILITY_ALL);
+     *
+     * // or
+     *
+     * $manager->setAttribute('portability', Doctrine::PORTABILITY_ALL);
+     *
+     * // or
+     *
+     * $manager->setAttribute('portability', 'all');
+     * </code>
+     *
+     * @param mixed $attribute              either a Doctrine::ATTR_* integer constant or a string
+     *                                      corresponding to a constant
+     * @param mixed $value                  the value of the attribute
+     * @see Doctrine::ATTR_* constants
+     * @throws Doctrine_Exception           if the value is invalid
+     * @return void
+     */
+    public function setAttribute($attribute, $value)
+    {
+        if (is_string($attribute)) {
+            $stringAttribute = $attribute;
+            $attribute = $this->getAttributeFromString($attribute);
+            $this->_state = $attribute;
+        }
+
+        if (is_string($value) && isset($stringAttribute)) {
+            $value = $this->getAttributeValueFromString($stringAttribute, $value);
+        }
+
+        switch ($attribute) {
+            case Doctrine::ATTR_FETCHMODE:
+                throw new Doctrine_Exception('Deprecated attribute. See http://www.phpdoctrine.org/documentation/manual?chapter=configuration');
+            case Doctrine::ATTR_LISTENER:
+                $this->setEventListener($value);
+                break;
+            case Doctrine::ATTR_COLL_KEY:
+                if ( ! ($this instanceof Doctrine_Table)) {
+                    throw new Doctrine_Exception("This attribute can only be set at table level.");
+                }
+                if ($value !== null && ! $this->hasField($value)) {
+                    throw new Doctrine_Exception("Couldn't set collection key attribute. No such field '$value'.");
+                }
+                break;
+            case Doctrine::ATTR_CACHE:
+            case Doctrine::ATTR_RESULT_CACHE:
+            case Doctrine::ATTR_QUERY_CACHE:
+                if ($value !== null) {
+                    if ( ! ($value instanceof Doctrine_Cache_Interface)) {
+                        throw new Doctrine_Exception('Cache driver should implement Doctrine_Cache_Interface');
+                    }
+                }
+                break;
+            case Doctrine::ATTR_VALIDATE:
+            case Doctrine::ATTR_QUERY_LIMIT:
+            case Doctrine::ATTR_QUOTE_IDENTIFIER:
+            case Doctrine::ATTR_PORTABILITY:
+            case Doctrine::ATTR_DEFAULT_TABLE_TYPE:
+            case Doctrine::ATTR_EMULATE_DATABASE:
+            case Doctrine::ATTR_USE_NATIVE_ENUM:
+            case Doctrine::ATTR_DEFAULT_SEQUENCE:
+            case Doctrine::ATTR_EXPORT:
+            case Doctrine::ATTR_DECIMAL_PLACES:
+            case Doctrine::ATTR_LOAD_REFERENCES:
+            case Doctrine::ATTR_RECORD_LISTENER:
+            case Doctrine::ATTR_THROW_EXCEPTIONS:
+            case Doctrine::ATTR_DEFAULT_PARAM_NAMESPACE:
+            case Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES:
+            case Doctrine::ATTR_MODEL_LOADING:
+            case Doctrine::ATTR_RESULT_CACHE_LIFESPAN:
+            case Doctrine::ATTR_QUERY_CACHE_LIFESPAN:
+            case Doctrine::ATTR_RECURSIVE_MERGE_FIXTURES;
+            case Doctrine::ATTR_USE_DQL_CALLBACKS;
+            case Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE;
+            case Doctrine::ATTR_HYDRATE_OVERWRITE;
+
+                break;
+            case Doctrine::ATTR_SEQCOL_NAME:
+                if ( ! is_string($value)) {
+                    throw new Doctrine_Exception('Sequence column name attribute only accepts string values');
+                }
+                break;
+            case Doctrine::ATTR_FIELD_CASE:
+                if ($value != 0 && $value != CASE_LOWER && $value != CASE_UPPER)
+                    throw new Doctrine_Exception('Field case attribute should be either 0, CASE_LOWER or CASE_UPPER constant.');
+                break;
+            case Doctrine::ATTR_SEQNAME_FORMAT:
+            case Doctrine::ATTR_IDXNAME_FORMAT:
+            case Doctrine::ATTR_TBLNAME_FORMAT:
+                if ($this instanceof Doctrine_Table) {
+                    throw new Doctrine_Exception('Sequence / index name format attributes cannot be set'
+                                               . 'at table level (only at connection or global level).');
+                }
+                break;
+            default:
+                throw new Doctrine_Exception("Unknown attribute.");
+        }
+
+        $this->attributes[$attribute] = $value;
+    }
+
+    public function getParams($namespace = null)
+    {
+    	if ($namespace == null) {
+    	    $namespace = $this->getAttribute(Doctrine::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) 
+    {
+    	if ($namespace == null) {
+    	    $namespace = $this->getAttribute(Doctrine::ATTR_DEFAULT_PARAM_NAMESPACE);
+    	}
+    	
+    	$this->_params[$namespace][$name] = $value;
+    	
+    	return $this;
+    }
+    
+    public function getParam($name, $namespace = null) 
+    {
+    	if ($namespace == null) {
+    	    $namespace = $this->getAttribute(Doctrine::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];
+    }
+    /**
+     * setImpl
+     * binds given class to given template name
+     *
+     * this method is the base of Doctrine dependency injection
+     *
+     * @param string $template      name of the class template
+     * @param string $class         name of the class to be bound
+     * @return Doctrine_Configurable    this object
+     */
+    public function setImpl($template, $class)
+    {
+        $this->_impl[$template] = $class;
+
+        return $this;
+    }
+
+    /**
+     * getImpl
+     * returns the implementation for given class
+     *
+     * @return string   name of the concrete implementation
+     */
+    public function getImpl($template)
+    {
+        if ( ! isset($this->_impl[$template])) {
+            if (isset($this->parent)) {
+                return $this->parent->getImpl($template);
+            }
+            return null;
+        }
+        return $this->_impl[$template];
+    }
+    
+    
+    public function hasImpl($template)
+    {
+        if ( ! isset($this->_impl[$template])) {
+            if (isset($this->parent)) {
+                return $this->parent->hasImpl($template);
+            }
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * @param Doctrine_EventListener $listener
+     * @return void
+     */
+    public function setEventListener($listener)
+    {
+        return $this->setListener($listener);
+    }
+
+    /**
+     * addRecordListener
+     *
+     * @param Doctrine_EventListener_Interface|Doctrine_Overloadable $listener
+     * @return mixed        this object
+     */
+    public function addRecordListener($listener, $name = null)
+    {
+        if ( ! isset($this->attributes[Doctrine::ATTR_RECORD_LISTENER]) ||
+             ! ($this->attributes[Doctrine::ATTR_RECORD_LISTENER] instanceof Doctrine_Record_Listener_Chain)) {
+
+            $this->attributes[Doctrine::ATTR_RECORD_LISTENER] = new Doctrine_Record_Listener_Chain();
+        }
+        $this->attributes[Doctrine::ATTR_RECORD_LISTENER]->add($listener, $name);
+
+        return $this;
+    }
+
+    /**
+     * getListener
+     *
+     * @return Doctrine_EventListener_Interface|Doctrine_Overloadable
+     */
+    public function getRecordListener()
+    {
+        if ( ! isset($this->attributes[Doctrine::ATTR_RECORD_LISTENER])) {
+            if (isset($this->parent)) {
+                return $this->parent->getRecordListener();
+            }
+            return null;
+        }
+        return $this->attributes[Doctrine::ATTR_RECORD_LISTENER];
+    }
+
+    /**
+     * setListener
+     *
+     * @param Doctrine_EventListener_Interface|Doctrine_Overloadable $listener
+     * @return Doctrine_Configurable        this object
+     */
+    public function setRecordListener($listener)
+    {
+        if ( ! ($listener instanceof Doctrine_Record_Listener_Interface)
+            && ! ($listener instanceof Doctrine_Overloadable)
+        ) {
+            throw new Doctrine_Exception("Couldn't set eventlistener. Record listeners should implement either Doctrine_Record_Listener_Interface or Doctrine_Overloadable");
+        }
+        $this->attributes[Doctrine::ATTR_RECORD_LISTENER] = $listener;
+
+        return $this;
+    }
+
+    /**
+     * addListener
+     *
+     * @param Doctrine_EventListener_Interface|Doctrine_Overloadable $listener
+     * @return mixed        this object
+     */
+    public function addListener($listener, $name = null)
+    {
+        if ( ! isset($this->attributes[Doctrine::ATTR_LISTENER]) ||
+             ! ($this->attributes[Doctrine::ATTR_LISTENER] instanceof Doctrine_EventListener_Chain)) {
+
+            $this->attributes[Doctrine::ATTR_LISTENER] = new Doctrine_EventListener_Chain();
+        }
+        $this->attributes[Doctrine::ATTR_LISTENER]->add($listener, $name);
+
+        return $this;
+    }
+
+    /**
+     * getListener
+     *
+     * @return Doctrine_EventListener_Interface|Doctrine_Overloadable
+     */
+    public function getListener()
+    {
+        if ( ! isset($this->attributes[Doctrine::ATTR_LISTENER])) {
+            if (isset($this->parent)) {
+                return $this->parent->getListener();
+            }
+            return null;
+        }
+        return $this->attributes[Doctrine::ATTR_LISTENER];
+    }
+
+    /**
+     * setListener
+     *
+     * @param Doctrine_EventListener_Interface|Doctrine_Overloadable $listener
+     * @return Doctrine_Configurable        this object
+     */
+    public function setListener($listener)
+    {
+        if ( ! ($listener instanceof Doctrine_EventListener_Interface)
+            && ! ($listener instanceof Doctrine_Overloadable)
+        ) {
+            throw new Doctrine_EventListener_Exception("Couldn't set eventlistener. EventListeners should implement either Doctrine_EventListener_Interface or Doctrine_Overloadable");
+        }
+        $this->attributes[Doctrine::ATTR_LISTENER] = $listener;
+
+        return $this;
+    }
+
+    /**
+     * returns the value of an attribute
+     *
+     * @param integer $attribute
+     * @return mixed
+     */
+    public function getAttribute($attribute)
+    {
+        if (is_string($attribute)) {
+            $upper = strtoupper($attribute);
+
+            $const = 'Doctrine::ATTR_' . $upper; 
+
+            if (defined($const)) {
+                $attribute = constant($const);
+                $this->_state = $attribute;
+            } else {
+                throw new Doctrine_Exception('Unknown attribute: "' . $attribute . '"');
+            }
+        }
+
+        $attribute = (int) $attribute;
+
+        if ($attribute < 0) {
+            throw new Doctrine_Exception('Unknown attribute.');
+        }
+
+        if (isset($this->attributes[$attribute])) {
+            return $this->attributes[$attribute];
+        }
+        
+        if (isset($this->parent)) {
+            return $this->parent->getAttribute($attribute);
+        }
+        return null;
+    }
+
+    /**
+     * getAttributes
+     * returns all attributes as an array
+     *
+     * @return array
+     */
+    public function getAttributes()
+    {
+        return $this->attributes;
+    }
+
+    /**
+     * sets a parent for this configurable component
+     * the parent must be configurable component itself
+     *
+     * @param Doctrine_Configurable $component
+     * @return void
+     */
+    public function setParent(Doctrine_Configurable $component)
+    {
+        $this->parent = $component;
+    }
+
+    /**
+     * getParent
+     * returns the parent of this component
+     *
+     * @return Doctrine_Configurable
+     */
+    public function getParent()
+    {
+        return $this->parent;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,1596 @@
+<?php
+/*
+ *  $Id: Connection.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection
+ *
+ * A wrapper layer on top of PDO / Doctrine_Adapter
+ *
+ * Doctrine_Connection is the heart of any Doctrine based application.
+ *
+ * 1. Event listeners
+ *    An easy to use, pluggable eventlistener architecture. Aspects such as
+ *    logging, query profiling and caching can be easily implemented through
+ *    the use of these listeners
+ *
+ * 2. Lazy-connecting
+ *    Creating an instance of Doctrine_Connection does not connect
+ *    to database. Connecting to database is only invoked when actually needed
+ *    (for example when query() is being called) 
+ *
+ * 3. Convenience methods
+ *    Doctrine_Connection provides many convenience methods such as fetchAll(), fetchOne() etc.
+ *
+ * 4. Modular structure
+ *    Higher level functionality such as schema importing, exporting, sequence handling etc.
+ *    is divided into modules. For a full list of connection modules see 
+ *    Doctrine_Connection::$_modules
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (MDB2 library)
+ */
+abstract class Doctrine_Connection extends Doctrine_Configurable implements Countable, IteratorAggregate, Serializable
+{
+    /**
+     * @var $dbh                                the database handler
+     */
+    protected $dbh;
+
+    /**
+     * @var array $tables                       an array containing all the initialized Doctrine_Table objects
+     *                                          keys representing Doctrine_Table component names and values as Doctrine_Table objects
+     */
+    protected $tables           = array();
+
+    /**
+     * $_name
+     *
+     * Name of the connection
+     *
+     * @var string $_name
+     */
+    protected $_name;
+
+    /**
+     * The name of this connection driver.
+     *
+     * @var string $driverName                  
+     */
+    protected $driverName;
+
+    /**
+     * @var boolean $isConnected                whether or not a connection has been established
+     */
+    protected $isConnected      = false;
+
+    /**
+     * @var array $supported                    an array containing all features this driver supports,
+     *                                          keys representing feature names and values as
+     *                                          one of the following (true, false, 'emulated')
+     */
+    protected $supported        = array();
+
+    /**
+     * @var array $pendingAttributes            An array of pending attributes. When setting attributes
+     *                                          no connection is needed. When connected all the pending
+     *                                          attributes are passed to the underlying adapter (usually PDO) instance.
+     */
+    protected $pendingAttributes  = array();
+
+    /**
+     * @var array $modules                      an array containing all modules
+     *              transaction                 Doctrine_Transaction driver, handles savepoint and transaction isolation abstraction
+     *
+     *              expression                  Doctrine_Expression driver, handles expression abstraction
+     *
+     *              dataDict                    Doctrine_DataDict driver, handles datatype abstraction
+     *
+     *              export                      Doctrine_Export driver, handles db structure modification abstraction (contains
+     *                                          methods such as alterTable, createConstraint etc.)
+     *              import                      Doctrine_Import driver, handles db schema reading
+     *
+     *              sequence                    Doctrine_Sequence driver, handles sequential id generation and retrieval
+     *
+     *              unitOfWork                  Doctrine_Connection_UnitOfWork handles many orm functionalities such as object
+     *                                          deletion and saving
+     *
+     *              formatter                   Doctrine_Formatter handles data formatting, quoting and escaping
+     *
+     * @see Doctrine_Connection::__get()
+     * @see Doctrine_DataDict
+     * @see Doctrine_Expression
+     * @see Doctrine_Export
+     * @see Doctrine_Transaction
+     * @see Doctrine_Sequence
+     * @see Doctrine_Connection_UnitOfWork
+     * @see Doctrine_Formatter
+     */
+    private $modules = array('transaction' => false,
+                             'expression'  => false,
+                             'dataDict'    => false,
+                             'export'      => false,
+                             'import'      => false,
+                             'sequence'    => false,
+                             'unitOfWork'  => false,
+                             'formatter'   => false,
+                             'util'        => false,
+                             );
+
+    /**
+     * @var array $properties               an array of connection properties
+     */
+    protected $properties = array('sql_comments'        => array(array('start' => '--', 'end' => "\n", 'escape' => false),
+                                                                 array('start' => '/*', 'end' => '*/', 'escape' => false)),
+                                  'identifier_quoting'  => array('start' => '"', 'end' => '"','escape' => '"'),
+                                  'string_quoting'      => array('start' => "'",
+                                                                 'end' => "'",
+                                                                 'escape' => false,
+                                                                 'escape_pattern' => false),
+                                  'wildcards'           => array('%', '_'),
+                                  'varchar_max_length'  => 255,
+                                  'sql_file_delimiter'  => ";\n",
+                                  );
+
+    /**
+     * @var array $serverInfo
+     */
+    protected $serverInfo = array();
+    
+    protected $options    = array();
+
+    /**
+     * @var array $supportedDrivers         an array containing all supported drivers
+     */
+    private static $supportedDrivers    = array(
+                                        'Mysql',
+                                        'Pgsql',
+                                        'Oracle',
+                                        'Informix',
+                                        'Mssql',
+                                        'Sqlite',
+                                        'Firebird'
+                                        );
+    protected $_count = 0;
+
+    /**
+     * the constructor
+     *
+     * @param Doctrine_Manager $manager                 the manager object
+     * @param PDO|Doctrine_Adapter_Interface $adapter   database driver
+     */
+    public function __construct(Doctrine_Manager $manager, $adapter, $user = null, $pass = null)
+    {
+        if (is_object($adapter)) {
+            if ( ! ($adapter instanceof PDO) && ! in_array('Doctrine_Adapter_Interface', class_implements($adapter))) {
+                throw new Doctrine_Connection_Exception('First argument should be an instance of PDO or implement Doctrine_Adapter_Interface');
+            }
+            $this->dbh = $adapter;
+
+            $this->isConnected = true;
+
+        } else if (is_array($adapter)) {
+            $this->pendingAttributes[Doctrine::ATTR_DRIVER_NAME] = $adapter['scheme'];
+
+            $this->options['dsn']      = $adapter['dsn'];
+            $this->options['username'] = $adapter['user'];
+            $this->options['password'] = $adapter['pass'];
+            
+            $this->options['other'] = array();  
+            if (isset($adapter['other'])) {
+                $this->options['other'] = array(Doctrine::ATTR_PERSISTENT => $adapter['persistent']);
+            }
+
+        }
+
+        $this->setParent($manager);
+
+        $this->setAttribute(Doctrine::ATTR_CASE, Doctrine::CASE_NATURAL);
+        $this->setAttribute(Doctrine::ATTR_ERRMODE, Doctrine::ERRMODE_EXCEPTION);
+
+        $this->getAttribute(Doctrine::ATTR_LISTENER)->onOpen($this);
+    }
+
+    /**
+     * getOptions
+     *
+     * Get array of all options
+     *
+     * @return void
+     */
+    public function getOptions()
+    {
+      return $this->options;
+    }
+
+    /**
+     * getOption
+     * 
+     * Retrieves option
+     *
+     * @param string $option 
+     * @return void
+     */
+    public function getOption($option)
+    {
+        if (isset($this->options[$option])) {
+            return $this->options[$option];
+        }
+    }
+
+    /**
+     * setOption
+     * 
+     * Set option value
+     *
+     * @param string $option 
+     * @return void
+     */
+    public function setOption($option, $value)
+    {
+      return $this->options[$option] = $value;
+    }
+
+    /**
+     * getAttribute
+     * retrieves a database connection attribute
+     *
+     * @param integer $attribute
+     * @return mixed
+     */
+    public function getAttribute($attribute)
+    {
+        if (is_string($attribute)) {
+            $stringAttribute = $attribute;
+            $attribute = $this->getAttributeFromString($attribute);
+        }
+
+        if ($attribute >= 100) {
+            if ( ! isset($this->attributes[$attribute])) {
+                return parent::getAttribute($attribute);
+            }
+            return $this->attributes[$attribute];
+        }
+
+        if ($this->isConnected) {
+            try {
+                return $this->dbh->getAttribute($attribute);
+            } catch (Exception $e) {
+                throw new Doctrine_Connection_Exception('Attribute ' . $attribute . ' not found.');
+            }
+        } else {
+            if ( ! isset($this->pendingAttributes[$attribute])) {
+                $this->connect();
+                $this->getAttribute($attribute);
+            }
+
+            return $this->pendingAttributes[$attribute];
+        }
+    }
+
+    /**
+     * returns an array of available PDO drivers
+     */
+    public static function getAvailableDrivers()
+    {
+        return PDO::getAvailableDrivers();
+    }
+
+    /**
+     * Returns an array of supported drivers by Doctrine
+     *
+     * @return array $supportedDrivers
+     */
+    public static function getSupportedDrivers()
+    {
+        return self::$supportedDrivers;
+    }
+
+    /**
+     * setAttribute
+     * sets an attribute
+     *
+     * @todo why check for >= 100? has this any special meaning when creating 
+     * attributes?
+     *
+     * @param integer $attribute
+     * @param mixed $value
+     * @return boolean
+     */
+    public function setAttribute($attribute, $value)
+    {
+        if (is_string($attribute)) {
+            $attributeString = $attribute;
+            $attribute = parent::getAttributeFromString($attribute);
+        }
+
+        if (is_string($value) && isset($attributeString)) {
+            $value = parent::getAttributeValueFromString($attributeString, $value);
+        }
+
+        if ($attribute >= 100) {
+            parent::setAttribute($attribute, $value);
+        } else {
+            if ($this->isConnected) {
+                $this->dbh->setAttribute($attribute, $value);
+            } else {
+                $this->pendingAttributes[$attribute] = $value;
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * getName
+     * returns the name of this driver
+     *
+     * @return string           the name of this driver
+     */
+    public function getName()
+    {
+        return $this->_name;
+    }
+
+    /**
+     * setName
+     *
+     * Sets the name of the connection
+     *
+     * @param string $name 
+     * @return void
+     */
+    public function setName($name)
+    {
+        $this->_name = $name;
+    }
+
+    /**
+     * getDriverName
+     *
+     * Gets the name of the instance driver
+     *
+     * @return void
+     */
+    public function getDriverName()
+    {
+        return $this->driverName;
+    }
+
+    /**
+     * __get
+     * lazy loads given module and returns it
+     *
+     * @see Doctrine_DataDict
+     * @see Doctrine_Expression
+     * @see Doctrine_Export
+     * @see Doctrine_Transaction
+     * @see Doctrine_Connection::$modules       all availible modules
+     * @param string $name                      the name of the module to get
+     * @throws Doctrine_Connection_Exception    if trying to get an unknown module
+     * @return Doctrine_Connection_Module       connection module
+     */
+    public function __get($name)
+    {
+        if (isset($this->properties[$name])) {
+            return $this->properties[$name];
+        }
+
+        if ( ! isset($this->modules[$name])) {
+            throw new Doctrine_Connection_Exception('Unknown module / property ' . $name);
+        }
+        if ($this->modules[$name] === false) {
+            switch ($name) {
+                case 'unitOfWork':
+                    $this->modules[$name] = new Doctrine_Connection_UnitOfWork($this);
+                    break;
+                case 'formatter':
+                    $this->modules[$name] = new Doctrine_Formatter($this);
+                    break;
+                default:
+                    $class = 'Doctrine_' . ucwords($name) . '_' . $this->getDriverName();
+                    $this->modules[$name] = new $class($this);
+                }
+        }
+
+        return $this->modules[$name];
+    }
+
+    /**
+     * returns the manager that created this connection
+     *
+     * @return Doctrine_Manager
+     */
+    public function getManager()
+    {
+        return $this->getParent();
+    }
+
+    /**
+     * returns the database handler of which this connection uses
+     *
+     * @return PDO              the database handler
+     */
+    public function getDbh()
+    {
+        $this->connect();
+        
+        return $this->dbh;
+    }
+
+    /**
+     * connect
+     * connects into database
+     *
+     * @return boolean
+     */
+    public function connect()
+    {
+        if ($this->isConnected) {
+            return false;
+        }
+
+        $event = new Doctrine_Event($this, Doctrine_Event::CONN_CONNECT);
+
+        $this->getListener()->preConnect($event);
+
+        $e     = explode(':', $this->options['dsn']);
+        $found = false;
+        
+        if (extension_loaded('pdo')) {
+            if (in_array($e[0], self::getAvailableDrivers())) {
+            	try {
+                    $this->dbh = new PDO($this->options['dsn'], $this->options['username'], 
+                                     (!$this->options['password'] ? '':$this->options['password']), $this->options['other']);
+
+                    $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+            	} catch (PDOException $e) {
+            		throw new Doctrine_Connection_Exception('PDO Connection Error: ' . $e->getMessage());
+            	}
+                $found = true;
+            }
+        }
+
+        if ( ! $found) {
+            $class = 'Doctrine_Adapter_' . ucwords($e[0]);
+
+            if (class_exists($class)) {
+                $this->dbh = new $class($this->options['dsn'], $this->options['username'], $this->options['password']);
+            } else {
+                throw new Doctrine_Connection_Exception("Couldn't locate driver named " . $e[0]);          
+            }
+        }
+
+        // attach the pending attributes to adapter
+        foreach($this->pendingAttributes as $attr => $value) {
+            // some drivers don't support setting this so we just skip it
+            if ($attr == Doctrine::ATTR_DRIVER_NAME) {
+                continue;
+            }
+            $this->dbh->setAttribute($attr, $value);
+        }
+
+        $this->isConnected = true;
+
+        $this->getListener()->postConnect($event);
+        return true;
+    }
+    
+    public function incrementQueryCount() 
+    {
+        $this->_count++;
+    }
+
+    /**
+     * converts given driver name
+     *
+     * @param
+     */
+    public function driverName($name)
+    {
+    }
+
+    /**
+     * supports
+     *
+     * @param string $feature   the name of the feature
+     * @return boolean          whether or not this drivers supports given feature
+     */
+    public function supports($feature)
+    {
+        return (isset($this->supported[$feature])
+                  && ($this->supported[$feature] === 'emulated'
+                   || $this->supported[$feature]));
+    }
+
+    /**
+     * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
+     * query, except that if there is already a row in the table with the same
+     * key field values, the REPLACE query just updates its values instead of
+     * inserting a new row.
+     *
+     * The REPLACE type of query does not make part of the SQL standards. Since
+     * practically only MySQL and SQLIte implement it natively, this type of
+     * query isemulated through this method for other DBMS using standard types
+     * of queries inside a transaction to assure the atomicity of the operation.
+     *
+     * @param                   string  name of the table on which the REPLACE query will
+     *                          be executed.
+     *
+     * @param   array           an associative array that describes the fields and the
+     *                          values that will be inserted or updated in the specified table. The
+     *                          indexes of the array are the names of all the fields of the table.
+     *
+     *                          The values of the array are values to be assigned to the specified field.
+     *
+     * @param array $keys       an array containing all key fields (primary key fields
+     *                          or unique index fields) for this table
+     *
+     *                          the uniqueness of a row will be determined according to
+     *                          the provided key fields
+     *
+     *                          this method will fail if no key fields are specified
+     *
+     * @throws Doctrine_Connection_Exception        if this driver doesn't support replace
+     * @throws Doctrine_Connection_Exception        if some of the key values was null
+     * @throws Doctrine_Connection_Exception        if there were no key fields
+     * @throws PDOException                         if something fails at PDO level
+     * @ return integer                              number of rows affected
+     */
+    public function replace(Doctrine_Table $table, array $fields, array $keys)
+    {
+        if (empty($keys)) {
+            throw new Doctrine_Connection_Exception('Not specified which fields are keys');
+        }
+        $identifier = (array) $table->getIdentifier();
+        $condition = array();
+
+        foreach ($fields as $fieldName => $value) {
+            if (in_array($fieldName, $keys)) {
+                if ($value !== null) {
+                    $condition[] = $table->getColumnName($fieldName) . ' = ?';
+                    $conditionValues[] = $value;
+                }
+            }
+        }
+
+        $affectedRows = 0;
+        if ( ! empty($condition) && ! empty($conditionValues)) {
+            $query = 'DELETE FROM ' . $this->quoteIdentifier($table->getTableName())
+                    . ' WHERE ' . implode(' AND ', $condition);
+
+            $affectedRows = $this->exec($query, $conditionValues);
+        }
+
+        $this->insert($table, $fields);
+
+        $affectedRows++;
+
+        return $affectedRows;
+    }
+
+    /**
+     * deletes table row(s) matching the specified identifier
+     *
+     * @throws Doctrine_Connection_Exception    if something went wrong at the database level
+     * @param string $table         The table to delete data from
+     * @param array $identifier     An associateve array containing identifier column-value pairs.
+     * @return integer              The number of affected rows
+     */
+    public function delete(Doctrine_Table $table, array $identifier)
+    {
+        $tmp = array();
+
+        foreach (array_keys($identifier) as $id) {
+            $tmp[] = $this->quoteIdentifier($table->getColumnName($id)) . ' = ?';
+        }
+
+        $query = 'DELETE FROM '
+               . $this->quoteIdentifier($table->getTableName())
+               . ' WHERE ' . implode(' AND ', $tmp);
+        
+        return $this->exec($query, array_values($identifier));
+    }
+
+    /**
+     * Updates table row(s) with specified data
+     *
+     * @throws Doctrine_Connection_Exception    if something went wrong at the database level
+     * @param string $table     The table to insert data into
+     * @param array $values     An associateve array containing column-value pairs.
+     * @return mixed            boolean false if empty value array was given,
+     *                          otherwise returns the number of affected rows
+     */
+    public function update(Doctrine_Table $table, array $fields, array $identifier)
+    {
+        if (empty($fields)) {
+            return false;
+        }
+
+        $set = array();
+        foreach ($fields as $fieldName => $value) {
+            if ($value instanceof Doctrine_Expression) {
+                $set[] = $this->quoteIdentifier($table->getColumnName($fieldName)) . ' = ' . $value->getSql();
+                unset($fields[$fieldName]);
+            } else {
+                $set[] = $this->quoteIdentifier($table->getColumnName($fieldName)) . ' = ?';
+            }
+        }
+
+        $params = array_merge(array_values($fields), array_values($identifier));
+
+        $sql  = 'UPDATE ' . $this->quoteIdentifier($table->getTableName())
+              . ' SET ' . implode(', ', $set)
+              . ' WHERE ' . implode(' = ? AND ', $this->quoteMultipleIdentifier($table->getIdentifierColumnNames()))
+              . ' = ?';
+          
+        return $this->exec($sql, $params);
+    }
+
+    /**
+     * Inserts a table row with specified data.
+     *
+     * @param string $table     The table to insert data into.
+     * @param array $values     An associateve array containing column-value pairs.
+     * @return mixed            boolean false if empty value array was given,
+     *                          otherwise returns the number of affected rows
+     */
+    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) {
+            $cols[] = $this->quoteIdentifier($table->getColumnName($fieldName));
+            if ($value instanceof Doctrine_Expression) {
+                $a[] = $value->getSql();
+                unset($fields[$fieldName]);
+            } else {
+                $a[] = '?';
+            }
+        }
+
+        // build the statement
+        $query = 'INSERT INTO ' . $this->quoteIdentifier($tableName)
+                . ' (' . implode(', ', $cols) . ')'
+                . ' VALUES (' . implode(', ', $a) . ')';
+
+        return $this->exec($query, array_values($fields));
+    }
+
+    /**
+     * Set the charset on the current connection
+     *
+     * @param string    charset
+     */
+    public function setCharset($charset)
+    {
+
+    }
+
+    /**
+     * Quote a string so it can be safely used as a table or column name
+     *
+     * Delimiting style depends on which database driver is being used.
+     *
+     * NOTE: just because you CAN use delimited identifiers doesn't mean
+     * you SHOULD use them.  In general, they end up causing way more
+     * problems than they solve.
+     *
+     * Portability is broken by using the following characters inside
+     * delimited identifiers:
+     *   + backtick (<kbd>`</kbd>) -- due to MySQL
+     *   + double quote (<kbd>"</kbd>) -- due to Oracle
+     *   + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access
+     *
+     * Delimited identifiers are known to generally work correctly under
+     * the following drivers:
+     *   + mssql
+     *   + mysql
+     *   + mysqli
+     *   + oci8
+     *   + pgsql
+     *   + sqlite
+     *
+     * InterBase doesn't seem to be able to use delimited identifiers
+     * via PHP 4.  They work fine under PHP 5.
+     *
+     * @param string $str           identifier name to be quoted
+     * @param bool $checkOption     check the 'quote_identifier' option
+     *
+     * @return string               quoted identifier string
+     */
+    public function quoteIdentifier($str, $checkOption = true)
+    {
+        // quick fix for the identifiers that contain a dot
+        if (strpos($str, '.')) {
+            $e = explode('.', $str);
+            
+            return $this->formatter->quoteIdentifier($e[0], $checkOption) . '.' 
+                 . $this->formatter->quoteIdentifier($e[1], $checkOption);
+        }
+        return $this->formatter->quoteIdentifier($str, $checkOption);
+    }
+    
+    /**
+     * quoteMultipleIdentifier
+     * Quotes multiple identifier strings
+     *
+     * @param array $arr           identifiers array to be quoted
+     * @param bool $checkOption     check the 'quote_identifier' option
+     *
+     * @return string               quoted identifier string
+     */
+    public function quoteMultipleIdentifier($arr, $checkOption = true)
+    {
+        foreach ($arr as $k => $v) {
+            $arr[$k] = $this->quoteIdentifier($v, $checkOption);
+        }
+
+		return $arr;
+    }
+
+
+    /**
+     * convertBooleans
+     * 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)
+    {
+        return $this->formatter->convertBooleans($item);
+    }
+
+    /**
+     * quote
+     * quotes given input parameter
+     *
+     * @param mixed $input      parameter to be quoted
+     * @param string $type
+     * @return mixed
+     */
+    public function quote($input, $type = null)
+    {
+        return $this->formatter->quote($input, $type);
+    }
+
+    /**
+     * Set the date/time format for the current connection
+     *
+     * @param string    time format
+     *
+     * @return void
+     */
+    public function setDateFormat($format = null)
+    {
+    }
+
+    /**
+     * fetchAll
+     *
+     * @param string $statement         sql query to be executed
+     * @param array $params             prepared statement params
+     * @return array
+     */
+    public function fetchAll($statement, array $params = array()) 
+    {
+        return $this->execute($statement, $params)->fetchAll(Doctrine::FETCH_ASSOC);
+    }
+
+    /**
+     * fetchOne
+     *
+     * @param string $statement         sql query to be executed
+     * @param array $params             prepared statement params
+     * @param int $colnum               0-indexed column number to retrieve
+     * @return mixed
+     */
+    public function fetchOne($statement, array $params = array(), $colnum = 0) 
+    {
+        return $this->execute($statement, $params)->fetchColumn($colnum);
+    }
+
+    /**
+     * fetchRow
+     *
+     * @param string $statement         sql query to be executed
+     * @param array $params             prepared statement params
+     * @return array
+     */
+    public function fetchRow($statement, array $params = array()) 
+    {
+        return $this->execute($statement, $params)->fetch(Doctrine::FETCH_ASSOC);
+    }
+
+    /**
+     * fetchArray
+     *
+     * @param string $statement         sql query to be executed
+     * @param array $params             prepared statement params
+     * @return array
+     */
+    public function fetchArray($statement, array $params = array()) 
+    {
+        return $this->execute($statement, $params)->fetch(Doctrine::FETCH_NUM);
+    }
+
+    /**
+     * fetchColumn
+     *
+     * @param string $statement         sql query to be executed
+     * @param array $params             prepared statement params
+     * @param int $colnum               0-indexed column number to retrieve
+     * @return array
+     */
+    public function fetchColumn($statement, array $params = array(), $colnum = 0) 
+    {
+        return $this->execute($statement, $params)->fetchAll(Doctrine::FETCH_COLUMN, $colnum);
+    }
+
+    /**
+     * fetchAssoc
+     *
+     * @param string $statement         sql query to be executed
+     * @param array $params             prepared statement params
+     * @return array
+     */
+    public function fetchAssoc($statement, array $params = array()) 
+    {
+        return $this->execute($statement, $params)->fetchAll(Doctrine::FETCH_ASSOC);
+    }
+
+    /**
+     * fetchBoth
+     *
+     * @param string $statement         sql query to be executed
+     * @param array $params             prepared statement params
+     * @return array
+     */
+    public function fetchBoth($statement, array $params = array()) 
+    {
+        return $this->execute($statement, $params)->fetchAll(Doctrine::FETCH_BOTH);
+    }
+
+    /**
+     * query
+     * queries the database using Doctrine Query Language
+     * returns a collection of Doctrine_Record objects
+     *
+     * <code>
+     * $users = $conn->query('SELECT u.* FROM User u');
+     *
+     * $users = $conn->query('SELECT u.* FROM User u WHERE u.name LIKE ?', array('someone'));
+     * </code>
+     *
+     * @param string $query             DQL query
+     * @param array $params             query parameters
+     * @param int $hydrationMode        Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD
+     * @see Doctrine_Query
+     * @return Doctrine_Collection      Collection of Doctrine_Record objects
+     */
+    public function query($query, array $params = array(), $hydrationMode = null)
+    {
+        $parser = new Doctrine_Query($this);
+        $res = $parser->query($query, $params, $hydrationMode);
+        $parser->free();
+
+        return $res;
+    }
+
+    /**
+     * prepare
+     *
+     * @param string $statement
+     */
+    public function prepare($statement)
+    {
+        $this->connect();
+
+        try {
+            $event = new Doctrine_Event($this, Doctrine_Event::CONN_PREPARE, $statement);
+    
+            $this->getAttribute(Doctrine::ATTR_LISTENER)->prePrepare($event);
+
+            $stmt = false;
+    
+            if ( ! $event->skipOperation) {
+                $stmt = $this->dbh->prepare($statement);
+            }
+    
+            $this->getAttribute(Doctrine::ATTR_LISTENER)->postPrepare($event);
+            
+            return new Doctrine_Connection_Statement($this, $stmt);
+        } catch(Doctrine_Adapter_Exception $e) {
+        } catch(PDOException $e) { }
+
+        $this->rethrowException($e, $this);
+    }
+
+    /**
+     * query
+     * queries the database using Doctrine Query Language and returns
+     * the first record found
+     *
+     * <code>
+     * $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.id = ?', array(1));
+     *
+     * $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.name LIKE ? AND u.password = ?',
+     *         array('someone', 'password')
+     *         );
+     * </code>
+     *
+     * @param string $query             DQL query
+     * @param array $params             query parameters
+     * @see Doctrine_Query
+     * @return Doctrine_Record|false    Doctrine_Record object on success,
+     *                                  boolean false on failure
+     */
+    public function queryOne($query, array $params = array()) 
+    {
+        $parser = new Doctrine_Query($this);
+
+        $coll = $parser->query($query, $params);
+        if ( ! $coll->contains(0)) {
+            return false;
+        }
+        return $coll[0];
+    }
+
+    /**
+     * queries the database with limit and offset
+     * added to the query and returns a Doctrine_Connection_Statement object
+     *
+     * @param string $query
+     * @param integer $limit
+     * @param integer $offset
+     * @return Doctrine_Connection_Statement
+     */
+    public function select($query, $limit = 0, $offset = 0)
+    {
+        if ($limit > 0 || $offset > 0) {
+            $query = $this->modifyLimitQuery($query, $limit, $offset);
+        }
+        return $this->execute($query);
+    }
+
+    /**
+     * standaloneQuery
+     *
+     * @param string $query     sql query
+     * @param array $params     query parameters
+     *
+     * @return PDOStatement|Doctrine_Adapter_Statement
+     */
+    public function standaloneQuery($query, $params = array())
+    {
+        return $this->execute($query, $params);
+    }
+
+    /**
+     * execute
+     * @param string $query     sql query
+     * @param array $params     query parameters
+     *
+     * @return PDOStatement|Doctrine_Adapter_Statement
+     */
+    public function execute($query, array $params = array())
+    {
+        $this->connect();
+
+        try {
+            if ( ! empty($params)) {
+                $stmt = $this->prepare($query);
+                $stmt->execute($params);
+
+                return $stmt;
+            } else {
+                $event = new Doctrine_Event($this, Doctrine_Event::CONN_QUERY, $query, $params);
+
+                $this->getAttribute(Doctrine::ATTR_LISTENER)->preQuery($event);
+
+                if ( ! $event->skipOperation) {
+                    $stmt = $this->dbh->query($query);
+                    $this->_count++;
+                }
+                $this->getAttribute(Doctrine::ATTR_LISTENER)->postQuery($event);
+
+                return $stmt;
+            }
+        } 
+        catch (Doctrine_Adapter_Exception $e) { }
+        catch (PDOException $e) { }
+
+        $this->rethrowException($e, $this);
+    }
+
+    /**
+     * exec
+     * @param string $query     sql query
+     * @param array $params     query parameters
+     *
+     * @return PDOStatement|Doctrine_Adapter_Statement
+     */
+    public function exec($query, array $params = array())
+    {
+        $this->connect();
+
+        try {
+            if ( ! empty($params)) {
+                $stmt = $this->prepare($query);
+                $stmt->execute($params);
+
+                return $stmt->rowCount();
+            } else {
+                $event = new Doctrine_Event($this, Doctrine_Event::CONN_EXEC, $query, $params);
+
+                $this->getAttribute(Doctrine::ATTR_LISTENER)->preExec($event);
+                if ( ! $event->skipOperation) {
+                    $count = $this->dbh->exec($query);
+
+                    $this->_count++;
+                }
+                $this->getAttribute(Doctrine::ATTR_LISTENER)->postExec($event);
+
+                return $count;
+            }
+        } catch (Doctrine_Adapter_Exception $e) {
+        } catch (PDOException $e) { }
+
+        $this->rethrowException($e, $this);
+    }
+
+    /**
+     * rethrowException
+     *
+     * @throws Doctrine_Connection_Exception
+     */
+    public function rethrowException(Exception $e, $invoker)
+    {
+        $event = new Doctrine_Event($this, Doctrine_Event::CONN_ERROR);
+
+        $this->getListener()->preError($event);
+        
+        $name = 'Doctrine_Connection_' . $this->driverName . '_Exception';
+
+        $exc  = new $name($e->getMessage(), (int) $e->getCode());
+        if ( ! isset($e->errorInfo) || ! is_array($e->errorInfo)) {
+            $e->errorInfo = array(null, null, null, null);
+        }
+        $exc->processErrorInfo($e->errorInfo);
+
+         if ($this->getAttribute(Doctrine::ATTR_THROW_EXCEPTIONS)) {
+            throw $exc;
+        }
+        
+        $this->getListener()->postError($event);
+    }
+
+    /**
+     * hasTable
+     * whether or not this connection has table $name initialized
+     *
+     * @param mixed $name
+     * @return boolean
+     */
+    public function hasTable($name)
+    {
+        return isset($this->tables[$name]);
+    }
+
+    /**
+     * returns a table object for given component name
+     *
+     * @param string $name              component name
+     * @return object Doctrine_Table
+     */
+    public function getTable($name)
+    {
+        if (isset($this->tables[$name])) {
+            return $this->tables[$name];
+        }
+        $class = $name . 'Table';
+
+        if (class_exists($class, $this->getAttribute(Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES)) &&
+                in_array('Doctrine_Table', class_parents($class))) {
+            $table = new $class($name, $this, true);
+        } else {
+            $table = new Doctrine_Table($name, $this, true);
+        }
+
+        $this->tables[$name] = $table;
+
+        return $table;
+    }
+
+    /**
+     * returns an array of all initialized tables
+     *
+     * @return array
+     */
+    public function getTables()
+    {
+        return $this->tables;
+    }
+
+    /**
+     * returns an iterator that iterators through all
+     * initialized table objects
+     *
+     * <code>
+     * foreach ($conn as $index => $table) {
+     *      print $table;  // get a string representation of each table object
+     * }
+     * </code>
+     *
+     * @return ArrayIterator        SPL ArrayIterator object
+     */
+    public function getIterator()
+    {
+        return new ArrayIterator($this->tables);
+    }
+
+    /**
+     * returns the count of initialized table objects
+     *
+     * @return integer
+     */
+    public function count()
+    {
+        return $this->_count;
+    }
+
+    /**
+     * addTable
+     * adds a Doctrine_Table object into connection registry
+     *
+     * @param $table                a Doctrine_Table object to be added into registry
+     * @return boolean
+     */
+    public function addTable(Doctrine_Table $table)
+    {
+        $name = $table->getComponentName();
+
+        if (isset($this->tables[$name])) {
+            return false;
+        }
+        $this->tables[$name] = $table;
+        return true;
+    }
+
+    /**
+     * create
+     * creates a record
+     *
+     * create                       creates a record
+     * @param string $name          component name
+     * @return Doctrine_Record      Doctrine_Record object
+     */
+    public function create($name)
+    {
+        return $this->getTable($name)->create();
+    }
+    
+    /**
+     * Creates a new Doctrine_Query object that operates on this connection.
+     * 
+     * @return Doctrine_Query 
+     */
+    public function createQuery()
+    {
+        return new Doctrine_Query($this);
+    }
+
+    /**
+     * flush
+     * saves all the records from all tables
+     * this operation is isolated using a transaction
+     *
+     * @throws PDOException         if something went wrong at database level
+     * @return void
+     */
+    public function flush()
+    {
+        try {
+            $this->beginInternalTransaction();
+            $this->unitOfWork->saveAll();
+            $this->commit();
+        } catch (Exception $e) {
+            $this->rollback();
+            throw $e;
+        }
+    }
+
+    /**
+     * clear
+     * clears all repositories
+     *
+     * @return void
+     */
+    public function clear()
+    {
+        foreach ($this->tables as $k => $table) {
+            $table->getRepository()->evictAll();
+            $table->clear();
+        }
+    }
+
+    /**
+     * evictTables
+     * evicts all tables
+     *
+     * @return void
+     */
+    public function evictTables()
+    {
+        $this->tables = array();
+        $this->exported = array();
+    }
+
+    /**
+     * close
+     * closes the connection
+     *
+     * @return void
+     */
+    public function close()
+    {
+        $event = new Doctrine_Event($this, Doctrine_Event::CONN_CLOSE);
+
+        $this->getAttribute(Doctrine::ATTR_LISTENER)->preClose($event);
+
+        $this->clear();
+        
+        unset($this->dbh);
+        $this->isConnected = false;
+
+        $this->getAttribute(Doctrine::ATTR_LISTENER)->postClose($event);
+    }
+
+    /**
+     * get the current transaction nesting level
+     *
+     * @return integer
+     */
+    public function getTransactionLevel()
+    {
+        return $this->transaction->getTransactionLevel();
+    }
+
+    /**
+     * errorCode
+     * Fetch the SQLSTATE associated with the last operation on the database handle
+     *
+     * @return integer
+     */
+    public function errorCode()
+    {
+        $this->connect();
+
+        return $this->dbh->errorCode();
+    }
+
+    /**
+     * errorInfo
+     * Fetch extended error information associated with the last operation on the database handle
+     *
+     * @return array
+     */
+    public function errorInfo()
+    {
+        $this->connect();
+
+        return $this->dbh->errorInfo();
+    }
+    
+    /**
+     * getCacheDriver
+     *
+     * @return Doctrine_Cache_Interface
+     * @deprecated Use getResultCacheDriver()
+     */
+    public function getCacheDriver()
+    {
+        return $this->getResultCacheDriver();
+    }
+    
+    /**
+     * getResultCacheDriver
+     *
+     * @return Doctrine_Cache_Interface
+     */
+    public function getResultCacheDriver()
+    {
+        if ( ! $this->getAttribute(Doctrine::ATTR_RESULT_CACHE)) {
+            throw new Doctrine_Exception('Result Cache driver not initialized.');
+        }
+
+        return $this->getAttribute(Doctrine::ATTR_RESULT_CACHE);
+    }
+    
+    /**
+     * getQueryCacheDriver
+     *
+     * @return Doctrine_Cache_Interface
+     */
+    public function getQueryCacheDriver()
+    {
+        if ( ! $this->getAttribute(Doctrine::ATTR_QUERY_CACHE)) {
+            throw new Doctrine_Exception('Query Cache driver not initialized.');
+        }
+
+        return $this->getAttribute(Doctrine::ATTR_QUERY_CACHE);
+    }
+
+    /**
+     * lastInsertId
+     *
+     * Returns the ID of the last inserted row, or the last value from a sequence object,
+     * depending on the underlying driver.
+     *
+     * Note: This method may not return a meaningful or consistent result across different drivers, 
+     * because the underlying database may not even support the notion of auto-increment fields or sequences.
+     *
+     * @param string $table     name of the table into which a new row was inserted
+     * @param string $field     name of the field into which a new row was inserted
+     */
+    public function lastInsertId($table = null, $field = null)
+    {
+        return $this->sequence->lastInsertId($table, $field);
+    }
+
+    /**
+     * beginTransaction
+     * Start a transaction or set a savepoint.
+     *
+     * if trying to set a savepoint and there is no active transaction
+     * a new transaction is being started
+     *
+     * Listeners: onPreTransactionBegin, onTransactionBegin
+     *
+     * @param string $savepoint                 name of a savepoint to set
+     * @throws Doctrine_Transaction_Exception   if the transaction fails at database level
+     * @return integer                          current transaction nesting level
+     */
+    public function beginTransaction($savepoint = null)
+    {
+        return $this->transaction->beginTransaction($savepoint);
+    }
+    
+    public function beginInternalTransaction($savepoint = null)
+    {
+        return $this->transaction->beginInternalTransaction($savepoint);
+    }
+
+    /**
+     * commit
+     * Commit the database changes done during a transaction that is in
+     * progress or release a savepoint. This function may only be called when
+     * auto-committing is disabled, otherwise it will fail.
+     *
+     * Listeners: onPreTransactionCommit, onTransactionCommit
+     *
+     * @param string $savepoint                 name of a savepoint to release
+     * @throws Doctrine_Transaction_Exception   if the transaction fails at PDO level
+     * @throws Doctrine_Validator_Exception     if the transaction fails due to record validations
+     * @return boolean                          false if commit couldn't be performed, true otherwise
+     */
+    public function commit($savepoint = null)
+    {
+        return $this->transaction->commit($savepoint);
+    }
+
+    /**
+     * rollback
+     * Cancel any database changes done during a transaction or since a specific
+     * savepoint that is in progress. This function may only be called when
+     * auto-committing is disabled, otherwise it will fail. Therefore, a new
+     * transaction is implicitly started after canceling the pending changes.
+     *
+     * this method can be listened with onPreTransactionRollback and onTransactionRollback
+     * eventlistener methods
+     *
+     * @param string $savepoint                 name of a savepoint to rollback to   
+     * @throws Doctrine_Transaction_Exception   if the rollback operation fails at database level
+     * @return boolean                          false if rollback couldn't be performed, true otherwise
+     */
+    public function rollback($savepoint = null)
+    {
+        return $this->transaction->rollback($savepoint);
+    }
+
+    /**
+     * createDatabase
+     *
+     * Issue create database command for this instance of Doctrine_Connection
+     *
+     * @return mixed Returns Doctrine_Exception or success string
+     */
+    public function createDatabase()
+    {
+        if ( ! $dsn = $this->getOption('dsn')) {
+            throw new Doctrine_Connection_Exception('You must create your Doctrine_Connection by using a valid Doctrine style dsn in order to use the create/drop database functionality');
+        }
+
+        // Parse pdo dsn so we are aware of the connection information parts
+        $info = $this->getManager()->parsePdoDsn($dsn);
+
+        // Get the temporary connection to issue the drop database command
+        $tmpConnection = $this->getTmpConnection($info);
+
+        try {
+            // Issue create database command
+            $tmpConnection->export->createDatabase($info['dbname']);
+        } catch (Exception $e) {}
+
+        // Close the temporary connection used to issue the drop database command
+        $this->getManager()->closeConnection($tmpConnection);
+
+        if (isset($e)) {
+            return $e;
+        } else {
+            return 'Successfully created database for connection "' . $this->getName() . '" named "' . $info['dbname'] . '"';
+        }
+    }
+
+    /**
+     * dropDatabase
+     *
+     * Issue drop database command for this instance of Doctrine_Connection
+     *
+     * @return mixed Returns Doctrine_Exception or success string
+     */
+    public function dropDatabase()
+    {
+        if ( ! $dsn = $this->getOption('dsn')) {
+            throw new Doctrine_Connection_Exception('You must create your Doctrine_Connection by using a valid Doctrine style dsn in order to use the create/drop database functionality');
+        }
+
+        // Parse pdo dsn so we are aware of the connection information parts
+        $info = $this->getManager()->parsePdoDsn($dsn);
+
+        // Get the temporary connection to issue the drop database command
+        $tmpConnection = $this->getTmpConnection($info);
+
+        try {
+            // Issue drop database command
+            $tmpConnection->export->dropDatabase($info['dbname']);
+        } catch (Exception $e) {}
+
+        // Close the temporary connection used to issue the drop database command
+        $this->getManager()->closeConnection($tmpConnection);
+
+        if (isset($e)) {
+            return $e;
+        } else {
+            return 'Successfully dropped database for connection "' . $this->getName() . '" named "' . $info['dbname'] . '"';
+        }
+    }
+
+    /**
+     * getTmpConnection
+     *
+     * Create a temporary connection to the database with the user credentials.
+     * This is so the user can make a connection to a db server. Some dbms allow
+     * connections with no database, but some do not. In that case we have a table
+     * which is always guaranteed to exist. Mysql: 'mysql', PostgreSQL: 'postgres', etc.
+     * This value is set in the Doctrine_Export_{DRIVER} classes if required
+     *
+     * @param string $info 
+     * @return void
+     */
+    public function getTmpConnection($info)
+    {
+        $pdoDsn = $info['scheme'] . ':';
+        
+        if ($info['unix_socket']) {
+            $pdoDsn .= 'unix_socket=' . $info['unix_socket'] . ';';
+        }
+
+ 	    $pdoDsn .= 'host=' . $info['host'];
+
+ 	    if ($info['port']) {
+ 	        $pdoDsn .= ';port=' . $info['port'];
+ 	    }
+
+        if (isset($this->export->tmpConnectionDatabase) && $this->export->tmpConnectionDatabase) {
+            $pdoDsn .= ';dbname=' . $this->export->tmpConnectionDatabase;
+        }
+
+        $username = $this->getOption('username');
+        $password = $this->getOption('password');
+
+        return $this->getManager()->openConnection(new PDO($pdoDsn, $username, $password), 'doctrine_tmp_connection', false);
+    }
+
+    /**
+     * modifyLimitQuery
+     *
+     * Some dbms require specific functionality for this. Check the other connection adapters for examples
+     *
+     * @return string
+     */
+    public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false)
+    {
+        return $query;
+    }
+    
+    /**
+     * 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);
+    }
+
+    /**
+     * returns a string representation of this object
+     * @return string
+     */
+    public function __toString()
+    {
+        return Doctrine_Lib::getConnectionAsString($this);
+    }
+
+    /**
+     * Serialize. Remove database connection(pdo) since it cannot be serialized
+     *
+     * @return string $serialized
+     */
+    public function serialize()
+    {
+        $vars = get_object_vars($this);
+        $vars['dbh'] = null;
+        $vars['isConnected'] = false;
+        return serialize($vars);
+    }
+
+    /**
+     * Unserialize. Recreate connection from serialized content
+     *
+     * @param string $serialized 
+     * @return void
+     */
+    public function unserialize($serialized)
+    {
+        $array = unserialize($serialized);
+
+        foreach ($array as $name => $values) {
+            $this->$name = $values;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Common.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,57 @@
+<?php
+/*
+ *  $Id: Common.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * standard connection, the parent of pgsql, mysql and sqlite
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @link        www.phpdoctrine.org
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Connection_Common extends Doctrine_Connection
+{
+    /**
+     * Adds an driver-specific LIMIT clause to the query
+     *
+     * @param string $query
+     * @param mixed $limit
+     * @param mixed $offset
+     */
+    public function modifyLimitQuery($query, $limit = false,$offset = false,$isManip=false)
+    {
+        $limit = (int) $limit;
+        $offset = (int) $offset;
+        
+        if ($limit && $offset) {
+            $query .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
+        } elseif ($limit && ! $offset) {
+            $query .= ' LIMIT ' . $limit;
+        } elseif ( ! $limit && $offset) {
+            $query .= ' LIMIT 999999999999 OFFSET ' . $offset;
+        }
+
+        return $query;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Db2.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,64 @@
+<?php
+/*
+ *  $Id: Db2.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Db2
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Connection_Db2 extends Doctrine_Connection
+{
+    /**
+     * 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)
+    {
+        if ($limit <= 0)
+            return $query;
+
+        if ($offset == 0) {
+            return $query . ' FETCH FIRST '. $limit .' ROWS ONLY';
+        } else {
+            $sqlPieces = explode('from', $query);
+            $select = $sqlPieces[0];
+            $table = $sqlPieces[1];
+
+            $col = explode('select', $select);
+
+            $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);
+            return $sql;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,130 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Connection_Exception extends Doctrine_Exception
+{
+    /**
+     * @var array $errorMessages        an array containing messages for portable error codes
+     */
+    static protected $errorMessages = array(
+                Doctrine::ERR                    => 'unknown error',
+                Doctrine::ERR_ALREADY_EXISTS     => 'already exists',
+                Doctrine::ERR_CANNOT_CREATE      => 'can not create',
+                Doctrine::ERR_CANNOT_ALTER       => 'can not alter',
+                Doctrine::ERR_CANNOT_REPLACE     => 'can not replace',
+                Doctrine::ERR_CANNOT_DELETE      => 'can not delete',
+                Doctrine::ERR_CANNOT_DROP        => 'can not drop',
+                Doctrine::ERR_CONSTRAINT         => 'constraint violation',
+                Doctrine::ERR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint',
+                Doctrine::ERR_DIVZERO            => 'division by zero',
+                Doctrine::ERR_INVALID            => 'invalid',
+                Doctrine::ERR_INVALID_DATE       => 'invalid date or time',
+                Doctrine::ERR_INVALID_NUMBER     => 'invalid number',
+                Doctrine::ERR_MISMATCH           => 'mismatch',
+                Doctrine::ERR_NODBSELECTED       => 'no database selected',
+                Doctrine::ERR_NOSUCHFIELD        => 'no such field',
+                Doctrine::ERR_NOSUCHTABLE        => 'no such table',
+                Doctrine::ERR_NOT_CAPABLE        => 'Doctrine backend not capable',
+                Doctrine::ERR_NOT_FOUND          => 'not found',
+                Doctrine::ERR_NOT_LOCKED         => 'not locked',
+                Doctrine::ERR_SYNTAX             => 'syntax error',
+                Doctrine::ERR_UNSUPPORTED        => 'not supported',
+                Doctrine::ERR_VALUE_COUNT_ON_ROW => 'value count on row',
+                Doctrine::ERR_INVALID_DSN        => 'invalid DSN',
+                Doctrine::ERR_CONNECT_FAILED     => 'connect failed',
+                Doctrine::ERR_NEED_MORE_DATA     => 'insufficient data supplied',
+                Doctrine::ERR_EXTENSION_NOT_FOUND=> 'extension not found',
+                Doctrine::ERR_NOSUCHDB           => 'no such database',
+                Doctrine::ERR_ACCESS_VIOLATION   => 'insufficient permissions',
+                Doctrine::ERR_LOADMODULE         => 'error while including on demand module',
+                Doctrine::ERR_TRUNCATED          => 'truncated',
+                Doctrine::ERR_DEADLOCK           => 'deadlock detected',
+                );
+
+    /**
+     * @see Doctrine::ERR_* constants
+     * @since 1.0
+     * @var integer $portableCode           portable error code
+     */
+    protected $portableCode;
+
+    /**
+     * getPortableCode
+     * returns portable error code
+     *
+     * @return integer      portable error code
+     */
+    public function getPortableCode()
+    {
+        return $this->portableCode;
+    }
+
+    /**
+     * getPortableMessage
+     * returns portable error message
+     *
+     * @return string       portable error message
+     */
+    public function getPortableMessage()
+    {
+        return self::errorMessage($this->portableCode);
+    }
+
+    /**
+     * Return a textual error message for a Doctrine error code
+     *
+     * @param   int|array   integer error code,
+     *                           null to get the current error code-message map,
+     *                           or an array with a new error code-message map
+     *
+     * @return  string  error message, or false if the error code was
+     *                  not recognized
+     */
+    public function errorMessage($value = null)
+    {
+        return isset(self::$errorMessages[$value]) ?
+           self::$errorMessages[$value] : self::$errorMessages[Doctrine::ERR];
+    }
+
+    /**
+     * This method checks if native error code/message can be
+     * converted into a portable code and then adds this
+     * portable error code to $portableCode field
+     *
+     * @param array $errorInfo      error info array
+     * @since 1.0
+     * @return boolean              whether or not the error info processing was successfull
+     *                              (the process is successfull if portable error code was found)
+     */
+    public function processErrorInfo(array $errorInfo)
+    { }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Firebird.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,114 @@
+<?php
+/*
+ *  $Id: Firebird.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Firebird
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @author      Lorenzo Alberton <l.alberton@quipo.it> (PEAR MDB2 Interbase driver)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Connection_Firebird extends Doctrine_Connection
+{
+    /**
+     * @var string $driverName                  the name of this connection driver
+     */
+    protected $driverName = 'Firebird';
+
+    /**
+     * the constructor
+     *
+     * @param Doctrine_Manager $manager
+     * @param PDO $pdo                          database handle
+     */
+    public function __construct(Doctrine_Manager $manager, $adapter)
+    {
+
+        $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'         => 'emulated',
+                          'LOBs'                  => true,
+                          'replace'               => 'emulated',
+                          'sub_selects'           => true,
+                          'auto_increment'        => true,
+                          'primary_key'           => true,
+                          'result_introspection'  => true,
+                          'prepared_statements'   => true,
+                          'identifier_quoting'    => false,
+                          'pattern_escaping'      => true
+                          );
+        // initialize all driver options
+        /**
+        $this->options['DBA_username'] = false;
+        $this->options['DBA_password'] = false;
+        $this->options['database_path'] = '';
+        $this->options['database_extension'] = '.gdb';
+        $this->options['server_version'] = '';
+        */
+        parent::__construct($manager, $adapter);
+    }
+
+    /**
+     * Set the charset on the current connection
+     *
+     * @param string    charset
+     *
+     * @return void
+     */
+    public function setCharset($charset)
+    {
+        $query = 'SET NAMES '.$this->dbh->quote($charset);
+        $this->exec($query);
+    }
+
+    /**
+     * 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 modified  query
+     */
+    public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false)
+    {
+        if ( ! $offset) {
+            $offset = 0;
+        }
+        if ($limit > 0) {
+            $query = preg_replace('/^([\s(])*SELECT(?!\s*FIRST\s*\d+)/i',
+                "SELECT FIRST $limit SKIP $offset", $query);
+        }
+        return $query;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Firebird/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,136 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Firebird_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lorenzo Alberton <l.alberton@quipo.it> (PEAR MDB2 Interbase driver)
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ */
+class Doctrine_Connection_Firebird_Exception extends Doctrine_Connection_Exception
+{
+    /**
+     * @var array $errorCodeMap         an array that is used for determining portable
+     *                                  error code from a native database error code
+     */
+    protected static $errorCodeMap = array(
+                                    -104 => Doctrine::ERR_SYNTAX,
+                                    -150 => Doctrine::ERR_ACCESS_VIOLATION,
+                                    -151 => Doctrine::ERR_ACCESS_VIOLATION,
+                                    -155 => Doctrine::ERR_NOSUCHTABLE,
+                                    -157 => Doctrine::ERR_NOSUCHFIELD,
+                                    -158 => Doctrine::ERR_VALUE_COUNT_ON_ROW,
+                                    -170 => Doctrine::ERR_MISMATCH,
+                                    -171 => Doctrine::ERR_MISMATCH,
+                                    -172 => Doctrine::ERR_INVALID,
+                                    // -204 =>  // Covers too many errors, need to use regex on msg
+                                    -205 => Doctrine::ERR_NOSUCHFIELD,
+                                    -206 => Doctrine::ERR_NOSUCHFIELD,
+                                    -208 => Doctrine::ERR_INVALID,
+                                    -219 => Doctrine::ERR_NOSUCHTABLE,
+                                    -297 => Doctrine::ERR_CONSTRAINT,
+                                    -303 => Doctrine::ERR_INVALID,
+                                    -413 => Doctrine::ERR_INVALID_NUMBER,
+                                    -530 => Doctrine::ERR_CONSTRAINT,
+                                    -551 => Doctrine::ERR_ACCESS_VIOLATION,
+                                    -552 => Doctrine::ERR_ACCESS_VIOLATION,
+                                    // -607 =>  // Covers too many errors, need to use regex on msg
+                                    -625 => Doctrine::ERR_CONSTRAINT_NOT_NULL,
+                                    -803 => Doctrine::ERR_CONSTRAINT,
+                                    -804 => Doctrine::ERR_VALUE_COUNT_ON_ROW,
+                                    -904 => Doctrine::ERR_CONNECT_FAILED,
+                                    -922 => Doctrine::ERR_NOSUCHDB,
+                                    -923 => Doctrine::ERR_CONNECT_FAILED,
+                                    -924 => Doctrine::ERR_CONNECT_FAILED
+                                    );
+
+    /**
+     * @var array $errorRegexps         an array that is used for determining portable
+     *                                  error code from a native database error message
+     */
+    protected static $errorRegexps = array(
+                                    '/generator .* is not defined/'
+                                        => Doctrine::ERR_SYNTAX,  // for compat. w ibase_errcode()
+                                    '/table.*(not exist|not found|unknown)/i'
+                                        => Doctrine::ERR_NOSUCHTABLE,
+                                    '/table .* already exists/i'
+                                        => Doctrine::ERR_ALREADY_EXISTS,
+                                    '/unsuccessful metadata update .* failed attempt to store duplicate value/i'
+                                        => Doctrine::ERR_ALREADY_EXISTS,
+                                    '/unsuccessful metadata update .* not found/i'
+                                        => Doctrine::ERR_NOT_FOUND,
+                                    '/validation error for column .* value "\*\*\* null/i'
+                                        => Doctrine::ERR_CONSTRAINT_NOT_NULL,
+                                    '/violation of [\w ]+ constraint/i'
+                                        => Doctrine::ERR_CONSTRAINT,
+                                    '/conversion error from string/i'
+                                        => Doctrine::ERR_INVALID_NUMBER,
+                                    '/no permission for/i'
+                                        => Doctrine::ERR_ACCESS_VIOLATION,
+                                    '/arithmetic exception, numeric overflow, or string truncation/i'
+                                        => Doctrine::ERR_INVALID,
+                                    '/table unknown/i'
+                                        => Doctrine::ERR_NOSUCHTABLE,
+                                    );
+
+    /**
+     * This method checks if native error code/message can be
+     * converted into a portable code and then adds this
+     * portable error code to errorInfo array and returns the modified array
+     *
+     * the portable error code is added at the end of array
+     *
+     * @param array $errorInfo      error info array
+     * @since 1.0
+     * @return array
+     */
+    public function processErrorInfo(array $errorInfo)
+    {
+            /**
+            // todo: are the following lines needed?
+            // memo for the interbase php module hackers: we need something similar
+            // to mysql_errno() to retrieve error codes instead of this ugly hack
+            if (preg_match('/^([^0-9\-]+)([0-9\-]+)\s+(.*)$/', $native_msg, $m)) {
+                $native_code = (int)$m[2];
+            } else {
+                $native_code = null;
+            }
+            */
+
+        foreach (self::$errorRegexps as $regexp => $code) {
+            if (preg_match($regexp, $errorInfo[2])) {
+                $errorInfo[3] = $code;
+                break;
+            }
+        }
+        if (isset(self::$errorCodeMap[$errorInfo[1]])) {
+            $errorInfo[3] = self::$errorCodeMap[$errorInfo[1]];
+        }
+        return $errorInfo;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Informix.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,62 @@
+<?php
+/*
+ *  $Id: Informix.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Mysql
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Connection_Informix extends Doctrine_Connection
+{
+    /**
+     * @var string $driverName                  the name of this connection driver
+     */
+    protected $driverName = 'Informix';
+
+    /**
+     * the constructor
+     *
+     * @param Doctrine_Manager $manager
+     * @param PDO $pdo                          database handle
+     */
+    public function __construct(Doctrine_Manager $manager, $adapter)
+    {
+        parent::__construct($manager, $adapter);
+    }
+
+    /**
+     * quoteIdentifier
+     *
+     * @param string $identifier 
+     * @param string $checkOption 
+     * @return void
+     */
+    public function quoteIdentifier($identifier, $checkOption = false)
+    {
+        return $identifier;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Informix/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Informix_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Connection_Informix_Exception extends Doctrine_Connection_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mock.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,51 @@
+<?php
+/*
+ *  $Id: Mock.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Mysql
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Connection_Mock extends Doctrine_Connection_Common
+{
+    /**
+     * @var string $driverName                  the name of this connection driver
+     */
+    protected $driverName = 'Mock';
+
+    /**
+     * the constructor
+     *
+     * @param Doctrine_Manager $manager
+     * @param PDO|Doctrine_Adapter $adapter     database handler
+     */
+    public function __construct(Doctrine_Manager $manager, $adapter)
+    {
+
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Module.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,83 @@
+<?php
+/*
+ *  $Id: Module.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Module
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Connection_Module
+{
+    /**
+     * @var Doctrine_Connection $conn       Doctrine_Connection object, every connection
+     *                                      module holds an instance of Doctrine_Connection
+     */
+    protected $conn;
+
+    /**
+     * @var string $moduleName              the name of this module
+     */
+    protected $moduleName;
+
+    /**
+     * @param Doctrine_Connection $conn     Doctrine_Connection object, every connection
+     *                                      module holds an instance of Doctrine_Connection
+     */
+    public function __construct($conn = null)
+    {
+        if ( ! ($conn instanceof Doctrine_Connection)) {
+            $conn = Doctrine_Manager::getInstance()->getCurrentConnection();
+        }
+        $this->conn = $conn;
+
+        $e = explode('_', get_class($this));
+
+        $this->moduleName = $e[1];
+    }
+
+    /**
+     * getConnection
+     * returns the connection object this module uses
+     *
+     * @return Doctrine_Connection
+     */
+    public function getConnection()
+    {
+        return $this->conn;
+    }
+
+    /**
+     * getModuleName
+     * returns the name of this module
+     *
+     * @return string       the name of this module
+     */
+    public function getModuleName()
+    {
+        return $this->moduleName;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mssql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,278 @@
+<?php
+/*
+ *  $Id: Mssql.php 5804 2009-06-02 19:52:42Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Mssql
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5804 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Connection_Mssql extends Doctrine_Connection
+{
+    /**
+     * @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',
+                          );
+
+        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::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 '[' . str_replace(']', ']]', $identifier) . ']';
+    }
+
+    /**
+     * Adds an adapter-specific LIMIT clause to the SELECT statement.
+     * [ original code borrowed from Zend Framework ]
+     *
+     * License available at: http://framework.zend.com/license
+     *
+     * Copyright (c) 2005-2008, Zend Technologies USA, Inc.
+     * All rights reserved.
+     * 
+     * Redistribution and use in source and binary forms, with or without modification,
+     * are permitted provided that the following conditions are met:
+     * 
+     *     * Redistributions of source code must retain the above copyright notice,
+     *       this list of conditions and the following disclaimer.
+     * 
+     *     * Redistributions in binary form must reproduce the above copyright notice,
+     *       this list of conditions and the following disclaimer in the documentation
+     *       and/or other materials provided with the distribution.
+     * 
+     *     * Neither the name of Zend Technologies USA, Inc. nor the names of its
+     *       contributors may be used to endorse or promote products derived from this
+     *       software without specific prior written permission.
+     * 
+     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+     * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+     * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+     * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+     *
+     * @param string $query
+     * @param mixed $limit
+     * @param mixed $offset
+     * @link http://lists.bestpractical.com/pipermail/rt-devel/2005-June/007339.html
+     * @return string
+     */
+    public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false)
+    {
+        if ($limit > 0) {
+            $count = intval($limit);
+            $offset = intval($offset);
+
+            if ($offset < 0) {
+                throw new Doctrine_Connection_Exception("LIMIT argument offset=$offset is not valid");
+            }
+    
+            $orderby = stristr($query, 'ORDER BY');
+
+            if ($orderby !== false) {
+                // Ticket #1835: Fix for ORDER BY alias
+				// Ticket #2050: Fix for multiple ORDER BY clause 
+                $order = str_ireplace('ORDER BY', '', $orderby);
+                $orders = explode(',', $order); 
+ 
+                for ($i = 0; $i < count($orders); $i++) { 
+                    $sorts[$i] = (stripos($orders[$i], ' desc') !== false) ? 'desc' : 'asc'; 
+                    $orders[$i] = trim(preg_replace('/\s+(ASC|DESC)$/i', '', $orders[$i])); 
+	 
+                    // find alias in query string 
+                    $helper_string = stristr($query, $orders[$i]); 
+
+                    $from_clause_pos = strpos($helper_string, ' FROM '); 
+                    $fields_string = substr($helper_string, 0, $from_clause_pos + 1); 
+	 
+                    $field_array = explode(',', $fields_string); 
+                    $field_array = array_shift($field_array); 
+                    $aux2 = spliti(' as ', $field_array); 
+
+                    $aliases[$i] = trim(end($aux2)); 
+                }
+            }
+    
+            // Ticket #1259: Fix for limit-subquery in MSSQL
+            $selectRegExp = 'SELECT\s+';
+            $selectReplace = 'SELECT ';
+
+            if (preg_match('/^SELECT(\s+)DISTINCT/i', $query)) {
+                $selectRegExp .= 'DISTINCT\s+';
+                $selectReplace .= 'DISTINCT ';
+            }
+
+            $query = preg_replace('/^'.$selectRegExp.'/i', $selectReplace . 'TOP ' . ($count + $offset) . ' ', $query);
+            $query = 'SELECT * FROM (SELECT TOP ' . $count . ' * FROM (' . $query . ') AS ' . $this->quoteIdentifier('inner_tbl');
+
+            if ($orderby !== false) {
+                $query .= ' ORDER BY '; 
+
+                for ($i = 0, $l = count($orders); $i < $l; $i++) { 
+                    if ($i > 0) { // not first order clause 
+                        $query .= ', '; 
+                    } 
+
+                    $query .= $this->quoteIdentifier('inner_tbl') . '.' . $aliases[$i] . ' '; 
+                    $query .= (stripos($sorts[$i], 'asc') !== false) ? 'DESC' : 'ASC';
+                }
+            }
+
+            $query .= ') AS ' . $this->quoteIdentifier('outer_tbl');
+
+            if ($orderby !== false) {
+                $query .= ' ORDER BY '; 
+
+                for ($i = 0, $l = count($orders); $i < $l; $i++) { 
+                    if ($i > 0) { // not first order clause 
+                        $query .= ', '; 
+                    } 
+
+                    $query .= $this->quoteIdentifier('outer_tbl') . '.' . $aliases[$i] . ' ' . $sorts[$i];
+                }
+            }
+        }
+
+        return $query;
+    }
+
+    /**
+     * return version information about the server
+     *
+     * @param bool   $native  determines if the raw version string should be returned
+     * @return mixed array/string with version information or MDB2 error object
+     */
+    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::ERR_NOSUCHTABLE) {
+                return false;
+            }
+
+            throw $e;
+        }
+        return true;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mssql/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,75 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Mssql_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ */
+class Doctrine_Connection_Mssql_Exception extends Doctrine_Connection_Exception
+{
+    /**
+     * @var array $errorCodeMap         an array that is used for determining portable
+     *                                  error code from a native database error code
+     */
+    protected static $errorCodeMap = array(
+                                      110   => Doctrine::ERR_VALUE_COUNT_ON_ROW,
+                                      155   => Doctrine::ERR_NOSUCHFIELD,
+                                      170   => Doctrine::ERR_SYNTAX,
+                                      207   => Doctrine::ERR_NOSUCHFIELD,
+                                      208   => Doctrine::ERR_NOSUCHTABLE,
+                                      245   => Doctrine::ERR_INVALID_NUMBER,
+                                      515   => Doctrine::ERR_CONSTRAINT_NOT_NULL,
+                                      547   => Doctrine::ERR_CONSTRAINT,
+                                      1913  => Doctrine::ERR_ALREADY_EXISTS,
+                                      2627  => Doctrine::ERR_CONSTRAINT,
+                                      2714  => Doctrine::ERR_ALREADY_EXISTS,
+                                      3701  => Doctrine::ERR_NOSUCHTABLE,
+                                      8134  => Doctrine::ERR_DIVZERO,
+                                      );
+
+    /**
+     * This method checks if native error code/message can be
+     * converted into a portable code and then adds this
+     * portable error code to $portableCode field
+     *
+     * @param array $errorInfo      error info array
+     * @since 1.0
+     * @return boolean              whether or not the error info processing was successfull
+     *                              (the process is successfull if portable error code was found)
+     */
+    public function processErrorInfo(array $errorInfo)
+    {
+        $code = $errorInfo[1];
+        if (isset(self::$errorCodeMap[$code])) {
+            $this->portableCode = self::$errorCodeMap[$code];
+            return true;
+        }
+        return false;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mysql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,213 @@
+<?php
+/*
+ *  $Id: Mysql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Mysql
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Connection_Mysql extends Doctrine_Connection_Common
+{
+    /**
+     * @var string $driverName                  the name of this connection driver
+     */
+    protected $driverName = 'Mysql';
+
+    /**
+     * the constructor
+     *
+     * @param Doctrine_Manager $manager
+     * @param PDO|Doctrine_Adapter $adapter     database handler
+     */
+    public function __construct(Doctrine_Manager $manager, $adapter)
+    {
+        $this->setAttribute(Doctrine::ATTR_DEFAULT_TABLE_TYPE, 'INNODB');
+        $this->supported = array(
+                          'sequences'            => 'emulated',
+                          'indexes'              => true,
+                          'affected_rows'        => true,
+                          'transactions'         => true,
+                          'savepoints'           => false,
+                          'summary_functions'    => true,
+                          'order_by_text'        => true,
+                          'current_id'           => 'emulated',
+                          'limit_queries'        => true,
+                          'LOBs'                 => true,
+                          'replace'              => true,
+                          'sub_selects'          => true,
+                          'auto_increment'       => true,
+                          'primary_key'          => true,
+                          'result_introspection' => true,
+                          'prepared_statements'  => 'emulated',
+                          'identifier_quoting'   => true,
+                          'pattern_escaping'     => true
+                          );
+
+        $this->properties['string_quoting'] = array('start' => "'",
+                                                    'end' => "'",
+                                                    'escape' => '\\',
+                                                    'escape_pattern' => '\\');
+
+        $this->properties['identifier_quoting'] = array('start' => '`',
+                                                        'end' => '`',
+                                                        'escape' => '`');
+
+        $this->properties['sql_comments'] = array(
+                                            array('start' => '-- ', 'end' => "\n", 'escape' => false),
+                                            array('start' => '#', 'end' => "\n", 'escape' => false),
+                                            array('start' => '/*', 'end' => '*/', 'escape' => false),
+                                            );
+
+        $this->properties['varchar_max_length'] = 255;
+
+        parent::__construct($manager, $adapter);
+    }
+
+    /**
+     * Overrides connect Method, to add specific attributes
+     * PDO emulate prepares is required to avoid bugs on mysql < 5.1
+     * when trying to prepare DROP DATABASE or CREATE DATABASE statements
+     *
+     * @see Doctrine_Connection :: connect();
+     * @return boolean connected
+     */
+     public function connect()
+     {
+         $connected = parent::connect();
+         $this->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
+
+         return $connected;
+     }
+    
+    
+    /**
+     * returns the name of the connected database
+     *
+     * @return string
+     */
+    public function getDatabaseName()
+    {
+        return $this->fetchOne('SELECT DATABASE()');
+    }
+
+    /**
+     * Set the charset on the current connection
+     *
+     * @param string    charset
+     */
+    public function setCharset($charset)
+    {
+        $query = 'SET NAMES ' . $this->quote($charset);
+
+        $this->exec($query);
+    }
+
+    /**
+     * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
+     * query, except that if there is already a row in the table with the same
+     * key field values, the REPLACE query just updates its values instead of
+     * inserting a new row.
+     *
+     * The REPLACE type of query does not make part of the SQL standards. Since
+     * practically only MySQL implements it natively, this type of query is
+     * emulated through this method for other DBMS using standard types of
+     * queries inside a transaction to assure the atomicity of the operation.
+     *
+     * @access public
+     *
+     * @param string $table name of the table on which the REPLACE query will
+     *  be executed.
+     * @param array $fields associative array that describes the fields and the
+     *  values that will be inserted or updated in the specified table. The
+     *  indexes of the array are the names of all the fields of the table. The
+     *  values of the array are also associative arrays that describe the
+     *  values and other properties of the table fields.
+     *
+     *  Here follows a list of field properties that need to be specified:
+     *
+     *    value:
+     *          Value to be assigned to the specified field. This value may be
+     *          of specified in database independent type format as this
+     *          function can perform the necessary datatype conversions.
+     *
+     *    Default:
+     *          this property is required unless the Null property
+     *          is set to 1.
+     *
+     *    type
+     *          Name of the type of the field. Currently, all types Metabase
+     *          are supported except for clob and blob.
+     *
+     *    Default: no type conversion
+     *
+     *    null
+     *          Boolean property that indicates that the value for this field
+     *          should be set to null.
+     *
+     *          The default value for fields missing in INSERT queries may be
+     *          specified the definition of a table. Often, the default value
+     *          is already null, but since the REPLACE may be emulated using
+     *          an UPDATE query, make sure that all fields of the table are
+     *          listed in this function argument array.
+     *
+     *    Default: 0
+     *
+     *    key
+     *          Boolean property that indicates that this field should be
+     *          handled as a primary key or at least as part of the compound
+     *          unique index of the table that will determine the row that will
+     *          updated if it exists or inserted a new row otherwise.
+     *
+     *          This function will fail if no key field is specified or if the
+     *          value of a key field is set to null because fields that are
+     *          part of unique index they may not be null.
+     *
+     *    Default: 0
+     *
+     * @return integer      the number of affected rows
+     */
+    public function replace(Doctrine_Table $table, array $fields, array $keys)
+    {
+        if (empty($keys)) {
+            throw new Doctrine_Connection_Exception('Not specified which fields are keys');
+        }
+
+        $columns = array();
+        $values = array();
+        $params = array();
+        foreach ($fields as $fieldName => $value) {
+            $columns[] = $table->getColumnName($fieldName);
+            $values[] = '?';
+            $params[] = $value;
+        }
+
+        $query = 'REPLACE INTO ' . $table->getTableName() . ' (' . implode(',', $columns) . ') VALUES (' . implode(',', $values) . ')';
+
+        return $this->exec($query, $params);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mysql/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,86 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Mysql_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ */
+class Doctrine_Connection_Mysql_Exception extends Doctrine_Connection_Exception
+{
+    /**
+     * @var array $errorCodeMap         an array that is used for determining portable
+     *                                  error code from a native database error code
+     */
+    protected static $errorCodeMap = array(
+                                      1004 => Doctrine::ERR_CANNOT_CREATE,
+                                      1005 => Doctrine::ERR_CANNOT_CREATE,
+                                      1006 => Doctrine::ERR_CANNOT_CREATE,
+                                      1007 => Doctrine::ERR_ALREADY_EXISTS,
+                                      1008 => Doctrine::ERR_CANNOT_DROP,
+                                      1022 => Doctrine::ERR_ALREADY_EXISTS,
+                                      1044 => Doctrine::ERR_ACCESS_VIOLATION,
+                                      1046 => Doctrine::ERR_NODBSELECTED,
+                                      1048 => Doctrine::ERR_CONSTRAINT,
+                                      1049 => Doctrine::ERR_NOSUCHDB,
+                                      1050 => Doctrine::ERR_ALREADY_EXISTS,
+                                      1051 => Doctrine::ERR_NOSUCHTABLE,
+                                      1054 => Doctrine::ERR_NOSUCHFIELD,
+                                      1061 => Doctrine::ERR_ALREADY_EXISTS,
+                                      1062 => Doctrine::ERR_ALREADY_EXISTS,
+                                      1064 => Doctrine::ERR_SYNTAX,
+                                      1091 => Doctrine::ERR_NOT_FOUND,
+                                      1100 => Doctrine::ERR_NOT_LOCKED,
+                                      1136 => Doctrine::ERR_VALUE_COUNT_ON_ROW,
+                                      1142 => Doctrine::ERR_ACCESS_VIOLATION,
+                                      1146 => Doctrine::ERR_NOSUCHTABLE,
+                                      1216 => Doctrine::ERR_CONSTRAINT,
+                                      1217 => Doctrine::ERR_CONSTRAINT,
+                                      1451 => Doctrine::ERR_CONSTRAINT,
+                                      );
+
+    /**
+     * This method checks if native error code/message can be
+     * converted into a portable code and then adds this
+     * portable error code to $portableCode field
+     *
+     * @param array $errorInfo      error info array
+     * @since 1.0
+     * @return boolean              whether or not the error info processing was successfull
+     *                              (the process is successfull if portable error code was found)
+     */
+    public function processErrorInfo(array $errorInfo)
+    {
+        $code = $errorInfo[1];
+        if (isset(self::$errorCodeMap[$code])) {
+            $this->portableCode = self::$errorCodeMap[$code];
+            return true;
+        }
+        return false;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Oracle.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?php
+/*
+ *  $Id: Oracle.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Oracle
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Connection_Oracle extends Doctrine_Connection
+{
+    /**
+     * @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['varchar2_max_length']  = 4000;
+        $this->properties['number_max_precision'] = 38;
+        
+        parent::__construct($manager, $adapter);
+    }
+
+    /**
+     * 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 ? '*' : $column;
+                if ($offset > 0) {
+                    $min = $offset + 1;
+                    $query = 'SELECT b.'.$column.' FROM ('.
+                                 'SELECT a.*, ROWNUM AS doctrine_rownum FROM ('
+                                   . $query . ') a '.
+                              ') 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);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Oracle/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,80 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Oracle_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ */
+class Doctrine_Connection_Oracle_Exception extends Doctrine_Connection_Exception
+{
+    /**
+     * @var array $errorCodeMap         an array that is used for determining portable
+     *                                  error code from a native database error code
+     */
+    protected static $errorCodeMap = array(
+                                      1    => Doctrine::ERR_CONSTRAINT,
+                                      900  => Doctrine::ERR_SYNTAX,
+                                      904  => Doctrine::ERR_NOSUCHFIELD,
+                                      913  => Doctrine::ERR_VALUE_COUNT_ON_ROW,
+                                      921  => Doctrine::ERR_SYNTAX,
+                                      923  => Doctrine::ERR_SYNTAX,
+                                      942  => Doctrine::ERR_NOSUCHTABLE,
+                                      955  => Doctrine::ERR_ALREADY_EXISTS,
+                                      1400 => Doctrine::ERR_CONSTRAINT_NOT_NULL,
+                                      1401 => Doctrine::ERR_INVALID,
+                                      1407 => Doctrine::ERR_CONSTRAINT_NOT_NULL,
+                                      1418 => Doctrine::ERR_NOT_FOUND,
+                                      1476 => Doctrine::ERR_DIVZERO,
+                                      1722 => Doctrine::ERR_INVALID_NUMBER,
+                                      2289 => Doctrine::ERR_NOSUCHTABLE,
+                                      2291 => Doctrine::ERR_CONSTRAINT,
+                                      2292 => Doctrine::ERR_CONSTRAINT,
+                                      2449 => Doctrine::ERR_CONSTRAINT,
+                                      );
+
+    /**
+     * This method checks if native error code/message can be
+     * converted into a portable code and then adds this
+     * portable error code to $portableCode field
+     *
+     * @param array $errorInfo      error info array
+     * @since 1.0
+     * @return boolean              whether or not the error info processing was successfull
+     *                              (the process is successfull if portable error code was found)
+     */
+    public function processErrorInfo(array $errorInfo)
+    {
+        $code = $errorInfo[1];
+        if (isset(self::$errorCodeMap[$code])) {
+            $this->portableCode = self::$errorCodeMap[$code];
+            return true;
+        }
+        return false;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Pgsql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,195 @@
+<?php
+/*
+ *  $Id: Pgsql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Pgsql
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.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);
+    }
+
+    /**
+     * 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 ' . $limit . ')';
+
+            } else {
+                if ( ! empty($limit)) {
+                  $query .= ' LIMIT ' . $limit;
+                }
+                if ( ! empty($offset)) {
+                  $query .= ' OFFSET ' . $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;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Pgsql/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,108 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Pgsql_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Paul Cooper <pgc@ucecom.com> (PEAR MDB2 Pgsql driver)
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Connection_Pgsql_Exception extends Doctrine_Connection_Exception
+{
+    /**
+     * @var array $errorRegexps         an array that is used for determining portable
+     *                                  error code from a native database error message
+     */
+    protected static $errorRegexps = array(
+                                    '/parser: parse error at or near/i'
+                                        => Doctrine::ERR_SYNTAX,
+                                    '/syntax error at/'
+                                        => Doctrine::ERR_SYNTAX,
+                                    '/column reference .* is ambiguous/i'
+                                        => Doctrine::ERR_SYNTAX,
+                                    '/column .* (of relation .*)?does not exist/i'
+                                        => Doctrine::ERR_NOSUCHFIELD,
+                                    '/attribute .* not found|relation .* does not have attribute/i'
+                                        => Doctrine::ERR_NOSUCHFIELD,
+                                    '/column .* specified in USING clause does not exist in (left|right) table/i'
+                                        => Doctrine::ERR_NOSUCHFIELD,
+                                    '/(relation|sequence|table).*does not exist|class .* not found/i'
+                                        => Doctrine::ERR_NOSUCHTABLE,
+                                    '/index .* does not exist/'
+                                        => Doctrine::ERR_NOT_FOUND,
+                                    '/relation .* already exists/i'
+                                        => Doctrine::ERR_ALREADY_EXISTS,
+                                    '/(divide|division) by zero$/i'
+                                        => Doctrine::ERR_DIVZERO,
+                                    '/pg_atoi: error in .*: can\'t parse /i'
+                                        => Doctrine::ERR_INVALID_NUMBER,
+                                    '/invalid input syntax for( type)? (integer|numeric)/i'
+                                        => Doctrine::ERR_INVALID_NUMBER,
+                                    '/value .* is out of range for type \w*int/i'
+                                        => Doctrine::ERR_INVALID_NUMBER,
+                                    '/integer out of range/i'
+                                        => Doctrine::ERR_INVALID_NUMBER,
+                                    '/value too long for type character/i'
+                                        => Doctrine::ERR_INVALID,
+                                    '/permission denied/'
+                                        => Doctrine::ERR_ACCESS_VIOLATION,
+                                    '/violates [\w ]+ constraint/'
+                                        => Doctrine::ERR_CONSTRAINT,
+                                    '/referential integrity violation/'
+                                        => Doctrine::ERR_CONSTRAINT,
+                                    '/violates not-null constraint/'
+                                        => Doctrine::ERR_CONSTRAINT_NOT_NULL,
+                                    '/more expressions than target columns/i'
+                                        => Doctrine::ERR_VALUE_COUNT_ON_ROW,
+                                );
+
+    /**
+     * This method checks if native error code/message can be
+     * converted into a portable code and then adds this
+     * portable error code to $portableCode field
+     *
+     * the portable error code is added at the end of array
+     *
+     * @param array $errorInfo      error info array
+     * @since 1.0
+     * @see Doctrine::ERR_* constants
+     * @see Doctrine_Connection::$portableCode
+     * @return boolean              whether or not the error info processing was successfull
+     *                              (the process is successfull if portable error code was found)
+     */
+    public function processErrorInfo(array $errorInfo)
+    {
+        foreach (self::$errorRegexps as $regexp => $code) {
+            if (preg_match($regexp, $errorInfo[2])) {
+                $this->portableCode = $code;
+                return true;
+            }
+        }
+        return false;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Profiler.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,182 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Profiler
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ */
+class Doctrine_Connection_Profiler implements Doctrine_Overloadable, IteratorAggregate, Countable
+{
+    /**
+     * @param array $listeners      an array containing all availible listeners
+     */
+    private $listeners  = array('query',
+                                'prepare',
+                                'commit',
+                                'rollback',
+                                'connect',
+                                'begintransaction',
+                                'exec',
+                                'execute');
+
+    /**
+     * @param array $events         an array containing all listened events
+     */
+    private $events     = array();
+
+    /**
+     * constructor
+     */
+    public function __construct() {
+
+    }
+
+    /**
+     * setFilterQueryType
+     *
+     * @param integer $filter
+     * @return boolean
+     */
+    public function setFilterQueryType() {
+                                             
+    }                                         
+    /**
+     * method overloader
+     * this method is used for invoking different listeners, for the full
+     * list of availible listeners, see Doctrine_EventListener
+     *
+     * @param string $m     the name of the method
+     * @param array $a      method arguments
+     * @see Doctrine_EventListener
+     * @return boolean
+     */
+    public function __call($m, $a)
+    {
+        // first argument should be an instance of Doctrine_Event
+        if ( ! ($a[0] instanceof Doctrine_Event)) {
+            throw new Doctrine_Connection_Profiler_Exception("Couldn't listen event. Event should be an instance of Doctrine_Event.");
+        }
+
+
+        if (substr($m, 0, 3) === 'pre') {
+            // pre-event listener found
+            $a[0]->start();
+
+            if ( ! in_array($a[0], $this->events, true)) {
+                $this->events[] = $a[0];
+            }
+        } else {
+            // after-event listener found
+            $a[0]->end();
+        }
+        /**
+         * If filtering by query type is enabled, only keep the query if
+         * it was one of the allowed types.
+         */
+         /**
+        if ( ! is_null($this->filterTypes)) {
+            if ( ! ($a[0]->getQueryType() & $this->_filterTypes)) {
+
+            }
+        }
+        */
+
+    }
+
+    /**
+     * get
+     *
+     * @param mixed $key
+     * @return Doctrine_Event
+     */
+    public function get($key) 
+    {
+        if (isset($this->events[$key])) {
+            return $this->events[$key];
+        }
+        return null;
+    }
+
+    /**
+     * getAll
+     * returns all profiled events as an array
+     *
+     * @return array        all events in an array
+     */
+    public function getAll() 
+    {
+        return $this->events;
+    }
+
+    /**
+     * getIterator
+     * returns an iterator that iterates through the logged events
+     *
+     * @return ArrayIterator
+     */
+    public function getIterator()
+    {
+        return new ArrayIterator($this->events);
+    }
+
+    /**
+     * count
+     * 
+     * @return integer
+     */
+    public function count() 
+    {
+        return count($this->events);
+    }
+
+    /**
+     * pop the last event from the event stack
+     *
+     * @return Doctrine_Event
+     */
+    public function pop() 
+    {
+        return array_pop($this->events);
+    }
+
+    /**
+     * Get the Doctrine_Event object for the last query that was run, regardless if it has
+     * ended or not. If the event has not ended, it's end time will be Null.
+     *
+     * @return Doctrine_Event
+     */
+    public function lastEvent()
+    {
+        if (empty($this->events)) {
+            return false;
+        }
+
+        end($this->events);
+        return current($this->events);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Profiler/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,35 @@
+<?php
+/*
+ *  $Id: Exception.php 1345 2007-05-14 13:00:14Z meus $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Profiler_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1345 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Connection_Profiler_Exception extends Doctrine_Exception
+{
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Sqlite.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,141 @@
+<?php
+/*
+ *  $Id: Sqlite.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Sqlite
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Connection_Sqlite extends Doctrine_Connection_Common
+{
+    /**
+     * @var string $driverName                  the name of this connection driver
+     */
+    protected $driverName = 'Sqlite';
+
+    /**
+     * the constructor
+     *
+     * @param Doctrine_Manager $manager
+     * @param PDO $pdo                          database handle
+     */
+    public function __construct(Doctrine_Manager $manager, $adapter)
+    {
+        $this->supported = array('sequences'            => 'emulated',
+                          'indexes'              => true,
+                          'affected_rows'        => true,
+                          'summary_functions'    => true,
+                          'order_by_text'        => true,
+                          'current_id'           => 'emulated',
+                          'limit_queries'        => true,
+                          'LOBs'                 => true,
+                          'replace'              => true,
+                          'transactions'         => true,
+                          'savepoints'           => false,
+                          'sub_selects'          => true,
+                          'auto_increment'       => true,
+                          'primary_key'          => true,
+                          'result_introspection' => false, // not implemented
+                          'prepared_statements'  => 'emulated',
+                          'identifier_quoting'   => true,
+                          'pattern_escaping'     => false,
+                          );
+         parent::__construct($manager, $adapter);
+
+        if ($this->isConnected) {
+            $this->dbh->sqliteCreateFunction('mod',    array('Doctrine_Expression_Sqlite', 'modImpl'), 2);
+            $this->dbh->sqliteCreateFunction('concat', array('Doctrine_Expression_Sqlite', 'concatImpl'));
+            $this->dbh->sqliteCreateFunction('md5', 'md5', 1);
+            $this->dbh->sqliteCreateFunction('now', 'time', 0);
+        }
+    }
+
+    /**
+     * initializes database functions missing in sqlite
+     *
+     * @see Doctrine_Expression
+     * @return void
+     */
+    public function connect() 
+    {
+        if ($this->isConnected) {
+            return false;
+        }
+
+        parent::connect();
+
+        $this->dbh->sqliteCreateFunction('mod',    array('Doctrine_Expression_Sqlite', 'modImpl'), 2);
+        $this->dbh->sqliteCreateFunction('concat', array('Doctrine_Expression_Sqlite', 'concatImpl'));
+        $this->dbh->sqliteCreateFunction('md5', 'md5', 1);
+        $this->dbh->sqliteCreateFunction('now', 'time', 0);
+    }
+
+    /**
+     * createDatabase
+     *
+     * @return void
+     */
+    public function createDatabase()
+    {
+      try {
+          if ( ! $dsn = $this->getOption('dsn')) {
+              throw new Doctrine_Connection_Exception('You must create your Doctrine_Connection by using a valid Doctrine style dsn in order to use the create/drop database functionality');
+          }
+
+          $info = $this->getManager()->parseDsn($dsn);
+
+          $this->export->createDatabase($info['database']);
+
+          return 'Successfully created database for connection "' . $this->getName() . '" at path "' . $info['database'] . '"';
+      } catch (Exception $e) {
+          return $e;
+      }
+    }
+
+    /**
+     * dropDatabase
+     *
+     * @return void
+     */
+    public function dropDatabase()
+    {
+      try {
+          if ( ! $dsn = $this->getOption('dsn')) {
+              throw new Doctrine_Connection_Exception('You must create your Doctrine_Connection by using a valid Doctrine style dsn in order to use the create/drop database functionality');
+          }
+          
+          $info = $this->getManager()->parseDsn($dsn);
+
+          $this->export->dropDatabase($info['database']);
+
+          return 'Successfully dropped database for connection "' . $this->getName() . '" at path "' . $info['database'] . '"';
+      } catch (Exception $e) {
+          return $e;
+      }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Sqlite/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,78 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Sqlite_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ */
+class Doctrine_Connection_Sqlite_Exception extends Doctrine_Connection_Exception
+{
+    /**
+     * @var array $errorRegexps         an array that is used for determining portable
+     *                                  error code from a native database error message
+     */
+    protected static $errorRegexps = array(
+                              '/^no such table:/'                    => Doctrine::ERR_NOSUCHTABLE,
+                              '/^no such index:/'                    => Doctrine::ERR_NOT_FOUND,
+                              '/^(table|index) .* already exists$/'  => Doctrine::ERR_ALREADY_EXISTS,
+                              '/PRIMARY KEY must be unique/i'        => Doctrine::ERR_CONSTRAINT,
+                              '/is not unique/'                      => Doctrine::ERR_CONSTRAINT,
+                              '/columns .* are not unique/i'         => Doctrine::ERR_CONSTRAINT,
+                              '/uniqueness constraint failed/'       => Doctrine::ERR_CONSTRAINT,
+                              '/may not be NULL/'                    => Doctrine::ERR_CONSTRAINT_NOT_NULL,
+                              '/^no such column:/'                   => Doctrine::ERR_NOSUCHFIELD,
+                              '/column not present in both tables/i' => Doctrine::ERR_NOSUCHFIELD,
+                              '/^near ".*": syntax error$/'          => Doctrine::ERR_SYNTAX,
+                              '/[0-9]+ values for [0-9]+ columns/i'  => Doctrine::ERR_VALUE_COUNT_ON_ROW,
+                              );
+
+    /**
+     * This method checks if native error code/message can be
+     * converted into a portable code and then adds this
+     * portable error code to $portableCode field
+     *
+     * @param array $errorInfo      error info array
+     * @since 1.0
+     * @see Doctrine::ERR_* constants
+     * @see Doctrine_Connection::$portableCode
+     * @return boolean              whether or not the error info processing was successfull
+     *                              (the process is successfull if portable error code was found)
+     */
+    public function processErrorInfo(array $errorInfo)
+    {
+        foreach (self::$errorRegexps as $regexp => $code) {
+            if (preg_match($regexp, $errorInfo[2])) {
+
+                $this->portableCode = $code;
+                return true;
+            }
+        }
+        return false;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Statement.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,468 @@
+<?php
+/*
+ *  $Id: Statement.php 1532 2007-05-31 17:45:07Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Connection_Statement
+ *
+ * @package     Doctrine
+ * @subpackage  Connection
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1532 $
+ */
+class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interface
+{
+    /**
+     * @var Doctrine_Connection $conn       Doctrine_Connection object, every connection
+     *                                      statement holds an instance of Doctrine_Connection
+     */
+    protected $_conn;
+
+    /**
+     * @var mixed $_stmt                    PDOStatement object, boolean false or Doctrine_Adapter_Statement object
+     */
+    protected $_stmt;
+
+    /**
+     * constructor
+     *
+     * @param Doctrine_Connection $conn     Doctrine_Connection object, every connection
+     *                                      statement holds an instance of Doctrine_Connection
+     * @param mixed $stmt
+     */
+    public function __construct(Doctrine_Connection $conn, $stmt)
+    {
+        $this->_conn = $conn;
+        $this->_stmt = $stmt;
+
+        if ($stmt === false) {
+            throw new Doctrine_Exception('Unknown statement object given.');
+        }
+    }
+
+    /**
+     * getConnection
+     * returns the connection object this statement uses
+     *
+     * @return Doctrine_Connection
+     */
+    public function getConnection()
+    {
+        return $this->_conn;
+    }
+    public function getStatement()
+    {
+        return $this->_stmt;
+    }
+    public function getQuery()
+    {
+        return $this->_stmt->queryString;
+    }
+
+    /**
+     * bindColumn
+     * 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::PARAM_* constants.
+     * @return boolean              Returns TRUE on success or FALSE on failure
+     */
+    public function bindColumn($column, $param, $type = null)
+    {
+        if ($type === null) {
+            return $this->_stmt->bindColumn($column, $param);
+        } else {
+            return $this->_stmt->bindColumn($column, $param, $type);
+        }
+    }
+
+    /**
+     * bindValue
+     * 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::PARAM_* constants.
+     *
+     * @return boolean              Returns TRUE on success or FALSE on failure.
+     */
+    public function bindValue($param, $value, $type = null)
+    {
+        if ($type === null) {
+            return $this->_stmt->bindValue($param, $value);
+        } else {
+            return $this->_stmt->bindValue($param, $value, $type);
+        }
+    }
+
+    /**
+     * bindParam
+     * 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::PARAM_* constants. To return
+     *                              an INOUT parameter from a stored procedure, use the bitwise OR operator to set the
+     *                              Doctrine::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 ($type === null) {
+            return $this->_stmt->bindParam($column, $variable);
+        } else {
+            return $this->_stmt->bindParam($column, $variable, $type, $length, $driverOptions);
+        }
+    }
+
+    /**
+     * closeCursor
+     * Closes the cursor, enabling the statement to be executed again.
+     *
+     * @return boolean              Returns TRUE on success or FALSE on failure.
+     */
+    public function closeCursor()
+    {
+        return $this->_stmt->closeCursor();
+    }
+
+    /**
+     * columnCount
+     * 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 $this->_stmt->columnCount();
+    }
+
+    /**
+     * errorCode
+     * 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()
+    {
+        return $this->_stmt->errorCode();
+    }
+
+    /**
+     * errorInfo
+     * 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()
+    {
+        return $this->_stmt->errorInfo();
+    }
+
+    /**
+     * execute
+     * 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)
+    {
+        try {
+            $event = new Doctrine_Event($this, Doctrine_Event::STMT_EXECUTE, $this->getQuery(), $params);
+            $this->_conn->getListener()->preStmtExecute($event);
+
+            $result = true;
+            if ( ! $event->skipOperation) {
+
+                if ($this->_conn->getAttribute(Doctrine::PORTABILITY_EMPTY_TO_NULL)) {
+                    foreach ($params as $key => $value) {
+                        if ($value == '') {
+                            $params[$key] = null;
+                        }
+                    }
+                }
+
+                $result = $this->_stmt->execute($params);
+                $this->_conn->incrementQueryCount();
+            }
+
+            $this->_conn->getListener()->postStmtExecute($event);
+
+            return $result;
+        } catch (PDOException $e) {
+        } catch (Doctrine_Adapter_Exception $e) {
+        }
+
+        $this->_conn->rethrowException($e, $this);
+
+        return false;
+    }
+
+    /**
+     * fetch
+     *
+     * @see Doctrine::FETCH_* constants
+     * @param integer $fetchStyle           Controls how the next row will be returned to the caller.
+     *                                      This value must be one of the Doctrine::FETCH_* constants,
+     *                                      defaulting to Doctrine::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::FETCH_ORI_* constants, defaulting to
+     *                                      Doctrine::FETCH_ORI_NEXT. To request a scrollable cursor for your
+     *                                      Doctrine_Adapter_Statement_Interface object,
+     *                                      you must set the Doctrine::ATTR_CURSOR attribute to Doctrine::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::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::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($fetchMode = Doctrine::FETCH_BOTH,
+                          $cursorOrientation = Doctrine::FETCH_ORI_NEXT,
+                          $cursorOffset = null)
+    {
+        $event = new Doctrine_Event($this, Doctrine_Event::STMT_FETCH, $this->getQuery());
+
+        $event->fetchMode = $fetchMode;
+        $event->cursorOrientation = $cursorOrientation;
+        $event->cursorOffset = $cursorOffset;
+
+        $data = $this->_conn->getListener()->preFetch($event);
+
+        if ( ! $event->skipOperation) {
+            $data = $this->_stmt->fetch($fetchMode, $cursorOrientation, $cursorOffset);
+        }
+
+        $this->_conn->getListener()->postFetch($event);
+
+        return $data;
+    }
+
+    /**
+     * fetchAll
+     * Returns an array containing all of the result set rows
+     *
+     * @param integer $fetchMode            Controls how the next row will be returned to the caller.
+     *                                      This value must be one of the Doctrine::FETCH_* constants,
+     *                                      defaulting to Doctrine::FETCH_BOTH
+     *
+     * @param integer $columnIndex          Returns the indicated 0-indexed column when the value of $fetchStyle is
+     *                                      Doctrine::FETCH_COLUMN. Defaults to 0.
+     *
+     * @return array
+     */
+    public function fetchAll($fetchMode = Doctrine::FETCH_BOTH,
+                             $columnIndex = null)
+    {
+        $event = new Doctrine_Event($this, Doctrine_Event::STMT_FETCHALL, $this->getQuery());
+        $event->fetchMode = $fetchMode;
+        $event->columnIndex = $columnIndex;
+
+        $this->_conn->getListener()->preFetchAll($event);
+
+        if ( ! $event->skipOperation) {
+            if ($columnIndex !== null) {
+                $data = $this->_stmt->fetchAll($fetchMode, $columnIndex);
+            } else {
+                $data = $this->_stmt->fetchAll($fetchMode);
+            }
+
+            $event->data = $data;
+        }
+
+        $this->_conn->getListener()->postFetchAll($event);
+
+        return $data;
+    }
+
+    /**
+     * fetchColumn
+     * 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)
+    {
+        return $this->_stmt->fetchColumn($columnIndex);
+    }
+
+    /**
+     * fetchObject
+     * 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::FETCH_CLASS or Doctrine::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())
+    {
+        return $this->_stmt->fetchObject($className, $args);
+    }
+
+    /**
+     * getAttribute
+     * Retrieve a statement attribute
+     *
+     * @param integer $attribute
+     * @see Doctrine::ATTR_* constants
+     * @return mixed                        the attribute value
+     */
+    public function getAttribute($attribute)
+    {
+        return $this->_stmt->getAttribute($attribute);
+    }
+
+    /**
+     * getColumnMeta
+     * 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)
+    {
+        return $this->_stmt->getColumnMeta($column);
+    }
+
+    /**
+     * nextRowset
+     * 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()
+    {
+        return $this->_stmt->nextRowset();
+    }
+
+    /**
+     * rowCount
+     * 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 $this->_stmt->rowCount();
+    }
+
+    /**
+     * setAttribute
+     * 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)
+    {
+        return $this->_stmt->setAttribute($attribute, $value);
+    }
+
+    /**
+     * setFetchMode
+     * Set the default fetch mode for this statement
+     *
+     * @param integer $mode                 The fetch mode must be one of the Doctrine::FETCH_* constants.
+     * @return boolean                      Returns 1 on success or FALSE on failure.
+     */
+    public function setFetchMode($mode, $arg1 = null, $arg2 = null)
+    {
+        return $this->_stmt->setFetchMode($mode, $arg1, $arg2);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/UnitOfWork.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,894 @@
+<?php
+/*
+ *  $Id: UnitOfWork.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * 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.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Roman Borschel <roman@code-factory.org>
+ */
+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)
+    {
+        $record->assignInheritanceValues();
+
+        $conn = $this->getConnection();
+
+        $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();
+            $this->saveRelatedLocalKeys($record);
+
+            $record->state($state);
+
+            $event = new Doctrine_Event($record, Doctrine_Event::RECORD_SAVE);
+            $record->preSave($event);
+            $record->getTable()->getRecordListener()->preSave($event);
+            $state = $record->state();
+
+            $isValid = true;
+
+            if ( ! $event->skipOperation) {
+                switch ($state) {
+                    case Doctrine_Record::STATE_TDIRTY:
+                    case Doctrine_Record::STATE_TCLEAN:
+                        $isValid = $this->insert($record);
+                        break;
+                    case Doctrine_Record::STATE_DIRTY:
+                    case Doctrine_Record::STATE_PROXY:
+                        $isValid = $this->update($record);
+                        break;
+                    case Doctrine_Record::STATE_CLEAN:
+                        // do nothing
+                        break;
+                }
+            }
+
+            if ($isValid) {
+                // NOTE: what about referential integrity issues?
+                foreach ($record->getPendingDeletes() as $pendingDelete) {
+                    $pendingDelete->delete();
+                }
+
+                $record->postSave($event);
+                $record->getTable()->getRecordListener()->postSave($event);
+            } else {
+                $conn->transaction->addInvalid($record);
+            }
+
+            $state = $record->state();
+
+            $record->state($record->exists() ? Doctrine_Record::STATE_LOCKED : Doctrine_Record::STATE_TLOCKED);
+
+            $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)) {
+                        $obj->save($conn);
+                    }
+                }
+            }
+
+            // 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;
+        }
+
+        return true;
+    }
+
+    /**
+     * saves the given record
+     *
+     * @param Doctrine_Record $record
+     * @return void
+     */
+    public function save(Doctrine_Record $record)
+    {
+        $event = new Doctrine_Event($record, Doctrine_Event::RECORD_SAVE);
+
+        $record->preSave($event);
+
+        $record->getTable()->getRecordListener()->preSave($event);
+
+        if ( ! $event->skipOperation) {
+            switch ($record->state()) {
+                case Doctrine_Record::STATE_TDIRTY:
+                case Doctrine_Record::STATE_TCLEAN:
+                    $this->insert($record);
+                    break;
+                case Doctrine_Record::STATE_DIRTY:
+                case Doctrine_Record::STATE_PROXY:
+                    $this->update($record);
+                    break;
+                case Doctrine_Record::STATE_CLEAN:
+                    // do nothing
+                    break;
+            }
+        }
+
+        $record->getTable()->getRecordListener()->postSave($event);
+
+        $record->postSave($event);
+    }
+
+    /**
+     * 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) {
+                    while (list($fieldName, $value) = each($idMap)) {
+                        $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)
+    {
+        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 => $field) {
+                            if (isset($id[$k]) && $id[$k] && $record->getTable()->hasField($field)) {
+                                $record->set($field, $id[$k]);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 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) {
+                $v->save($this->conn, false);
+
+                $assocTable = $rel->getAssociationTable();
+                foreach ($v->getDeleteDiff() as $r) {
+                    $query = 'DELETE FROM ' . $assocTable->getTableName()
+                           . ' WHERE ' . $rel->getForeign() . ' = ?'
+                           . ' AND ' . $rel->getLocal() . ' = ?';
+
+                    $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 = new Doctrine_Event($record, Doctrine_Event::RECORD_UPDATE);
+        $record->preUpdate($event);
+        $table = $record->getTable();
+        $table->getRecordListener()->preUpdate($event);
+
+        if ($record->isValid()) {
+            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);
+            }
+
+            $table->getRecordListener()->postUpdate($event);
+
+            $record->postUpdate($event);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * inserts a record into database
+     *
+     * @param Doctrine_Record $record   record to be inserted
+     * @return boolean
+     */
+    public function insert(Doctrine_Record $record)
+    {
+        // listen the onPreInsert event
+        $event = new Doctrine_Event($record, Doctrine_Event::RECORD_INSERT);
+        $record->preInsert($event);
+        $table = $record->getTable();
+        $table->getRecordListener()->preInsert($event);
+
+        if ($record->isValid()) {
+            if ( ! $event->skipOperation) {
+                if ($table->getOption('joinedParents')) {
+                    // just for bc!
+                    $this->_insertCTIRecord($table, $record);
+                    //--
+                } else {
+                    $this->processSingleInsert($record);
+                }
+            }
+
+            $table->addRecord($record);
+            $table->getRecordListener()->postInsert($event);
+            $record->postInsert($event);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * @todo DESCRIBE WHAT THIS METHOD DOES, PLEASE!
+     */
+    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;
+            }
+        }
+
+        $identifier = (array) $table->getIdentifier();
+
+        $seq = $record->getTable()->sequenceName;
+
+        if ( ! empty($seq)) {
+            $id = $this->conn->sequence->nextId($seq);
+            $seqName = $table->getIdentifier();
+            $fields[$seqName] = $id;
+
+            $record->assignIdentifier($id);
+        }
+
+        $this->conn->insert($table, $fields);
+
+        if (empty($seq) && count($identifier) == 1 && $identifier[0] == $table->getIdentifier() &&
+            $table->getIdentifierType() != Doctrine::IDENTIFIER_NATURAL) {
+            if (($driver = strtolower($this->conn->getDriverName())) == 'pgsql') {
+                $seq = $table->getTableName() . '_' . $identifier[0];
+            } elseif ($driver == 'oracle') {
+                $seq = $table->getTableName();
+            }
+
+            $id = $this->conn->sequence->lastInsertId($seq);
+
+            if ( ! $id) {
+                throw new Doctrine_Connection_Exception("Couldn't get last insert identifier.");
+            }
+            $record->assignIdentifier($id);
+        } else {
+            $record->assignIdentifier(true);
+        }
+    }
+
+    /**
+     * 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[$index]);
+                        array_splice($flushList, $index3, 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();
+            }
+
+            $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;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,279 @@
+<?php
+/*
+ *  $Id: Data.php 2552 2007-09-19 19:33:00Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * 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.
+ *
+ * @package     Doctrine
+ * @subpackage  Data
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2552 $
+ */
+class Doctrine_Data
+{
+    /**
+     * formats
+     *
+     * array of formats data can be in
+     *
+     * @var string
+     */
+    protected $_formats = array('csv', 'yml', 'xml');
+
+    /**
+     * format
+     * 
+     * the default and current format we are working with
+     *
+     * @var string
+     */
+    protected $_format = 'yml';
+
+    /**
+     * directory
+     *
+     * array of directory/yml paths or single directory/yml file
+     *
+     * @var string
+     */
+    protected $_directory = null;
+
+    /**
+     * models
+     *
+     * specified array of models to use
+     *
+     * @var string
+     */
+    protected $_models = array();
+
+    /**
+     * _exportIndividualFiles
+     *
+     * whether or not to export data to individual files instead of 1
+     *
+     * @var string
+     */
+    protected $_exportIndividualFiles = false;
+
+    /**
+     * setFormat
+     *
+     * Set the current format we are working with
+     * 
+     * @param string $format 
+     * @return void
+     */
+    public function setFormat($format)
+    {
+        $this->_format = $format;
+    }
+
+    /**
+     * getFormat
+     *
+     * Get the current format we are working with
+     * 
+     * @return void
+     */
+    public function getFormat()
+    {
+        return $this->_format;
+    }
+
+    /**
+     * getFormats 
+     *
+     * Get array of available formats
+     * 
+     * @return void
+     */
+    public function getFormats()
+    {
+        return $this->_formats;
+    }
+
+    /**
+     * setDirectory
+     *
+     * Set the array/string of directories or yml file paths
+     * 
+     * @return void
+     */
+    public function setDirectory($directory)
+    {
+        $this->_directory = $directory;
+    }
+
+    /**
+     * getDirectory
+     *
+     * Get directory for dumping/loading data from and to
+     * 
+     * @return void
+     */
+    public function getDirectory()
+    {
+        return $this->_directory;
+    }
+
+    /**
+     * setModels
+     *
+     * Set the array of specified models to work with
+     * 
+     * @param string $models 
+     * @return void
+     */
+    public function setModels($models)
+    {
+        $this->_models = $models;
+    }
+
+    /**
+     * getModels
+     *
+     * Get the array of specified models to work with
+     *
+     * @return void
+     */
+    public function getModels()
+    {
+        return $this->_models;
+    }
+
+    /**
+     * _exportIndividualFiles 
+     *
+     * Set/Get whether or not to export individual files
+     * 
+     * @return bool $_exportIndividualFiles
+     */
+    public function exportIndividualFiles($bool = null)
+    {
+        if ($bool !== null) {
+            $this->_exportIndividualFiles = $bool;
+        }
+        
+        return $this->_exportIndividualFiles;
+    }
+
+    /**
+     * exportData
+     *
+     * Interface for exporting data to fixtures files from Doctrine models
+     *
+     * @param string $directory 
+     * @param string $format 
+     * @param string $models 
+     * @param string $_exportIndividualFiles 
+     * @return void
+     */
+    public function exportData($directory, $format = 'yml', $models = array(), $_exportIndividualFiles = false)
+    {
+        $export = new Doctrine_Data_Export($directory);
+        $export->setFormat($format);
+        $export->setModels($models);
+        $export->exportIndividualFiles($_exportIndividualFiles);
+        
+        return $export->doExport();
+    }
+
+    /**
+     * importData
+     *
+     * Interface for importing data from fixture files to Doctrine models
+     *
+     * @param string $directory 
+     * @param string $format 
+     * @param string $models 
+     * @return void
+     */
+    public function importData($directory, $format = 'yml', $models = array(), $append = false)
+    {
+        $import = new Doctrine_Data_Import($directory);
+        $import->setFormat($format);
+        $import->setModels($models);
+        
+        return $import->doImport($append);
+    }
+
+    /**
+     * 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 
+     * @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 
+     * @return void
+     */
+    public function purge($models = null)
+    {
+        if ($models) {
+            $models = Doctrine::filterInvalidModels($models);
+        } else {
+            $models = Doctrine::getLoadedModels();
+        }
+
+        $connections = array();
+        foreach ($models as $model) {
+          $connections[Doctrine::getTable($model)->getConnection()->getName()][] = $model;
+        }
+
+        foreach ($connections as $connection => $models) {
+            $models = Doctrine_Manager::getInstance()->getConnection($connection)->unitOfWork->buildFlushTree($models);
+            $models = array_reverse($models);
+            foreach ($models as $model) {
+                Doctrine::getTable($model)->createQuery()->delete()->execute();
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 2552 2007-09-19 19:33:00Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Data_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Data
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2552 $
+ */
+class Doctrine_Data_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data/Export.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,212 @@
+<?php
+/*
+ *  $Id: Export.php 2552 2007-09-19 19:33:00Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Data_Export
+ *
+ * @package     Doctrine
+ * @subpackage  Data
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2552 $
+ */
+class Doctrine_Data_Export extends Doctrine_Data
+{
+    /**
+     * constructor
+     *
+     * @param string $directory 
+     * @return void
+     */
+    public function __construct($directory)
+    {
+        $this->setDirectory($directory);
+    }
+
+    /**
+     * doExport
+     *
+     * 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::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::initializeModels($models);
+
+        // temporarily disable indexBy query parts of selected and related tables
+        $originalIndexBy = array();
+        foreach ($models AS $name) {
+          $table = Doctrine::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::getTable($name)->findAll();
+
+            if ($results->count() > 0) {
+                $data[$name] = $results;
+            }
+        }
+
+        // Restore the temporarily disabled indexBy query parts
+        foreach($originalIndexBy AS $name => $indexBy) {
+            Doctrine::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();
+            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 (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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Data/Import.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,374 @@
+<?php
+/*
+ *  $Id: Import.php 2552 2007-09-19 19:33:00Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Data_Import
+ *
+ * @package     Doctrine
+ * @package     Data
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2552 $
+ */
+class Doctrine_Data_Import extends Doctrine_Data
+{
+    /**
+     * Array of imported objects for processing and saving
+     *
+     * @var array
+     */
+    protected $_importedObjects = array();
+
+    /**
+     * Array of the raw data parsed from yaml
+     *
+     * @var array
+     */
+    protected $_rows = array();
+
+    /**
+     * Optionally pass the directory/path to the yaml for importing
+     *
+     * @param string $directory
+     * @return void
+     */
+    public function __construct($directory = null)
+    {
+        if ($directory !== null) {
+            $this->setDirectory($directory);
+        }
+    }
+
+    /**
+     * Do the parsing of the yaml files and return the final parsed array
+     *
+     * @return array $array
+     */
+    public function doParsing()
+    {
+        $recursiveMerge = Doctrine_Manager::getInstance()->getAttribute('recursive_merge_fixtures');
+        $mergeFunction = $recursiveMerge === true ? 'array_merge_recursive':'array_merge';
+        $directory = $this->getDirectory();
+
+        $array = array();
+
+        if ($directory !== null) {
+            foreach ((array) $directory as $dir) {
+                $e = explode('.', $dir);
+
+                // If they specified a specific yml file
+                if (end($e) == 'yml') {
+                    $array = $mergeFunction($array, Doctrine_Parser::load($dir, $this->getFormat()));
+                // If they specified a directory
+                } else if(is_dir($dir)) {
+                    $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir),
+                                                            RecursiveIteratorIterator::LEAVES_ONLY);
+
+                    foreach ($it as $file) {
+                        $e = explode('.', $file->getFileName());
+                        if (in_array(end($e), $this->getFormats())) {
+                            $array = $mergeFunction($array, Doctrine_Parser::load($file->getPathName(), $this->getFormat()));
+                        }
+                    }
+                }
+            }
+        }
+
+        return $array;
+    }
+
+    /**
+     * Do the importing of the data parsed from the fixtures
+     *
+     * @return void
+     */
+    public function doImport($append = false)
+    {
+        $array = $this->doParsing();
+
+        if ( ! $append) {
+            $this->purge(array_reverse(array_keys($array)));
+        }
+
+        $this->_loadData($array);
+    }
+
+    /**
+     * Recursively loop over all data fixtures and build the array of className rows
+     *
+     * @return void
+     */
+    protected function _buildRows($className, $data)
+    {
+        foreach ($data as $rowKey => $row) {
+            // do the same for the row information
+            $this->_rows[$className][$rowKey] = $row;
+
+            foreach ((array) $row as $key => $value) {
+                if (Doctrine::getTable($className)->hasRelation($key) && is_array($value)) {
+                    $keys = array_keys($value);
+
+                    // Skip associative arrays defining keys to relationships
+                    if ( ! isset($keys[0])) {
+                        $this->_buildRows(Doctrine::getTable($className)->getRelation($key)->getTable()->getOption('name'), $value);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Build the rows for nested set models
+     *
+     * @return void
+     */
+    protected function _buildNestedSetRows($className, $data)
+    {
+        foreach ($data as $rowKey => $row) {
+            $children = isset($row['children']) ? $row['children']:array();
+            unset($row['children']);
+            $this->_rows[$className][$rowKey] = $row;
+
+            $this->_buildNestedSetRows($className, $children);
+        }
+    }
+
+    /**
+     * Get the unsaved object for a specified row key and validate that it is the valid object class
+     * for the passed record and relation name
+     *
+     * @param  string $rowKey
+     * @param  Doctrine_Record $record
+     * @param  string $relationName
+     * @param  string $referringRowKey
+     * @return Doctrine_Record
+     * @throws Doctrine_Data_Exception
+     */
+    protected function _getImportedObject($rowKey, Doctrine_Record $record, $relationName, $referringRowKey)
+    {
+        if ( ! isset($this->_importedObjects[$rowKey])) {
+            throw new Doctrine_Data_Exception(
+                sprintf('Invalid row key specified: %s, referred to in %s', $rowKey, $referringRowKey)
+            );
+        }
+
+        $relatedRowKeyObject = $this->_importedObjects[$rowKey];
+
+        $relation = $record->getTable()->getRelation($relationName);
+        if ($relation->getClass() !== get_class($relatedRowKeyObject)) {
+            if ( ! is_subclass_of($relatedRowKeyObject, $relation->getClass())) {
+                throw new Doctrine_Data_Exception(sprintf(
+                    'Class referred to in "%s" is expected to be "%s" and "%s" was given',
+                    $referringRowKey, $relation->getClass(), get_class($relatedRowKeyObject)));
+            }
+        }
+
+        return $relatedRowKeyObject;
+    }
+
+    /**
+     * Process a row and make all the appropriate relations between the imported data
+     *
+     * @param string $rowKey
+     * @param string $row
+     * @return void
+     */
+    protected function _processRow($rowKey, $row)
+    {
+        $obj = $this->_importedObjects[$rowKey];
+
+        foreach ((array) $row as $key => $value) {
+            if (method_exists($obj, 'set' . Doctrine_Inflector::classify($key))) {
+                $func = 'set' . Doctrine_Inflector::classify($key);
+                $obj->$func($value);
+            } else if ($obj->getTable()->hasField($key)) {
+                if ($obj->getTable()->getTypeOf($key) == 'object') {
+                    $value = unserialize($value);
+                }
+                $obj->set($key, $value);
+            } else if ($obj->getTable()->hasRelation($key)) {
+                if (is_array($value)) {
+                    if (isset($value[0]) && ! is_array($value[0])) {
+                        foreach ($value as $link) {
+                            if ($obj->getTable()->getRelation($key)->getType() === Doctrine_Relation::ONE) {
+                                $obj->set($key, $this->_getImportedObject($link, $obj, $key, $rowKey));
+                            } else if ($obj->getTable()->getRelation($key)->getType() === Doctrine_Relation::MANY) {
+                                $relation = $obj->$key;
+
+                                $relation[] = $this->_getImportedObject($link, $obj, $key, $rowKey);
+                            }
+                        }
+                    } else {
+                        $obj->$key->fromArray($value);
+                    }
+                } else {
+                    $obj->set($key, $this->_getImportedObject($value, $obj, $key, $rowKey));
+                }
+            } else {
+                try {
+                    $obj->$key = $value;
+                } catch (Exception $e) {
+                    // used for Doctrine plugin methods (Doctrine_Template)
+                    if (is_callable(array($obj, 'set' . Doctrine_Inflector::classify($key)))) {
+                        $func = 'set' . Doctrine_Inflector::classify($key);
+                        $obj->$func($value);
+                    } else {
+                        throw new Doctrine_Data_Exception('Invalid fixture element "'. $key . '" under "' . $rowKey . '"');
+                    }
+                }
+            }
+        }
+    }
+
+   /**
+    * NestedSet fixtures may come in a 'natural' format with nested children listed under a 'children'
+    * key or in a raw, non-nested format with lft/rgt values.
+    *
+    * This method returns true if the given $data is a nested set in 'natural' form.
+    *
+    * @param $className
+    * @param $data
+    * @return boolean
+    */
+    protected function _hasNaturalNestedSetFormat($className, array &$data)
+    {
+        if (Doctrine::getTable($className)->isTree()) {
+            if (isset($data['NestedSet']) && $data['NestedSet'] == true) {
+                unset($data['NestedSet']);
+                return true;
+            } else {
+                $first = current($data);
+                return array_key_exists('children', $first);
+            }
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Perform the loading of the data from the passed array
+     *
+     * @param string $array
+     * @return void
+     */
+    protected function _loadData(array $array)
+    {
+        $nestedSets = array();
+
+        $specifiedModels = $this->getModels();
+        $rows = array();
+
+        foreach ($array as $className => $data) {
+            if ( ! empty($specifiedModels) && !in_array($className, $specifiedModels)) {
+                continue;
+            }
+
+            // if loaded data is a nested set in natural format, process through _buildNestedSetRows.
+            // 'raw' nested sets and all other models are processed through _buildRows.
+            if ($this->_hasNaturalNestedSetFormat($className, $data)) {
+                $nestedSets[$className][] = $data;
+                $this->_buildNestedSetRows($className, $data);
+            } else {
+                $this->_buildRows($className, $data);
+            }
+        }
+
+        $buildRows = array();
+        foreach ($this->_rows as $className => $classRows) {
+            foreach ($classRows as $rowKey => $row) {
+                $buildRows[$rowKey] = $row;
+                $this->_importedObjects[$rowKey] = new $className();
+                $this->_importedObjects[$rowKey]->state('TDIRTY');
+            }
+        }
+
+        foreach($buildRows as $rowKey => $row) {
+            $this->_processRow($rowKey, $row);
+        }
+
+        // save natural nested set fixture data and unset from _importedObjects
+        foreach ($nestedSets as $className => $sets) {
+            foreach ($sets as $data) {
+                $this->_loadNestedSetData($className, $data);
+            }
+        }
+
+        $objects = array();
+        foreach ($this->_importedObjects as $object) {
+            $className = get_class($object);
+            $objects[$className] = $className;
+        }
+
+        $manager = Doctrine_Manager::getInstance();
+        foreach ($manager as $connection) {
+            $tree = $connection->unitOfWork->buildFlushTree($objects);
+
+            foreach ($tree as $model) {
+                foreach ($this->_importedObjects as $obj) {
+
+                    if ($obj instanceof $model) {
+                        $obj->save();
+                    }
+                }
+            }
+        }
+
+    }
+
+    /**
+     * Load nested set data for models with nested set enabled
+     *
+     * @param string $model
+     * @param string $nestedSetData
+     * @param string $parent
+     * @return void
+     */
+    protected function _loadNestedSetData($model, $nestedSetData, $parent = null)
+    {
+        foreach($nestedSetData AS $rowKey => $nestedSet) {
+            $children = array();
+            $data  = array();
+
+            if (array_key_exists('children', $nestedSet)) {
+                $children = (array) $nestedSet['children'];
+                $children = array_reverse($children, true);
+                unset($nestedSet['children']);
+            }
+
+            $record = $this->_importedObjects[$rowKey];
+            // remove this nested set from _importedObjects so it's not processed in the save routine for normal objects
+            unset($this->_importedObjects[$rowKey]);
+
+            if( ! $parent) {
+                $record->save(); // save, so that createRoot can do: root id = id
+                Doctrine::getTable($model)->getTree()->createRoot($record);
+            } else {
+                $parent->getNode()->addChild($record);
+            }
+
+            if (is_array($children) AND !empty($children)) {
+                $this->_loadNestedSetData($model, $children, $record);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,96 @@
+<?php
+/*
+ *  $Id: DataDict.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_DataDict
+ *
+ * @package     Doctrine
+ * @subpackage  DataDict
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ */
+class Doctrine_DataDict extends Doctrine_Connection_Module
+{
+    /**
+     * Obtain an array of changes that may need to applied
+     *
+     * @param array $current new definition
+     * @param array  $previous old definition
+     * @return array  containing all changes that will need to be applied
+     */
+    public function compareDefinition($current, $previous)
+    {
+        $type = !empty($current['type']) ? $current['type'] : null;
+
+        if ( ! method_exists($this, "_compare{$type}Definition")) {
+            throw new Doctrine_DataDict_Exception('type "'.$current['type'].'" is not yet supported');
+        }
+
+        if (empty($previous['type']) || $previous['type'] != $type) {
+            return $current;
+        }
+
+        $change = $this->{"_compare{$type}Definition"}($current, $previous);
+
+        if ($previous['type'] != $type) {
+            $change['type'] = true;
+        }
+
+        $previous_notnull = !empty($previous['notnull']) ? $previous['notnull'] : false;
+        $notnull = !empty($current['notnull']) ? $current['notnull'] : false;
+        if ($previous_notnull != $notnull) {
+            $change['notnull'] = true;
+        }
+
+        $previous_default = array_key_exists('default', $previous) ? $previous['default'] :
+            ($previous_notnull ? '' : null);
+        $default = array_key_exists('default', $current) ? $current['default'] :
+            ($notnull ? '' : null);
+        if ($previous_default !== $default) {
+            $change['default'] = true;
+        }
+
+        return $change;
+    }
+
+    /**
+     * 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)
+    {
+        // parse booleans
+        if ($value == 'true') {
+            $value = 1;
+        } elseif ($value == 'false') {
+            $value = 0;
+        }
+        return $value;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_DataDict_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  DataDict
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_DataDict_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Firebird.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,219 @@
+<?php
+/*
+ *  $Id: Firebird.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  DataDict
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lorenzo Alberton <l.alberton@quipo.it> (PEAR MDB2 Interbase driver)
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_DataDict_Firebird 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 'varchar':
+            case 'string':
+            case 'array':
+            case 'object':
+            case 'char':
+            case 'text':
+            case 'gzip':
+                $length = !empty($field['length'])
+                    ? $field['length'] : 16777215; // TODO: $this->conn->options['default_text_field_length'];
+
+                $fixed  = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
+
+                return $fixed ? 'CHAR('.$length.')' : 'VARCHAR('.$length.')';
+            case 'clob':
+                return 'BLOB SUB_TYPE 1';
+            case 'blob':
+                return 'BLOB SUB_TYPE 0';
+            case 'integer':
+            case 'int':
+                return 'INT';
+            case 'boolean':
+                return 'SMALLINT';
+            case 'date':
+                return 'DATE';
+            case 'time':
+                return 'TIME';
+            case 'timestamp':
+                return 'TIMESTAMP';
+            case 'float':
+                return 'DOUBLE PRECISION';
+            case 'decimal':
+                $length = !empty($field['length']) ? $field['length'] : 18;
+                $scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
+                return 'DECIMAL('.$length.','.$scale.')';
+        }
+
+        throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] .  '\'.');
+    }
+
+    /**
+     * Maps a native array description of a field to a Doctrine datatype and length
+     *
+     * @param array  $field native field description
+     * @return array containing the various possible types, length, sign, fixed
+     */
+    public function getPortableDeclaration($field)
+    {
+        $length  = (isset($field['length']) && $field['length'] > 0) ? $field['length'] : null;
+
+        $type = array();
+        $unsigned = $fixed = null;
+        $dbType = strtolower($field['type']);
+        $field['field_sub_type'] = !empty($field['field_sub_type'])
+            ? strtolower($field['field_sub_type']) : null;
+
+        if ( ! isset($field['name'])) {
+            $field['name'] = '';
+        }
+
+        switch ($dbType) {
+            case 'smallint':
+            case 'integer':
+            case 'int64':
+                //these may be 'numeric' or 'decimal'
+                if (isset($field['field_sub_type'])) {
+                    $field['type'] = $field['field_sub_type'];
+                    return $this->getPortableDeclaration($field);
+                }
+            case 'bigint':
+            case 'quad':
+                $type[] = 'integer';
+                if ($length == '1') {
+                    $type[] = 'boolean';
+                    if (preg_match('/^(is|has)/', $field['name'])) {
+                        $type = array_reverse($type);
+                    }
+                }
+                break;
+            case 'varchar':
+                $fixed = false;
+            case 'char':
+            case 'cstring':
+                $type[] = 'string';
+                if ($length == '1') {
+                    $type[] = 'boolean';
+                    if (preg_match('/^(is|has)/', $field['name'])) {
+                        $type = array_reverse($type);
+                    }
+                }
+                if ($fixed !== false) {
+                    $fixed = true;
+                }
+                break;
+            case 'date':
+                $type[] = 'date';
+                $length = null;
+                break;
+            case 'timestamp':
+                $type[] = 'timestamp';
+                $length = null;
+                break;
+            case 'time':
+                $type[] = 'time';
+                $length = null;
+                break;
+            case 'float':
+            case 'double':
+            case 'double precision':
+            case 'd_float':
+                $type[] = 'float';
+                break;
+            case 'decimal':
+            case 'numeric':
+                $type[] = 'decimal';
+                break;
+            case 'blob':
+                $type[] = ($field['field_sub_type'] == 'text') ? 'clob' : 'blob';
+                $length = null;
+                break;
+            default:
+                throw new Doctrine_DataDict_Exception('unknown database attribute type: '.$dbType);
+        }
+
+        return array('type'     => $type,
+                     'length'   => $length,
+                     'unsigned' => $unsigned,
+                     'fixed'    => $fixed);
+    }
+
+    /**
+     * 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;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Informix.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,112 @@
+<?php
+/*
+ *  $Id: Informix.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  DataDict
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_DataDict_Informix 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 'char':
+            case 'enum':
+                $field['length'] = isset($field['length']) && $field['length'] ? $field['length']:255;
+            case 'varchar':
+            case 'array':
+            case 'object':
+            case 'string':
+                if (empty($field['length']) && array_key_exists('default', $field)) {
+                    $field['length'] = $this->conn->varchar_max_length;
+                }
+
+                $length = ( ! empty($field['length'])) ? $field['length'] : false;
+                $fixed  = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
+
+                return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR(255)')
+                    : ($length ? 'VARCHAR('.$length.')' : 'NVARCHAR');
+            case 'clob':
+                return 'TEXT';
+            case 'blob':
+                return 'BLOB';
+            case 'integer':
+                if ( ! empty($field['length'])) {
+                    $length = $field['length'];
+                    if ($length <= 1) {
+                        return 'SMALLINT';
+                    } elseif ($length == 2) {
+                        return 'SMALLINT';
+                    } elseif ($length == 3 || $length == 4) {
+                        return 'INTEGER';
+                    } elseif ($length > 4) {
+                        return 'DECIMAL(20)';
+                    }
+                }
+                return 'INT';
+            case 'boolean':
+                return 'SMALLINT';
+            case 'date':
+                return 'DATE';
+            case 'time':
+                return 'DATETIME YEAR TO SECOND';
+            case 'timestamp':
+                return 'DATETIME';
+            case 'float':
+                return 'FLOAT';
+            case 'decimal':
+                return 'DECIMAL';
+        }
+        throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] .  '\'.');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Mssql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,254 @@
+<?php
+/*
+ *  $Id: Mssql.php 5848 2009-06-09 08:15:56Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  DataDict
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @author      Frank M. Kromann <frank@kromann.info> (PEAR MDB2 Mssql driver)
+ * @author      David Coallier <davidc@php.net> (PEAR MDB2 Mssql driver)
+ * @version     $Revision: 5848 $
+ * @link        www.phpdoctrine.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->options['default_text_field_length'].')')
+                    : ($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 '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::ATTR_DECIMAL_PLACES);
+                return 'DECIMAL('.$length.','.$scale.')';
+        }
+
+        throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] .  '\'.');
+    }
+
+    /**
+     * 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;
+            default:
+                throw new Doctrine_DataDict_Exception('unknown database attribute type: '.$db_type);
+        }
+
+        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;
+            }
+
+            $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 '" . $field['comment'] . "'" : '';
+
+        $name = $this->conn->quoteIdentifier($name, true);
+
+        return $name . ' ' . $this->getNativeDeclaration($field) . $unsigned 
+            . $default . $notnull . $autoinc . $comment;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Mysql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,499 @@
+<?php
+/*
+ *  $Id: Mysql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  DataDict
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.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::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 'varchar':
+            case 'array':
+            case 'object':
+            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 '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':
+            case 'double':
+                return 'DOUBLE';
+            case 'decimal':
+                $length = !empty($field['length']) ? $field['length'] : 18;
+                $scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
+                return 'DECIMAL('.$length.','.$scale.')';
+            case 'bit':
+                return 'BIT';
+        }
+        throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] .  '\'.');
+    }
+
+    /**
+     * 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('(), ') ? strtok('(), '):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:
+                throw new Doctrine_DataDict_Exception('unknown database attribute type: ' . $dbType);
+        }
+
+        $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)
+    {
+        $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']));
+        }
+        /**
+        elseif (empty($field['notnull'])) {
+            $default = ' DEFAULT NULL';
+        }
+        */
+
+        $notnull  = (isset($field['notnull'])  && $field['notnull'])  ? ' NOT NULL' : '';
+        $unsigned = (isset($field['unsigned']) && $field['unsigned']) ? ' UNSIGNED' : '';
+        $comment  = (isset($field['comment']) && $field['comment']) 
+            ? " COMMENT '" . $field['comment'] . "'" : '';
+
+        $name = $this->conn->quoteIdentifier($name, true);
+
+        return $name . ' ' . $this->getNativeDeclaration($field) . $unsigned 
+            . $default . $notnull . $autoinc . $comment;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Oracle.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,201 @@
+<?php
+/*
+ *  $Id: Oracle.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  DataDict
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_DataDict_Oracle 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(array $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 'string':
+            case 'array':
+            case 'object':
+            case 'gzip':
+            case 'char':
+            case 'varchar':
+                $length = !empty($field['length']) ? $field['length'] : false;
+
+                $fixed  = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
+                
+                if ($length && $length <= $this->conn->varchar2_max_length) {
+                    return $fixed ? 'CHAR('.$length.')' : 'VARCHAR2('.$length.')';
+                }
+            case 'clob':
+                return 'CLOB';
+            case 'blob':
+                return 'BLOB';
+            case 'integer':
+            case 'int':
+                if ( ! empty($field['length']) && $field['length'] <= $this->conn->number_max_precision)  {
+                    return 'NUMBER('.$field['length'].')';
+                }
+                return 'INT';
+            case 'boolean':
+                return 'NUMBER(1)';
+            case 'date':
+            case 'time':
+            case 'timestamp':
+                return 'DATE';
+            case 'float':
+            case 'double':
+                return 'NUMBER';
+            case 'decimal':
+                $scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
+                return 'NUMBER(*,'.$scale.')';
+            default:
+        }
+        throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] .  '\'.');
+    }
+
+    /**
+     * Maps a native array description of a field to a doctrine datatype and length
+     *
+     * @param array  $field native field description
+     * @return array containing the various possible types, length, sign, fixed
+     * @throws Doctrine_DataDict_Oracle_Exception
+     */
+    public function getPortableDeclaration(array $field)
+    {
+        if ( ! isset($field['data_type'])) {
+            throw new Doctrine_DataDict_Exception('Native oracle definition must have a data_type key specified');
+        }
+        
+        $dbType = strtolower($field['data_type']);
+        $type = array();
+        $length = $unsigned = $fixed = null;
+        if ( ! empty($field['data_length'])) {
+            $length = $field['data_length'];
+        }
+
+        if ( ! isset($field['column_name'])) {
+            $field['column_name'] = '';
+        }
+
+        switch ($dbType) {
+            case 'integer':
+            case 'pls_integer':
+            case 'binary_integer':
+                $type[] = 'integer';
+                if ($length == '1') {
+                    $type[] = 'boolean';
+                    if (preg_match('/^(is|has)/', $field['column_name'])) {
+                        $type = array_reverse($type);
+                    }
+                }
+                break;
+            case 'varchar':
+            case 'varchar2':
+            case 'nvarchar2':
+                $fixed = false;
+            case 'char':
+            case 'nchar':
+                $type[] = 'string';
+                if ($length == '1') {
+                    $type[] = 'boolean';
+                    if (preg_match('/^(is|has)/', $field['column_name'])) {
+                        $type = array_reverse($type);
+                    }
+                }
+                if ($fixed !== false) {
+                    $fixed = true;
+                }
+                break;
+            case 'date':
+            case 'timestamp':
+                $type[] = 'timestamp';
+                $length = null;
+                break;
+            case 'float':
+                $type[] = 'float';
+                break;
+            case 'number':
+                if ( ! empty($field['data_scale'])) {
+                    $type[] = 'decimal';
+                } else {
+                    $type[] = 'integer';
+                    if ($length == '1') {
+                        $type[] = 'boolean';
+                        if (preg_match('/^(is|has)/', $field['column_name'])) {
+                            $type = array_reverse($type);
+                        }
+                    }
+                }
+                break;
+            case 'long':
+                $type[] = 'string';
+            case 'clob':
+            case 'nclob':
+                $type[] = 'clob';
+                break;
+            case 'blob':
+            case 'raw':
+            case 'long raw':
+            case 'bfile':
+                $type[] = 'blob';
+                $length = null;
+            break;
+            case 'rowid':
+            case 'urowid':
+            default:
+                throw new Doctrine_DataDict_Exception('unknown database attribute type: ' . $dbType);
+        }
+
+        return array('type'     => $type,
+                     'length'   => $length,
+                     'unsigned' => $unsigned,
+                     'fixed'    => $fixed);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Pgsql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,655 @@
+<?php
+/*
+ *  $Id: Pgsql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  DataDict
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Paul Cooper <pgc@ucecom.com>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.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.');
+        }
+        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->options['default_text_field_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 without time zone';
+            case 'timestamp':
+                return 'TIMESTAMP without time zone';
+            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::ATTR_DECIMAL_PLACES);
+                return 'NUMERIC('.$length.','.$scale.')';
+        }
+        throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] .  '\'.');
+    }
+
+    /**
+     * 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']);
+
+        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 '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 '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:
+                throw new Doctrine_DataDict_Exception('unknown database attribute type: '.$dbType);
+        }
+
+        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 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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataDict/Sqlite.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,320 @@
+<?php
+/*
+ *  $Id: Sqlite.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  DataDict
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_DataDict_Sqlite 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.
+     * @author Lukas Smith (PEAR MDB2 library)
+     * @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.');
+        }
+        switch ($field['type']) {
+            case 'enum':
+                $field['length'] = isset($field['length']) && $field['length'] ? $field['length']:255;
+            case 'text':
+            case 'object':
+            case 'array':
+            case 'string':
+            case 'char':
+            case 'gzip':
+            case 'varchar':
+                $length = (isset($field['length']) && $field['length']) ? $field['length'] : null;
+
+                $fixed  = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
+
+                return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$this->conn->getAttribute(Doctrine::ATTR_DEFAULT_TEXTFLD_LENGTH).')')
+                    : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
+            case 'clob':
+                if ( ! empty($field['length'])) {
+                    $length = $field['length'];
+                    if ($length <= 255) {
+                        return 'TINYTEXT';
+                    } elseif ($length <= 65535) {
+                        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 <= 65535) {
+                        return 'BLOB';
+                    } elseif ($length <= 16777215) {
+                        return 'MEDIUMBLOB';
+                    }
+                }
+                return 'LONGBLOB';
+            case 'integer':
+            case 'boolean':
+            case 'int':
+                return 'INTEGER';
+            case 'date':
+                return 'DATE';
+            case 'time':
+                return 'TIME';
+            case 'timestamp':
+                return 'DATETIME';
+            case 'float':
+            case 'double':
+                return 'DOUBLE';//($this->conn->options['fixed_float'] ? '('.
+                    //($this->conn->options['fixed_float']+2).','.$this->conn->options['fixed_float'].')' : '');
+            case 'decimal':
+                $length = !empty($field['length']) ? $field['length'] : 18;
+                $scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
+                return 'DECIMAL('.$length.','.$scale.')';
+        }
+        throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] .  '\'.');
+    }
+
+    /**
+     * Maps a native array description of a field to 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)
+    {
+        $e = explode('(', $field['type']);
+        $field['type'] = $e[0];
+        if (isset($e[1])) {
+            $length = trim($e[1], ')');
+            $field['length'] = $length;
+        }
+
+        $dbType = strtolower($field['type']);
+
+        if ( ! $dbType) {
+            throw new Doctrine_DataDict_Exception('Missing "type" from field definition');
+        }
+
+        $length = (isset($field['length'])) ? $field['length'] : null;
+        $unsigned = (isset($field['unsigned'])) ? $field['unsigned'] : null;
+        $fixed = null;
+        $type = array();
+
+        if ( ! isset($field['name'])) {
+            $field['name'] = '';
+        }
+
+        switch ($dbType) {
+            case 'boolean':
+                $type[] = 'boolean';
+                break;
+            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':
+            case 'serial':
+                $type[] = 'integer';
+                $unsigned = preg_match('/ unsigned/i', $field['type']);
+                $length = 4;
+                break;
+            case 'bigint':
+            case 'bigserial':
+                $type[] = 'integer';
+                $unsigned = preg_match('/ unsigned/i', $field['type']);
+                $length = 8;
+                break;
+            case 'clob':
+            case 'tinytext':
+            case 'mediumtext':
+            case 'longtext':
+            case 'text':
+            case 'varchar':
+            case 'varchar2':
+            case 'nvarchar':
+            case 'ntext':
+            case 'image':
+            case 'nchar':
+                $fixed = false;
+            case 'char':
+                $type[] = 'text';
+                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 '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';
+                $length = null;
+                break;
+            case 'decimal':
+            case 'numeric':
+                $type[] = 'decimal';
+                $length = null;
+                break;
+            case 'tinyblob':
+            case 'mediumblob':
+            case 'longblob':
+            case 'blob':
+                $type[] = 'blob';
+                $length = null;
+                break;
+            case 'year':
+                $type[] = 'integer';
+                $type[] = 'date';
+                $length = null;
+                break;
+            default:
+                throw new Doctrine_DataDict_Exception('unknown database attribute type: '.$dbType);
+        }
+
+        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 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.
+     * @access protected
+     */
+    public function getIntegerDeclaration($name, array $field)
+    {
+        $default = $autoinc = '';
+        $type    = $this->getNativeDeclaration($field);
+
+        $autoincrement = isset($field['autoincrement']) && $field['autoincrement'];
+
+        if ($autoincrement) {
+            $autoinc = ' PRIMARY KEY AUTOINCREMENT';
+            $type    = 'INTEGER';
+        } 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'], $field['type']));
+        }/**
+        elseif (empty($field['notnull'])) {
+            $default = ' DEFAULT NULL';
+        }
+        */
+
+        $notnull  = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : '';
+
+        // sqlite does not support unsigned attribute for autoinremented fields
+        $unsigned = (isset($field['unsigned']) && $field['unsigned'] && !$autoincrement) ? ' UNSIGNED' : '';
+
+        $name = $this->conn->quoteIdentifier($name, true);
+        return $name . ' ' . $type . $unsigned . $default . $notnull . $autoinc;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/DataType.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,49 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+ 
+/**
+ * Doctrine_DataType
+ *
+ * @package     Doctrine
+ * @subpackage  DataType
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1986 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_DataType
+{
+    public function __construct()
+    {
+        
+    }
+    
+    public function getName()
+    {
+        
+    }
+    
+    public function getDefaultLength()
+    {
+        
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Event.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,354 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Event
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @package     Doctrine
+ * @subpackage  Event
+ * @link        www.phpdoctrine.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 $_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->_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;
+    }
+
+    /**
+     * getInvoker
+     * returns the handler that invoked this event
+     *
+     * @return 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 mixed
+     */
+    public function getElapsedSecs()
+    {
+        if (is_null($this->_endedMicrotime)) {
+            return false;
+        }
+        return ($this->_endedMicrotime - $this->_startedMicrotime);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,119 @@
+<?php
+/*
+ *  $Id: EventListener.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_EventListener     all event listeners extend this base class
+ *                            the empty methods allow child classes to only implement the methods they need to implement
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @package     Doctrine
+ * @subpackage  EventListener
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_EventListener implements Doctrine_EventListener_Interface
+{
+    public function preClose(Doctrine_Event $event)
+    { }
+    public function postClose(Doctrine_Event $event)
+    { }
+
+    public function onCollectionDelete(Doctrine_Collection $collection)
+    { }
+    public function onPreCollectionDelete(Doctrine_Collection $collection)
+    { }
+
+    public function onOpen(Doctrine_Connection $connection)
+    { }
+
+    public function preTransactionCommit(Doctrine_Event $event)
+    { }
+    public function postTransactionCommit(Doctrine_Event $event)
+    { }
+
+    public function preTransactionRollback(Doctrine_Event $event)
+    { }
+    public function postTransactionRollback(Doctrine_Event $event)
+    { }
+
+    public function preTransactionBegin(Doctrine_Event $event)
+    { }
+    public function postTransactionBegin(Doctrine_Event $event)
+    { }
+
+
+    public function preSavepointCommit(Doctrine_Event $event)
+    { }
+    public function postSavepointCommit(Doctrine_Event $event)
+    { }
+
+    public function preSavepointRollback(Doctrine_Event $event)
+    { }
+    public function postSavepointRollback(Doctrine_Event $event)
+    { }
+
+    public function preSavepointCreate(Doctrine_Event $event)
+    { }
+    public function postSavepointCreate(Doctrine_Event $event)
+    { }
+
+    public function postConnect(Doctrine_Event $event)
+    { }
+    public function preConnect(Doctrine_Event $event)
+    { }
+
+    public function preQuery(Doctrine_Event $event)
+    { }
+    public function postQuery(Doctrine_Event $event)
+    { }
+
+    public function prePrepare(Doctrine_Event $event)
+    { }
+    public function postPrepare(Doctrine_Event $event)
+    { }
+
+    public function preExec(Doctrine_Event $event)
+    { }
+    public function postExec(Doctrine_Event $event)
+    { }
+
+    public function preError(Doctrine_Event $event)
+    { }
+    public function postError(Doctrine_Event $event)
+    { }
+
+    public function preFetch(Doctrine_Event $event)
+    { }
+    public function postFetch(Doctrine_Event $event)
+    { }
+
+    public function preFetchAll(Doctrine_Event $event)
+    { }
+    public function postFetchAll(Doctrine_Event $event)
+    { }
+
+    public function preStmtExecute(Doctrine_Event $event)
+    { }
+    public function postStmtExecute(Doctrine_Event $event)
+    { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener/Chain.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,405 @@
+<?php
+/*
+ *  $Id: Chain.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_EventListener_Chain
+ * this class represents a chain of different listeners,
+ * useful for having multiple listeners listening the events at the same time
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @package     Doctrine
+ * @subpackage  EventListener
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_EventListener_Chain extends Doctrine_Access implements Doctrine_EventListener_Interface
+{
+    /**
+     * @var array $listeners        an array containing all listeners
+     */
+    protected $_listeners = array();
+
+    /**
+     * add
+     * adds a listener to the chain of listeners
+     *
+     * @param object $listener
+     * @param string $name
+     * @return void
+     */
+    public function add($listener, $name = null)
+    {
+        if ( ! ($listener instanceof Doctrine_EventListener_Interface) &&
+             ! ($listener instanceof Doctrine_Overloadable)) {
+            
+            throw new Doctrine_EventListener_Exception("Couldn't add eventlistener. EventListeners should implement either Doctrine_EventListener_Interface or Doctrine_Overloadable");
+        }
+        if ($name === null) {
+            $this->_listeners[] = $listener;
+        } else {
+            $this->_listeners[$name] = $listener;
+        }
+    }
+
+    /**
+     * returns a Doctrine_EventListener on success
+     * and null on failure
+     *
+     * @param mixed $key
+     * @return mixed
+     */
+    public function get($key)
+    {
+        if ( ! isset($this->_listeners[$key])) {
+            return null;
+        }
+        return $this->_listeners[$key];
+    }
+
+    /**
+     * set
+     *
+     * @param mixed $key
+     * @param Doctrine_EventListener $listener
+     * @return void
+     */
+    public function set($key, $listener)
+    {
+        $this->_listeners[$key] = $listener;
+    }
+
+    /**
+     * onLoad
+     * an event invoked when Doctrine_Record is being loaded from database
+     *
+     * @param Doctrine_Record $record
+     * @return void
+     */
+    public function onLoad(Doctrine_Record $record)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->onLoad($record);
+        }
+    }
+
+    /**
+     * onPreLoad
+     * an event invoked when Doctrine_Record is being loaded
+     * from database but not yet initialized
+     *
+     * @param Doctrine_Record $record
+     * @return void
+     */
+    public function onPreLoad(Doctrine_Record $record)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->onPreLoad($record);
+        }
+    }
+
+    /**
+     * onSleep
+     * an event invoked when Doctrine_Record is serialized
+     *
+     * @param Doctrine_Record $record
+     * @return void
+     */
+    public function onSleep(Doctrine_Record $record)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->onSleep($record);
+        }
+    }
+
+    /**
+     * onWakeUp
+     * an event invoked when Doctrine_Record is unserialized
+     *
+     * @param Doctrine_Record $record
+     * @return void
+     */
+    public function onWakeUp(Doctrine_Record $record)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->onWakeUp($record);
+        }
+    }
+
+    /**
+     * postClose
+     * an event invoked after Doctrine_Connection is closed
+     *
+     * @param Doctrine_Event $event
+     * @return void
+     */
+    public function postClose(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postClose($event);
+        }
+    }
+
+    /**
+     * preClose
+     * an event invoked before Doctrine_Connection is closed
+     *
+     * @param Doctrine_Event $event
+     * @return void
+     */
+    public function preClose(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preClose($event);
+        }
+    }
+
+    /**
+     * onOpen
+     * an event invoked after Doctrine_Connection is opened
+     *
+     * @param Doctrine_Connection $connection
+     * @return void
+     */
+    public function onOpen(Doctrine_Connection $connection)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->onOpen($connection);
+        }
+    }
+
+    /**
+     * onTransactionCommit
+     * an event invoked after a Doctrine_Connection transaction is committed
+     *
+     * @param Doctrine_Event $event
+     * @return void
+     */
+    public function postTransactionCommit(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postTransactionCommit($event);
+        }
+    }
+
+    /**
+     * onPreTransactionCommit
+     * an event invoked before a Doctrine_Connection transaction is committed
+     *
+     * @param Doctrine_Event $event
+     * @return void
+     */
+    public function preTransactionCommit(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preTransactionCommit($event);
+        }
+    }
+
+    /**
+     * onTransactionRollback
+     * an event invoked after a Doctrine_Connection transaction is being rolled back
+     *
+     * @param Doctrine_Event $event
+     * @return void
+     */
+    public function postTransactionRollback(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postTransactionRollback($event);
+        }
+    }
+
+    /**
+     * onPreTransactionRollback
+     * an event invoked before a Doctrine_Connection transaction is being rolled back
+     *
+     * @param Doctrine_Event $event
+     * @return void
+     */
+    public function preTransactionRollback(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preTransactionRollback($event);
+        }
+    }
+
+    /**
+     * onTransactionBegin
+     * an event invoked after a Doctrine_Connection transaction has been started
+     *
+     * @param Doctrine_Event $event
+     * @return void
+     */
+    public function postTransactionBegin(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postTransactionBegin($event);
+        }
+    }
+
+    /**
+     * onTransactionBegin
+     * an event invoked before a Doctrine_Connection transaction is being started
+     *
+     * @param Doctrine_Event $event
+     * @return void
+     */
+    public function preTransactionBegin(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preTransactionBegin($event);
+        }
+    }
+
+    /**
+     * onCollectionDelete
+     * an event invoked after a Doctrine_Collection is being deleted
+     *
+     * @param Doctrine_Collection $collection
+     * @return void
+     */
+    public function onCollectionDelete(Doctrine_Collection $collection)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->onCollectionDelete($collection);
+        }
+    }
+
+    /**
+     * onCollectionDelete
+     * an event invoked after a Doctrine_Collection is being deleted
+     *
+     * @param Doctrine_Collection $collection
+     * @return void
+     */
+    public function onPreCollectionDelete(Doctrine_Collection $collection)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->onPreCollectionDelete($collection);
+        }
+    }
+    public function postConnect(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postConnect($event);
+        }
+    }
+    public function preConnect(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preConnect($event);
+        }
+    }
+    public function preQuery(Doctrine_Event $event)
+    { 
+        foreach ($this->_listeners as $listener) {
+            $listener->preQuery($event);
+        }
+    }
+    public function postQuery(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postQuery($event);
+        }
+    }
+
+    public function prePrepare(Doctrine_Event $event)
+    { 
+        foreach ($this->_listeners as $listener) {
+            $listener->prePrepare($event);
+        }
+    }
+    public function postPrepare(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postPrepare($event);
+        }
+    }
+
+    public function preExec(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preExec($event);
+        }
+    }
+    public function postExec(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postExec($event);
+        }
+    }
+
+    public function preError(Doctrine_Event $event)
+    { 
+        foreach ($this->_listeners as $listener) {
+            $listener->preError($event);
+        }
+    }
+    public function postError(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postError($event);
+        }
+    }
+
+    public function preFetch(Doctrine_Event $event)
+    { 
+        foreach ($this->_listeners as $listener) {
+            $listener->preFetch($event);
+        }
+    }
+    public function postFetch(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postFetch($event);
+        }
+    }
+
+    public function preFetchAll(Doctrine_Event $event)
+    { 
+        foreach ($this->_listeners as $listener) {
+            $listener->preFetchAll($event);
+        }
+    }
+
+    public function postFetchAll(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postFetchAll($event);
+        }
+    }
+
+    public function preStmtExecute(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preStmtExecute($event);
+        }
+    }
+
+    public function postStmtExecute(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postStmtExecute($event);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 1344 2007-05-12 23:27:16Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_EventListener_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  EventListener
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1344 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_EventListener_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/EventListener/Interface.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,68 @@
+<?php
+/*
+ *  $Id: Interface.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_EventListener     all event listeners extend this base class
+ *                            the empty methods allow child classes to only implement the methods they need to implement
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @package     Doctrine
+ * @subpackage  EventListener
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+interface Doctrine_EventListener_Interface
+{
+    public function preTransactionCommit(Doctrine_Event $event);
+    public function postTransactionCommit(Doctrine_Event $event);
+
+    public function preTransactionRollback(Doctrine_Event $event);
+    public function postTransactionRollback(Doctrine_Event $event);
+
+    public function preTransactionBegin(Doctrine_Event $event);
+    public function postTransactionBegin(Doctrine_Event $event);
+
+    public function postConnect(Doctrine_Event $event);
+    public function preConnect(Doctrine_Event $event);
+
+    public function preQuery(Doctrine_Event $event);
+    public function postQuery(Doctrine_Event $event);
+
+    public function prePrepare(Doctrine_Event $event);
+    public function postPrepare(Doctrine_Event $event);
+
+    public function preExec(Doctrine_Event $event);
+    public function postExec(Doctrine_Event $event);
+
+    public function preError(Doctrine_Event $event);
+    public function postError(Doctrine_Event $event);
+
+    public function preFetch(Doctrine_Event $event);
+    public function postFetch(Doctrine_Event $event);
+
+    public function preFetchAll(Doctrine_Event $event);
+    public function postFetchAll(Doctrine_Event $event);
+
+    public function preStmtExecute(Doctrine_Event $event);
+    public function postStmtExecute(Doctrine_Event $event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,92 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Exception
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Exception extends Exception
+{ 
+    /**
+     * @var array $_errorMessages       an array of error messages
+     */
+    protected static $_errorMessages = array(
+                Doctrine::ERR                    => 'unknown error',
+                Doctrine::ERR_ALREADY_EXISTS     => 'already exists',
+                Doctrine::ERR_CANNOT_CREATE      => 'can not create',
+                Doctrine::ERR_CANNOT_ALTER       => 'can not alter',
+                Doctrine::ERR_CANNOT_REPLACE     => 'can not replace',
+                Doctrine::ERR_CANNOT_DELETE      => 'can not delete',
+                Doctrine::ERR_CANNOT_DROP        => 'can not drop',
+                Doctrine::ERR_CONSTRAINT         => 'constraint violation',
+                Doctrine::ERR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint',
+                Doctrine::ERR_DIVZERO            => 'division by zero',
+                Doctrine::ERR_INVALID            => 'invalid',
+                Doctrine::ERR_INVALID_DATE       => 'invalid date or time',
+                Doctrine::ERR_INVALID_NUMBER     => 'invalid number',
+                Doctrine::ERR_MISMATCH           => 'mismatch',
+                Doctrine::ERR_NODBSELECTED       => 'no database selected',
+                Doctrine::ERR_NOSUCHFIELD        => 'no such field',
+                Doctrine::ERR_NOSUCHTABLE        => 'no such table',
+                Doctrine::ERR_NOT_CAPABLE        => 'Doctrine backend not capable',
+                Doctrine::ERR_NOT_FOUND          => 'not found',
+                Doctrine::ERR_NOT_LOCKED         => 'not locked',
+                Doctrine::ERR_SYNTAX             => 'syntax error',
+                Doctrine::ERR_UNSUPPORTED        => 'not supported',
+                Doctrine::ERR_VALUE_COUNT_ON_ROW => 'value count on row',
+                Doctrine::ERR_INVALID_DSN        => 'invalid DSN',
+                Doctrine::ERR_CONNECT_FAILED     => 'connect failed',
+                Doctrine::ERR_NEED_MORE_DATA     => 'insufficient data supplied',
+                Doctrine::ERR_EXTENSION_NOT_FOUND=> 'extension not found',
+                Doctrine::ERR_NOSUCHDB           => 'no such database',
+                Doctrine::ERR_ACCESS_VIOLATION   => 'insufficient permissions',
+                Doctrine::ERR_LOADMODULE         => 'error while including on demand module',
+                Doctrine::ERR_TRUNCATED          => 'truncated',
+                Doctrine::ERR_DEADLOCK           => 'deadlock detected',
+            );
+
+    /**
+     * Return a textual error message for a Doctrine error code
+     *
+     * @param   int|array   integer error code,
+     *                           null to get the current error code-message map,
+     *                           or an array with a new error code-message map
+     *
+     * @return  string  error message
+     */
+    public function errorMessage($value = null)
+    {
+        if (is_null($value)) {
+            return self::$_errorMessages;
+        }
+
+        return isset(self::$_errorMessages[$value]) ?
+           self::$_errorMessages[$value] : self::$_errorMessages[Doctrine::ERR];
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,1377 @@
+<?php
+/*
+ *  $Id: Export.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Export
+ *
+ * @package     Doctrine
+ * @subpackage  Export
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+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)
+    {
+        $this->conn->execute($this->dropDatabaseSql($database));
+    }
+
+    /**
+     * 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, $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::ATTR_PORTABILITY) & Doctrine::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($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::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::filterInvalidModels(Doctrine::loadModels($directory));
+        } else {
+            $models = Doctrine::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;
+                 }
+             }
+         }
+
+         // 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::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::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::ERR_ALREADY_EXISTS
+     *                                          occurred during the create table operation
+     * @param array $classes
+     * @return void
+     */
+    public function exportClassesSql(array $classes)
+    {
+        $models = Doctrine::filterInvalidModels($classes);
+        
+        $sql = array();
+        
+        foreach ($models as $name) {
+            try {
+                $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);
+                }
+
+                $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::ATTR_EXPORT) & Doctrine::EXPORT_PLUGINS) {
+                    $sql = array_merge($sql, $this->exportGeneratorsSql($table));
+                }
+            } catch (Exception $e) {
+                throw new Doctrine_Export_Exception("While exporting model class '$name' to SQL: " . $e->getMessage());
+            }
+
+        }
+        
+        $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::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::filterInvalidModels(Doctrine::loadModels($directory));
+        } else {
+            $models = Doctrine::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::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::ERR_ALREADY_EXISTS) {
+                throw $e;
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Export_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Export
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Export_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Firebird.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,551 @@
+<?php
+/*
+ *  $Id: Firebird.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Export_Sqlite
+ *
+ * @package     Doctrine
+ * @subpackage  Export
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @author      Lorenzo Alberton <l.alberton@quipo.it> (PEAR MDB2 Interbase driver)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Export_Firebird extends Doctrine_Export
+{
+    /**
+     * create a new database
+     *
+     * @param string $name  name of the database that should be created
+     * @return void
+     */
+    public function createDatabase($name)
+    {
+        throw new Doctrine_Export_Exception(
+                'PHP Interbase API does not support direct queries. You have to ' .
+                'create the db manually by using isql command or a similar program');
+    }
+
+    /**
+     * drop an existing database
+     *
+     * @param string $name  name of the database that should be dropped
+     * @return void
+     */
+    public  function dropDatabase($name)
+    {
+        throw new Doctrine_Export_Exception(
+                'PHP Interbase API does not support direct queries. You have ' .
+                'to drop the db manually by using isql command or a similar program');
+    }
+
+    /**
+     * add an autoincrement sequence + trigger
+     *
+     * @param string $name  name of the PK field
+     * @param string $table name of the table
+     * @param string $start start value for the sequence
+     * @return void
+     */
+    public function _makeAutoincrement($name, $table, $start = null)
+    {
+        if (is_null($start)) {
+            $this->conn->beginTransaction();
+            $query = 'SELECT MAX(' . $this->conn->quoteIdentifier($name, true) . ') FROM ' . $this->conn->quoteIdentifier($table, true);
+            $start = $this->conn->fetchOne($query, 'integer');
+
+            ++$start;
+            $result = $this->createSequence($table, $start);
+            $this->conn->commit();
+        } else {
+            $result = $this->createSequence($table, $start);
+        }
+
+        $sequence_name = $this->conn->formatter->getSequenceName($table);
+        $trigger_name  = $this->conn->quoteIdentifier($table . '_AUTOINCREMENT_PK', true);
+
+        $table = $this->conn->quoteIdentifier($table, true);
+        $name  = $this->conn->quoteIdentifier($name,  true);
+
+        $triggerSql = 'CREATE TRIGGER ' . $trigger_name . ' FOR ' . $table
+                    . ' ACTIVE BEFORE INSERT POSITION 0 AS'
+                    . ' BEGIN'
+                    . ' IF (NEW.' . $name . ' IS NULL OR NEW.' . $name . ' = 0) THEN'
+                    . ' NEW.' . $name . ' = GEN_ID('.$sequence_name.', 1)'
+                    . ' END';
+        $result = $this->conn->exec($triggerSql);
+
+        // TODO ? $this->_silentCommit();
+
+        return $result;
+    }
+
+    /**
+     * drop an existing autoincrement sequence + trigger
+     *
+     * @param string $table name of the table
+     * @return void
+     */
+    public function _dropAutoincrement($table)
+    {
+
+        $result = $this->dropSequence($table);
+
+        //remove autoincrement trigger associated with the table
+        $table = $this->conn->quote(strtoupper($table));
+        $triggerName = $this->conn->quote(strtoupper($table) . '_AUTOINCREMENT_PK');
+
+        return $this->conn->exec("DELETE FROM RDB\$TRIGGERS WHERE UPPER(RDB\$RELATION_NAME)=" . $table . " AND UPPER(RDB\$TRIGGER_NAME)=" . $triggerName);
+    }
+
+    /**
+     * 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.
+     *
+     *                        Example
+     *                        array(
+     *
+     *                            'id' => array(
+     *                                'type' => 'integer',
+     *                                'unsigned' => 1,
+     *                                'notnull' => 1,
+     *                                'default' => 0,
+     *                            ),
+     *                            'name' => array(
+     *                                'type' => 'text',
+     *                                'length' => 12,
+     *                            ),
+     *                            'description' => array(
+     *                                'type' => 'text',
+     *                                'length' => 12,
+     *                            )
+     *                        );
+     * @param array $options  An associative array of table options:
+     *
+     * @return void
+     */
+    public function createTable($name, array $fields, array $options = array()) {
+        parent::createTable($name, $fields, $options);
+
+        // TODO ? $this->_silentCommit();
+        foreach ($fields as $field_name => $field) {
+            if ( ! empty($field['autoincrement'])) {
+                //create PK constraint
+                $pk_definition = array(
+                    'fields' => array($field_name => array()),
+                    'primary' => true,
+                );
+                //$pk_name = $name.'_PK';
+                $pk_name = null;
+                $result = $this->createConstraint($name, $pk_name, $pk_definition);
+
+                //create autoincrement sequence + trigger
+                return $this->_makeAutoincrement($field_name, $name, 1);
+            }
+        }
+    }
+
+    /**
+     * Check if planned changes are supported
+     *
+     * @param string $name name of the database that should be dropped
+     * @return void
+     */
+    public function checkSupportedChanges(&$changes)
+    {
+        foreach ($changes as $change_name => $change) {
+            switch ($change_name) {
+                case 'notnull':
+                    throw new Doctrine_DataDict_Exception('it is not supported changes to field not null constraint');
+                case 'default':
+                    throw new Doctrine_DataDict_Exception('it is not supported changes to field default value');
+                case 'length':
+                    /*
+                    return throw new Doctrine_DataDict_Firebird_Exception('it is not supported changes to field default length');
+                    */
+                case 'unsigned':
+                case 'type':
+                case 'declaration':
+                case 'definition':
+                    break;
+                default:
+                    throw new Doctrine_DataDict_Exception('it is not supported change of type' . $change_name);
+            }
+        }
+        return true;
+    }
+
+    /**
+     * drop an existing table
+     *
+     * @param string $name name of the table that should be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    public function dropTable($name)
+    {
+        $result = $this->_dropAutoincrement($name);
+        $result = parent::dropTable($name);
+
+        //$this->_silentCommit();
+
+        return $result;
+    }
+
+    /**
+     * 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)
+    {
+        foreach ($changes as $changeName => $change) {
+            switch ($changeName) {
+                case 'add':
+                case 'remove':
+                case 'rename':
+                    break;
+                case 'change':
+                    foreach ($changes['change'] as $field) {
+                        $this->checkSupportedChanges($field);
+                    }
+                    break;
+                default:
+                    throw new Doctrine_DataDict_Exception('change type ' . $changeName . ' not yet supported');
+            }
+        }
+        if ($check) {
+            return true;
+        }
+        $query = '';
+        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 $field_name => $field) {
+                if ($query) {
+                    $query.= ', ';
+                }
+                $field_name = $this->conn->quoteIdentifier($field_name, true);
+                $query.= 'DROP ' . $field_name;
+            }
+        }
+
+        if ( ! empty($changes['rename']) && is_array($changes['rename'])) {
+            foreach ($changes['rename'] as $field_name => $field) {
+                if ($query) {
+                    $query.= ', ';
+                }
+                $field_name = $this->conn->quoteIdentifier($field_name, true);
+                $query.= 'ALTER ' . $field_name . ' TO ' . $this->conn->quoteIdentifier($field['name'], true);
+            }
+        }
+
+        if ( ! empty($changes['change']) && is_array($changes['change'])) {
+            // missing support to change DEFAULT and NULLability
+            foreach ($changes['change'] as $fieldName => $field) {
+                $this->checkSupportedChanges($field);
+                if ($query) {
+                    $query.= ', ';
+                }
+                $this->conn->loadModule('Datatype', null, true);
+                $field_name = $this->conn->quoteIdentifier($fieldName, true);
+                $query.= 'ALTER ' . $field_name.' TYPE ' . $this->getTypeDeclaration($field['definition']);
+            }
+        }
+
+        if ( ! strlen($query)) {
+            return false;
+        }
+
+        $name = $this->conn->quoteIdentifier($name, true);
+        $result = $this->conn->exec('ALTER TABLE ' . $name . ' ' . $query);
+        $this->_silentCommit();
+        return $result;
+    }
+
+    /**
+     * 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 support() 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 createIndexSql($table, $name, array $definition)
+    {
+        $query = 'CREATE';
+
+        $query_sort = '';
+        foreach ($definition['fields'] as $field) {
+            if ( ! strcmp($query_sort, '') && isset($field['sorting'])) {
+                switch ($field['sorting']) {
+                    case 'ascending':
+                        $query_sort = ' ASC';
+                        break;
+                    case 'descending':
+                        $query_sort = ' DESC';
+                        break;
+                }
+            }
+        }
+        $table = $this->conn->quoteIdentifier($table, true);
+        $name  = $this->conn->quoteIdentifier($this->conn->formatter->getIndexName($name), true);
+        $query .= $query_sort. ' INDEX ' . $name . ' ON ' . $table;
+        $fields = array();
+        foreach (array_keys($definition['fields']) as $field) {
+            $fields[] = $this->conn->quoteIdentifier($field, true);
+        }
+        $query .= ' ('.implode(', ', $fields) . ')';
+
+        return $query;
+    }
+
+    /**
+     * 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)
+    {
+        $table = $this->conn->quoteIdentifier($table, true);
+
+        if ( ! empty($name)) {
+            $name = $this->conn->quoteIdentifier($this->conn->formatter->getIndexName($name), true);
+        }
+        $query = "ALTER TABLE $table ADD";
+        if ( ! empty($definition['primary'])) {
+            if ( ! empty($name)) {
+                $query.= ' CONSTRAINT '.$name;
+            }
+            $query.= ' PRIMARY KEY';
+        } else {
+            $query.= ' CONSTRAINT '. $name;
+            if ( ! empty($definition['unique'])) {
+               $query.= ' UNIQUE';
+            }
+        }
+        $fields = array();
+        foreach (array_keys($definition['fields']) as $field) {
+            $fields[] = $this->conn->quoteIdentifier($field, true);
+        }
+        $query .= ' ('. implode(', ', $fields) . ')';
+        $result = $this->conn->exec($query);
+        // TODO ? $this->_silentCommit();
+        return $result;
+    }
+
+    /**
+     * A method to return the required SQL string that fits between CREATE ... TABLE
+     * to create the table as a 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 'GLOBAL TEMPORARY';
+    }
+
+    /**
+     * 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 boolean
+     */
+    public function createSequence($seqName, $start = 1, array $options = array())
+    {
+        $sequenceName = $this->conn->formatter->getSequenceName($seqName);
+
+        $this->conn->exec('CREATE GENERATOR ' . $sequenceName);
+
+        try {
+            $this->conn->exec('SET GENERATOR ' . $sequenceName . ' TO ' . ($start-1));
+            
+            return true;
+        } catch (Doctrine_Connection_Exception $e) {
+            try {
+                $this->dropSequence($seqName);
+            } catch(Doctrine_Connection_Exception $e) {
+                throw new Doctrine_Export_Exception('Could not drop inconsistent sequence table');
+            }
+        }
+        throw new Doctrine_Export_Exception('could not create sequence table');
+    }
+
+    /**
+     * drop existing sequence
+     *
+     * @param string $seqName name of the sequence to be dropped
+     * @return void
+     */
+    public function dropSequenceSql($seqName)
+    {
+        $sequenceName = $this->conn->formatter->getSequenceName($seqName);
+        $sequenceName = $this->conn->quote($sequenceName);
+        $query = "DELETE FROM RDB\$GENERATORS WHERE UPPER(RDB\$GENERATOR_NAME)=" . $sequenceName;
+        
+        return $query;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Frontbase.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,316 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Export_Frontbase
+ *
+ * @package     Doctrine
+ * @subpackage  Export
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ */
+class Doctrine_Export_Frontbase extends Doctrine_Export
+{
+    /**
+     * create a new database
+     *
+     * @param string $name name of the database that should be created
+     * @return string
+     */
+    public function createDatabaseSql($name)
+    {
+        $name  = $this->conn->quoteIdentifier($name, true);
+        return 'CREATE DATABASE ' . $name;
+    }
+
+    /**
+     * drop an existing database
+     *
+     * @param string $name name of the database that should be dropped
+     * @return string
+     */
+    public function dropDatabaseSql($name)
+    {
+        $name  = $this->conn->quoteIdentifier($name, true);
+        return 'DELETE DATABASE ' . $name;    
+    }
+
+    /**
+     * drop an existing table
+     *
+     * @param object $this->conns        database object that is extended by this class
+     * @param string $name       name of the table that should be dropped
+     * @return string
+     */
+    public function dropTableSql($name)
+    {
+        $name = $this->conn->quoteIdentifier($name, true);
+        return 'DROP TABLE ' . $name . ' CASCADE';
+    }
+
+    /**
+     * 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 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.
+     * @access public
+     *
+     * @return boolean
+     */
+    public function alterTable($name, array $changes, $check = false)
+    {
+        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'])) {
+            $changeName = $this->conn->quoteIdentifier($changes['name'], true);
+            $query .= 'RENAME TO ' . $changeName;
+        }
+
+        if ( ! empty($changes['add']) && is_array($changes['add'])) {
+            foreach ($changes['add'] as $fieldName => $field) {
+                if ($query) {
+                    $query.= ', ';
+                }
+                $query.= 'ADD ' . $this->conn->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, true);
+                $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->conn->getDeclaration($oldFieldName, $field['definition']);
+            }
+        }
+
+        if ( ! empty($rename) && is_array($rename)) {
+            foreach ($rename as $renamedFieldName => $renamed_field) {
+                if ($query) {
+                    $query.= ', ';
+                }
+                $oldFieldName = $rename[$renamedFieldName];
+                $field = $changes['rename'][$oldFieldName];
+                $query.= 'CHANGE ' . $this->conn->getDeclaration($oldFieldName, $field['definition']);
+            }
+        }
+
+        if ( ! $query) {
+            return true;
+        }
+
+        $name = $this->conn->quoteIdentifier($name, true);
+        return $this->conn->exec('ALTER TABLE ' . $name . ' ' . $query);
+    }
+
+    /**
+     * 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 void
+     */
+    public function createSequence($sequenceName, $start = 1, array $options = array())
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->getSequenceName($sequenceName), true);
+        $seqcolName   = $this->conn->quoteIdentifier($this->conn->getAttribute(Doctrine::ATTR_SEQCOL_NAME), true);
+
+        $query = 'CREATE TABLE ' . $sequenceName . ' (' . $seqcolName . ' INTEGER DEFAULT UNIQUE, PRIMARY KEY(' . $seqcolName . '))';
+        $res = $this->conn->exec($query);
+        $res = $this->conn->exec('SET UNIQUE = 1 FOR ' . $sequenceName);
+
+        if ($start == 1) {
+            return true;
+        }
+        
+        try {
+            $this->conn->exec('INSERT INTO ' . $sequenceName . ' (' . $seqcolName . ') VALUES (' . ($start-1) . ')');
+        } catch(Doctrine_Connection_Exception $e) {
+            // Handle error
+            try {
+                $this->conn->exec('DROP TABLE ' . $sequenceName);
+            } catch(Doctrine_Connection_Exception $e) {
+                throw new Doctrine_Export_Exception('could not drop inconsistent sequence table');
+            }
+
+            throw new Doctrine_Export_Exception('could not create sequence table');
+        }
+    }
+
+    /**
+     * drop existing sequence
+     *
+     * @param string $seqName       name of the sequence to be dropped
+     * @return string
+     */
+    public function dropSequenceSql($seqName)
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->getSequenceName($seqName), true);
+
+        return 'DROP TABLE ' . $sequenceName . ' CASCADE';
+    }
+
+    /**
+     * 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 boolean
+     */
+    public function dropIndexSql($table, $name)
+    {
+        $table = $this->conn->quoteIdentifier($table, true);
+        $name = $this->conn->quoteIdentifier($this->conn->getIndexName($name), true);
+
+        return 'ALTER TABLE ' . $table . ' DROP INDEX ' . $name;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Informix.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,37 @@
+<?php
+/*
+ *  $Id: Firebird.php 3884 2008-02-22 18:26:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Export_Informix
+ *
+ * @package     Doctrine
+ * @subpackage  Export
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @author      Lorenzo Alberton <l.alberton@quipo.it> (PEAR MDB2 Interbase driver)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3884 $
+ */
+class Doctrine_Export_Informix extends Doctrine_Export
+{
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Mssql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,349 @@
+<?php
+/*
+ *  $Id: Mssql.php 5824 2009-06-04 15:17:57Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Export_Mssql
+ *
+ * @package     Doctrine
+ * @subpackage  Export
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @author      Frank M. Kromann <frank@kromann.info> (PEAR MDB2 Mssql driver)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5824 $
+ */
+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";
+        if ($this->conn->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, null, 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 '';
+    }  
+    /**
+     * 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)
+    {
+        foreach ($changes as $changeName => $change) {
+            switch ($changeName) {
+                case 'add':
+                    break;
+                case 'remove':
+                    break;
+                case 'name':
+                case 'rename':
+                case 'change':
+                default:
+                    throw new Doctrine_Export_Exception('alterTable: change type "' . $changeName . '" not yet supported');
+            }
+        }
+
+        $query = '';
+        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 .= ', ';
+                }
+                $field_name = $this->conn->quoteIdentifier($fieldName, true);
+                $query .= 'DROP COLUMN ' . $fieldName;
+            }
+        }
+
+        if ( ! $query) {
+            return false;
+        }
+
+        $name = $this->conn->quoteIdentifier($name, true);
+        return $this->conn->exec('ALTER TABLE ' . $name . ' ' . $query);
+    }
+
+    /**
+     * 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);
+        }
+
+        $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';
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Mysql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,778 @@
+<?php
+/*
+ *  $Id: Mysql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Export_Mysql
+ *
+ * @package     Doctrine
+ * @subpackage  Export
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+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 'DROP DATABASE ' . $this->conn->quoteIdentifier($name);
+    }
+
+    /**
+     * 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 = ($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'])) {
+            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::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 '" . $field['comment'] . "'" : '';
+
+        $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());
+        }
+    }
+
+    /**
+     * 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::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::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;
+        $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::ATTR_PORTABILITY) & Doctrine::PORTABILITY_EMPTY_TO_NULL)
+                ) {
+                    $field['default'] = ' ';
+                }
+            }
+    
+            // Proposed patch:
+            if ($field['type'] == 'enum' && $this->conn->getAttribute(Doctrine::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);
+    }
+
+    /**
+     * 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($name);
+
+        return $this->conn->exec('ALTER TABLE ' . $table . ' DROP FOREIGN KEY ' . $name);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Oracle.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,560 @@
+<?php
+/*
+ *  $Id: Oracle.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Export_Oracle
+ *
+ * @package     Doctrine
+ * @subpackage  Export
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Export_Oracle extends Doctrine_Export
+{
+    /**
+     * create a new database
+     *
+     * @param object $db database object that is extended by this class
+     * @param string $name name of the database that should be created
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    public function createDatabase($name)
+    {
+        if ( ! $this->conn->getAttribute(Doctrine::ATTR_EMULATE_DATABASE))
+            throw new Doctrine_Export_Exception('database creation is only supported if the "emulate_database" attribute is enabled');
+
+        $username   = sprintf($this->conn->getAttribute(Doctrine::ATTR_DB_NAME_FORMAT), $name);
+        $password   = $this->conn->dsn['password'] ? $this->conn->dsn['password'] : $name;
+
+        $tablespace = $this->conn->getAttribute(Doctrine::ATTR_DB_NAME_FORMAT)
+                    ? ' DEFAULT TABLESPACE '.$this->conn->options['default_tablespace'] : '';
+
+        $query  = 'CREATE USER ' . $username . ' IDENTIFIED BY ' . $password . $tablespace;
+        $result = $this->conn->exec($query);
+
+        try {
+            $query = 'GRANT CREATE SESSION, CREATE TABLE, UNLIMITED TABLESPACE, CREATE SEQUENCE, CREATE TRIGGER TO ' . $username;
+            $result = $this->conn->exec($query);
+        } catch (Exception $e) {
+            $query = 'DROP USER '.$username.' CASCADE';
+            $result2 = $this->conn->exec($query);
+        }
+        return true;
+    }
+
+    /**
+     * drop an existing database
+     *
+     * @param object $this->conn database object that is extended by this class
+     * @param string $name name of the database that should be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    public function dropDatabase($name)
+    {
+        if ( ! $this->conn->getAttribute(Doctrine::ATTR_EMULATE_DATABASE))
+            throw new Doctrine_Export_Exception('database dropping is only supported if the
+                                                       "emulate_database" option is enabled');
+
+        $username = sprintf($this->conn->getAttribute(Doctrine::ATTR_DB_NAME_FORMAT), $name);
+
+        return $this->conn->exec('DROP USER ' . $username . ' CASCADE');
+    }
+
+    /**
+     * add an autoincrement sequence + trigger
+     *
+     * @param string $name  name of the PK field
+     * @param string $table name of the table
+     * @param string $start start value for the sequence
+     * @return mixed        MDB2_OK on success, a MDB2 error on failure
+     * @access private
+     */
+    public function _makeAutoincrement($name, $table, $start = 1)
+    {
+        $sql   = array();
+
+        if ( ! $this->conn->getAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER)) {
+        	$table = strtoupper($table);
+        }
+        $indexName  = $table . '_AI_PK';
+        $definition = array(
+            'primary' => true,
+            'fields' => array($name => true),
+        );
+		
+        $sql[] = 'DECLARE
+  constraints_Count NUMBER;
+BEGIN
+  SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = \''.$table.'\' AND CONSTRAINT_TYPE = \'P\';
+  IF constraints_Count = 0 THEN
+    EXECUTE IMMEDIATE \''.$this->createConstraintSql($table, $indexName, $definition).'\';
+  END IF;
+END;';   
+		
+        if (is_null($start)) {
+            $query = 'SELECT MAX(' . $this->conn->quoteIdentifier($name, true) . ') FROM ' . $this->conn->quoteIdentifier($table, true);
+            $start = $this->conn->fetchOne($query);
+
+            ++$start;
+        }
+
+        $sql[] = $this->createSequenceSql($table, $start);
+
+        $sequenceName = $this->conn->formatter->getSequenceName($table);
+        $triggerName  = $this->conn->quoteIdentifier($table . '_AI_PK', true);
+        $table = $this->conn->quoteIdentifier($table, true);
+        $name  = $this->conn->quoteIdentifier($name, true);
+        $sql[] = 'CREATE TRIGGER ' . $triggerName . '
+   BEFORE INSERT
+   ON ' . $table . '
+   FOR EACH ROW
+DECLARE
+   last_Sequence NUMBER;
+   last_InsertID NUMBER;
+BEGIN
+   SELECT ' . $this->conn->quoteIdentifier($sequenceName) . '.NEXTVAL INTO :NEW.' . $name . ' FROM DUAL;
+   IF (:NEW.' . $name . ' IS NULL OR :NEW.'.$name.' = 0) THEN
+      SELECT ' . $this->conn->quoteIdentifier($sequenceName) . '.NEXTVAL INTO :NEW.' . $name . ' FROM DUAL;
+   ELSE
+      SELECT NVL(Last_Number, 0) INTO last_Sequence
+        FROM User_Sequences
+       WHERE Sequence_Name = \'' . $sequenceName . '\';
+      SELECT :NEW.' . $name . ' INTO last_InsertID FROM DUAL;
+      WHILE (last_InsertID > last_Sequence) LOOP
+         SELECT ' . $this->conn->quoteIdentifier($sequenceName) . '.NEXTVAL INTO last_Sequence FROM DUAL;
+      END LOOP;
+   END IF;
+END;';
+        return $sql;
+    }
+
+    /**
+     * drop an existing autoincrement sequence + trigger
+     *
+     * @param string $table name of the table
+     * @return void
+     */
+    public function dropAutoincrement($table)
+    {
+        $table = strtoupper($table);
+        $triggerName = $table . '_AI_PK';
+        $trigger_name_quoted = $this->conn->quote($triggerName);
+        $query = 'SELECT trigger_name FROM user_triggers';
+        $query.= ' WHERE trigger_name='.$trigger_name_quoted.' OR trigger_name='.strtoupper($trigger_name_quoted);
+        $trigger = $this->conn->fetchOne($query);
+
+        if ($trigger) {
+            $trigger_name  = $this->conn->quoteIdentifier($table . '_AI_PK', true);
+            $trigger_sql = 'DROP TRIGGER ' . $trigger_name;
+
+            // if throws exception, trigger for autoincrement PK could not be dropped
+            $this->conn->exec($trigger_sql);
+
+            // if throws exception, sequence for autoincrement PK could not be dropped
+            $this->dropSequence($table);
+
+            $indexName = $table . '_AI_PK';
+
+            // if throws exception, primary key for autoincrement PK could not be dropped
+            $this->dropConstraint($table, $indexName);
+        }
+    }
+   /**
+     * A method to return the required SQL string that fits between CREATE ... TABLE
+     * to create the table as a 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 'GLOBAL TEMPORARY';
+    }
+
+    /**
+     * 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['onDelete']) && strtoupper(trim($definition['onDelete'])) != 'NO ACTION') {
+            $query .= ' ON DELETE ' . $definition['onDelete'];
+        }
+        if (isset($definition['deferrable'])) {
+            $query .= ' DEFERRABLE';
+        } else {
+            $query .= ' NOT DEFERRABLE';
+        }
+        if (isset($definition['feferred'])) {
+            $query .= ' INITIALLY DEFERRED';
+        } else {
+            $query .= ' INITIALLY IMMEDIATE';
+        }
+        return $query;
+    }
+
+    /**
+     * 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.
+     *
+     *                        Example
+     *                        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 void
+     */
+    public function createTable($name, array $fields, array $options = array())
+    {
+        $this->conn->beginTransaction();
+
+        foreach ($this->createTableSql($name, $fields, $options) as $sql) {
+            $this->conn->exec($sql);
+        }
+
+        $this->conn->commit();
+    }
+
+    /**
+     * 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.
+     *
+     *                        Example
+     *                        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 void
+     */
+    public function createTableSql($name, array $fields, array $options = array())
+    {
+        $sql = parent::createTableSql($name, $fields, $options);
+
+        foreach ($fields as $fieldName => $field) {
+            if (isset($field['sequence'])) {
+              $sql[] = $this->createSequenceSql($field['sequence'], 1);
+            }
+
+            if (isset($field['autoincrement']) && $field['autoincrement'] ||
+               (isset($field['autoinc']) && $fields['autoinc'])) {           
+                $sql = array_merge($sql, $this->_makeAutoincrement($fieldName, $name));
+            }
+        }
+        
+        if (isset($options['indexes']) && ! empty($options['indexes'])) {
+            foreach ($options['indexes'] as $indexName => $definition) {
+                // create nonunique indexes, as they are a part od CREATE TABLE DDL
+                if ( ! isset($definition['type']) || 
+                    (isset($definition['type']) && strtolower($definition['type']) != 'unique')) {
+                    $sql[] = $this->createIndexSql($name, $indexName, $definition);
+                }
+            }
+        }
+        
+        return $sql;
+    }
+
+    /**
+     * drop an existing table
+     *
+     * @param string $name name of the table that should be dropped
+     * @return void
+     */
+    public function dropTable($name)
+    {
+        //$this->conn->beginNestedTransaction();
+        $result = $this->dropAutoincrement($name);
+        $result = parent::dropTable($name);
+        //$this->conn->completeNestedTransaction();
+        return $result;
+    }
+
+    /**
+     * 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 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)
+    {
+
+        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 false;
+        }
+
+        $name = $this->conn->quoteIdentifier($name, true);
+
+        if ( ! empty($changes['add']) && is_array($changes['add'])) {
+            $fields = array();
+            foreach ($changes['add'] as $fieldName => $field) {
+                $fields[] = $this->conn->getDeclaration($fieldName, $field);
+            }
+            $result = $this->conn->exec('ALTER TABLE ' . $name . ' ADD (' . implode(', ', $fields) . ')');
+        }
+
+        if ( ! empty($changes['change']) && is_array($changes['change'])) {
+            $fields = array();
+            foreach ($changes['change'] as $fieldName => $field) {
+                $fields[] = $fieldName. ' ' . $this->conn->getDeclaration('', $field['definition']);
+            }
+            $result = $this->conn->exec('ALTER TABLE ' . $name . ' MODIFY (' . implode(', ', $fields) . ')');
+        }
+
+        if ( ! empty($changes['rename']) && is_array($changes['rename'])) {
+            foreach ($changes['rename'] as $fieldName => $field) {
+                $query = 'ALTER TABLE ' . $name . ' RENAME COLUMN ' . $this->conn->quoteIdentifier($fieldName, true)
+                       . ' TO ' . $this->conn->quoteIdentifier($field['name']);
+
+                $result = $this->conn->exec($query);
+            }
+        }
+
+        if ( ! empty($changes['remove']) && is_array($changes['remove'])) {
+            $fields = array();
+            foreach ($changes['remove'] as $fieldName => $field) {
+                $fields[] = $this->conn->quoteIdentifier($fieldName, true);
+            }
+            $result = $this->conn->exec('ALTER TABLE ' . $name . ' DROP COLUMN ' . implode(', ', $fields));
+        }
+
+        if ( ! empty($changes['name'])) {
+            $changeName = $this->conn->quoteIdentifier($changes['name'], true);
+            $result = $this->conn->exec('ALTER TABLE ' . $name . ' RENAME TO ' . $changeName);
+        }
+    }
+
+    /**
+     * 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 createSequenceSql($seqName, $start = 1, array $options = array())
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+        $query  = 'CREATE SEQUENCE ' . $sequenceName . ' START WITH ' . $start . ' INCREMENT BY 1 NOCACHE';
+        $query .= ($start < 1 ? ' MINVALUE ' . $start : '');
+        return $query;
+    }
+
+    /**
+     * drop existing sequence
+     *
+     * @param object $this->conn database object that is extended by this class
+     * @param string $seqName name of the sequence to be dropped
+     * @return string
+     */
+    public function dropSequenceSql($seqName)
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+        return 'DROP SEQUENCE ' . $sequenceName;
+    }
+
+    /**
+     * return Oracle's SQL code portion needed to set an index
+     * declaration to be unsed in statements like CREATE TABLE.
+     * 
+     * @param string $name      name of the index
+     * @param array $definition index definition
+     * @return string           Oracle's 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
+                );
+            }
+        } else {
+            // only unique indexes should be defined in create table statement
+            return null;
+        }
+        
+        if (!isset($definition['fields']) || !is_array($definition['fields'])) {
+            throw new Doctrine_Export_Exception('No columns given for index '.$name);
+        }
+        
+        $query = 'CONSTRAINT '.$name.' '.$type.' ('.$this->getIndexFieldDeclarationList($definition['fields']).')';
+        
+        return $query;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Pgsql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,374 @@
+<?php
+/*
+ *  $Id: Pgsql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Export_Pgsql
+ *
+ * @package     Doctrine
+ * @subpackage  Export
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+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['feferred'])) {
+            $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 ' . $name . ' ' . $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 ' . $name . ' ' . $query;
+            }
+        }
+
+        if (isset($changes['change']) && is_array($changes['change'])) {
+            foreach ($changes['change'] as $fieldName => $field) {
+                $fieldName = $this->conn->quoteIdentifier($fieldName, true);
+                if (isset($field['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->datatype->getTypeDeclaration($field['definition']);
+                    $sql[] = 'ALTER TABLE ' . $name . ' ' . $query;
+                }
+                if (array_key_exists('default', $field)) {
+                    $query = 'ALTER ' . $fieldName . ' SET DEFAULT ' . $this->conn->quote($field['definition']['default'], $field['definition']['type']);
+                    $sql[] = 'ALTER TABLE ' . $name . ' ' . $query;
+                }
+                if ( ! empty($field['notnull'])) {
+                    $query = 'ALTER ' . $fieldName . ' ' . ($field['definition']['notnull'] ? 'SET' : 'DROP') . ' NOT NULL';
+                    $sql[] = 'ALTER TABLE ' . $name . ' ' . $query;
+                }
+            }
+        }
+
+        if (isset($changes['rename']) && is_array($changes['rename'])) {
+            foreach ($changes['rename'] as $fieldName => $field) {
+                $fieldName = $this->conn->quoteIdentifier($fieldName, true);
+                $sql[] = 'ALTER TABLE ' . $name . ' 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 ' . $name . ' 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);
+                }
+            }
+        }
+        
+        return $sql;
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Reporter.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: Reporter.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Export_Reporter
+ *
+ * @package     Doctrine
+ * @subpackage  Export
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Export_Reporter implements IteratorAggregate {
+    protected $messages = array();
+
+    public function add($code, $message) {
+        $this->messages[] = array($code, $message);
+    }
+    public function pop() {
+        return array_pop($this->messages);
+    }
+    public function getIterator() {
+        return new ArrayIterator($this->messages);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Schema.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,150 @@
+<?php
+/*
+ * $Id: Schema.php 1838 2007-06-26 00:58:21Z nicobn $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Export_Schema
+ * 
+ * Used for exporting a schema to a yaml file
+ *
+ * @package     Doctrine
+ * @subpackage  Export
+ * @link        www.phpdoctrine.org
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision: 1838 $
+ * @author      Nicolas Bérard-Nault <nicobn@gmail.com>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Export_Schema
+{    
+    /**
+     * buildSchema
+     * 
+     * Build schema array that can be dumped to file
+     *
+     * @param string $directory 
+     * @return void
+     */
+    public function buildSchema($directory = null, $models = array())
+    {
+        if ($directory !== null) {
+            $loadedModels = Doctrine::filterInvalidModels(Doctrine::loadModels($directory));
+        } else {
+            $loadedModels = Doctrine::getLoadedModels();
+        }
+        
+        $array = array();
+        
+        $parent = new ReflectionClass('Doctrine_Record');
+
+        $sql = array();
+        $fks = array();
+
+        // we iterate through the diff of previously declared classes
+        // and currently declared classes
+        foreach ($loadedModels as $className) {
+            if ( ! empty($models) && !in_array($className, $models)) {
+                continue;
+            }
+
+            $recordTable = Doctrine::getTable($className);
+            
+            $data = $recordTable->getExportableFormat();
+            
+            $table = array();
+            $remove = array('ptype', 'ntype', 'alltypes');
+            // Fix explicit length in schema, concat it to type in this format: type(length)
+            foreach ($data['columns'] AS $name => $column) {
+                if (isset($column['length']) && $column['length'] && isset($column['scale']) && $column['scale']) {
+                    $data['columns'][$name]['type'] = $column['type'] . '(' . $column['length'] . ', ' . $column['scale'] . ')';
+                    unset($data['columns'][$name]['length'], $data['columns'][$name]['scale']);
+                } else {
+                    $data['columns'][$name]['type'] = $column['type'] . '(' . $column['length'] . ')';
+                    unset($data['columns'][$name]['length']);
+                }
+                // Strip out schema information which is not necessary to be dumped to the yaml schema file
+                foreach ($remove as $value) {
+                    if (isset($data['columns'][$name][$value])) {
+                        unset($data['columns'][$name][$value]);
+                    }
+                }
+                
+                // If type is the only property of the column then lets abbreviate the syntax
+                // columns: { name: string(255) }
+                if (count($data['columns'][$name]) === 1 && isset($data['columns'][$name]['type'])) {
+                    $type = $data['columns'][$name]['type'];
+                    unset($data['columns'][$name]);
+                    $data['columns'][$name] = $type;
+                }
+            }
+            $table['tableName'] = $data['tableName'];
+            $table['columns'] = $data['columns'];
+            
+            $relations = $recordTable->getRelations();
+            foreach ($relations as $key => $relation) {
+                $relationData = $relation->toArray();
+                
+                $relationKey = $relationData['alias'];
+                
+                if (isset($relationData['refTable']) && $relationData['refTable']) {
+                    $table['relations'][$relationKey]['refClass'] = $relationData['refTable']->getComponentName();
+                }
+                
+                if (isset($relationData['class']) && $relationData['class'] && $relation['class'] != $relationKey) {
+                    $table['relations'][$relationKey]['class'] = $relationData['class'];
+                }
+ 
+                $table['relations'][$relationKey]['local'] = $relationData['local'];
+                $table['relations'][$relationKey]['foreign'] = $relationData['foreign'];
+                
+                if ($relationData['type'] === Doctrine_Relation::ONE) {
+                    $table['relations'][$relationKey]['type'] = 'one';
+                } else if($relationData['type'] === Doctrine_Relation::MANY) {
+                    $table['relations'][$relationKey]['type'] = 'many';
+                } else {
+                    $table['relations'][$relationKey]['type'] = 'one';
+                }
+            }
+            
+            $array[$className] = $table;
+        }
+        
+        return $array;
+    }
+
+    /**
+     * exportSchema
+     *
+     * @param  string $schema 
+     * @param  string $directory 
+     * @return string $string of data in the specified format
+     * @return void
+     */
+    public function exportSchema($schema, $format = 'yml', $directory = null, $models = array())
+    {
+        $array = $this->buildSchema($directory, $models);
+        
+        if (is_dir($schema)) {
+          $schema = $schema . DIRECTORY_SEPARATOR . 'schema.' . $format;
+        }
+        
+        return Doctrine_Parser::dump($array, $format, $schema);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Export/Sqlite.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,421 @@
+<?php
+/*
+ *  $Id: Sqlite.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Export_Sqlite
+ *
+ * @package     Doctrine
+ * @subpackage  Export
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Export_Sqlite extends Doctrine_Export
+{
+    /**
+     * dropDatabase
+     *
+     * drop an existing database
+     *
+     * @param string $databaseFile          Path of the database that should be dropped
+     * @throws Doctrine_Export_Exception    if the database file does not exist
+     * @throws Doctrine_Export_Exception    if something failed during the removal of the database file
+     * @return void
+     */
+    public function dropDatabase($databaseFile)
+    {
+        if ( ! @file_exists($databaseFile)) {
+            throw new Doctrine_Export_Exception('database does not exist');
+        }
+
+        $result = @unlink($databaseFile);
+
+        if ( ! $result) {
+            throw new Doctrine_Export_Exception('could not remove the database file');
+        }
+    }
+
+    /**
+     * createDatabase
+     *
+     * Create sqlite database file
+     *
+     * @param string $databaseFile  Path of the database that should be dropped
+     * @return void
+     */
+    public function createDatabase($databaseFile)
+    {
+        return new PDO('sqlite:' . $databaseFile);
+    }
+
+    /**
+     * 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 support() to determine whether the DBMS driver can manage indexes.
+     *                                 Example
+     *                                    array(
+     *                                        'fields' => array(
+     *                                            'user_name' => array(
+     *                                                'sorting' => 'ascending'
+     *                                            ),
+     *                                            'last_login' => array()
+     *                                        )
+     *                                    )
+     * @throws PDOException
+     * @return void
+     */
+    public function createIndexSql($table, $name, array $definition)
+    {
+        $name  = $this->conn->formatter->getIndexName($name);
+        $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;
+        $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['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);
+    }
+
+    /**
+     * 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 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);
+        
+        $autoinc = false;
+        foreach($fields as $field) {
+            if (isset($field['autoincrement']) && $field['autoincrement'] || 
+              (isset($field['autoinc']) && $field['autoinc'])) {
+                $autoinc = true;
+                break;
+            }
+        }
+
+        if ( ! $autoinc && isset($options['primary']) && ! empty($options['primary'])) {
+            $keyColumns = array_values($options['primary']);
+            $keyColumns = array_map(array($this->conn, 'quoteIdentifier'), $keyColumns);
+            $queryFields.= ', PRIMARY KEY('.implode(', ', $keyColumns).')';
+        }
+
+        $name  = $this->conn->quoteIdentifier($name, true);
+        $sql   = 'CREATE TABLE ' . $name . ' (' . $queryFields;
+
+        if ($check = $this->getCheckDeclaration($fields)) {
+            $sql .= ', ' . $check;
+        }
+
+        if (isset($options['checks']) && $check = $this->getCheckDeclaration($options['checks'])) {
+            $sql .= ', ' . $check;
+        }
+
+        $sql .= ')';
+
+        $query[] = $sql;
+
+        if (isset($options['indexes']) && ! empty($options['indexes'])) {
+            foreach ($options['indexes'] as $index => $definition) {
+                $query[] = $this->createIndexSql($name, $index, $definition);
+            }
+        }
+
+        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['feferred'])) {
+            $query .= ' INITIALLY DEFERRED';
+        } else {
+            $query .= ' INITIALLY IMMEDIATE';
+        }
+        return $query;
+    }
+
+    /**
+     * 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 boolean
+     */
+    public function createSequence($seqName, $start = 1, array $options = array())
+    {
+        $sequenceName   = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+        $seqcolName     = $this->conn->quoteIdentifier($this->conn->getAttribute(Doctrine::ATTR_SEQCOL_NAME), true);
+        $query          = 'CREATE TABLE ' . $sequenceName . ' (' . $seqcolName . ' INTEGER PRIMARY KEY DEFAULT 0 NOT NULL)';
+
+        $this->conn->exec($query);
+
+        if ($start == 1) {
+            return true;
+        }
+
+        try {
+            $this->conn->exec('INSERT INTO ' . $sequenceName . ' (' . $seqcolName . ') VALUES (' . ($start-1) . ')');
+            return true;
+        } catch(Doctrine_Connection_Exception $e) {
+            // Handle error    
+
+            try {
+                $result = $db->exec('DROP TABLE ' . $sequenceName);
+            } catch(Doctrine_Connection_Exception $e) {
+                throw new Doctrine_Export_Exception('could not drop inconsistent sequence table');
+            }
+        }
+        throw new Doctrine_Export_Exception('could not create sequence table');
+    }
+
+    /**
+     * drop existing sequence
+     *
+     * @param string $sequenceName      name of the sequence to be dropped
+     * @return string
+     */
+    public function dropSequenceSql($sequenceName)
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($sequenceName), true);
+
+        return 'DROP TABLE ' . $sequenceName;
+    }
+    
+    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 '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);
+            }
+        }
+
+        $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;
+    }
+
+    /**
+     * createForeignKey
+     *
+     * Sqlite does not support foreign keys so we are not even going to do anything if this function is called
+     * to avoid any sql errors if a user tries to use this on sqlite
+     *
+     * @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)
+    {
+        return false;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,145 @@
+<?php
+/*
+ *  $Id: Expression.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Expression
+ *
+ * @package     Doctrine
+ * @subpackage  Expression
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Expression
+{
+    protected $_expression;
+    protected $_conn;
+    protected $_tokenizer;
+
+    /**
+     * Create an expression 
+     * 
+     * @param string $expr The expression
+     * @param Doctrine_Connection $conn The connection (optional)
+     * @return void
+     */
+    public function __construct($expr, $conn = null)
+    {
+        $this->_tokenizer = new Doctrine_Query_Tokenizer();
+        $this->setExpression($expr);
+        if ($conn !== null) {
+            $this->_conn = $conn;
+        }
+    }
+
+    /**
+     * getConnection 
+     * 
+     * @return Doctrine_Connection The connection
+     */
+    public function getConnection()
+    {
+        if ( ! isset($this->_conn)) {
+            return Doctrine_Manager::connection();
+        }
+
+        return $this->_conn;
+    }
+
+    /**
+     * setExpression 
+     * 
+     * @param string $clause The expression to set
+     * @return void
+     */
+    public function setExpression($clause)
+    {
+        $this->_expression = $this->parseClause($clause);
+    }
+
+    /**
+     * parseExpression 
+     *
+     * @todo: What does this function do?
+     * 
+     * @param string $expr The expression to parse
+     * @return void
+     */
+    public function parseExpression($expr)
+    {
+        $pos  = strpos($expr, '(');
+        $quoted = (substr($expr, 0, 1) === "'" && substr($expr, -1) === "'");
+        if ($pos === false || $quoted) {
+            return $expr;
+        }
+
+        // get the name of the function
+        $name   = substr($expr, 0, $pos);
+        $argStr = substr($expr, ($pos + 1), -1);
+
+        // parse args
+        foreach ($this->_tokenizer->bracketExplode($argStr, ',') as $arg) {
+           $args[] = $this->parseClause($arg);
+        }
+
+        return call_user_func_array(array($this->getConnection()->expression, $name), $args);
+    }
+
+    /**
+     * parseClause 
+     * 
+     * @param string $clause The clause
+     * @return string The parse clause
+     */
+    public function parseClause($clause)
+    {
+        $e = $this->_tokenizer->bracketExplode($clause, ' ');
+
+        foreach ($e as $k => $expr) {
+            $e[$k] = $this->parseExpression($expr);
+        }
+        
+        return implode(' ', $e);
+    }
+
+    /**
+     * getSql 
+     * 
+     * @return string The expression
+     */
+    public function getSql()
+    {
+
+        return $this->_expression;
+    }
+
+    /**
+     * __toString 
+     * 
+     * @return void
+     */
+    public function __toString()
+    {
+        return $this->getSql();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Driver.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,773 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Expression_Driver
+ *
+ * @package     Doctrine
+ * @subpackage  Expression
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Expression_Driver extends Doctrine_Connection_Module
+{
+    public function getIdentifier($column)
+    {
+        return $column;
+    }
+    public function getIdentifiers($columns)
+    {
+        return $columns;
+    }
+
+    /**
+     * regexp
+     * returns the regular expression operator
+     *
+     * @return string
+     */
+    public function regexp()
+    {
+        throw new Doctrine_Expression_Exception('Regular expression operator is not supported by this database driver.');
+    }
+
+    /**
+     * Returns the average value of a column
+     *
+     * @param string $column    the column to use
+     * @return string           generated sql including an AVG aggregate function
+     */
+    public function avg($column)
+    {
+        $column = $this->getIdentifier($column);
+        return 'AVG(' .  $column . ')';
+    }
+
+    /**
+     * Returns the number of rows (without a NULL value) of a column
+     *
+     * If a '*' is used instead of a column the number of selected rows
+     * is returned.
+     *
+     * @param string|integer $column    the column to use
+     * @return string                   generated sql including a COUNT aggregate function
+     */
+    public function count($column)
+    {
+        $column = $this->getIdentifier($column);
+        return 'COUNT(' . $column . ')';
+    }
+
+    /**
+     * Returns the highest value of a column
+     *
+     * @param string $column    the column to use
+     * @return string           generated sql including a MAX aggregate function
+     */
+    public function max($column)
+    {
+        $column = $this->getIdentifier($column);
+        return 'MAX(' . $column . ')';
+    }
+
+    /**
+     * Returns the lowest value of a column
+     *
+     * @param string $column the column to use
+     * @return string
+     */
+    public function min($column)
+    {
+        $column = $this->getIdentifier($column);
+        return 'MIN(' . $column . ')';
+    }
+
+    /**
+     * Returns the total sum of a column
+     *
+     * @param string $column the column to use
+     * @return string
+     */
+    public function sum($column)
+    {
+        $column = $this->getIdentifier($column);
+        return 'SUM(' . $column . ')';
+    }
+
+    // scalar functions
+
+    /**
+     * Returns the md5 sum of a field.
+     *
+     * Note: Not SQL92, but common functionality
+     *
+     * @return string
+     */
+    public function md5($column)
+    {
+        $column = $this->getIdentifier($column);
+        return 'MD5(' . $column . ')';
+    }
+
+    /**
+     * Returns the length of a text field.
+     *
+     * @param string $expression1
+     * @param string $expression2
+     * @return string
+     */
+    public function length($column)
+    {
+        $column = $this->getIdentifier($column);
+        return 'LENGTH(' . $column . ')';
+    }
+
+    /**
+     * Rounds a numeric field to the number of decimals specified.
+     *
+     * @param string $expression1
+     * @param string $expression2
+     * @return string
+     */
+    public function round($column, $decimals = 0)
+    {
+        $column = $this->getIdentifier($column);
+
+        return 'ROUND(' . $column . ', ' . $decimals . ')';
+    }
+
+    /**
+     * Returns the remainder of the division operation
+     * $expression1 / $expression2.
+     *
+     * @param string $expression1
+     * @param string $expression2
+     * @return string
+     */
+    public function mod($expression1, $expression2)
+    {
+        $expression1 = $this->getIdentifier($expression1);
+        $expression2 = $this->getIdentifier($expression2);
+        return 'MOD(' . $expression1 . ', ' . $expression2 . ')';
+    }
+
+    /**
+     * trim
+     * returns the string $str with leading and proceeding space characters removed
+     *
+     * @param string $str       literal string or column name
+     * @return string
+     */
+    public function trim($str)
+    {
+        return 'TRIM(' . $str . ')';
+    }
+
+    /**
+     * rtrim
+     * returns the string $str with proceeding space characters removed
+     *
+     * @param string $str       literal string or column name
+     * @return string
+     */
+    public function rtrim($str)
+    {
+        return 'RTRIM(' . $str . ')';
+    }
+
+    /**
+     * ltrim
+     * returns the string $str with leading space characters removed
+     *
+     * @param string $str       literal string or column name
+     * @return string
+     */
+    public function ltrim($str)
+    {
+        return 'LTRIM(' . $str . ')';
+    }
+
+    /**
+     * upper
+     * Returns the string $str with all characters changed to
+     * uppercase according to the current character set mapping.
+     *
+     * @param string $str       literal string or column name
+     * @return string
+     */
+    public function upper($str)
+    {
+        return 'UPPER(' . $str . ')';
+    }
+
+    /**
+     * lower
+     * Returns the string $str with all characters changed to
+     * lowercase according to the current character set mapping.
+     *
+     * @param string $str       literal string or column name
+     * @return string
+     */
+    public function lower($str)
+    {
+        return 'LOWER(' . $str . ')';
+    }
+
+    /**
+     * locate
+     * returns the position of the first occurrence of substring $substr in string $str
+     *
+     * @param string $substr    literal string to find
+     * @param string $str       literal string
+     * @return integer
+     */
+    public function locate($str, $substr)
+    {
+        return 'LOCATE(' . $str . ', ' . $substr . ')';
+    }
+
+    /**
+     * Returns the current system date.
+     *
+     * @return string
+     */
+    public function now()
+    {
+        return 'NOW()';
+    }
+
+    /**
+     * soundex
+     * Returns a string to call a function to compute the
+     * soundex encoding of a string
+     *
+     * The string "?000" is returned if the argument is NULL.
+     *
+     * @param string $value
+     * @return string   SQL soundex function with given parameter
+     */
+    public function soundex($value)
+    {
+        throw new Doctrine_Expression_Exception('SQL soundex function not supported by this driver.');
+    }
+
+    /**
+     * return string to call a function to get a substring inside an SQL statement
+     *
+     * Note: Not SQL92, but common functionality.
+     *
+     * SQLite only supports the 2 parameter variant of this function
+     *
+     * @param string $value         an sql string literal or column name/alias
+     * @param integer $position     where to start the substring portion
+     * @param integer $length       the substring portion length
+     * @return string               SQL substring function with given parameters
+     */
+    public function substring($value, $from, $len = null)
+    {
+        $value = $this->getIdentifier($value);
+        if ($len === null)
+            return 'SUBSTRING(' . $value . ' FROM ' . $from . ')';
+        else {
+            $len = $this->getIdentifier($len);
+            return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $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.
+     */
+    public function concat()
+    {
+        $args = func_get_args();
+
+        return 'CONCAT(' . join(', ', (array) $args) . ')';
+    }
+
+    /**
+     * Returns the SQL for a logical not.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $e = $q->expr;
+     * $q->select('*')->from('table')
+     *   ->where($e->eq('id', $e->not('null'));
+     * </code>
+     *
+     * @return string a logical expression
+     */
+    public function not($expression)
+    {
+        $expression = $this->getIdentifier($expression);
+        return 'NOT(' . $expression . ')';
+    }
+
+    /**
+     * Returns the SQL to perform the same mathematical operation over an array
+     * of values or expressions.
+     *
+     * basicMath() accepts an arbitrary number of parameters. Each parameter
+     * must contain a value or an expression or an array with values or
+     * expressions.
+     *
+     * @param string $type the type of operation, can be '+', '-', '*' or '/'.
+     * @param string|array(string)
+     * @return string an expression
+     */
+    private function basicMath($type, array $args)
+    {
+        $elements = $this->getIdentifiers($args);
+        if (count($elements) < 1) {
+            return '';
+        }
+        if (count($elements) == 1) {
+            return $elements[0];
+        } else {
+            return '(' . implode(' ' . $type . ' ', $elements) . ')';
+        }
+    }
+
+    /**
+     * Returns the SQL to add values or expressions together.
+     *
+     * add() accepts an arbitrary number of parameters. Each parameter
+     * must contain a value or an expression or an array with values or
+     * expressions.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $e = $q->expr;
+     *
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($e->eq($e->add('id', 2), 12));
+     * </code>
+     *
+     * @param string|array(string)
+     * @return string an expression
+     */
+    public function add(array $args)
+    {
+        return $this->basicMath('+', $args);
+    }
+
+    /**
+     * Returns the SQL to subtract values or expressions from eachother.
+     *
+     * subtract() accepts an arbitrary number of parameters. Each parameter
+     * must contain a value or an expression or an array with values or
+     * expressions.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $e = $q->expr;
+     *
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($e->eq($e->sub('id', 2), 12));
+     * </code>
+     *
+     * @param string|array(string)
+     * @return string an expression
+     */
+    public function sub(array $args)
+    {
+        return $this->basicMath('-', $args );
+    }
+
+    /**
+     * Returns the SQL to multiply values or expressions by eachother.
+     *
+     * multiply() accepts an arbitrary number of parameters. Each parameter
+     * must contain a value or an expression or an array with values or
+     * expressions.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $e = $q->expr;
+     *
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($e->eq($e->mul('id', 2), 12));
+     * </code>
+     *
+     * @param string|array(string)
+     * @return string an expression
+     */
+    public function mul(array $args)
+    {
+        return $this->basicMath('*', $args);
+    }
+
+    /**
+     * Returns the SQL to divide values or expressions by eachother.
+     *
+     * divide() accepts an arbitrary number of parameters. Each parameter
+     * must contain a value or an expression or an array with values or
+     * expressions.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $e = $q->expr;
+     *
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($e->eq($e->div('id', 2), 12));
+     * </code>
+     *
+     * @param string|array(string)
+     * @return string an expression
+     */
+    public function div(array $args)
+    {
+        return $this->basicMath('/', $args);
+    }
+
+    /**
+     * Returns the SQL to check if two values are equal.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($q->expr->eq('id', 1));
+     * </code>
+     *
+     * @param string $value1 logical expression to compare
+     * @param string $value2 logical expression to compare with
+     * @return string logical expression
+     */
+    public function eq($value1, $value2)
+    {
+        $value1 = $this->getIdentifier($value1);
+        $value2 = $this->getIdentifier($value2);
+        return $value1 . ' = ' . $value2;
+    }
+
+    /**
+     * Returns the SQL to check if two values are unequal.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($q->expr->neq('id', 1));
+     * </code>
+     *
+     * @param string $value1 logical expression to compare
+     * @param string $value2 logical expression to compare with
+     * @return string logical expression
+     */
+    public function neq($value1, $value2)
+    {
+        $value1 = $this->getIdentifier($value1);
+        $value2 = $this->getIdentifier($value2);
+        return $value1 . ' <> ' . $value2;
+    }
+
+    /**
+     * Returns the SQL to check if one value is greater than another value.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($q->expr->gt('id', 1));
+     * </code>
+     *
+     * @param string $value1 logical expression to compare
+     * @param string $value2 logical expression to compare with
+     * @return string logical expression
+     */
+    public function gt($value1, $value2)
+    {
+        $value1 = $this->getIdentifier($value1);
+        $value2 = $this->getIdentifier($value2);
+        return $value1 . ' > ' . $value2;
+    }
+
+    /**
+     * Returns the SQL to check if one value is greater than or equal to
+     * another value.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($q->expr->gte('id', 1));
+     * </code>
+     *
+     * @param string $value1 logical expression to compare
+     * @param string $value2 logical expression to compare with
+     * @return string logical expression
+     */
+    public function gte($value1, $value2)
+    {
+        $value1 = $this->getIdentifier($value1);
+        $value2 = $this->getIdentifier($value2);
+        return $value1 . ' >= ' . $value2;
+    }
+
+    /**
+     * Returns the SQL to check if one value is less than another value.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($q->expr->lt('id', 1));
+     * </code>
+     *
+     * @param string $value1        logical expression to compare
+     * @param string $value2        logical expression to compare with
+     * @return string logical expression
+     */
+    public function lt($value1, $value2)
+    {
+        $value1 = $this->getIdentifier($value1);
+        $value2 = $this->getIdentifier($value2);
+        return $value1 . ' < ' . $value2;
+    }
+
+    /**
+     * Returns the SQL to check if one value is less than or equal to
+     * another value.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($q->expr->lte('id', 1));
+     * </code>
+     *
+     * @param string $value1        logical expression to compare
+     * @param string $value2        logical expression to compare with
+     * @return string logical expression
+     */
+    public function lte($value1, $value2)
+    {
+        $value1 = $this->getIdentifier($value1);
+        $value2 = $this->getIdentifier($value2);
+        return $value1 . ' <= ' . $value2;
+    }
+
+    /**
+     * Returns the SQL to check if a value is one in a set of
+     * given values..
+     *
+     * in() accepts an arbitrary number of parameters. The first parameter
+     * must always specify the value that should be matched against. Successive
+     * must contain a logical expression or an array with logical expressions.
+     * These expressions will be matched against the first parameter.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($q->expr->in( 'id', array(1,2,3)));
+     * </code>
+     *
+     * @param string $column        the value that should be matched against
+     * @param string|array(string)  values that will be matched against $column
+     * @return string logical expression
+     */
+    public function in($column, $values)
+    {
+        if ( ! is_array($values)) {
+            $values = array($values);
+        }
+        $values = $this->getIdentifiers($values);
+        $column = $this->getIdentifier($column);
+
+        if (count($values) == 0) {
+            throw new Doctrine_Expression_Exception('Values array for IN operator should not be empty.');
+        }
+        return $column . ' IN (' . implode(', ', $values) . ')';
+    }
+
+    /**
+     * Returns SQL that checks if a expression is null.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($q->expr->isNull('id'));
+     * </code>
+     *
+     * @param string $expression the expression that should be compared to null
+     * @return string logical expression
+     */
+    public function isNull($expression)
+    {
+        $expression = $this->getIdentifier($expression);
+        return $expression . ' IS NULL';
+    }
+
+    /**
+     * Returns SQL that checks if a expression is not null.
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($q->expr->isNotNull('id'));
+     * </code>
+     *
+     * @param string $expression the expression that should be compared to null
+     * @return string logical expression
+     */
+    public function isNotNull($expression)
+    {
+        $expression = $this->getIdentifier($expression);
+        return $expression . ' IS NOT NULL';
+    }
+
+    /**
+     * Returns SQL that checks if an expression evaluates to a value between
+     * two values.
+     *
+     * The parameter $expression is checked if it is between $value1 and $value2.
+     *
+     * Note: There is a slight difference in the way BETWEEN works on some databases.
+     * http://www.w3schools.com/sql/sql_between.asp. If you want complete database
+     * independence you should avoid using between().
+     *
+     * Example:
+     * <code>
+     * $q = new Doctrine_Query();
+     * $q->select('u.*')
+     *   ->from('User u')
+     *   ->where($q->expr->between('id', 1, 5));
+     * </code>
+     *
+     * @param string $expression the value to compare to
+     * @param string $value1 the lower value to compare with
+     * @param string $value2 the higher value to compare with
+     * @return string logical expression
+     */
+    public function between($expression, $value1, $value2)
+    {
+        $expression = $this->getIdentifier($expression);
+        $value1 = $this->getIdentifier($value1);
+        $value2 = $this->getIdentifier($value2);
+        return $expression . ' BETWEEN ' .$value1 . ' AND ' . $value2;
+    }
+
+    /**
+     * Returns global unique identifier
+     *
+     * @return string to get global unique identifier
+     */
+    public function guid()
+    {
+        throw new Doctrine_Expression_Exception('method not implemented');
+    }
+
+    /**
+     * returns arcus cosine SQL string
+     *
+     * @return string
+     */
+    public function acos($value)
+    {
+        return 'ACOS(' . $value . ')';
+    }
+
+    /**
+     * sin
+     *
+     * @param string $value 
+     * @return void
+     */
+    public function sin($value)
+    {
+        return 'SIN(' . $value . ')';
+    }
+
+    /**
+     * pi
+     *
+     * @return void
+     */
+    public function pi()
+    {
+        return 'PI()';
+    }
+
+    /**
+     * cos
+     *
+     * @param string $value 
+     * @return void
+     */
+    public function cos($value)
+    {
+        return 'COS(' . $value . ')';
+    }
+
+    /**
+     * coalesce
+     *
+     * @return string
+     */
+    public function coalesce()
+    {
+        $args = func_get_args();
+
+	    return 'COALESCE(' . join(', ', (array) $args) . ')';
+    }
+
+    /**
+     * __call
+     *
+     * for all native RDBMS functions the function name itself is returned
+     */
+    public function __call($m, $a) 
+    {
+        if ($this->conn->getAttribute(Doctrine::ATTR_PORTABILITY) & Doctrine::PORTABILITY_EXPR) {
+            throw new Doctrine_Expression_Exception('Unknown expression ' . $m);
+        }
+        return $m . '(' . implode(', ', $a) . ')';
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Expression_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Expression
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Expression_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Firebird.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,57 @@
+<?php
+/*
+ *  $Id: Firebird.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Expression_Firebird
+ *
+ * @package     Doctrine
+ * @subpackage  Expression
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lorenzo Alberton <l.alberton@quipo.it> (PEAR MDB2 Interbase driver)
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ */
+class Doctrine_Expression_Firebird extends Doctrine_Expression_Driver
+{
+    /**
+     * return string for internal table used when calling only a function
+     *
+     * @return string for internal table used when calling only a function
+     * @access public
+     */
+    public function functionTable()
+    {
+        return ' FROM RDB$DATABASE';
+    }
+
+    /**
+     * build string to define escape pattern string
+     *
+     * @return string define escape pattern
+     */
+    function patternEscapeString()
+    {
+        return " ESCAPE '". $this->conn->string_quoting['escape_pattern'] ."'";
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Informix.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Informix.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Expression_Informix
+ *
+ * @package     Doctrine
+ * @subpackage  Expression
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Expression_Informix extends Doctrine_Expression
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Mock.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,35 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Expression_Mock
+ * Mock driver that is used for testing purposes
+ *
+ * @package     Doctrine
+ * @subpackage  Expression
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Expression_Mock extends Doctrine_Expression_Driver
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Mssql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,104 @@
+<?php
+/*
+ *  $Id: Mssql.php 5836 2009-06-06 21:31:13Z guilhermeblanco $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Expression_Mssql
+ *
+ * @package     Doctrine
+ * @subpackage  Expression
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5836 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+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 . ')';
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Mysql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,160 @@
+<?php
+/*
+ *  $Id: Mysql.php 5837 2009-06-06 21:38:32Z guilhermeblanco $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Expression_Mysql
+ *
+ * @package     Doctrine
+ * @subpackage  Expression
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5837 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Expression_Mysql extends Doctrine_Expression_Driver
+{
+    /**
+     * returns the regular expression operator
+     *
+     * @return string
+     */
+    public function regexp()
+    {
+        return 'RLIKE';
+    }
+
+    /**
+     * return string to call a function to get random value inside an SQL statement
+     *
+     * @return string to generate float between 0 and 1
+     */
+    public function random()
+    {
+        return 'RAND()';
+    }
+
+    /**
+     * build a pattern matching string
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change signature at
+     * any time until labelled as non-experimental
+     *
+     * @access public
+     *
+     * @param array $pattern even keys are strings, odd are patterns (% and _)
+     * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
+     * @param string $field optional field name that is being matched against
+     *                  (might be required when emulating ILIKE)
+     *
+     * @return string SQL pattern
+     */
+    public function matchPattern($pattern, $operator = null, $field = null)
+    {
+        $match = '';
+        if ( ! is_null($operator)) {
+            $field = is_null($field) ? '' : $field.' ';
+            $operator = strtoupper($operator);
+            switch ($operator) {
+                // case insensitive
+                case 'ILIKE':
+                    $match = $field.'LIKE ';
+                    break;
+                // case sensitive
+                case 'LIKE':
+                    $match = $field.'LIKE BINARY ';
+                    break;
+                default:
+                    throw new Doctrine_Expression_Mysql_Exception('not a supported operator type:'. $operator);
+            }
+        }
+        $match.= "'";
+        foreach ($pattern as $key => $value) {
+            if ($key % 2) {
+                $match .= $value;
+            } else {
+                $match .= $this->conn->escapePattern($this->conn->escape($value));
+            }
+        }
+        $match.= "'";
+        $match.= $this->patternEscapeString();
+        return $match;
+    }
+
+    /**
+     * Returns global unique identifier
+     *
+     * @return string to get global unique identifier
+     */
+    public function guid()
+    {
+        return 'UUID()';
+    }
+
+    /**
+     * Returns the year from dbms
+     *
+     * @param string $column 
+     * @return string to get year from dbms
+     */
+    public function year($column)
+    {
+        $column = $this->getIdentifier($column);
+        return 'YEAR(' .  $column . ')';
+    }
+
+    /**
+     * Returns the month from dbms
+     *
+     * @param string $column 
+     * @return string to get month from dbms
+     */
+    public function month($column)
+    {
+        $column = $this->getIdentifier($column);
+        return 'MONTH(' .  $column . ')';
+    }
+
+    /**
+     * Returns day from dbms
+     *
+     * @param string $column
+     * @return string to get day from dbms
+     */
+    public function day($column)
+    {
+        $column = $this->getIdentifier($column);
+        return 'DAY(' .  $column . ')';
+    }
+
+    /**
+     * Returns soundex from dbms
+     *
+     * @param string $column
+     * @return string to get soundex from dbms
+     */
+    public function soundex($column)
+    {
+        return 'SOUNDEX(' . $column . ')';
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Oracle.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,108 @@
+<?php
+/*
+ *  $Id: Oracle.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Expression_Sqlite
+ *
+ * @package     Doctrine
+ * @subpackage  Expression
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Expression_Oracle extends Doctrine_Expression_Driver
+{
+    /**
+     * Returns a series of strings concatinated
+     *
+     * concat() accepts an arbitrary number of parameters. Each parameter
+     * must contain an expression
+     *
+     * @param string $arg1, $arg2 ... $argN     strings that will be concatinated.
+     * @return string
+     */
+    public function concat()
+    {
+        $args = func_get_args();
+
+        return join(' || ' , $args);
+    }
+
+    /**
+     * return string to call a function to get a substring inside an SQL statement
+     *
+     * Note: Not SQL92, but common functionality.
+     *
+     * @param string $value         an sql string literal or column name/alias
+     * @param integer $position     where to start the substring portion
+     * @param integer $length       the substring portion length
+     * @return string               SQL substring function with given parameters
+     */
+    public function substring($value, $position, $length = null)
+    {
+        if ($length !== null)
+            return "SUBSTR($value, $position, $length)";
+
+        return "SUBSTR($value, $position)";
+    }
+
+    /**
+     * 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
+     */
+    public function now($type = 'timestamp')
+    {
+        switch ($type) {
+            case 'date':
+            case 'time':
+            case 'timestamp':
+            default:
+                return 'TO_CHAR(CURRENT_TIMESTAMP, \'YYYY-MM-DD HH24:MI:SS\')';
+        }
+    }
+
+    /**
+     * random
+     *
+     * @return string           an oracle SQL string that generates a float between 0 and 1
+     */
+    public function random()
+    {
+        return 'dbms_random.value';
+    }
+
+    /**
+     * Returns global unique identifier
+     *
+     * @return string to get global unique identifier
+     */
+    public function guid()
+    {
+        return 'SYS_GUID()';
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Pgsql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,233 @@
+<?php
+/*
+ *  $Id: Pgsql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Expression_Pgsql
+ *
+ * @package     Doctrine
+ * @subpackage  Expression
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+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:
+     * <code>
+     * psql [dbname] < /usr/share/pgsql/contrib/pgcrypto.sql
+     * </code>
+     * 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(<timestamp1> [, <timestamp2>]) 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( <text>, <time> ) function.
+     *
+     * @param string $text what to extract
+     * @param string $time timestamp or interval to extract from
+     * @return string
+     */
+    public function date_part($text, $time) {
+        return 'DATE_PART(' . $text . ', ' . $time . ')';
+    }
+
+
+    /**
+     * PostgreSQLs TO_CHAR( <time>, <text> ) function.
+     *
+     * @param string $time timestamp or interval
+     * @param string $text how to the format the output
+     * @return string
+     */
+    public function to_char($time, $text) {
+        return 'TO_CHAR(' . $time . ', ' . $text . ')';
+    }
+
+    /**
+     * PostgreSQLs CONCAT() function
+     *
+     * @param  an array of values
+     * @return string
+     */
+    public function concat()
+    {
+        $args = func_get_args();
+
+        return join(' || ' , $args);
+    }
+
+    /**
+     * Returns the SQL string to return the current system date and time.
+     *
+     * @return string
+     */
+    public function now()
+    {
+        return 'LOCALTIMESTAMP(0)';
+    }
+
+    /**
+     * regexp
+     *
+     * @return string           the regular expression operator
+     */
+    public function regexp()
+    {
+        return 'SIMILAR TO';
+    }
+
+    /**
+     * return string to call a function to get random value inside an SQL statement
+     *
+     * @return return string to generate float between 0 and 1
+     * @access public
+     */
+    public function random()
+    {
+        return 'RANDOM()';
+    }
+
+    /**
+     * build a pattern matching string
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change signature at
+     * any time until labelled as non-experimental
+     *
+     * @access public
+     *
+     * @param array $pattern even keys are strings, odd are patterns (% and _)
+     * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
+     * @param string $field optional field name that is being matched against
+     *                  (might be required when emulating ILIKE)
+     *
+     * @return string SQL pattern
+     */
+    public function matchPattern($pattern, $operator = null, $field = null)
+    {
+        $match = '';
+        if ( ! is_null($operator)) {
+            $field = is_null($field) ? '' : $field.' ';
+            $operator = strtoupper($operator);
+            switch ($operator) {
+                // case insensitive
+            case 'ILIKE':
+                $match = $field.'ILIKE ';
+                break;
+                // case sensitive
+            case 'LIKE':
+                $match = $field.'LIKE ';
+                break;
+            default:
+                throw new Doctrine_Expression_Pgsql_Exception('not a supported operator type:'. $operator);
+            }
+        }
+        $match.= "'";
+        foreach ($pattern as $key => $value) {
+            if ($key % 2) {
+                $match.= $value;
+            } else {
+                $match.= $this->conn->escapePattern($this->conn->escape($value));
+            }
+        }
+        $match.= "'";
+        $match.= $this->patternEscapeString();
+        return $match;
+    }
+
+    /**
+     * return syntax for pgsql TRANSLATE() dbms function
+     *
+     * @return string $sql
+     */
+    public function translate($string, $from, $to)
+    {
+    	$translate = 'TRANSLATE(' . $string . ', ' . $from . ', ' . $to . ')';
+    	return $translate;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Expression/Sqlite.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,172 @@
+<?php
+/*
+ *  $Id: Sqlite.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Expression_Sqlite
+ *
+ * @package     Doctrine
+ * @subpackage  Expression
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Expression_Sqlite extends Doctrine_Expression_Driver
+{
+    /**
+     * Returns the md5 sum of the data that SQLite's md5() function receives.
+     *
+     * @param mixed $data
+     * @return string
+     */
+    public static function md5Impl($data)
+    {
+        return md5($data);
+    }
+
+    /**
+     * Returns the modules of the data that SQLite's mod() function receives.
+     *
+     * @param integer $dividend
+     * @param integer $divisor
+     * @return string
+     */
+    public static function modImpl($dividend, $divisor)
+    {
+        return $dividend % $divisor;
+    }
+
+    /**
+     * Returns a concatenation of the data that SQLite's concat() function receives.
+     *
+     * @return string
+     */
+    public static function concatImpl()
+    {
+        $args = func_get_args();
+        return join('', $args);
+    }
+
+    /**
+     * locate
+     * returns the position of the first occurrence of substring $substr in string $str that
+     * SQLite's locate() function receives
+     *
+     * @param string $substr    literal string to find
+     * @param string $str       literal string
+     * @return string
+     */
+    public static function locateImpl($substr, $str)
+    {
+        return strpos($str, $substr);
+    }
+    public static function sha1Impl($str)
+    {
+        return sha1($str);
+    }
+    public static function ltrimImpl($str)
+    {
+        return ltrim($str);
+    }
+    public static function rtrimImpl($str)
+    {
+        return rtrim($str);
+    }
+    public static function trimImpl($str)
+    {
+        return trim($str);
+    }
+
+    /**
+     * returns the regular expression operator
+     *
+     * @return string
+     */
+    public function regexp()
+    {
+        return 'RLIKE';
+    }
+
+    /**
+     * soundex
+     * Returns a string to call a function to compute the
+     * soundex encoding of a string
+     *
+     * The string "?000" is returned if the argument is NULL.
+     *
+     * @param string $value
+     * @return string   SQL soundex function with given parameter
+     */
+    public function soundex($value)
+    {
+        return 'SOUNDEX(' . $value . ')';
+    }
+
+    /**
+     * Return string to call a variable with the current timestamp inside an SQL statement
+     * There are three special variables for current date and time.
+     *
+     * @return string       sqlite function as string
+     */
+    public function now($type = 'timestamp')
+    {
+        switch ($type) {
+            case 'time':
+                return 'time(\'now\')';
+            case 'date':
+                return 'date(\'now\')';
+            case 'timestamp':
+            default:
+                return 'datetime(\'now\')';
+        }
+    }
+
+    /**
+     * return string to call a function to get random value inside an SQL statement
+     *
+     * @return string to generate float between 0 and 1
+     */
+    public function random()
+    {
+        return '((RANDOM() + 2147483648) / 4294967296)';
+    }
+
+    /**
+     * return string to call a function to get a substring inside an SQL statement
+     *
+     * Note: Not SQL92, but common functionality.
+     *
+     * SQLite only supports the 2 parameter variant of this function
+     *
+     * @param string $value         an sql string literal or column name/alias
+     * @param integer $position     where to start the substring portion
+     * @param integer $length       the substring portion length
+     * @return string               SQL substring function with given parameters
+     */
+    public function substring($value, $position, $length = null)
+    {
+        if ($length !== null) {
+            return 'SUBSTR(' . $value . ', ' . $position . ', ' . $length . ')';
+        }
+        return 'SUBSTR(' . $value . ', ' . $position . ', LENGTH(' . $value . '))';
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/File.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,53 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_File
+ *
+ * @package     Doctrine
+ * @subpackage  File
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_File extends Doctrine_Record
+{
+    public function setTableDefinition()
+    {
+        $this->hasColumn('url', 'string', 255);
+    }
+    public function setUp()
+    {
+        $this->actAs('Searchable', array('className' => 'Doctrine_File_Index',
+                                         'fields' => array('url', 'content')));
+        
+        $this->index('url', array('fields' => array('url')));
+    }
+    public function get($name, $load = true)
+    {
+        if ($name === 'content') {
+            return file_get_contents(parent::get('url'));
+        }
+        return parent::get($name, $load);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/File/Index.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,56 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_File_Index
+ *
+ * @package     Doctrine
+ * @subpackage  File
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_File_Index extends Doctrine_Record
+{
+    public function setTableDefinition()
+    {
+        $this->hasColumn('keyword', 'string', 255, array('notnull' => true,
+                                                         'primary' => true));
+                                                         
+        $this->hasColumn('field', 'string', 50, array('notnull' => true,
+                                                      'primary' => true));
+
+        $this->hasColumn('position', 'string', 255, array('notnull' => true,
+                                                          'primary' => true));
+                                                          
+        $this->hasColumn('file_id', 'integer', 8, array('notnull' => true,
+                                                        'primary' => true));
+    }
+    public function setUp()
+    {
+        $this->hasOne('Doctrine_File', array('local' => 'file_id',
+                                             'foreign' => 'id',
+                                             'onDelete' => 'CASCADE',
+                                             'onUpdate' => 'CASCADE'));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Formatter.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,265 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Formatter
+ *
+ * @package     Doctrine
+ * @subpackage  Formatter
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Formatter extends Doctrine_Connection_Module
+{
+    /**
+     * Quotes pattern (% and _) characters in a string)
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change signature at
+     * any time until labelled as non-experimental
+     *
+     * @param   string  the input string to quote
+     *
+     * @return  string  quoted string
+     */
+    public function escapePattern($text)
+    {
+        if ( ! $this->string_quoting['escape_pattern']) {
+            return $text;
+        }
+        $tmp = $this->conn->string_quoting;
+
+        $text = str_replace($tmp['escape_pattern'], 
+            $tmp['escape_pattern'] .
+            $tmp['escape_pattern'], $text);
+
+        foreach ($this->wildcards as $wildcard) {
+            $text = str_replace($wildcard, $tmp['escape_pattern'] . $wildcard, $text);
+        }
+        return $text;
+    }
+
+    /**
+     * convertBooleans
+     * 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 $k => $value) {
+                if (is_bool($value)) {
+                    $item[$k] = (int) $value;
+                }
+            }
+        } else {
+            if (is_bool($item)) {
+                $item = (int) $item;
+            }
+        }
+        return $item;
+    }
+
+    /**
+     * Quote a string so it can be safely used as a table or column name
+     *
+     * Delimiting style depends on which database driver is being used.
+     *
+     * NOTE: just because you CAN use delimited identifiers doesn't mean
+     * you SHOULD use them.  In general, they end up causing way more
+     * problems than they solve.
+     *
+     * Portability is broken by using the following characters inside
+     * delimited identifiers:
+     *   + backtick (<kbd>`</kbd>) -- due to MySQL
+     *   + double quote (<kbd>"</kbd>) -- due to Oracle
+     *   + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access
+     *
+     * Delimited identifiers are known to generally work correctly under
+     * the following drivers:
+     *   + mssql
+     *   + mysql
+     *   + mysqli
+     *   + oci8
+     *   + pgsql
+     *   + sqlite
+     *
+     * InterBase doesn't seem to be able to use delimited identifiers
+     * via PHP 4.  They work fine under PHP 5.
+     *
+     * @param string $str           identifier name to be quoted
+     * @param bool $checkOption     check the 'quote_identifier' option
+     *
+     * @return string               quoted identifier string
+     */
+    public function quoteIdentifier($str, $checkOption = true)
+    {
+        if ($checkOption && ! $this->conn->getAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER)) {
+            return $str;
+        }
+        $tmp = $this->conn->identifier_quoting;
+        $str = str_replace($tmp['end'],
+            $tmp['escape'] .
+            $tmp['end'], $str);
+
+        return $tmp['start'] . $str . $tmp['end'];
+    }
+    
+    
+    /**
+     * quoteMultipleIdentifier
+     * Quotes multiple identifier strings
+     *
+     * @param array $arr           identifiers array to be quoted
+     * @param bool $checkOption     check the 'quote_identifier' option
+     *
+     * @return string               quoted identifier string
+     */
+    public function quoteMultipleIdentifier($arr, $checkOption = true)
+    {
+        foreach ($arr as $k => $v) {
+            $arr[$k] = $this->quoteIdentifier($v, $checkOption);
+        }
+
+		return $arr;
+    }
+
+
+    /**
+     * quote
+     * quotes given input parameter
+     *
+     * @param mixed $input      parameter to be quoted
+     * @param string $type
+     * @return mixed
+     */
+    public function quote($input, $type = null)
+    {
+        if ($type == null) {
+            $type = gettype($input);
+        }
+        switch ($type) {
+        case 'integer':
+        case 'double':
+        case 'float':
+        case 'bool':
+        case 'decimal':
+        case 'int':
+            return $input;
+        case 'array':
+        case 'object':
+            $input = serialize($input);
+        case 'date':
+        case 'time':
+        case 'timestamp':
+        case 'string':
+        case 'char':
+        case 'varchar':
+        case 'text':
+        case 'gzip':
+        case 'blob':
+        case 'clob':
+        case 'enum':
+        case 'boolean':
+            $this->conn->connect();
+
+            return $this->conn->getDbh()->quote($input);
+        }
+    }
+
+    /**
+     * Removes any formatting in an sequence name using the 'seqname_format' option
+     *
+     * @param string $sqn string that containts name of a potential sequence
+     * @return string name of the sequence with possible formatting removed
+     */
+    public function fixSequenceName($sqn)
+    {
+        $seqPattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)',  $this->conn->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT)).'$/i';
+        $seqName    = preg_replace($seqPattern, '\\1', $sqn);
+
+        if ($seqName && ! strcasecmp($sqn, $this->getSequenceName($seqName))) {
+            return $seqName;
+        }
+        return $sqn;
+    }
+
+    /**
+     * Removes any formatting in an index name using the 'idxname_format' option
+     *
+     * @param string $idx string that containts name of anl index
+     * @return string name of the index with possible formatting removed
+     */
+    public function fixIndexName($idx)
+    {
+        $indexPattern   = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $this->conn->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT)).'$/i';
+        $indexName      = preg_replace($indexPattern, '\\1', $idx);
+        if ($indexName && ! strcasecmp($idx, $this->getIndexName($indexName))) {
+            return $indexName;
+        }
+        return $idx;
+    }
+
+    /**
+     * adds sequence name formatting to a sequence name
+     *
+     * @param string    name of the sequence
+     * @return string   formatted sequence name
+     */
+    public function getSequenceName($sqn)
+    {
+        return sprintf($this->conn->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT),
+            preg_replace('/[^a-z0-9_\$.]/i', '_', $sqn));
+    }
+
+    /**
+     * adds index name formatting to a index name
+     *
+     * @param string    name of the index
+     * @return string   formatted index name
+     */
+    public function getIndexName($idx)
+    {
+        return sprintf($this->conn->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT),
+            preg_replace('/[^a-z0-9_\$]/i', '_', $idx));
+    }
+
+    /**
+     * adds table name formatting to a table name
+     *
+     * @param string    name of the table
+     * @return string   formatted table name
+     */
+    public function getTableName($table)
+    {
+        return sprintf($this->conn->getAttribute(Doctrine::ATTR_TBLNAME_FORMAT),
+                $table);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hook.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,230 @@
+<?php
+/*
+ *  $Id: Hook.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Hook
+ *
+ * @package     Doctrine
+ * @subpackage  Hook
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Hook
+{
+    /**
+     * @var Doctrine_Query $query           the base query
+     */
+    protected $query;
+
+    /**
+     * @var array $joins                    the optional joins of the base query
+     */
+    protected $joins;
+
+    /**
+     * @var array $hooks                    hooks array
+     */
+    protected $hooks        = array(
+                             'where',
+                             'orderby',
+                             'limit',
+                             'offset'
+                              );
+
+    /**
+     * @var array $fieldParsers             custom field parsers array
+     *                                      keys as field names in the format componentAlias.FieldName
+     *                                      values as parser names / objects
+     */
+    protected $fieldParsers = array();
+
+    /**
+     * @var array $typeParsers              type parsers array
+     *                                      keys as type names and values as parser names / objects
+     */
+    protected $typeParsers  = array(
+                              'char'      => 'Doctrine_Hook_WordLike',
+                              'string'    => 'Doctrine_Hook_WordLike',
+                              'varchar'   => 'Doctrine_Hook_WordLike',
+                              'integer'   => 'Doctrine_Hook_Integer',
+                              'enum'      => 'Doctrine_Hook_Integer',
+                              'time'      => 'Doctrine_Hook_Time',
+                              'date'      => 'Doctrine_Hook_Date',
+                              );
+
+    /**
+     * @param Doctrine_Query $query         the base query
+     */
+    public function __construct($query)
+    {
+        if (is_string($query)) {
+            $this->query = new Doctrine_Query();
+            $this->query->parseQuery($query);
+        } elseif ($query instanceof Doctrine_Query) {
+            $this->query = $query;
+        } else {
+            throw new Doctrine_Exception('Constructor argument should be either Doctrine_Query object or valid DQL query');          
+        }
+        
+        $this->query->getQuery();
+    }
+
+    /**
+     * getQuery
+     *
+     * @return Doctrine_Query       returns the query object associated with this hook
+     */
+    public function getQuery()
+    {
+        return $this->query;
+    }
+
+    /**
+     * setTypeParser
+     *
+     * @param string $type              type name
+     * @param string|object $parser     parser name or custom parser object
+     */
+    public function setTypeParser($type, $parser) 
+    {
+        $this->typeParsers[$type] = $parser;
+    }
+
+    /**
+     * setFieldParser
+     *
+     * @param string $field             field name
+     * @param string|object $parser     parser name or custom parser object
+     */
+    public function setFieldParser($field, $parser)
+    {
+        $this->fieldParsers[$field] = $parser;
+    }
+
+    /**
+     * hookWhere
+     * builds DQL query where part from given parameter array
+     *
+     * @param array $params         an associative array containing field
+     *                              names and their values
+     * @return boolean              whether or not the hooking was
+     */
+    public function hookWhere($params)
+    {
+        if ( ! is_array($params)) {
+            return false;
+        }
+        foreach ($params as $name => $value) {
+            if ($value === '' || $value === '-') {
+                continue;
+            }
+            $e = explode('.', $name);
+
+            if (count($e) == 2) {
+                list($alias, $column) = $e;
+
+                $map   = $this->query->getAliasDeclaration($alias);
+                $table = $map['table'];
+
+                if ( ! $table) {
+                    throw new Doctrine_Exception('Unknown alias ' . $alias);
+                }
+
+                if ($def = $table->getDefinitionOf($column)) {
+
+                $def[0] = gettype($value);
+                    if (isset($this->typeParsers[$def[0]])) {
+                        $name   = $this->typeParsers[$def[0]];
+                        $parser = new $name;
+                    }
+
+                    $parser->parse($alias, $column, $value);
+
+                    $this->query->addWhere($parser->getCondition(), $parser->getParams());
+                }
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * hookOrderBy
+     * builds DQL query orderby part from given parameter array
+     *
+     * @param array $params         an array containing all fields which the built query
+     *                              should be ordered by
+     * @return boolean              whether or not the hooking was successful
+     */
+    public function hookOrderby($params)
+    {
+        if ( ! is_array($params)) {
+            return false;
+        }
+        foreach ($params as $name) {
+            $e = explode(' ', $name);
+
+            $order = 'ASC';
+
+            if (count($e) > 1) {
+                $order = ($e[1] == 'DESC') ? 'DESC' : 'ASC';
+            }
+
+            $e = explode('.', $e[0]);
+
+            if (count($e) == 2) {
+                list($alias, $column) = $e;
+
+                $map   = $this->query->getAliasDeclaration($alias);
+                $table = $map['table'];
+
+                if ($def = $table->getDefinitionOf($column)) {   
+                    $this->query->addOrderBy($alias . '.' . $column . ' ' . $order);
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * set the hook limit 
+     * 
+     * @param integer $limit 
+     * @return void
+     */
+    public function hookLimit($limit)
+    {
+        $this->query->limit((int) $limit);
+    }
+
+    /**
+     * set the hook offset
+     *
+     * @param integer $offset
+     */
+    public function hookOffset($offset)
+    {
+        $this->query->offset((int) $offset);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hook/Equal.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,52 @@
+<?php
+/*
+ *  $Id: Equal.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Hook_Equal
+ *
+ * @package     Doctrine
+ * @subpackage  Hook
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Hook_Equal extends Doctrine_Hook_Parser
+{
+    /**
+     * parse
+     * Parses given field and field value to DQL condition
+     * and parameters. This method should always return
+     * prepared statement conditions (conditions that use
+     * placeholders instead of literal values).
+     *
+     * @param string $alias     component alias
+     * @param string $field     the field name
+     * @param mixed $value      the value of the field
+     * @return void
+     */
+    public function parse($alias, $field, $value)
+    {
+        $this->params    = (array) $value;
+        $this->condition = $alias . '.' . $field . ' = ?';
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hook/Integer.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,75 @@
+<?php
+/*
+ *  $Id: Integer.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Hook_Integer
+ *
+ * @package     Doctrine
+ * @subpackage  Hook
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Hook_Integer extends Doctrine_Hook_Parser_Complex
+{
+    /**
+     * parse
+     * Parses given field and field value to DQL condition
+     * and parameters. This method should always return
+     * prepared statement conditions (conditions that use
+     * placeholders instead of literal values).
+     *
+     * @param string $alias     component alias
+     * @param string $field     the field name
+     * @param mixed $value      the value of the field
+     * @return void
+     */
+    public function parseSingle($alias, $field, $value)
+    {
+        $e = explode(' ', $value);
+
+        foreach ($e as $v) {
+             $v = trim($v);
+
+             $e2   = explode('-', $v);
+
+            $name = $alias. '.' . $field;
+
+             if (count($e2) == 1) {
+                 // one '-' found
+
+                $a[] = $name . ' = ?';
+
+                $this->params[] = $v;
+            } else {
+                // more than one '-' found
+
+                $a[] = '(' . $name . ' > ? AND ' . $name . ' < ?)';
+
+                $this->params += array($e2[0], $e2[1]);
+            }
+
+        }
+        return implode(' OR ', $a);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hook/Parser.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,67 @@
+<?php
+/*
+ *  $Id: Parser.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Hook_Parser
+ *
+ * @package     Doctrine
+ * @subpackage  Hook
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+abstract class Doctrine_Hook_Parser
+{
+    protected $condition;
+    protected $params = array();
+
+    public function getCondition()
+    {
+        return $this->condition;
+    }
+
+    /**
+     * getParams
+     * returns the parameters associated with this parser
+     *
+     * @return array
+     */
+    public function getParams()
+    {
+        return $this->params;
+    }
+
+    /**
+     * parse
+     * Parses given field and field value to DQL condition
+     * and parameters. This method should always return
+     * prepared statement conditions (conditions that use
+     * placeholders instead of literal values).
+     *
+     * @param string $alias     component alias
+     * @param string $field     the field name
+     * @param mixed $value      the value of the field
+     * @return void
+     */
+    abstract public function parse($alias, $field, $value);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hook/Parser/Complex.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,107 @@
+<?php
+/*
+ *  $Id: Complex.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Hook_Parser_Complex
+ *
+ * @package     Doctrine
+ * @subpackage  Hook
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+abstract class Doctrine_Hook_Parser_Complex extends Doctrine_Hook_Parser
+{
+    protected $_tokenizer;
+    
+    /**
+     * Constructor.
+     */
+    public function __construct()
+    {
+        $this->_tokenizer = new Doctrine_Query_Tokenizer();
+    }
+    
+    /**
+     * parse
+     * Parses given field and field value to DQL condition
+     * and parameters. This method should always return
+     * prepared statement conditions (conditions that use
+     * placeholders instead of literal values).
+     *
+     * @param string $alias     component alias
+     * @param string $field     the field name
+     * @param mixed $value      the value of the field
+     * @return void
+     */
+    public function parse($alias, $field, $value)
+    {
+        $this->condition = $this->parseClause($alias, $field, $value);
+    }
+
+    /**
+     * parseClause
+     *
+     * @param string $alias     component alias
+     * @param string $field     the field name
+     * @param mixed $value      the value of the field
+     * @return void
+     */
+    public function parseClause($alias, $field, $value)
+    {
+        $parts = $this->_tokenizer->quoteExplode($value, ' AND ');
+
+        if (count($parts) > 1) {
+            $ret = array();
+            foreach ($parts as $part) {
+                $ret[] = $this->parseSingle($alias, $field, $part);
+            }
+
+            $r = implode(' AND ', $ret);
+        } else {
+            $parts = $this->_tokenizer->quoteExplode($value, ' OR ');
+            if (count($parts) > 1) {
+                $ret = array();
+                foreach ($parts as $part) {
+                    $ret[] = $this->parseClause($alias, $field, $part);
+                }
+
+                $r = implode(' OR ', $ret);
+            } else {
+                $ret = $this->parseSingle($alias, $field, $parts[0]);
+                return $ret;
+            }
+        }
+        return '(' . $r . ')';
+    }
+
+    /**
+     * parseSingle
+     *
+     * @param string $alias     component alias
+     * @param string $field     the field name
+     * @param mixed $value      the value of the field
+     * @return void
+     */
+    abstract public function parseSingle($alias, $field, $value);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hook/WordLike.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,66 @@
+<?php
+/*
+ *  $Id: WordLike.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Hook_WordLike
+ *
+ * @package     Doctrine
+ * @subpackage  Hook
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Hook_WordLike extends Doctrine_Hook_Parser_Complex
+{
+    /**
+     * parse
+     * Parses given field and field value to DQL condition
+     * and parameters. This method should always return
+     * prepared statement conditions (conditions that use
+     * placeholders instead of literal values).
+     *
+     * @param string $alias     component alias
+     * @param string $field     the field name
+     * @param mixed $value      the value of the field
+     * @return void
+     */
+    public function parseSingle($alias, $field, $value)
+    {
+        if (strpos($value, "'") !== false) {
+            $value = $this->_tokenizer->bracketTrim($value, "'", "'");
+        
+            $a[]   = $alias . '.' . $field . ' LIKE ?';
+            $this->params[] = '%' . $value . '%';
+
+        } else {
+            $e2 = explode(' ',$value);
+    
+            foreach ($e2 as $v) {
+                $v = trim($v);
+                $a[] = $alias . '.' . $field . ' LIKE ?';
+                $this->params[] = '%' . $v . '%';
+            }
+        }
+        return implode(' OR ', $a);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hydrator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,337 @@
+<?php
+/*
+ *  $Id: Hydrate.php 3192 2007-11-19 17:55:23Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Its purpose is to populate object graphs.
+ *
+ *
+ * @package     Doctrine
+ * @subpackage  Hydrate
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3192 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
+{
+    protected $_rootAlias = null;
+    /**
+     * hydrateResultSet
+     * parses the data returned by statement object
+     *
+     * This is method defines the core of Doctrine's object population algorithm
+     * hence this method strives to be as fast as possible
+     *
+     * The key idea is the loop over the rowset only once doing all the needed operations
+     * within this massive loop.
+     *
+     * @todo: Detailed documentation. Refactor (too long & nesting level).
+     *
+     * @param mixed $stmt
+     * @param array $tableAliases  Array that maps table aliases (SQL alias => DQL alias)
+     * @param array $aliasMap  Array that maps DQL aliases to their components
+     *                         (DQL alias => array(
+     *                              'table' => Table object,
+     *                              'parent' => Parent DQL alias (if any),
+     *                              'relation' => Relation object (if any),
+     *                              'map' => Custom index to use as the key in the result (if any)
+     *                              )
+     *                         )
+     * @return array
+     */
+    public function hydrateResultSet($stmt, $tableAliases)
+    {
+        $hydrationMode = $this->_hydrationMode;
+
+        $this->_tableAliases = $tableAliases;
+
+        if ($hydrationMode == Doctrine::HYDRATE_NONE) {
+            return $stmt->fetchAll(PDO::FETCH_NUM);
+        }
+
+        if ($hydrationMode == Doctrine::HYDRATE_ARRAY) {
+            $driver = new Doctrine_Hydrator_ArrayDriver();
+        } else {
+            $driver = new Doctrine_Hydrator_RecordDriver();
+        }
+
+        // Used variables during hydration
+        reset($this->_queryComponents);
+        $rootAlias = key($this->_queryComponents);
+        $this->_rootAlias = $rootAlias;
+        $rootComponentName = $this->_queryComponents[$rootAlias]['table']->getComponentName();
+        // if only one component is involved we can make our lives easier
+        $isSimpleQuery = count($this->_queryComponents) <= 1;
+        // Holds the resulting hydrated data structure
+        $result = array();
+        // Holds hydration listeners that get called during hydration
+        $listeners = array();
+        // Lookup map to quickly discover/lookup existing records in the result
+        $identifierMap = array();
+        // Holds for each component the last previously seen element in the result set
+        $prev = array();
+        // holds the values of the identifier/primary key fields of components,
+        // separated by a pipe '|' and grouped by component alias (r, u, i, ... whatever)
+        // the $idTemplate is a prepared template. $id is set to a fresh template when
+        // starting to process a row.
+        $id = array();
+        $idTemplate = array();
+
+        $result = $driver->getElementCollection($rootComponentName);
+
+        if ($stmt === false || $stmt === 0) {
+            return $result;
+        }
+
+        // Initialize
+        foreach ($this->_queryComponents as $dqlAlias => $data) {
+            $componentName = $data['table']->getComponentName();
+            $listeners[$componentName] = $data['table']->getRecordListener();
+            $identifierMap[$dqlAlias] = array();
+            $prev[$dqlAlias] = null;
+            $idTemplate[$dqlAlias] = '';
+        }
+
+        $event = new Doctrine_Event(null, Doctrine_Event::HYDRATE, null);
+
+        // Process result set
+        $cache = array();
+        while ($data = $stmt->fetch(Doctrine::FETCH_ASSOC)) {
+            $id = $idTemplate; // initialize the id-memory
+            $nonemptyComponents = array();
+            $rowData = $this->_gatherRowData($data, $cache, $id, $nonemptyComponents);
+
+            //
+            // hydrate the data of the root component from the current row
+            //
+            $table = $this->_queryComponents[$rootAlias]['table'];
+            $componentName = $table->getComponentName();
+            // Ticket #1115 (getInvoker() should return the component that has addEventListener)
+            $event->setInvoker($table);
+            $event->set('data', $rowData[$rootAlias]);
+            $listeners[$componentName]->preHydrate($event);
+
+            $index = false;
+
+            // Check for an existing element
+            if ($isSimpleQuery || ! isset($identifierMap[$rootAlias][$id[$rootAlias]])) {
+                $element = $driver->getElement($rowData[$rootAlias], $componentName);
+                $event->set('data', $element);
+                $listeners[$componentName]->postHydrate($event);
+
+                // do we need to index by a custom field?
+                if ($field = $this->_getCustomIndexField($rootAlias)) {
+                    if ( ! isset($element[$field])) {
+                        throw new Doctrine_Hydrator_Exception("Couldn't hydrate. Found a non-existent key named '$field'.");
+                    } else if (isset($result[$element[$field]])) {
+                        throw new Doctrine_Hydrator_Exception("Couldn't hydrate. Found non-unique key mapping named '$field'.");
+                    }
+                    $result[$element[$field]] = $element;
+                } else {
+                    $result[] = $element;
+                }
+
+                $identifierMap[$rootAlias][$id[$rootAlias]] = $driver->getLastKey($result);
+            } else {
+                $index = $identifierMap[$rootAlias][$id[$rootAlias]];
+            }
+
+            $driver->setLastElement($prev, $result, $index, $rootAlias, false);
+            unset($rowData[$rootAlias]);
+
+            // end hydrate data of the root component for the current row
+
+
+            // $prev[$rootAlias] now points to the last element in $result.
+            // now hydrate the rest of the data found in the current row, that belongs to other
+            // (related) components.
+            foreach ($rowData as $dqlAlias => $data) {
+                $index = false;
+                $map = $this->_queryComponents[$dqlAlias];
+                $table = $map['table'];
+                $componentName = $table->getComponentName();
+                $event->set('data', $data);
+                $event->setInvoker($table);
+                $listeners[$componentName]->preHydrate($event);
+
+                // It would be nice if this could be moved to the query parser but I could not find a good place to implement it
+                if ( ! isset($map['parent'])) {
+                    throw new Doctrine_Hydrator_Exception(
+                        '"' . $componentName . '" with an alias of "' . $dqlAlias . '"' .
+                        ' in your query does not reference the parent component it is related to.'
+                    );
+                }
+
+                $parent = $map['parent'];
+                $relation = $map['relation'];
+                $relationAlias = $map['relation']->getAlias();
+
+                $path = $parent . '.' . $dqlAlias;
+
+                if ( ! isset($prev[$parent])) {
+                    unset($prev[$dqlAlias]); // Ticket #1228
+                    continue;
+                }
+
+                // check the type of the relation
+                if ( ! $relation->isOneToOne() && $driver->initRelated($prev[$parent], $relationAlias)) {
+                    $oneToOne = false;
+                    // append element
+                    if (isset($nonemptyComponents[$dqlAlias])) {
+                        $indexExists = isset($identifierMap[$path][$id[$parent]][$id[$dqlAlias]]);
+                        $index = $indexExists ? $identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false;
+                        $indexIsValid = $index !== false ? isset($prev[$parent][$relationAlias][$index]) : false;
+                        if ( ! $indexExists || ! $indexIsValid) {
+                            $element = $driver->getElement($data, $componentName);
+                            $event->set('data', $element);
+                            $listeners[$componentName]->postHydrate($event);
+
+                            if ($field = $this->_getCustomIndexField($dqlAlias)) {
+                                if ( ! isset($element[$field])) {
+                                    throw new Doctrine_Hydrator_Exception("Couldn't hydrate. Found a non-existent key named '$field'.");
+                                } else if (isset($prev[$parent][$relationAlias][$element[$field]])) {
+                                    throw new Doctrine_Hydrator_Exception("Couldn't hydrate. Found non-unique key mapping named '$field'.");
+                                }
+                                $prev[$parent][$relationAlias][$element[$field]] = $element;
+                            } else {
+                                $prev[$parent][$relationAlias][] = $element; 
+                            }
+                            $identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = $driver->getLastKey($prev[$parent][$relationAlias]);                            
+                        }
+                        // register collection for later snapshots
+                        $driver->registerCollection($prev[$parent][$relationAlias]);
+                    }
+                } else {
+                    // 1-1 relation
+                    $oneToOne = true;
+                    if ( ! isset($nonemptyComponents[$dqlAlias]) && ! isset($prev[$parent][$relationAlias])) {
+                        $prev[$parent][$relationAlias] = $driver->getNullPointer();
+                    } else if ( ! isset($prev[$parent][$relationAlias])) {
+                        $element = $driver->getElement($data, $componentName);
+
+						// [FIX] Tickets #1205 and #1237
+                        $event->set('data', $element);
+                        $listeners[$componentName]->postHydrate($event);
+
+                        $prev[$parent][$relationAlias] = $element;
+                    }
+                }
+                if ($prev[$parent][$relationAlias] !== null) {
+                    $coll =& $prev[$parent][$relationAlias];
+                    $driver->setLastElement($prev, $coll, $index, $dqlAlias, $oneToOne);
+                }
+            }
+        }
+
+        $stmt->closeCursor();
+        $driver->flush();
+        //$e = microtime(true);
+        //echo 'Hydration took: ' . ($e - $s) . ' for '.count($result).' records<br />';
+
+        return $result;
+    }
+
+    /**
+     * Puts the fields of a data row into a new array, grouped by the component
+     * they belong to. The column names in the result set are mapped to their
+     * field names during this procedure.
+     *
+     * @return array  An array with all the fields (name => value) of the data row,
+     *                grouped by their component (alias).
+     */
+    protected function _gatherRowData(&$data, &$cache, &$id, &$nonemptyComponents)
+    {
+        $rowData = array();
+
+        foreach ($data as $key => $value) {
+            // Parse each column name only once. Cache the results. 
+            if ( ! isset($cache[$key])) {
+                // check ignored names. fastest solution for now. if we get more we'll start
+                // to introduce a list.
+                if ($key == 'DOCTRINE_ROWNUM') continue;
+                $e = explode('__', $key);
+                $last = strtolower(array_pop($e));
+                $cache[$key]['dqlAlias'] = $this->_tableAliases[strtolower(implode('__', $e))];
+                $table = $this->_queryComponents[$cache[$key]['dqlAlias']]['table'];
+                $fieldName = $table->getFieldName($last);
+                $cache[$key]['fieldName'] = $fieldName;
+                if ($table->isIdentifier($fieldName)) {
+                    $cache[$key]['isIdentifier'] = true;
+                } else {
+                  $cache[$key]['isIdentifier'] = false;
+                }
+                $type = $table->getTypeOfColumn($last);
+                if ($type == 'integer' || $type == 'string') {
+                    $cache[$key]['isSimpleType'] = true;
+                } else {
+                    $cache[$key]['type'] = $type;
+                    $cache[$key]['isSimpleType'] = false;
+                }
+            }
+
+            $map = $this->_queryComponents[$cache[$key]['dqlAlias']];
+            $table = $map['table'];
+            $dqlAlias = $cache[$key]['dqlAlias'];
+            $fieldName = $cache[$key]['fieldName'];
+            $agg = false;
+            if (isset($this->_queryComponents[$dqlAlias]['agg'][$fieldName])) {
+                $fieldName = $this->_queryComponents[$dqlAlias]['agg'][$fieldName];
+                $agg = true;
+            }
+
+            if ($cache[$key]['isIdentifier']) {
+                $id[$dqlAlias] .= '|' . $value;
+            }
+
+            if ($cache[$key]['isSimpleType']) {
+                $rowData[$dqlAlias][$fieldName] = $value;
+            } else {
+                $rowData[$dqlAlias][$fieldName] = $table->prepareValue(
+                        $fieldName, $value, $cache[$key]['type']);
+            }
+
+            // Ticket #1380
+            // Hydrate aggregates in to the root component as well.
+            // So we know that all aggregate values will always be available in the root component
+            if ($agg) {
+                $rowData[$this->_rootAlias][$fieldName] = $rowData[$dqlAlias][$fieldName];
+            }
+
+            if ( ! isset($nonemptyComponents[$dqlAlias]) && $value !== null) {
+                $nonemptyComponents[$dqlAlias] = true;
+            }
+        }
+
+        return $rowData;
+    }
+
+    /**
+     * Gets the custom field used for indexing for the specified component alias.
+     *
+     * @return string  The field name of the field used for indexing or NULL
+     *                 if the component does not use any custom field indices.
+     */
+    protected function _getCustomIndexField($alias)
+    {
+        return isset($this->_queryComponents[$alias]['map']) ? $this->_queryComponents[$alias]['map'] : null;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hydrator/Abstract.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,124 @@
+<?php
+/*
+ *  $Id: Hydrate.php 3192 2007-11-19 17:55:23Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Hydrator_Abstract
+ *
+ * @package     Doctrine
+ * @subpackage  Hydrate
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3192 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+abstract class Doctrine_Hydrator_Abstract extends Doctrine_Locator_Injectable
+{
+    /**
+     * @var array $_aliasMap                    two dimensional array containing the map for query aliases
+     *      Main keys are component aliases
+     *
+     *          table               table object associated with given alias
+     *
+     *          relation            the relation object owned by the parent
+     *
+     *          parent              the alias of the parent
+     *
+     *          agg                 the aggregates of this component
+     *
+     *          map                 the name of the column / aggregate value this
+     *                              component is mapped to a collection
+     */
+    protected $_queryComponents = array();
+
+    /**
+     * The current hydration mode.
+     */
+    protected $_hydrationMode = Doctrine::HYDRATE_RECORD;
+
+    /**
+     * constructor
+     *
+     * @param Doctrine_Connection|null $connection
+     */
+    public function __construct() {}
+
+    /**
+     * Sets the fetchmode.
+     *
+     * @param integer $fetchmode  One of the Doctrine::HYDRATE_* constants.
+     */
+    public function setHydrationMode($hydrationMode)
+    {
+        $this->_hydrationMode = $hydrationMode;
+    }
+
+    /**
+     * Get the fetchmode
+     *
+     * @return integer $fetchMode One of the Doctrine::HYDRATE_* constants
+     */
+    public function getHydrationMode()
+    {
+        return $this->_hydrationMode;
+    }
+
+    /**
+     * setAliasMap
+     * sets the whole component alias map
+     *
+     * @param array $map            alias map
+     * @return Doctrine_Hydrate     this object
+     */
+    public function setQueryComponents(array $queryComponents)
+    {
+        $this->_queryComponents = $queryComponents;
+    }
+
+    /**
+     * getAliasMap
+     * returns the component alias map
+     *
+     * @return array    component alias map
+     */
+    public function getQueryComponents()
+    {
+        return $this->_queryComponents;
+    }
+
+    /**
+     * parseData
+     * parses the data returned by statement object
+     *
+     * This is method defines the core of Doctrine object population algorithm
+     * hence this method strives to be as fast as possible
+     *
+     * The key idea is the loop over the rowset only once doing all the needed operations
+     * within this massive loop.
+     *
+     * @todo: Can we refactor this function so that it is not so long and 
+     * nested?
+     *
+     * @param mixed $stmt
+     * @return array
+     */
+    abstract public function hydrateResultSet($stmt, $tableAliases);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hydrator/ArrayDriver.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,107 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Hydrate_Array
+ * defines an array fetching strategy for Doctrine_Hydrate
+ *
+ * @package     Doctrine
+ * @subpackage  Hydrate
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Hydrator_ArrayDriver
+{
+    public function getElementCollection($component)
+    {
+        return array();
+    }
+    public function getElement(array $data, $component)
+    {
+        return $data;
+    }
+    /*
+    public function isIdentifiable(array $data, Doctrine_Table $table)
+    {
+        return ( ! empty($data));
+    }
+    */
+    public function registerCollection($coll)
+    {
+
+    }
+    public function initRelated(array &$data, $name)
+    {
+        if ( ! isset($data[$name])) {
+            $data[$name] = array();
+        }
+        return true;
+    }
+    public function getNullPointer() 
+    {
+        return null;    
+    }
+    public function getLastKey(&$data)
+    {
+        end($data);
+        return key($data);
+    }
+    
+    /**
+     * sets the last element of given data array / collection
+     * as previous element
+     *
+     * @param boolean|integer $index
+     * @return void
+     * @todo Detailed documentation
+     */
+    public function setLastElement(&$prev, &$coll, $index, $dqlAlias, $oneToOne)
+    {
+        if ($coll === null) {
+            unset($prev[$dqlAlias]); // Ticket #1228
+            return;
+        }
+
+        if ($index !== false) {
+            // Link element at $index to previous element for the component
+            // identified by the DQL alias $alias
+            $prev[$dqlAlias] =& $coll[$index];
+            return;
+        }
+        
+        if ($coll) {
+            if ($oneToOne) {
+                $prev[$dqlAlias] =& $coll;
+            } else {
+                end($coll);
+                $prev[$dqlAlias] =& $coll[key($coll)];
+            }
+        }
+    }
+
+    public function flush()
+    {
+        
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hydrator/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 1080 2007-02-10 18:17:08Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Hydrator_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Hydrate
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Hydrator_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Hydrator/RecordDriver.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,171 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Hydrate_RecordDriver
+ * Hydration strategy used for creating collections of entity objects.
+ *
+ * @package     Doctrine
+ * @subpackage  Hydrate
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Roman Borschel <roman@code-factory.org>
+ */
+class Doctrine_Hydrator_RecordDriver extends Doctrine_Locator_Injectable
+{
+    protected $_collections = array();
+    protected $_tables = array();
+    private $_initializedRelations = array();
+
+    public function getElementCollection($component)
+    {
+        $coll = new Doctrine_Collection($component);
+        $this->_collections[] = $coll;
+
+        return $coll;
+    }
+
+    public function getLastKey($coll) 
+    {
+        $coll->end();
+        
+        return $coll->key();
+    }
+    
+    public function initRelated(Doctrine_Record $record, $name)
+    {
+        if ( ! isset($this->_initializedRelations[$record->getOid()][$name])) {
+            $relation = $record->getTable()->getRelation($name);
+            $coll = new Doctrine_Collection($relation->getTable()->getComponentName());
+            $coll->setReference($record, $relation);
+            $record[$name] = $coll;
+            $this->_initializedRelations[$record->getOid()][$name] = true;
+        }
+        return true;
+    }
+    
+    public function registerCollection(Doctrine_Collection $coll)
+    {
+        $this->_collections[] = $coll;
+    }
+    
+    public function getNullPointer() 
+    {
+        return self::$_null;
+    }
+    
+    public function getElement(array $data, $component)
+    {
+        $component = $this->_getClassNameToReturn($data, $component);
+        if ( ! isset($this->_tables[$component])) {
+            $this->_tables[$component] = Doctrine::getTable($component);
+            $this->_tables[$component]->setAttribute(Doctrine::ATTR_LOAD_REFERENCES, false);
+        }
+
+        $this->_tables[$component]->setData($data);
+        $record = $this->_tables[$component]->getRecord();
+
+        return $record;
+    }
+    
+    public function flush()
+    {
+        // take snapshots from all initialized collections
+        foreach ($this->_collections as $key => $coll) {
+            $coll->takeSnapshot();
+        }
+        foreach ($this->_tables as $table) {
+            $table->setAttribute(Doctrine::ATTR_LOAD_REFERENCES, true);
+        }
+        $this->_initializedRelations = null;
+        $this->_collections = null;
+        $this->_tables = null;
+    }
+    
+    /**
+     * sets the last element of given data array / collection
+     * as previous element
+     *
+     * @param boolean|integer $index
+     * @return void
+     * @todo Detailed documentation
+     */
+    public function setLastElement(&$prev, &$coll, $index, $dqlAlias, $oneToOne)
+    {
+        if ($coll === self::$_null) {
+            unset($prev[$dqlAlias]); // Ticket #1228
+            return;
+        }
+
+        if ($index !== false) {
+            // Link element at $index to previous element for the component
+            // identified by the DQL alias $alias
+            $prev[$dqlAlias] = $coll[$index];
+            return;
+        }
+        
+        if (count($coll) > 0) {
+            $prev[$dqlAlias] = $coll->getLast();
+        }
+    }
+    
+    /**
+     * Get the classname to return. Most often this is just the options['name']
+     *
+     * Check the subclasses option and the inheritanceMap for each subclass to see
+     * if all the maps in a subclass is met. If this is the case return that
+     * subclass name. If no subclasses match or if there are no subclasses defined
+     * return the name of the class for this tables record.
+     *
+     * @todo this function could use reflection to check the first time it runs
+     * if the subclassing option is not set.
+     *
+     * @return string The name of the class to create
+     *
+     */
+    protected function _getClassnameToReturn(array &$data, $component)
+    {
+        if ( ! isset($this->_tables[$component])) {
+            $this->_tables[$component] = Doctrine::getTable($component);
+            $this->_tables[$component]->setAttribute(Doctrine::ATTR_LOAD_REFERENCES, false);
+        }
+        
+        if ( ! ($subclasses = $this->_tables[$component]->getOption('subclasses'))) {
+            return $component;
+        }
+        
+        foreach ($subclasses as $subclass) {
+            $table = Doctrine::getTable($subclass);
+            $inheritanceMap = $table->getOption('inheritanceMap');
+            list($key, $value) = each($inheritanceMap);
+            $key = $this->_tables[$component]->getFieldName($key);
+            if ( ! isset($data[$key]) || $data[$key] != $value) {
+                continue;
+            } else {
+                return $table->getComponentName();
+            }
+        }
+        return $component;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/I18n.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,128 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_I18n
+ *
+ * @package     Doctrine
+ * @subpackage  I18n
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_I18n extends Doctrine_Record_Generator
+{
+    protected $_options = array(
+                            'className'     => '%CLASS%Translation',
+                            'fields'        => array(),
+                            'generateFiles' => false,
+                            'table'         => false,
+                            'pluginTable'   => false,
+                            'children'      => array(),
+                            'type'          => 'string',
+                            'length'        => 2,
+                            'options'       => array()
+                            );
+
+    /**
+     * __construct
+     *
+     * @param string $options 
+     * @return void
+     */
+    public function __construct($options)
+    {
+        $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
+    }
+
+    public function buildRelation()
+    {
+        $this->buildForeignRelation('Translation');
+        $this->buildLocalRelation();
+    }
+
+    /**
+     * buildDefinition
+     *
+     * @param object $Doctrine_Table
+     * @return void
+     */
+    public function setTableDefinition()
+    {
+      	if (empty($this->_options['fields'])) {
+      	    throw new Doctrine_I18n_Exception('Fields not set.');
+      	}
+
+        $options = array('className' => $this->_options['className']);
+
+        $cols = $this->_options['table']->getColumns();
+
+        $columns = array();
+        foreach ($cols as $column => $definition) {
+            $fieldName = $this->_options['table']->getFieldName($column);
+            if (in_array($fieldName, $this->_options['fields'])) {
+                if ($column != $fieldName) {
+                    $column .= ' as ' . $fieldName;
+                }
+                $columns[$column] = $definition;
+                $this->_options['table']->removeColumn($fieldName);
+            }
+        }
+
+        $this->hasColumns($columns);
+
+        $options = $this->_options['options'];
+        $options['fixed'] = true;
+        $options['primary'] = true;
+
+        $this->hasColumn('lang', $this->_options['type'], $this->_options['length'], $options);
+
+        $this->bindQueryParts(array('indexBy' => 'lang'));
+ 
+        // Rewrite any relations to our original table
+        $originalName = $this->_options['table']->getClassnameToReturn();
+        $relations = $this->_options['table']->getRelationParser()->getPendingRelations();
+        foreach($relations as $table => $relation) {
+            if ($table != $this->_table->getTableName() ) {
+                // check that the localColumn is part of the moved col
+                if (isset($relation['local']) && in_array($relation['local'], $this->_options['fields'])) {
+                    // found one, let's rewrite it
+                    $this->_options['table']->getRelationParser()->unsetPendingRelations($table);
+        
+                    // and bind the rewritten one
+                    $this->_table->getRelationParser()->bind($table, $relation);
+        
+                    // now try to get the reverse relation, to rewrite it
+                    $rp = Doctrine::getTable($table)->getRelationParser();
+                    $others = $rp->getPendingRelation($originalName);
+                    if (isset($others)) {
+                        $others['class'] = $this->_table->getClassnameToReturn();
+                        $others['alias'] = $this->_table->getClassnameToReturn();
+                        $rp->unsetPendingRelations($originalName);
+                        $rp->bind($this->_table->getClassnameToReturn() ,$others);
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/I18n/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+ 
+/**
+ * Doctrine_I18n_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  I18n
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_I18n_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,441 @@
+<?php
+/*
+ *  $Id: Import.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * class Doctrine_Import
+ * Main responsible of performing import operation. Delegates database schema
+ * reading to a reader object and passes the result to a builder object which
+ * builds a Doctrine data model.
+ *
+ * @package     Doctrine
+ * @subpackage  Import
+ * @link        www.phpdoctrine.org
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jukka Hassinen <Jukka.Hassinen@BrainAlliance.com>
+ */
+class Doctrine_Import extends Doctrine_Connection_Module
+{
+    protected $sql = array();
+
+    /**
+     * lists all databases
+     *
+     * @return array
+     */
+    public function listDatabases()
+    {
+        if ( ! isset($this->sql['listDatabases'])) {
+            throw new Doctrine_Import_Exception(__FUNCTION__ . ' not supported by this driver.');
+        }
+
+        return $this->conn->fetchColumn($this->sql['listDatabases']);
+    }
+
+    /**
+     * lists all availible database functions
+     *
+     * @return array
+     */
+    public function listFunctions()
+    {
+        if ( ! isset($this->sql['listFunctions'])) {
+            throw new Doctrine_Import_Exception(__FUNCTION__ . ' not supported by this driver.');
+        }
+
+        return $this->conn->fetchColumn($this->sql['listFunctions']);
+    }
+
+    /**
+     * lists all database triggers
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listTriggers($database = null)
+    {
+        throw new Doctrine_Import_Exception(__FUNCTION__ . ' not supported by this driver.');
+    }
+
+    /**
+     * lists all database sequences
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listSequences($database = null)
+    {
+        if ( ! isset($this->sql['listSequences'])) {
+            throw new Doctrine_Import_Exception(__FUNCTION__ . ' not supported by this driver.');
+        }
+
+        return $this->conn->fetchColumn($this->sql['listSequences']);
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableConstraints($table)
+    {
+        throw new Doctrine_Import_Exception(__FUNCTION__ . ' not supported by this driver.');
+    }
+
+    /**
+     * lists table relations
+     *
+     * Expects an array of this format to be returned with all the relationships in it where the key is 
+     * the name of the foreign table, and the value is an array containing the local and foreign column
+     * name
+     *
+     * Array
+     * (
+     *   [groups] => Array
+     *     (
+     *        [local] => group_id
+     *        [foreign] => id
+     *     )
+     * )
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableRelations($table)
+    {
+        throw new Doctrine_Import_Exception(__FUNCTION__ . ' not supported by this driver.');
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableColumns($table)
+    {
+        throw new Doctrine_Import_Exception(__FUNCTION__ . ' not supported by this driver.');
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableIndexes($table)
+    {
+        throw new Doctrine_Import_Exception(__FUNCTION__ . ' not supported by this driver.');
+    }
+
+    /**
+     * lists tables
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listTables($database = null)
+    {
+        throw new Doctrine_Import_Exception(__FUNCTION__ . ' not supported by this driver.');
+    }
+
+    /**
+     * lists table triggers
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableTriggers($table)
+    {
+        throw new Doctrine_Import_Exception(__FUNCTION__ . ' not supported by this driver.');
+    }
+
+    /**
+     * lists table views
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableViews($table)
+    {
+        throw new Doctrine_Import_Exception(__FUNCTION__ . ' not supported by this driver.');
+    }
+
+    /**
+     * lists database users
+     *
+     * @return array
+     */
+    public function listUsers()
+    {
+        if ( ! isset($this->sql['listUsers'])) {
+            throw new Doctrine_Import_Exception(__FUNCTION__ . ' not supported by this driver.');
+        }
+
+        return $this->conn->fetchColumn($this->sql['listUsers']);
+    }
+
+    /**
+     * lists database views
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listViews($database = null)
+    {
+        if ( ! isset($this->sql['listViews'])) {
+            throw new Doctrine_Import_Exception(__FUNCTION__ . ' not supported by this driver.');
+        }
+
+        return $this->conn->fetchColumn($this->sql['listViews']);
+    }
+
+    /**
+     * checks if a database exists
+     *
+     * @param string $database
+     * @return boolean
+     */
+    public function databaseExists($database)
+    {
+        return in_array($database, $this->listDatabases());
+    }
+
+    /**
+     * checks if a function exists
+     *
+     * @param string $function
+     * @return boolean
+     */
+    public function functionExists($function)
+    {
+        return in_array($function, $this->listFunctions());
+    }
+
+    /**
+     * checks if a trigger exists
+     *
+     * @param string $trigger
+     * @param string|null $database
+     * @return boolean
+     */
+    public function triggerExists($trigger, $database = null)
+    {
+        return in_array($trigger, $this->listTriggers($database));
+    }
+
+    /**
+     * checks if a sequence exists
+     *
+     * @param string $sequence
+     * @param string|null $database
+     * @return boolean
+     */
+    public function sequenceExists($sequence, $database = null)
+    {
+        return in_array($sequence, $this->listSequences($database));
+    }
+
+    /**
+     * checks if a table constraint exists
+     *
+     * @param string $constraint
+     * @param string $table     database table name
+     * @return boolean
+     */
+    public function tableConstraintExists($constraint, $table)
+    {
+        return in_array($constraint, $this->listTableConstraints($table));
+    }
+
+    /**
+     * checks if a table column exists
+     *
+     * @param string $column
+     * @param string $table     database table name
+     * @return boolean
+     */
+    public function tableColumnExists($column, $table)
+    {
+        return in_array($column, $this->listTableColumns($table));
+    }
+
+    /**
+     * checks if a table index exists
+     *
+     * @param string $index
+     * @param string $table     database table name
+     * @return boolean
+     */
+    public function tableIndexExists($index, $table)
+    {
+        return in_array($index, $this->listTableIndexes($table));
+    }
+
+    /**
+     * checks if a table exists
+     *
+     * @param string $table
+     * @param string|null $database
+     * @return boolean
+     */
+    public function tableExists($table, $database = null)
+    {
+        return in_array($table, $this->listTables($database));
+    }
+
+    /**
+     * checks if a table trigger exists
+     *
+     * @param string $trigger
+     * @param string $table     database table name
+     * @return boolean
+     */
+    public function tableTriggerExists($trigger, $table)
+    {
+        return in_array($trigger, $this->listTableTriggers($table));
+    }
+
+    /**
+     * checks if a table view exists
+     *
+     * @param string $view
+     * @param string $table     database table name
+     * @return boolean
+     */
+    public function tableViewExists($view, $table)
+    {
+        return in_array($view, $this->listTableViews($table));
+    }
+
+    /**
+     * checks if a user exists
+     *
+     * @param string $user
+     * @return boolean
+     */
+    public function userExists($user)
+    {
+        return in_array($user, $this->listUsers());
+    }
+
+    /**
+     * checks if a view exists
+     *
+     * @param string $view
+     * @param string|null $database
+     * @return boolean
+     */
+    public function viewExists($view, $database = null)
+    {
+         return in_array($view, $this->listViews($database));
+    }
+
+    /**
+     * importSchema
+     *
+     * method for importing existing schema to Doctrine_Record classes
+     *
+     * @param string $directory
+     * @param array $databases
+     * @return array                the names of the imported classes
+     */
+    public function importSchema($directory, array $databases = array(), array $options = array())
+    {
+        $connections = Doctrine_Manager::getInstance()->getConnections();
+
+        foreach ($connections as $name => $connection) {
+          // Limit the databases to the ones specified by $databases.
+          // Check only happens if array is not empty
+          if ( ! empty($databases) && ! in_array($name, $databases)) {
+            continue;
+          }
+
+          $builder = new Doctrine_Import_Builder();
+          $builder->setTargetPath($directory);
+          $builder->setOptions($options);
+
+          $definitions = array();
+          $classes = array();
+          foreach ($connection->import->listTables() as $table) {
+              $definition = array();
+              $definition['tableName'] = $table;
+              $definition['className'] = Doctrine_Inflector::classify($table);
+              $definition['columns'] = $connection->import->listTableColumns($table);
+
+              try {
+                  $definition['relations'] = array();
+                  $relations = $connection->import->listTableRelations($table);
+                  $relClasses = array();
+                  foreach ($relations as $relation) {
+                      $table = $relation['table'];
+                      $class = Doctrine_Inflector::classify($table);
+                      if (in_array($class, $relClasses)) {
+                          $alias = $class . '_' . (count($relClasses) + 1);
+                      } else {
+                          $alias = $class;
+                      }
+                      $relClasses[] = $class;
+                      $definition['relations'][$alias] = array(
+                          'alias'   => $alias,
+                          'class'   => $class,
+                          'local'   => $relation['local'],
+                          'foreign' => $relation['foreign']
+                      );
+                  }
+              } catch (Exception $e) {}
+
+              $definitions[$definition['className']] = $definition;
+              $classes[] = $definition['className'];
+          }
+
+          // Build opposite end of relationships
+          foreach ($definitions as $className => $definition) {
+              $relClasses = array();
+              foreach ($definition['relations'] as $alias => $relation) {
+                  if (in_array($relation['class'], $relClasses) || isset($definitions[$relation['class']]['relations'][$className])) {
+                      $alias = $className . '_' . (count($relClasses) + 1);
+                  } else {
+                      $alias = $className;
+                  }
+                  $relClasses[] = $relation['class'];
+                  $definitions[$relation['class']]['relations'][$alias] = array(
+                    'type' => Doctrine_Relation::MANY,
+                    'alias' => $alias,
+                    'class' => $className,
+                    'local' => $relation['foreign'],
+                    'foreign' => $relation['local']
+                  );
+              }
+          }
+
+          // Build records
+          foreach ($definitions as $definition) {
+              $builder->buildRecord($definition);
+          }
+        }
+
+        return $classes;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Builder.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,1061 @@
+<?php
+/*
+ *  $Id: Builder.php 5818 2009-06-03 19:45:58Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Import_Builder
+ *
+ * Import builder is responsible of building Doctrine_Record classes
+ * based on a database schema.
+ *
+ * @package     Doctrine
+ * @subpackage  Import
+ * @link        www.phpdoctrine.org
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @since       1.0
+ * @version     $Revision: 5818 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jukka Hassinen <Jukka.Hassinen@BrainAlliance.com>
+ * @author      Nicolas Bérard-Nault <nicobn@php.net>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Import_Builder extends Doctrine_Builder
+{
+    /**
+     * _path
+     *
+     * the path where imported files are being generated
+     *
+     * @var string $_path
+     */
+    protected $_path = '';
+
+    /**
+     * _packagesPrefix
+     *
+     * @var string
+     */
+    protected $_packagesPrefix = 'Package';
+
+    /**
+     * _packagesPath
+     *
+     * @var string
+     */
+    protected $_packagesPath = '';
+
+    /**
+     * _packagesFolderName
+     *
+     * @var string
+     */
+    protected $_packagesFolderName = 'packages';
+
+    /**
+     * _suffix
+     *
+     * File suffix to use when writing class definitions
+     *
+     * @var string $suffix
+     */
+    protected $_suffix = '.php';
+
+    /**
+     * _generateBaseClasses
+     *
+     * Bool true/false for whether or not to generate base classes
+     *
+     * @var boolean $generateBaseClasses
+     */
+    protected $_generateBaseClasses = true;
+
+    /**
+     * _generateTableClasses
+     *
+     * Bool true/false for whether or not to generate child table classes
+     *
+     * @var boolean $generateTableClasses
+     */
+    protected $_generateTableClasses = false;
+
+    /**
+     * _base
+     *
+     * Prefix to use for generated base classes
+     *
+     * @var string
+     */
+    protected $_baseClassPrefix = 'Base';
+
+    /**
+     * _baseClassesDirectory
+     *
+     * Directory to put the generate base classes in
+     *
+     * @var string $suffix
+     */
+    protected $_baseClassesDirectory = 'generated';
+
+    /**
+     * _baseClassName
+     *
+     * @var string
+     */
+    protected $_baseClassName = 'Doctrine_Record';
+
+    /**
+     * _generateAccessors
+     *
+     * @var boolean $generateAccessors
+     */
+    protected $_generateAccessors = false;
+
+    /**
+     * _tpl
+     *
+     * Class template used for writing classes
+     *
+     * @var $_tpl
+     */
+    protected static $_tpl;
+
+    /**
+     * __construct
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        $this->loadTemplate();
+    }
+
+    /**
+     * setTargetPath
+     *
+     * @param string path   the path where imported files are being generated
+     * @return
+     */
+    public function setTargetPath($path)
+    {
+        if ($path) {
+            if ( ! $this->_packagesPath) {
+                $this->setPackagesPath($path . DIRECTORY_SEPARATOR . $this->_packagesFolderName);
+            }
+
+            $this->_path = $path;
+        }
+    }
+
+    /**
+     * setPackagePath
+     *
+     * @param string $packagesPrefix
+     * @return void
+     */
+    public function setPackagesPrefix($packagesPrefix)
+    {
+        $this->_packagesPrefix = $packagesPrefix;
+    }
+
+    /**
+     * setPackagesPath
+     *
+     * @param string $packagesPath
+     * @return void
+     */
+    public function setPackagesPath($packagesPath)
+    {
+        if ($packagesPath) {
+            $this->_packagesPath = $packagesPath;
+        }
+    }
+
+    /**
+     * generateBaseClasses
+     *
+     * Specify whether or not to generate classes which extend from generated base classes
+     *
+     * @param  boolean $bool
+     * @return boolean $bool
+     */
+    public function generateBaseClasses($bool = null)
+    {
+        if ($bool !== null) {
+            $this->_generateBaseClasses = $bool;
+        }
+
+        return $this->_generateBaseClasses;
+    }
+
+    /**
+     * generateTableClasses
+     *
+     * Specify whether or not to generate children table classes
+     *
+     * @param  boolean $bool
+     * @return boolean $bool
+     */
+    public function generateTableClasses($bool = null)
+    {
+        if ($bool !== null) {
+            $this->_generateTableClasses = $bool;
+        }
+
+        return $this->_generateTableClasses;
+    }
+
+    /**
+     * Generate physical accessors for columns and relationships
+     *
+     * @param boolean $bool
+     * @return boolean $generateAccessors
+     */
+    public function generateAccessors($bool = null)
+    {
+      if ($bool !== null) {
+          $this->_generateAccessors = $bool;
+      }
+
+      return $this->_generateAccessors;
+    }
+
+    /**
+     * setBaseClassPrefix
+     *
+     * @param string $prefix
+     * @return void
+     */
+    public function setBaseClassPrefix($prefix)
+    {
+        $this->_baseClassPrefix = $prefix;
+    }
+
+    /**
+     * getBaseClassPrefix
+     *
+     * @return void
+     */
+    public function getBaseClassPrefix()
+    {
+        return $this->_baseClassPrefix;
+    }
+
+    /**
+     * setBaseClassesDirectory
+     *
+     * @return void
+     */
+    public function setBaseClassesDirectory($baseClassesDirectory)
+    {
+        $this->_baseClassesDirectory = $baseClassesDirectory;
+    }
+
+    /**
+     * setBaseClassName
+     *
+     * @package default
+     */
+    public function setBaseClassName($className)
+    {
+        $this->_baseClassName = $className;
+    }
+
+    /**
+     * setSuffix
+     *
+     * @param string $suffix
+     * @return void
+     */
+    public function setSuffix($suffix)
+    {
+        $this->_suffix = $suffix;
+    }
+
+    /**
+     * getTargetPath
+     *
+     * @return string       the path where imported files are being generated
+     */
+    public function getTargetPath()
+    {
+        return $this->_path;
+    }
+
+    /**
+     * setOptions
+     *
+     * @param string $options
+     * @return void
+     */
+    public function setOptions($options)
+    {
+        if ( ! empty($options)) {
+            foreach ($options as $key => $value) {
+                $this->setOption($key, $value);
+            }
+        }
+    }
+
+    /**
+     * setOption
+     *
+     * @param string $key
+     * @param string $value
+     * @return void
+     */
+    public function setOption($key, $value)
+    {
+        $name = 'set' . Doctrine_Inflector::classify($key);
+
+        if (method_exists($this, $name)) {
+            $this->$name($value);
+        } else {
+            $key = '_' . $key;
+            $this->$key = $value;
+        }
+    }
+
+    /**
+     * loadTemplate
+     *
+     * Loads the class template used for generating classes
+     *
+     * @return void
+     */
+    public function loadTemplate()
+    {
+        if (isset(self::$_tpl)) {
+            return;
+        }
+
+        self::$_tpl = '/**' . PHP_EOL
+                    . ' * This class has been auto-generated by the Doctrine ORM Framework' . PHP_EOL
+                    . ' */' . PHP_EOL
+                    . '%sclass %s extends %s' . PHP_EOL
+                    . '{'
+                    . '%s' . PHP_EOL
+                    . '%s' . PHP_EOL
+                    . '}';
+    }
+
+    /*
+     * Build the table definition of a Doctrine_Record object
+     *
+     * @param  string $table
+     * @param  array  $tableColumns
+     */
+    public function buildTableDefinition(array $definition)
+    {
+        if (isset($definition['inheritance']['type']) && ($definition['inheritance']['type'] == 'simple' || $definition['inheritance']['type'] == 'column_aggregation')) {
+            return;
+        }
+
+        $ret = array();
+
+        $i = 0;
+
+        if (isset($definition['inheritance']['type']) && $definition['inheritance']['type'] == 'concrete') {
+            $ret[$i] = "        parent::setTableDefinition();";
+            $i++;
+        }
+
+        if (isset($definition['tableName']) && !empty($definition['tableName'])) {
+            $ret[$i] = "        ".'$this->setTableName(\''. $definition['tableName'].'\');';
+            $i++;
+        }
+
+        if (isset($definition['columns']) && is_array($definition['columns']) && !empty($definition['columns'])) {
+            $ret[$i] = $this->buildColumns($definition['columns']);
+            $i++;
+        }
+
+        if (isset($definition['indexes']) && is_array($definition['indexes']) && !empty($definition['indexes'])) {
+            $ret[$i] = $this->buildIndexes($definition['indexes']);
+            $i++;
+        }
+
+        if (isset($definition['attributes']) && is_array($definition['attributes']) && !empty($definition['attributes'])) {
+            $ret[$i] = $this->buildAttributes($definition['attributes']);
+            $i++;
+        }
+
+        if (isset($definition['options']) && is_array($definition['options']) && !empty($definition['options'])) {
+            $ret[$i] = $this->buildOptions($definition['options']);
+            $i++;
+        }
+
+        if (isset($definition['checks']) && is_array($definition['checks']) && !empty($definition['checks'])) {
+            $ret[$i] = $this->buildChecks($definition['checks']);
+            $i++;
+        }
+
+        if (isset($definition['inheritance']['subclasses']) && ! empty($definition['inheritance']['subclasses'])) {
+            $ret[$i] = "        ".'$this->setSubClasses('. $this->varExport($definition['inheritance']['subclasses']).');';
+            $i++;
+        }
+
+        $code = implode(PHP_EOL, $ret);
+        $code = trim($code);
+
+        return PHP_EOL . "    public function setTableDefinition()" . PHP_EOL . '    {' . PHP_EOL . '        ' . $code . PHP_EOL . '    }';
+    }
+
+    /**
+     * buildSetUp
+     *
+     * @param  array $options
+     * @param  array $columns
+     * @param  array $relations
+     * @return string
+     */
+    public function buildSetUp(array $definition)
+    {
+        $ret = array();
+        $i = 0;
+
+        if (isset($definition['relations']) && is_array($definition['relations']) && ! empty($definition['relations'])) {
+            foreach ($definition['relations'] as $name => $relation) {
+                $class = isset($relation['class']) ? $relation['class']:$name;
+                $alias = (isset($relation['alias']) && $relation['alias'] !== $relation['class']) ? ' as ' . $relation['alias'] : '';
+
+                if ( ! isset($relation['type'])) {
+                    $relation['type'] = Doctrine_Relation::ONE;
+                }
+
+                if ($relation['type'] === Doctrine_Relation::ONE) {
+                    $ret[$i] = "        ".'$this->hasOne(\'' . $class . $alias . '\'';
+                } else {
+                    $ret[$i] = "        ".'$this->hasMany(\'' . $class . $alias . '\'';
+                }
+
+                $a = array();
+
+                if (isset($relation['refClass'])) {
+                    $a[] = '\'refClass\' => ' . $this->varExport($relation['refClass']);
+                }
+                
+                if (isset($relation['refClassRelationAlias'])) {
+                    $a[] = '\'refClassRelationAlias\' => ' . $this->varExport($relation['refClassRelationAlias']);
+                }
+                
+                if (isset($relation['deferred']) && $relation['deferred']) {
+                    $a[] = '\'default\' => ' . $this->varExport($relation['deferred']);
+                }
+
+                if (isset($relation['local']) && $relation['local']) {
+                    $a[] = '\'local\' => ' . $this->varExport($relation['local']);
+                }
+
+                if (isset($relation['foreign']) && $relation['foreign']) {
+                    $a[] = '\'foreign\' => ' . $this->varExport($relation['foreign']);
+                }
+
+                if (isset($relation['onDelete']) && $relation['onDelete']) {
+                    $a[] = '\'onDelete\' => ' . $this->varExport($relation['onDelete']);
+                }
+
+                if (isset($relation['onUpdate']) && $relation['onUpdate']) {
+                    $a[] = '\'onUpdate\' => ' . $this->varExport($relation['onUpdate']);
+                }
+
+                if (isset($relation['cascade']) && $relation['cascade']) {
+                    $a[] = '\'cascade\' => ' . $this->varExport($relation['cascade']);
+                }
+
+                if (isset($relation['equal']) && $relation['equal']) {
+                    $a[] = '\'equal\' => ' . $this->varExport($relation['equal']);
+                }
+
+                if (isset($relation['owningSide']) && $relation['owningSide']) {
+                    $a[] = '\'owningSide\' => ' . $this->varExport($relation['owningSide']);
+                }
+
+                if ( ! empty($a)) {
+                    $ret[$i] .= ', ' . 'array(' . PHP_EOL . str_repeat(' ', 13);
+                    $length = strlen($ret[$i]);
+                    $ret[$i] .= implode(',' . PHP_EOL . str_repeat(' ', 13), $a) . ')';
+                }
+
+                $ret[$i] .= ');'.PHP_EOL;
+                $i++;
+            }
+        }
+
+        if (isset($definition['actAs']) && is_array($definition['actAs']) && !empty($definition['actAs'])) {
+            $ret[$i] = $this->buildActAs($definition['actAs']);
+            $i++;
+        }
+
+        if (isset($definition['listeners']) && is_array($definition['listeners']) && !empty($definition['listeners'])) {
+            $ret[$i] = $this->buildListeners($definition['listeners']);
+            $i++;
+        }
+
+        $code = implode(PHP_EOL, $ret);
+        $code = trim($code);
+
+        // If the body of the function has contents then we need to 
+        if ($code) {
+            // If the body of the function has contents and we are using inheritance
+            // then we need call the parent::setUp() before the body of the function
+            // Class table inheritance is the only one we shouldn't call parent::setUp() for
+            if ($code && isset($definition['inheritance']['type']) && $definition['inheritance']['type'] != 'class_table') {
+                $code = "parent::setUp();" . PHP_EOL . '    ' . $code;
+            }
+        }
+
+        // If we have some code for the function then lets define it and return it
+        if ($code) {
+            return '    public function setUp()' . PHP_EOL . '    {' . PHP_EOL . '        ' . $code . PHP_EOL . '    }';
+        }
+    }
+
+    /**
+     * Build php code for record checks
+     *
+     * @param array $checks
+     * @return string $build
+     */
+    public function buildChecks($checks)
+    {
+        $build = '';
+        foreach ($checks as $check) {
+            $build .= "        \$this->check('" . $check . "');" . PHP_EOL;
+        }
+        return $build;
+    }
+
+    /**
+     * buildColumns
+     *
+     * @param string $array
+     * @return void
+     */
+    public function buildColumns(array $columns)
+    {
+        $build = null;
+        foreach ($columns as $name => $column) {
+            $columnName = isset($column['name']) ? $column['name']:$name;
+            $build .= "        ".'$this->hasColumn(\'' . $columnName . '\', \'' . $column['type'] . '\'';
+
+            if ($column['length']) {
+                $build .= ', ' . $column['length'];
+            } else {
+                $build .= ', null';
+            }
+
+            $options = $column;
+
+            // Remove name, alltypes, ntype. They are not needed in options array
+            unset($options['name']);
+            unset($options['alltypes']);
+            unset($options['ntype']);
+
+            // Remove notnull => true if the column is primary
+            // Primary columns are implied to be notnull in Doctrine
+            if (isset($options['primary']) && $options['primary'] == true && (isset($options['notnull']) && $options['notnull'] == true)) {
+                unset($options['notnull']);
+            }
+
+            // Remove default if the value is 0 and the column is a primary key
+            // Doctrine defaults to 0 if it is a primary key
+            if (isset($options['primary']) && $options['primary'] == true && (isset($options['default']) && $options['default'] == 0)) {
+                unset($options['default']);
+            }
+
+            // These can be removed if they are empty. They all default to a false/0/null value anyways
+            $remove = array('fixed', 'primary', 'notnull', 'autoincrement', 'unsigned');
+            foreach ($remove as $key) {
+                if (isset($options[$key]) && empty($options[$key])) {
+                    unset($options[$key]);
+                }
+            }
+
+            // Remove null and empty array values
+            foreach ($options as $key => $value) {
+                if (is_null($value) || (is_array($value) && empty($value))) {
+                    unset($options[$key]);
+                }
+            }
+
+            if (is_array($options) && !empty($options)) {
+                $build .= ', ' . $this->varExport($options);
+            }
+
+            $build .= ');' . PHP_EOL;
+        }
+
+        return $build;
+    }
+
+    /**
+     * emit a behavior assign
+     *
+     * @param int $level
+     * @param string $name
+     * @param string $option
+     * @return string assignation code
+     */
+    private function emitAssign($level, $name, $option)
+    {
+        // find class matching $name
+        $classname = $name;
+        if (class_exists("Doctrine_Template_$name", true)) {
+            $classname = "Doctrine_Template_$name";
+        }
+        return "        \$" . strtolower($name) . "$level = new $classname($option);". PHP_EOL;
+    }
+
+    /**
+     * emit an addChild
+     *
+     * @param int $level
+     * @param string $name
+     * @param string $option
+     * @return string addChild code
+     */
+    private function emitAddChild($level, $parent, $name)
+    {
+        return "        \$" . strtolower($parent) . ($level - 1) . "->addChild(\$" . strtolower($name) . "$level);" . PHP_EOL;
+    }
+
+    /**
+     * emit an indented actAs
+     *
+     * @param int $level
+     * @param string $name
+     * @param string $option
+     * @return string actAs code
+     */
+    private function emitActAs($level, $name)
+    {
+        return "        \$this->actAs(\$" . strtolower($name) . "$level);" . PHP_EOL;
+    }
+
+
+    /**
+     * buildActAs: builds a complete actAs code. It supports hierarchy of plugins
+     * @param array $actAs array of plugin definitions and options
+     */
+    public function buildActAs($actAs)
+    {
+        $emittedActAs = array();
+        $build = $this->innerBuildActAs($actAs, 0, null, $emittedActAs);
+        foreach($emittedActAs as $str) {
+            $build .= $str;
+        }
+        return $build;
+    }
+
+    /**
+     * innerBuildActAs: build a complete actAs code that handles hierarchy of plugins
+     *
+     * @param array  $actAs array of plugin definitions and options
+     * @param int    $level current indentation level
+     * @param string $parent name of the parent template/plugin
+     * @param array  $emittedActAs contains on output an array of actAs command to be appended to output
+     * @return string actAs full definition
+     */
+    private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emittedActAs)
+    {
+        // rewrite special case of actAs: [Behavior] which gave [0] => Behavior
+        if(is_array($actAs) && isset($actAs[0]) && !is_array($actAs[0])) {
+            $actAs = array_flip($actAs);
+        }
+
+        $build = '';
+        $currentParent = $parent;
+        if(is_array($actAs)) {
+            foreach($actAs as $template => $options) {
+                if ($template == 'actAs') {
+                    // found another actAs
+                    $build .= $this->innerBuildActAs($options, $level + 1, $parent, $emittedActAs);
+                } else if (is_array($options)) {
+                    // remove actAs from options
+                    $realOptions = array();
+                    $leftActAs = array();
+                    foreach($options as $name => $value) {
+                        if ($name != 'actAs') {
+                            $realOptions[$name] = $options[$name];
+                        } else {
+                            $leftActAs[$name] = $options[$name];
+                        }
+                    } 
+
+                    $optionPHP = $this->varExport($realOptions);
+                    $build .= $this->emitAssign($level, $template, $optionPHP); 
+                    if ($level == 0) {
+                        $emittedActAs[] = $this->emitActAs($level, $template);
+                    } else {
+                        $build .= $this->emitAddChild($level, $currentParent, $template);
+                    }
+                    // descend for the remainings actAs
+                    $parent = $template;            
+                    $build .= $this->innerBuildActAs($leftActAs, $level, $template, $emittedActAs);
+                } else {
+                    $build .= $this->emitAssign($level, $template, null);
+                    if ($level == 0) {
+                        $emittedActAs[] = $this->emitActAs($level, $template);
+                    } else {
+                        $build .= $this->emitAddChild($level, $currentParent, $template);
+                    }
+                    $parent = $template;            
+                }
+            }
+        } else {
+            $build .= $this->emitAssign($level, $actAs, null);
+            if ($level == 0) {
+                $emittedActAs[] = $this->emitActAs($level, $actAs);
+            } else {
+                $build .= $this->emitAddChild($level, $currentParent, $actAs);
+            }
+        }
+
+        return $build;
+    }
+
+    /**
+     * Build php code for adding record listeners
+     *
+     * @param string $listeners 
+     * @return string $build
+     */
+    public function buildListeners($listeners)
+    {
+        $build = '';
+        foreach($listeners as $listener) {
+            $build .= "        \$this->addListener(new " . $listener . "());" . PHP_EOL;
+        }
+
+        return $build;
+    }
+
+    /**
+     * buildAttributes
+     *
+     * @param string $array
+     * @return void
+     */
+    public function buildAttributes(array $attributes)
+    {
+        $build = PHP_EOL;
+        foreach ($attributes as $key => $value) {
+
+            $values = array();
+            if (is_bool($value))
+            {
+              $values[] = $value ? 'true':'false';
+            } else {
+                if ( ! is_array($value)) {
+                    $value = array($value);
+                }
+
+                foreach ($value as $attr) {
+                    $const = "Doctrine::" . strtoupper($key) . "_" . strtoupper($attr);
+                    if (defined($const)) {
+                        $values[] = $const;
+                    } else {
+                        $values[] = "'" . $attr . "'";
+                    }
+                }
+            }
+
+            $string = implode(' ^ ', $values);
+            $build .= "        \$this->setAttribute(Doctrine::ATTR_" . strtoupper($key) . ", " . $string . ");" . PHP_EOL;
+        }
+
+        return $build;
+    }
+
+    /**
+     * buildTableOptions
+     *
+     * @param string $array
+     * @return void
+     */
+    public function buildOptions(array $options)
+    {
+        $build = '';
+        foreach ($options as $name => $value) {
+            $build .= "        \$this->option('$name', " . $this->varExport($value) . ");" . PHP_EOL;
+        }
+
+        return $build;
+    }
+
+    /**
+     * buildIndexes
+     *
+     * @param string $array
+     * @return void
+     */
+    public function buildIndexes(array $indexes)
+    {
+      $build = '';
+
+      foreach ($indexes as $indexName => $definitions) {
+          $build .= PHP_EOL . "        \$this->index('" . $indexName . "'";
+          $build .= ', ' . $this->varExport($definitions);
+          $build .= ');';
+      }
+
+      return $build;
+    }
+
+    /**
+     * buildDefinition
+     *
+     * @param array $definition
+     * @return string
+     */
+    public function buildDefinition(array $definition)
+    {
+        if ( ! isset($definition['className'])) {
+            throw new Doctrine_Import_Builder_Exception('Missing class name.');
+        }
+
+        $abstract = isset($definition['abstract']) && $definition['abstract'] === true ? 'abstract ':null;
+        $className = $definition['className'];
+        $extends = isset($definition['inheritance']['extends']) ? $definition['inheritance']['extends']:$this->_baseClassName;
+
+        if ( ! (isset($definition['no_definition']) && $definition['no_definition'] === true)) {
+            $tableDefinitionCode = $this->buildTableDefinition($definition);
+            $setUpCode = $this->buildSetUp($definition);
+        } else {
+            $tableDefinitionCode = null;
+            $setUpCode = null;
+        }
+
+        if ($tableDefinitionCode && $setUpCode) {
+            $setUpCode = PHP_EOL . $setUpCode;
+        }
+
+        $content = sprintf(self::$_tpl, $abstract,
+                                       $className,
+                                       $extends,
+                                       $tableDefinitionCode,
+                                       $setUpCode);
+
+        return $content;
+    }
+
+    /**
+     * buildRecord
+     *
+     * @param array $options
+     * @param array $columns
+     * @param array $relations
+     * @param array $indexes
+     * @param array $attributes
+     * @param array $templates
+     * @param array $actAs
+     * @return void=
+     */
+    public function buildRecord(array $definition)
+    {
+        if ( ! isset($definition['className'])) {
+            throw new Doctrine_Import_Builder_Exception('Missing class name.');
+        }
+
+        $definition['topLevelClassName'] = $definition['className'];
+
+        if ($this->generateBaseClasses()) {
+            $definition['is_package'] = (isset($definition['package']) && $definition['package']) ? true:false;
+
+            if ($definition['is_package']) {
+                $e = explode('.', trim($definition['package']));
+                $definition['package_name'] = $e[0];
+
+                $definition['package_path'] = ! empty($e) ? implode(DIRECTORY_SEPARATOR, $e):$definition['package_name'];
+            }
+            // Top level definition that extends from all the others
+            $topLevel = $definition;
+            unset($topLevel['tableName']);
+
+            // If we have a package then we need to make this extend the package definition and not the base definition
+            // The package definition will then extends the base definition
+            $topLevel['inheritance']['extends'] = (isset($topLevel['package']) && $topLevel['package']) ? $this->_packagesPrefix . $topLevel['className']:$this->_baseClassPrefix . $topLevel['className'];
+            $topLevel['no_definition'] = true;
+            $topLevel['generate_once'] = true;
+            $topLevel['is_main_class'] = true;
+            unset($topLevel['connection']);
+
+            // Package level definition that extends from the base definition
+            if (isset($definition['package'])) {
+
+                $packageLevel = $definition;
+                $packageLevel['className'] = $topLevel['inheritance']['extends'];
+                $packageLevel['inheritance']['extends'] = $this->_baseClassPrefix . $topLevel['className'];
+                $packageLevel['no_definition'] = true;
+                $packageLevel['abstract'] = true;
+                $packageLevel['override_parent'] = true;
+                $packageLevel['generate_once'] = true;
+                $packageLevel['is_package_class'] = true;
+                unset($packageLevel['connection']);
+
+                $packageLevel['tableClassName'] = $packageLevel['className'] . 'Table';
+                $packageLevel['inheritance']['tableExtends'] = isset($definition['inheritance']['extends']) ? $definition['inheritance']['extends'] . 'Table':'Doctrine_Table';
+
+                $topLevel['tableClassName'] = $topLevel['topLevelClassName'] . 'Table';
+                $topLevel['inheritance']['tableExtends'] = $packageLevel['className'] . 'Table';
+            } else {
+                $topLevel['tableClassName'] = $topLevel['className'] . 'Table';
+                $topLevel['inheritance']['tableExtends'] = isset($definition['inheritance']['extends']) ? $definition['inheritance']['extends'] . 'Table':'Doctrine_Table';
+            }
+
+            $baseClass = $definition;
+            $baseClass['className'] = $this->_baseClassPrefix . $baseClass['className'];
+            $baseClass['abstract'] = true;
+            $baseClass['override_parent'] = false;
+            $baseClass['is_base_class'] = true;
+
+            $this->writeDefinition($baseClass);
+
+            if ( ! empty($packageLevel)) {
+                $this->writeDefinition($packageLevel);
+            }
+
+            $this->writeDefinition($topLevel);
+        } else {
+            $this->writeDefinition($definition);
+        }
+    }
+
+    /**
+     * writeTableDefinition
+     *
+     * @return void
+     */
+    public function writeTableDefinition($className, $path, $options = array())
+    {
+        $content  = '<?php' . PHP_EOL;
+        $content .= sprintf(self::$_tpl, false,
+                                       $className,
+                                       isset($options['extends']) ? $options['extends']:'Doctrine_Table',
+                                       null,
+                                       null,
+                                       null
+                                       );
+
+        Doctrine_Lib::makeDirectories($path);
+
+        $writePath = $path . DIRECTORY_SEPARATOR . $className . $this->_suffix;
+
+        Doctrine::loadModel($className, $writePath);
+
+        if ( ! file_exists($writePath)) {
+            file_put_contents($writePath, $content);
+        }
+    }
+
+    /**
+     * writeDefinition
+     *
+     * @param array $options
+     * @param array $columns
+     * @param array $relations
+     * @param array $indexes
+     * @param array $attributes
+     * @param array $templates
+     * @param array $actAs
+     * @return void
+     */
+    public function writeDefinition(array $definition)
+    {
+        $definitionCode = $this->buildDefinition($definition);
+
+        $fileName = $definition['className'] . $this->_suffix;
+
+        $packagesPath = $this->_packagesPath ? $this->_packagesPath:$this->_path;
+
+        // If this is a main class that either extends from Base or Package class
+        if (isset($definition['is_main_class']) && $definition['is_main_class']) {
+            // If is package then we need to put it in a package subfolder
+            if (isset($definition['is_package']) && $definition['is_package']) {
+                $writePath = $this->_path . DIRECTORY_SEPARATOR . $definition['package_name'];
+            // Otherwise lets just put it in the root of the path
+            } else {
+                $writePath = $this->_path;
+            }
+
+            if ($this->generateTableClasses()) {
+                $this->writeTableDefinition($definition['tableClassName'], $writePath, array('extends' => $definition['inheritance']['tableExtends']));
+            }
+        }
+        // If is the package class then we need to make the path to the complete package
+        else if (isset($definition['is_package_class']) && $definition['is_package_class']) {
+            if (isset($definition['package_custom_path'])) {
+              $writePath = $definition['package_custom_path'];
+            } else {
+              $writePath = $packagesPath . DIRECTORY_SEPARATOR . $definition['package_path'];
+            }
+
+            if ($this->generateTableClasses()) {
+                $this->writeTableDefinition($definition['tableClassName'], $writePath, array('extends' => $definition['inheritance']['tableExtends']));
+            }
+        }
+        // If it is the base class of the doctrine record definition
+        else if (isset($definition['is_base_class']) && $definition['is_base_class']) {
+            // If it is a part of a package then we need to put it in a package subfolder
+            if (isset($definition['is_package']) && $definition['is_package']) {
+                $basePath = $this->_path . DIRECTORY_SEPARATOR . $definition['package_name'];
+                $writePath = $basePath . DIRECTORY_SEPARATOR . $this->_baseClassesDirectory;
+            // Otherwise lets just put it in the root generated folder
+            } else {
+                $writePath = $this->_path . DIRECTORY_SEPARATOR . $this->_baseClassesDirectory;
+            }
+        }
+
+        // If we have a writePath from the if else conditionals above then use it
+        if (isset($writePath)) {
+            Doctrine_Lib::makeDirectories($writePath);
+
+            $writePath .= DIRECTORY_SEPARATOR . $fileName;
+        // Otherwise none of the conditions were met and we aren't generating base classes
+        } else {
+            Doctrine_Lib::makeDirectories($this->_path);
+
+            $writePath = $this->_path . DIRECTORY_SEPARATOR . $fileName;
+        }
+
+        $code = "<?php" . PHP_EOL;
+
+        if (isset($definition['connection']) && $definition['connection']) {
+            $code .= "// Connection Component Binding" . PHP_EOL;
+            $code .= "Doctrine_Manager::getInstance()->bindComponent('" . $definition['connectionClassName'] . "', '" . $definition['connection'] . "');" . PHP_EOL;
+        }
+
+        $code .= PHP_EOL . $definitionCode;
+
+        if (isset($definition['generate_once']) && $definition['generate_once'] === true) {
+            if ( ! file_exists($writePath)) {
+                $bytes = file_put_contents($writePath, $code);
+            }
+        } else {
+            $bytes = file_put_contents($writePath, $code);
+        }
+
+        if (isset($bytes) && $bytes === false) {
+            throw new Doctrine_Import_Builder_Exception("Couldn't write file " . $writePath);
+        }
+
+        Doctrine::loadModel($definition['className'], $writePath);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Builder/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Import_Builder_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Import
+ * @link        www.phpdoctrine.org
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Import_Builder_Exception extends Doctrine_Import_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * class Doctrine_Import_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Import
+ * @link        www.phpdoctrine.org
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Import_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Firebird.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,128 @@
+<?php
+/*
+ *  $Id: Firebird.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Import
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lorenzo Alberton <l.alberton@quipo.it> (PEAR MDB2 Interbase driver)
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Import_Firebird extends Doctrine_Import
+{
+    /**
+     * list all tables in the current database
+     *
+     * @return array        data array
+     */
+    public function listTables($database = null)
+    {
+        $query = 'SELECT RDB$RELATION_NAME FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG=0 AND RDB$VIEW_BLR IS NULL';
+
+        return $this->conn->fetchColumn($query);
+    }
+
+    /**
+     * list all fields in a tables in the current database
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     * @access public
+     */
+    public function listTableColumns($table)
+    {
+        $table = $this->conn->quote(strtoupper($table), 'text');
+        $query = 'SELECT RDB$FIELD_NAME FROM RDB$RELATION_FIELDS WHERE UPPER(RDB$RELATION_NAME) = ' . $table;
+
+        return $this->conn->fetchColumn($query);
+    }
+
+    /**
+     * list all users
+     *
+     * @return array            data array containing all database users
+     */
+    public function listUsers()
+    {
+        return $this->conn->fetchColumn('SELECT DISTINCT RDB$USER FROM RDB$USER_PRIVILEGES');
+    }
+
+    /**
+     * list the views in the database
+     *
+     * @return array            data array containing all database views
+     */
+    public function listViews($database = null)
+    {
+        return $this->conn->fetchColumn('SELECT DISTINCT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS');
+    }
+
+    /**
+     * list the views in the database that reference a given table
+     *
+     * @param string $table     table for which all references views should be found
+     * @return array            data array containing all views for given table
+     */
+    public function listTableViews($table)
+    {
+        $query  = 'SELECT DISTINCT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS';
+        $table  = $this->conn->quote(strtoupper($table), 'text');
+        $query .= ' WHERE UPPER(RDB$RELATION_NAME) = ' . $table;
+
+        return $this->conn->fetchColumn($query);
+    }
+
+    /**
+     * list all functions in the current database
+     *
+     * @return array              data array containing all availible functions
+     */
+    public function listFunctions()
+    {
+        $query = 'SELECT RDB$FUNCTION_NAME FROM RDB$FUNCTIONS WHERE RDB$SYSTEM_FLAG IS NULL';
+
+        return $this->conn->fetchColumn($query);
+    }
+
+    /**
+     * This function will be called to get all triggers of the
+     * current database ($this->conn->getDatabase())
+     *
+     * @param  string $table      The name of the table from the
+     *                            previous database to query against.
+     * @return array              data array containing all triggers for given table
+     */
+    public function listTableTriggers($table)
+    {
+        $query = 'SELECT RDB$TRIGGER_NAME FROM RDB$TRIGGERS WHERE RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0';
+
+        if ( ! is_null($table)) {
+            $table = $this->conn->quote(strtoupper($table), 'text');
+            $query .= ' WHERE UPPER(RDB$RELATION_NAME) = ' . $table;
+        }
+
+        return $this->conn->fetchColumn($query);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Informix.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,55 @@
+<?php
+/*
+ *  $Id: Informix.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Import
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Import_Informix extends Doctrine_Import
+{
+    protected $sql = array(
+                    'listTables'          => "SELECT tabname,tabtype FROM systables WHERE tabtype IN ('T','V') AND owner != 'informix'",
+                    'listColumns'         => "SELECT c.colname, c.coltype, c.collength, d.default, c.colno
+                                              FROM syscolumns c, systables t,outer sysdefaults d
+                                              WHERE c.tabid = t.tabid AND d.tabid = t.tabid AND d.colno = c.colno
+                                              AND tabname='%s' ORDER BY c.colno",
+                    'listPk'              => "SELECT part1, part2, part3, part4, part5, part6, part7, part8 FROM
+                                              systables t, sysconstraints s, sysindexes i WHERE t.tabname='%s'
+                                              AND s.tabid=t.tabid AND s.constrtype='P'
+                                              AND i.idxname=s.idxname",
+                    'listForeignKeys'     => "SELECT tr.tabname,updrule,delrule,
+                                              i.part1 o1,i2.part1 d1,i.part2 o2,i2.part2 d2,i.part3 o3,i2.part3 d3,i.part4 o4,i2.part4 d4,
+                                              i.part5 o5,i2.part5 d5,i.part6 o6,i2.part6 d6,i.part7 o7,i2.part7 d7,i.part8 o8,i2.part8 d8
+                                              from systables t,sysconstraints s,sysindexes i,
+                                              sysreferences r,systables tr,sysconstraints s2,sysindexes i2
+                                              where t.tabname='%s'
+                                              and s.tabid=t.tabid and s.constrtype='R' and r.constrid=s.constrid
+                                              and i.idxname=s.idxname and tr.tabid=r.ptabid
+                                              and s2.constrid=r.primary and i2.idxname=s2.idxname",
+                                        );
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Mssql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,248 @@
+<?php
+/*
+ *  $Id: Mssql.php 5847 2009-06-09 08:13:25Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Import
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @author      Frank M. Kromann <frank@kromann.info> (PEAR MDB2 Mssql driver)
+ * @author      David Coallier <davidc@php.net> (PEAR MDB2 Mssql driver)
+ * @version     $Revision: 5847 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Import_Mssql extends Doctrine_Import
+{
+    /**
+     * lists all database sequences
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listSequences($database = null)
+    {
+        $query = "SELECT name FROM sysobjects WHERE xtype = 'U'";
+        $tableNames = $this->conn->fetchColumn($query);
+
+        return array_map(array($this->conn->formatter, 'fixSequenceName'), $tableNames);
+    }
+
+    /**
+     * lists table relations
+     *
+     * Expects an array of this format to be returned with all the relationships in it where the key is 
+     * the name of the foreign table, and the value is an array containing the local and foreign column
+     * name
+     *
+     * Array
+     * (
+     *   [groups] => Array
+     *     (
+     *        [local] => group_id
+     *        [foreign] => id
+     *     )
+     * )
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableRelations($tableName)
+    {
+        $relations = array();
+        $sql = 'SELECT o1.name as table_name, c1.name as column_name, o2.name as referenced_table_name, c2.name as referenced_column_name, s.name as constraint_name FROM sysforeignkeys fk	inner join sysobjects o1 on fk.fkeyid = o1.id inner join sysobjects o2 on fk.rkeyid = o2.id inner join syscolumns c1 on c1.id = o1.id and c1.colid = fk.fkey inner join syscolumns c2 on c2.id = o2.id and c2.colid = fk.rkey inner join sysobjects s on fk.constid = s.id AND o1.name = \'' . $tableName . '\'';
+        $results = $this->conn->fetchAssoc($sql);
+        foreach ($results as $result)
+        {
+            $result = array_change_key_case($result, CASE_LOWER);
+            $relations[] = array('table'   => $result['referenced_table_name'],
+                                 'local'   => $result['column_name'],
+                                 'foreign' => $result['referenced_column_name']);
+        }
+        return $relations;
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableColumns($table)
+    {
+        $sql = 'EXEC sp_primary_keys_rowset @table_name = ' . $this->conn->quoteIdentifier($table, true);
+        $result = $this->conn->fetchAssoc($sql);
+        $primary = array();
+        foreach ($result as $key => $val) {
+            $primary[] = $val['COLUMN_NAME'];
+        }
+
+        $sql     = 'EXEC sp_columns @table_name = ' . $this->conn->quoteIdentifier($table, true);
+        $result  = $this->conn->fetchAssoc($sql);
+        $columns = array();
+
+        foreach ($result as $key => $val) {
+            $val = array_change_key_case($val, CASE_LOWER);
+
+            if (strstr($val['type_name'], ' ')) {
+                list($type, $identity) = explode(' ', $val['type_name']);
+            } else {
+                $type = $val['type_name'];
+                $identity = '';
+            }
+
+            if ($type == 'varchar') {
+                $type .= '(' . $val['length'] . ')';
+            }
+
+            $val['type'] = $type;
+            $val['identity'] = $identity;
+            $decl = $this->conn->dataDict->getPortableDeclaration($val);
+
+            $isIdentity = (bool) (strtoupper(trim($identity)) == 'IDENTITY');
+            $isNullable = (bool) (strtoupper(trim($val['is_nullable'])) == 'NO');
+            $isPrimary = in_array($val['column_name'], $primary);
+
+            $description  = array(
+                'name'          => $val['column_name'],
+                'ntype'         => $type,
+                'type'          => $decl['type'][0],
+                'alltypes'      => $decl['type'],
+                'length'        => $decl['length'],
+                'fixed'         => $decl['fixed'],
+                'unsigned'      => $decl['unsigned'],
+                'notnull'       => $isIdentity ? true : $isNullable,
+                'default'       => $val['column_def'],
+                'primary'       => $isPrimary,
+                'autoincrement' => $isIdentity,
+            );
+
+            $columns[$val['column_name']] = $description;
+        }
+
+        return $columns;
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableIndexes($table)
+    {
+
+    }
+
+    /**
+     * lists tables
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listTables($database = null)
+    {
+        $sql = "SELECT name FROM sysobjects WHERE type = 'U' AND name <> 'dtproperties' AND name <> 'sysdiagrams' ORDER BY name";
+
+        return $this->conn->fetchColumn($sql);
+    }
+
+    /**
+     * lists all triggers
+     *
+     * @return array
+     */
+    public function listTriggers($database = null)
+    {
+        $query = "SELECT name FROM sysobjects WHERE xtype = 'TR'";
+
+        $result = $this->conn->fetchColumn($query);
+
+        return $result;
+    }
+
+    /**
+     * lists table triggers
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableTriggers($table)
+    {
+        $table = $this->conn->quote($table, 'text');
+        $query = "SELECT name FROM sysobjects WHERE xtype = 'TR' AND object_name(parent_obj) = " . $table;
+
+        $result = $this->conn->fetchColumn($query);
+
+        return $result;
+    }
+
+    /**
+     * lists table views
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableViews($table)
+    {
+        $keyName = 'INDEX_NAME';
+        $pkName = 'PK_NAME';
+        if ($this->conn->getAttribute(Doctrine::ATTR_PORTABILITY) & Doctrine::PORTABILITY_FIX_CASE) {
+            if ($this->conn->getAttribute(Doctrine::ATTR_FIELD_CASE) == CASE_LOWER) {
+                $keyName = strtolower($keyName);
+                $pkName  = strtolower($pkName);
+            } else {
+                $keyName = strtoupper($keyName);
+                $pkName  = strtoupper($pkName);
+            }
+        }
+        $table = $this->conn->quote($table, 'text');
+        $query = 'EXEC sp_statistics @table_name = ' . $table;
+        $indexes = $this->conn->fetchColumn($query, $keyName);
+
+        $query = 'EXEC sp_pkeys @table_name = ' . $table;
+        $pkAll = $this->conn->fetchColumn($query, $pkName);
+
+        $result = array();
+
+        foreach ($indexes as $index) {
+            if ( ! in_array($index, $pkAll) && $index != null) {
+                $result[] = $this->conn->formatter->fixIndexName($index);
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * lists database views
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listViews($database = null)
+    {
+        $query = "SELECT name FROM sysobjects WHERE xtype = 'V'";
+
+        return $this->conn->fetchColumn($query);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Mysql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,240 @@
+<?php
+/*
+ *  $Id: Mysql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Import
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Import_Mysql extends Doctrine_Import
+{
+    protected $sql  = array(
+                            'listDatabases'   => 'SHOW DATABASES',
+                            'listTableFields' => 'DESCRIBE %s',
+                            'listSequences'   => 'SHOW TABLES',
+                            'listTables'      => 'SHOW TABLES',
+                            'listUsers'       => 'SELECT DISTINCT USER FROM USER',
+                            'listViews'       => "SHOW FULL TABLES %s WHERE Table_type = 'VIEW'",
+                            );
+
+    /**
+     * lists all database sequences
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listSequences($database = null)
+    {
+        $query = 'SHOW TABLES';
+        if ( ! is_null($database)) {
+            $query .= ' FROM ' . $database;
+        }
+        $tableNames = $this->conn->fetchColumn($query);
+
+        return array_map(array($this->conn->formatter, 'fixSequenceName'), $tableNames);
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableConstraints($table)
+    {
+        $keyName = 'Key_name';
+        $nonUnique = 'Non_unique';
+        if ($this->conn->getAttribute(Doctrine::ATTR_PORTABILITY) & Doctrine::PORTABILITY_FIX_CASE) {
+            if ($this->conn->getAttribute(Doctrine::ATTR_FIELD_CASE) == CASE_LOWER) {
+                $keyName = strtolower($keyName);
+                $nonUnique = strtolower($nonUnique);
+            } else {
+                $keyName = strtoupper($keyName);
+                $nonUnique = strtoupper($nonUnique);
+            }
+        }
+
+        $table = $this->conn->quoteIdentifier($table, true);
+        $query = 'SHOW INDEX FROM ' . $table;
+        $indexes = $this->conn->fetchAssoc($query);
+
+        $result = array();
+        foreach ($indexes as $indexData) {
+            if ( ! $indexData[$nonUnique]) {
+                if ($indexData[$keyName] !== 'PRIMARY') {
+                    $index = $this->conn->formatter->fixIndexName($indexData[$keyName]);
+                } else {
+                    $index = 'PRIMARY';
+                }
+                if ( ! empty($index)) {
+                    $result[] = $index;
+                }
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * lists table relations
+     *
+     * Expects an array of this format to be returned with all the relationships in it where the key is 
+     * the name of the foreign table, and the value is an array containing the local and foreign column
+     * name
+     *
+     * Array
+     * (
+     *   [groups] => Array
+     *     (
+     *        [local] => group_id
+     *        [foreign] => id
+     *     )
+     * )
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableRelations($tableName)
+    {
+        $relations = array();
+        $sql = "SELECT column_name, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME FROM information_schema.key_column_usage WHERE table_name = '" . $tableName . "' AND table_schema = '" . $this->conn->getDatabaseName() . "' and REFERENCED_COLUMN_NAME is not NULL";
+        $results = $this->conn->fetchAssoc($sql);
+        foreach ($results as $result)
+        {
+            $result = array_change_key_case($result, CASE_LOWER);
+            $relations[] = array('table'   => $result['referenced_table_name'],
+                                 'local'   => $result['column_name'],
+                                 'foreign' => $result['referenced_column_name']);
+        }
+        return $relations;
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableColumns($table)
+    {
+        $sql = 'DESCRIBE ' . $this->conn->quoteIdentifier($table, true);
+        $result = $this->conn->fetchAssoc($sql);
+
+        $description = array();
+        $columns = array();
+        foreach ($result as $key => $val) {
+
+            $val = array_change_key_case($val, CASE_LOWER);
+
+            $decl = $this->conn->dataDict->getPortableDeclaration($val);
+
+            $values = isset($decl['values']) ? $decl['values'] : array();
+            $val['default'] = $val['default'] == 'CURRENT_TIMESTAMP' ? null : $val['default'];
+
+            $description = array(
+                          'name'          => $val['field'],
+                          'type'          => $decl['type'][0],
+                          'alltypes'      => $decl['type'],
+                          'ntype'         => $val['type'],
+                          'length'        => $decl['length'],
+                          'fixed'         => $decl['fixed'],
+                          'unsigned'      => $decl['unsigned'],
+                          'values'        => $values,
+                          'primary'       => (strtolower($val['key']) == 'pri'),
+                          'default'       => $val['default'],
+                          'notnull'       => (bool) ($val['null'] != 'YES'),
+                          'autoincrement' => (bool) (strpos($val['extra'], 'auto_increment') !== false),
+                          );
+            if (isset($decl['scale'])) {
+                $description['scale'] = $decl['scale'];
+            }
+            $columns[$val['field']] = $description;
+        }
+
+        return $columns;
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableIndexes($table)
+    {
+        $keyName = 'Key_name';
+        $nonUnique = 'Non_unique';
+        if ($this->conn->getAttribute(Doctrine::ATTR_PORTABILITY) & Doctrine::PORTABILITY_FIX_CASE) {
+            if ($this->conn->getAttribute(Doctrine::ATTR_FIELD_CASE) == CASE_LOWER) {
+                $keyName = strtolower($keyName);
+                $nonUnique = strtolower($nonUnique);
+            } else {
+                $keyName = strtoupper($keyName);
+                $nonUnique = strtoupper($nonUnique);
+            }
+        }
+
+        $table = $this->conn->quoteIdentifier($table, true);
+        $query = 'SHOW INDEX FROM ' . $table;
+        $indexes = $this->conn->fetchAssoc($query);
+
+
+        $result = array();
+        foreach ($indexes as $indexData) {
+            if ($indexData[$nonUnique] && ($index = $this->conn->formatter->fixIndexName($indexData[$keyName]))) {
+                $result[] = $index;
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * lists tables
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listTables($database = null)
+    {
+        return $this->conn->fetchColumn($this->sql['listTables']);
+    }
+
+    /**
+     * lists database views
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listViews($database = null)
+    {
+        if (is_null($database)) {
+            $query = 'SELECT table_name FROM information_schema.VIEWS';
+        } else {
+            $query = sprintf($this->sql['listViews'], ' FROM ' . $database);
+        }
+
+        return $this->conn->fetchColumn($query);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Oracle.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,269 @@
+<?php
+/*
+ *  $Id: Oracle.php 5850 2009-06-09 08:52:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Import
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @version     $Revision: 5850 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Import_Oracle extends Doctrine_Import
+{
+    /**
+     * lists all databases
+     *
+     * @return array
+     */
+    public function listDatabases()
+    {
+        if ( ! $this->conn->getAttribute(Doctrine::ATTR_EMULATE_DATABASE)) {
+            throw new Doctrine_Import_Exception('database listing is only supported if the "emulate_database" option is enabled');
+        }
+        /**
+        if ($this->conn->options['database_name_prefix']) {
+            $query = 'SELECT SUBSTR(username, ';
+            $query.= (strlen($this->conn->getAttribute(['database_name_prefix'])+1);
+            $query.= ") FROM sys.dba_users WHERE username LIKE '";
+            $query.= $this->conn->options['database_name_prefix']."%'";
+        } else {
+        */
+        $query   = 'SELECT username FROM sys.dba_users';
+
+        $result2 = $this->conn->standaloneQuery($query);
+        $result  = $result2->fetchColumn();
+
+        return $result;
+    }
+
+    /**
+     * lists all availible database functions
+     *
+     * @return array
+     */
+    public function listFunctions()
+    {
+        $query = "SELECT name FROM sys.user_source WHERE line = 1 AND type = 'FUNCTION'";
+
+        return $this->conn->fetchColumn($query);
+    }
+
+    /**
+     * lists all database triggers
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listTriggers($database = null)
+    {
+
+    }
+
+    /**
+     * lists all database sequences
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listSequences($database = null)
+    {
+        $query = "SELECT sequence_name FROM sys.user_sequences";
+
+        $tableNames = $this->conn->fetchColumn($query);
+
+        return array_map(array($this->conn->formatter, 'fixSequenceName'), $tableNames);
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableConstraints($table)
+    {
+        $table = $this->conn->quote($table, 'text');
+
+        $query = 'SELECT index_name name FROM user_constraints'
+               . ' WHERE table_name = ' . $table . ' OR table_name = ' . strtoupper($table);
+
+        $constraints = $this->conn->fetchColumn($query);
+
+        return array_map(array($this->conn->formatter, 'fixIndexName'), $constraints);
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableColumns($table)
+    {
+		$sql = <<<QEND
+SELECT tc.column_name, data_type,
+CASE WHEN data_type = 'NUMBER' THEN data_precision ELSE data_length END AS data_length,
+nullable, data_default, data_scale, data_precision, pk.primary
+FROM all_tab_columns tc
+LEFT JOIN (
+ select 'primary' primary, cc.table_name, cc.column_name from all_constraints cons
+ join all_cons_columns cc on cons.constraint_name = cc.constraint_name
+ where cons.constraint_type = 'P'
+) pk ON pk.column_name = tc.column_name and pk.table_name = tc.table_name
+WHERE tc.table_name = :tableName ORDER BY column_id
+QEND;
+        $result = $this->conn->fetchAssoc($sql, array(':tableName' => $table));
+
+        $descr = array();
+
+        foreach($result as $val) {
+            $val = array_change_key_case($val, CASE_LOWER);
+            $decl = $this->conn->dataDict->getPortableDeclaration($val);
+
+            $descr[$val['column_name']] = array(
+               'name'       => $val['column_name'],
+               'notnull'    => (bool) ($val['nullable'] === 'N'),
+               'ntype'      => $val['data_type'],
+               'type'       => $decl['type'][0],
+               'alltypes'   => $decl['type'],
+               'fixed'      => $decl['fixed'],
+               'unsigned'   => $decl['unsigned'],
+               'default'    => $val['data_default'],
+               'length'     => $val['data_length'],
+               'primary'    => $val['primary'] ? true:false,
+               'scale'      => isset($val['scale']) ? $val['scale']:null,
+            );
+        }
+
+        return $descr;
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableIndexes($table)
+    {
+        $table = $this->conn->quote($table, 'text');
+        $query = 'SELECT index_name name FROM user_indexes'
+               . ' WHERE table_name = ' . $table . ' OR table_name = ' . strtoupper($table)
+               . ' AND generated = ' . $this->conn->quote('N', 'text');
+
+        $indexes = $this->conn->fetchColumn($query);
+
+        return array_map(array($this->conn->formatter, 'fixIndexName'), $indexes);
+    }
+    
+    /**
+     * list table relations
+     */
+    public function listTableRelations($table)
+    {
+        $relations = array();
+        $sql  = 'SELECT ac.table_name AS referenced_table_name, lcc.column_name AS local_column_name, rcc.column_name AS referenced_column_name '
+              . 'FROM all_constraints ac '
+              . 'JOIN all_cons_columns lcc ON ac.r_constraint_name = lcc.constraint_name '
+              . 'JOIN all_cons_columns rcc ON ac.constraint_name = rcc.constraint_name '
+              . "WHERE ac.constraint_type = 'R'" 
+              . "AND ac.r_constraint_name IN (SELECT constraint_name FROM all_constraints WHERE constraint_type IN ('P', 'U') AND table_name = :tableName)";
+        
+        $results = $this->conn->fetchAssoc($sql, array(':tableName' => $table));
+        foreach ($results as $result) 
+        {
+            $result = array_change_key_case($result, CASE_LOWER);
+            $relations[] = array('table'   => $result['referenced_table_name'],
+                                 'local'   => $result['local_column_name'],
+                                 'foreign' => $result['referenced_column_name']);
+        }
+        return $relations;
+    }
+    /**
+     * lists tables
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listTables($database = null)
+    {
+        $query = 'SELECT table_name FROM sys.user_tables';
+        return $this->conn->fetchColumn($query);
+    }
+
+    /**
+     * lists table triggers
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableTriggers($table)
+    {
+
+    }
+
+    /**
+     * lists table views
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableViews($table)
+    {
+
+    }
+
+    /**
+     * lists database users
+     *
+     * @return array
+     */
+    public function listUsers()
+    {
+        /**
+        if ($this->conn->options['emulate_database'] && $this->conn->options['database_name_prefix']) {
+            $query = 'SELECT SUBSTR(username, ';
+            $query.= (strlen($this->conn->options['database_name_prefix'])+1);
+            $query.= ") FROM sys.dba_users WHERE username NOT LIKE '";
+            $query.= $this->conn->options['database_name_prefix']."%'";
+        } else {
+        */
+
+        $query = 'SELECT username FROM sys.dba_users';
+        //}
+
+        return $this->conn->fetchColumn($query);
+    }
+
+    /**
+     * lists database views
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listViews($database = null)
+    {
+        $query = 'SELECT view_name FROM sys.user_views';
+        return $this->conn->fetchColumn($query);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Pgsql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,282 @@
+<?php
+/*
+ *  $Id: Pgsql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Import
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Paul Cooper <pgc@ucecom.com>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Import_Pgsql extends Doctrine_Import
+{
+
+    protected $sql = array(
+                        'listDatabases' => 'SELECT datname FROM pg_database',
+                        'listFunctions' => "SELECT
+                                                proname
+                                            FROM
+                                                pg_proc pr,
+                                                pg_type tp
+                                            WHERE
+                                                tp.oid = pr.prorettype
+                                                AND pr.proisagg = FALSE
+                                                AND tp.typname <> 'trigger'
+                                                AND pr.pronamespace IN
+                                                    (SELECT oid FROM pg_namespace
+                                                     WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema'",
+                        'listSequences' => "SELECT
+                                                relname
+                                            FROM
+                                                pg_class
+                                            WHERE relkind = 'S' AND relnamespace IN
+                                                (SELECT oid FROM pg_namespace
+                                                 WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')",
+                        'listTables'    => "SELECT
+                                                c.relname AS table_name
+                                            FROM pg_class c, pg_user u
+                                            WHERE c.relowner = u.usesysid
+                                                AND c.relkind = 'r'
+                                                AND NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname)
+                                                AND c.relname !~ '^(pg_|sql_)'
+                                            UNION
+                                            SELECT c.relname AS table_name
+                                            FROM pg_class c
+                                            WHERE c.relkind = 'r'
+                                                AND NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname)
+                                                AND NOT EXISTS (SELECT 1 FROM pg_user WHERE usesysid = c.relowner)
+                                                AND c.relname !~ '^pg_'",
+                        'listViews'     => 'SELECT viewname FROM pg_views',
+                        'listUsers'     => 'SELECT usename FROM pg_user',
+                        'listTableConstraints' => "SELECT
+                                                        relname
+                                                   FROM
+                                                        pg_class
+                                                   WHERE oid IN (
+                                                        SELECT indexrelid
+                                                        FROM pg_index, pg_class
+                                                        WHERE pg_class.relname = %s
+                                                            AND pg_class.oid = pg_index.indrelid
+                                                            AND (indisunique = 't' OR indisprimary = 't')
+                                                        )",
+                        'listTableIndexes'     => "SELECT
+                                                        relname
+                                                   FROM
+                                                        pg_class
+                                                   WHERE oid IN (
+                                                        SELECT indexrelid
+                                                        FROM pg_index, pg_class
+                                                        WHERE pg_class.relname = %s
+                                                            AND pg_class.oid=pg_index.indrelid
+                                                            AND indisunique != 't'
+                                                            AND indisprimary != 't'
+                                                        )",
+                        'listTableColumns'     => "SELECT
+                                                        a.attnum,
+                                                        a.attname AS field,
+                                                        t.typname AS type,
+                                                        format_type(a.atttypid, a.atttypmod) AS complete_type,
+                                                        a.attnotnull AS isnotnull,
+                                                        (SELECT 't'
+                                                          FROM pg_index
+                                                          WHERE c.oid = pg_index.indrelid
+                                                          AND pg_index.indkey[0] = a.attnum
+                                                          AND pg_index.indisprimary = 't'
+                                                        ) AS pri,
+                                                        (SELECT pg_attrdef.adsrc
+                                                          FROM pg_attrdef
+                                                          WHERE c.oid = pg_attrdef.adrelid
+                                                          AND pg_attrdef.adnum=a.attnum
+                                                        ) AS default
+                                                  FROM pg_attribute a, pg_class c, pg_type t
+                                                  WHERE c.relname = %s
+                                                        AND a.attnum > 0
+                                                        AND a.attrelid = c.oid
+                                                        AND a.atttypid = t.oid
+                                                  ORDER BY a.attnum",
+                        'listTableRelations'   => "SELECT pg_catalog.pg_get_constraintdef(oid, true) as condef
+                                                          FROM pg_catalog.pg_constraint r
+                                                          WHERE r.conrelid =
+                                                          (
+                                                              SELECT c.oid
+                                                              FROM pg_catalog.pg_class c
+                                                              LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
+                                                              WHERE c.relname ~ ? AND pg_catalog.pg_table_is_visible(c.oid)
+                                                          )
+                                                          AND r.contype = 'f'"
+                        );
+
+    /**
+     * lists all database triggers
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listTriggers($database = null)
+    {
+
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableConstraints($table)
+    {
+        $table = $this->conn->quote($table);
+        $query = sprintf($this->sql['listTableConstraints'], $table);
+
+        return $this->conn->fetchColumn($query);
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableColumns($table)
+    {
+        $table = $this->conn->quote($table);
+        $query = sprintf($this->sql['listTableColumns'], $table);
+        $result = $this->conn->fetchAssoc($query);
+
+        $columns     = array();
+        foreach ($result as $key => $val) {
+            $val = array_change_key_case($val, CASE_LOWER);
+
+            if (strtolower($val['type']) === 'varchar') {
+                // get length from varchar definition
+                $length = preg_replace('~.*\(([0-9]*)\).*~', '$1', $val['complete_type']);
+                $val['length'] = $length;
+            }
+            
+            $decl = $this->conn->dataDict->getPortableDeclaration($val);
+
+            $description = array(
+                'name'      => $val['field'],
+                'ntype'     => $val['type'],
+                'type'      => $decl['type'][0],
+                'alltypes'  => $decl['type'],
+                'length'    => $decl['length'],
+                'fixed'     => $decl['fixed'],
+                'unsigned'  => $decl['unsigned'],
+                'notnull'   => ($val['isnotnull'] == true),
+                'default'   => $val['default'],
+                'primary'   => ($val['pri'] == 't'),
+            );
+            
+            $matches = array(); 
+
+            if (preg_match("/^nextval\('(.*)'(::.*)?\)$/", $description['default'], $matches)) { 
+     
+                $description['sequence'] = $this->conn->formatter->fixSequenceName($matches[1]); 
+                $description['default'] = null; 
+            } 
+            
+            $columns[$val['field']] = $description;
+        }
+        
+        return $columns;
+    }
+
+    /**
+     * list all indexes in a table
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableIndexes($table)
+    {
+        $table = $this->conn->quote($table);
+        $query = sprintf($this->sql['listTableIndexes'], $table);
+
+        return $this->conn->fetchColumn($query);
+    }
+
+    /**
+     * lists tables
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listTables($database = null)
+    {
+        return $this->conn->fetchColumn($this->sql['listTables']);
+    }
+
+    /**
+     * lists table triggers
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableTriggers($table)
+    {
+        $query = 'SELECT trg.tgname AS trigger_name
+                    FROM pg_trigger trg,
+                         pg_class tbl
+                   WHERE trg.tgrelid = tbl.oid';
+        if ($table !== null) {
+            $table = $this->conn->quote(strtoupper($table), 'string');
+            $query .= " AND tbl.relname = $table";
+        }
+        return $this->conn->fetchColumn($query);
+    }
+
+    /**
+     * list the views in the database that reference a given table
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableViews($table)
+    {
+        return $this->conn->fetchColumn($table);
+    }
+
+    public function listTableRelations($table)
+    {
+        $sql = $this->sql['listTableRelations'];
+        $param = array('^(' . $table . ')$');
+
+        $relations = array();
+
+        $results = $this->conn->fetchAssoc($sql, $param);
+        foreach ($results as $result)
+        {
+            preg_match('/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)/', $result['condef'], $values);
+            if ((strpos(',', $values[1]) === false) && (strpos(',', $values[3]) === false)) {
+                $relations[] = array('table'   => $values[2],
+                                     'local'   => $values[1],
+                                     'foreign' => $values[3]);
+            }
+        }
+
+        return $relations;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Schema.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,753 @@
+<?php
+/*
+ * $Id: Schema.php 1838 2007-06-26 00:58:21Z nicobn $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Import_Schema
+ *
+ * Class for importing Doctrine_Record classes from a yaml schema definition
+ *
+ * @package     Doctrine
+ * @subpackage  Import
+ * @link        www.phpdoctrine.org
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision: 1838 $
+ * @author      Nicolas Bérard-Nault <nicobn@gmail.com>
+ * @author      Jonathan H. Wage <jonwage@gmail.com>
+ */
+class Doctrine_Import_Schema
+{
+    /**
+     * _relations
+     *
+     * Array of all relationships parsed from all schema files
+     *
+     * @var array
+     */
+    protected $_relations = array();
+
+    /**
+     * _options
+     *
+     * Array of options used to configure the model generation from the parsed schema files
+     * This array is forwarded to Doctrine_Import_Builder
+     *
+     * @var array
+     */
+    protected $_options = array('packagesPrefix'        =>  'Package',
+                                'packagesPath'          =>  '',
+                                'packagesFolderName'    =>  'packages',
+                                'suffix'                =>  '.php',
+                                'generateBaseClasses'   =>  true,
+                                'generateTableClasses'  =>  false,
+                                'generateAccessors'     =>  false,
+                                'baseClassPrefix'       =>  'Base',
+                                'baseClassesDirectory'  =>  'generated',
+                                'baseClassName'         =>  'Doctrine_Record');
+
+    /**
+     * _validation
+     *
+     * Array used to validate schema element.
+     * See: _validateSchemaElement
+     *
+     * @var array
+     */
+    protected $_validation = array('root'       =>  array('abstract',
+                                                          'connection',
+                                                          'className',
+                                                          'tableName',
+                                                          'connection',
+                                                          'relations',
+                                                          'columns',
+                                                          'indexes',
+                                                          'attributes',
+                                                          'templates',
+                                                          'actAs',
+                                                          'options',
+                                                          'package',
+                                                          'package_custom_path',
+                                                          'inheritance',
+                                                          'detect_relations',
+                                                          'listeners',
+                                                          'checks'),
+
+                                   'column'     =>  array('name',
+                                                          'format',
+                                                          'fixed',
+                                                          'primary',
+                                                          'autoincrement',
+                                                          'type',
+                                                          'length',
+                                                          'size',
+                                                          'default',
+                                                          'scale',
+                                                          'values',
+                                                          'comment',
+                                                          'sequence',
+                                                          'protected',
+                                                          'zerofill',
+                                                          'owner',
+                                                          'extra'),
+
+                                   'relation'   =>  array('key',
+                                                          'class',
+                                                          'alias',
+                                                          'type',
+                                                          'refClass',
+                                                          'local',
+                                                          'foreign',
+                                                          'foreignClass',
+                                                          'foreignAlias',
+                                                          'foreignType',
+                                                          'autoComplete',
+                                                          'cascade',
+                                                          'onDelete',
+                                                          'onUpdate',
+                                                          'equal',
+                                                          'owningSide',
+                                                          'refClassRelationAlias'),
+
+                                   'inheritance'=>  array('type',
+                                                          'extends',
+                                                          'keyField',
+                                                          'keyValue'));
+
+    /**
+     * _validators
+     *
+     * Array of available validators
+     *
+     * @see getValidators()
+     * @var array Array of available validators
+     */
+    protected $_validators = array();
+
+    /**
+     * getValidators
+     *
+     * Retrieve the array of available validators
+     *
+     * @return array
+     */
+    public function getValidators()
+    {
+        if (empty($this->_validators)) {
+            $this->_validators = Doctrine_Lib::getValidators();
+        }
+
+        return $this->_validators;
+    }
+
+    /**
+     * getOption
+     *
+     * @param string $name 
+     * @return void
+     */
+    public function getOption($name)
+    {
+        if (isset($this->_options[$name]))   {
+            return $this->_options[$name];
+        }
+    }
+
+    /**
+     * getOptions
+     *
+     * @return void
+     */
+    public function getOptions()
+    {
+        return $this->_options;
+    }
+
+    /**
+     * setOption
+     *
+     * @param string $name 
+     * @param string $value 
+     * @return void
+     */
+    public function setOption($name, $value)
+    {
+        if (isset($this->_options[$name])) {
+            $this->_options[$name] = $value;
+        }
+    }
+    
+    /**
+     * setOptions
+     *
+     * @param string $options 
+     * @return void
+     */
+    public function setOptions($options)
+    {
+        if ( ! empty($options)) {
+          $this->_options = $options;
+        }
+    }
+
+    /**
+     * buildSchema
+     *
+     * Loop throug directories of schema files and parse them all in to one complete array of schema information
+     *
+     * @param  string   $schema Array of schema files or single schema file. Array of directories with schema files or single directory
+     * @param  string   $format Format of the files we are parsing and building from
+     * @return array    $array
+     */
+    public function buildSchema($schema, $format)
+    {
+        $array = array();
+
+        foreach ((array) $schema AS $s) {
+            if (is_file($s)) {
+                $e = explode('.', $s);
+                if (end($e) === $format) {
+                    $array = array_merge($array, $this->parseSchema($s, $format));
+                }
+            } else if (is_dir($s)) {
+                $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($s),
+                                                      RecursiveIteratorIterator::LEAVES_ONLY);
+
+                foreach ($it as $file) {
+                    $e = explode('.', $file->getFileName());
+                    if (end($e) === $format) {
+                        $array = array_merge($array, $this->parseSchema($file->getPathName(), $format));
+                    }
+                }
+            } else {
+              $array = array_merge($array, $this->parseSchema($s, $format));
+            }
+        }
+
+        $array = $this->_buildRelationships($array);
+        $array = $this->_processInheritance($array);
+
+        return $array;
+    }
+
+    /**
+     * importSchema
+     *
+     * A method to import a Schema and translate it into a Doctrine_Record object
+     *
+     * @param  string $schema       The file containing the XML schema
+     * @param  string $format       Format of the schema file
+     * @param  string $directory    The directory where the Doctrine_Record class will be written
+     * @param  array  $models       Optional array of models to import
+     *
+     * @return void
+     */
+    public function importSchema($schema, $format = 'yml', $directory = null, $models = array())
+    {
+        $schema = (array) $schema;
+        $builder = new Doctrine_Import_Builder();
+        $builder->setTargetPath($directory);
+        $builder->setOptions($this->getOptions());
+        
+        $array = $this->buildSchema($schema, $format);
+
+        if (count($array) == 0) { 
+            throw new Doctrine_Import_Exception(
+                sprintf('No ' . $format . ' schema found in ' . implode(", ", $schema))
+            ); 
+        }
+
+        foreach ($array as $name => $definition) {
+            if ( ! empty($models) && !in_array($definition['className'], $models)) {
+                continue;
+            }
+            
+            $builder->buildRecord($definition);
+        }
+    }
+
+    /**
+     * parseSchema
+     *
+     * A method to parse a Schema and translate it into a property array.
+     * The function returns that property array.
+     *
+     * @param  string $schema   Path to the file containing the schema
+     * @param  string $type     Format type of the schema we are parsing
+     * @return array  $build    Built array of schema information
+     */
+    public function parseSchema($schema, $type)
+    {
+        $defaults = array('abstract'            =>  false,
+                          'className'           =>  null,
+                          'tableName'           =>  null,
+                          'connection'          =>  null,
+                          'relations'           =>  array(),
+                          'indexes'             =>  array(),
+                          'attributes'          =>  array(),
+                          'templates'           =>  array(),
+                          'actAs'               =>  array(),
+                          'options'             =>  array(),
+                          'package'             =>  null,
+                          'inheritance'         =>  array(),
+                          'detect_relations'    =>  false);
+        
+        $array = Doctrine_Parser::load($schema, $type);
+
+        // Go through the schema and look for global values so we can assign them to each table/class
+        $globals = array();
+        $globalKeys = array('connection',
+                            'attributes',
+                            'templates',
+                            'actAs',
+                            'options',
+                            'package',
+                            'package_custom_path',
+                            'inheritance',
+                            'detect_relations');
+
+        // Loop over and build up all the global values and remove them from the array
+        foreach ($array as $key => $value) {
+            if (in_array($key, $globalKeys)) {
+                unset($array[$key]);
+                $globals[$key] = $value;
+            }
+        }
+
+        // Apply the globals to each table if it does not have a custom value set already
+        foreach ($array as $className => $table) {
+            foreach ($globals as $key => $value) {
+                if (!isset($array[$className][$key])) {
+                    $array[$className][$key] = $value;
+                }
+            }
+        }
+
+        $build = array();
+
+        foreach ($array as $className => $table) {
+            $table = (array) $table;
+            $this->_validateSchemaElement('root', array_keys($table), $className);
+
+            $columns = array();
+
+            $className = isset($table['className']) ? (string) $table['className']:(string) $className;
+
+            if (isset($table['inheritance']['keyField']) || isset($table['inheritance']['keyValue'])) {
+                $table['inheritance']['type'] = 'column_aggregation';
+            }
+
+            if (isset($table['tableName']) && $table['tableName']) {
+                $tableName = $table['tableName'];
+            } else {
+                if (isset($table['inheritance']['type']) && ($table['inheritance']['type'] == 'column_aggregation')) {
+                    $tableName = null;
+                } else {
+                    $tableName = Doctrine_Inflector::tableize($className);
+                }
+            }
+
+            $connection = isset($table['connection']) ? $table['connection']:'current';
+
+            $columns = isset($table['columns']) ? $table['columns']:array();
+
+            if ( ! empty($columns)) {
+                foreach ($columns as $columnName => $field) {
+
+                    // Support short syntax: my_column: integer(4)
+                    if ( ! is_array($field)) {
+                        $original = $field;
+                        $field = array();
+                        $field['type'] = $original;
+                    }
+
+                    $colDesc = array();
+                    if (isset($field['name'])) {
+                        $colDesc['name'] = $field['name'];
+                    } else {
+                        $colDesc['name'] = $columnName;
+                    }
+
+                    $this->_validateSchemaElement('column', array_keys($field), $className . '->columns->' . $colDesc['name']);
+
+                    // Support short type(length) syntax: my_column: { type: integer(4) }
+                    $e = explode('(', $field['type']);
+                    if (isset($e[0]) && isset($e[1])) {
+                        $colDesc['type'] = $e[0];
+                        $value = substr($e[1], 0, strlen($e[1]) - 1);
+                        $e = explode(',', $value);
+                        $colDesc['length'] = $e[0];
+                        if (isset($e[1]) && $e[1]) {
+                            $colDesc['scale'] = $e[1];
+                        }
+                    } else {
+                        $colDesc['type'] = isset($field['type']) ? (string) $field['type']:null;
+                        $colDesc['length'] = isset($field['length']) ? (int) $field['length']:null;
+                        $colDesc['length'] = isset($field['size']) ? (int) $field['size']:$colDesc['length'];
+                    }
+
+                    $colDesc['fixed'] = isset($field['fixed']) ? (int) $field['fixed']:null;
+                    $colDesc['primary'] = isset($field['primary']) ? (bool) (isset($field['primary']) && $field['primary']):null;
+                    $colDesc['default'] = isset($field['default']) ? $field['default']:null;
+                    $colDesc['autoincrement'] = isset($field['autoincrement']) ? (bool) (isset($field['autoincrement']) && $field['autoincrement']):null;
+                    $colDesc['sequence'] = isset($field['sequence']) ? (string) $field['sequence']:null;
+                    $colDesc['values'] = isset($field['values']) ? (array) $field['values']:null;
+
+                    // Include all the specified and valid validators in the colDesc
+                    $validators = $this->getValidators();
+
+                    foreach ($validators as $validator) {
+                        if (isset($field[$validator])) {
+                            $colDesc[$validator] = $field[$validator];
+                        }
+                    }
+
+                    $columns[(string) $columnName] = $colDesc;
+                }
+            }
+
+            // Apply the default values
+            foreach ($defaults as $key => $defaultValue) {
+                if (isset($table[$key]) && ! isset($build[$className][$key])) {
+                    $build[$className][$key] = $table[$key];
+                } else {
+                    $build[$className][$key] = isset($build[$className][$key]) ? $build[$className][$key]:$defaultValue;
+                }
+            }
+            
+            $build[$className]['className'] = $className;
+            $build[$className]['tableName'] = $tableName;
+            $build[$className]['columns'] = $columns;
+            
+            // Make sure that anything else that is specified in the schema makes it to the final array
+            $build[$className] = Doctrine_Lib::arrayDeepMerge($table, $build[$className]);
+            
+            // We need to keep track of the className for the connection
+            $build[$className]['connectionClassName'] = $build[$className]['className'];
+        }
+
+        return $build;
+    }
+
+    /**
+     * _processInheritance
+     * 
+     * Perform some processing on inheritance.
+     * Sets the default type and sets some default values for certain types
+     *
+     * @param string $array 
+     * @return void
+     */
+    protected function _processInheritance($array)
+    {
+        // Apply default inheritance configuration
+        foreach ($array as $className => $definition) {
+            if ( ! empty($array[$className]['inheritance'])) {
+                $this->_validateSchemaElement('inheritance', array_keys($definition['inheritance']), $className . '->inheritance');
+
+                // Default inheritance to concrete inheritance
+                if ( ! isset($array[$className]['inheritance']['type'])) {
+                    $array[$className]['inheritance']['type'] = 'concrete';
+                }
+
+                // Some magic for setting up the keyField and keyValue column aggregation options
+                // Adds keyField to the parent class automatically
+                if ($array[$className]['inheritance']['type'] == 'column_aggregation') {
+                    // Set the keyField to 'type' by default
+                    if ( ! isset($array[$className]['inheritance']['keyField'])) {
+                        $array[$className]['inheritance']['keyField'] = 'type';                        
+                    }
+                    
+                    // Set the keyValue to the name of the child class if it does not exist
+                    if ( ! isset($array[$className]['inheritance']['keyValue'])) {
+                        $array[$className]['inheritance']['keyValue'] = $className;
+                    }
+
+                    $parent = $this->_findBaseSuperClass($array, $definition['className']);
+                    // Add the keyType column to the parent if a definition does not already exist
+                    if ( ! isset($array[$parent]['columns'][$array[$className]['inheritance']['keyField']])) {
+                        $array[$parent]['columns'][$array[$className]['inheritance']['keyField']] = array('name' => $array[$className]['inheritance']['keyField'], 'type' => 'string', 'length' => 255);
+                    }
+                }
+            }
+        }
+
+        // Array of the array keys to move to the parent, and the value to default the child definition to
+        // after moving it. Will also populate the subclasses array for the inheritance parent
+        $moves = array('columns' => array(),
+                       'indexes' => array(),
+                       'attributes' => array(),
+                       'options' => array(),
+                       'checks' => array());
+
+        foreach ($array as $className => $definition) {
+            // Move any definitions on the schema to the parent
+            if (isset($definition['inheritance']['extends']) && isset($definition['inheritance']['type']) && ($definition['inheritance']['type'] == 'simple' || $definition['inheritance']['type'] == 'column_aggregation')) {
+                $parent = $this->_findBaseSuperClass($array, $definition['className']);
+                foreach ($moves as $move => $resetValue) {
+                    if (isset($array[$parent][$move]) && isset($definition[$move])) {
+                        $array[$parent][$move] = Doctrine_Lib::arrayDeepMerge($array[$parent][$move], $definition[$move]);
+                        $array[$definition['className']][$move] = $resetValue;
+                    }
+                }
+
+                // Populate the parents subclasses
+                if ($definition['inheritance']['type'] == 'column_aggregation') {
+                    $array[$parent]['inheritance']['subclasses'][$definition['className']] = array($definition['inheritance']['keyField'] => $definition['inheritance']['keyValue']);
+                }
+            }
+        }
+
+        return $array;
+    }
+
+    /**
+     * Find the base super class for this inheritance child. We need to move all levels of children to the
+     * top most parent.
+     *
+     * @param  array  $array  Array of schema information
+     * @return string $class  Class to get find the parent for
+     */
+    protected function _findBaseSuperClass($array, $class)
+    {
+        if (isset($array[$class]['inheritance']['extends']) && isset($array[$class]['inheritance']['type']) && ($array[$class]['inheritance']['type'] == 'simple' || $array[$class]['inheritance']['type'] == 'column_aggregation')) {
+            return $this->_findBaseSuperClass($array, $array[$class]['inheritance']['extends']);
+        } else {
+            return $class;
+        }
+    }
+
+    /**
+     * buildRelationships
+     *
+     * Loop through an array of schema information and build all the necessary relationship information
+     * Will attempt to auto complete relationships and simplify the amount of information required 
+     * for defining a relationship
+     *
+     * @param  string $array 
+     * @return void
+     */
+    protected function _buildRelationships($array)
+    {
+        // Handle auto detecting relations by the names of columns
+        // User.contact_id will automatically create User hasOne Contact local => contact_id, foreign => id
+        foreach ($array as $className => $properties) {
+            if (isset($properties['columns']) && ! empty($properties['columns']) && isset($properties['detect_relations']) && $properties['detect_relations']) {
+                foreach ($properties['columns'] as $column) {
+                    // Check if the column we are inflecting has a _id on the end of it before trying to inflect it and find
+                    // the class name for the column
+                    if (strpos($column['name'], '_id')) {
+                        $columnClassName = Doctrine_Inflector::classify(str_replace('_id', '', $column['name']));
+                        if (isset($array[$columnClassName]) && !isset($array[$className]['relations'][$columnClassName])) {
+                            $array[$className]['relations'][$columnClassName] = array();
+
+                            // Set the detected foreign key type and length to the same as the primary key
+                            // of the related table
+                            $type = isset($array[$columnClassName]['columns']['id']['type']) ? $array[$columnClassName]['columns']['id']['type']:'integer';
+                            $length = isset($array[$columnClassName]['columns']['id']['length']) ? $array[$columnClassName]['columns']['id']['length']:8;
+                            $array[$className]['columns'][$column['name']]['type'] = $type;
+                            $array[$className]['columns'][$column['name']]['length'] = $length;
+                        }
+                    }
+                }
+            }
+        }
+
+        foreach ($array as $name => $properties) {
+            if ( ! isset($properties['relations'])) {
+                continue;
+            }
+            
+            $className = $properties['className'];
+            $relations = $properties['relations'];
+            
+            foreach ($relations as $alias => $relation) {
+                $class = isset($relation['class']) ? $relation['class']:$alias;
+                if ( ! isset($array[$class])) {
+                    continue;
+                }
+                $relation['class'] = $class;
+                $relation['alias'] = isset($relation['alias']) ? $relation['alias'] : $alias;
+                
+                // Attempt to guess the local and foreign
+                if (isset($relation['refClass'])) {
+                    $relation['local'] = isset($relation['local']) ? $relation['local']:Doctrine_Inflector::tableize($name) . '_id';
+                    $relation['foreign'] = isset($relation['foreign']) ? $relation['foreign']:Doctrine_Inflector::tableize($class) . '_id';
+                } else {
+                    $relation['local'] = isset($relation['local']) ? $relation['local']:Doctrine_Inflector::tableize($relation['class']) . '_id';
+                    $relation['foreign'] = isset($relation['foreign']) ? $relation['foreign']:'id';
+                }
+                
+                if (isset($relation['refClass'])) {
+                    $relation['type'] = 'many';
+                }
+                
+                if (isset($relation['type']) && $relation['type']) {
+                    $relation['type'] = $relation['type'] === 'one' ? Doctrine_Relation::ONE:Doctrine_Relation::MANY;
+                } else {
+                    $relation['type'] = Doctrine_Relation::ONE;
+                }
+
+                if (isset($relation['foreignType']) && $relation['foreignType']) {
+                    $relation['foreignType'] = $relation['foreignType'] === 'one' ? Doctrine_Relation::ONE:Doctrine_Relation::MANY;
+                }
+                
+                $relation['key'] = $this->_buildUniqueRelationKey($relation);
+                
+                $this->_validateSchemaElement('relation', array_keys($relation), $className . '->relation->' . $relation['alias']);
+                
+                $this->_relations[$className][$alias] = $relation;
+            }
+        }
+        
+        // Now we auto-complete opposite ends of relationships
+        $this->_autoCompleteOppositeRelations();
+        
+        // Make sure we do not have any duplicate relations
+        $this->_fixDuplicateRelations();
+
+        // Set the full array of relationships for each class to the final array
+        foreach ($this->_relations as $className => $relations) {
+            $array[$className]['relations'] = $relations;
+        }
+        
+        return $array;
+    }
+
+    /**
+     * fixRelationships
+     *
+     * Loop through all relationships building the opposite ends of each relationship
+     * and make sure no duplicate relations exist
+     *
+     * @return void
+     */
+    protected function _autoCompleteOppositeRelations()
+    {
+        foreach($this->_relations as $className => $relations) {
+            foreach ($relations AS $alias => $relation) {
+                if ((isset($relation['equal']) && $relation['equal']) || (isset($relation['autoComplete']) && $relation['autoComplete'] === false)) {
+                    continue;
+                }
+                
+                $newRelation = array();
+                $newRelation['foreign'] = $relation['local'];
+                $newRelation['local'] = $relation['foreign'];
+                $newRelation['class'] = isset($relation['foreignClass']) ? $relation['foreignClass']:$className;
+                $newRelation['alias'] = isset($relation['foreignAlias']) ? $relation['foreignAlias']:$className;
+                $newRelation['foreignAlias'] = $alias;
+                
+                // this is so that we know that this relation was autogenerated and
+                // that we do not need to include it if it is explicitly declared in the schema by the users.
+                $newRelation['autogenerated'] = true; 
+                
+                if (isset($relation['refClass'])) {
+                    $newRelation['refClass'] = $relation['refClass'];
+                    $newRelation['type'] = isset($relation['foreignType']) ? $relation['foreignType']:$relation['type'];
+                } else {                
+                    if(isset($relation['foreignType'])) {
+                        $newRelation['type'] = $relation['foreignType'];
+                    } else {
+                        $newRelation['type'] = $relation['type'] === Doctrine_Relation::ONE ? Doctrine_Relation::MANY:Doctrine_Relation::ONE;
+                    }
+                }
+
+                // Make sure it doesn't already exist
+                if ( ! isset($this->_relations[$relation['class']][$newRelation['alias']])) {
+                    $newRelation['key'] = $this->_buildUniqueRelationKey($newRelation);
+                    $this->_relations[$relation['class']][$newRelation['alias']] = $newRelation;
+                }
+            }
+        }
+    }
+
+    /**
+     * _fixDuplicateRelations
+     *
+     * Ensure the relations for each class are unique and that no duplicated relations exist from the auto generated relations
+     * and the user explicitely defining the opposite end
+     *
+     * @return void
+     */
+    protected function _fixDuplicateRelations()
+    {
+        foreach($this->_relations as $className => $relations) {
+            // This is for checking for duplicates between alias-relations and a auto-generated relations to ensure the result set of unique relations
+            $existingRelations = array();
+            $uniqueRelations = array();
+            foreach ($relations as $relation) {
+                if ( ! in_array($relation['key'], $existingRelations)) {
+                    $existingRelations[] = $relation['key'];
+                    $uniqueRelations = array_merge($uniqueRelations, array($relation['alias'] => $relation));
+                } else {
+                    // check to see if this relationship is not autogenerated, if it's not, then the user must have explicitly declared it
+                    if ( ! isset($relation['autogenerated']) || $relation['autogenerated'] != true) {
+                        $uniqueRelations = array_merge($uniqueRelations, array($relation['alias'] => $relation));
+                    }
+                }
+            }
+            
+            $this->_relations[$className] = $uniqueRelations;
+        }
+    }
+
+    /**
+     * _buildUniqueRelationKey
+     *
+     * Build a unique key to identify a relationship by
+     * Md5 hash of all the relationship parameters
+     *
+     * @param string $relation 
+     * @return void
+     */
+    protected function _buildUniqueRelationKey($relation)
+    {
+        return md5($relation['local'].$relation['foreign'].$relation['class'].(isset($relation['refClass']) ? $relation['refClass']:null));
+    }
+
+    /**
+     * _validateSchemaElement
+     *
+     * @param string $name 
+     * @param string $value 
+     * @return void
+     */
+    protected function _validateSchemaElement($name, $element, $path)
+    {
+        $element = (array) $element;
+
+        $validation = $this->_validation[$name];
+
+        // Validators are a part of the column validation
+        // This should be fixed, made cleaner
+        if ($name == 'column') {
+            $validators = $this->getValidators();
+            $validation = array_merge($validation, $validators);
+        }
+
+        $validation = array_flip($validation);
+        foreach ($element as $key => $value) {
+            if ( ! isset($validation[$value])) {
+                throw new Doctrine_Import_Exception(
+                    sprintf('Invalid schema element named "' . $value . '" at path "' . $path . '"')
+                );
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Sqlite.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,240 @@
+<?php
+/*
+ *  $Id: Sqlite.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Import
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Import_Sqlite extends Doctrine_Import
+{
+    /**
+     * lists all databases
+     *
+     * @return array
+     */
+    public function listDatabases()
+    {
+
+    }
+
+    /**
+     * lists all availible database functions
+     *
+     * @return array
+     */
+    public function listFunctions()
+    {
+
+    }
+
+    /**
+     * lists all database triggers
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listTriggers($database = null)
+    {
+
+    }
+
+    /**
+     * lists all database sequences
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listSequences($database = null)
+    {
+        $query      = "SELECT name FROM sqlite_master WHERE type='table' AND sql NOT NULL ORDER BY name";
+        $tableNames = $this->conn->fetchColumn($query);
+
+        $result = array();
+        foreach ($tableNames as $tableName) {
+            if ($sqn = $this->conn->fixSequenceName($tableName, true)) {
+                $result[] = $sqn;
+            }
+        }
+        if ($this->conn->getAttribute(Doctrine::ATTR_PORTABILITY) & Doctrine::PORTABILITY_FIX_CASE) {
+            $result = array_map(($this->conn->getAttribute(Doctrine::ATTR_FIELD_CASE) == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableConstraints($table)
+    {
+        $table = $this->conn->quote($table, 'text');
+
+        $query = "SELECT sql FROM sqlite_master WHERE type='index' AND ";
+
+        if ($this->conn->getAttribute(Doctrine::ATTR_PORTABILITY) & Doctrine::PORTABILITY_FIX_CASE) {
+            $query .= 'LOWER(tbl_name) = ' . strtolower($table);
+        } else {
+            $query .= 'tbl_name = ' . $table;
+        }
+        $query  .= ' AND sql NOT NULL ORDER BY name';
+        $indexes = $this->conn->fetchColumn($query);
+
+        $result = array();
+        foreach ($indexes as $sql) {
+            if (preg_match("/^create unique index ([^ ]+) on /i", $sql, $tmp)) {
+                $index = $this->conn->formatter->fixIndexName($tmp[1]);
+                if ( ! empty($index)) {
+                    $result[$index] = true;
+                }
+            }
+        }
+
+        if ($this->conn->getAttribute(Doctrine::ATTR_PORTABILITY) & Doctrine::PORTABILITY_FIX_CASE) {
+            $result = array_change_key_case($result, $this->conn->getAttribute(Doctrine::ATTR_FIELD_CASE));
+        }
+        return array_keys($result);
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableColumns($table)
+    {
+        $sql    = 'PRAGMA table_info(' . $table . ')';
+        $result = $this->conn->fetchAll($sql);
+
+        $description = array();
+        $columns     = array();
+        foreach ($result as $key => $val) {
+            $val = array_change_key_case($val, CASE_LOWER);
+            $decl = $this->conn->dataDict->getPortableDeclaration($val);
+
+            $description = array(
+                    'name'      => $val['name'],
+                    'ntype'     => $val['type'],
+                    'type'      => $decl['type'][0],
+                    'alltypes'  => $decl['type'],
+                    'notnull'   => (bool) $val['notnull'],
+                    'default'   => $val['dflt_value'],
+                    'primary'   => (bool) $val['pk'],
+                    'length'    => null,
+                    'scale'     => null,
+                    'precision' => null,
+                    'unsigned'  => null,
+                    );
+            $columns[$val['name']] = $description;
+        }
+        return $columns;
+    }
+
+    /**
+     * lists table constraints
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableIndexes($table)
+    {
+        $sql  = 'PRAGMA index_list(' . $table . ')';
+        return $this->conn->fetchColumn($sql);
+   }
+    /**
+     * lists tables
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listTables($database = null)
+    {
+        $sql = "SELECT name FROM sqlite_master WHERE type = 'table' AND name != 'sqlite_sequence' "
+             . "UNION ALL SELECT name FROM sqlite_temp_master "
+             . "WHERE type = 'table' ORDER BY name";
+
+        return $this->conn->fetchColumn($sql);
+    }
+
+    /**
+     * lists table triggers
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableTriggers($table)
+    {
+
+    }
+
+    /**
+     * lists table views
+     *
+     * @param string $table     database table name
+     * @return array
+     */
+    public function listTableViews($table)
+    {
+        $query = "SELECT name, sql FROM sqlite_master WHERE type='view' AND sql NOT NULL";
+        $views = $db->fetchAll($query);
+
+        $result = array();
+        foreach ($views as $row) {
+            if (preg_match("/^create view .* \bfrom\b\s+\b{$table}\b /i", $row['sql'])) {
+                if ( ! empty($row['name'])) {
+                    $result[$row['name']] = true;
+                }
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * lists database users
+     *
+     * @return array
+     */
+    public function listUsers()
+    {
+
+    }
+
+    /**
+     * lists database views
+     *
+     * @param string|null $database
+     * @return array
+     */
+    public function listViews($database = null)
+    {
+        $query = "SELECT name FROM sqlite_master WHERE type='view' AND sql NOT NULL";
+
+        return $this->conn->fetchColumn($query);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Inflector.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,267 @@
+<?php
+/*
+ *  $Id: Inflector.php 3189 2007-11-18 20:37:44Z meus $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine inflector has static methods for inflecting text
+ * 
+ * The methods in these classes are from several different sources collected
+ * across several different php projects and several different authors. The 
+ * original author names and emails are not known
+ *
+ * @package     Doctrine
+ * @subpackage  Inflector
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3189 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jonwage@gmail.com>
+ */
+class Doctrine_Inflector
+{
+    /**
+     * Convert word in to the format for a Doctrine table name. Converts 'ModelName' to 'model_name'
+     *
+     * @param  string $word  Word to tableize
+     * @return string $word  Tableized word
+     */
+    public static function tableize($word)
+    {
+        return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $word));
+    }
+
+    /**
+     * Convert a word in to the format for a Doctrine class name. Converts 'table_name' to 'TableName'
+     *
+     * @param string  $word  Word to classify
+     * @return string $word  Classified word
+     */
+    public static function classify($word)
+    {
+        $word = preg_replace('/[$]/', '', $word);
+        return preg_replace_callback('~(_?)(_)([\w])~', array("Doctrine_Inflector", "classifyCallback"), ucfirst(strtolower($word)));
+    }
+
+    /**
+     * Callback function to classify a classname properly.
+     *
+     * @param  array  $matches  An array of matches from a pcre_replace call
+     * @return string $string   A string with matches 1 and mathces 3 in upper case.
+     */
+    public static function classifyCallback($matches)
+    {
+        return $matches[1] . strtoupper($matches[3]);
+    }
+
+    /**
+     * Check if a string has utf7 characters in it
+     *
+     * By bmorel at ssi dot fr
+     *
+     * @param  string $string
+     * @return boolean $bool
+     */
+    public static function seemsUtf8($string)
+    {
+    	for ($i = 0; $i < strlen($string); $i++) {
+    		if (ord($string[$i]) < 0x80) continue; # 0bbbbbbb
+    		elseif ((ord($string[$i]) & 0xE0) == 0xC0) $n=1; # 110bbbbb
+    		elseif ((ord($string[$i]) & 0xF0) == 0xE0) $n=2; # 1110bbbb
+    		elseif ((ord($string[$i]) & 0xF8) == 0xF0) $n=3; # 11110bbb
+    		elseif ((ord($string[$i]) & 0xFC) == 0xF8) $n=4; # 111110bb
+    		elseif ((ord($string[$i]) & 0xFE) == 0xFC) $n=5; # 1111110b
+    		else return false; # Does not match any model
+    		for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
+    			if ((++$i == strlen($string)) || ((ord($string[$i]) & 0xC0) != 0x80))
+    			return false;
+    		}
+    	}
+    	return true;
+    }
+    
+    /**
+     * Remove any illegal characters, accents, etc.
+     *
+     * @param  string $string  String to unaccent 
+     * @return string $string  Unaccented string
+     */
+    public static function unaccent($string)
+    {
+      	if ( ! preg_match('/[\x80-\xff]/', $string) ) {
+      		return $string;
+  		}
+
+      	if (self::seemsUtf8($string)) {
+      		$chars = array(
+      		// Decompositions for Latin-1 Supplement
+      		chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
+      		chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
+      		chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
+      		chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
+      		chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
+      		chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
+      		chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
+      		chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
+      		chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
+      		chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
+      		chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
+      		chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
+      		chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
+      		chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
+      		chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
+      		chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
+      		chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
+      		chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
+      		chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
+      		chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
+      		chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
+      		chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
+      		chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
+      		chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
+      		chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
+      		chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
+      		chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
+      		chr(195).chr(191) => 'y',
+      		// Decompositions for Latin Extended-A
+      		chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
+      		chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
+      		chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
+      		chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
+      		chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
+      		chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
+      		chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
+      		chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
+      		chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
+      		chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
+      		chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
+      		chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
+      		chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
+      		chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
+      		chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
+      		chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
+      		chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
+      		chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
+      		chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
+      		chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
+      		chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
+      		chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
+      		chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
+      		chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
+      		chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
+      		chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
+      		chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
+      		chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
+      		chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
+      		chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
+      		chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
+      		chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
+      		chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
+      		chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
+      		chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
+      		chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
+      		chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
+      		chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
+      		chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
+      		chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
+      		chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
+      		chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
+      		chr(197).chr(148) => 'R', chr(197).chr(149) => 'r',
+      		chr(197).chr(150) => 'R', chr(197).chr(151) => 'r',
+      		chr(197).chr(152) => 'R', chr(197).chr(153) => 'r',
+      		chr(197).chr(154) => 'S', chr(197).chr(155) => 's',
+      		chr(197).chr(156) => 'S', chr(197).chr(157) => 's',
+      		chr(197).chr(158) => 'S', chr(197).chr(159) => 's',
+      		chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
+      		chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
+      		chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
+      		chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
+      		chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
+      		chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
+      		chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
+      		chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
+      		chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
+      		chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
+      		chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
+      		chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
+      		chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
+      		chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
+      		chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
+      		chr(197).chr(190) => 'z', chr(197).chr(191) => 's',
+      		// Euro Sign
+      		chr(226).chr(130).chr(172) => 'E',
+      		// GBP (Pound) Sign
+      		chr(194).chr(163) => '');
+
+      		$string = strtr($string, $chars);
+      	} else {
+      		// Assume ISO-8859-1 if not UTF-8
+      		$chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158)
+      			.chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194)
+      			.chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202)
+      			.chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210)
+      			.chr(211).chr(212).chr(213).chr(214).chr(216).chr(217).chr(218)
+      			.chr(219).chr(220).chr(221).chr(224).chr(225).chr(226).chr(227)
+      			.chr(228).chr(229).chr(231).chr(232).chr(233).chr(234).chr(235)
+      			.chr(236).chr(237).chr(238).chr(239).chr(241).chr(242).chr(243)
+      			.chr(244).chr(245).chr(246).chr(248).chr(249).chr(250).chr(251)
+      			.chr(252).chr(253).chr(255);
+
+      		$chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy";
+
+      		$string = strtr($string, $chars['in'], $chars['out']);
+      		$doubleChars['in'] = array(chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254));
+      		$doubleChars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th');
+      		$string = str_replace($doubleChars['in'], $doubleChars['out'], $string);
+      	}
+
+      	return $string;
+    }
+
+    /**
+     * Convert any passed string to a url friendly string. Converts 'My first blog post' to 'my-first-blog-post'
+     *
+     * @param  string $text  Text to urlize
+     * @return string $text  Urlized text
+     */
+    public static function urlize($text)
+    {
+        // Remove all non url friendly characters with the unaccent function
+        $text = self::unaccent($text);
+        
+        if (function_exists('mb_strtolower'))
+        {
+            $text = mb_strtolower($text);
+        } else {
+            $text = strtolower($text);
+        }
+        
+        // Remove all none word characters
+        $text = preg_replace('/\W/', ' ', $text);
+        
+        // More stripping. Replace spaces with dashes
+        $text = strtolower(preg_replace('/[^A-Z^a-z^0-9^\/]+/', '-',
+                           preg_replace('/([a-z\d])([A-Z])/', '\1_\2',
+                           preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1_\2',
+                           preg_replace('/::/', '/', $text)))));
+        
+        return trim($text, '-');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/IntegrityMapper.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,174 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_IntegrityMapper
+ *
+ * @package     Doctrine
+ * @subpackage  IntegrityMapper
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_IntegrityMapper 
+{
+    /**
+     * processDeleteIntegrity 
+     * 
+     * @param Doctrine_Record $record 
+     * @return void
+     */
+    public function processDeleteIntegrity(Doctrine_Record $record)
+    {
+        $coll = $this->buildIntegrityRelationQuery($record);
+        
+        $this->invokeIntegrityActions($record);
+    }
+
+
+    /**
+     * invokeIntegrityActions 
+     * 
+     * @param Doctrine_Record $record 
+     * @return void
+     */
+    public function invokeIntegrityActions(Doctrine_Record $record)
+    {
+        $deleteActions = Doctrine_Manager::getInstance()
+                         ->getDeleteActions($record->getTable()->getComponentName());
+                         
+        foreach ($record->getTable()->getRelations() as $relation) {
+            $componentName = $relation->getTable()->getComponentName();
+            
+            foreach($record->get($relation->getAlias()) as $coll) {
+                if ( ! ($coll instanceof Doctrine_Collection)) {
+                    $coll = array($coll);
+                }
+                foreach ($coll as $record) {
+                    $this->invokeIntegrityActions($record);
+
+                    if (isset($deleteActions[$componentName])) {
+                        if ($deleteActions[$componentName] === 'SET NULL') {
+                            $record->set($relation->getForeign(), null);
+                        } elseif ($deleteActions[$componentName] === 'CASCADE') {
+                            $this->conn->transaction->addDelete($record);
+                        }
+                    }
+
+                }
+            }
+        }
+    }
+
+    /**
+     * buildIntegrityRelationQuery 
+     * 
+     * @param Doctrine_Record $record 
+     * @return array The result
+     */
+    public function buildIntegrityRelationQuery(Doctrine_Record $record)
+    {
+        $q = new Doctrine_Query();
+        
+        $aliases = array();
+        $indexes = array();
+
+        $root = $record->getTable()->getComponentName();
+        $rootAlias = strtolower(substr($root, 0, 1));
+        $aliases[$rootAlias] = $root;
+
+        foreach ((array) $record->getTable()->getIdentifier() as $id) {
+            $field = $rootAlias . '.' . $id;
+            $cond[]   = $field . ' = ?';
+            $fields[] = $field;
+            $params   = $record->get($id);
+        }
+        $fields = implode(', ', $fields);
+        $components[] = $root;
+        $this->buildIntegrityRelations($record->getTable(), $aliases, $fields, $indexes, $components);
+
+        $q->select($fields)->from($root. ' ' . $rootAlias);
+
+        foreach ($aliases as $alias => $name) {
+            $q->leftJoin($rootAlias . '.' . $name . ' ' . $alias);
+        }
+        $q->where(implode(' AND ', $cond));
+
+        return $q->execute(array($params));
+    }
+
+    /**
+     * buildIntegrityRelations 
+     * 
+     * @param Doctrine_Table $table 
+     * @param mixed $aliases 
+     * @param mixed $fields 
+     * @param mixed $indexes 
+     * @param mixed $components 
+     * @return void
+     */
+    public function buildIntegrityRelations(Doctrine_Table $table, &$aliases, &$fields, &$indexes, &$components)
+    {
+        $deleteActions = Doctrine_Manager::getInstance()
+                         ->getDeleteActions($table->getComponentName());
+
+        foreach ($table->getRelations() as $relation) {
+            $componentName = $relation->getTable()->getComponentName();
+            if (in_array($componentName, $components)) {
+                continue;
+            }
+            $components[] = $componentName;
+
+            $alias = strtolower(substr($relation->getAlias(), 0, 1));
+
+            if ( ! isset($indexes[$alias])) {
+                $indexes[$alias] = 1;
+            }
+
+            if (isset($deleteActions[$componentName])) {
+                if (isset($aliases[$alias])) {
+                    $alias = $alias . ++$indexes[$alias];
+                }
+                $aliases[$alias] = $relation->getAlias();
+
+                if ($deleteActions[$componentName] === 'SET NULL') {
+                    if ($relation instanceof Doctrine_Relation_ForeignKey) {
+                        foreach ((array) $relation->getForeign() as $foreign) {
+                            $fields .= ', ' . $alias . '.' . $foreign;
+                        }
+                    } elseif ($relation instanceof Doctrine_Relation_LocalKey) {
+                        foreach ((array) $relation->getLocal() as $foreign) {
+                            $fields .= ', ' . $alias . '.' . $foreign;
+                        }
+                    }
+                }
+                foreach ((array) $relation->getTable()->getIdentifier() as $id) {
+                    $fields .= ', ' . $alias . '.' . $id;
+                }
+                if ($deleteActions[$componentName] === 'CASCADE') {
+                    $this->buildIntegrityRelations($relation->getTable(), $aliases, $fields, $indexes, $components);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Lib.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,386 @@
+<?php
+/*
+ *  $Id: Lib.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Lib has not commonly used static functions, mostly for debugging purposes
+ *
+ * @package     Doctrine
+ * @subpackage  Lib
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Lib
+{
+    /**
+     * getRecordStateAsString
+     *
+     * @param integer $state the state of record
+     * @see Doctrine_Record::STATE_* constants
+     * @return string string representation of given state
+     */
+    public static function getRecordStateAsString($state)
+    {
+        switch ($state) {
+            case Doctrine_Record::STATE_PROXY:
+                return "proxy";
+                break;
+            case Doctrine_Record::STATE_CLEAN:
+                return "persistent clean";
+                break;
+            case Doctrine_Record::STATE_DIRTY:
+                return "persistent dirty";
+                break;
+            case Doctrine_Record::STATE_TDIRTY:
+                return "transient dirty";
+                break;
+            case Doctrine_Record::STATE_TCLEAN:
+                return "transient clean";
+                break;
+        }
+    }
+
+    /**
+     * getRecordAsString
+     *
+     * returns a string representation of Doctrine_Record object
+     *
+     * @param Doctrine_Record $record
+     * @return string
+     */
+    public static function getRecordAsString(Doctrine_Record $record)
+    {
+        $r[] = '<pre>';
+        $r[] = 'Component  : ' . $record->getTable()->getComponentName();
+        $r[] = 'ID         : ' . Doctrine::dump($record->identifier());
+        $r[] = 'References : ' . count($record->getReferences());
+        $r[] = 'State      : ' . Doctrine_Lib::getRecordStateAsString($record->state());
+        $r[] = 'OID        : ' . $record->getOID();
+        $r[] = 'data       : ' . Doctrine::dump($record->getData(), false);
+        $r[] = '</pre>';
+
+        return implode("\n",$r)."<br />";
+    }
+
+    /**
+     * getConnectionStateAsString
+     *
+     * returns a given connection state as string
+     *
+     * @param integer $state State of the connection as a string
+     */
+    public static function getConnectionStateAsString($state)
+    {
+        switch ($state) {
+            case Doctrine_Transaction::STATE_SLEEP:
+                return "open";
+                break;
+            case Doctrine_Transaction::STATE_BUSY:
+                return "busy";
+                break;
+            case Doctrine_Transaction::STATE_ACTIVE:
+                return "active";
+                break;
+        }
+    }
+
+    /**
+     * getConnectionAsString
+     *
+     * returns a string representation of Doctrine_Connection object
+     *
+     * @param Doctrine_Connection $connection
+     * @return string
+     */
+    public static function getConnectionAsString(Doctrine_Connection $connection)
+    {
+        $r[] = '<pre>';
+        $r[] = 'Doctrine_Connection object';
+        $r[] = 'State               : ' . Doctrine_Lib::getConnectionStateAsString($connection->transaction->getState());
+        $r[] = 'Open Transactions   : ' . $connection->transaction->getTransactionLevel();
+        $r[] = 'Table in memory     : ' . $connection->count();
+        $r[] = 'Driver name         : ' . $connection->getAttribute(Doctrine::ATTR_DRIVER_NAME);
+        $r[] = "</pre>";
+        
+        return implode("\n",$r)."<br>";
+    }
+
+    /**
+     * getTableAsString
+     *
+     * returns a string representation of Doctrine_Table object
+     *
+     * @param Doctrine_Table $table
+     * @return string
+     */
+    public static function getTableAsString(Doctrine_Table $table)
+    {
+        $r[] = "<pre>";
+        $r[] = "Component   : ".$table->getComponentName();
+        $r[] = "Table       : ".$table->getTableName();
+        $r[] = "</pre>";
+        
+        return implode("\n",$r)."<br>";
+    }
+
+    /**
+     * formatSql 
+     * 
+     * @todo: What about creating a config varialbe for the color?
+     * @param mixed $sql 
+     * @return string the formated sql
+     */
+    public static function formatSql($sql)
+    {
+        $e = explode("\n",$sql);
+        $color = "367FAC";
+        $l = $sql;
+        $l = str_replace("SELECT ", "<font color='$color'><b>SELECT </b></font><br \>  ",$l);
+        $l = str_replace("FROM ", "<font color='$color'><b>FROM </b></font><br \>",$l);
+        $l = str_replace(" LEFT JOIN ", "<br \><font color='$color'><b> LEFT JOIN </b></font>",$l);
+        $l = str_replace(" INNER JOIN ", "<br \><font color='$color'><b> INNER JOIN </b></font>",$l);
+        $l = str_replace(" WHERE ", "<br \><font color='$color'><b> WHERE </b></font>",$l);
+        $l = str_replace(" GROUP BY ", "<br \><font color='$color'><b> GROUP BY </b></font>",$l);
+        $l = str_replace(" HAVING ", "<br \><font color='$color'><b> HAVING </b></font>",$l);
+        $l = str_replace(" AS ", "<font color='$color'><b> AS </b></font><br \>  ",$l);
+        $l = str_replace(" ON ", "<font color='$color'><b> ON </b></font>",$l);
+        $l = str_replace(" ORDER BY ", "<font color='$color'><b> ORDER BY </b></font><br \>",$l);
+        $l = str_replace(" LIMIT ", "<font color='$color'><b> LIMIT </b></font><br \>",$l);
+        $l = str_replace(" OFFSET ", "<font color='$color'><b> OFFSET </b></font><br \>",$l);
+        $l = str_replace("  ", "<dd>",$l);
+
+        return $l;
+    }
+
+    /**
+     * getCollectionAsString
+     *
+     * returns a string representation of Doctrine_Collection object
+     *
+     * @param Doctrine_Collection $collection
+     * @return string
+     */
+    public static function getCollectionAsString(Doctrine_Collection $collection)
+    {
+        $r[] = "<pre>";
+        $r[] = get_class($collection);
+        $r[] = 'data : ' . Doctrine::dump($collection->getData(), false);
+        //$r[] = 'snapshot : ' . Doctrine::dump($collection->getSnapshot());
+        $r[] = "</pre>";
+        
+        return implode("\n",$r);
+    }
+
+    // Code from symfony sfToolkit class. See LICENSE
+    // code from php at moechofe dot com (array_merge comment on php.net)
+    /*
+     * arrayDeepMerge
+     *
+     * array arrayDeepMerge ( array array1 [, array array2 [, array ...]] )
+     *
+     * Like array_merge
+     *
+     *  arrayDeepMerge() merges the elements of one or more arrays together so
+     * that the values of one are appended to the end of the previous one. It
+     * returns the resulting array.
+     *  If the input arrays have the same string keys, then the later value for
+     * that key will overwrite the previous one. If, however, the arrays contain
+     * numeric keys, the later value will not overwrite the original value, but
+     * will be appended.
+     *  If only one array is given and the array is numerically indexed, the keys
+     * get reindexed in a continuous way.
+     *
+     * Different from array_merge
+     *  If string keys have arrays for values, these arrays will merge recursively.
+     */
+     public static function arrayDeepMerge()
+     {
+         switch (func_num_args()) {
+             case 0:
+                return false;
+             case 1:
+                return func_get_arg(0);
+             case 2:
+                $args = func_get_args();
+                $args[2] = array();
+                
+                if (is_array($args[0]) && is_array($args[1]))
+                {
+                    foreach (array_unique(array_merge(array_keys($args[0]),array_keys($args[1]))) as $key)
+                    {
+                        $isKey0 = array_key_exists($key, $args[0]);
+                        $isKey1 = array_key_exists($key, $args[1]);
+
+                        if ($isKey0 && $isKey1 && is_array($args[0][$key]) && is_array($args[1][$key]))
+                        {
+                            $args[2][$key] = self::arrayDeepMerge($args[0][$key], $args[1][$key]);
+                        } else if ($isKey0 && $isKey1) {
+                            $args[2][$key] = $args[1][$key];
+                        } else if ( ! $isKey1) {
+                            $args[2][$key] = $args[0][$key];
+                        } else if ( ! $isKey0) {
+                            $args[2][$key] = $args[1][$key];
+                        }
+                    }
+
+                    return $args[2];
+                } else {
+                    return $args[1];
+                }
+            default:
+                $args = func_get_args();
+                $args[1] = self::arrayDeepMerge($args[0], $args[1]);
+                array_shift($args);
+
+                return call_user_func_array(array('Doctrine_Lib', 'arrayDeepMerge'), $args);
+            break;
+        }
+    }
+
+    /**
+     * getValidators
+     *
+     * Get available doctrine validators
+     *
+     * @return array $validators
+     */
+    public static function getValidators()
+    {
+        $validators = array();
+
+        $dir = Doctrine::getPath() . DIRECTORY_SEPARATOR . 'Doctrine' . DIRECTORY_SEPARATOR . 'Validator';
+
+        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY);
+        foreach ($files as $file) {
+            $e = explode('.', $file->getFileName());
+
+            if (end($e) == 'php') {
+                $name = strtolower($e[0]);
+
+                $validators[$name] = $name;
+            }
+        }
+
+        return $validators;
+    }
+
+    /**
+     * makeDirectories
+     *
+     * Makes the directories for a path recursively
+     *
+     * @param string $path
+     * @return void
+     */
+    public static function makeDirectories($path, $mode = 0777)
+    {
+        if ( ! $path) {
+          return false;
+        }
+
+        if (is_dir($path) || is_file($path)) {
+          return true;
+        }
+
+        return mkdir(trim($path), $mode, true);
+    }
+
+    /**
+     * removeDirectories
+     *
+     * @param string $folderPath
+     * @return void
+     */
+    public static function removeDirectories($folderPath)
+    {
+        if (is_dir($folderPath))
+        {
+            foreach (scandir($folderPath) as $value)
+            {
+                if ($value != '.' && $value != '..')
+                {
+                    $value = $folderPath . "/" . $value;
+
+                    if (is_dir($value)) {
+                        self::removeDirectories($value);
+                    } else if (is_file($value)) {
+                        unlink($value);
+                    }
+                }
+            }
+
+            return rmdir($folderPath);
+        } else {
+            return false;
+        }
+    }
+
+    public static function copyDirectory($source, $dest)
+    {
+        // Simple copy for a file
+        if (is_file($source)) {
+            return copy($source, $dest);
+        }
+
+        // Make destination directory
+        if ( ! is_dir($dest)) {
+            mkdir($dest);
+        }
+
+        // Loop through the folder
+        $dir = dir($source);
+        while (false !== $entry = $dir->read()) {
+            // Skip pointers
+            if ($entry == '.' || $entry == '..') {
+                continue;
+            }
+
+            // Deep copy directories
+            if ($dest !== "$source/$entry") {
+                self::copyDirectory("$source/$entry", "$dest/$entry");
+            }
+        }
+
+        // Clean up
+        $dir->close();
+
+        return true;
+    }
+
+    /**
+     * isValidClassName
+     *
+     * checks for valid class name (uses camel case and underscores)
+     *
+     * @param string $classname
+     * @return boolean
+     */
+    public static function isValidClassName($className)
+    {
+        if (preg_match('~(^[a-z])|(_[a-z])|([\W])|(_{2})~', $className)) {
+            return false;
+        }
+
+        return true;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Locator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,197 @@
+<?php
+/**
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.net>.
+ */
+
+/**
+ * Doctrine_Locator
+ *
+ * @package     Doctrine
+ * @subpackage  Doctrine_Locator
+ * @category    Locator
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL
+ * @link        http://www.phpdoctrine.net
+ * @author      Janne Vanhala <jpvanhal@cc.hut.fi>
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Eevert Saukkokoski <dmnEe0@gmail.com>
+ * @version     $Revision$
+ * @since       1.0
+ */
+class Doctrine_Locator implements Countable, IteratorAggregate
+{
+    /**
+     * @var array $_resources       an array of bound resources
+     */
+    protected $_resources = array();
+
+    /**
+     * @var string $_classPrefix    the default class prefix
+     */
+    protected $_classPrefix = 'Doctrine_';
+
+    /** 
+     * @var array $_instances       a pool of this object's instances
+     */
+    protected static $_instances = array();
+
+    /**
+     * Constructor. Provide an array of resources to set initial contents.
+     *
+     * @param array
+     * @return void
+     */
+    public function __construct(array $defaults = null)
+    {
+        if (null !== $defaults) {
+            foreach ($defaults as $name => $resource) {
+                if ($resource instanceof Doctrine_Locator_Injectable) {
+                    $resource->setLocator($this);
+                }
+                $this->_resources[$name] = $resource;
+            }
+        }
+        self::$_instances[] = $this;
+    }
+
+    /** 
+     * instance
+     *
+     * @return Sensei_Locator
+     */
+    public static function instance()
+    {
+        if (empty(self::$_instances)) {
+            $obj = new Doctrine_Locator();
+        }
+        return current(self::$_instances);
+    }
+
+    /**
+     * setClassPrefix
+     *
+     * @param string $prefix
+     */
+    public function setClassPrefix($prefix) 
+    {
+        $this->_classPrefix = $prefix;
+    }
+
+    /**
+     * getClassPrefix
+     *
+     * @return string
+     */
+    public function getClassPrefix()
+    {
+        return $this->_classPrefix;
+    }
+
+    /**
+     * contains
+     * checks if a resource exists under the given name
+     *
+     * @return boolean      whether or not given resource name exists
+     */
+    public function contains($name)
+    {
+        return isset($this->_resources[$name]);
+    }
+
+    /**
+     * bind
+     * binds a resource to a name
+     *
+     * @param string $name      the name of the resource to bind
+     * @param mixed $value      the value of the resource
+     * @return Sensei_Locator   this object
+     */
+    public function bind($name, $value)
+    {
+        $this->_resources[$name] = $value;
+        
+        return $this;
+    }
+
+    /**
+     * locate
+     * locates a resource by given name and returns it
+     *
+     * @throws Doctrine_Locator_Exception     if the resource could not be found
+     * @param string $name      the name of the resource
+     * @return mixed            the located resource
+     */
+    public function locate($name)
+    {
+        if (isset($this->_resources[$name])) {
+            return $this->_resources[$name];
+        } else {
+            $className = $name;
+
+            if ( ! class_exists($className)) {
+
+                $name = explode('.', $name);
+                $name = array_map('strtolower', $name);
+                $name = array_map('ucfirst', $name);
+                $name = implode('_', $name);
+                
+                $className = $this->_classPrefix . $name;
+                
+                if ( ! class_exists($className)) {
+                    throw new Doctrine_Locator_Exception("Couldn't locate resource " . $className);
+                }
+            }
+
+            $this->_resources[$name] = new $className();
+
+            if ($this->_resources[$name] instanceof Doctrine_Locator_Injectable) {
+                $this->_resources[$name]->setLocator($this);
+            }
+
+            return $this->_resources[$name];
+        }
+
+        throw new Doctrine_Locator_Exception("Couldn't locate resource " . $name);
+    }
+
+    /**
+     * count
+     * returns the number of bound resources associated with
+     * this object
+     *
+     * @see Countable interface
+     * @return integer              the number of resources
+     */
+    public function count()
+    {
+        return count($this->_resources);
+    }
+
+    /**
+     * getIterator
+     * returns an ArrayIterator that iterates through all 
+     * bound resources
+     *
+     * @return ArrayIterator    an iterator for iterating through 
+     *                          all bound resources
+     */
+    public function getIterator()
+    {
+        return new ArrayIterator($this->_resources);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Locator/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,36 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.net>.
+ */
+
+/**
+ * Doctrine_Locator_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Doctrine_Locator
+ * @category    Locator
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL
+ * @link        http://www.phpdoctrine.net
+ * @author      Janne Vanhala <jpvanhal@cc.hut.fi>
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @version     $Revision$
+ * @since       1.0
+ */
+class Doctrine_Locator_Exception extends Doctrine_Exception
+{ }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Locator/Injectable.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,149 @@
+<?php
+/**
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.net>.
+ */
+
+/**
+ * Doctrine_Locator_Injectable
+ *
+ * @package     Doctrine
+ * @subpackage  Doctrine_Locator
+ * @category    Locator
+ * @license     http://www.gnu.org/licenses/lgpl.txt LGPL
+ * @link        http://www.phpdoctrine.net
+ * @author      Janne Vanhala <jpvanhal@cc.hut.fi>
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Eevert Saukkokoski <dmnEe0@gmail.com>
+ * @version     $Revision$
+ * @since       1.0
+ */
+class Doctrine_Locator_Injectable
+{
+    /**
+     * @var Doctrine_Locator      the locator object
+     */
+    protected $_locator;
+
+    /**
+     * @var array               an array of bound resources
+     */
+    protected $_resources = array();
+
+    /**
+     * @var Doctrine_Null $null     Doctrine_Null object, used for extremely fast null value checking
+     */
+    protected static $_null;
+
+    /**
+     * setLocator
+     * this method can be used for setting the locator object locally
+     *
+     * @param Doctrine_Locator                the locator object
+     * @return Doctrine_Locator_Injectable    this instance
+     */
+    public function setLocator(Doctrine_Locator $locator)
+    {
+        $this->_locator = $locator;
+        return $this;
+    }
+
+    /**
+     * getLocator
+     * returns the locator associated with this object
+     * 
+     * if there are no locator locally associated then
+     * this method tries to fetch the current global locator
+     *
+     * @return Doctrine_Locator
+     */
+    public function getLocator()
+    {
+        if ( ! isset($this->_locator)) {
+            $this->_locator = Doctrine_Locator::instance();
+
+        }
+        return $this->_locator;
+    }
+
+    /**
+     * locate
+     * locates a resource by given name and returns it
+     *
+     * if the resource cannot be found locally this method tries
+     * to use the global locator for finding the resource
+     *
+     * @see Doctrine_Locator::locate()
+     * @throws Doctrine_Locator_Exception     if the resource could not be found
+     * @param string $name                  the name of the resource
+     * @return mixed                        the located resource
+     */
+    public function locate($name)
+    {
+        if (isset($this->_resources[$name])) {
+            if (is_object($this->_resources[$name])) {
+                return $this->_resources[$name];
+            } else {
+                // get the name of the concrete implementation
+                $concreteImpl = $this->_resources[$name];
+                
+                return $this->getLocator()->locate($concreteImpl);
+            }
+        } else {
+            return $this->getLocator()->locate($name);
+        }
+    }
+
+    /**
+     * bind
+     * binds a resource to a name
+     *
+     * @param string $name      the name of the resource to bind
+     * @param mixed $value      the value of the resource
+     * @return Doctrine_Locator   this object
+     */
+    public function bind($name, $resource)
+    {
+        $this->_resources[$name] = $resource;
+        
+        return $this;    
+    }
+
+    /**
+     * initNullObject
+     * initializes the null object
+     *
+     * @param Doctrine_Null $null
+     * @return void
+     */
+    public static function initNullObject(Doctrine_Null $null)
+    {
+        self::$_null = $null;
+    }
+
+    /**
+     * getNullObject
+     * returns the null object associated with this object
+     *
+     * @return Doctrine_Null
+     */
+    public static function getNullObject()
+    {
+        return self::$_null;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Locking/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,37 @@
+<?PHP
+/**
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.net>.
+ */
+
+/**
+ * Locking exception class
+ *
+ * A loking exception represents an error that occured during a locking process
+ * (obtain/release locks).
+ *
+ * @package     Doctrine
+ * @subpackage  Locking
+ * @link        www.phpdoctrine.org
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Locking_Exception extends Doctrine_Exception
+{}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Locking/Manager/Pessimistic.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,291 @@
+<?php
+/*
+ *  $Id: Pessimistic.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Offline locking of records comes in handy where you need to make sure that
+ * a time-consuming task on a record or many records, which is spread over several
+ * page requests can't be interfered by other users.
+ *
+ * @package     Doctrine
+ * @subpackage  Locking
+ * @link        www.phpdoctrine.org
+ * @author      Roman Borschel <roman@code-factory.org>
+ * @author      Pierre Minnieur <pm@pierre-minnieur.de>
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Locking_Manager_Pessimistic
+{
+    /**
+     * The conn that is used by the locking manager
+     *
+     * @var Doctrine_Connection object
+     */
+    private $conn;
+
+    /**
+     * The database table name for the lock tracking
+     */
+    private $_lockTable = 'doctrine_lock_tracking';
+
+    /**
+     * Constructs a new locking manager object
+     *
+     * When the CREATE_TABLES attribute of the connection on which the manager
+     * is supposed to work on is set to true, the locking table is created.
+     *
+     * @param Doctrine_Connection $conn The database connection to use
+     */
+    public function __construct(Doctrine_Connection $conn)
+    {
+        $this->conn = $conn;
+
+        if ($this->conn->getAttribute(Doctrine::ATTR_EXPORT) & Doctrine::EXPORT_TABLES) {
+            $columns = array();
+            $columns['object_type']        = array('type'    => 'string',
+                                                   'length'  => 50,
+                                                   'notnull' => true,
+                                                   'primary' => true);
+
+            $columns['object_key']         = array('type'    => 'string',
+                                                   'length'  => 250,
+                                                   'notnull' => true,
+                                                   'primary' => true);
+
+            $columns['user_ident']         = array('type'    => 'string',
+                                                   'length'  => 50,
+                                                   'notnull' => true);
+
+            $columns['timestamp_obtained'] = array('type'    => 'integer',
+                                                   'length'  => 10,
+                                                   'notnull' => true);
+
+            $options = array('primary' => array('object_type', 'object_key'));
+            try {
+                $this->conn->export->createTable($this->_lockTable, $columns, $options);
+            } catch(Exception $e) {
+
+            }
+        }
+    }
+
+    /**
+     * Obtains a lock on a {@link Doctrine_Record}
+     *
+     * @param  Doctrine_Record $record     The record that has to be locked
+     * @param  mixed           $userIdent  A unique identifier of the locking user
+     * @return boolean  TRUE if the locking was successful, FALSE if another user
+     *                  holds a lock on this record
+     * @throws Doctrine_Locking_Exception  If the locking failed due to database errors
+     */
+    public function getLock(Doctrine_Record $record, $userIdent)
+    {
+        $objectType = $record->getTable()->getComponentName();
+        $key        = $record->getTable()->getIdentifier();
+
+        $gotLock = false;
+        $time = time();
+
+        if (is_array($key)) {
+            // Composite key
+            $key = implode('|', $key);
+        }
+
+        try {
+            $dbh = $this->conn->getDbh();
+            $this->conn->beginTransaction();
+
+            $stmt = $dbh->prepare('INSERT INTO ' . $this->_lockTable
+                                  . ' (object_type, object_key, user_ident, timestamp_obtained)'
+                                  . ' VALUES (:object_type, :object_key, :user_ident, :ts_obtained)');
+
+            $stmt->bindParam(':object_type', $objectType);
+            $stmt->bindParam(':object_key', $key);
+            $stmt->bindParam(':user_ident', $userIdent);
+            $stmt->bindParam(':ts_obtained', $time);
+
+            try {
+                $stmt->execute();
+                $gotLock = true;
+
+            // we catch an Exception here instead of PDOException since we might also be catching Doctrine_Exception
+            } catch(Exception $pkviolation) {
+                // PK violation occured => existing lock!
+            }
+
+            if ( ! $gotLock) {
+                $lockingUserIdent = $this->_getLockingUserIdent($objectType, $key);
+                if ($lockingUserIdent !== null && $lockingUserIdent == $userIdent) {
+                    $gotLock = true; // The requesting user already has a lock
+                    // Update timestamp
+                    $stmt = $dbh->prepare('UPDATE ' . $this->_lockTable 
+                                          . ' SET timestamp_obtained = :ts'
+                                          . ' WHERE object_type = :object_type AND'
+                                          . ' object_key  = :object_key  AND'
+                                          . ' user_ident  = :user_ident');
+                    $stmt->bindParam(':ts', $time);
+                    $stmt->bindParam(':object_type', $objectType);
+                    $stmt->bindParam(':object_key', $key);
+                    $stmt->bindParam(':user_ident', $lockingUserIdent);
+                    $stmt->execute();
+                }
+            }
+            $this->conn->commit();
+        } catch (Exception $pdoe) {
+            $this->conn->rollback();
+            throw new Doctrine_Locking_Exception($pdoe->getMessage());
+        }
+
+        return $gotLock;
+    }
+
+    /**
+     * Releases a lock on a {@link Doctrine_Record}
+     *
+     * @param  Doctrine_Record $record    The record for which the lock has to be released
+     * @param  mixed           $userIdent The unique identifier of the locking user
+     * @return boolean  TRUE if a lock was released, FALSE if no lock was released
+     * @throws Doctrine_Locking_Exception If the release procedure failed due to database errors
+     */
+    public function releaseLock(Doctrine_Record $record, $userIdent)
+    {
+        $objectType = $record->getTable()->getComponentName();
+        $key        = $record->getTable()->getIdentifier();
+
+        if (is_array($key)) {
+            // Composite key
+            $key = implode('|', $key);
+        }
+
+        try {
+            $dbh = $this->conn->getDbh();
+            $stmt = $dbh->prepare("DELETE FROM $this->_lockTable WHERE
+                                        object_type = :object_type AND
+                                        object_key  = :object_key  AND
+                                        user_ident  = :user_ident");
+            $stmt->bindParam(':object_type', $objectType);
+            $stmt->bindParam(':object_key', $key);
+            $stmt->bindParam(':user_ident', $userIdent);
+            $stmt->execute();
+
+            $count = $stmt->rowCount();
+
+            return ($count > 0);
+        } catch (PDOException $pdoe) {
+            throw new Doctrine_Locking_Exception($pdoe->getMessage());
+        }
+    }
+
+    /**
+     * Gets the unique user identifier of a lock
+     *
+     * @param  string $objectType  The type of the object (component name)
+     * @param  mixed  $key         The unique key of the object
+     * @return mixed  The unique user identifier for the specified lock
+     * @throws Doctrine_Locking_Exception If the query failed due to database errors
+     */
+    private function _getLockingUserIdent($objectType, $key)
+    {
+        if (is_array($key)) {
+            // Composite key
+            $key = implode('|', $key);
+        }
+
+        try {
+            $dbh = $this->conn->getDbh();
+            $stmt = $dbh->prepare('SELECT user_ident FROM ' . $this->_lockTable
+                                  . ' WHERE object_type = :object_type AND object_key = :object_key');
+            $stmt->bindParam(':object_type', $objectType);
+            $stmt->bindParam(':object_key', $key);
+            $success = $stmt->execute();
+
+            if ( ! $success) {
+                throw new Doctrine_Locking_Exception("Failed to determine locking user");
+            }
+
+            $userIdent = $stmt->fetchColumn();
+        } catch (PDOException $pdoe) {
+            throw new Doctrine_Locking_Exception($pdoe->getMessage());
+        }
+
+        return $userIdent;
+    }
+
+    /**
+     * Gets the identifier that identifies the owner of the lock on the given
+     * record.
+     *
+     * @param Doctrine_Record $lockedRecord  The record.
+     * @return mixed The unique user identifier that identifies the owner of the lock.
+     */
+    public function getLockOwner($lockedRecord)
+    {
+        $objectType = $lockedRecord->getTable()->getComponentName();
+        $key        = $lockedRecord->getTable()->getIdentifier();
+        return $this->_getLockingUserIdent($objectType, $key);
+    }
+
+    /**
+     * Releases locks older than a defined amount of seconds
+     *
+     * When called without parameters all locks older than 15 minutes are released.
+     *
+     * @param  integer $age  The maximum valid age of locks in seconds
+     * @param  string  $objectType  The type of the object (component name)
+     * @param  mixed   $userIdent The unique identifier of the locking user
+     * @return integer The number of locks that have been released
+     * @throws Doctrine_Locking_Exception If the release process failed due to database errors
+     */
+    public function releaseAgedLocks($age = 900, $objectType = null, $userIdent = null)
+    {
+        $age = time() - $age;
+
+        try {
+            $dbh = $this->conn->getDbh();
+            $stmt = $dbh->prepare('DELETE FROM ' . $this->_lockTable . ' WHERE timestamp_obtained < :age');
+            $stmt->bindParam(':age', $age);
+            $query = 'DELETE FROM ' . $this->_lockTable . ' WHERE timestamp_obtained < :age';
+            if ($objectType) {
+                $query .= ' AND object_type = :object_type';
+            }
+            if ($userIdent) {
+                $query .= ' AND user_ident = :user_ident';
+            }
+            $stmt = $dbh->prepare($query);
+            $stmt->bindParam(':age', $age);
+            if ($objectType) {
+                $stmt->bindParam(':object_type', $objectType);
+            }
+            if ($userIdent) {
+                $stmt->bindParam(':user_ident', $userIdent);
+            }
+            $stmt->execute();
+
+            $count = $stmt->rowCount();
+
+            return $count;
+        } catch (PDOException $pdoe) {
+            throw new Doctrine_Locking_Exception($pdoe->getMessage());
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Manager.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,646 @@
+<?php
+/*
+ *  $Id: Manager.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ *
+ * Doctrine_Manager is the base component of all doctrine based projects.
+ * It opens and keeps track of all connections (database connections).
+ *
+ * @package     Doctrine
+ * @subpackage  Manager
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Manager extends Doctrine_Configurable implements Countable, IteratorAggregate
+{
+    /**
+     * @var array $connections          an array containing all the opened connections
+     */
+    protected $_connections   = array();
+
+    /**
+     * @var array $bound                an array containing all components that have a bound connection
+     */
+    protected $_bound         = array();
+
+    /**
+     * @var integer $index              the incremented index
+     */
+    protected $_index         = 0;
+
+    /**
+     * @var integer $currIndex          the current connection index
+     */
+    protected $_currIndex     = 0;
+
+    /**
+     * @var Doctrine_Query_Registry     the query registry
+     */
+    protected $_queryRegistry;
+
+    /**
+     * constructor
+     *
+     * this is private constructor (use getInstance to get an instance of this class)
+     */
+    private function __construct()
+    {
+        Doctrine_Locator_Injectable::initNullObject(new Doctrine_Null);
+    }
+
+    /**
+     * setDefaultAttributes
+     * sets default attributes
+     *
+     * @todo I do not understand the flow here. Explain or refactor?
+     * @return boolean
+     */
+    public function setDefaultAttributes()
+    {
+        static $init = false;
+        if ( ! $init) {
+            $init = true;
+            $attributes = array(
+                        Doctrine::ATTR_CACHE                    => null,
+                        Doctrine::ATTR_RESULT_CACHE             => null,
+                        Doctrine::ATTR_QUERY_CACHE              => null,
+                        Doctrine::ATTR_LOAD_REFERENCES          => true,
+                        Doctrine::ATTR_LISTENER                 => new Doctrine_EventListener(),
+                        Doctrine::ATTR_RECORD_LISTENER          => new Doctrine_Record_Listener(),
+                        Doctrine::ATTR_THROW_EXCEPTIONS         => true,
+                        Doctrine::ATTR_VALIDATE                 => Doctrine::VALIDATE_NONE,
+                        Doctrine::ATTR_QUERY_LIMIT              => Doctrine::LIMIT_RECORDS,
+                        Doctrine::ATTR_IDXNAME_FORMAT           => "%s_idx",
+                        Doctrine::ATTR_SEQNAME_FORMAT           => "%s_seq",
+                        Doctrine::ATTR_TBLNAME_FORMAT           => "%s",
+                        Doctrine::ATTR_QUOTE_IDENTIFIER         => false,
+                        Doctrine::ATTR_SEQCOL_NAME              => 'id',
+                        Doctrine::ATTR_PORTABILITY              => Doctrine::PORTABILITY_NONE,
+                        Doctrine::ATTR_EXPORT                   => Doctrine::EXPORT_ALL,
+                        Doctrine::ATTR_DECIMAL_PLACES           => 2,
+                        Doctrine::ATTR_DEFAULT_PARAM_NAMESPACE  => 'doctrine',
+                        Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES   => false,
+                        Doctrine::ATTR_USE_DQL_CALLBACKS        => false,
+                        Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE   => false,
+                        Doctrine::ATTR_HYDRATE_OVERWRITE        => true
+                        ); 
+            foreach ($attributes as $attribute => $value) {
+                $old = $this->getAttribute($attribute);
+                if ($old === null) {
+                    $this->setAttribute($attribute,$value);
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns an instance of this class
+     * (this class uses the singleton pattern)
+     *
+     * @return Doctrine_Manager
+     */
+    public static function getInstance()
+    {
+        static $instance;
+        if ( ! isset($instance)) {
+            $instance = new self();
+        }
+        return $instance;
+    }
+
+    /**
+     * Lazy-initializes the query registry object and returns it
+     *
+     * @return Doctrine_Query_Registry
+     */
+    public function getQueryRegistry()
+    {
+      	if ( ! isset($this->_queryRegistry)) {
+      	   $this->_queryRegistry = new Doctrine_Query_Registry();
+      	}
+        return $this->_queryRegistry;
+    }
+
+    /**
+     * Sets the query registry
+     *
+     * @return Doctrine_Manager     this object
+     */
+    public function setQueryRegistry(Doctrine_Query_Registry $registry)
+    {
+        $this->_queryRegistry = $registry;
+        
+        return $this;
+    }
+
+    /**
+     * Open a new connection. If the adapter parameter is set this method acts as
+     * a short cut for Doctrine_Manager::getInstance()->openConnection($adapter, $name);
+     *
+     * if the adapter paramater is not set this method acts as
+     * a short cut for Doctrine_Manager::getInstance()->getCurrentConnection()
+     *
+     * @param PDO|Doctrine_Adapter_Interface $adapter   database driver
+     * @param string $name                              name of the connection, if empty numeric key is used
+     * @throws Doctrine_Manager_Exception               if trying to bind a connection with an existing name
+     * @return Doctrine_Connection
+     */
+    public static function connection($adapter = null, $name = null)
+    {
+        if ($adapter == null) {
+            return Doctrine_Manager::getInstance()->getCurrentConnection();
+        } else {
+            return Doctrine_Manager::getInstance()->openConnection($adapter, $name);
+        }
+    }
+
+    /**
+     * Opens a new connection and saves it to Doctrine_Manager->connections
+     *
+     * @param PDO|Doctrine_Adapter_Interface $adapter   database driver
+     * @param string $name                              name of the connection, if empty numeric key is used
+     * @throws Doctrine_Manager_Exception               if trying to bind a connection with an existing name
+     * @throws Doctrine_Manager_Exception               if trying to open connection for unknown driver
+     * @return Doctrine_Connection
+     */
+    public function openConnection($adapter, $name = null, $setCurrent = true)
+    {
+        if (is_object($adapter)) {
+            if ( ! ($adapter instanceof PDO) && ! in_array('Doctrine_Adapter_Interface', class_implements($adapter))) {
+                throw new Doctrine_Manager_Exception("First argument should be an instance of PDO or implement Doctrine_Adapter_Interface");
+            }
+
+            $driverName = $adapter->getAttribute(Doctrine::ATTR_DRIVER_NAME);
+        } else if (is_array($adapter)) {
+            if ( ! isset($adapter[0])) {
+                throw new Doctrine_Manager_Exception('Empty data source name given.');
+            }
+            $e = explode(':', $adapter[0]);
+
+            if ($e[0] == 'uri') {
+                $e[0] = 'odbc';
+            }
+
+            $parts['dsn']    = $adapter[0];
+            $parts['scheme'] = $e[0];
+            $parts['user']   = (isset($adapter[1])) ? $adapter[1] : null;
+            $parts['pass']   = (isset($adapter[2])) ? $adapter[2] : null;
+            $driverName = $e[0];
+            $adapter = $parts;
+        } else {
+            $parts = $this->parseDsn($adapter);
+            $driverName = $parts['scheme'];
+            $adapter = $parts;
+        }
+
+        // Decode adapter information
+        if (is_array($adapter)) {
+            foreach ($adapter as $key => $value) {
+                $adapter[$key]  = $value?urldecode($value):null;
+            }
+        }
+
+        // initialize the default attributes
+        $this->setDefaultAttributes();
+
+        if ($name !== null) {
+            $name = (string) $name;
+            if (isset($this->_connections[$name])) {
+                if ($setCurrent) {
+                    $this->_currIndex = $name;
+                }
+                return $this->_connections[$name];
+            }
+        } else {
+            $name = $this->_index;
+            $this->_index++;
+        }
+
+        $drivers = array('mysql'    => 'Doctrine_Connection_Mysql',
+                         'sqlite'   => 'Doctrine_Connection_Sqlite',
+                         'pgsql'    => 'Doctrine_Connection_Pgsql',
+                         'oci'      => 'Doctrine_Connection_Oracle',
+                         'oci8'     => 'Doctrine_Connection_Oracle',
+                         'oracle'   => 'Doctrine_Connection_Oracle',
+                         'mssql'    => 'Doctrine_Connection_Mssql',
+                         'dblib'    => 'Doctrine_Connection_Mssql',
+                         'odbc'     => 'Doctrine_Connection_Mssql', 
+                         'firebird' => 'Doctrine_Connection_Firebird',
+                         'informix' => 'Doctrine_Connection_Informix',
+                         'mock'     => 'Doctrine_Connection_Mock');
+
+        if ( ! isset($drivers[$driverName])) {
+            throw new Doctrine_Manager_Exception('Unknown driver ' . $driverName);
+        }
+
+        $className = $drivers[$driverName];
+        $conn = new $className($this, $adapter);
+        $conn->setName($name);
+
+        $this->_connections[$name] = $conn;
+
+        if ($setCurrent) {
+            $this->_currIndex = $name;
+        }
+        return $this->_connections[$name];
+    }
+    
+    /**
+     * Parse a pdo style dsn in to an array of parts
+     *
+     * @param array $dsn An array of dsn information
+     * @return array The array parsed
+     * @todo package:dbal
+     */
+    public function parsePdoDsn($dsn)
+    {
+        $parts = array();
+
+        $names = array('dsn', 'scheme', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment', 'unix_socket');
+
+        foreach ($names as $name) {
+            if ( ! isset($parts[$name])) {
+                $parts[$name] = null;
+            }
+        }
+
+        $e = explode(':', $dsn);
+        $parts['scheme'] = $e[0];
+        $parts['dsn'] = $dsn;
+
+        $e = explode(';', $e[1]);
+        foreach ($e as $string) {
+            if ($string) {
+                $e2 = explode('=', $string);
+
+                if (isset($e2[0]) && isset($e2[1])) {
+                    list($key, $value) = $e2;
+                    $parts[$key] = $value;
+                }
+            }
+        }
+
+        return $parts;
+    }
+
+    /**
+     * Build the blank dsn parts array used with parseDsn()
+     *
+     * @see parseDsn()
+     * @param string $dsn 
+     * @return array $parts
+     */
+    protected function _buildDsnPartsArray($dsn)
+    {
+        // fix sqlite dsn so that it will parse correctly
+        $dsn = str_replace("////", "/", $dsn);
+        $dsn = str_replace("\\", "/", $dsn);
+        $dsn = preg_replace("/\/\/\/(.*):\//", "//$1:/", $dsn);
+
+        // silence any warnings
+        $parts = @parse_url($dsn);
+
+        $names = array('dsn', 'scheme', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment', 'unix_socket');
+
+        foreach ($names as $name) {
+            if ( ! isset($parts[$name])) {
+                $parts[$name] = null;
+            }
+        }
+
+        if (count($parts) == 0 || ! isset($parts['scheme'])) {
+            throw new Doctrine_Manager_Exception('Could not parse dsn');
+        }
+
+        return $parts;
+    }
+
+    /**
+     * Parse a Doctrine style dsn string in to an array of parts
+     *
+     * @param string $dsn
+     * @return array Parsed contents of DSN
+     * @todo package:dbal
+     */
+    public function parseDsn($dsn)
+    {
+        $parts = $this->_buildDsnPartsArray($dsn);
+
+        switch ($parts['scheme']) {
+            case 'sqlite':
+            case 'sqlite2':
+            case 'sqlite3':
+                if (isset($parts['host']) && $parts['host'] == ':memory') {
+                    $parts['database'] = ':memory:';
+                    $parts['dsn']      = 'sqlite::memory:';
+                } else {
+                    //fix windows dsn we have to add host: to path and set host to null
+                    if (isset($parts['host'])) {
+                        $parts['path'] = $parts['host'] . ":" . $parts["path"];
+                        $parts['host'] = null;
+                    }
+                    $parts['database'] = $parts['path'];
+                    $parts['dsn'] = $parts['scheme'] . ':' . $parts['path'];
+                }
+
+                break;
+
+            case 'mssql':
+            case 'dblib':
+                if ( ! isset($parts['path']) || $parts['path'] == '/') {
+                    throw new Doctrine_Manager_Exception('No database available in data source name');
+                }
+                if (isset($parts['path'])) {
+                    $parts['database'] = substr($parts['path'], 1);
+                }
+                if ( ! isset($parts['host'])) {
+                    throw new Doctrine_Manager_Exception('No hostname set in data source name');
+                }
+
+                $parts['dsn'] = $parts['scheme'] . ':host='
+                              . $parts['host'] . (isset($parts['port']) ? ':' . $parts['port']:null) . ';dbname='
+                              . $parts['database'];
+
+                break;
+
+            case 'mysql':
+            case 'informix':
+            case 'oci8':
+            case 'oci':
+            case 'firebird':
+            case 'pgsql':
+            case 'odbc':
+            case 'mock':
+            case 'oracle':
+                if ( ! isset($parts['path']) || $parts['path'] == '/') {
+                    throw new Doctrine_Manager_Exception('No database available in data source name');
+                }
+                if (isset($parts['path'])) {
+                    $parts['database'] = substr($parts['path'], 1);
+                }
+                if ( ! isset($parts['host'])) {
+                    throw new Doctrine_Manager_Exception('No hostname set in data source name');
+                }
+
+                $parts['dsn'] = $parts['scheme'] . ':host='
+                              . $parts['host'] . (isset($parts['port']) ? ';port=' . $parts['port']:null) . ';dbname='
+                              . $parts['database'];
+
+                break;
+            default:
+                throw new Doctrine_Manager_Exception('Unknown driver '.$parts['scheme']);
+        }
+
+        return $parts;
+    }
+
+    /**
+     * Get the connection instance for the passed name
+     *
+     * @param string $name                  name of the connection, if empty numeric key is used
+     * @return object Doctrine_Connection
+     * @throws Doctrine_Manager_Exception   if trying to get a non-existent connection
+     */
+    public function getConnection($name)
+    {
+        if ( ! isset($this->_connections[$name])) {
+            throw new Doctrine_Manager_Exception('Unknown connection: ' . $name);
+        }
+
+        return $this->_connections[$name];
+    }
+
+    /**
+     * Get the name of the passed connection instance
+     *
+     * @param Doctrine_Connection $conn     connection object to be searched for
+     * @return string                       the name of the connection
+     */
+    public function getConnectionName(Doctrine_Connection $conn)
+    {
+        return array_search($conn, $this->_connections, true);
+    }
+
+    /**
+     * Binds given component to given connection
+     * this means that when ever the given component uses a connection
+     * it will be using the bound connection instead of the current connection
+     *
+     * @param string $componentName
+     * @param string $connectionName
+     * @return boolean
+     */
+    public function bindComponent($componentName, $connectionName)
+    {
+        $this->_bound[$componentName] = $connectionName;
+    }
+
+    /**
+     * Get the connection instance for the specified component
+     *
+     * @param string $componentName
+     * @return Doctrine_Connection
+     */
+    public function getConnectionForComponent($componentName)
+    {
+        Doctrine::autoload($componentName);
+
+        if (isset($this->_bound[$componentName])) {
+            return $this->getConnection($this->_bound[$componentName]);
+        }
+
+        return $this->getCurrentConnection();
+    }
+    
+    /**
+     * Check if a component is bound to a connection
+     *
+     * @param string $componentName
+     * @return boolean
+     */
+    public function hasConnectionForComponent($componentName = null)
+    {
+        return isset($this->_bound[$componentName]);
+    }
+
+    /**
+     * Closes the specified connection
+     *
+     * @param Doctrine_Connection $connection
+     * @return void
+     */
+    public function closeConnection(Doctrine_Connection $connection)
+    {
+        $connection->close();
+
+        $key = array_search($connection, $this->_connections, true);
+
+        if ($key !== false) {
+            unset($this->_connections[$key]);
+        }
+        $this->_currIndex = key($this->_connections);
+
+        unset($connection);
+    }
+
+    /**
+     * Returns all opened connections
+     *
+     * @return array
+     */
+    public function getConnections()
+    {
+        return $this->_connections;
+    }
+
+    /**
+     * Sets the current connection to $key
+     *
+     * @param mixed $key                        the connection key
+     * @throws InvalidKeyException
+     * @return void
+     */
+    public function setCurrentConnection($key)
+    {
+        $key = (string) $key;
+        if ( ! isset($this->_connections[$key])) {
+            throw new Doctrine_Connection_Exception("Connection key '$key' does not exist.");
+        }
+        $this->_currIndex = $key;
+    }
+
+    /**
+     * Whether or not the manager contains specified connection
+     *
+     * @param mixed $key                        the connection key
+     * @return boolean
+     */
+    public function contains($key)
+    {
+        return isset($this->_connections[$key]);
+    }
+
+    /**
+     * Returns the number of opened connections
+     *
+     * @return integer
+     */
+    public function count()
+    {
+        return count($this->_connections);
+    }
+
+    /**
+     * Returns an ArrayIterator that iterates through all connections
+     *
+     * @return ArrayIterator
+     */
+    public function getIterator()
+    {
+        return new ArrayIterator($this->_connections);
+    }
+
+    /**
+     * Get the current connection instance
+     *
+     * @throws Doctrine_Connection_Exception       if there are no open connections
+     * @return Doctrine_Connection
+     */
+    public function getCurrentConnection()
+    {
+        $i = $this->_currIndex;
+        if ( ! isset($this->_connections[$i])) {
+            throw new Doctrine_Connection_Exception('There is no open connection');
+        }
+        return $this->_connections[$i];
+    }
+
+    /**
+     * Creates databases for all existing connections
+     *
+     * @param string $specifiedConnections Array of connections you wish to create the database for
+     * @return void
+     * @todo package:dbal
+     */
+    public function createDatabases($specifiedConnections = array())
+    {
+        if ( ! is_array($specifiedConnections)) {
+            $specifiedConnections = (array) $specifiedConnections;
+        }
+
+        $results = array();
+
+        foreach ($this as $name => $connection) {
+            if ( ! empty($specifiedConnections) && ! in_array($name, $specifiedConnections)) {
+                continue;
+            }
+
+            $results[$name] = $connection->createDatabase();
+        }
+
+        return $results;
+    }
+
+    /**
+     * Drops databases for all existing connections
+     *
+     * @param string $specifiedConnections Array of connections you wish to drop the database for
+     * @return void
+     * @todo package:dbal
+     */
+    public function dropDatabases($specifiedConnections = array())
+    {
+        if ( ! is_array($specifiedConnections)) {
+            $specifiedConnections = (array) $specifiedConnections;
+        }
+
+        $results = array();
+
+        foreach ($this as $name => $connection) {
+            if ( ! empty($specifiedConnections) && ! in_array($name, $specifiedConnections)) {
+                continue;
+            }
+
+            $results[$name] = $connection->dropDatabase();
+        }
+
+        return $results;
+    }
+
+    /**
+     * Returns a string representation of this object
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        $r[] = "<pre>";
+        $r[] = "Doctrine_Manager";
+        $r[] = "Connections : ".count($this->_connections);
+        $r[] = "</pre>";
+        return implode("\n",$r);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Manager/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Manager_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Manager
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Manager_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Migration.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,638 @@
+<?php
+/*
+ *  $Id: Migration.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Migration
+ *
+ * this class represents a database view
+ *
+ * @package     Doctrine
+ * @subpackage  Migration
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Migration
+{
+    protected $_changes = array('created_tables'      =>  array(),
+                                'renamed_tables'      =>  array(),
+                                'created_constraints' =>  array(),
+                                'dropped_fks'         =>  array(),
+                                'created_fks'         =>  array(),
+                                'dropped_constraints' =>  array(),
+                                'removed_indexes'     =>  array(),
+                                'dropped_tables'      =>  array(),
+                                'added_columns'       =>  array(),
+                                'renamed_columns'     =>  array(),
+                                'changed_columns'     =>  array(),
+                                'removed_columns'     =>  array(),
+                                'added_indexes'       =>  array()),
+              $_migrationTableName = 'migration_version',
+              $_migrationClassesDirectory = array(),
+              $_migrationClasses = array(),
+              $_loadedMigrations = array();
+
+    /**
+     * construct
+     *
+     * Specify the path to the directory with the migration classes.
+     * The classes will be loaded and the migration table will be created if it does not already exist
+     *
+     * @param string $directory 
+     * @return void
+     */
+    public function __construct($directory = null)
+    {
+        if ($directory != null) {
+            $this->_migrationClassesDirectory = $directory;
+            
+            $this->loadMigrationClasses();
+            
+            $this->createMigrationTable();
+        }
+    }
+
+    /**
+     * getTableName
+     *
+     * @return void
+     */
+    public function getTableName()
+    {
+        return $this->_migrationTableName;
+    }
+
+    /**
+     * setTableName
+     *
+     * @param string $tableName 
+     * @return void
+     */
+    public function setTableName($tableName)
+    {
+        $this->_migrationTableName = Doctrine_Manager::connection()
+                ->formatter->getTableName($tableName);
+    }
+
+    /**
+     * createMigrationTable
+     * 
+     * Creates the migration table used to store the current version
+     *
+     * @return void
+     */
+    protected function createMigrationTable()
+    {
+        $conn = Doctrine_Manager::connection();
+        
+        try {
+            $conn->export->createTable($this->_migrationTableName, array('version' => array('type' => 'integer', 'size' => 11)));
+            
+            return true;
+        } catch(Exception $e) {
+            return false;
+        }
+    }
+
+
+    /**
+     * loadMigrationClassesFromDirectory 
+     * 
+     * refactored out from loadMigrationClasses
+     * $param array An array of classes
+     * @return void
+     */
+    public function loadMigrationClassesFromDirectory()
+    {
+        $classes = get_declared_classes();
+        
+        foreach ((array) $this->_migrationClassesDirectory as $dir) {
+            $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 ( ! in_array($file->getFileName(), $this->_loadedMigrations)) {
+                        require_once($file->getPathName());
+
+                        $requiredClass = array_diff(get_declared_classes(), $classes);
+                        $requiredClass = end($requiredClass);
+
+                        if ($requiredClass) {
+                            $this->_loadedMigrations[$requiredClass] = $file->getFileName();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * loadMigrationClasses
+     *
+     * Loads the migration classes for the directory specified by the constructor
+     *
+     * @return void
+     */
+    protected function loadMigrationClasses()
+    {
+        if ($this->_migrationClassesDirectory !== null) {
+            $this->loadMigrationClassesFromDirectory();
+        }
+        
+        $parent = new ReflectionClass('Doctrine_Migration');
+        
+        foreach ($this->_loadedMigrations as $name => $fileName) {
+            $class = new ReflectionClass($name);
+            
+            while ($class->isSubclassOf($parent)) {
+
+                $class = $class->getParentClass();
+                if ($class === false) {
+                    break;
+                }
+            }
+            
+            if ($class === false) {
+                continue;
+            }
+            
+            $e = explode('_', $fileName);
+            $classMigrationNum = (int) $e[0];
+
+            if (isset($this->_migrationClasses[$classMigrationNum]) && $fileName != $this->_migrationClasses[$classMigrationNum]['fileName']) {
+                throw new Doctrine_Migration_Exception(
+                    'You have two migration classes with the same migration number, "' . $classMigrationNum . '". '.
+                    'The two files are "'. $fileName . '" and "' . $this->_migrationClasses[$classMigrationNum]['fileName'] . '"'
+                );
+            }
+
+            $this->_migrationClasses[$classMigrationNum] = array('className' => $name, 'fileName' => $fileName);
+        }
+        
+        return $this->_migrationClasses;
+    }
+
+    /**
+     * getMigrationClasses
+     *
+     * @return void
+     */
+    public function getMigrationClasses()
+    {
+        return $this->_migrationClasses;
+    }
+
+    /**
+     * setCurrentVersion
+     *
+     * Sets the current version in the migration table
+     *
+     * @param string $number 
+     * @return void
+     */
+    protected function setCurrentVersion($number)
+    {
+        $conn = Doctrine_Manager::connection();
+        
+        if ($this->hasMigrated()) {
+            $conn->exec("UPDATE " . $this->_migrationTableName . " SET version = $number");
+        } else {
+            $conn->exec("INSERT INTO " . $this->_migrationTableName . " (version) VALUES ($number)");
+        }
+    }
+
+    /**
+     * getCurrentVersion
+     *
+     * Get the current version of the database
+     *
+     * @return void
+     */
+    public function getCurrentVersion()
+    {
+        $conn = Doctrine_Manager::connection();
+        
+        $result = $conn->fetchColumn("SELECT version FROM " . $this->_migrationTableName);
+        
+        return isset($result[0]) ? $result[0]:0;
+    }
+
+    /**
+     * hasMigrated
+     *
+     * Returns true/false for whether or not this database has been migrated in the past
+     *
+     * @return void
+     */
+    public function hasMigrated()
+    {
+        $conn = Doctrine_Manager::connection();
+        
+        $result = $conn->fetchColumn("SELECT version FROM " . $this->_migrationTableName);
+        
+        return isset($result[0]) ? true:false; 
+    }
+
+    /**
+     * getLatestVersion
+     *
+     * Gets the latest possible version from the loaded migration classes
+     *
+     * @return void
+     */
+    public function getLatestVersion()
+    {
+        $this->loadMigrationClasses();
+        
+        $versions = array();
+        foreach (array_keys($this->_migrationClasses) as $classMigrationNum) {
+            $versions[$classMigrationNum] = $classMigrationNum;
+        }
+        
+        rsort($versions);
+        
+        return isset($versions[0]) ? $versions[0]:0;
+    }
+
+    /**
+     * getNextVersion
+     *
+     * @return integer $nextVersion
+     */
+    public function getNextVersion()
+    {
+        return $this->getLatestVersion() + 1;
+    }
+
+    /**
+     * getMigrationClass
+     *
+     * Get instance of migration class for $num
+     *
+     * @param string $num 
+     * @return void
+     */
+    protected function getMigrationClass($num)
+    {
+        foreach ($this->_migrationClasses as $classMigrationNum => $info) {
+            $className = $info['className'];
+            
+            if ($classMigrationNum == $num) {
+                return new $className();
+            }
+        }
+        
+        throw new Doctrine_Migration_Exception('Could not find migration class for migration step: '.$num);
+    }
+
+    /**
+     * doMigrateStep
+     *
+     * Perform migration directory for the specified version. Loads migration classes and performs the migration then processes the changes
+     *
+     * @param string $direction 
+     * @param string $num 
+     * @return void
+     */
+    protected function doMigrateStep($direction, $num)
+    {
+        $migrate = $this->getMigrationClass($num);
+        
+        $migrate->doMigrate($direction);
+
+        $this->setCurrentVersion($num);
+    }
+
+    /**
+     * doMigrate
+     * 
+     * Perform migration for a migration class. Executes the up or down method then processes the changes
+     *
+     * @param string $direction 
+     * @return void
+     */
+    protected function doMigrate($direction)
+    {
+        $method = 'pre'.$direction;
+        $this->$method();
+
+        if (method_exists($this, $direction)) {
+            $this->$direction();
+
+            foreach ($this->_changes as $type => $changes) {
+                $process = new Doctrine_Migration_Process();
+                $funcName = 'process' . Doctrine_Inflector::classify($type);
+
+                if ( ! empty($changes)) {
+                    $process->$funcName($changes); 
+                }
+            }
+        }
+
+        $method = 'post'.$direction;
+        $this->$method();
+    }
+
+    /**
+     * migrate
+     *
+     * Perform a migration chain by specifying the $from and $to.
+     * If you do not specify a $from or $to then it will attempt to migrate from the current version to the latest version
+     *
+     * @param string $from 
+     * @param string $to 
+     * @return void
+     */
+    public function migrate($to = null)
+    {
+        $from = $this->getCurrentVersion();
+        
+        // If nothing specified then lets assume we are migrating from the current version to the latest version
+        if ($to === null) {
+            $to = $this->getLatestVersion();
+        }
+        
+        if ($from == $to) {
+            throw new Doctrine_Migration_Exception('Already at version # ' . $to);
+        }
+        
+        $direction = $from > $to ? 'down':'up';
+        
+        if ($direction === 'up') {
+            for ($i = $from + 1; $i <= $to; $i++) {
+                $this->doMigrateStep($direction, $i);
+            }
+        } else {
+            for ($i = $from; $i > $to; $i--) {
+                $this->doMigrateStep($direction, $i);
+            }
+        }
+        
+        $this->setCurrentVersion($to);
+        
+        return $to;
+    }
+
+    /**
+     * addChange
+     *
+     * @param string $type 
+     * @param string $array 
+     * @return void
+     */
+    protected function addChange($type, array $change = array())
+    {
+        $this->_changes[$type][] = $change;
+    }
+
+    /**
+     * createTable
+     *
+     * @param string $tableName 
+     * @param string $array 
+     * @param string $array 
+     * @return void
+     */
+    public function createTable($tableName, array $fields = array(), array $options = array())
+    {
+        $options = get_defined_vars();
+        
+        $this->addChange('created_tables', $options);
+    }
+
+    /**
+     * dropTable
+     *
+     * @param string $tableName 
+     * @return void
+     */
+    public function dropTable($tableName)
+    {
+        $options = get_defined_vars();
+        
+        $this->addChange('dropped_tables', $options);
+    }
+
+    /**
+     * renameTable
+     *
+     * @param string $oldTableName 
+     * @param string $newTableName 
+     * @return void
+     */
+    public function renameTable($oldTableName, $newTableName)
+    {
+        $options = get_defined_vars();
+        
+        $this->addChange('renamed_tables', $options);
+    }
+
+    /**
+     * createConstraint
+     *
+     * @param string $tableName
+     * @param string $constraintName
+     * @return void
+     */
+    public function createConstraint($tableName, $constraintName, array $definition)
+    {
+        $options = get_defined_vars();
+        
+        $this->addChange('created_constraints', $options);
+    }
+
+    /**
+     * dropConstraint
+     *
+     * @param string $tableName
+     * @param string $constraintName
+     * @return void
+     */
+    public function dropConstraint($tableName, $constraintName, $primary = false)
+    {
+        $options = get_defined_vars();
+        
+        $this->addChange('dropped_constraints', $options);
+    }
+
+    /**
+     * createForeignKey
+     *
+     * @param string $tableName
+     * @param string $constraintName
+     * @return void
+     */
+    public function createForeignKey($tableName, array $definition)
+    {
+        $options = get_defined_vars();
+        
+        $this->addChange('created_fks', $options);
+    }
+
+    /**
+     * dropForeignKey
+     *
+     * @param string $tableName
+     * @param string $constraintName
+     * @return void
+     */
+    public function dropForeignKey($tableName, $fkName)
+    {
+        $options = get_defined_vars();
+        
+        $this->addChange('dropped_fks', $options);
+    }
+
+    /**
+     * addColumn
+     *
+     * @param string $tableName 
+     * @param string $columnName 
+     * @param string $type 
+     * @param string $array 
+     * @return void
+     */
+    public function addColumn($tableName, $columnName, $type, array $options = array())
+    {
+        $options = get_defined_vars();
+        
+        $this->addChange('added_columns', $options);
+    }
+
+    /**
+     * renameColumn
+     *
+     * @param string $tableName 
+     * @param string $oldColumnName 
+     * @param string $newColumnName 
+     * @return void
+     */
+    public function renameColumn($tableName, $oldColumnName, $newColumnName)
+    {
+        $options = get_defined_vars();
+        
+        $this->addChange('renamed_columns', $options);
+    }
+
+    /**
+     * renameColumn
+     *
+     * @param string $tableName 
+     * @param string $columnName 
+     * @param string $type 
+     * @param string $array 
+     * @return void
+     */
+    public function changeColumn($tableName, $columnName, $type, array $options = array())
+    {
+        $options = get_defined_vars();
+        
+        $this->addChange('changed_columns', $options);
+    }
+
+    /**
+     * removeColumn
+     *
+     * @param string $tableName 
+     * @param string $columnName 
+     * @return void
+     */
+    public function removeColumn($tableName, $columnName)
+    {
+        $options = get_defined_vars();
+        
+        $this->addChange('removed_columns', $options);
+    }
+
+    /**
+     * addIndex
+     *
+     * @param string $tableName 
+     * @param string $indexName 
+     * @param string $array 
+     * @return void
+     */
+    public function addIndex($tableName, $indexName, array $definition)
+    {
+        $options = get_defined_vars();
+        
+        $this->addChange('added_indexes', $options);
+    }
+
+    /**
+     * removeIndex
+     *
+     * @param string $tableName 
+     * @param string $indexName 
+     * @return void
+     */
+    public function removeIndex($tableName, $indexName)
+    {
+        $options = get_defined_vars();
+        
+        $this->addChange('removed_indexes', $options);
+    }
+
+    /**
+     * preUp
+     *
+     * @return void
+     */
+    public function preUp()
+    {
+        return;
+    }
+
+    /**
+     * postUp
+     *
+     * @return void
+     */
+    public function postUp()
+    {
+        return;
+    }
+
+    /**
+     * preDown
+     *
+     * @return void
+     */
+    public function preDown()
+    {
+        return;
+    }
+
+    /**
+     * postDown
+     *
+     * @return void
+     */
+    public function postDown()
+    {
+        return;
+    }
+    
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Migration/Builder.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,323 @@
+<?php
+/*
+ *  $Id: Builder.php 2939 2007-10-19 14:23:42Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Migration_Builder
+ *
+ * @package     Doctrine
+ * @subpackage  Migration
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2939 $
+ */
+class Doctrine_Migration_Builder extends Doctrine_Builder
+{
+    /**
+     * migrationsPath
+     * 
+     * The path to your migration classes directory
+     *
+     * @var string
+     */
+    private $migrationsPath = '';
+
+    /**
+     * suffix
+     * 
+     * File suffix to use when writing class definitions
+     *
+     * @var string $suffix
+     */
+    private $suffix = '.class.php';
+
+    /**
+     * migration
+     *
+     * @var string
+     */
+    private $migration;
+
+    /**
+     * tpl
+     *
+     * Class template used for writing classes
+     *
+     * @var $tpl
+     */
+    private static $tpl;
+
+    /**
+     * __construct
+     *
+     * @return void
+     */
+    public function __construct($migrationsPath = null)
+    {
+        if ($migrationsPath) {
+            $this->setMigrationsPath($migrationsPath);
+            $this->migration = new Doctrine_Migration($migrationsPath);
+        }
+        
+        $this->loadTemplate();
+    }
+
+    /**
+     * setMigrationsPath
+     *
+     * @param string path   the path where migration classes are stored and being generated
+     * @return
+     */
+    public function setMigrationsPath($path)
+    {
+        Doctrine_Lib::makeDirectories($path);
+
+        $this->migrationsPath = $path;
+    }
+
+    /**
+     * getMigrationsPath
+     *
+     * @return string       the path where migration classes are stored and being generated
+     */
+    public function getMigrationsPath()
+    {
+        return $this->migrationsPath;
+    }
+
+    /**
+     * loadTemplate
+     * 
+     * Loads the class template used for generating classes
+     *
+     * @return void
+     */
+    protected function loadTemplate() 
+    {
+        if (isset(self::$tpl)) {
+            return;
+        }
+
+        self::$tpl =<<<END
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class %s extends %s
+{
+	public function up()
+	{
+%s
+	}
+
+	public function down()
+	{
+%s
+	}
+}
+END;
+    }
+
+    /**
+     * generateMigrationsFromDb
+     *
+     * @return void
+     */
+    public function generateMigrationsFromDb()
+    {
+        $directory = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'tmp_doctrine_models';
+
+        Doctrine::generateModelsFromDb($directory);
+
+        $result = $this->generateMigrationsFromModels($directory, Doctrine::MODEL_LOADING_CONSERVATIVE);
+
+        Doctrine_Lib::removeDirectories($directory);
+
+        return $result;
+    }
+
+    /**
+     * generateMigrationsFromModels
+     *
+     * @param string $modelsPath 
+     * @return void
+     */
+    public function generateMigrationsFromModels($modelsPath = null, $modelLoading = null)
+    {
+        if ($modelsPath !== null) {
+            $models = Doctrine::filterInvalidModels(Doctrine::loadModels($modelsPath, $modelLoading));
+        } else {
+            $models = Doctrine::getLoadedModels();
+        }
+
+        $models = Doctrine::initializeModels($models);
+
+        $foreignKeys = array();
+        
+        foreach ($models as $model) {
+            $table = Doctrine::getTable($model);
+            if ($table->getTableName() !== $this->migration->getTableName()) {
+                $export = $table->getExportableFormat();
+
+                $foreignKeys[$export['tableName']] = $export['options']['foreignKeys'];
+
+                $up = $this->buildCreateTable($export);
+                $down = $this->buildDropTable($export);
+
+                $className = 'Add' . Doctrine_Inflector::classify($export['tableName']);
+
+                $this->generateMigrationClass($className, array(), $up, $down);
+            }
+        }
+        
+        if ( ! empty($foreignKeys)) {
+            $className = 'ApplyForeignKeyConstraints';
+        
+            $up = '';
+            $down = '';
+            foreach ($foreignKeys as $tableName => $definitions)    {
+                $tableForeignKeyNames[$tableName] = array();
+            
+                foreach ($definitions as $definition) {
+                    $definition['name'] = $tableName . '_' .implode('_', (array)$definition['local']);
+
+                    $up .= $this->buildCreateForeignKey($tableName, $definition);
+                    $down .= $this->buildDropForeignKey($tableName, $definition);
+                }
+            }
+        
+            $this->generateMigrationClass($className, array(), $up, $down);
+        }
+        
+        return true;
+    }
+
+    /**
+     * buildCreateForeignKey
+     *
+     * @param string $tableName 
+     * @param string $definition 
+     * @return void
+     */
+    public function buildCreateForeignKey($tableName, $definition)
+    {
+        return "\t\t\$this->createForeignKey('" . $tableName . "', " . $this->varExport($definition, true) . ");";
+    }
+
+    /**
+     * buildDropForeignKey
+     *
+     * @param string $tableName 
+     * @param string $definition 
+     * @return void
+     */
+    public function buildDropForeignKey($tableName, $definition)
+    {
+        return "\t\t\$this->dropForeignKey('" . $tableName . "', '" . $definition['name'] . "');\n";
+    }
+
+    /**
+     * buildCreateTable
+     *
+     * @param string $tableData 
+     * @return void
+     */
+    public function buildCreateTable($tableData)
+    {
+        $code  = "\t\t\$this->createTable('" . $tableData['tableName'] . "', ";
+        
+        $code .= $this->varExport($tableData['columns'], true) . ", ";
+        
+        $code .= $this->varExport(array('indexes' => $tableData['options']['indexes'], 'primary' => $tableData['options']['primary']), true);
+        
+        $code .= ");";
+        
+        return $code;
+    }
+
+    /**
+     * buildDropTable
+     *
+     * @param string $tableData 
+     * @return string
+     */
+    public function buildDropTable($tableData)
+    {
+        return "\t\t\$this->dropTable('" . $tableData['tableName'] . "');";
+    }
+
+    /**
+     * generateMigrationClass
+     *
+     * @return void
+     */
+    public function generateMigrationClass($className, $options = array(), $up = null, $down = null, $return = false)
+    {
+        $className = Doctrine_Inflector::urlize($className);
+        $className = str_replace('-', '_', $className);
+        $className = Doctrine_Inflector::classify($className);
+
+        if ($return || ! $this->getMigrationsPath()) {
+            return $this->buildMigrationClass($className, null, $options, $up, $down);
+        } else {
+            if ( ! $this->getMigrationsPath()) {
+                throw new Doctrine_Migration_Exception('You must specify the path to your migrations.');
+            }
+            
+            $next = (string) $this->migration->getNextVersion();
+            
+            $fileName = str_repeat('0', (3 - strlen($next))) . $next . '_' . Doctrine_Inflector::tableize($className) . $this->suffix;
+            
+            $class = $this->buildMigrationClass($className, $fileName, $options, $up, $down);
+            
+            $path = $this->getMigrationsPath() . DIRECTORY_SEPARATOR . $fileName;
+            
+            if ( class_exists($className) || file_exists($path)) {
+                return false;
+            }
+            
+            file_put_contents($path, $class);
+
+            return true;
+        }
+    }
+
+    /**
+     * buildMigrationClass
+     *
+     * @return string
+     */
+    public function buildMigrationClass($className, $fileName = null, $options = array(), $up = null, $down = null)
+    {
+        $extends = isset($options['extends']) ? $options['extends']:'Doctrine_Migration';
+        
+        $content  = '<?php' . PHP_EOL;
+        
+        $content .= sprintf(self::$tpl, $className,
+                                       $extends,
+                                       $up,
+                                       $down);
+        
+        
+        return $content;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Migration/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Migration_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Migration
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Migration_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Migration/IrreversibleMigrationException.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: IrreversibleMigration.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Migration_IrreversibleMigration
+ *
+ * @package     Doctrine
+ * @subpackage  Migration
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Migration_IrreversibleMigrationException extends Doctrine_Migration_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Migration/Process.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,251 @@
+<?php
+/*
+ *  $Id: Process.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Migration_Process
+ *
+ * @package     Doctrine
+ * @subpackage  Migration
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Migration_Process
+{
+    /**
+     * getConnection
+     *
+     * @param string $tableName 
+     * @return void
+     */
+    public function getConnection($tableName)
+    {
+        return Doctrine::getConnectionByTableName($tableName);
+    }
+
+    /**
+     * processCreatedTables
+     *
+     * @param string $tables 
+     * @return void
+     */
+    public function processCreatedTables($tables)
+    {
+        foreach ($tables as $table) {
+            $conn = $this->getConnection($table['tableName']);
+            
+            $conn->export->createTable($table['tableName'], $table['fields'], $table['options']);
+        }
+    }
+
+    /**
+     * processDroppedTables
+     *
+     * @param string $tables 
+     * @return void
+     */
+    public function processDroppedTables($tables)
+    {
+        foreach ($tables as $table) {
+            $conn = $this->getConnection($table['tableName']);
+            
+            $conn->export->dropTable($table['tableName']);
+        }
+    }
+
+    /**
+     * processRenamedTables
+     *
+     * @param string $tables 
+     * @return void
+     */
+    public function processRenamedTables($tables)
+    {
+        foreach ($tables as $table) {
+            $conn = $this->getConnection($table['newTableName']);
+            
+            $conn->export->alterTable($table['oldTableName'], array('name' => $table['newTableName']));
+        }
+    }
+
+    /**
+     * processAddedColumns
+     *
+     * @param string $columns 
+     * @return void
+     */
+    public function processAddedColumns($columns)
+    {
+        foreach ($columns as $column) {
+            $conn = $this->getConnection($column['tableName']);
+            
+            $options = array();
+            $options = $column['options'];
+            $options['type'] = $column['type'];
+            
+            $conn->export->alterTable($column['tableName'], array('add' => array($column['columnName'] => $options)));
+        }
+    }
+
+    /**
+     * processRenamedColumns
+     *
+     * @param string $columns 
+     * @return void
+     */
+    public function processRenamedColumns($columns)
+    {
+        foreach ($columns as $column) {
+            $conn = $this->getConnection($column['tableName']);
+            
+            $columnList = $conn->import->listTableColumns($column['tableName']);
+            if (isset($columnList[$column['oldColumnName']])) {
+	            $conn->export->alterTable($column['tableName'], 
+	                                      array('rename' => array($column['oldColumnName'] => array('name' => $column['newColumnName'],
+	                                      																													'definition'=>$columnList[$column['oldColumnName']]))));
+            }
+        }
+    }
+
+    /**
+     * processChangedColumns
+     *
+     * @param string $columns 
+     * @return void
+     */
+    public function processChangedColumns($columns)
+    {
+        foreach ($columns as $column) {
+            $conn = $this->getConnection($column['tableName']);
+            
+            $options = array();
+            $options = $column['options'];
+            $options['type'] = $column['type'];
+            
+            $conn->export->alterTable($column['tableName'], array('change' => array($column['columnName'] => array('definition' => $options))));
+        }  
+    }
+
+    /**
+     * processRemovedColumns
+     *
+     * @param string $columns 
+     * @return void
+     */
+    public function processRemovedColumns($columns)
+    {
+        foreach ($columns as $column) {
+            $conn = $this->getConnection($column['tableName']);
+            
+            $conn->export->alterTable($column['tableName'], array('remove' => array($column['columnName'] => array())));
+        }
+    }
+
+    /**
+     * processAddexIndexes
+     *
+     * @param string $indexes 
+     * @return void
+     */
+    public function processAddedIndexes($indexes)
+    {
+        foreach ($indexes as $index) {
+            $conn = $this->getConnection($index['tableName']);
+            
+            $conn->export->createIndex($index['tableName'], $index['indexName'], $index['definition']);
+        }
+    }
+
+    /**
+     * processRemovedIndexes
+     *
+     * @param string $indexes 
+     * @return void
+     */
+    public function processRemovedIndexes($indexes)
+    {
+        foreach ($indexes as $index) {
+            $conn = $this->getConnection($index['tableName']);
+            
+            $conn->export->dropIndex($index['tableName'], $index['indexName']);
+        } 
+    }
+
+    /**
+     * processCreatedConstraints
+     *
+     * @param string $constraints 
+     * @return void
+     */
+    public function processCreatedConstraints($constraints)
+    {
+        foreach ($constraints as $constraint) {
+            $conn = $this->getConnection($constraint['tableName']);
+            $conn->export->createConstraint($constraint['tableName'], $constraint['constraintName'],
+                    $constraint['definition']);
+        }
+    }
+
+    /**
+     * processDroppedConstraints
+     *
+     * @param string $constraints 
+     * @return void
+     */
+    public function processDroppedConstraints($constraints)
+    {
+        foreach ($constraints as $constraint) {
+            $conn = $this->getConnection($constraint['tableName']);
+            $conn->export->dropConstraint($constraint['tableName'], $constraint['constraintName'],
+                    $constraint['primary']);
+        }
+    }
+
+    /**
+     * processCreatedFks
+     *
+     * @param string $foreignKeys 
+     * @return void
+     */
+    public function processCreatedFks($foreignKeys)
+    {
+        foreach ($foreignKeys as $fk) {
+            $conn = $this->getConnection($fk['tableName']);
+            $conn->export->createForeignKey($fk['tableName'], $fk['definition']);
+        }
+    }
+
+    /**
+     * processDroppedFks
+     *
+     * @param string $foreignKeys 
+     * @return void
+     */
+    public function processDroppedFks($foreignKeys)
+    {
+        foreach ($foreignKeys as $fk) {
+            $conn = $this->getConnection($fk['tableName']);
+            $conn->export->dropForeignKey($fk['tableName'], $fk['fkName']);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,194 @@
+<?php
+/*
+ *  $Id: Node.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node implements IteratorAggregate
+{
+    /**
+     * @param object    $record   reference to associated Doctrine_Record instance
+     */
+    protected $record;
+
+    /**
+     * @param array     $options
+     */
+    protected $options;
+
+    /**
+     * @param string     $iteratorType  (Pre | Post | Level)
+     */
+    protected $iteratorType;
+
+    /**
+     * @param array     $iteratorOptions
+     */
+    protected $iteratorOptions;
+
+    /**
+     * The tree to which the node belongs.
+     *
+     * @var unknown_type
+     */
+    protected $_tree;
+
+    /**
+     * contructor, creates node with reference to record and any options
+     *
+     * @param object $record                    instance of Doctrine_Record
+     * @param array $options                    options
+     */
+    public function __construct(Doctrine_Record $record, $options)
+    {
+        $this->record = $record;
+        $this->options = $options;
+        
+        // Make sure that the tree object of the root class is used in the case
+        // of column aggregation inheritance (single table inheritance).
+        $class = $record->getTable()->getComponentName();
+        $thisTable = $record->getTable();
+        $table = $thisTable;
+        if ($thisTable->getOption('inheritanceMap')) {
+            // Move up the hierarchy until we find the "subclasses" option. This option
+            // MUST be set on the root class of the user's hierarchy that uses STI.
+            while ( ! $subclasses = $table->getOption('subclasses')) {
+                $class = get_parent_class($class);
+                $reflectionClass = new ReflectionClass($class);
+                if ($reflectionClass->isAbstract()) {
+                    continue;
+                }
+                if ($class == 'Doctrine_Record') {
+                    throw new Doctrine_Node_Exception("No subclasses specified. You are "
+                            . "using Single Table Inheritance with NestedSet but you have "
+                            . "not specified the subclasses correctly. Make sure you use "
+                            . "setSubclasses() in the root class of your hierarchy.");
+                }
+                $table = $table->getConnection()->getTable($class);
+            }
+        }
+        if ($thisTable !== $table) {
+            $this->_tree = $table->getTree();
+        } else {
+            $this->_tree = $thisTable->getTree();
+        }
+    }
+
+    /**
+     * factory method to return node instance based upon chosen implementation
+     *
+     * @param object $record                    instance of Doctrine_Record
+     * @param string $impName                   implementation (NestedSet, AdjacencyList, MaterializedPath)
+     * @param array $options                    options
+     * @return object $options                  instance of Doctrine_Node
+     */
+    public static function factory(Doctrine_Record $record, $implName, $options = array())
+    {
+        $class = 'Doctrine_Node_' . $implName;
+
+        if ( ! class_exists($class)) {
+            throw new Doctrine_Node_Exception("The class $class must exist and extend Doctrine_Node");
+        }
+
+        return new $class($record, $options);
+    }
+
+    /**
+     * setter for record attribute
+     *
+     * @param object $record                    instance of Doctrine_Record
+     */
+    public function setRecord(Doctrine_Record $record)
+    {
+        $this->record = $record;
+    }
+
+    /**
+     * getter for record attribute
+     *
+     * @return object                           instance of Doctrine_Record
+     */
+    public function getRecord()
+    {
+        return $this->record;
+    }
+
+    /**
+     * convenience function for getIterator
+     *
+     * @param string $type                      type of iterator (Pre | Post | Level)
+     * @param array $options                    options
+     */
+    public function traverse($type = 'Pre', $options = array())
+    {
+        return $this->getIterator($type, $options);
+    }
+
+    /**
+     * get iterator
+     *
+     * @param string $type                      type of iterator (Pre | Post | Level)
+     * @param array $options                    options
+     */
+    public function getIterator($type = null, $options = null)
+    {
+        if ($type === null) {
+            $type = (isset($this->iteratorType) ? $this->iteratorType : 'Pre');
+        }
+
+        if ($options === null) {
+            $options = (isset($this->iteratorOptions) ? $this->iteratorOptions : array());
+        }
+
+        $implName = $this->record->getTable()->getOption('treeImpl');
+        $iteratorClass = 'Doctrine_Node_' . $implName . '_' . ucfirst(strtolower($type)) . 'OrderIterator';
+
+        return new $iteratorClass($this->record, $options);
+    }
+
+    /**
+     * sets node's iterator type
+     *
+     * @param int
+     */
+    public function setIteratorType($type)
+    {
+        $this->iteratorType = $type;
+    }
+
+    /**
+     * sets node's iterator options
+     *
+     * @param int
+     */
+    public function setIteratorOptions($options)
+    {
+        $this->iteratorOptions = $options;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/AdjacencyList.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: AdjacencyList.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_AdjacencyList
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Node_AdjacencyList extends Doctrine_Node implements Doctrine_Node_Interface
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/AdjacencyList/LevelOrderIterator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: LevelOrderIterator.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_AdjacencyList_LevelOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Node_AdjacencyList_LevelOrderIterator implements Iterator
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/AdjacencyList/PostOrderIterator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: PostOrderIterator.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_AdjacencyList_PostOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Node_AdjacencyList_PostOrderIterator implements Iterator
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/AdjacencyList/PreOrderIterator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: PreOrderIterator.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_AdjacencyList_PreOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Node_AdjacencyList_PreOrderIterator implements Iterator
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/Interface.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,268 @@
+<?php
+/*
+ *  $Id: Interface.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_Interface
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+interface Doctrine_Node_Interface {
+
+    /**
+     * test if node has previous sibling
+     *
+     * @return bool
+     */
+    public function hasPrevSibling();
+
+    /**
+     * test if node has next sibling
+     *
+     * @return bool
+     */
+    public function hasNextSibling();
+
+    /**
+     * test if node has children
+     *
+     * @return bool
+     */
+    public function hasChildren();
+
+    /**
+     * test if node has parent
+     *
+     * @return bool
+     */
+    public function hasParent();
+
+    /**
+     * gets record of prev sibling or empty record
+     *
+     * @return object Doctrine_Record
+     */
+    public function getPrevSibling();
+
+    /**
+     * gets record of next sibling or empty record
+     *
+     * @return object Doctrine_Record
+     */
+    public function getNextSibling();
+
+    /**
+     * gets siblings for node
+     *
+     * @return array                            array of sibling Doctrine_Record objects
+     */
+    public function getSiblings($includeNode = false);
+
+    /**
+     * gets record of first child or empty record
+     *
+     * @return object Doctrine_Record
+     */
+    public function getFirstChild();
+
+    /**
+     * gets record of last child or empty record
+     *
+     * @return object Doctrine_Record
+     */
+    public function getLastChild();
+
+    /**
+     * gets children for node (direct descendants only)
+     *
+     * @return array                            array of sibling Doctrine_Record objects
+     */
+    public function getChildren();
+
+    /**
+     * gets descendants for node (direct descendants only)
+     *
+     * @return iterator                         iterator to traverse descendants from node
+     */
+    public function getDescendants();
+
+    /**
+     * gets record of parent or empty record
+     *
+     * @return object Doctrine_Record
+     */
+    public function getParent();
+
+    /**
+     * gets ancestors for node
+     *
+     * @return object Doctrine_Collection
+     */
+    public function getAncestors();
+
+    /**
+     * gets path to node from root, uses record::toString() method to get node names
+     *
+     * @param string $seperator                 path seperator
+     * @param bool $includeNode                 whether or not to include node at end of path
+     * @return string                           string representation of path
+     */
+    public function getPath($seperator = ' > ', $includeNode = false);
+
+    /**
+     * gets level (depth) of node in the tree
+     *
+     * @return int
+     */
+    public function getLevel();
+
+    /**
+     * gets number of children (direct descendants)
+     *
+     * @return int
+     */
+    public function getNumberChildren();
+
+    /**
+     * gets number of descendants (children and their children)
+     *
+     * @return int
+     */
+    public function getNumberDescendants();
+
+    /**
+     * inserts node as parent of dest record
+     *
+     * @return bool
+     */
+    public function insertAsParentOf(Doctrine_Record $dest);
+
+    /**
+     * inserts node as previous sibling of dest record
+     *
+     * @return bool
+     */
+    public function insertAsPrevSiblingOf(Doctrine_Record $dest);
+
+    /**
+     * inserts node as next sibling of dest record
+     *
+     * @return bool
+     */
+    public function insertAsNextSiblingOf(Doctrine_Record $dest);
+
+    /**
+     * inserts node as first child of dest record
+     *
+     * @return bool
+     */
+    public function insertAsFirstChildOf(Doctrine_Record $dest);
+
+    /**
+     * inserts node as first child of dest record
+     *
+     * @return bool
+     */
+    public function insertAsLastChildOf(Doctrine_Record $dest);
+
+    /**
+     * moves node as prev sibling of dest record
+     *
+     */  
+    public function moveAsPrevSiblingOf(Doctrine_Record $dest);
+
+    /**
+     * moves node as next sibling of dest record
+     *
+     */
+    public function moveAsNextSiblingOf(Doctrine_Record $dest);
+
+    /**
+     * moves node as first child of dest record
+     *
+     */
+    public function moveAsFirstChildOf(Doctrine_Record $dest);
+
+    /**
+     * moves node as last child of dest record
+     *
+     */
+    public function moveAsLastChildOf(Doctrine_Record $dest);
+
+    /**
+     * adds node as last child of record
+     *
+     */
+    public function addChild(Doctrine_Record $record);
+
+    /**
+     * determines if node is leaf
+     *
+     * @return bool
+     */
+    public function isLeaf();
+
+    /**
+     * determines if node is root
+     *
+     * @return bool
+     */
+    public function isRoot();
+
+    /**
+     * determines if node is equal to subject node
+     *
+     * @return bool
+     */
+    public function isEqualTo(Doctrine_Record $subj);
+
+    /**
+     * determines if node is child of subject node
+     *
+     * @return bool
+     */
+    public function isDescendantOf(Doctrine_Record $subj);
+
+    /**
+     * determines if node is child of or sibling to subject node
+     *
+     * @return bool
+     */
+    public function isDescendantOfOrEqualTo(Doctrine_Record $subj);
+
+    /**
+     * determines if node is valid
+     *
+     * @return bool
+     */
+    public function isValidNode();
+
+    /**
+     * deletes node and it's descendants
+     *
+     */
+    public function delete();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/MaterializedPath.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: MaterializedPath.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_MaterializedPath
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Node_MaterializedPath extends Doctrine_Node implements Doctrine_Node_Interface
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/MaterializedPath/LevelOrderIterator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,68 @@
+<?php
+/*
+ *  $Id: LevelOrderIterator.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_MaterializedPath_LevelOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_MaterializedPath_LevelOrderIterator implements Iterator
+{
+    private $topNode = null;
+
+    private $curNode = null;
+
+    public function __construct($node, $opts)
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function rewind()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function valid()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function current()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function key()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function next()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/MaterializedPath/PostOrderIterator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,68 @@
+<?php
+/*
+ *  $Id: PostOrderIterator.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_MaterializedPath_PostOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_MaterializedPath_PostOrderIterator implements Iterator
+{
+    private $topNode = null;
+
+    private $curNode = null;
+
+    public function __construct($node, $opts)
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function rewind()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function valid()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function current()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function key()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function next()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/MaterializedPath/PreOrderIterator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,68 @@
+<?php
+/*
+ *  $Id: PreOrderIterator.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_MaterializedPath_PreOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_MaterializedPath_PreOrderIterator implements Iterator
+{
+    private $topNode = null;
+
+    private $curNode = null;
+
+    public function __construct($node, $opts)
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function rewind()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function valid()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function current()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function key()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function next()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/NestedSet.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,1198 @@
+<?php
+/*
+ *    $Id: NestedSet.php 5844 2009-06-09 07:07:36Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_NestedSet
+ *
+ * @package    Doctrine
+ * @subpackage Node
+ * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link       www.phpdoctrine.org
+ * @since      1.0
+ * @version    $Revision: 5844 $
+ * @author     Joe Simms <joe.simms@websites4.com>
+ * @author     Roman Borschel <roman@code-factory.org>     
+ */
+class Doctrine_Node_NestedSet extends Doctrine_Node implements Doctrine_Node_Interface
+{
+    /**
+     * test if node has previous sibling
+     *
+     * @return bool            
+     */
+    public function hasPrevSibling()
+    {
+        return $this->isValidNode($this->getPrevSibling());        
+    }
+
+    /**
+     * test if node has next sibling
+     *
+     * @return bool            
+     */ 
+    public function hasNextSibling()
+    {
+        return $this->isValidNode($this->getNextSibling());        
+    }
+
+    /**
+     * test if node has children
+     *
+     * @return bool            
+     */
+    public function hasChildren()
+    {
+        return (($this->getRightValue() - $this->getLeftValue() ) >1 );        
+    }
+
+    /**
+     * test if node has parent
+     *
+     * @return bool            
+     */
+    public function hasParent()
+    {
+        return !$this->isRoot();
+    }
+
+    /**
+     * gets record of prev sibling or empty record
+     *
+     * @return object     Doctrine_Record            
+     */
+    public function getPrevSibling()
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $q = $q->addWhere("$baseAlias.rgt = ?", $this->getLeftValue() - 1);
+        $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $result = $q->execute();
+
+        if (count($result) <= 0) {
+            return false;
+        }
+        
+        if ($result instanceof Doctrine_Collection) {
+            $sibling = $result->getFirst();
+        } else if (is_array($result)) {
+            $sibling = array_shift($result);
+        }
+        
+        return $sibling;
+    }
+
+    /**
+     * gets record of next sibling or empty record
+     *
+     * @return object     Doctrine_Record            
+     */
+    public function getNextSibling()
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $q = $q->addWhere("$baseAlias.lft = ?", $this->getRightValue() + 1);
+        $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $result = $q->execute();
+
+        if (count($result) <= 0) {
+            return false;
+        }
+        
+        if ($result instanceof Doctrine_Collection) {
+            $sibling = $result->getFirst();
+        } else if (is_array($result)) {
+            $sibling = array_shift($result);
+        }
+        
+        return $sibling;
+    }
+
+    /**
+     * gets siblings for node
+     *
+     * @return array     array of sibling Doctrine_Record objects            
+     */
+    public function getSiblings($includeNode = false)
+    {
+        $parent = $this->getParent();
+        $siblings = array();
+        if ($parent && $parent->exists()) {
+            foreach ($parent->getNode()->getChildren() as $child) {
+                if ($this->isEqualTo($child) && !$includeNode) {
+                    continue;
+                }
+                $siblings[] = $child;
+            }        
+        }
+        return $siblings;
+    }
+
+    /**
+     * gets record of first child or empty record
+     *
+     * @return object     Doctrine_Record            
+     */
+    public function getFirstChild()
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $q->addWhere("$baseAlias.lft = ?", $this->getLeftValue() + 1);
+        $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $result = $q->execute();
+
+        if (count($result) <= 0) {
+            return false;
+        }
+        
+        if ($result instanceof Doctrine_Collection) {
+            $child = $result->getFirst();
+        } else if (is_array($result)) {
+            $child = array_shift($result);
+        }
+        
+        return $child;       
+    }
+
+    /**
+     * gets record of last child or empty record
+     *
+     * @return object     Doctrine_Record            
+     */
+    public function getLastChild()
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $q->addWhere("$baseAlias.rgt = ?", $this->getRightValue() - 1);
+        $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $result = $q->execute();
+
+        if (count($result) <= 0) {
+            return false;
+        }
+        
+        if ($result instanceof Doctrine_Collection) {
+            $child = $result->getFirst();
+        } else if (is_array($result)) {
+            $child = array_shift($result);
+        }
+        
+        return $child;      
+    }
+
+    /**
+     * gets children for node (direct descendants only)
+     *
+     * @return mixed The children of the node or FALSE if the node has no children.               
+     */
+    public function getChildren()
+    { 
+        return $this->getDescendants(1);
+    }
+
+    /**
+     * gets descendants for node (direct descendants only)
+     *
+     * @return mixed  The descendants of the node or FALSE if the node has no descendants.  
+     */
+    public function getDescendants($depth = null, $includeNode = false)
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $params = array($this->record->get('lft'), $this->record->get('rgt'));
+        
+        if ($includeNode) {
+            $q->addWhere("$baseAlias.lft >= ? AND $baseAlias.rgt <= ?", $params)->addOrderBy("$baseAlias.lft asc");
+        } else {
+            $q->addWhere("$baseAlias.lft > ? AND $baseAlias.rgt < ?", $params)->addOrderBy("$baseAlias.lft asc");
+        }
+        
+        if ($depth !== null) {
+            $q->addWhere("$baseAlias.level <= ?", $this->record['level'] + $depth);
+        }
+        
+        $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $result = $q->execute();
+
+        if (count($result) <= 0) {
+            return false;
+        }
+
+        return $result;
+    }
+
+    /**
+     * gets record of parent or empty record
+     *
+     * @return object     Doctrine_Record            
+     */
+    public function getParent()
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $q->addWhere("$baseAlias.lft < ? AND $baseAlias.rgt > ?", array($this->getLeftValue(), $this->getRightValue()))
+                ->addOrderBy("$baseAlias.rgt asc");
+        $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $result = $q->execute();
+        
+        if (count($result) <= 0) {
+            return false;
+        }
+               
+        if ($result instanceof Doctrine_Collection) {
+            $parent = $result->getFirst();
+        } else if (is_array($result)) {
+            $parent = array_shift($result);
+        }
+        
+        return $parent;
+    }
+
+    /**
+     * gets ancestors for node
+     *
+     * @param integer $deth  The depth 'upstairs'.
+     * @return mixed  The ancestors of the node or FALSE if the node has no ancestors (this 
+     *                basically means it's a root node).                
+     */
+    public function getAncestors($depth = null)
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $q->addWhere("$baseAlias.lft < ? AND $baseAlias.rgt > ?", array($this->getLeftValue(), $this->getRightValue()))
+                ->addOrderBy("$baseAlias.lft asc");
+        if ($depth !== null) {
+            $q->addWhere("$baseAlias.level >= ?", $this->record['level'] - $depth);
+        }
+        $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $ancestors = $q->execute();
+        if (count($ancestors) <= 0) {
+            return false;
+        }
+        return $ancestors;
+    }
+
+    /**
+     * gets path to node from root, uses record::toString() method to get node names
+     *
+     * @param string     $seperator     path seperator
+     * @param bool     $includeNode     whether or not to include node at end of path
+     * @return string     string representation of path                
+     */     
+    public function getPath($seperator = ' > ', $includeRecord = false)
+    {
+        $path = array();
+        $ancestors = $this->getAncestors();
+        if ($ancestors) {
+            foreach ($ancestors as $ancestor) {
+                $path[] = $ancestor->__toString();
+            }
+        }
+        if ($includeRecord) {
+            $path[] = $this->getRecord()->__toString();
+        }
+            
+        return implode($seperator, $path);
+    }
+
+    /**
+     * gets number of children (direct descendants)
+     *
+     * @return int            
+     */     
+    public function getNumberChildren()
+    {
+        $children = $this->getChildren();
+        return $children === false ? 0 : count($children);
+    }
+
+    /**
+     * gets number of descendants (children and their children)
+     *
+     * @return int            
+     */
+    public function getNumberDescendants()
+    {
+        return ($this->getRightValue() - $this->getLeftValue() - 1) / 2;
+    }
+
+    /**
+     * inserts node as parent of dest record
+     *
+     * @return bool
+     * @todo Wrap in transaction          
+     */
+    public function insertAsParentOf(Doctrine_Record $dest)
+    {
+        // cannot insert a node that has already has a place within the tree
+        if ($this->isValidNode()) {
+            return false;
+        }
+        // cannot insert as parent of root
+        if ($dest->getNode()->isRoot()) {
+            return false;
+        }
+        
+        // cannot insert as parent of itself
+        if (
+		    $dest === $this->record ||
+			($dest->exists() && $this->record->exists() && $dest->identifier() === $this->record->identifier())
+		) {
+            throw new Doctrine_Tree_Exception("Cannot insert node as parent of itself");
+
+            return false;
+        }
+
+        $newLeft  = $dest->getNode()->getLeftValue();
+        $newRight = $dest->getNode()->getRightValue() + 2;
+        $newRoot  = $dest->getNode()->getRootValue();
+		$newLevel = $dest->getNode()->getLevel();
+		
+		$conn = $this->record->getTable()->getConnection();
+		try {
+		    $conn->beginInternalTransaction();
+		    
+		    // Make space for new node
+            $this->shiftRLValues($dest->getNode()->getRightValue() + 1, 2, $newRoot);
+
+            // Slide child nodes over one and down one to allow new parent to wrap them
+    		$componentName = $this->_tree->getBaseComponent();		
+            $q = new Doctrine_Query();
+            $q->update($componentName);
+            $q->set("$componentName.lft", "$componentName.lft + 1");
+            $q->set("$componentName.rgt", "$componentName.rgt + 1");
+            $q->set("$componentName.level", "$componentName.level + 1");
+            $q->where("$componentName.lft >= ? AND $componentName.rgt <= ?", array($newLeft, $newRight));
+    		$q = $this->_tree->returnQueryWithRootId($q, $newRoot);
+    		$q->execute();
+
+            $this->record['level'] = $newLevel;
+    		$this->insertNode($newLeft, $newRight, $newRoot);
+    		
+    		$conn->commit();
+		} catch (Exception $e) {
+		    $conn->rollback();
+		    throw $e;
+		}
+        
+        return true;
+    }
+
+    /**
+     * inserts node as previous sibling of dest record
+     *
+     * @return bool
+     * @todo Wrap in transaction       
+     */
+    public function insertAsPrevSiblingOf(Doctrine_Record $dest)
+    {
+        // cannot insert a node that has already has a place within the tree
+        if ($this->isValidNode()) {
+            return false;
+        }
+        // cannot insert as sibling of itself
+        if (
+		    $dest === $this->record ||
+			($dest->exists() && $this->record->exists() && $dest->identifier() === $this->record->identifier())
+		) {
+            throw new Doctrine_Tree_Exception("Cannot insert node as previous sibling of itself");
+
+            return false;
+        }
+
+        $newLeft = $dest->getNode()->getLeftValue();
+        $newRight = $dest->getNode()->getLeftValue() + 1;
+        $newRoot = $dest->getNode()->getRootValue();
+        
+        $conn = $this->record->getTable()->getConnection();
+        try {
+            $conn->beginInternalTransaction();
+            
+            $this->shiftRLValues($newLeft, 2, $newRoot);
+            $this->record['level'] = $dest['level'];
+            $this->insertNode($newLeft, $newRight, $newRoot);
+            // update destination left/right values to prevent a refresh
+            // $dest->getNode()->setLeftValue($dest->getNode()->getLeftValue() + 2);
+            // $dest->getNode()->setRightValue($dest->getNode()->getRightValue() + 2);
+            
+            $conn->commit();
+        } catch (Exception $e) {
+            $conn->rollback();
+            throw $e;
+        }
+                        
+        return true;
+    }
+
+    /**
+     * inserts node as next sibling of dest record
+     *
+     * @return bool
+     * @todo Wrap in transaction           
+     */    
+    public function insertAsNextSiblingOf(Doctrine_Record $dest)
+    {
+        // cannot insert a node that has already has a place within the tree
+        if ($this->isValidNode()) {
+            return false;
+        }
+        // cannot insert as sibling of itself
+        if (
+		    $dest === $this->record ||
+			($dest->exists() && $this->record->exists() && $dest->identifier() === $this->record->identifier())
+		) {
+            throw new Doctrine_Tree_Exception("Cannot insert node as next sibling of itself");
+
+            return false;
+        }
+
+        $newLeft = $dest->getNode()->getRightValue() + 1;
+        $newRight = $dest->getNode()->getRightValue() + 2;
+        $newRoot = $dest->getNode()->getRootValue();
+
+        $conn = $this->record->getTable()->getConnection();
+        try {
+            $conn->beginInternalTransaction();
+            
+            $this->shiftRLValues($newLeft, 2, $newRoot);
+            $this->record['level'] = $dest['level'];
+            $this->insertNode($newLeft, $newRight, $newRoot);
+            // update destination left/right values to prevent a refresh
+            // no need, node not affected
+            
+            $conn->commit();
+        } catch (Exception $e) {
+            $conn->rollback();
+            throw $e;
+        }
+
+        return true;
+    }
+
+    /**
+     * inserts node as first child of dest record
+     *
+     * @return bool
+     * @todo Wrap in transaction         
+     */
+    public function insertAsFirstChildOf(Doctrine_Record $dest)
+    {
+        // cannot insert a node that has already has a place within the tree
+        if ($this->isValidNode()) {
+            return false;
+        }
+        // cannot insert as child of itself
+        if (
+		    $dest === $this->record ||
+			($dest->exists() && $this->record->exists() && $dest->identifier() === $this->record->identifier())
+		) {
+            throw new Doctrine_Tree_Exception("Cannot insert node as first child of itself");
+
+            return false;
+        }
+
+        $newLeft = $dest->getNode()->getLeftValue() + 1;
+        $newRight = $dest->getNode()->getLeftValue() + 2;
+        $newRoot = $dest->getNode()->getRootValue();
+
+        $conn = $this->record->getTable()->getConnection();
+        try {
+            $conn->beginInternalTransaction();
+            
+            $this->shiftRLValues($newLeft, 2, $newRoot);
+            $this->record['level'] = $dest['level'] + 1;
+            $this->insertNode($newLeft, $newRight, $newRoot);
+            
+            // update destination left/right values to prevent a refresh
+            // $dest->getNode()->setRightValue($dest->getNode()->getRightValue() + 2);
+            
+            $conn->commit();
+        } catch (Exception $e) {
+            $conn->rollback();
+            throw $e;
+        }
+
+        return true;
+    }
+
+    /**
+     * inserts node as last child of dest record
+     *
+     * @return bool
+     * @todo Wrap in transaction            
+     */
+    public function insertAsLastChildOf(Doctrine_Record $dest)
+    {
+        // cannot insert a node that has already has a place within the tree
+        if ($this->isValidNode()) {
+            return false;
+        }
+        // cannot insert as child of itself
+        if (
+		    $dest === $this->record ||
+			($dest->exists() && $this->record->exists() && $dest->identifier() === $this->record->identifier())
+		) {
+            throw new Doctrine_Tree_Exception("Cannot insert node as last child of itself");
+
+            return false;
+        }
+
+        $newLeft = $dest->getNode()->getRightValue();
+        $newRight = $dest->getNode()->getRightValue() + 1;
+        $newRoot = $dest->getNode()->getRootValue();
+
+        $conn = $this->record->getTable()->getConnection();
+        try {
+            $conn->beginInternalTransaction();
+            
+            $this->shiftRLValues($newLeft, 2, $newRoot);
+            $this->record['level'] = $dest['level'] + 1;
+            $this->insertNode($newLeft, $newRight, $newRoot);
+
+            // update destination left/right values to prevent a refresh
+            // $dest->getNode()->setRightValue($dest->getNode()->getRightValue() + 2);
+            
+            $conn->commit();
+        } catch (Exception $e) {
+            $conn->rollback();
+            throw $e;
+        }
+        
+        return true;
+    }
+
+    /**
+     * Accomplishes moving of nodes between different trees.
+     * Used by the move* methods if the root values of the two nodes are different.
+     *
+     * @param Doctrine_Record $dest
+     * @param unknown_type $newLeftValue
+     * @param unknown_type $moveType
+     * @todo Better exception handling/wrapping
+     */
+    private function _moveBetweenTrees(Doctrine_Record $dest, $newLeftValue, $moveType)
+    {
+        $conn = $this->record->getTable()->getConnection();
+            
+        try {
+            $conn->beginInternalTransaction();
+
+            // Move between trees: Detach from old tree & insert into new tree
+            $newRoot = $dest->getNode()->getRootValue();
+            $oldRoot = $this->getRootValue();
+            $oldLft = $this->getLeftValue();
+            $oldRgt = $this->getRightValue();
+            $oldLevel = $this->record['level'];
+
+            // Prepare target tree for insertion, make room
+            $this->shiftRlValues($newLeftValue, $oldRgt - $oldLft - 1, $newRoot);
+
+            // Set new root id for this node
+            $this->setRootValue($newRoot);
+            $this->record->save();
+
+            // Close gap in old tree
+            $first = $oldRgt + 1;
+            $delta = $oldLft - $oldRgt - 1;
+            $this->shiftRLValues($first, $delta, $oldRoot);
+
+            // Insert this node as a new node
+            $this->setRightValue(0);
+            $this->setLeftValue(0);
+
+            switch ($moveType) {
+                case 'moveAsPrevSiblingOf':
+                    $this->insertAsPrevSiblingOf($dest);
+                break;
+                case 'moveAsFirstChildOf':
+                    $this->insertAsFirstChildOf($dest);
+                break;
+                case 'moveAsNextSiblingOf':
+                    $this->insertAsNextSiblingOf($dest);
+                break;
+                case 'moveAsLastChildOf':
+                    $this->insertAsLastChildOf($dest);
+                break;
+                default:
+                    throw new Exception("Unknown move operation: $moveType.");
+            }
+
+            $diff = $oldRgt - $oldLft;
+            $this->setRightValue($this->getLeftValue() + ($oldRgt - $oldLft));
+            $this->record->save();
+
+            $newLevel = $this->record['level'];
+            $levelDiff = $newLevel - $oldLevel;
+
+            // Relocate descendants of the node
+            $diff = $this->getLeftValue() - $oldLft;
+            $componentName = $this->_tree->getBaseComponent();
+            $rootColName = $this->_tree->getAttribute('rootColumnName');
+
+            // Update lft/rgt/root/level for all descendants
+            $q = new Doctrine_Query($conn);
+            $q = $q->update($componentName)
+                    ->set($componentName . '.lft', $componentName.'.lft + ?', $diff)
+                    ->set($componentName . '.rgt', $componentName.'.rgt + ?', $diff)
+                    ->set($componentName . '.level', $componentName.'.level + ?', $levelDiff)
+                    ->set($componentName . '.' . $rootColName, '?', $newRoot)
+                    ->where($componentName . '.lft > ? AND ' . $componentName . '.rgt < ?',
+                    array($oldLft, $oldRgt));
+            $q = $this->_tree->returnQueryWithRootId($q, $oldRoot);
+            $q->execute();
+
+            $conn->commit();
+     
+	        return true;
+        } catch (Exception $e) {
+            $conn->rollback();
+            throw $e;
+        }
+        
+        return false;
+    }
+
+    /**
+     * moves node as prev sibling of dest record
+     * 
+     */     
+    public function moveAsPrevSiblingOf(Doctrine_Record $dest)
+    {
+        if (
+		    $dest === $this->record ||
+			($dest->exists() && $this->record->exists() && $dest->identifier() === $this->record->identifier())
+		) {
+            throw new Doctrine_Tree_Exception("Cannot move node as previous sibling of itself");
+
+			return false;
+		}
+
+        if ($dest->getNode()->getRootValue() != $this->getRootValue()) {
+            // Move between trees
+            return $this->_moveBetweenTrees($dest, $dest->getNode()->getLeftValue(), __FUNCTION__);
+        } else {
+            // Move within the tree
+            $oldLevel = $this->record['level'];
+            $this->record['level'] = $dest['level'];
+            $this->updateNode($dest->getNode()->getLeftValue(), $this->record['level'] - $oldLevel);
+        }
+        
+        return true;
+    }
+
+    /**
+     * moves node as next sibling of dest record
+     *        
+     */
+    public function moveAsNextSiblingOf(Doctrine_Record $dest)
+    {
+        if (
+		    $dest === $this->record ||
+			($dest->exists() && $this->record->exists() && $dest->identifier() === $this->record->identifier())
+		) {
+            throw new Doctrine_Tree_Exception("Cannot move node as next sibling of itself");
+            
+            return false;
+        }
+
+        if ($dest->getNode()->getRootValue() != $this->getRootValue()) {
+            // Move between trees
+            return $this->_moveBetweenTrees($dest, $dest->getNode()->getRightValue() + 1, __FUNCTION__);
+        } else {
+            // Move within tree
+            $oldLevel = $this->record['level'];
+            $this->record['level'] = $dest['level'];
+            $this->updateNode($dest->getNode()->getRightValue() + 1, $this->record['level'] - $oldLevel);
+        }
+        
+        return true;
+    }
+
+    /**
+     * moves node as first child of dest record
+     *            
+     */
+    public function moveAsFirstChildOf(Doctrine_Record $dest)
+    {
+        if (
+		    $dest === $this->record ||
+			($dest->exists() && $this->record->exists() && $dest->identifier() === $this->record->identifier())
+		) {
+            throw new Doctrine_Tree_Exception("Cannot move node as first child of itself");
+
+			return false;
+		}
+
+		if ($dest->getNode()->getRootValue() != $this->getRootValue()) {
+            // Move between trees
+            return $this->_moveBetweenTrees($dest, $dest->getNode()->getLeftValue() + 1, __FUNCTION__);
+        } else {
+            // Move within tree
+            $oldLevel = $this->record['level'];
+            $this->record['level'] = $dest['level'] + 1;
+            $this->updateNode($dest->getNode()->getLeftValue() + 1, $this->record['level'] - $oldLevel);
+        }
+
+        return true;
+    }
+
+    /**
+     * moves node as last child of dest record
+     *        
+     */
+    public function moveAsLastChildOf(Doctrine_Record $dest)
+    {
+        if (
+		    $dest === $this->record ||
+			($dest->exists() && $this->record->exists() && $dest->identifier() === $this->record->identifier())
+		) {
+            throw new Doctrine_Tree_Exception("Cannot move node as last child of itself");
+
+			return false;
+		}
+
+        if ($dest->getNode()->getRootValue() != $this->getRootValue()) {
+            // Move between trees
+            return $this->_moveBetweenTrees($dest, $dest->getNode()->getRightValue(), __FUNCTION__);
+        } else {
+            // Move within tree
+            $oldLevel = $this->record['level'];
+            $this->record['level'] = $dest['level'] + 1;
+            $this->updateNode($dest->getNode()->getRightValue(), $this->record['level'] - $oldLevel);
+        }
+        
+        return true;
+    }
+
+    /**
+     * Makes this node a root node. Only used in multiple-root trees.
+     *
+     * @todo Exception handling/wrapping
+     */
+    public function makeRoot($newRootId)
+    {
+        // TODO: throw exception instead?
+        if ($this->getLeftValue() == 1 || ! $this->_tree->getAttribute('hasManyRoots')) {
+            return false;
+        }
+        
+        $oldRgt = $this->getRightValue();
+        $oldLft = $this->getLeftValue();
+        $oldRoot = $this->getRootValue();
+        $oldLevel = $this->record['level'];
+        
+        $conn = $this->record->getTable()->getConnection();
+        try {
+            $conn->beginInternalTransaction();
+            
+            // Update descendants lft/rgt/root/level values
+            $diff = 1 - $oldLft;
+            $newRoot = $newRootId;
+            $componentName = $this->_tree->getBaseComponent();
+            $rootColName = $this->_tree->getAttribute('rootColumnName');
+            $q = new Doctrine_Query($conn);
+            $q = $q->update($componentName)
+                    ->set($componentName . '.lft', $componentName.'.lft + ?', $diff)
+                    ->set($componentName . '.rgt', $componentName.'.rgt + ?', $diff)
+                    ->set($componentName . '.level', $componentName.'.level - ?', $oldLevel)
+                    ->set($componentName . '.' . $rootColName, '?', $newRoot)
+                    ->where($componentName . '.lft > ? AND ' . $componentName . '.rgt < ?',
+                    array($oldLft, $oldRgt));
+            $q = $this->_tree->returnQueryWithRootId($q, $oldRoot);
+            $q->execute();
+            
+            // Detach from old tree (close gap in old tree)
+            $first = $oldRgt + 1;
+            $delta = $oldLft - $oldRgt - 1;
+            $this->shiftRLValues($first, $delta, $this->getRootValue());
+            
+            // Set new lft/rgt/root/level values for root node
+            $this->setLeftValue(1);
+            $this->setRightValue($oldRgt - $oldLft + 1);
+            $this->setRootValue($newRootId);
+            $this->record['level'] = 0;
+            
+            $this->record->save();
+            
+            $conn->commit();
+            
+            return true;
+        } catch (Exception $e) {
+            $conn->rollback();
+            throw $e;
+        }
+        
+        return false;
+    }
+
+    /**
+     * adds node as last child of record
+     *        
+     */
+    public function addChild(Doctrine_Record $record)
+    {
+        $record->getNode()->insertAsLastChildOf($this->getRecord());
+    }
+
+    /**
+     * determines if node is leaf
+     *
+     * @return bool            
+     */
+    public function isLeaf()
+    {
+        return (($this->getRightValue() - $this->getLeftValue()) == 1);
+    }
+
+    /**
+     * determines if node is root
+     *
+     * @return bool            
+     */
+    public function isRoot()
+    {
+        return ($this->getLeftValue() == 1);
+    }
+
+    /**
+     * determines if node is equal to subject node
+     *
+     * @return bool            
+     */    
+    public function isEqualTo(Doctrine_Record $subj)
+    {
+        return (($this->getLeftValue() == $subj->getNode()->getLeftValue()) &&
+                ($this->getRightValue() == $subj->getNode()->getRightValue()) && 
+                ($this->getRootValue() == $subj->getNode()->getRootValue())
+                );
+    }
+
+    /**
+     * determines if node is child of subject node
+     *
+     * @return bool
+     */
+    public function isDescendantOf(Doctrine_Record $subj)
+    {
+        return (($this->getLeftValue() > $subj->getNode()->getLeftValue()) &&
+                ($this->getRightValue() < $subj->getNode()->getRightValue()) &&
+                ($this->getRootValue() == $subj->getNode()->getRootValue()));
+    }
+
+    /**
+     * determines if node is child of or sibling to subject node
+     *
+     * @return bool            
+     */
+    public function isDescendantOfOrEqualTo(Doctrine_Record $subj)
+    {
+        return (($this->getLeftValue() >= $subj->getNode()->getLeftValue()) &&
+                ($this->getRightValue() <= $subj->getNode()->getRightValue()) &&
+                ($this->getRootValue() == $subj->getNode()->getRootValue()));
+    }
+
+    /**
+     * determines if node is valid
+     *
+     * @return bool
+     */
+    public function isValidNode($record = null)
+    {
+        if ($record === null) {
+            return ($this->getRightValue() > $this->getLeftValue());
+        } else if ( $record instanceof Doctrine_Record ) {
+            return ($record->getNode()->getRightValue() > $record->getNode()->getLeftValue());
+        } else {
+            return false;
+        }
+    }
+    
+    /**
+     * Detaches the node from the tree by invalidating it's lft & rgt values
+     * (they're set to 0).
+     */
+    public function detach()
+    {
+        $this->setLeftValue(0);
+        $this->setRightValue(0);
+    }
+
+    /**
+     * deletes node and it's descendants
+     * @todo Delete more efficiently. Wrap in transaction if needed.      
+     */
+    public function delete()
+    {
+        $conn = $this->record->getTable()->getConnection();
+        try {
+            $conn->beginInternalTransaction();
+            
+            // TODO: add the setting whether or not to delete descendants or relocate children
+            $oldRoot = $this->getRootValue();
+            $q = $this->_tree->getBaseQuery();
+
+            $baseAlias = $this->_tree->getBaseAlias();
+            $componentName = $this->_tree->getBaseComponent();
+
+            $q = $q->addWhere("$baseAlias.lft >= ? AND $baseAlias.rgt <= ?", array($this->getLeftValue(), $this->getRightValue()));
+
+            $q = $this->_tree->returnQueryWithRootId($q, $oldRoot);
+
+            $coll = $q->execute();
+
+            $coll->delete();
+
+            $first = $this->getRightValue() + 1;
+            $delta = $this->getLeftValue() - $this->getRightValue() - 1;
+            $this->shiftRLValues($first, $delta, $oldRoot);
+            
+            $conn->commit();
+        } catch (Exception $e) {
+            $conn->rollback();
+            throw $e;
+        }
+        
+        return true; 
+    }
+
+    /**
+     * sets node's left and right values and save's it
+     *
+     * @param int     $destLeft     node left value
+     * @param int        $destRight    node right value
+     */    
+    private function insertNode($destLeft = 0, $destRight = 0, $destRoot = 1)
+    {
+        $this->setLeftValue($destLeft);
+        $this->setRightValue($destRight);
+        $this->setRootValue($destRoot);
+        $this->record->save();    
+    }
+
+    /**
+     * move node's and its children to location $destLeft and updates rest of tree
+     *
+     * @param int     $destLeft    destination left value
+     * @todo Wrap in transaction
+     */
+    private function updateNode($destLeft, $levelDiff)
+    { 
+        $componentName = $this->_tree->getBaseComponent();
+        $left = $this->getLeftValue();
+        $right = $this->getRightValue();
+        $rootId = $this->getRootValue();
+
+        $treeSize = $right - $left + 1;
+
+        $conn = $this->record->getTable()->getConnection();
+        try {
+            $conn->beginInternalTransaction();
+            
+            // Make room in the new branch
+            $this->shiftRLValues($destLeft, $treeSize, $rootId);
+
+            if ($left >= $destLeft) { // src was shifted too?
+                $left += $treeSize;
+                $right += $treeSize;
+            }
+
+            // update level for descendants
+            $q = new Doctrine_Query();
+            $q = $q->update($componentName)
+                    ->set($componentName . '.level', $componentName.'.level + ?', array($levelDiff))
+                    ->where($componentName . '.lft > ? AND ' . $componentName . '.rgt < ?',
+                            array($left, $right));
+            $q = $this->_tree->returnQueryWithRootId($q, $rootId);
+            $q->execute();
+
+            // now there's enough room next to target to move the subtree
+            $this->shiftRLRange($left, $right, $destLeft - $left, $rootId);
+
+            // correct values after source (close gap in old tree)
+            $this->shiftRLValues($right + 1, -$treeSize, $rootId);
+
+            $this->record->save();
+            $this->record->refresh();
+            
+            $conn->commit();
+        } catch (Exception $e) {
+            $conn->rollback();
+            throw $e;
+        }
+        
+        return true;
+    }
+
+    /**
+     * adds '$delta' to all Left and Right values that are >= '$first'. '$delta' can also be negative.
+     *
+     * Note: This method does wrap its database queries in a transaction. This should be done
+     * by the invoking code.
+     *
+     * @param int $first         First node to be shifted
+     * @param int $delta         Value to be shifted by, can be negative
+     */    
+    private function shiftRlValues($first, $delta, $rootId = 1)
+    {
+        $qLeft  = new Doctrine_Query();
+        $qRight = new Doctrine_Query();
+
+        // shift left columns
+        $componentName = $this->_tree->getBaseComponent();
+        $qLeft = $qLeft->update($componentName)
+                ->set($componentName . '.lft', $componentName.'.lft + ?', $delta)
+                ->where($componentName . '.lft >= ?', $first);
+        
+        $qLeft = $this->_tree->returnQueryWithRootId($qLeft, $rootId);
+        
+        $resultLeft = $qLeft->execute();
+        
+        // shift right columns
+        $qRight = $qRight->update($componentName)
+                ->set($componentName . '.rgt', $componentName.'.rgt + ?', $delta)
+                ->where($componentName . '.rgt >= ?', $first);
+
+        $qRight = $this->_tree->returnQueryWithRootId($qRight, $rootId);
+
+        $resultRight = $qRight->execute();
+    }
+
+    /**
+     * adds '$delta' to all Left and Right values that are >= '$first' and <= '$last'. 
+     * '$delta' can also be negative.
+     *
+     * Note: This method does wrap its database queries in a transaction. This should be done
+     * by the invoking code.
+     *
+     * @param int $first     First node to be shifted (L value)
+     * @param int $last     Last node to be shifted (L value)
+     * @param int $delta         Value to be shifted by, can be negative
+     */ 
+    private function shiftRlRange($first, $last, $delta, $rootId = 1)
+    {
+        $qLeft  = new Doctrine_Query();
+        $qRight = new Doctrine_Query();
+
+        // shift left column values
+        $componentName = $this->_tree->getBaseComponent();
+        $qLeft = $qLeft->update($componentName)
+                ->set($componentName . '.lft', $componentName.'.lft + ?', $delta)
+                ->where($componentName . '.lft >= ? AND ' . $componentName . '.lft <= ?', array($first, $last));
+        
+        $qLeft = $this->_tree->returnQueryWithRootId($qLeft, $rootId);
+
+        $resultLeft = $qLeft->execute();
+        
+        // shift right column values
+        $qRight = $qRight->update($componentName)
+                ->set($componentName . '.rgt', $componentName.'.rgt + ?', $delta)
+                ->where($componentName . '.rgt >= ? AND ' . $componentName . '.rgt <= ?', array($first, $last));
+
+        $qRight = $this->_tree->returnQueryWithRootId($qRight, $rootId);
+
+        $resultRight = $qRight->execute();
+    }
+
+    /**
+     * gets record's left value
+     *
+     * @return int            
+     */     
+    public function getLeftValue()
+    {
+        return $this->record->get('lft');
+    }
+
+    /**
+     * sets record's left value
+     *
+     * @param int            
+     */     
+    public function setLeftValue($lft)
+    {
+        $this->record->set('lft', $lft);        
+    }
+
+    /**
+     * gets record's right value
+     *
+     * @return int            
+     */     
+    public function getRightValue()
+    {
+        return $this->record->get('rgt');        
+    }
+
+    /**
+     * sets record's right value
+     *
+     * @param int            
+     */    
+    public function setRightValue($rgt)
+    {
+        $this->record->set('rgt', $rgt);         
+    }
+
+    /**
+     * gets level (depth) of node in the tree
+     *
+     * @return int            
+     */    
+    public function getLevel()
+    {
+        if ( ! isset($this->record['level'])) {
+            $baseAlias = $this->_tree->getBaseAlias();
+            $componentName = $this->_tree->getBaseComponent();
+            $q = $this->_tree->getBaseQuery();
+            $q = $q->addWhere("$baseAlias.lft < ? AND $baseAlias.rgt > ?", array($this->getLeftValue(), $this->getRightValue()));
+
+            $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+            
+            $coll = $q->execute();
+
+            $this->record['level'] = count($coll) ? count($coll) : 0;
+        }
+        return $this->record['level'];
+    }
+
+    /**
+     * get records root id value
+     *            
+     */     
+    public function getRootValue()
+    {
+        if ($this->_tree->getAttribute('hasManyRoots')) {
+            return $this->record->get($this->_tree->getAttribute('rootColumnName'));
+        }
+        return 1;
+    }
+
+    /**
+     * sets records root id value
+     *
+     * @param int            
+     */
+    public function setRootValue($value)
+    {
+        if ($this->_tree->getAttribute('hasManyRoots')) {
+            $this->record->set($this->_tree->getAttribute('rootColumnName'), $value);   
+        }    
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/NestedSet/LevelOrderIterator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: LevelOrderIterator.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_NestedSet_LevelOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_NestedSet_LevelOrderIterator
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/NestedSet/PostOrderIterator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: PostOrderIterator.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_NestedSet_PostOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_NestedSet_PostOrderIterator
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Node/NestedSet/PreOrderIterator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,183 @@
+<?php
+/*
+ *  $Id: PreOrderIterator.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_NestedSet_PreOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_NestedSet_PreOrderIterator implements Iterator
+{
+    /**
+     * @var Doctrine_Collection $collection
+     */
+    protected $collection;
+
+    /**
+     * @var array $keys
+     */
+    protected $keys;
+
+    /**
+     * @var mixed $key
+     */
+    protected $key;
+
+    /**
+     * @var integer $index
+     */
+    protected $index;
+
+    /**
+     * @var integer $index
+     */
+    protected $prevIndex;
+
+    /**
+     * @var integer $index
+     */
+    protected $traverseLevel;
+
+    /**
+     * @var integer $count
+     */
+    protected $count;
+
+    public function __construct($record, $opts)
+    {
+        $componentName = $record->getTable()->getComponentName();
+
+        $q = $record->getTable()->createQuery();
+
+        $params = array($record->get('lft'), $record->get('rgt'));
+        if (isset($opts['include_record']) && $opts['include_record']) {
+            $query = $q->where("$componentName.lft >= ? AND $componentName.rgt <= ?", $params)->orderBy("$componentName.lft asc");
+        } else {
+            $query = $q->where("$componentName.lft > ? AND $componentName.rgt < ?", $params)->orderBy("$componentName.lft asc");
+        }
+        
+        $query = $record->getTable()->getTree()->returnQueryWithRootId($query, $record->getNode()->getRootValue());
+
+        $this->maxLevel   = isset($opts['depth']) ? ($opts['depth'] + $record->getNode()->getLevel()) : 0;
+        $this->options    = $opts;
+        $this->collection = isset($opts['collection']) ? $opts['collection'] : $query->execute();
+        $this->keys       = $this->collection->getKeys();
+        $this->count      = $this->collection->count();
+        $this->index      = -1;
+        $this->level      = $record->getNode()->getLevel();
+        $this->prevLeft   = $record->getNode()->getLeftValue();
+
+        // clear the table identity cache
+        $record->getTable()->clear();
+    }
+
+    /**
+     * rewinds the iterator
+     *
+     * @return void
+     */
+    public function rewind()
+    {
+        $this->index = -1;
+        $this->key = null;
+    }
+
+    /**
+     * returns the current key
+     *
+     * @return integer
+     */
+    public function key()
+    {
+        return $this->key;
+    }
+
+    /**
+     * returns the current record
+     *
+     * @return Doctrine_Record
+     */
+    public function current()
+    {
+        $record = $this->collection->get($this->key);
+        $record->getNode()->setLevel($this->level);
+        return $record;
+    }
+
+    /**
+     * advances the internal pointer
+     *
+     * @return void
+     */
+    public function next()
+    {
+        while ($current = $this->advanceIndex()) {
+            if ($this->maxLevel && ($this->level > $this->maxLevel)) {
+                continue;
+            }
+
+            return $current;
+        }
+
+        return false;
+    }
+
+    /**
+     * @return boolean                          whether or not the iteration will continue
+     */
+    public function valid()
+    {
+        return ($this->index < $this->count);
+    }
+
+    public function count()
+    {
+        return $this->count;
+    }
+
+    private function updateLevel()
+    {
+        if ( ! (isset($this->options['include_record']) && $this->options['include_record'] && $this->index == 0)) {
+            $left = $this->collection->get($this->key)->getNode()->getLeftValue();
+            $this->level += $this->prevLeft - $left + 2;
+            $this->prevLeft = $left;
+        }
+    }
+
+    private function advanceIndex()
+    {
+        $this->index++;
+        $i = $this->index;
+        if (isset($this->keys[$i])) {
+            $this->key   = $this->keys[$i];
+            $this->updateLevel();
+            return $this->current();
+        }
+
+        return false;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Null.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,46 @@
+<?php
+/*
+ *  $Id: Null.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Null
+ *
+ * Simple empty class representing a null value
+ * used for extra fast null value testing with isset() rather than array_key_exists()
+ *
+ * @package     Doctrine
+ * @subpackage  Null
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+final class Doctrine_Null
+{ 
+    public function exists()
+    {
+        return false;    
+    }
+    public function __toString()
+    {
+        return '';
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Overloadable.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,44 @@
+<?php
+/*
+ *  $Id: Overloadable.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Overloadable
+ * a very generic overloading interface
+ *
+ * @package     Doctrine
+ * @subpackage  Overloadable
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+interface Doctrine_Overloadable {
+    /**
+     * __call
+     * method overloader
+     *
+     * @param string $m     the name of the method
+     * @param array $a      method arguments
+     * @return mixed        anything
+     */
+    public function __call($m, $a);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Pager.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,576 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Pager
+ *
+ * @author      Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @package     Doctrine
+ * @subpackage  Pager
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       0.9
+ */
+class Doctrine_Pager
+{
+    /**
+     * @var Doctrine_Query $_query      Doctrine_Query object related to the pager
+     */
+    protected $_query;
+
+    /**
+     * @var Doctrine_Query $_countQuery Doctrine_Query object related to the counter of pager
+     */
+    protected $_countQuery;
+
+    /**
+     * @var array $_countQueryParams    Hold the params to be used by Doctrine_Query counter object of pager
+     */
+    protected $_countQueryParams;
+
+    /**
+     * @var integer $_numResults        Number of results found
+     */
+    protected $_numResults;
+
+    /**
+     * @var integer $_maxPerPage        Maximum number of itens per page
+     */
+    protected $_maxPerPage;
+
+    /**
+     * @var integer $page               Current page
+     */
+    protected $_page;
+
+    /**
+     * @var integer $_lastPage          Last page (total of pages)
+     */
+    protected $_lastPage;
+
+    /**
+     * @var boolean $_executed          Pager was initialized (called "execute" at least once)
+     */
+    protected $_executed;
+
+
+
+    /**
+     * __construct
+     *
+     * @param mixed $query     Accepts either a Doctrine_Query object or a string 
+     *                        (which does the Doctrine_Query class creation).
+     * @param int $page     Current page
+     * @param int $maxPerPage     Maximum itens per page
+     * @return void
+     */
+    public function __construct($query, $page, $maxPerPage = 0)
+    {
+        $this->_setExecuted(false);
+
+        $this->_setQuery($query);
+        $this->_setPage($page);
+
+        $this->setMaxPerPage($maxPerPage);
+    }
+
+
+    /**
+     * _initialize
+     *
+     * Initialize Pager object calculating number of results
+     *
+     * @param $params  Optional parameters to Doctrine_Query::execute
+     * @return void
+     */
+    protected function _initialize($params = array())
+    {
+        // retrieve the number of items found
+        $countQuery = clone $this->getCountQuery();
+        $count = $countQuery->count($this->getCountQueryParams($params));
+
+        $this->_setNumResults($count);
+        $this->_setExecuted(true); // _adjustOffset relies of _executed equals true = getNumResults()
+
+        $this->_adjustOffset();
+    }
+
+
+    /**
+     * _adjustOffset
+     *
+     * Adjusts last page of Doctrine_Pager, offset and limit of Doctrine_Query associated
+     *
+     * @return void
+     */
+    protected function _adjustOffset()
+    {
+        // Define new total of pages
+        $this->_setLastPage(
+            max(1, ceil($this->getNumResults() / $this->getMaxPerPage()))
+        );
+        $offset = ($this->getPage() - 1) * $this->getMaxPerPage();
+
+        // Assign new offset and limit to Doctrine_Query object
+        $p = $this->getQuery();
+        $p->offset($offset);
+        $p->limit($this->getMaxPerPage());
+    }
+
+
+    /**
+     * getExecuted
+     *
+     * Returns the check if Pager was already executed at least once
+     *
+     * @return boolen        Pager was executed
+     */
+    public function getExecuted()
+    {
+        return $this->_executed;
+    }
+
+
+    /**
+     * _setExecuted
+     *
+     * Defines if Pager was already executed
+     *
+     * @param $executed       Pager was executed
+     * @return void
+     */
+    protected function _setExecuted($executed)
+    {
+        $this->_executed = $executed;
+    }
+
+
+    /**
+     * getRange
+     *
+     * Builds and return a Doctrine_Pager_Range_* based on arguments
+     *
+     * @param string $rangeStyle Pager Range style
+     * @param array $options     Custom subclass implementation options.
+     *                           Default is a blank array
+     * @return Doctrine_Pager_Range Pager Range
+     */
+    public function getRange($rangeStyle, $options = array())
+    {
+        $class = 'Doctrine_Pager_Range_' . ucfirst($rangeStyle);
+
+        return new $class($options, $this);
+    }
+
+
+    /**
+     * getNumResults
+     *
+     * Returns the number of results found
+     *
+     * @return int        the number of results found
+     */
+    public function getNumResults()
+    {
+        if ($this->getExecuted()) {
+            return $this->_numResults;
+        }
+
+        throw new Doctrine_Pager_Exception(
+            'Cannot retrieve the number of results of a not yet executed Pager query'
+        );
+    }
+
+
+    /**
+     * _setNumResults
+     *
+     * Defines the number of total results on initial query
+     *
+     * @param $nb       Number of results found on initial query fetch
+     * @return void
+     */
+    protected function _setNumResults($nb)
+    {
+        $this->_numResults = $nb;
+    }
+
+
+    /**
+     * getFirstPage
+     *
+     * Returns the first page
+     *
+     * @return int        first page
+     */
+    public function getFirstPage()
+    {
+        return 1;
+    }
+
+
+    /**
+     * getLastPage
+     *
+     * Returns the last page (total of pages)
+     *
+     * @return int        last page (total of pages)
+     */
+    public function getLastPage()
+    {
+        if ($this->getExecuted()) {
+            return $this->_lastPage;
+        }
+
+        throw new Doctrine_Pager_Exception(
+            'Cannot retrieve the last page number of a not yet executed Pager query'
+        );
+    }
+
+
+    /**
+     * _setLastPage
+     *
+     * Defines the last page (total of pages)
+     *
+     * @param $page       last page (total of pages)
+     * @return void
+     */
+    protected function _setLastPage($page)
+    {
+        $this->_lastPage = $page;
+
+        if ($this->getPage() > $page) {
+            $this->_setPage($page);
+        }
+    }
+
+
+    /**
+     * getLastPage
+     *
+     * Returns the current page
+     *
+     * @return int        current page
+     */
+    public function getPage()
+    {
+        return $this->_page;
+    }
+
+
+    /**
+     * getNextPage
+     *
+     * Returns the next page
+     *
+     * @return int        next page
+     */
+    public function getNextPage()
+    {
+        if ($this->getExecuted()) {
+            return min($this->getPage() + 1, $this->getLastPage());
+        }
+
+        throw new Doctrine_Pager_Exception(
+            'Cannot retrieve the last page number of a not yet executed Pager query'
+        );
+    }
+
+
+    /**
+     * getPreviousPage
+     *
+     * Returns the previous page
+     *
+     * @return int        previous page
+     */
+    public function getPreviousPage()
+    {
+        if ($this->getExecuted()) {
+            return max($this->getPage() - 1, $this->getFirstPage());
+        }
+
+        throw new Doctrine_Pager_Exception(
+            'Cannot retrieve the previous page number of a not yet executed Pager query'
+        );
+    }
+
+
+    /**
+     * getFirstIndice
+     *
+     * Return the first indice number for the current page
+     *
+     * @return int First indice number
+     */
+    public function getFirstIndice()
+    {
+        return ($this->getPage() - 1) * $this->getMaxPerPage() + 1;
+    }
+
+
+    /**
+     * getLastIndice
+     *
+     * Return the last indice number for the current page
+     *
+     * @return int Last indice number
+     */
+    public function getLastIndice()
+    {
+        return min($this->getNumResults(), ($this->getPage() * $this->getMaxPerPage()));
+    }
+
+
+    /**
+     * haveToPaginate
+     *
+     * Return true if it's necessary to paginate or false if not
+     *
+     * @return bool        true if it is necessary to paginate, false otherwise
+     */
+    public function haveToPaginate()
+    {
+        if ($this->getExecuted()) {
+            return $this->getNumResults() > $this->getMaxPerPage();
+        }
+
+        throw new Doctrine_Pager_Exception(
+            'Cannot know if it is necessary to paginate a not yet executed Pager query'
+        );
+    }
+
+
+    /**
+     * setPage
+     *
+     * Defines the current page and automatically adjust offset and limits
+     *
+     * @param $page       current page
+     * @return void
+     */
+    public function setPage($page)
+    {
+        $this->_setPage($page);
+        $this->_setExecuted(false);
+    }
+
+
+    /**
+     * _setPage
+     *
+     * Defines the current page
+     *
+     * @param $page       current page
+     * @return void
+     */
+    private function _setPage($page)
+    {
+        $page = intval($page);
+        $this->_page = ($page <= 0) ? 1 : $page;
+    }
+
+
+    /**
+     * getLastPage
+     *
+     * Returns the maximum number of itens per page
+     *
+     * @return int        maximum number of itens per page
+     */
+    public function getMaxPerPage()
+    {
+        return $this->_maxPerPage;
+    }
+
+
+    /**
+     * setMaxPerPage
+     *
+     * Defines the maximum number of itens per page and automatically adjust offset and limits
+     *
+     * @param $max       maximum number of itens per page
+     * @return void
+     */
+    public function setMaxPerPage($max)
+    {
+        if ($max > 0) {
+            $this->_maxPerPage = $max;
+        } else if ($max == 0) {
+            $this->_maxPerPage = 25;
+        } else {
+            $this->_maxPerPage = abs($max);
+        }
+
+        $this->_setExecuted(false);
+    }
+
+
+    /**
+     * getResultsInPage
+     *
+     * Returns the number of itens in current page
+     *
+     * @return int    Number of itens in current page
+     */
+    public function getResultsInPage()
+    {
+        $page = $this->getPage();
+
+        if ($page != $this->getLastPage()) {
+            return $this->getMaxPerPage();
+        }
+
+        $offset = ($this->getPage() - 1) * $this->getMaxPerPage();
+
+        return abs($this->getNumResults() - $offset);
+    }
+
+
+    /**
+     * getQuery
+     *
+     * Returns the Doctrine_Query collector object related to the pager
+     *
+     * @return Doctrine_Query    Doctrine_Query object related to the pager
+     */
+    public function getQuery()
+    {
+        return $this->_query;
+    }
+
+
+    /**
+     * _setQuery
+     *
+     * Defines the collector query to be used by pager
+     *
+     * @param Doctrine_Query     Accepts either a Doctrine_Query object or a string 
+     *                           (which does the Doctrine_Query class creation).
+     * @return void
+     */
+    protected function _setQuery($query)
+    {
+        if (is_string($query)) {
+            $query = Doctrine_Query::create()->parseQuery($query);
+        }
+
+        $this->_query = $query;
+    }
+
+
+    /**
+     * getCountQuery
+     *
+     * Returns the Doctrine_Query object that is used to make the count results to pager
+     *
+     * @return Doctrine_Query     Doctrine_Query object related to the pager
+     */
+    public function getCountQuery()
+    {
+        return ($this->_countQuery !== null) ? $this->_countQuery : $this->_query;
+    }
+
+
+    /**
+     * setCountQuery
+     *
+     * Defines the counter query to be used by pager
+     *
+     * @param Doctrine_Query  Accepts either a Doctrine_Query object or a string 
+     *                        (which does the Doctrine_Query class creation).
+     * @param array           Optional params to be used by counter Doctrine_Query. 
+     *                        If not defined, the params passed to execute method will be used.
+     * @return void
+     */
+    public function setCountQuery($query, $params = null)
+    {
+        if (is_string($query)) {
+            $query = Doctrine_Query::create()->parseQuery($query);
+        }
+
+        $this->_countQuery = $query;
+
+        $this->setCountQueryParams($params);
+
+        $this->_setExecuted(false);
+    }
+
+
+    /**
+     * getCountQueryParams
+     *
+     * Returns the params to be used by counter Doctrine_Query
+     *
+     * @return array     Doctrine_Query counter params
+     */
+    public function getCountQueryParams($defaultParams = array())
+    {
+        return ($this->_countQueryParams !== null) ? $this->_countQueryParams : $defaultParams;
+    }
+
+
+    /**
+     * setCountQueryParams
+     *
+     * Defines the params to be used by counter Doctrine_Query
+     *
+     * @param array       Optional params to be used by counter Doctrine_Query. 
+     *                    If not defined, the params passed to execute method will be used.
+     * @param boolean     Optional argument that append the query param instead of overriding the existent ones.
+     * @return void
+     */
+    public function setCountQueryParams($params = array(), $append = false)
+    {
+        if ($append && is_array($this->_countQueryParams)) {
+            $this->_countQueryParams = array_merge($this->_countQueryParams, $params);
+        } else {
+            if ($params !== null && !is_array($params)) {
+                $params = array($params);
+            }
+
+            $this->_countQueryParams = $params;
+        }
+
+        $this->_setExecuted(false);
+    }
+
+
+    /**
+     * execute
+     *
+     * Executes the query, populates the collection and then return it
+     *
+     * @param $params               Optional parameters to Doctrine_Query::execute
+     * @param $hydrationMode        Hydration Mode of Doctrine_Query::execute returned ResultSet.
+     * @return Doctrine_Collection  The root collection
+     */
+    public function execute($params = array(), $hydrationMode = null)
+    {
+        if (!$this->getExecuted()) {
+            $this->_initialize($params);
+        }
+        
+        return $this->getQuery()->execute($params, $hydrationMode);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Pager/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Pager_Exception
+ *
+ * @author      Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @package     Doctrine
+ * @subpackage  Pager
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       0.9
+ */
+class Doctrine_Pager_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Pager/Layout.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,512 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Pager_Layout
+ *
+ * @author      Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @package     Doctrine
+ * @subpackage  Pager
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       0.9
+ */
+class Doctrine_Pager_Layout
+{
+    /**
+     * @var Doctrine_Pager $_pager      Doctrine_Pager object related to the pager layout
+     */
+    private $_pager;
+
+    /**
+     * @var Doctrine_Pager_Range $_pagerRange      Doctrine_Pager_Range object related to the pager layout
+     */
+    private $_pagerRange;
+
+    /**
+     * @var string $_template      Template to be applied for inactive pages
+     *                             (and also active is selected template is not defined)
+     */
+    private $_template;
+
+    /**
+     * @var string $_selectedTemplate     Template to be applied for active page
+     */
+    private $_selectedTemplate;
+
+    /**
+     * @var string $_separatorTemplate     Separator template, applied between each page
+     */
+    private $_separatorTemplate;
+
+    /**
+     * @var string $_urlMask      URL to be assigned for each page. Masks are used as: {%var_name}
+     */
+    private $_urlMask;
+    
+    /**
+     * @var array $_maskReplacements      Stores references of masks and their correspondent 
+     *                                    (replaces defined masks with new masks or values)
+     */
+    private $_maskReplacements = array();
+
+
+    /**
+     * __construct
+     *
+     * @param Doctrine_Pager $pager     Doctrine_Pager object related to the pager layout
+     * @param Doctrine_Pager_Range $pagerRange     Doctrine_Pager_Range object related to the pager layout
+     * @param string $urlMask     URL to be assigned for each page
+     * @return void
+     */
+    public function __construct($pager, $pagerRange, $urlMask)
+    {
+        $this->_setPager($pager);
+        $this->_setPagerRange($pagerRange);
+        $this->_setUrlMask($urlMask);
+
+        $this->setTemplate('[<a href="{%url}">{%page}</a>]');
+        $this->setSelectedTemplate('');
+        $this->setSeparatorTemplate('');
+    }
+
+
+    /**
+     * getPager
+     *
+     * Returns the Doctrine_Pager object related to the pager layout
+     *
+     * @return Doctrine_Pager        Doctrine_Pager object related to the pager range
+     */
+    public function getPager()
+    {
+        return $this->_pager;
+    }
+
+
+    /**
+     * _setPager
+     *
+     * Defines the Doctrine_Pager object related to the pager layout
+     *
+     * @param $pager       Doctrine_Pager object related to the pager range
+     * @return void
+     */
+    protected function _setPager($pager)
+    {
+        $this->_pager = $pager;
+    }
+
+
+    /**
+     * execute
+     *
+     * Handy method to execute the query without need to retrieve the Pager instance
+     *
+     * @param $params               Optional parameters to Doctrine_Query::execute
+     * @param $hydrationMode        Hydration Mode of Doctrine_Query::execute returned ResultSet.
+     * @return Doctrine_Collection  The root collection
+     */
+    public function execute($params = array(), $hydrationMode = null)
+    {
+        return $this->getPager()->execute($params, $hydrationMode);
+    }
+
+
+    /**
+     * getPagerRange
+     *
+     * Returns the Doctrine_Pager_Range subclass object related to the pager layout
+     *
+     * @return Doctrine_Pager_Range        Doctrine_Pager_Range subclass object related to the pager range
+     */
+    public function getPagerRange()
+    {
+        return $this->_pagerRange;
+    }
+
+
+    /**
+     * _setPagerRange
+     *
+     * Defines the Doctrine_Pager_Range subclass object related to the pager layout
+     *
+     * @param $pagerRange       Doctrine_Pager_Range subclass object related to the pager range
+     * @return void
+     */
+    protected function _setPagerRange($pagerRange)
+    {
+        $this->_pagerRange = $pagerRange;
+        $this->getPagerRange()->setPager($this->getPager());
+    }
+
+
+    /**
+     * getUrlMask
+     *
+     * Returns the URL to be assigned for each page
+     *
+     * @return string        URL to be assigned for each page
+     */
+    public function getUrlMask()
+    {
+        return $this->_urlMask;
+    }
+
+
+    /**
+     * _setUrlMask
+     *
+     * Defines the URL to be assigned for each page
+     *
+     * @param $urlMask       URL to be assigned for each page
+     * @return void
+     */
+    protected function _setUrlMask($urlMask)
+    {
+        $this->_urlMask = $urlMask;
+    }
+
+
+     /**
+     * getTemplate
+     *
+     * Returns the Template to be applied for inactive pages
+     *
+     * @return string        Template to be applied for inactive pages
+     */
+    public function getTemplate()
+    {
+        return $this->_template;
+    }
+
+
+    /**
+     * setTemplate
+     *
+     * Defines the Template to be applied for inactive pages 
+     * (also active page if selected template not defined)
+     *
+     * @param $template       Template to be applied for inactive pages
+     * @return void
+     */
+    public function setTemplate($template)
+    {
+        $this->_template = $template;
+    }
+
+
+    /**
+     * getSelectedTemplate
+     *
+     * Returns the Template to be applied for active page
+     *
+     * @return string        Template to be applied for active page
+     */
+    public function getSelectedTemplate()
+    {
+        return $this->_selectedTemplate;
+    }
+
+
+    /**
+     * setSelectedTemplate
+     *
+     * Defines the Template to be applied for active page
+     *
+     * @param $selectedTemplate       Template to be applied for active page
+     * @return void
+     */
+    public function setSelectedTemplate($selectedTemplate)
+    {
+        $this->_selectedTemplate = $selectedTemplate;
+    }
+
+
+    /**
+     * getSeparatorTemplate
+     *
+     * Returns the Separator template, applied between each page
+     *
+     * @return string        Separator template, applied between each page
+     */
+    public function getSeparatorTemplate()
+    {
+        return $this->_separatorTemplate;
+    }
+
+
+    /**
+     * setSeparatorTemplate
+     *
+     * Defines the Separator template, applied between each page
+     *
+     * @param $separatorTemplate       Separator template, applied between each page
+     * @return void
+     */ 
+    public function setSeparatorTemplate($separatorTemplate)
+    {
+        $this->_separatorTemplate = $separatorTemplate;
+    }
+
+
+    /**
+     * addMaskReplacement
+     *
+     * Defines a mask replacement. When parsing template, it converts replacement
+     * masks into new ones (or values), allowing to change masks behavior on the fly
+     *
+     * @param $oldMask       Mask to be replaced
+     * @param $newMask       Mask or Value that will be defined after replacement
+     * @param $asValue       Optional value (default false) that if defined as true,
+     *                       changes the bahavior of replacement mask to replacement
+     *                       value
+     * @return void
+     */ 
+    public function addMaskReplacement($oldMask, $newMask, $asValue = false)
+    {
+        if (($oldMask = trim($oldMask)) != 'page_number') {
+            $this->_maskReplacements[$oldMask] = array(
+                'newMask' => $newMask,
+                'asValue' => ($asValue === false) ? false : true
+            );
+        }
+    }
+
+
+    /**
+     * removeMaskReplacement
+     *
+     * Remove a mask replacement
+     *
+     * @param $oldMask       Replacement Mask to be removed
+     * @return void
+     */ 
+    public function removeMaskReplacement($oldMask)
+    {
+        if (isset($this->_maskReplacements[$oldMask])) {
+            $this->_maskReplacements[$oldMask] = null;
+            unset($this->_maskReplacements[$oldMask]);
+        }
+    }
+    
+    
+    /**
+     * cleanMaskReplacements
+     *
+     * Remove all mask replacements
+     *
+     * @return void
+     */ 
+    public function cleanMaskReplacements()
+    {
+        $this->_maskReplacements = null;
+        $this->_maskReplacements = array();
+    }
+
+
+    /**
+     * display
+     *
+     * Displays the pager on screen based on templates and options defined
+     *
+     * @param $options    Optional parameters to be applied in template and url mask
+     * @param $return     Optional parameter if you want to capture the output of this method call 
+     *                    (Default value is false), instead of printing it
+     * @return mixed      If you would like to capture the output of Doctrine_Pager_Layout::display(),
+     *                    use the return  parameter. If this parameter is set to TRUE, this method 
+     *                    will return its output, instead of printing it (which it does by default)
+     */
+    public function display($options = array(), $return = false)
+    {
+        $range = $this->getPagerRange()->rangeAroundPage();
+        $str = '';
+
+        // For each page in range
+        for ($i = 0, $l = count($range); $i < $l; $i++) {
+            // Define some optional mask values
+            $options['page_number'] = $range[$i];
+
+            $str .= $this->processPage($options);
+
+            // Apply separator between pages
+            if ($i < $l - 1) {
+                $str .= $this->getSeparatorTemplate();
+            }
+        }
+
+        // Possible wish to return value instead of print it on screen
+        if ($return) {
+            return $str;
+        }
+
+        echo $str;
+    }
+
+
+    /**
+     * processPage
+     *
+     * Parses the template and returns the string of a processed page
+     *
+     * @param array    Optional parameters to be applied in template and url mask
+     * @return string  Processed template for the given page
+     */
+    public function processPage($options = array())
+    {
+        // Check if at least basic options are defined
+        if (!isset($options['page_number'])) {
+            throw new Doctrine_Pager_Exception(
+                'Cannot process template of the given page. ' .
+                'Missing at least one of needed parameters: \'page\' or \'page_number\''
+            );
+
+            // Should never reach here
+            return '';
+        }
+
+        // Assign "page" options index if not defined yet
+        if (!isset($this->_maskReplacements['page']) && !isset($options['page'])) {
+            $options['page'] = $options['page_number'];
+        }
+
+        return $this->_parseTemplate($options);
+    }
+
+
+    /**
+     * Simply calls display, and returns the output.
+     */
+    public function __toString()
+    {
+      return $this->display(array(), true);
+    }
+
+
+    /**
+     * _parseTemplate
+     *
+     * Parse the template of a given page and return the processed template
+     *
+     * @param array    Optional parameters to be applied in template and url mask
+     * @return string  
+     */
+    protected function _parseTemplate($options = array())
+    {
+        $str = $this->_parseUrlTemplate($options);
+        $replacements = $this->_parseReplacementsTemplate($options);
+
+        return strtr($str, $replacements);
+    }
+
+
+    /**
+     * _parseUrlTemplate
+     *
+     * Parse the url mask to return the correct template depending of the options sent.
+     * Already process the mask replacements assigned.
+     *
+     * @param $options    Optional parameters to be applied in template and url mask
+     * @return string
+     */
+    protected function _parseUrlTemplate($options = array())
+    {
+        $str = '';
+
+        // If given page is the current active one
+        if ($options['page_number'] == $this->getPager()->getPage()) {
+            $str = $this->_parseMaskReplacements($this->getSelectedTemplate());
+        }
+
+        // Possible attempt where Selected == Template
+        if ($str == '') {
+            $str = $this->_parseMaskReplacements($this->getTemplate());
+        }
+
+        return $str;
+    }
+
+
+    /**
+     * _parseUrl
+     *
+     * Parse the mask replacements of a given page
+     *
+     * @param $options    Optional parameters to be applied in template and url mask
+     * @return string
+     */
+    protected function _parseReplacementsTemplate($options = array())
+    {
+        // Defining "url" options index to allow {%url} mask
+        $options['url'] = $this->_parseUrl($options);
+
+        $replacements = array();
+
+        foreach ($options as $k => $v) {
+            $replacements['{%'.$k.'}'] = $v;
+        }
+
+        return $replacements;
+    }
+
+
+    /**
+     * _parseUrl
+     *
+     * Parse the url mask of a given page and return the processed url
+     *
+     * @param $options    Optional parameters to be applied in template and url mask
+     * @return string
+     */
+    protected function _parseUrl($options = array())
+    {
+        $str = $this->_parseMaskReplacements($this->getUrlMask());
+
+        $replacements = array();
+
+        foreach ($options as $k => $v) {
+            $replacements['{%'.$k.'}'] = $v;
+        }
+
+        return strtr($str, $replacements);
+    }
+
+
+    /**
+     * _parseMaskReplacements
+     *
+     * Parse the mask replacements, changing from to-be replaced mask with new masks/values
+     *
+     * @param $str    String to have masks replaced
+     * @return string  
+     */
+    protected function _parseMaskReplacements($str)
+    {
+        $replacements = array();
+
+        foreach ($this->_maskReplacements as $k => $v) {
+            $replacements['{%'.$k.'}'] = ($v['asValue'] === true) ? $v['newMask'] : '{%'.$v['newMask'].'}';
+        }
+
+        return strtr($str, $replacements);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Pager/Range.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,176 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Pager_Range
+ *
+ * @author      Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @package     Doctrine
+ * @subpackage  Pager
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       0.9
+ */
+abstract class Doctrine_Pager_Range
+{
+    /**
+     * @var array $_options     Custom Doctrine_Pager_Range implementation options
+     */
+    protected $_options;
+
+    /**
+     * @var Doctrine_Pager $pager     Doctrine_Pager object related to the pager range
+     */
+    private $pager;
+
+
+    /**
+     * __construct
+     *
+     * @param array $options     Custom subclass implementation options.
+     *                           Default is a blank array
+     * @param Doctrine_Pager $pager     Optional Doctrine_Pager object to be associated
+     * @return void
+     */
+    final public function __construct($options = array(), $pager = null)
+    {
+        $this->_setOptions($options);
+
+        if ($pager !== null) {
+            $this->setPager($pager);
+        }
+    }
+
+
+    /**
+     * getPager
+     *
+     * Returns the Doctrine_Pager object related to the pager range
+     *
+     * @return Doctrine_Pager        Doctrine_Pager object related to the pager range
+     */
+    public function getPager()
+    {
+        return $this->pager;
+    }
+
+
+    /**
+     * setPager
+     *
+     * Defines the Doctrine_Pager object related to the pager range and
+     * automatically (re-)initialize Doctrine_Pager_Range
+     *
+     * @param $pager       Doctrine_Pager object related to the pager range
+     * @return void
+     */
+    public function setPager($pager)
+    {
+        $this->pager = $pager;
+
+        // Lazy-load initialization. It only should be called when all
+        // needed information data is ready (this can only happens when we have
+        // options stored and a Doctrine_Pager assocated)
+        $this->_initialize();
+    }
+
+
+    /**
+     * getOptions
+     *
+     * Returns the custom Doctrine_Pager_Range implementation options
+     *
+     * @return array        Custom Doctrine_Pager_Range implementation options
+     */
+    public function getOptions()
+    {
+        return $this->_options;
+    }
+
+
+    /**
+     * getOption
+     *
+     * Returns the custom Doctrine_Pager_Range implementation offset option
+     *
+     * @return array        Custom Doctrine_Pager_Range implementation options
+     */
+    public function getOption($option)
+    {
+        if (isset($this->_options[$option])) {
+            return $this->_options[$option];
+        }
+
+        throw new Doctrine_Pager_Exception(
+            'Cannot access unexistent option \'' . $option . '\' in Doctrine_Pager_Range class'
+        );
+    }
+
+
+    /**
+     * _setOptions
+     *
+     * Defines the subclass implementation options
+     *
+     * @param $options       Custom Doctrine_Pager_Range implementation options
+     * @return void
+     */
+    protected function _setOptions($options)
+    {
+        $this->_options = $options;
+    }
+
+
+    /**
+     * isInRange
+     *
+     * Check if a given page is in the range
+     *
+     * @param $page       Page to be checked
+     * @return boolean
+     */
+    public function isInRange($page)
+    {
+        return (array_search($page, $this->rangeAroundPage()) !== false);
+    }
+
+
+
+    /**
+     * _initialize
+     *
+     * Initialize Doctrine_Page_Range subclass which does custom class definitions
+     *
+     * @return void
+     */
+    abstract protected function _initialize();
+
+
+    /**
+     * rangeAroundPage
+     *
+     * Calculate and returns an array representing the range around the current page
+     *
+     * @return array
+     */
+    abstract public function rangeAroundPage();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Pager/Range/Jumping.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,117 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Pager_Range_Jumping
+ *
+ * @author      Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @package     Doctrine
+ * @subpackage  Pager
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       0.9
+ */
+class Doctrine_Pager_Range_Jumping extends Doctrine_Pager_Range
+{
+    /**
+     * @var int $_chunkLength     Chunk length to be returned
+     */
+    private $_chunkLength;
+
+
+    /**
+     * _initialize
+     *
+     * Initialize Doctrine_Pager_Range_Jumping and does custom assignments
+     *
+     * @return void
+     */
+    protected function _initialize()
+    {
+        if (isset($this->_options['chunk'])) {
+            $this->_setChunkLength($this->_options['chunk']);
+        } else {
+            throw new Doctrine_Pager_Exception('Missing parameter \'chunk\' that must be define in options.');
+        }
+    }
+
+
+    /**
+     * getChunkLength
+     *
+     * Returns the size of the chunk defined
+     *
+     * @return int        Chunk length
+     */
+    public function getChunkLength()
+    {
+        return $this->_chunkLength;
+    }
+
+
+    /**
+     * _setChunkLength
+     *
+     * Defines the size of the chunk
+     *
+     * @param $chunkLength       Chunk length
+     * @return void
+     */
+    protected function _setChunkLength($chunkLength)
+    {
+        $this->_chunkLength = $chunkLength;
+    }
+
+
+    /**
+     * rangeAroundPage
+     *
+     * Calculate and returns an array representing the range around the current page
+     *
+     * @return array
+     */
+    public function rangeAroundPage()
+    {
+        $pager = $this->getPager();
+
+        if ($pager->getExecuted()) {
+            $page = $pager->getPage();
+
+            // Define initial assignments for StartPage and EndPage
+            $startPage = $page - ($page - 1) % $this->getChunkLength();
+            $endPage = ($startPage + $this->getChunkLength()) - 1;
+
+            // Check for EndPage out-range
+            if ($endPage > $pager->getLastPage()) {
+                $endPage = $pager->getLastPage();
+            }
+
+            // No need to check for out-range in start, it will never happens
+
+            return range($startPage, $endPage);
+        }
+
+        throw new Doctrine_Pager_Exception(
+            'Cannot retrieve the range around the page of a not yet executed Pager query'
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Pager/Range/Sliding.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,133 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Pager_Range_Sliding
+ *
+ * @author      Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @package     Doctrine
+ * @subpackage  Pager
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       0.9
+ */
+class Doctrine_Pager_Range_Sliding extends Doctrine_Pager_Range
+{
+    /**
+     * @var int $_chunkLength     Chunk length to be returned
+     */
+    private $_chunkLength;
+
+
+    /**
+     * _initialize
+     *
+     * Initialize Doctrine_Pager_Range_Sliding and does custom assignments
+     *
+     * @return void
+     */
+    protected function _initialize()
+    {
+        if (isset($this->_options['chunk'])) {
+            $this->_setChunkLength($this->_options['chunk']);
+        } else {
+            throw new Doctrine_Pager_Exception('Missing parameter \'chunk\' that must be defined in options.');
+        }
+    }
+
+
+    /**
+     * getChunkLength
+     *
+     * Returns the size of the chunk defined
+     *
+     * @return int        Chunk length
+     */
+    public function getChunkLength()
+    {
+        return $this->_chunkLength;
+    }
+
+
+    /**
+     * _setChunkLength
+     *
+     * Defines the size of the chunk
+     *
+     * @param $chunkLength       Chunk length
+     * @return void
+     */
+    protected function _setChunkLength($chunkLength)
+    {
+        $chunkLength = (int) $chunkLength;
+        if (!$chunkLength) {
+            $chunkLength = 1;
+        } else {
+            $this->_chunkLength = $chunkLength;
+        }
+    }
+
+
+    /**
+     * rangeAroundPage
+     *
+     * Calculate and returns an array representing the range around the current page
+     *
+     * @return array
+     */
+    public function rangeAroundPage()
+    {
+        $pager = $this->getPager();
+
+        if ($pager->getExecuted()) {
+            $page  = $pager->getPage();
+            $pages = $pager->getLastPage();
+
+            $chunk = $this->getChunkLength();
+
+            if ($chunk > $pages) {
+                $chunk = $pages;
+            }
+
+            $chunkStart = $page - (floor($chunk / 2));
+            $chunkEnd   = $page + (ceil($chunk / 2)-1);
+
+            if ($chunkStart < 1) {
+                $adjust = 1 - $chunkStart;
+                $chunkStart = 1;
+                $chunkEnd = $chunkEnd + $adjust;
+            }
+
+            if ($chunkEnd > $pages) {
+                $adjust = $chunkEnd - $pages;
+                $chunkStart = $chunkStart - $adjust;
+                $chunkEnd = $pages;
+            }
+
+            return range($chunkStart, $chunkEnd);
+        }
+
+        throw new Doctrine_Pager_Exception(
+            'Cannot retrieve the range around the page of a not yet executed Pager query'
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,151 @@
+<?php
+/*
+ *  $Id: Parser.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Parser
+ *
+ * @package     Doctrine
+ * @subpackage  Parser
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+abstract class Doctrine_Parser
+{
+    /**
+     * loadData
+     *
+     * Override in the parser driver
+     *
+     * @param string $array 
+     * @return void
+     * @author Jonathan H. Wage
+     */
+    abstract public function loadData($array);
+
+    /**
+     * dumpData
+     *
+     * Override in the praser driver
+     *
+     * @param string $array 
+     * @param string $path 
+     * @return void
+     * @author Jonathan H. Wage
+     */
+    abstract public function dumpData($array, $path = null);
+
+    /**
+     * getParser
+     *
+     * Get instance of the specified parser
+     *
+     * @param string $type 
+     * @return void
+     * @author Jonathan H. Wage
+     */
+    static public function getParser($type)
+    {
+        $class = 'Doctrine_Parser_'.ucfirst($type);
+
+        return new $class;
+    }
+
+    /**
+     * load
+     *
+     * Interface for loading and parsing data from a file
+     *
+     * @param string $path 
+     * @param string $type 
+     * @return void
+     * @author Jonathan H. Wage
+     */
+    static public function load($path, $type = 'xml')
+    {
+        $parser = self::getParser($type);
+
+        return (array) $parser->loadData($path);
+    }
+
+    /**
+     * dump
+     *
+     * Interface for pulling and dumping data to a file
+     *
+     * @param string $array 
+     * @param string $path 
+     * @param string $type 
+     * @return void
+     * @author Jonathan H. Wage
+     */
+    static public function dump($array, $type = 'xml', $path = null)
+    {
+        $parser = self::getParser($type);
+
+        return $parser->dumpData($array, $path);
+    }
+
+    /**
+     * doLoad
+     *
+     * Get contents whether it is the path to a file file or a string of txt.
+     * Either should allow php code in it.
+     *
+     * @param string $path 
+     * @return void
+     */
+    public function doLoad($path)
+    {
+        ob_start();
+        if ( ! file_exists($path)) {
+            $contents = $path;
+            $path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'dparser_' . microtime();
+
+            file_put_contents($path, $contents);
+        }
+
+        include($path);
+
+        // Fix #1569. Need to check if it's still all valid
+        $contents = ob_get_clean(); //iconv("UTF-8", "UTF-8", ob_get_clean());
+
+        return $contents;
+    }
+
+    /**
+     * doDump
+     *
+     * @param string $data 
+     * @param string $path 
+     * @return void
+     */
+    public function doDump($data, $path = null)
+    {
+      if ($path !== null) {
+            return file_put_contents($path, $data);
+        } else {
+            return $data;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 1080 2007-02-10 18:17:08Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Parser_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Parser
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Parser_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Json.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,68 @@
+<?php
+/*
+ *  $Id: Json.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Parser_Json
+ *
+ * @package     Doctrine
+ * @subpackage  Parser
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Parser_Json extends Doctrine_Parser
+{
+    /**
+     * dumpData
+     *
+     * Dump an array of data to a specified path or return
+     * 
+     * @param string $array Array of data to dump to json
+     * @param string $path  Path to dump json data to
+     * @return string $json
+     * @return void
+     */
+    public function dumpData($array, $path = null)
+    {
+        $data = json_encode($array);
+        
+        return $this->doDump($data, $path);
+    }
+
+    /**
+     * loadData
+     *
+     * Load and unserialize data from a file or from passed data
+     * 
+     * @param  string $path   Path to dump data to
+     * @return array  $json   Array of json objects
+     */
+    public function loadData($path)
+    {
+        $contents = $this->doLoad($path);
+        
+        $json = json_decode($contents);
+        
+        return $json;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Serialize.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,65 @@
+<?php
+/*
+ *  $Id: Serialize.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Parser_Serialize
+ *
+ * @package     Doctrine
+ * @subpackage  Parser
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Parser_Serialize extends Doctrine_Parser
+{
+    /**
+     * dumpData
+     *
+     * Dump an array of data to a specified path or return
+     * 
+     * @param string $array 
+     * @param string $path 
+     * @return void
+     */
+    public function dumpData($array, $path = null)
+    {
+        $data = serialize($array);
+        
+        return $this->doDump($data, $path);
+    }
+
+    /**
+     * loadData
+     *
+     * Load and unserialize data from a file or from passed data
+     * 
+     * @param string $path 
+     * @return void
+     */
+    public function loadData($path)
+    {
+        $contents = $this->doLoad($path);
+        
+        return unserialize($contents);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Spyc.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,836 @@
+<?php
+/**
+ * The Simple PHP YAML Class.
+ *
+ * This class can be used to read a YAML file and convert its contents
+ * into a PHP array.  It currently supports a very limited subsection of
+ * the YAML spec.
+ *
+ * Usage:
+ * <code>
+ *   $parser = new Doctrine_Spyc;
+ *   $array  = $parser->load($file);
+ * </code>
+ * @package Doctrine
+ * @subpackage Spyc
+ */
+class Doctrine_Parser_Spyc {
+
+  /**
+   * Load YAML into a PHP array statically
+   *
+   * The load method, when supplied with a YAML stream (string or file),
+   * will do its best to convert YAML in a file into a PHP array.  Pretty
+   * simple.
+   *  Usage:
+   *  <code>
+   *   $array = Doctrine_Spyc::YAMLLoad('lucky.yaml');
+   *   print_r($array);
+   *  </code>
+   * @access public
+   * @return array
+   * @param string $input Path of YAML file or string containing YAML
+   */
+  function YAMLLoad($input) {
+    $spyc = new Doctrine_Spyc;
+    return $spyc->load($input);
+  }
+
+  /**
+   * Dump YAML from PHP array statically
+   *
+   * The dump method, when supplied with an array, will do its best
+   * to convert the array into friendly YAML.  Pretty simple.  Feel free to
+   * save the returned string as nothing.yaml and pass it around.
+   *
+   * Oh, and you can decide how big the indent is and what the wordwrap
+   * for folding is.  Pretty cool -- just pass in 'false' for either if
+   * you want to use the default.
+   *
+   * Indent's default is 2 spaces, wordwrap's default is 40 characters.  And
+   * you can turn off wordwrap by passing in 0.
+   *
+   * @access public
+   * @return string
+   * @param array $array PHP array
+   * @param int $indent Pass in false to use the default, which is 2
+   * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
+   */
+  function YAMLDump($array,$indent = false,$wordwrap = false) {
+    $spyc = new Doctrine_Spyc;
+    return $spyc->dump($array,$indent,$wordwrap);
+  }
+
+  /**
+   * Load YAML into a PHP array from an instantiated object
+   *
+   * The load method, when supplied with a YAML stream (string or file path),
+   * will do its best to convert the YAML into a PHP array.  Pretty simple.
+   *  Usage:
+   *  <code>
+   *   $parser = new Doctrine_Spyc;
+   *   $array  = $parser->load('lucky.yaml');
+   *   print_r($array);
+   *  </code>
+   * @access public
+   * @return array
+   * @param string $input Path of YAML file or string containing YAML
+   */
+  function load($input) {
+    // See what type of input we're talking about
+    // If it's not a file, assume it's a string
+    if ( ! empty($input) && (strpos($input, "\n") === false)
+        && file_exists($input)) {
+      $yaml = file($input);
+    } else {
+      $yaml = explode("\n",$input);
+    }
+    // Initiate some objects and values
+    $base              = new Doctrine_Parser_Spyc_YamlNode (1);
+    $base->indent      = 0;
+    $this->_lastIndent = 0;
+    $this->_lastNode   = $base->id;
+    $this->_inBlock    = false;
+    $this->_isInline   = false;
+    $this->_nodeId     = 2;
+
+    foreach ($yaml as $linenum => $line) {
+      $ifchk = trim($line);
+
+      // If the line starts with a tab (instead of a space), throw a fit.
+      if (preg_match('/^(\t)+(\w+)/', $line)) {
+        $err = 'ERROR: Line '. ($linenum + 1) .' in your input YAML begins'.
+               ' with a tab.  YAML only recognizes spaces.  Please reformat.';
+        die($err);
+      }
+
+      if ($this->_inBlock === false && empty($ifchk)) {
+        continue;
+      } elseif ($this->_inBlock == true && empty($ifchk)) {
+        $last =& $this->_allNodes[$this->_lastNode];
+        $last->data[key($last->data)] .= "\n";
+      } elseif ($ifchk{0} != '#' && substr($ifchk,0,3) != '---') {
+        // Create a new node and get its indent
+        $node         = new Doctrine_Parser_Spyc_YamlNode ($this->_nodeId);
+	  $this->_nodeId++;
+
+        $node->indent = $this->_getIndent($line);
+
+        // Check where the node lies in the hierarchy
+        if ($this->_lastIndent == $node->indent) {
+          // If we're in a block, add the text to the parent's data
+          if ($this->_inBlock === true) {
+            $parent =& $this->_allNodes[$this->_lastNode];
+            $parent->data[key($parent->data)] .= trim($line).$this->_blockEnd;
+          } else {
+            // The current node's parent is the same as the previous node's
+            if (isset($this->_allNodes[$this->_lastNode])) {
+              $node->parent = $this->_allNodes[$this->_lastNode]->parent;
+            }
+          }
+        } elseif ($this->_lastIndent < $node->indent) {
+          if ($this->_inBlock === true) {
+            $parent =& $this->_allNodes[$this->_lastNode];
+            $parent->data[key($parent->data)] .= trim($line).$this->_blockEnd;
+          } elseif ($this->_inBlock === false) {
+            // The current node's parent is the previous node
+            $node->parent = $this->_lastNode;
+
+            // If the value of the last node's data was > or | we need to
+            // start blocking i.e. taking in all lines as a text value until
+            // we drop our indent.
+            $parent =& $this->_allNodes[$node->parent];
+            $this->_allNodes[$node->parent]->children = true;
+            if (is_array($parent->data)) {
+              $chk = '';
+              if (isset ($parent->data[key($parent->data)]))
+                  $chk = $parent->data[key($parent->data)];
+              if ($chk === '>') {
+                $this->_inBlock  = true;
+                $this->_blockEnd = ' ';
+                $parent->data[key($parent->data)] =
+                      str_replace('>','',$parent->data[key($parent->data)]);
+                $parent->data[key($parent->data)] .= trim($line).' ';
+                $this->_allNodes[$node->parent]->children = false;
+                $this->_lastIndent = $node->indent;
+              } elseif ($chk === '|') {
+                $this->_inBlock  = true;
+                $this->_blockEnd = "\n";
+                $parent->data[key($parent->data)] =
+                      str_replace('|','',$parent->data[key($parent->data)]);
+                $parent->data[key($parent->data)] .= trim($line)."\n";
+                $this->_allNodes[$node->parent]->children = false;
+                $this->_lastIndent = $node->indent;
+              }
+            }
+          }
+        } elseif ($this->_lastIndent > $node->indent) {
+          // Any block we had going is dead now
+          if ($this->_inBlock === true) {
+            $this->_inBlock = false;
+            if ($this->_blockEnd = "\n") {
+              $last =& $this->_allNodes[$this->_lastNode];
+              $last->data[key($last->data)] =
+                    trim($last->data[key($last->data)]);
+            }
+          }
+
+          // We don't know the parent of the node so we have to find it
+          // foreach ($this->_allNodes as $n) {
+          foreach ($this->_indentSort[$node->indent] as $n) {
+            if ($n->indent == $node->indent) {
+              $node->parent = $n->parent;
+            }
+          }
+        }
+
+        if ($this->_inBlock === false) {
+          // Set these properties with information from our current node
+          $this->_lastIndent = $node->indent;
+          // Set the last node
+          $this->_lastNode = $node->id;
+          // Parse the YAML line and return its data
+          $node->data = $this->_parseLine($line);
+          // Add the node to the master list
+          $this->_allNodes[$node->id] = $node;
+          // Add a reference to the parent list
+          $this->_allParent[intval($node->parent)][] = $node->id;
+          // Add a reference to the node in an indent array
+          $this->_indentSort[$node->indent][] =& $this->_allNodes[$node->id];
+          // Add a reference to the node in a References array if this node
+          // has a YAML reference in it.
+          if (
+            ( (is_array($node->data)) &&
+              isset($node->data[key($node->data)]) &&
+              ( ! is_array($node->data[key($node->data)])) )
+            &&
+            ( (preg_match('/^&([^ ]+)/',$node->data[key($node->data)]))
+              ||
+              (preg_match('/^\*([^ ]+)/',$node->data[key($node->data)])) )
+          ) {
+              $this->_haveRefs[] =& $this->_allNodes[$node->id];
+          } elseif (
+            ( (is_array($node->data)) &&
+              isset($node->data[key($node->data)]) &&
+               (is_array($node->data[key($node->data)])) )
+          ) {
+            // Incomplete reference making code.  Ugly, needs cleaned up.
+            foreach ($node->data[key($node->data)] as $d) {
+              if ( !is_array($d) &&
+                ( (preg_match('/^&([^ ]+)/',$d))
+                  ||
+                  (preg_match('/^\*([^ ]+)/',$d)) )
+                ) {
+                  $this->_haveRefs[] =& $this->_allNodes[$node->id];
+              }
+            }
+          }
+        }
+      }
+    }
+    unset($node);
+
+    // Here we travel through node-space and pick out references (& and *)
+    $this->_linkReferences();
+
+    // Build the PHP array out of node-space
+    $trunk = $this->_buildArray();
+    return $trunk;
+  }
+
+  /**
+   * Dump PHP array to YAML
+   *
+   * The dump method, when supplied with an array, will do its best
+   * to convert the array into friendly YAML.  Pretty simple.  Feel free to
+   * save the returned string as tasteful.yaml and pass it around.
+   *
+   * Oh, and you can decide how big the indent is and what the wordwrap
+   * for folding is.  Pretty cool -- just pass in 'false' for either if
+   * you want to use the default.
+   *
+   * Indent's default is 2 spaces, wordwrap's default is 40 characters.  And
+   * you can turn off wordwrap by passing in 0.
+   *
+   * @access public
+   * @return string
+   * @param array $array PHP array
+   * @param int $indent Pass in false to use the default, which is 2
+   * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
+   */
+  function dump($array,$indent = false,$wordwrap = false) {
+    // Dumps to some very clean YAML.  We'll have to add some more features
+    // and options soon.  And better support for folding.
+
+    // New features and options.
+    if ($indent === false or !is_numeric($indent)) {
+      $this->_dumpIndent = 2;
+    } else {
+      $this->_dumpIndent = $indent;
+    }
+
+    if ($wordwrap === false or !is_numeric($wordwrap)) {
+      $this->_dumpWordWrap = 40;
+    } else {
+      $this->_dumpWordWrap = $wordwrap;
+    }
+
+    // New YAML document
+    $string = "---\n";
+
+    // Start at the base of the array and move through it.
+    foreach ($array as $key => $value) {
+      $string .= $this->_yamlize($key,$value,0);
+    }
+    return $string;
+  }
+
+  /**** Private Properties ****/
+
+  /**#@+
+   * @access private
+   * @var mixed
+   */
+  var $_haveRefs;
+  var $_allNodes;
+  var $_allParent;
+  var $_lastIndent;
+  var $_lastNode;
+  var $_inBlock;
+  var $_isInline;
+  var $_dumpIndent;
+  var $_dumpWordWrap;
+
+  /**#@+*/
+
+  /**** Public Properties ****/
+
+  /**#@+
+   * @access public
+   * @var mixed
+   */
+  var $_nodeId;
+
+  /**#@+*/
+
+  /**** Private Methods ****/
+
+  /**
+   * Attempts to convert a key / value array item to YAML
+   * @access private
+   * @return string
+   * @param $key The name of the key
+   * @param $value The value of the item
+   * @param $indent The indent of the current node
+   */
+  function _yamlize($key,$value,$indent) {
+    if (is_array($value)) {
+      // It has children.  What to do?
+      // Make it the right kind of item
+      $string = $this->_dumpNode($key,NULL,$indent);
+      // Add the indent
+      $indent += $this->_dumpIndent;
+      // Yamlize the array
+      $string .= $this->_yamlizeArray($value,$indent);
+    } elseif ( ! is_array($value)) {
+      // It doesn't have children.  Yip.
+      $string = $this->_dumpNode($key,$value,$indent);
+    }
+    return $string;
+  }
+
+  /**
+   * Attempts to convert an array to YAML
+   * @access private
+   * @return string
+   * @param $array The array you want to convert
+   * @param $indent The indent of the current level
+   */
+  function _yamlizeArray($array,$indent) {
+    if (is_array($array)) {
+      $string = '';
+      foreach ($array as $key => $value) {
+        $string .= $this->_yamlize($key,$value,$indent);
+      }
+      return $string;
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * Returns YAML from a key and a value
+   * @access private
+   * @return string
+   * @param $key The name of the key
+   * @param $value The value of the item
+   * @param $indent The indent of the current node
+   */
+  function _dumpNode($key,$value,$indent) {
+    // do some folding here, for blocks
+    if (strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false) {
+      $value = $this->_doLiteralBlock($value,$indent);
+    } else {
+      $value  = $this->_doFolding($value,$indent);
+    }
+
+    if (is_bool($value)) {
+      $value = ($value) ? "true" : "false";
+    }
+
+    $spaces = str_repeat(' ',$indent);
+
+    if (is_int($key)) {
+      // It's a sequence
+      $string = $spaces.'- '.$value."\n";
+    } else {
+      // It's mapped
+      $string = $spaces.$key.': '.$value."\n";
+    }
+    return $string;
+  }
+
+  /**
+   * Creates a literal block for dumping
+   * @access private
+   * @return string
+   * @param $value
+   * @param $indent int The value of the indent
+   */
+  function _doLiteralBlock($value,$indent) {
+    $exploded = explode("\n",$value);
+    $newValue = '|';
+    $indent  += $this->_dumpIndent;
+    $spaces   = str_repeat(' ',$indent);
+    foreach ($exploded as $line) {
+      $newValue .= "\n" . $spaces . trim($line);
+    }
+    return $newValue;
+  }
+
+  /**
+   * Folds a string of text, if necessary
+   * @access private
+   * @return string
+   * @param $value The string you wish to fold
+   */
+  function _doFolding($value,$indent) {
+    // Don't do anything if wordwrap is set to 0
+    if ($this->_dumpWordWrap === 0) {
+      return $value;
+    }
+
+    if (strlen($value) > $this->_dumpWordWrap) {
+      $indent += $this->_dumpIndent;
+      $indent = str_repeat(' ',$indent);
+      $wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent");
+      $value   = ">\n".$indent.$wrapped;
+    }
+    return $value;
+  }
+
+  /* Methods used in loading */
+
+  /**
+   * Finds and returns the indentation of a YAML line
+   * @access private
+   * @return int
+   * @param string $line A line from the YAML file
+   */
+  function _getIndent($line) {
+    preg_match('/^\s{1,}/',$line,$match);
+    if ( ! empty($match[0])) {
+      $indent = substr_count($match[0],' ');
+    } else {
+      $indent = 0;
+    }
+    return $indent;
+  }
+
+  /**
+   * Parses YAML code and returns an array for a node
+   * @access private
+   * @return array
+   * @param string $line A line from the YAML file
+   */
+  function _parseLine($line) {
+    $line = trim($line);
+
+    if(!preg_match("/\\\#/", $line)) { 
+      $line = trim(preg_replace('/#.*$/', '', $line)); 
+    }
+
+    $array = array();
+
+    if (preg_match('/^-(.*):$/',$line)) {
+      // It's a mapped sequence
+      $key         = trim(substr(substr($line,1),0,-1));
+      $array[$key] = '';
+    } elseif ($line[0] == '-' && substr($line,0,3) != '---') {
+      // It's a list item but not a new stream
+      if (strlen($line) > 1) {
+        $value   = trim(substr($line,1));
+        // Set the type of the value.  Int, string, etc
+        $value   = $this->_toType($value);
+        $array[] = $value;
+      } else {
+        $array[] = array();
+      }
+    } elseif (preg_match('/^(.+):/',$line,$key)) {
+      // It's a key/value pair most likely
+      // If the key is in double quotes pull it out
+      if (preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) {
+        $value = trim(str_replace($matches[1],'',$line));
+        $key   = $matches[2];
+      } else {
+        // Do some guesswork as to the key and the value
+        $explode = explode(':',$line);
+        $key     = trim($explode[0]);
+        array_shift($explode);
+        $value   = trim(implode(':',$explode));
+      }
+
+      // Set the type of the value.  Int, string, etc
+      $value = $this->_toType($value);
+      if (empty($key)) {
+        $array[]     = $value;
+      } else {
+        $array[$key] = $value;
+      }
+    }
+    return $array;
+  }
+
+  /**
+   * Finds the type of the passed value, returns the value as the new type.
+   * @access private
+   * @param string $value
+   * @return mixed
+   */
+  function _toType($value) {
+    if (preg_match('/^("(.*)"|\'(.*)\')/',$value,$matches)) {
+     $value = (string)preg_replace('/(\'\'|\\\\\')/',"'",end($matches));
+     $value = preg_replace('/\\\\"/','"',$value);
+    } elseif (preg_match('/^\\[(.*)\\]$/',$value,$matches)) {
+      // Inline Sequence
+
+      // Take out strings sequences and mappings
+      $explode = empty($matches[1]) ? array() : $this->_inlineEscape($matches[1]);
+
+      // Propogate value array
+      $value  = array();
+      foreach ($explode as $v) {
+        $value[] = $this->_toType($v);
+      }
+    } elseif (strpos($value,': ')!==false && !preg_match('/^{(.+)/',$value)) {
+        // It's a map
+        $array = explode(': ',$value);
+        $key   = trim($array[0]);
+        array_shift($array);
+        $value = trim(implode(': ',$array));
+        $value = $this->_toType($value);
+        $value = array($key => $value);
+    } elseif (preg_match("/{(.+)}$/",$value,$matches)) {
+      // Inline Mapping
+
+      // Take out strings sequences and mappings
+      $explode = $this->_inlineEscape($matches[1]);
+
+      // Propogate value array
+      $array = array();
+      foreach ($explode as $v) {
+        $array = $array + $this->_toType($v);
+      }
+      $value = $array;
+    } elseif (strtolower($value) == 'null' or $value == '' or $value == '~') {
+      $value = NULL;
+    } elseif (preg_match ('/^[0-9]+$/', $value)) {
+      // Cheeky change for compartibility with PHP < 4.2.0
+      $raw = $value;
+      $value = (int) $value;
+
+      if ((string) $value != (string) $raw) {
+          $value = (string) $raw;
+      }
+    } elseif (in_array(strtolower($value),
+                array('true', 'on', '+', 'yes', 'y'))) {
+      $value = true;
+    } elseif (in_array(strtolower($value),
+                array('false', 'off', '-', 'no', 'n'))) {
+      $value = false;
+    } elseif (is_numeric($value)) {
+      $raw = $value;
+      $value = (float) $value;
+
+      if ((string) $value != (string) $raw) {
+          $value = (string) $raw;
+      }
+    } else {
+      // Just a normal string, right?
+      $value = trim(preg_replace('/#(.+)$/','',$value));
+    }
+
+    return $value;
+  }
+
+  /**
+   * Used in inlines to check for more inlines or quoted strings
+   * @access private
+   * @return array
+   */
+  function _inlineEscape($inline) {
+    // There's gotta be a cleaner way to do this...
+    // While pure sequences seem to be nesting just fine,
+    // pure mappings and mappings with sequences inside can't go very
+    // deep.  This needs to be fixed.
+
+    $saved_strings = array();
+
+    // Check for strings
+    $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/';
+    if (preg_match_all($regex,$inline,$strings)) {
+      $saved_strings = $strings[0];
+      $inline  = preg_replace($regex,'YAMLString',$inline);
+    }
+    unset($regex);
+
+    // Check for sequences
+    if (preg_match_all('/\[(.+)\]/U',$inline,$seqs)) {
+      $inline = preg_replace('/\[(.+)\]/U','YAMLSeq',$inline);
+      $seqs   = $seqs[0];
+    }
+
+    // Check for mappings
+    if (preg_match_all('/{(.+)}/U',$inline,$maps)) {
+      $inline = preg_replace('/{(.+)}/U','YAMLMap',$inline);
+      $maps   = $maps[0];
+    }
+
+    $explode = explode(', ',$inline);
+
+
+    // Re-add the sequences
+    if ( ! empty($seqs)) {
+      $i = 0;
+      foreach ($explode as $key => $value) {
+        if (strpos($value,'YAMLSeq') !== false) {
+          $explode[$key] = str_replace('YAMLSeq',$seqs[$i],$value);
+          ++$i;
+        }
+      }
+    }
+
+    // Re-add the mappings
+    if ( ! empty($maps)) {
+      $i = 0;
+      foreach ($explode as $key => $value) {
+        if (strpos($value,'YAMLMap') !== false) {
+          $explode[$key] = str_replace('YAMLMap',$maps[$i],$value);
+          ++$i;
+        }
+      }
+    }
+
+    // Re-add the strings
+    if ( ! empty($saved_strings)) {
+      $i = 0;
+      foreach ($explode as $key => $value) {
+        while (strpos($value,'YAMLString') !== false) {
+          $explode[$key] = preg_replace('/YAMLString/',$saved_strings[$i],$value, 1);
+          ++$i;
+          $value = $explode[$key];
+        }
+      }
+    }
+
+    return $explode;
+  }
+
+  /**
+   * Builds the PHP array from all the YAML nodes we've gathered
+   * @access private
+   * @return array
+   */
+  function _buildArray() {
+    $trunk = array();
+
+    if ( ! isset($this->_indentSort[0])) {
+      return $trunk;
+    }
+
+    foreach ($this->_indentSort[0] as $n) {
+      if (empty($n->parent)) {
+        $this->_nodeArrayizeData($n);
+        // Check for references and copy the needed data to complete them.
+        $this->_makeReferences($n);
+        // Merge our data with the big array we're building
+        $trunk = $this->_array_kmerge($trunk,$n->data);
+      }
+    }
+
+    return $trunk;
+  }
+
+  /**
+   * Traverses node-space and sets references (& and *) accordingly
+   * @access private
+   * @return bool
+   */
+  function _linkReferences() {
+    if (is_array($this->_haveRefs)) {
+      foreach ($this->_haveRefs as $node) {
+        if ( ! empty($node->data)) {
+          $key = key($node->data);
+          // If it's an array, don't check.
+          if (is_array($node->data[$key])) {
+            foreach ($node->data[$key] as $k => $v) {
+              $this->_linkRef($node,$key,$k,$v);
+            }
+          } else {
+            $this->_linkRef($node,$key);
+          }
+        }
+      }
+    }
+    return true;
+  }
+
+  function _linkRef(&$n,$key,$k = NULL,$v = NULL) {
+    if (empty($k) && empty($v)) {
+      // Look for &refs
+      if (preg_match('/^&([^ ]+)/',$n->data[$key],$matches)) {
+        // Flag the node so we know it's a reference
+        $this->_allNodes[$n->id]->ref = substr($matches[0],1);
+        $this->_allNodes[$n->id]->data[$key] =
+                 substr($n->data[$key],strlen($matches[0])+1);
+      // Look for *refs
+      } elseif (preg_match('/^\*([^ ]+)/',$n->data[$key],$matches)) {
+        $ref = substr($matches[0],1);
+        // Flag the node as having a reference
+        $this->_allNodes[$n->id]->refKey =  $ref;
+      }
+    } elseif ( ! empty($k) && !empty($v)) {
+      if (preg_match('/^&([^ ]+)/',$v,$matches)) {
+        // Flag the node so we know it's a reference
+        $this->_allNodes[$n->id]->ref = substr($matches[0],1);
+        $this->_allNodes[$n->id]->data[$key][$k] =
+                            substr($v,strlen($matches[0])+1);
+      // Look for *refs
+      } elseif (preg_match('/^\*([^ ]+)/',$v,$matches)) {
+        $ref = substr($matches[0],1);
+        // Flag the node as having a reference
+        $this->_allNodes[$n->id]->refKey =  $ref;
+      }
+    }
+  }
+
+  /**
+   * Finds the children of a node and aids in the building of the PHP array
+   * @access private
+   * @param int $nid The id of the node whose children we're gathering
+   * @return array
+   */
+  function _gatherChildren($nid) {
+    $return = array();
+    $node   =& $this->_allNodes[$nid];
+    if (is_array ($this->_allParent[$node->id])) {
+      foreach ($this->_allParent[$node->id] as $nodeZ) {
+        $z =& $this->_allNodes[$nodeZ];
+        // We found a child
+        $this->_nodeArrayizeData($z);
+        // Check for references
+        $this->_makeReferences($z);
+        // Merge with the big array we're returning
+        // The big array being all the data of the children of our parent node
+        $return = $this->_array_kmerge($return,$z->data);
+      }
+    }
+    return $return;
+  }
+
+  /**
+   * Turns a node's data and its children's data into a PHP array
+   *
+   * @access private
+   * @param array $node The node which you want to arrayize
+   * @return boolean
+   */
+  function _nodeArrayizeData(&$node) {
+    if (is_array($node->data) && $node->children == true) {
+      // This node has children, so we need to find them
+      $childs = $this->_gatherChildren($node->id);
+      // We've gathered all our children's data and are ready to use it
+      $key = key($node->data);
+      $key = empty($key) ? 0 : $key;
+      // If it's an array, add to it of course
+      if (isset ($node->data[$key])) {
+          if (is_array($node->data[$key])) {
+            $node->data[$key] = $this->_array_kmerge($node->data[$key],$childs);
+          } else {
+            $node->data[$key] = $childs;
+          }
+      } else {
+          $node->data[$key] = $childs;
+      }
+    } elseif ( ! is_array($node->data) && $node->children == true) {
+      // Same as above, find the children of this node
+      $childs       = $this->_gatherChildren($node->id);
+      $node->data   = array();
+      $node->data[] = $childs;
+    }
+
+    // We edited $node by reference, so just return true
+    return true;
+  }
+
+  /**
+   * Traverses node-space and copies references to / from this object.
+   * @access private
+   * @param object $z A node whose references we wish to make real
+   * @return bool
+   */
+  function _makeReferences(&$z) {
+    // It is a reference
+    if (isset($z->ref)) {
+      $key                = key($z->data);
+      // Copy the data to this object for easy retrieval later
+      $this->ref[$z->ref] =& $z->data[$key];
+    // It has a reference
+    } elseif (isset($z->refKey)) {
+      if (isset($this->ref[$z->refKey])) {
+        $key           = key($z->data);
+        // Copy the data from this object to make the node a real reference
+        $z->data[$key] =& $this->ref[$z->refKey];
+      }
+    }
+    return true;
+  }
+
+
+  /**
+   * Merges arrays and maintains numeric keys.
+   *
+   * An ever-so-slightly modified version of the array_kmerge() function posted
+   * to php.net by mail at nospam dot iaindooley dot com on 2004-04-08.
+   *
+   * http://us3.php.net/manual/en/function.array-merge.php#41394
+   *
+   * @access private
+   * @param array $arr1
+   * @param array $arr2
+   * @return array
+   */
+  function _array_kmerge($arr1,$arr2) {
+    if( ! is_array($arr1)) $arr1 = array();
+    if( ! is_array($arr2)) $arr2 = array();
+
+    $keys  = array_merge(array_keys($arr1),array_keys($arr2));
+    $vals  = array_merge(array_values($arr1),array_values($arr2));
+    $ret   = array();
+    foreach($keys as $key) {
+      list($unused,$val) = each($vals);
+      if (isset($ret[$key]) and is_int($key)) $ret[] = $val; else $ret[$key] = $val;
+    }
+    return $ret;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Spyc/YamlNode.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,56 @@
+<?php
+/**
+* Spyc -- A Simple PHP YAML Class
+* @version 0.2.(5) -- 2006-12-31
+* @author Chris Wanstrath <chris@ozmm.org>
+* @author Vlad Andersen <vlad@oneiros.ru>
+* @link http://spyc.sourceforge.net/
+* @copyright Copyright 2005-2006 Chris Wanstrath
+* @license http://www.opensource.org/licenses/mit-license.php MIT License
+* @package Doctrine
+* @subpackage Spyc
+*/
+
+/**
+* A node, used by Doctrine_Parser_Spyc for parsing YAML.
+* @package Doctrine
+* @subpackage Spyc
+*/
+class Doctrine_Parser_Spyc_YamlNode
+{
+    /**#@+
+     * @access public
+     * @var string
+     */
+    var $parent;
+    var $id;
+
+    /**#@+*/
+    /**
+     * @access public
+     * @var mixed
+     */
+    var $data;
+
+    /**
+     * @access public
+     * @var int
+     */
+    var $indent;
+
+    /**
+     * @access public
+     * @var bool
+     */
+    var $children = false;
+
+    /**
+     * The constructor assigns the node a unique ID.
+     * @access public
+     * @return void
+     */
+    function __construct($nodeId)
+    {
+      $this->id = $nodeId;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Xml.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,142 @@
+<?php
+/*
+ *  $Id: Xml.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Parser_Xml
+ *
+ * @package     Doctrine
+ * @subpackage  Parser
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Parser_Xml extends Doctrine_Parser
+{
+    /**
+     * dumpData
+     * 
+     * Convert array to xml and dump to specified path or return the xml
+     *
+     * @param  string $array Array of data to convert to xml
+     * @param  string $path  Path to write xml data to
+     * @return string $xml
+     * @return void
+     */
+    public function dumpData($array, $path = null)
+    {
+        $data = $this->arrayToXml($array);
+        
+        return $this->doDump($data, $path);
+    }
+
+    /**
+     * arrayToXml
+     *
+     * @param  string $array        Array to convert to xml    
+     * @param  string $rootNodeName Name of the root node
+     * @param  string $xml          SimpleXmlElement
+     * @return string $asXml        String of xml built from array
+     */
+    public function arrayToXml($array, $rootNodeName = 'data', $xml = null)
+    {
+        if ($xml === null) {
+            $xml = new SimpleXmlElement("<?xml version=\"1.0\" encoding=\"utf-8\"?><$rootNodeName/>");
+        }
+
+        foreach($array as $key => $value)
+        {
+            if (is_array($value)) {
+                $node = $xml->addChild($key);
+
+                $this->arrayToXml($value, $rootNodeName, $node);
+            } else if (is_int($key)) {               
+                $xml->addChild($value, 'true');
+            } else {
+                $value = htmlentities($value);
+
+                $xml->addChild($key, $value);
+            }
+        }
+
+        return $xml->asXML();
+    }
+
+    /**
+     * loadData
+     *
+     * Load xml file and return array of data
+     *
+     * @param  string $path  Path to load xml data from
+     * @return array  $array Array of data converted from xml
+     */
+    public function loadData($path)
+    {
+        $contents = $this->doLoad($path);
+        
+        $simpleXml = simplexml_load_string($contents);
+        
+        return $this->prepareData($simpleXml);
+    }
+
+    /**
+     * prepareData
+     *
+     * Prepare simple xml to array for return
+     *
+     * @param  string $simpleXml 
+     * @return array  $return
+     */
+    public function prepareData($simpleXml)
+    {
+        if ($simpleXml instanceof SimpleXMLElement) {
+            $children = $simpleXml->children();
+            $return = null;
+        }
+
+        foreach ($children as $element => $value) {
+            if ($value instanceof SimpleXMLElement) {
+                $values = (array) $value->children();
+
+                if (count($values) > 0) {
+                    $return[$element] = $this->prepareData($value);
+                } else {
+                    if ( ! isset($return[$element])) {
+                        $return[$element] = (string) $value;
+                    } else {
+                        if ( ! is_array($return[$element])) {
+                            $return[$element] = array($return[$element], (string) $value);
+                        } else {
+                            $return[$element][] = (string) $value;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (is_array($return)) {
+            return $return;
+        } else {
+            return array();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/YamlSf.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,98 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * YamlSf class.
+ *
+ * @package    symfony
+ * @subpackage util
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: YamlSf.class.php 8988 2008-05-15 20:24:26Z fabien $
+ */
+class Doctrine_Parser_YamlSf
+{
+  /**
+   * Load YAML into a PHP array statically
+   *
+   * The load method, when supplied with a YAML stream (string or file),
+   * will do its best to convert YAML in a file into a PHP array.
+   *
+   *  Usage:
+   *  <code>
+   *   $array = sfYAML::Load('config.yml');
+   *   print_r($array);
+   *  </code>
+   *
+   * @param string $input Path of YAML file or string containing YAML
+   *
+   * @return array
+   */
+  public static function load($input)
+  {
+    $file = '';
+
+    // if input is a file, process it
+    if (strpos($input, "\n") === false && is_file($input))
+    {
+      $file = $input;
+
+      ob_start();
+      $retval = include($input);
+      $content = ob_get_clean();
+
+      // if an array is returned by the config file assume it's in plain php form else in yaml
+      $input = is_array($retval) ? $retval : $content;
+    }
+
+    // if an array is returned by the config file assume it's in plain php form else in yaml
+    if (is_array($input))
+    {
+      return $input;
+    }
+
+    /* removed since it now use the doctrine autoload feature
+     * require_once dirname(__FILE__).'/Doctrine_Parser_YamlSf_Parser.class.php';
+     */
+
+    $yaml = new Doctrine_Parser_YamlSf_Parser();
+
+    try
+    {
+      $ret = $yaml->parse($input);
+    }
+    catch (Exception $e)
+    {
+      throw new InvalidArgumentException(sprintf('Unable to parse %s: %s', $file ? sprintf('file "%s"', $file) : 'string', $e->getMessage()));
+    }
+
+    return $ret;
+  }
+
+  /**
+   * Dump YAML from PHP array statically
+   *
+   * The dump method, when supplied with an array, will do its best
+   * to convert the array into friendly YAML.
+   *
+   * @param array $array PHP array
+   *
+   * @return string
+   */
+  public static function dump($array, $inline = 4)
+  {
+    /* removed since it now use the doctrine autoload feature
+     * require_once dirname(__FILE__).'/Doctrine_Parser_YamlSf_Dumper.class.php';
+     */
+
+    $yaml = new Doctrine_Parser_YamlSf_Dumper();
+
+    return $yaml->dump($array, $inline);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/YamlSf/Dumper.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,62 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/* removed since it now use the doctrine autoload feature
+ * require_once(dirname(__FILE__).'/Yml_Inline.class.php');
+ */
+
+/**
+ * YamlSfDumper class.
+ *
+ * @package    symfony
+ * @subpackage util
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: YamlSfDumper.class.php 8488 2008-04-16 22:20:29Z fabien $
+ */
+class Doctrine_Parser_YamlSf_Dumper
+{
+  /**
+   * Dumps a PHP value to YAML.
+   *
+   * @param  mixed   The PHP value
+   * @param  integer The level where you switch to inline YAML
+   * @param  integer The level o indentation indentation (used internally)
+   *
+   * @return string  The YAML representation of the PHP value
+   */
+  public function dump($input, $inline = 0, $indent = 0)
+  {
+    $output = '';
+    $prefix = $indent ? str_repeat(' ', $indent) : '';
+
+    if ($inline <= 0 || !is_array($input) || empty($input))
+    {
+      $output .= $prefix.Doctrine_Parser_YamlSf_Inline::dump($input);
+    }
+    else
+    {
+      $isAHash = count(array_diff_key($input, array_fill(0, count($input), true)));
+
+      foreach ($input as $key => $value)
+      {
+        $willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value);
+
+        $output .= sprintf('%s%s%s%s',
+          $prefix,
+          $isAHash ? Doctrine_Parser_YamlSf_Inline::dump($key).':' : '-',
+          $willBeInlined ? ' ' : "\n",
+          $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + 2)
+        ).($willBeInlined ? "\n" : '');
+      }
+    }
+
+    return $output;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/YamlSf/Inline.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,415 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * YamlSfInline implements a YAML parser/dumper for the YAML inline syntax.
+ *
+ * @package    symfony
+ * @subpackage util
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: YamlSfInline.class.php 9186 2008-05-22 15:19:18Z FabianLange $
+ */
+class Doctrine_Parser_YamlSf_Inline
+{
+  /**
+   * Load YAML into a PHP array.
+   *
+   * @param string YAML
+   *
+   * @return array PHP array
+   */
+  static public function load($value)
+  {
+    $value = trim($value);
+
+    if (0 == strlen($value))
+    {
+      return '';
+    }
+
+    switch ($value[0])
+    {
+      case '[':
+        return self::parseSequence($value);
+      case '{':
+        return self::parseMapping($value);
+      default:
+        return self::parseScalar($value);
+    }
+  }
+
+  /**
+   * Dumps PHP array to YAML.
+   *
+   * @param mixed   PHP
+   *
+   * @return string YAML
+   */
+  static public function dump($value)
+  {
+    switch (true)
+    {
+      case is_resource($value):
+        throw new InvalidArgumentException('Unable to dump PHP resources in a YAML file.');
+      case is_object($value):
+        return '!!php/object:'.serialize($value);
+      case is_array($value):
+        return self::dumpArray($value);
+      case is_null($value):
+        return 'null';
+      case true === $value:
+        return 'true';
+      case false === $value:
+        return 'false';
+      case ctype_digit($value):
+        return is_string($value) ? "'$value'" : (int) $value;
+      case is_numeric($value):
+        return is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : (is_string($value) ? "'$value'" : $value);
+      case false !== strpos($value, "\n"):
+        return sprintf('"%s"', str_replace(array('"', "\n", "\r"), array('\\"', '\n', ''), $value));
+      case preg_match('/[ \s \' " \: \{ \} \[ \] , & \*]/x', $value):
+        return sprintf("'%s'", str_replace('\'', '\'\'', $value));
+      case '' == $value:
+        return "''";
+      case preg_match(self::getTimestampRegex(), $value):
+        return "'$value'";
+      case in_array(strtolower($value), array('true', 'on', '+', 'yes', 'y')):
+        return "'$value'";
+      case in_array(strtolower($value), array('false', 'off', '-', 'no', 'n')):
+        return "'$value'";
+      default:
+        return $value;
+    }
+  }
+
+  /**
+   * Dumps PHP array to YAML
+   *
+   * @param array   The array to dump
+   *
+   * @return string YAML
+   */
+  static protected function dumpArray($value)
+  {
+    // array
+    $keys = array_keys($value);
+    if (
+      (1 == count($keys) && '0' == $keys[0])
+      ||
+      (count($keys) > 1 && array_reduce($keys, create_function('$v,$w', 'return (integer) $v + $w;'), 0) == count($keys) * (count($keys) - 1) / 2))
+    {
+      $output = array();
+      foreach ($value as $val)
+      {
+        $output[] = self::dump($val);
+      }
+
+      return sprintf('[%s]', implode(', ', $output));
+    }
+
+    // mapping
+    $output = array();
+    foreach ($value as $key => $val)
+    {
+      $output[] = sprintf('%s: %s', self::dump($key), self::dump($val));
+    }
+
+    return sprintf('{ %s }', implode(', ', $output));
+  }
+
+  /**
+   * Parses scalar to yaml
+   *
+   * @param scalar $scalar
+   * @param string $delimiters
+   * @param array  String delimiter
+   * @param integer $i
+   * @param boolean $evaluate
+   *
+   * @return string YAML
+   */
+  static public function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true)
+  {
+    if (in_array($scalar[$i], $stringDelimiters))
+    {
+      // quoted scalar
+      $output = self::parseQuotedScalar($scalar, $i);
+
+      // skip next delimiter
+      ++$i;
+    }
+    else
+    {
+      // "normal" string
+      if (!$delimiters)
+      {
+        $output = substr($scalar, $i);
+        $i += strlen($output);
+
+        // remove comments
+        if (false !== $strpos = strpos($output, ' #'))
+        {
+          $output = rtrim(substr($output, 0, $strpos));
+        }
+      }
+      else if (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match))
+      {
+        $output = $match[1];
+        $i += strlen($output);
+      }
+      else
+      {
+        throw new InvalidArgumentException(sprintf('Malformed inline YAML string (%s).', $scalar));
+      }
+
+      $output = $evaluate ? self::evaluateScalar($output) : $output;
+    }
+
+    return $output;
+  }
+
+  /**
+   * Parses quotes scalar
+   *
+   * @param string $scalar
+   * @param integer $i
+   *
+   * @return string YAML
+   */
+  static protected function parseQuotedScalar($scalar, &$i)
+  {
+    $delimiter = $scalar[$i];
+    ++$i;
+    $buffer = '';
+    $len = strlen($scalar);
+    $escaped = '"' == $delimiter ? '\\"' : "''";
+
+    while ($i < $len)
+    {
+      if (isset($scalar[$i + 1]) && $escaped == $scalar[$i].$scalar[$i + 1])
+      {
+        $buffer .= $delimiter;
+        ++$i;
+      }
+      else if ($delimiter == $scalar[$i])
+      {
+        break;
+      }
+      else
+      {
+        $buffer .= $scalar[$i];
+      }
+
+      ++$i;
+    }
+
+    if ('"' == $delimiter)
+    {
+      // evaluate the string
+      $buffer = str_replace('\\n', "\n", $buffer);
+    }
+
+    return $buffer;
+  }
+
+  /**
+   * Parse sequence to yaml
+   *
+   * @param string $sequence
+   * @param integer $i
+   *
+   * @return string YAML
+   */
+  static protected function parseSequence($sequence, &$i = 0)
+  {
+    $output = array();
+    $len = strlen($sequence);
+    $i += 1;
+
+    // [foo, bar, ...]
+    while ($i < $len)
+    {
+      switch ($sequence[$i])
+      {
+        case '[':
+          // nested sequence
+          $output[] = self::parseSequence($sequence, $i);
+          break;
+        case '{':
+          // nested mapping
+          $output[] = self::parseMapping($sequence, $i);
+          break;
+        case ']':
+          return $output;
+        case ',':
+        case ' ':
+          break;
+        default:
+          $isQuoted = in_array($sequence[$i], array('"', "'"));
+          $value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i);
+
+          if (!$isQuoted && false !== strpos($value, ': '))
+          {
+            // embedded mapping?
+            try
+            {
+              $value = self::parseMapping('{'.$value.'}');
+            }
+            catch (InvalidArgumentException $e)
+            {
+              // no, it's not
+            }
+          }
+
+          $output[] = $value;
+
+          --$i;
+      }
+
+      ++$i;
+    }
+
+    throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $sequence));
+  }
+
+  /**
+   * Parses mapping.
+   *
+   * @param string $mapping
+   * @param integer $i
+   *
+   * @return string YAML
+   */
+  static protected function parseMapping($mapping, &$i = 0)
+  {
+    $output = array();
+    $len = strlen($mapping);
+    $i += 1;
+
+    // {foo: bar, bar:foo, ...}
+    while ($i < $len)
+    {
+      switch ($mapping[$i])
+      {
+        case ' ':
+        case ',':
+          ++$i;
+          continue 2;
+        case '}':
+          return $output;
+      }
+
+      // key
+      $key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false);
+
+      // value
+      $done = false;
+      while ($i < $len)
+      {
+        switch ($mapping[$i])
+        {
+          case '[':
+            // nested sequence
+            $output[$key] = self::parseSequence($mapping, $i);
+            $done = true;
+            break;
+          case '{':
+            // nested mapping
+            $output[$key] = self::parseMapping($mapping, $i);
+            $done = true;
+            break;
+          case ':':
+          case ' ':
+            break;
+          default:
+            $output[$key] = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i);
+            $done = true;
+            --$i;
+        }
+
+        ++$i;
+
+        if ($done)
+        {
+          continue 2;
+        }
+      }
+    }
+
+    throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $mapping));
+  }
+
+  /**
+   * Evaluates scalars and replaces magic values.
+   *
+   * @param string $scalar
+   *
+   * @return string YAML
+   */
+  static protected function evaluateScalar($scalar)
+  {
+    $scalar = trim($scalar);
+
+    switch (true)
+    {
+      case 'null' == strtolower($scalar):
+      case '' == $scalar:
+      case '~' == $scalar:
+        return null;
+      case 0 === strpos($scalar, '!str'):
+        return (string) substr($scalar, 5);
+      case 0 === strpos($scalar, '! '):
+        return intval(self::parseScalar(substr($scalar, 2)));
+      case 0 === strpos($scalar, '!!php/object:'):
+        return unserialize(substr($scalar, 13));
+      case ctype_digit($scalar):
+        $raw = $scalar;
+        $cast = intval($scalar);
+
+        return '0' == $scalar[0]
+          ? octdec($scalar) : (((string) $raw == (string) $cast) ? strval($cast) : $raw);
+      case in_array(strtolower($scalar), array('true', 'on', '+', 'yes', 'y')):
+        return true;
+      case in_array(strtolower($scalar), array('false', 'off', '-', 'no', 'n')):
+        return false;
+      case is_numeric($scalar):
+        return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar);
+      case 0 == strcasecmp($scalar, '.inf'):
+      case 0 == strcasecmp($scalar, '.NaN'):
+        return -log(0);
+      case 0 == strcasecmp($scalar, '-.inf'):
+        return log(0);
+      case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
+        return floatval(str_replace(',', '', $scalar));
+      case preg_match(self::getTimestampRegex(), $scalar):
+        return strtotime($scalar);
+      default:
+        return (string) $scalar;
+    }
+  }
+
+  static protected function getTimestampRegex()
+  {
+    return <<<EOF
+    ~^
+    (?P<year>[0-9][0-9][0-9][0-9])
+    -(?P<month>[0-9][0-9]?)
+    -(?P<day>[0-9][0-9]?)
+    (?:(?:[Tt]|[ \t]+)
+    (?P<hour>[0-9][0-9]?)
+    :(?P<minute>[0-9][0-9])
+    :(?P<second>[0-9][0-9])
+    (?:\.(?P<fraction>[0-9]*))?
+    (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
+    (?::(?P<tz_minute>[0-9][0-9]))?))?)?
+    $~x
+EOF;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/YamlSf/Parser.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,482 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/* removed since it now use the doctrine autoload feature
+ * require_once(dirname(__FILE__).'/Yml_Inline.class.php');
+ */
+
+/**
+ * YamlSfParser class.
+ *
+ * @package    symfony
+ * @subpackage util
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: YamlSfParser.class.php 8869 2008-05-09 00:22:57Z dwhittle $
+ */
+class Doctrine_Parser_YamlSf_Parser
+{
+  protected
+    $value         = '',
+    $offset        = 0,
+    $lines         = array(),
+    $currentLineNb = -1,
+    $currentLine   = '',
+    $refs          = array();
+
+  /**
+   * Constructor
+   *
+   * @param integer The offset of YAML document (used for line numbers in error messages)
+   */
+  public function __construct($offset = 0)
+  {
+    $this->offset = $offset;
+  }
+
+  /**
+   * Parses a YAML string to a PHP value.
+   *
+   * @param  string A YAML string
+   *
+   * @return mixed  A PHP value
+   */
+  public function parse($value)
+  {
+    $this->value = $this->cleanup($value);
+    $this->currentLineNb = -1;
+    $this->currentLine = '';
+    $this->lines = explode("\n", $this->value);
+
+    $data = array();
+    while ($this->moveToNextLine())
+    {
+      if ($this->isCurrentLineEmpty())
+      {
+        continue;
+      }
+
+      // tab?
+      if (preg_match('#^\t+#', $this->currentLine))
+      {
+        throw new InvalidArgumentException(sprintf('A YAML file cannot contain tabs as indentation at line %d (%s).', $this->getRealCurrentLineNb(), $this->currentLine));
+      }
+
+      $isRef = $isInPlace = false;
+      if (preg_match('#^\-(\s+(?P<value>.+?))?\s*$#', $this->currentLine, $values))
+      {
+        if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#', $values['value'], $matches))
+        {
+          $isRef = $matches['ref'];
+          $values['value'] = $matches['value'];
+        }
+
+        // array
+        if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#'))
+        {
+          $c = $this->getRealCurrentLineNb() + 1;
+          $parser = new Doctrine_Parser_YamlSf_Parser($c);
+          $parser->refs =& $this->refs;
+          $data[] = $parser->parse($this->getNextEmbedBlock());
+        }
+        else
+        {
+          if (preg_match('/^([^ ]+)\: +({.*?)$/', $values['value'], $matches))
+          {
+            $data[] = array($matches[1] => Doctrine_Parser_YamlSf_Inline::load($matches[2]));
+          }
+          else
+          {
+            $data[] = $this->parseValue($values['value']);
+          }
+        }
+      }
+      else if (preg_match('#^(?P<key>[^ ].*?) *\:(\s+(?P<value>.+?))?\s*$#', $this->currentLine, $values))
+      {
+        $key = Doctrine_Parser_YamlSf_Inline::parseScalar($values['key']);
+
+        if ('<<' === $key)
+        {
+          if (isset($values['value']) && '*' === substr($values['value'], 0, 1))
+          {
+            $isInPlace = substr($values['value'], 1);
+            if (!array_key_exists($isInPlace, $this->refs))
+            {
+              throw new InvalidArgumentException(sprintf('Reference "%s" does not exist on line %s.', $isInPlace, $this->currentLine));
+            }
+          }
+          else
+          {
+            throw new InvalidArgumentException(sprintf('In place substitution must point to a reference on line %s.', $this->currentLine));
+          }
+        }
+        else if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#', $values['value'], $matches))
+        {
+          $isRef = $matches['ref'];
+          $values['value'] = $matches['value'];
+        }
+
+        // hash
+        if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#'))
+        {
+          // if next line is less indented or equal, then it means that the current value is null
+          if ($this->isNextLineIndented())
+          {
+            $data[$key] = null;
+          }
+          else
+          {
+            $c = $this->getRealCurrentLineNb() + 1;
+            $parser = new Doctrine_Parser_YamlSf_Parser($c);
+            $parser->refs =& $this->refs;
+            $data[$key] = $parser->parse($this->getNextEmbedBlock());
+          }
+        }
+        else
+        {
+          if ($isInPlace)
+          {
+            $data = $this->refs[$isInPlace];
+          }
+          else
+          {
+            $data[$key] = $this->parseValue($values['value']);
+          }
+        }
+      }
+      else
+      {
+        // one liner?
+        if (1 == count(explode("\n", rtrim($this->value, "\n"))))
+        {
+          return Doctrine_Parser_YamlSf_Inline::load($this->lines[0]);
+        }
+
+        throw new InvalidArgumentException(sprintf('Unable to parse line %d (%s).', $this->getRealCurrentLineNb(), $this->currentLine));
+      }
+
+      if ($isRef)
+      {
+        $this->refs[$isRef] = end($data);
+      }
+    }
+
+    return empty($data) ? null : $data;
+  }
+
+  /**
+   * Returns the current line number (takes the offset into account).
+   *
+   * @return integer The current line number
+   */
+  protected function getRealCurrentLineNb()
+  {
+    return $this->currentLineNb + $this->offset;
+  }
+
+  /**
+   * Returns the current line indentation.
+   *
+   * @returns integer The current line indentation
+   */
+  protected function getCurrentLineIndentation()
+  {
+    return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' '));
+  }
+
+  /**
+   * Returns the next embed block of YAML.
+   *
+   * @param string A YAML string
+   */
+  protected function getNextEmbedBlock()
+  {
+    $this->moveToNextLine();
+
+    $newIndent = $this->getCurrentLineIndentation();
+
+    if (!$this->isCurrentLineEmpty() && 0 == $newIndent)
+    {
+      throw new InvalidArgumentException(sprintf('Indentation problem at line %d (%s)', $this->getRealCurrentLineNb(), $this->currentLine));
+    }
+
+    $data = array(substr($this->currentLine, $newIndent));
+
+    while ($this->moveToNextLine())
+    {
+      if ($this->isCurrentLineEmpty())
+      {
+        if ($this->isCurrentLineBlank())
+        {
+          $data[] = substr($this->currentLine, $newIndent);
+        }
+
+        continue;
+      }
+
+      $indent = $this->getCurrentLineIndentation();
+
+      if (preg_match('#^(?P<text> *)$#', $this->currentLine, $match))
+      {
+        // empty line
+        $data[] = $match['text'];
+      }
+      else if ($indent >= $newIndent)
+      {
+        $data[] = substr($this->currentLine, $newIndent);
+      }
+      else if (0 == $indent)
+      {
+        $this->moveToPreviousLine();
+
+        break;
+      }
+      else
+      {
+        throw new InvalidArgumentException(sprintf('Indentation problem at line %d (%s)', $this->getRealCurrentLineNb(), $this->currentLine));
+      }
+    }
+
+    return implode("\n", $data);
+  }
+
+  /**
+   * Moves the parser to the next line.
+   */
+  protected function moveToNextLine()
+  {
+    if ($this->currentLineNb >= count($this->lines) - 1)
+    {
+      return false;
+    }
+
+    $this->currentLine = $this->lines[++$this->currentLineNb];
+
+    return true;
+  }
+
+  /**
+   * Moves the parser to the previous line.
+   */
+  protected function moveToPreviousLine()
+  {
+    $this->currentLine = $this->lines[--$this->currentLineNb];
+  }
+
+  /**
+   * Parses a YAML value.
+   *
+   * @param  string A YAML value
+   *
+   * @return mixed  A PHP value
+   */
+  protected function parseValue($value)
+  {
+    if ('*' === substr($value, 0, 1))
+    {
+      if (false !== $pos = strpos($value, '#'))
+      {
+        $value = substr($value, 1, $pos - 2);
+      }
+      else
+      {
+        $value = substr($value, 1);
+      }
+
+      if (!array_key_exists($value, $this->refs))
+      {
+        throw new InvalidArgumentException(sprintf('Reference "%s" does not exist (%s).', $value, $this->currentLine));
+      }
+      return $this->refs[$value];
+    }
+
+    if (preg_match('/^(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?$/', $value, $matches))
+    {
+      $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : '';
+
+      return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), intval(abs($modifiers)));
+    }
+    else
+    {
+      return Doctrine_Parser_YamlSf_Inline::load($value);
+    }
+  }
+
+  /**
+   * Parses a folded scalar.
+   *
+   * @param  string  The separator that was used to begin this folded scalar (| or >)
+   * @param  string  The indicator that was used to begin this folded scalar (+ or -)
+   * @param  integer The indentation that was used to begin this folded scalar
+   *
+   * @return string  The text value
+   */
+  protected function parseFoldedScalar($separator, $indicator = '', $indentation = 0)
+  {
+    $separator = '|' == $separator ? "\n" : ' ';
+    $text = '';
+
+    $notEOF = $this->moveToNextLine();
+
+    while ($notEOF && $this->isCurrentLineBlank())
+    {
+      $text .= "\n";
+
+      $notEOF = $this->moveToNextLine();
+    }
+
+    if (!$notEOF)
+    {
+      return '';
+    }
+
+    if (!preg_match('#^(?P<indent>'.($indentation ? str_repeat(' ', $indentation) : ' +').')(?P<text>.*)$#', $this->currentLine, $matches))
+    {
+      $this->moveToPreviousLine();
+
+      return '';
+    }
+
+    $textIndent = $matches['indent'];
+    $previousIndent = 0;
+
+    $text .= $matches['text'].$separator;
+    while ($this->currentLineNb + 1 < count($this->lines))
+    {
+      $this->moveToNextLine();
+
+      if (preg_match('#^(?P<indent> {'.strlen($textIndent).',})(?P<text>.+)$#', $this->currentLine, $matches))
+      {
+        if (' ' == $separator && $previousIndent != $matches['indent'])
+        {
+          $text = substr($text, 0, -1)."\n";
+        }
+        $previousIndent = $matches['indent'];
+
+        $text .= str_repeat(' ', $diff = strlen($matches['indent']) - strlen($textIndent)).$matches['text'].($diff ? "\n" : $separator);
+      }
+      else if (preg_match('#^(?P<text> *)$#', $this->currentLine, $matches))
+      {
+        $text .= preg_replace('#^ {1,'.strlen($textIndent).'}#', '', $matches['text'])."\n";
+      }
+      else
+      {
+        $this->moveToPreviousLine();
+
+        break;
+      }
+    }
+
+    if (' ' == $separator)
+    {
+      // replace last separator by a newline
+      $text = preg_replace('/ (\n*)$/', "\n$1", $text);
+    }
+
+    switch ($indicator)
+    {
+      case '':
+        $text = preg_replace('#\n+$#s', "\n", $text);
+        break;
+      case '+':
+        break;
+      case '-':
+        $text = preg_replace('#\n+$#s', '', $text);
+        break;
+    }
+
+    return $text;
+  }
+
+  /**
+   * Returns true if the next line is indented.
+   *
+   * @return Boolean Returns true if the next line is indented, false otherwise
+   */
+  protected function isNextLineIndented()
+  {
+    $currentIndentation = $this->getCurrentLineIndentation();
+    $notEOF = $this->moveToNextLine();
+
+    while ($notEOF && $this->isCurrentLineEmpty())
+    {
+      $notEOF = $this->moveToNextLine();
+    }
+
+    if (false === $notEOF)
+    {
+      return false;
+    }
+
+    $ret = false;
+    if ($this->getCurrentLineIndentation() <= $currentIndentation)
+    {
+      $ret = true;
+    }
+
+    $this->moveToPreviousLine();
+
+    return $ret;
+  }
+
+  /**
+   * Returns true if the current line is blank or if it is a comment line.
+   *
+   * @return Boolean Returns true if the current line is empty or if it is a comment line, false otherwise
+   */
+  protected function isCurrentLineEmpty()
+  {
+    return $this->isCurrentLineBlank() || $this->isCurrentLineComment();
+  }
+
+  /**
+   * Returns true if the current line is blank.
+   *
+   * @return Boolean Returns true if the current line is blank, false otherwise
+   */
+  protected function isCurrentLineBlank()
+  {
+    return '' == trim($this->currentLine, ' ');
+  }
+
+  /**
+   * Returns true if the current line is a comment line.
+   *
+   * @return Boolean Returns true if the current line is a comment line, false otherwise
+   */
+  protected function isCurrentLineComment()
+  {
+    return 0 === strpos(ltrim($this->currentLine, ' '), '#');
+  }
+
+  /**
+   * Cleanups a YAML string to be parsed.
+   *
+   * @param  string The input YAML string
+   *
+   * @return string A cleaned up YAML string
+   */
+  protected function cleanup($value)
+  {
+    $value = str_replace(array("\r\n", "\r"), "\n", $value);
+
+    if (!preg_match("#\n$#", $value))
+    {
+      $value .= "\n";
+    }
+
+    // strip YAML header
+    preg_replace('#^\%YAML[: ][\d\.]+.*\n#s', '', $value);
+
+    // remove ---
+    $value = preg_replace('#^\-\-\-.*?\n#s', '', $value);
+
+    return $value;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Parser/Yml.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,91 @@
+<?php
+/*
+ *  $Id: Yml.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Parser_Yml
+ *
+ * @package     Doctrine
+ * @subpackage  Parser
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>, Thomas Courbon <harthie@yahoo.fr>
+ */
+class Doctrine_Parser_Yml extends Doctrine_Parser
+{
+    /**
+     * dumpData
+     *
+     * Dump an array of data to a specified path or return
+     * 
+     * @throws Doctrine_Parser_Exception dumping error
+     * @param  string $array Array of data to dump to yaml
+     * @param  string $path  Path to dump the yaml to
+     * @return string $yaml
+     * @return void
+     */
+    public function dumpData($array, $path = null)
+    {
+       
+        try {
+          $data = Doctrine_Parser_YamlSf::dump($array);
+          
+          return $this->doDump($data, $path);
+          
+        } catch(InvalidArgumentException $e) {
+          // rethrow the exceptions
+          $rethrowed_exception = new Doctrine_Parser_Exception($e->getMessage(), $e->getCode());
+          
+          throw $rethrowed_exception;
+        }
+    }
+
+    /**
+     * loadData
+     *
+     * Load and parse data from a yml file
+     * 
+     * @throws Doctrine_Parser_Exception parsing error
+     * @param  string  $path  Path to load yaml data from
+     * @return array   $array Array of parsed yaml data
+     */
+    public function loadData($path)
+    {
+        try {
+          /*
+           * I still use the doLoad method even if sfYaml can load yml from a file
+           * since this way Doctrine can handle file on it own.
+           */ 
+          $contents = $this->doLoad($path);
+
+          $array = Doctrine_Parser_YamlSf::load($contents);
+          
+          return $array;
+          
+        } catch(InvalidArgumentException $e) {
+          // rethrow the exceptions
+          $rethrowed_exception = new Doctrine_Parser_Exception($e->getMessage(), $e->getCode());
+          
+          throw $rethrowed_exception;
+        }
+    }        
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,2055 @@
+<?php
+/*
+ *  $Id: Query.php 5874 2009-06-10 16:11:11Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query
+ * A Doctrine_Query object represents a DQL query. It is used to query databases for
+ * data in an object-oriented fashion. A DQL query understands relations and inheritance
+ * and is dbms independant.
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5874 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @todo        Proposal: This class does far too much. It should have only 1 task: Collecting
+ *              the DQL query parts and the query parameters (the query state and caching options/methods
+ *              can remain here, too).
+ *              The actual SQL construction could be done by a separate object (Doctrine_Query_SqlBuilder?)
+ *              whose task it is to convert DQL into SQL.
+ *              Furthermore the SqlBuilder? can then use other objects (Doctrine_Query_Tokenizer?),
+ *              (Doctrine_Query_Parser(s)?) to accomplish his work. Doctrine_Query does not need
+ *              to know the tokenizer/parsers. There could be extending
+ *              implementations of SqlBuilder? that cover the specific SQL dialects.
+ *              This would release Doctrine_Connection and the Doctrine_Connection_xxx classes
+ *              from this tedious task.
+ *              This would also largely reduce the currently huge interface of Doctrine_Query(_Abstract)
+ *              and better hide all these transformation internals from the public Query API.
+ *
+ * @internal    The lifecycle of a Query object is the following:
+ *              After construction the query object is empty. Through using the fluent
+ *              query interface the user fills the query object with DQL parts and query parameters.
+ *              These get collected in {@link $_dqlParts} and {@link $_params}, respectively.
+ *              When the query is executed the first time, or when {@link getSqlQuery()}
+ *              is called the first time, the collected DQL parts get parsed and the resulting
+ *              connection-driver specific SQL is generated. The generated SQL parts are
+ *              stored in {@link $_sqlParts} and the final resulting SQL query is stored in
+ *              {@link $_sql}.
+ */
+class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Serializable
+{
+    /**
+     * @var array  The DQL keywords.
+     */
+    protected static $_keywords  = array('ALL',
+                                         'AND',
+                                         'ANY',
+                                         'AS',
+                                         'ASC',
+                                         'AVG',
+                                         'BETWEEN',
+                                         'BIT_LENGTH',
+                                         'BY',
+                                         'CHARACTER_LENGTH',
+                                         'CHAR_LENGTH',
+                                         'CURRENT_DATE',
+                                         'CURRENT_TIME',
+                                         'CURRENT_TIMESTAMP',
+                                         'DELETE',
+                                         'DESC',
+                                         'DISTINCT',
+                                         'EMPTY',
+                                         'EXISTS',
+                                         'FALSE',
+                                         'FETCH',
+                                         'FROM',
+                                         'GROUP',
+                                         'HAVING',
+                                         'IN',
+                                         'INDEXBY',
+                                         'INNER',
+                                         'IS',
+                                         'JOIN',
+                                         'LEFT',
+                                         'LIKE',
+                                         'LOWER',
+                                         'MEMBER',
+                                         'MOD',
+                                         'NEW',
+                                         'NOT',
+                                         'NULL',
+                                         'OBJECT',
+                                         'OF',
+                                         'OR',
+                                         'ORDER',
+                                         'OUTER',
+                                         'POSITION',
+                                         'SELECT',
+                                         'SOME',
+                                         'TRIM',
+                                         'TRUE',
+                                         'UNKNOWN',
+                                         'UPDATE',
+                                         'WHERE');
+
+    /**
+     * @var array
+     */
+    protected $_subqueryAliases = array();
+
+    /**
+     * @var array $_aggregateAliasMap       an array containing all aggregate aliases, keys as dql aliases
+     *                                      and values as sql aliases
+     */
+    protected $_aggregateAliasMap      = array();
+
+    /**
+     * @var array
+     */
+    protected $_pendingAggregates = array();
+
+    /**
+     * @param boolean $needsSubquery
+     */
+    protected $_needsSubquery = false;
+
+    /**
+     * @param boolean $isSubquery           whether or not this query object is a subquery of another
+     *                                      query object
+     */
+    protected $_isSubquery;
+
+    /**
+     * @var array $_neededTables            an array containing the needed table aliases
+     */
+    protected $_neededTables = array();
+
+    /**
+     * @var array $pendingSubqueries        SELECT part subqueries, these are called pending subqueries since
+     *                                      they cannot be parsed directly (some queries might be correlated)
+     */
+    protected $_pendingSubqueries = array();
+
+    /**
+     * @var array $_pendingFields           an array of pending fields (fields waiting to be parsed)
+     */
+    protected $_pendingFields = array();
+
+    /**
+     * @var array $_parsers                 an array of parser objects, each DQL query part has its own parser
+     */
+    protected $_parsers = array();
+
+    /**
+     * @var array $_pendingJoinConditions    an array containing pending joins
+     */
+    protected $_pendingJoinConditions = array();
+
+    /**
+     * @var array
+     */
+    protected $_expressionMap = array();
+
+    /**
+     * @var string $_sql            cached SQL query
+     */
+    protected $_sql;
+
+    /**
+     * create
+     * returns a new Doctrine_Query object
+     *
+     * @param Doctrine_Connection $conn     optional connection parameter
+     * @return Doctrine_Query
+     */
+    public static function create($conn = null)
+    {
+        return new Doctrine_Query($conn);
+    }
+
+    /**
+     * Resets the query to the state just after it has been instantiated.
+     */
+    public function reset()
+    {
+        $this->_subqueryAliases = array();
+        $this->_aggregateAliasMap = array();
+        $this->_pendingAggregates = array();
+        $this->_pendingJoinConditions = array();
+        $this->_pendingSubqueries = array();
+        $this->_pendingFields = array();
+        $this->_neededTables = array();
+        $this->_expressionMap = array();
+        $this->_subqueryAliases = array();
+        $this->_needsSubquery = false;
+        $this->_isLimitSubqueryUsed = false;
+    }
+
+    /**
+     * createSubquery
+     * creates a subquery
+     *
+     * @return Doctrine_Hydrate
+     */
+    public function createSubquery()
+    {
+        $class = get_class($this);
+        $obj   = new $class();
+
+        // copy the aliases to the subquery
+        $obj->copySubqueryInfo($this);
+
+        // this prevents the 'id' being selected, re ticket #307
+        $obj->isSubquery(true);
+
+        return $obj;
+    }
+
+    /**
+     * _addPendingJoinCondition
+     *
+     * @param string $componentAlias    component alias
+     * @param string $joinCondition     dql join condition
+     * @return Doctrine_Query           this object
+     */
+    protected function _addPendingJoinCondition($componentAlias, $joinCondition)
+    {
+        $this->_pendingJoins[$componentAlias] = $joinCondition;
+    }
+
+    /**
+     * fetchArray
+     * Convenience method to execute using array fetching as hydration mode.
+     *
+     * @param string $params
+     * @return array
+     */
+    public function fetchArray($params = array()) {
+        return $this->execute($params, Doctrine::HYDRATE_ARRAY);
+    }
+
+    /**
+     * fetchOne
+     * Convenience method to execute the query and return the first item
+     * of the collection.
+     *
+     * @param string $params        Query parameters
+     * @param int $hydrationMode    Hydration mode: see Doctrine::HYDRATE_* constants
+     * @return mixed                Array or Doctrine_Collection, depending on hydration mode. False if no result.
+     */
+    public function fetchOne($params = array(), $hydrationMode = null)
+    {
+        $collection = $this->execute($params, $hydrationMode);
+
+        if (count($collection) === 0) {
+            return false;
+        }
+
+        if ($collection instanceof Doctrine_Collection) {
+            return $collection->getFirst();
+        } else if (is_array($collection)) {
+            return array_shift($collection);
+        }
+
+        return false;
+    }
+
+    /**
+     * isSubquery
+     * if $bool parameter is set this method sets the value of
+     * Doctrine_Query::$isSubquery. If this value is set to true
+     * the query object will not load the primary key fields of the selected
+     * components.
+     *
+     * If null is given as the first parameter this method retrieves the current
+     * value of Doctrine_Query::$isSubquery.
+     *
+     * @param boolean $bool     whether or not this query acts as a subquery
+     * @return Doctrine_Query|bool
+     */
+    public function isSubquery($bool = null)
+    {
+        if ($bool === null) {
+            return $this->_isSubquery;
+        }
+
+        $this->_isSubquery = (bool) $bool;
+        return $this;
+    }
+
+    /**
+     * getAggregateAlias
+     *
+     * @param string $dqlAlias      the dql alias of an aggregate value
+     * @return string
+     * @deprecated
+     */
+    public function getAggregateAlias($dqlAlias)
+    {
+        return $this->getSqlAggregateAlias($dqlAlias);
+    }
+
+    /**
+     * getSqlAggregateAlias
+     *
+     * @param string $dqlAlias      the dql alias of an aggregate value
+     * @return string
+     */
+    public function getSqlAggregateAlias($dqlAlias)
+    {
+        if (isset($this->_aggregateAliasMap[$dqlAlias])) {
+            // mark the expression as used
+            $this->_expressionMap[$dqlAlias][1] = true;
+
+            return $this->_aggregateAliasMap[$dqlAlias];
+        } else if ( ! empty($this->_pendingAggregates)) {
+            $this->processPendingAggregates();
+
+            return $this->getSqlAggregateAlias($dqlAlias);
+        } else {
+            throw new Doctrine_Query_Exception('Unknown aggregate alias: ' . $dqlAlias);
+        }
+    }
+
+    /**
+     * parseQueryPart
+     * parses given DQL query part
+     *
+     * @param string $queryPartName     the name of the query part
+     * @param string $queryPart         query part to be parsed
+     * @param boolean $append           whether or not to append the query part to its stack
+     *                                  if false is given, this method will overwrite
+     *                                  the given query part stack with $queryPart
+     * @return Doctrine_Query           this object
+     */
+    /*protected function parseQueryPart($queryPartName, $queryPart, $append = false)
+    {
+        if ($this->_state === self::STATE_LOCKED) {
+            throw new Doctrine_Query_Exception('This query object is locked. No query parts can be manipulated.');
+        }
+
+        // sanity check
+        if ($queryPart === '' || $queryPart === null) {
+            throw new Doctrine_Query_Exception('Empty ' . $queryPartName . ' part given.');
+        }
+
+        // add query part to the dql part array
+        if ($append) {
+            $this->_dqlParts[$queryPartName][] = $queryPart;
+        } else {
+            $this->_dqlParts[$queryPartName] = array($queryPart);
+        }
+
+        if ($this->_state === self::STATE_DIRECT) {
+            $parser = $this->_getParser($queryPartName);
+
+            $sql = $parser->parse($queryPart);
+
+            if (isset($sql)) {
+                if ($append) {
+                    $this->addSqlQueryPart($queryPartName, $sql);
+                } else {
+                    $this->setSqlQueryPart($queryPartName, $sql);
+                }
+            }
+        }
+
+        $this->_state = Doctrine_Query::STATE_DIRTY;
+
+        return $this;
+    }*/
+
+    /**
+     * getDqlPart
+     * returns a specific DQL query part.
+     *
+     * @param string $queryPart     the name of the query part
+     * @return string   the DQL query part
+     * @todo Description: List which query parts exist or point to the method/property
+     *       where they are listed.
+     */
+    public function getDqlPart($queryPart)
+    {
+        if ( ! isset($this->_dqlParts[$queryPart])) {
+           throw new Doctrine_Query_Exception('Unknown query part ' . $queryPart);
+        }
+
+        return $this->_dqlParts[$queryPart];
+    }
+
+    /**
+     * contains
+     *
+     * Method to check if a arbitrary piece of dql exists
+     *
+     * @param string $dql Arbitrary piece of dql to check for
+     * @return boolean
+     */
+    public function contains($dql)
+    {
+      return stripos($this->getDql(), $dql) === false ? false : true;
+    }
+
+    /**
+     * processPendingFields
+     * the fields in SELECT clause cannot be parsed until the components
+     * in FROM clause are parsed, hence this method is called everytime a
+     * specific component is being parsed.
+     *
+     * @throws Doctrine_Query_Exception     if unknown component alias has been given
+     * @param string $componentAlias        the alias of the component
+     * @return void
+     * @todo Description: What is a 'pending field' (and are there non-pending fields, too)?
+     *       What is 'processed'? (Meaning: What information is gathered & stored away)
+     */
+    public function processPendingFields($componentAlias)
+    {
+        $tableAlias = $this->getTableAlias($componentAlias);
+        $table = $this->_queryComponents[$componentAlias]['table'];
+
+        if ( ! isset($this->_pendingFields[$componentAlias])) {
+            if ($this->_hydrator->getHydrationMode() != Doctrine::HYDRATE_NONE) {
+                if ( ! $this->_isSubquery && $componentAlias == $this->getRootAlias()) {
+                    throw new Doctrine_Query_Exception("The root class of the query (alias $componentAlias) "
+                            . " must have at least one field selected.");
+                }
+            }
+            return;
+        }
+
+        // At this point we know the component is FETCHED (either it's the base class of
+        // the query (FROM xyz) or its a "fetch join").
+
+        // Check that the parent join (if there is one), is a "fetch join", too.
+        if ( ! $this->isSubquery() && isset($this->_queryComponents[$componentAlias]['parent'])) {
+            $parentAlias = $this->_queryComponents[$componentAlias]['parent'];
+            if (is_string($parentAlias) && ! isset($this->_pendingFields[$parentAlias])
+                    && $this->_hydrator->getHydrationMode() != Doctrine::HYDRATE_NONE) {
+                throw new Doctrine_Query_Exception("The left side of the join between "
+                        . "the aliases '$parentAlias' and '$componentAlias' must have at least"
+                        . " the primary key field(s) selected.");
+            }
+        }
+
+        $fields = $this->_pendingFields[$componentAlias];
+
+        // check for wildcards
+        if (in_array('*', $fields)) {
+            $fields = $table->getFieldNames();
+        } else {
+            // only auto-add the primary key fields if this query object is not
+            // a subquery of another query object and we're not using HYDRATE_NONE
+            if ( ! $this->_isSubquery && $this->_hydrator->getHydrationMode() != Doctrine::HYDRATE_NONE) {
+                $fields = array_unique(array_merge((array) $table->getIdentifier(), $fields));
+            }
+        }
+
+        $sql = array();
+        foreach ($fields as $fieldName) {
+            $columnName = $table->getColumnName($fieldName);
+            if (($owner = $table->getColumnOwner($columnName)) !== null &&
+                    $owner !== $table->getComponentName()) {
+
+                $parent = $this->_conn->getTable($owner);
+                $columnName = $parent->getColumnName($fieldName);
+                $parentAlias = $this->getTableAlias($componentAlias . '.' . $parent->getComponentName());
+                $sql[] = $this->_conn->quoteIdentifier($parentAlias . '.' . $columnName)
+                       . ' AS '
+                       . $this->_conn->quoteIdentifier($tableAlias . '__' . $columnName);
+            } else {
+                $columnName = $table->getColumnName($fieldName);
+                $sql[] = $this->_conn->quoteIdentifier($tableAlias . '.' . $columnName)
+                       . ' AS '
+                       . $this->_conn->quoteIdentifier($tableAlias . '__' . $columnName);
+            }
+        }
+
+        $this->_neededTables[] = $tableAlias;
+
+        return implode(', ', $sql);
+    }
+
+    /**
+     * parseSelectField
+     *
+     * @throws Doctrine_Query_Exception     if unknown component alias has been given
+     * @return void
+     * @todo Description: Explain what this method does. Is there a relation to parseSelect()?
+     *       (It doesnt seem to get called from there...?). In what circumstances is this method
+     *       used?
+     */
+    public function parseSelectField($field)
+    {
+        $terms = explode('.', $field);
+
+        if (isset($terms[1])) {
+            $componentAlias = $terms[0];
+            $field = $terms[1];
+        } else {
+            reset($this->_queryComponents);
+            $componentAlias = key($this->_queryComponents);
+            $fields = $terms[0];
+        }
+
+        $tableAlias = $this->getTableAlias($componentAlias);
+        $table      = $this->_queryComponents[$componentAlias]['table'];
+
+
+        // check for wildcards
+        if ($field === '*') {
+            $sql = array();
+
+            foreach ($table->getColumnNames() as $field) {
+                $sql[] = $this->parseSelectField($componentAlias . '.' . $field);
+            }
+
+            return implode(', ', $sql);
+        } else {
+            $name = $table->getColumnName($field);
+
+            $this->_neededTables[] = $tableAlias;
+
+            return $this->_conn->quoteIdentifier($tableAlias . '.' . $name)
+                   . ' AS '
+                   . $this->_conn->quoteIdentifier($tableAlias . '__' . $name);
+        }
+    }
+
+    /**
+     * getExpressionOwner
+     * returns the component alias for owner of given expression
+     *
+     * @param string $expr      expression from which to get to owner from
+     * @return string           the component alias
+     * @todo Description: What does it mean if a component is an 'owner' of an expression?
+     *       What kind of 'expression' are we talking about here?
+     */
+    public function getExpressionOwner($expr)
+    {
+        if (strtoupper(substr(trim($expr, '( '), 0, 6)) !== 'SELECT') {
+            preg_match_all("/[a-z_][a-z0-9_]*\.[a-z_][a-z0-9_]*[\.[a-z0-9]+]*/i", $expr, $matches);
+
+            $match = current($matches);
+
+            if (isset($match[0])) {
+                $terms = explode('.', $match[0]);
+
+                return $terms[0];
+            }
+        }
+        return $this->getRootAlias();
+
+    }
+
+    /**
+     * parseSelect
+     * parses the query select part and
+     * adds selected fields to pendingFields array
+     *
+     * @param string $dql
+     * @todo Description: What information is extracted (and then stored)?
+     */
+    public function parseSelect($dql)
+    {
+        $refs = $this->_tokenizer->sqlExplode($dql, ',');
+
+        $pos   = strpos(trim($refs[0]), ' ');
+        $first = substr($refs[0], 0, $pos);
+
+        // check for DISTINCT keyword
+        if ($first === 'DISTINCT') {
+            $this->_sqlParts['distinct'] = true;
+
+            $refs[0] = substr($refs[0], ++$pos);
+        }
+
+        $parsedComponents = array();
+
+        foreach ($refs as $reference) {
+            $reference = trim($reference);
+
+            if (empty($reference)) {
+                continue;
+            }
+
+            $terms = $this->_tokenizer->sqlExplode($reference, ' ');
+
+            $pos   = strpos($terms[0], '(');
+
+            if (count($terms) > 1 || $pos !== false) {
+                $expression = array_shift($terms);
+                $alias = array_pop($terms);
+
+                if ( ! $alias) {
+                    $alias = substr($expression, 0, $pos);
+                }
+
+                $componentAlias = $this->getExpressionOwner($expression);
+                $expression = $this->parseClause($expression);
+
+                $tableAlias = $this->getTableAlias($componentAlias);
+
+                $index    = count($this->_aggregateAliasMap);
+
+                $sqlAlias = $this->_conn->quoteIdentifier($tableAlias . '__' . $index);
+
+                $this->_sqlParts['select'][] = $expression . ' AS ' . $sqlAlias;
+
+                $this->_aggregateAliasMap[$alias] = $sqlAlias;
+                $this->_expressionMap[$alias][0] = $expression;
+
+                $this->_queryComponents[$componentAlias]['agg'][$index] = $alias;
+
+                $this->_neededTables[] = $tableAlias;
+            } else {
+                $e = explode('.', $terms[0]);
+
+                if (isset($e[1])) {
+                    $componentAlias = $e[0];
+                    $field = $e[1];
+                } else {
+                    reset($this->_queryComponents);
+                    $componentAlias = key($this->_queryComponents);
+                    $field = $e[0];
+                }
+
+                $this->_pendingFields[$componentAlias][] = $field;
+            }
+        }
+    }
+
+    /**
+     * parseClause
+     * parses given DQL clause
+     *
+     * this method handles five tasks:
+     *
+     * 1. Converts all DQL functions to their native SQL equivalents
+     * 2. Converts all component references to their table alias equivalents
+     * 3. Converts all field names to actual column names
+     * 4. Quotes all identifiers
+     * 5. Parses nested clauses and subqueries recursively
+     *
+     * @return string   SQL string
+     * @todo Description: What is a 'dql clause' (and what not)?
+     *       Refactor: Too long & nesting level
+     */
+    public function parseClause($clause)
+    {
+    	$clause = trim($clause);
+
+    	if (is_numeric($clause)) {
+    	   return $clause;
+    	}
+
+        $terms = $this->_tokenizer->clauseExplode($clause, array(' ', '+', '-', '*', '/', '<', '>', '=', '>=', '<=', '&', '|'));
+
+        $str = '';
+        foreach ($terms as $term) {
+            $pos = strpos($term[0], '(');
+
+            if ($pos !== false) {
+                $name = substr($term[0], 0, $pos);
+                $term[0] = $this->parseFunctionExpression($term[0]);
+            } else {
+                if (substr($term[0], 0, 1) !== "'" && substr($term[0], -1) !== "'") {
+
+                    if (strpos($term[0], '.') !== false) {
+                        if ( ! is_numeric($term[0])) {
+                            $e = explode('.', $term[0]);
+
+                            $field = array_pop($e);
+
+                            if ($this->getType() === Doctrine_Query::SELECT) {
+                                $componentAlias = implode('.', $e);
+
+                                if (empty($componentAlias)) {
+                                    $componentAlias = $this->getRootAlias();
+                                }
+
+                                $this->load($componentAlias);
+
+                                // check the existence of the component alias
+                                if ( ! isset($this->_queryComponents[$componentAlias])) {
+                                    throw new Doctrine_Query_Exception('Unknown component alias ' . $componentAlias);
+                                }
+
+                                $table = $this->_queryComponents[$componentAlias]['table'];
+
+                                $def = $table->getDefinitionOf($field);
+
+                                // get the actual field name from alias
+                                $field = $table->getColumnName($field);
+
+                                // check column existence
+                                if ( ! $def) {
+                                    throw new Doctrine_Query_Exception('Unknown column ' . $field);
+                                }
+
+                                if (isset($def['owner'])) {
+                                    $componentAlias = $componentAlias . '.' . $def['owner'];
+                                }
+
+                                $tableAlias = $this->getTableAlias($componentAlias);
+
+                                // build sql expression
+                                $term[0] = $this->_conn->quoteIdentifier($tableAlias)
+                                         . '.'
+                                         . $this->_conn->quoteIdentifier($field);
+                            } else {
+                                // build sql expression
+                                $field = $this->getRoot()->getColumnName($field);
+                                $term[0] = $this->_conn->quoteIdentifier($field);
+                            }
+                        }
+                    } else {
+                        if ( ! empty($term[0]) &&
+                             ! in_array(strtoupper($term[0]), self::$_keywords) &&
+                             ! is_numeric($term[0]) &&
+                            $term[0] !== '?' && substr($term[0], 0, 1) !== ':') {
+
+                            $componentAlias = $this->getRootAlias();
+
+                            $found = false;
+
+                            if ($componentAlias !== false &&
+                                $componentAlias !== null) {
+                                $table = $this->_queryComponents[$componentAlias]['table'];
+
+                                // check column existence
+                                if ($table->hasField($term[0])) {
+                                    $found = true;
+
+                                    $def = $table->getDefinitionOf($term[0]);
+
+                                    // get the actual column name from field name
+                                    $term[0] = $table->getColumnName($term[0]);
+
+
+                                    if (isset($def['owner'])) {
+                                        $componentAlias = $componentAlias . '.' . $def['owner'];
+                                    }
+
+                                    $tableAlias = $this->getTableAlias($componentAlias);
+
+                                    if ($this->getType() === Doctrine_Query::SELECT) {
+                                        // build sql expression
+                                        $term[0] = $this->_conn->quoteIdentifier($tableAlias)
+                                                 . '.'
+                                                 . $this->_conn->quoteIdentifier($term[0]);
+                                    } else {
+                                        // build sql expression
+                                        $term[0] = $this->_conn->quoteIdentifier($term[0]);
+                                    }
+                                } else {
+                                    $found = false;
+                                }
+                            }
+
+                            if ( ! $found) {
+                                $term[0] = $this->getSqlAggregateAlias($term[0]);
+                            }
+                        }
+                    }
+                }
+            }
+
+            $str .= $term[0] . $term[1];
+        }
+        return $str;
+    }
+
+    public function parseIdentifierReference($expr)
+    {
+
+    }
+
+    public function parseFunctionExpression($expr)
+    {
+        $pos = strpos($expr, '(');
+
+        $name = substr($expr, 0, $pos);
+
+        if ($name === '') {
+            return $this->parseSubquery($expr);
+        }
+
+        $argStr = substr($expr, ($pos + 1), -1);
+
+        $args   = array();
+        // parse args
+
+        foreach ($this->_tokenizer->sqlExplode($argStr, ',') as $arg) {
+           $args[] = $this->parseClause($arg);
+        }
+
+        // convert DQL function to its RDBMS specific equivalent
+        try {
+            $expr = call_user_func_array(array($this->_conn->expression, $name), $args);
+        } catch (Doctrine_Expression_Exception $e) {
+            throw new Doctrine_Query_Exception('Unknown function ' . $name . '.');
+        }
+
+        return $expr;
+    }
+    public function parseSubquery($subquery)
+    {
+        $trimmed = trim($this->_tokenizer->bracketTrim($subquery));
+
+        // check for possible subqueries
+        if (substr($trimmed, 0, 4) == 'FROM' || substr($trimmed, 0, 6) == 'SELECT') {
+            // parse subquery
+            $q = $this->createSubquery()->parseDqlQuery($trimmed);
+            $trimmed = $q->getSql();
+            $q->free();
+        } else {
+            // parse normal clause
+            $trimmed = $this->parseClause($trimmed);
+        }
+
+        return '(' . $trimmed . ')';
+    }
+    /**
+     * processPendingSubqueries
+     * processes pending subqueries
+     *
+     * subqueries can only be processed when the query is fully constructed
+     * since some subqueries may be correlated
+     *
+     * @return void
+     * @todo Better description. i.e. What is a 'pending subquery'? What does 'processed' mean?
+     *       (parsed? sql is constructed? some information is gathered?)
+     */
+    public function processPendingSubqueries()
+    {
+        foreach ($this->_pendingSubqueries as $value) {
+            list($dql, $alias) = $value;
+
+            $subquery = $this->createSubquery();
+
+            $sql = $subquery->parseDqlQuery($dql, false)->getQuery();
+
+            reset($this->_queryComponents);
+            $componentAlias = key($this->_queryComponents);
+            $tableAlias = $this->getTableAlias($componentAlias);
+
+            $sqlAlias = $tableAlias . '__' . count($this->_aggregateAliasMap);
+
+            $this->_sqlParts['select'][] = '(' . $sql . ') AS ' . $this->_conn->quoteIdentifier($sqlAlias);
+
+            $this->_aggregateAliasMap[$alias] = $sqlAlias;
+            $this->_queryComponents[$componentAlias]['agg'][] = $alias;
+        }
+        $this->_pendingSubqueries = array();
+    }
+
+    /**
+     * processPendingAggregates
+     * processes pending aggregate values for given component alias
+     *
+     * @return void
+     * @todo Better description. i.e. What is a 'pending aggregate'? What does 'processed' mean?
+     */
+    public function processPendingAggregates()
+    {
+        // iterate trhough all aggregates
+        foreach ($this->_pendingAggregates as $aggregate) {
+            list ($expression, $components, $alias) = $aggregate;
+
+            $tableAliases = array();
+
+            // iterate through the component references within the aggregate function
+            if ( ! empty ($components)) {
+                foreach ($components as $component) {
+
+                    if (is_numeric($component)) {
+                        continue;
+                    }
+
+                    $e = explode('.', $component);
+
+                    $field = array_pop($e);
+                    $componentAlias = implode('.', $e);
+
+                    // check the existence of the component alias
+                    if ( ! isset($this->_queryComponents[$componentAlias])) {
+                        throw new Doctrine_Query_Exception('Unknown component alias ' . $componentAlias);
+                    }
+
+                    $table = $this->_queryComponents[$componentAlias]['table'];
+
+                    $field = $table->getColumnName($field);
+
+                    // check column existence
+                    if ( ! $table->hasColumn($field)) {
+                        throw new Doctrine_Query_Exception('Unknown column ' . $field);
+                    }
+
+                    $sqlTableAlias = $this->getSqlTableAlias($componentAlias);
+
+                    $tableAliases[$sqlTableAlias] = true;
+
+                    // build sql expression
+
+                    $identifier = $this->_conn->quoteIdentifier($sqlTableAlias . '.' . $field);
+                    $expression = str_replace($component, $identifier, $expression);
+                }
+            }
+
+            if (count($tableAliases) !== 1) {
+                $componentAlias = reset($this->_tableAliasMap);
+                $tableAlias = key($this->_tableAliasMap);
+            }
+
+            $index    = count($this->_aggregateAliasMap);
+            $sqlAlias = $this->_conn->quoteIdentifier($tableAlias . '__' . $index);
+
+            $this->_sqlParts['select'][] = $expression . ' AS ' . $sqlAlias;
+
+            $this->_aggregateAliasMap[$alias] = $sqlAlias;
+            $this->_expressionMap[$alias][0] = $expression;
+
+            $this->_queryComponents[$componentAlias]['agg'][$index] = $alias;
+
+            $this->_neededTables[] = $tableAlias;
+        }
+        // reset the state
+        $this->_pendingAggregates = array();
+    }
+
+    /**
+     * _buildSqlQueryBase
+     * returns the base of the generated sql query
+     * On mysql driver special strategy has to be used for DELETE statements
+     * (where is this special strategy??)
+     *
+     * @return string       the base of the generated sql query
+     */
+    protected function _buildSqlQueryBase()
+    {
+        switch ($this->_type) {
+            case self::DELETE:
+                $q = 'DELETE FROM ';
+            break;
+            case self::UPDATE:
+                $q = 'UPDATE ';
+            break;
+            case self::SELECT:
+                $distinct = ($this->_sqlParts['distinct']) ? 'DISTINCT ' : '';
+                $q = 'SELECT ' . $distinct . implode(', ', $this->_sqlParts['select']) . ' FROM ';
+            break;
+        }
+        return $q;
+    }
+
+    /**
+     * _buildSqlFromPart
+     * builds the from part of the query and returns it
+     *
+     * @return string   the query sql from part
+     */
+    protected function _buildSqlFromPart()
+    {
+        $q = '';
+        foreach ($this->_sqlParts['from'] as $k => $part) {
+            if ($k === 0) {
+                $q .= $part;
+                continue;
+            }
+
+            // preserve LEFT JOINs only if needed
+            // Check if it's JOIN, if not add a comma separator instead of space
+            if (!preg_match('/\bJOIN\b/i', $part) && !isset($this->_pendingJoinConditions[$k])) {
+                $q .= ', ' . $part;
+            } else {
+                $e = explode(' ', $part);
+
+                if (substr($part, 0, 9) === 'LEFT JOIN') {
+                    $aliases = array_merge($this->_subqueryAliases,
+                                array_keys($this->_neededTables));
+
+                    if ( ! in_array($e[3], $aliases) &&
+                        ! in_array($e[2], $aliases) &&
+
+                        ! empty($this->_pendingFields)) {
+                        continue;
+                    }
+
+                }
+
+                if (isset($this->_pendingJoinConditions[$k])) {
+                    $parser = new Doctrine_Query_JoinCondition($this, $this->_tokenizer);
+
+                    if (strpos($part, ' ON ') !== false) {
+                        $part .= ' AND ';
+                    } else {
+                        $part .= ' ON ';
+                    }
+                    $part .= $parser->parse($this->_pendingJoinConditions[$k]);
+
+                    unset($this->_pendingJoinConditions[$k]);
+                }
+
+                $componentAlias = $this->getComponentAlias($e[3]);
+
+                $string = $this->getInheritanceCondition($componentAlias);
+
+                if ($string) {
+                    $part = $part . ' AND ' . $string;
+                }
+                $q .= ' ' . $part;
+            }
+
+            $this->_sqlParts['from'][$k] = $part;
+        }
+        return $q;
+    }
+
+    /**
+     * builds the sql query from the given parameters and applies things such as
+     * column aggregation inheritance and limit subqueries if needed
+     *
+     * @param array $params             an array of prepared statement params (needed only in mysql driver
+     *                                  when limit subquery algorithm is used)
+     * @return string                   the built sql query
+     */
+    public function getSqlQuery($params = array())
+    {
+        if ($this->_state !== self::STATE_DIRTY) {
+           return $this->_sql;
+        }
+
+        // reset the state
+        if ( ! $this->isSubquery()) {
+            $this->_queryComponents = array();
+            $this->_pendingAggregates = array();
+            $this->_aggregateAliasMap = array();
+        }
+        $this->reset();
+
+        // invoke the preQuery hook
+        $this->_preQuery();
+
+        // process the DQL parts => generate the SQL parts.
+        // this will also populate the $_queryComponents.
+        foreach ($this->_dqlParts as $queryPartName => $queryParts) {
+            // If we are parsing FROM clause, we'll need to diff the queryComponents later
+            if ($queryPartName == 'from') {
+                // Pick queryComponents before processing
+                $queryComponentsBefore = $this->getQueryComponents();
+            }
+
+            // FIX #1667: _sqlParts are cleaned inside _processDqlQueryPart.
+            if ($queryPartName != 'forUpdate') {
+                $this->_processDqlQueryPart($queryPartName, $queryParts);
+            }
+
+            // We need to define the root alias
+            if ($queryPartName == 'from') {
+                // Pick queryComponents aftr processing
+                $queryComponentsAfter = $this->getQueryComponents();
+                
+                // Root alias is the key of difference of query components
+                $this->_rootAlias = key(array_diff_key($queryComponentsAfter, $queryComponentsBefore));
+            }
+        }
+        $this->_state = self::STATE_CLEAN;
+
+        // Proceed with the generated SQL
+
+        if (empty($this->_sqlParts['from'])) {
+            return false;
+        }
+
+        $needsSubQuery = false;
+        $subquery = '';
+        $map = $this->getRootDeclaration();
+        $table = $map['table'];
+        $rootAlias = $this->getRootAlias();
+
+        if ( ! empty($this->_sqlParts['limit']) && $this->_needsSubquery &&
+                $table->getAttribute(Doctrine::ATTR_QUERY_LIMIT) == Doctrine::LIMIT_RECORDS) {
+            // We do not need a limit-subquery if only fields from the root component are
+            // selected and DISTINCT is used (i.e. DQL: SELECT DISTINCT u.id FROM User u LEFT JOIN u.phonenumbers LIMIT 5).
+            if (count($this->_pendingFields) > 1 || ! isset($this->_pendingFields[$this->getRootAlias()])
+                    || ! $this->_sqlParts['distinct']) {
+                $this->_isLimitSubqueryUsed = true;
+                $needsSubQuery = true;
+            }
+        }
+
+        $sql = array();
+        if ( ! empty($this->_pendingFields)) {
+            foreach ($this->_queryComponents as $alias => $map) {
+                $fieldSql = $this->processPendingFields($alias);
+                if ( ! empty($fieldSql)) {
+                    $sql[] = $fieldSql;
+                }
+            }
+        }
+        if ( ! empty($sql)) {
+            array_unshift($this->_sqlParts['select'], implode(', ', $sql));
+        }
+
+        $this->_pendingFields = array();
+
+        // build the basic query
+        $q  = $this->_buildSqlQueryBase();
+        $q .= $this->_buildSqlFromPart();
+
+        if ( ! empty($this->_sqlParts['set'])) {
+            $q .= ' SET ' . implode(', ', $this->_sqlParts['set']);
+        }
+
+        $string = $this->getInheritanceCondition($this->getRootAlias());
+
+        // apply inheritance to WHERE part
+        if ( ! empty($string)) {
+            if (count($this->_sqlParts['where']) > 0) {
+                $this->_sqlParts['where'][] = 'AND';
+            }
+
+            if (substr($string, 0, 1) === '(' && substr($string, -1) === ')') {
+                $this->_sqlParts['where'][] = $string;
+            } else {
+                $this->_sqlParts['where'][] = '(' . $string . ')';
+            }
+        }
+
+        $modifyLimit = true;
+
+        if ( ( ! empty($this->_sqlParts['limit']) || ! empty($this->_sqlParts['offset'])) && $needsSubQuery) {
+            $subquery = $this->getLimitSubquery();
+            
+            // what about composite keys?
+            $idColumnName = $table->getColumnName($table->getIdentifier());
+
+            switch (strtolower($this->_conn->getDriverName())) {
+                case 'mysql':
+                    $this->useQueryCache(false);
+            
+                    // mysql doesn't support LIMIT in subqueries
+                    $list = $this->_conn->execute($subquery, $params)->fetchAll(Doctrine::FETCH_COLUMN);
+                    $subquery = implode(', ', array_map(array($this->_conn, 'quote'), $list));
+
+                    break;
+
+                case 'pgsql':
+                    $subqueryAlias = $this->_conn->quoteIdentifier('doctrine_subquery_alias');
+
+                    // pgsql needs special nested LIMIT subquery
+                    $subquery = 'SELECT ' . $subqueryAlias . '.' . $this->_conn->quoteIdentifier($idColumnName)
+                            . ' FROM (' . $subquery . ') AS ' . $subqueryAlias;
+
+                    break;
+            }
+
+            // only append the subquery if it actually contains something
+            if (count($this->_sqlParts['where']) > 0) {
+                array_unshift($this->_sqlParts['where'], 'AND');
+            }
+
+            $field = $this->getSqlTableAlias($rootAlias) . '.' . $idColumnName;
+
+            // FIX #1868: If not ID under MySQL is found to be restricted, restrict pk column for null
+            //            (which will lead to a return of 0 items)
+            array_unshift(
+                $this->_sqlParts['where'], $this->_conn->quoteIdentifier($field) .
+                (( ! empty($subquery)) ? ' IN (' . $subquery . ')' : ' IS NULL')
+            );
+
+            $modifyLimit = false;
+        }
+
+        $q .= ( ! empty($this->_sqlParts['where']))?   ' WHERE '    . implode(' ', $this->_sqlParts['where']) : '';
+        $q .= ( ! empty($this->_sqlParts['groupby']))? ' GROUP BY ' . implode(', ', $this->_sqlParts['groupby'])  : '';
+        $q .= ( ! empty($this->_sqlParts['having']))?  ' HAVING '   . implode(' AND ', $this->_sqlParts['having']): '';
+        $q .= ( ! empty($this->_sqlParts['orderby']))? ' ORDER BY ' . implode(', ', $this->_sqlParts['orderby'])  : '';
+
+        if ($modifyLimit) {
+            $q = $this->_conn->modifyLimitQuery($q, $this->_sqlParts['limit'], $this->_sqlParts['offset']);
+        }
+
+        $q .= $this->_sqlParts['forUpdate'] === true ? ' FOR UPDATE ' : '';
+
+        // return to the previous state
+        if ( ! empty($string)) {
+            // We need to double pop if > 2
+            if (count($this->_sqlParts['where']) > 2) {
+                array_pop($this->_sqlParts['where']);
+            }
+
+            array_pop($this->_sqlParts['where']);
+        }
+
+        if ($needsSubQuery) {
+            // We need to double shift if > 2
+            if (count($this->_sqlParts['where']) > 2) {
+                array_shift($this->_sqlParts['where']);
+            }
+
+            array_shift($this->_sqlParts['where']);
+        }
+
+        $this->_sql = $q;
+
+        return $q;
+    }
+
+    /**
+     * getLimitSubquery
+     * this is method is used by the record limit algorithm
+     *
+     * when fetching one-to-many, many-to-many associated data with LIMIT clause
+     * an additional subquery is needed for limiting the number of returned records instead
+     * of limiting the number of sql result set rows
+     *
+     * @return string       the limit subquery
+     * @todo A little refactor to make the method easier to understand & maybe shorter?
+     */
+    public function getLimitSubquery()
+    {
+        $map = reset($this->_queryComponents);
+        $table = $map['table'];
+        $componentAlias = key($this->_queryComponents);
+
+        // get short alias
+        $alias = $this->getTableAlias($componentAlias);
+        // what about composite keys?
+        $primaryKey = $alias . '.' . $table->getColumnName($table->getIdentifier());
+
+        $driverName = $this->_conn->getAttribute(Doctrine::ATTR_DRIVER_NAME);
+
+        // initialize the base of the subquery
+        if (($driverName == 'oracle' || $driverName == 'oci') && $this->_isOrderedByJoinedColumn()) {
+            $subquery = 'SELECT ';
+        } else {
+            $subquery = 'SELECT DISTINCT ';
+        }
+        $subquery .= $this->_conn->quoteIdentifier($primaryKey);
+
+        // pgsql & oracle need the order by fields to be preserved in select clause
+        if ($driverName == 'pgsql' || $driverName == 'oracle' || $driverName == 'oci') {
+            foreach ($this->_sqlParts['orderby'] as $part) {
+                // Remove identifier quoting if it exists
+				$e = $this->_tokenizer->bracketExplode($part, ' ');
+                $part_original = trim($e[0]);
+                $callback = create_function('$e', 'return trim($e, \'[]`"\');');
+                $part = trim(implode('.', array_map($callback, explode('.', $part_original))));
+
+                if (strpos($part, '.') === false) {
+                    continue;
+                }
+
+                // don't add functions
+                if (strpos($part, '(') !== false) {
+                    continue;
+                }
+
+                // don't add primarykey column (its already in the select clause)
+                if ($part !== $primaryKey) {
+                    $subquery .= ', ' . $part_original;
+                }
+            }
+        }
+
+        if ($driverName == 'mysql' || $driverName == 'pgsql') {
+            foreach ($this->_expressionMap as $dqlAlias => $expr) {
+                if (isset($expr[1])) {
+                    $subquery .= ', ' . $expr[0] . ' AS ' . $this->_aggregateAliasMap[$dqlAlias];
+                }
+            }
+        }
+
+        $subquery .= ' FROM';
+
+        foreach ($this->_sqlParts['from'] as $part) {
+            // preserve LEFT JOINs only if needed
+            if (substr($part, 0, 9) === 'LEFT JOIN') {
+                $e = explode(' ', $part);
+
+                if (empty($this->_sqlParts['orderby']) && empty($this->_sqlParts['where']) && empty($this->_sqlParts['having'])) {
+                    continue;
+                }
+            }
+
+            $subquery .= ' ' . $part;
+        }
+
+        // all conditions must be preserved in subquery
+        $subquery .= ( ! empty($this->_sqlParts['where']))?   ' WHERE '    . implode(' ', $this->_sqlParts['where'])  : '';
+        $subquery .= ( ! empty($this->_sqlParts['groupby']))? ' GROUP BY ' . implode(', ', $this->_sqlParts['groupby'])   : '';
+        $subquery .= ( ! empty($this->_sqlParts['having']))?  ' HAVING '   . implode(' AND ', $this->_sqlParts['having']) : '';
+        $subquery .= ( ! empty($this->_sqlParts['orderby']))? ' ORDER BY ' . implode(', ', $this->_sqlParts['orderby'])   : '';
+
+        if (($driverName == 'oracle' || $driverName == 'oci') && $this->_isOrderedByJoinedColumn()) {
+            // When using "ORDER BY x.foo" where x.foo is a column of a joined table,
+            // we may get duplicate primary keys because all columns in ORDER BY must appear
+            // in the SELECT list when using DISTINCT. Hence we need to filter out the
+            // primary keys with an additional DISTINCT subquery.
+            // #1038
+            $subquery = 'SELECT doctrine_subquery_alias.' . $table->getColumnName($table->getIdentifier())
+                    . ' FROM (' . $subquery . ') doctrine_subquery_alias'
+                    . ' GROUP BY doctrine_subquery_alias.' . $table->getColumnName($table->getIdentifier())
+                    . ' ORDER BY MIN(ROWNUM)';
+        }
+
+        // add driver specific limit clause
+        $subquery = $this->_conn->modifyLimitSubquery($table, $subquery, $this->_sqlParts['limit'], $this->_sqlParts['offset']);
+
+        $parts = $this->_tokenizer->quoteExplode($subquery, ' ', "'", "'");
+
+        foreach ($parts as $k => $part) {
+            if (strpos($part, ' ') !== false) {
+                continue;
+            }
+
+            $part = str_replace(array('"', "'", '`'), "", $part);
+
+            if ($this->hasSqlTableAlias($part)) {
+                $parts[$k] = $this->_conn->quoteIdentifier($this->generateNewSqlTableAlias($part));
+                continue;
+            }
+
+            if (strpos($part, '.') === false) {
+                continue;
+            }
+
+            preg_match_all("/[a-zA-Z0-9_]+\.[a-z0-9_]+/i", $part, $m);
+
+            foreach ($m[0] as $match) {
+                $e = explode('.', $match);
+
+                // Rebuild the original part without the newly generate alias and with quoting reapplied
+                $e2 = array();
+                foreach ($e as $k2 => $v2) {
+                  $e2[$k2] = $this->_conn->quoteIdentifier($v2);
+                }
+                $match = implode('.', $e2);
+
+                // Generate new table alias
+                $e[0] = $this->generateNewSqlTableAlias($e[0]);
+
+                // Requote the part with the newly generated alias
+                foreach ($e as $k2 => $v2) {
+                  $e[$k2] = $this->_conn->quoteIdentifier($v2);
+                }
+
+                $replace = implode('.' , $e);
+
+                // Replace the original part with the new part with new sql table alias
+                $parts[$k] = str_replace($match, $replace, $parts[$k]);
+            }
+        }
+
+        if ($driverName == 'mysql' || $driverName == 'pgsql') {
+            foreach ($parts as $k => $part) {
+                if (strpos($part, "'") !== false) {
+                    continue;
+                }
+                if (strpos($part, '__') == false) {
+                    continue;
+                }
+
+                preg_match_all("/[a-zA-Z0-9_]+\_\_[a-z0-9_]+/i", $part, $m);
+
+                foreach ($m[0] as $match) {
+                    $e = explode('__', $match);
+                    $e[0] = $this->generateNewTableAlias($e[0]);
+
+                    $parts[$k] = str_replace($match, implode('__', $e), $parts[$k]);
+                }
+            }
+        }
+
+        $subquery = implode(' ', $parts);
+        return $subquery;
+    }
+
+    /**
+     * Checks whether the query has an ORDER BY on a column of a joined table.
+     * This information is needed in special scenarios like the limit-offset when its
+     * used with an Oracle database.
+     *
+     * @return boolean  TRUE if the query is ordered by a joined column, FALSE otherwise.
+     */
+    private function _isOrderedByJoinedColumn() {
+        if ( ! $this->_queryComponents) {
+            throw new Doctrine_Query_Exception("The query is in an invalid state for this "
+                    . "operation. It must have been fully parsed first.");
+        }
+        $componentAlias = key($this->_queryComponents);
+        $mainTableAlias = $this->getTableAlias($componentAlias);
+        foreach ($this->_sqlParts['orderby'] as $part) {
+            $part = trim($part);
+            $e = $this->_tokenizer->bracketExplode($part, ' ');
+            $part = trim($e[0]);
+            if (strpos($part, '.') === false) {
+                continue;
+            }
+            list($tableAlias, $columnName) = explode('.', $part);
+            if ($tableAlias != $mainTableAlias) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * DQL PARSER
+     * parses a DQL query
+     * first splits the query in parts and then uses individual
+     * parsers for each part
+     *
+     * @param string $query                 DQL query
+     * @param boolean $clear                whether or not to clear the aliases
+     * @throws Doctrine_Query_Exception     if some generic parsing error occurs
+     * @return Doctrine_Query
+     */
+    public function parseDqlQuery($query, $clear = true)
+    {
+        if ($clear) {
+            $this->clear();
+        }
+
+        $query = trim($query);
+        $query = str_replace("\r", "\n", str_replace("\r\n", "\n", $query));
+        $query = str_replace("\n", ' ', $query);
+
+        $parts = $this->_tokenizer->tokenizeQuery($query);
+
+        foreach ($parts as $partName => $subParts) {
+            $subParts = trim($subParts);
+            $partName = strtolower($partName);
+            switch ($partName) {
+                case 'create':
+                    $this->_type = self::CREATE;
+                break;
+                case 'insert':
+                    $this->_type = self::INSERT;
+                break;
+                case 'delete':
+                    $this->_type = self::DELETE;
+                break;
+                case 'select':
+                    $this->_type = self::SELECT;
+                    $this->_addDqlQueryPart($partName, $subParts);
+                break;
+                case 'update':
+                    $this->_type = self::UPDATE;
+                    $partName = 'from';
+                case 'from':
+                    $this->_addDqlQueryPart($partName, $subParts);
+                break;
+                case 'set':
+                    $this->_addDqlQueryPart($partName, $subParts, true);
+                break;
+                case 'group':
+                case 'order':
+                    $partName .= 'by';
+                case 'where':
+                case 'having':
+                case 'limit':
+                case 'offset':
+                    $this->_addDqlQueryPart($partName, $subParts);
+                break;
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * @todo Describe & refactor... too long and nested.
+     */
+    public function load($path, $loadFields = true)
+    {
+        if (isset($this->_queryComponents[$path])) {
+            return $this->_queryComponents[$path];
+        }
+
+        $e = $this->_tokenizer->quoteExplode($path, ' INDEXBY ');
+
+        $mapWith = null;
+        if (count($e) > 1) {
+            $mapWith = trim($e[1]);
+
+            $path = $e[0];
+        }
+
+        // parse custom join conditions
+        $e = explode(' ON ', str_ireplace(' on ', ' ON ', $path));
+
+        $joinCondition = '';
+
+        if (count($e) > 1) {
+            $joinCondition = substr($path, strlen($e[0]) + 4, strlen($e[1]));
+            $path = substr($path, 0, strlen($e[0]));
+
+            $overrideJoin = true;
+        } else {
+            $e = explode(' WITH ', str_ireplace(' with ', ' WITH ', $path));
+
+            if (count($e) > 1) {
+                $joinCondition = substr($path, strlen($e[0]) + 6, strlen($e[1]));
+                $path = substr($path, 0, strlen($e[0]));
+            }
+
+            $overrideJoin = false;
+        }
+
+        $tmp            = explode(' ', $path);
+        $componentAlias = $originalAlias = (count($tmp) > 1) ? end($tmp) : null;
+
+        $e = preg_split("/[.:]/", $tmp[0], -1);
+
+        $fullPath = $tmp[0];
+        $prevPath = '';
+        $fullLength = strlen($fullPath);
+
+        if (isset($this->_queryComponents[$e[0]])) {
+            $table = $this->_queryComponents[$e[0]]['table'];
+            $componentAlias = $e[0];
+
+            $prevPath = $parent = array_shift($e);
+        }
+
+        foreach ($e as $key => $name) {
+            // get length of the previous path
+            $length = strlen($prevPath);
+
+            // build the current component path
+            $prevPath = ($prevPath) ? $prevPath . '.' . $name : $name;
+
+            $delimeter = substr($fullPath, $length, 1);
+
+            // if an alias is not given use the current path as an alias identifier
+            if (strlen($prevPath) === $fullLength && isset($originalAlias)) {
+                $componentAlias = $originalAlias;
+            } else {
+                $componentAlias = $prevPath;
+            }
+
+            // if the current alias already exists, skip it
+            if (isset($this->_queryComponents[$componentAlias])) {
+                throw new Doctrine_Query_Exception("Duplicate alias '$componentAlias' in query.");
+            }
+
+            if ( ! isset($table)) {
+                // process the root of the path
+
+                $table = $this->loadRoot($name, $componentAlias);
+            } else {
+                $join = ($delimeter == ':') ? 'INNER JOIN ' : 'LEFT JOIN ';
+
+                $relation = $table->getRelation($name);
+                $localTable = $table;
+
+                $table = $relation->getTable();
+                $this->_queryComponents[$componentAlias] = array('table' => $table,
+                                                                 'parent'   => $parent,
+                                                                 'relation' => $relation,
+                                                                 'map'      => null);
+                if ( ! $relation->isOneToOne()) {
+                   $this->_needsSubquery = true;
+                }
+
+                $localAlias   = $this->getTableAlias($parent, $localTable->getTableName());
+                $foreignAlias = $this->getTableAlias($componentAlias, $relation->getTable()->getTableName());
+
+                $foreignSql   = $this->_conn->quoteIdentifier($relation->getTable()->getTableName())
+                              . ' '
+                              . $this->_conn->quoteIdentifier($foreignAlias);
+
+                $map = $relation->getTable()->inheritanceMap;
+
+                if ( ! $loadFields || ! empty($map) || $joinCondition) {
+                    $this->_subqueryAliases[] = $foreignAlias;
+                }
+
+                if ($relation instanceof Doctrine_Relation_Association) {
+                    $asf = $relation->getAssociationTable();
+
+                    $assocTableName = $asf->getTableName();
+
+                    if ( ! $loadFields || ! empty($map) || $joinCondition) {
+                        $this->_subqueryAliases[] = $assocTableName;
+                    }
+
+                    $assocPath = $prevPath . '.' . $asf->getComponentName();
+
+                    $this->_queryComponents[$assocPath] = array(
+                        'parent' => $prevPath,
+                        'relation' => $relation,
+                        'table' => $asf);
+
+                    $assocAlias = $this->getTableAlias($assocPath, $asf->getTableName());
+
+                    $queryPart = $join
+                            . $this->_conn->quoteIdentifier($assocTableName)
+                            . ' '
+                            . $this->_conn->quoteIdentifier($assocAlias);
+
+                    $queryPart .= ' ON (' . $this->_conn->quoteIdentifier($localAlias
+                                . '.'
+                                . $localTable->getColumnName($localTable->getIdentifier())) // what about composite keys?
+                                . ' = '
+                                . $this->_conn->quoteIdentifier($assocAlias . '.' . $relation->getLocalRefColumnName());
+
+                    if ($relation->isEqual()) {
+                        // equal nest relation needs additional condition
+                        $queryPart .= ' OR '
+                                    . $this->_conn->quoteIdentifier($localAlias
+                                    . '.'
+                                    . $table->getColumnName($table->getIdentifier()))
+                                    . ' = '
+                                    . $this->_conn->quoteIdentifier($assocAlias . '.' . $relation->getForeignRefColumnName());
+                    }
+
+                    $queryPart .= ')';
+
+                    $this->_sqlParts['from'][] = $queryPart;
+
+                    $queryPart = $join . $foreignSql;
+
+                    if ( ! $overrideJoin) {
+                        $queryPart .= $this->buildAssociativeRelationSql($relation, $assocAlias, $foreignAlias, $localAlias);
+                    }
+                } else {
+                    $queryPart = $this->buildSimpleRelationSql($relation, $foreignAlias, $localAlias, $overrideJoin, $join);
+                }
+
+                $queryPart .= $this->buildInheritanceJoinSql($table->getComponentName(), $componentAlias);
+
+                $this->_sqlParts['from'][$componentAlias] = $queryPart;
+                if ( ! empty($joinCondition)) {
+                    $this->_pendingJoinConditions[$componentAlias] = $joinCondition;
+                }
+            }
+            if ($loadFields) {
+
+                $restoreState = false;
+                // load fields if necessary
+                if ($loadFields && empty($this->_dqlParts['select'])) {
+                    $this->_pendingFields[$componentAlias] = array('*');
+                }
+            }
+            $parent = $prevPath;
+        }
+
+        $table = $this->_queryComponents[$componentAlias]['table'];
+
+        return $this->buildIndexBy($componentAlias, $mapWith);
+    }
+
+    protected function buildSimpleRelationSql(Doctrine_Relation $relation, $foreignAlias, $localAlias, $overrideJoin, $join)
+    {
+        $queryPart = $join . $this->_conn->quoteIdentifier($relation->getTable()->getTableName())
+                           . ' '
+                           . $this->_conn->quoteIdentifier($foreignAlias);
+
+        if ( ! $overrideJoin) {
+            $queryPart .= ' ON '
+                       . $this->_conn->quoteIdentifier($localAlias . '.' . $relation->getLocalColumnName())
+                       . ' = '
+                       . $this->_conn->quoteIdentifier($foreignAlias . '.' . $relation->getForeignColumnName());
+        }
+
+        return $queryPart;
+    }
+
+    protected function buildIndexBy($componentAlias, $mapWith = null)
+    {
+        $table = $this->_queryComponents[$componentAlias]['table'];
+
+        $indexBy = null;
+
+        if (isset($mapWith)) {
+            $terms = explode('.', $mapWith);
+
+            if (isset($terms[1])) {
+                $indexBy = $terms[1];
+            }
+        } elseif ($table->getBoundQueryPart('indexBy') !== null) {
+            $indexBy = $table->getBoundQueryPart('indexBy');
+        }
+
+        if ($indexBy !== null) {
+            if ( ! $table->hasColumn($table->getColumnName($indexBy))) {
+                throw new Doctrine_Query_Exception("Couldn't use key mapping. Column " . $indexBy . " does not exist.");
+            }
+
+            $this->_queryComponents[$componentAlias]['map'] = $indexBy;
+        }
+
+        return $this->_queryComponents[$componentAlias];
+    }
+
+
+    protected function buildAssociativeRelationSql(Doctrine_Relation $relation, $assocAlias, $foreignAlias, $localAlias)
+    {
+        $table = $relation->getTable();
+
+        $queryPart = ' ON ';
+
+        if ($relation->isEqual()) {
+            $queryPart .= '(';
+        }
+
+        $localIdentifier = $table->getColumnName($table->getIdentifier());
+
+        $queryPart .= $this->_conn->quoteIdentifier($foreignAlias . '.' . $localIdentifier)
+                    . ' = '
+                    . $this->_conn->quoteIdentifier($assocAlias . '.' . $relation->getForeignRefColumnName());
+
+        if ($relation->isEqual()) {
+            $queryPart .= ' OR '
+                        . $this->_conn->quoteIdentifier($foreignAlias . '.' . $localIdentifier)
+                        . ' = '
+                        . $this->_conn->quoteIdentifier($assocAlias . '.' . $relation->getLocalRefColumnName())
+                        . ') AND '
+                        . $this->_conn->quoteIdentifier($foreignAlias . '.' . $localIdentifier)
+                        . ' != '
+                        . $this->_conn->quoteIdentifier($localAlias . '.' . $localIdentifier);
+        }
+
+        return $queryPart;
+    }
+    /**
+     * loadRoot
+     *
+     * @param string $name
+     * @param string $componentAlias
+     * @todo DESCRIBE ME!
+     */
+    public function loadRoot($name, $componentAlias)
+    {
+        // get the connection for the component
+        $manager = Doctrine_Manager::getInstance();
+        if ($manager->hasConnectionForComponent($name)) {
+            $this->_conn = $manager->getConnectionForComponent($name);
+        }
+
+        $table = $this->_conn->getTable($name);
+        $tableName = $table->getTableName();
+
+        // get the short alias for this table
+        $tableAlias = $this->getTableAlias($componentAlias, $tableName);
+        // quote table name
+        $queryPart = $this->_conn->quoteIdentifier($tableName);
+
+        if ($this->_type === self::SELECT) {
+            $queryPart .= ' ' . $this->_conn->quoteIdentifier($tableAlias);
+        }
+
+        $this->_tableAliasMap[$tableAlias] = $componentAlias;
+
+        $queryPart .= $this->buildInheritanceJoinSql($name, $componentAlias);
+
+        $this->_sqlParts['from'][] = $queryPart;
+
+        $this->_queryComponents[$componentAlias] = array('table' => $table, 'map' => null);
+
+        return $table;
+    }
+
+    /**
+     * @todo DESCRIBE ME!
+     */
+    public function buildInheritanceJoinSql($name, $componentAlias)
+    {
+        // get the connection for the component
+        $manager = Doctrine_Manager::getInstance();
+        if ($manager->hasConnectionForComponent($name)) {
+            $this->_conn = $manager->getConnectionForComponent($name);
+        }
+
+        $table = $this->_conn->getTable($name);
+        $tableName = $table->getTableName();
+
+        // get the short alias for this table
+        $tableAlias = $this->getTableAlias($componentAlias, $tableName);
+
+        $queryPart = '';
+
+        foreach ($table->getOption('joinedParents') as $parent) {
+        	$parentTable = $this->_conn->getTable($parent);
+
+            $parentAlias = $componentAlias . '.' . $parent;
+
+            // get the short alias for the parent table
+            $parentTableAlias = $this->getTableAlias($parentAlias, $parentTable->getTableName());
+
+            $queryPart .= ' LEFT JOIN ' . $this->_conn->quoteIdentifier($parentTable->getTableName())
+                        . ' ' . $this->_conn->quoteIdentifier($parentTableAlias) . ' ON ';
+
+            //Doctrine::dump($table->getIdentifier());
+            foreach ((array) $table->getIdentifier() as $identifier) {
+                $column = $table->getColumnName($identifier);
+
+                $queryPart .= $this->_conn->quoteIdentifier($tableAlias)
+                            . '.' . $this->_conn->quoteIdentifier($column)
+                            . ' = ' . $this->_conn->quoteIdentifier($parentTableAlias)
+                            . '.' . $this->_conn->quoteIdentifier($column);
+            }
+        }
+
+        return $queryPart;
+    }
+
+    /**
+     * Get count sql query for this Doctrine_Query instance
+     * Used in Doctrine_Query::count() for returning an integer for the number of records which will
+     * be returned when executed.
+     *
+     * @return string $q
+     */
+    public function getCountQuery()
+    {
+        // triggers dql parsing/processing
+        $this->getSqlQuery(); // this is ugly
+
+        // initialize temporary variables
+        $where   = $this->_sqlParts['where'];
+        $having  = $this->_sqlParts['having'];
+        $groupby = $this->_sqlParts['groupby'];
+
+        $rootAlias = $this->getRootAlias();
+        $tableAlias = $this->getTableAlias($rootAlias);
+
+        // Build the query base
+        $q = 'SELECT COUNT(*) AS ' . $this->_conn->quoteIdentifier('num_results') . ' FROM ';
+
+        // Build the from clause
+        $from = $this->_buildSqlFromPart();
+
+        // Append column aggregation inheritance (if needed)
+        $string = $this->getInheritanceCondition($rootAlias);
+
+        if ( ! empty($string)) {
+            if ( ! empty($where)) {
+                $where[] = 'AND';
+            }
+
+            $where[] = $string;
+        }
+
+        // Build the where clause
+        $where = ( ! empty($where)) ? ' WHERE ' . implode(' ', $where) : '';
+
+        // Build the group by clause
+        $groupby = ( ! empty($groupby)) ? ' GROUP BY ' . implode(', ', $groupby) : '';
+
+        // Build the having clause
+        $having = ( ! empty($having)) ? ' HAVING ' . implode(' AND ', $having) : '';
+
+        // Building the from clause and finishing query
+        if (count($this->_queryComponents) == 1 && empty($having)) {
+            $q .= $from . $where . $groupby . $having;
+        } else {
+            // Subselect fields will contain only the pk of root entity
+            $ta = $this->_conn->quoteIdentifier($tableAlias);
+
+            $map = $this->getRootDeclaration();
+            $idColumnNames = $map['table']->getIdentifierColumnNames();
+            
+            $pkFields = $ta . '.' . implode(', ' . $ta . '.', $this->_conn->quoteMultipleIdentifier($idColumnNames));
+
+            // We need to do some magic in select fields if the query contain anything in having clause
+            $selectFields = $pkFields;
+
+            if ( ! empty($having)) {
+                // For each field defined in select clause
+                foreach ($this->_sqlParts['select'] as $field) {
+                    // We only include aggregate expressions to count query
+                    // This is needed because HAVING clause will use field aliases
+                    if (strpos($field, '(') !== false) {
+                        $selectFields .= ', ' . $field;
+                    }
+                }
+            }
+
+            // If we do not have a custom group by, apply the default one
+            if (empty($groupby)) {
+                $groupby = ' GROUP BY ' . $pkFields;
+            }
+
+            $q .= '(SELECT ' . $selectFields . ' FROM ' . $from . $where . $groupby . $having . ') '
+                . $this->_conn->quoteIdentifier('dctrn_count_query');
+        }
+
+        return $q;
+    }
+
+    /**
+     * count
+     * fetches the count of the query
+     *
+     * This method executes the main query without all the
+     * selected fields, ORDER BY part, LIMIT part and OFFSET part.
+     *
+     * Example:
+     * Main query:
+     *      SELECT u.*, p.phonenumber FROM User u
+     *          LEFT JOIN u.Phonenumber p
+     *          WHERE p.phonenumber = '123 123' LIMIT 10
+     *
+     * The modified DQL query:
+     *      SELECT COUNT(DISTINCT u.id) FROM User u
+     *          LEFT JOIN u.Phonenumber p
+     *          WHERE p.phonenumber = '123 123'
+     *
+     * @param array $params        an array of prepared statement parameters
+     * @return integer             the count of this query
+     */
+    public function count($params = array())
+    {
+        $q = $this->getCountQuery();
+
+        if ( ! is_array($params)) {
+            $params = array($params);
+        }
+
+        $params = array_merge($this->_params['join'], $this->_params['where'], $this->_params['having'], $params);
+        $params = $this->_conn->convertBooleans($params);
+
+        $results = $this->getConnection()->fetchAll($q, $params);
+
+        if (count($results) > 1) {
+            $count = count($results);
+        } else {
+            if (isset($results[0])) {
+                $results[0] = array_change_key_case($results[0], CASE_LOWER);
+                $count = $results[0]['num_results'];
+            } else {
+                $count = 0;
+            }
+        }
+
+        return (int) $count;
+    }
+
+    /**
+     * query
+     * query the database with DQL (Doctrine Query Language)
+     *
+     * @param string $query      DQL query
+     * @param array $params      prepared statement parameters
+     * @param int $hydrationMode Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD
+     * @see Doctrine::FETCH_* constants
+     * @return mixed
+     */
+    public function query($query, $params = array(), $hydrationMode = null)
+    {
+        $this->parseDqlQuery($query);
+        return $this->execute($params, $hydrationMode);
+    }
+
+    /**
+     * Copies a Doctrine_Query object.
+     *
+     * @return Doctrine_Query  Copy of the Doctrine_Query instance.
+     */
+    public function copy(Doctrine_Query $query = null)
+    {
+        if ( ! $query) {
+            $query = $this;
+        }
+
+        $new = clone $query;
+
+        return $new;
+    }
+
+    /**
+     * __clone
+     *
+     * @return void
+     */
+    public function __clone()
+    {
+        $this->_parsers = array();
+
+        // Subqueries share some information from the parent so it can intermingle
+        // with the dql of the main query. So when a subquery is cloned we need to
+        // kill those references or it causes problems
+        if ($this->isSubquery()) {
+            $this->_killReference('_params');
+            $this->_killReference('_tableAliasMap');
+            $this->_killReference('_queryComponents');
+        }
+    }
+
+    /**
+     * Kill the reference for the passed class property.
+     * This method simply copies the value to a temporary variable and then unsets
+     * the reference and re-assigns the old value but not by reference
+     *
+     * @param string $key
+     */
+    protected function _killReference($key)
+    {
+        $tmp = $this->$key;
+        unset($this->$key);
+        $this->$key = $tmp;
+    }
+
+    /**
+     * Frees the resources used by the query object. It especially breaks a
+     * cyclic reference between the query object and it's parsers. This enables
+     * PHP's current GC to reclaim the memory.
+     * This method can therefore be used to reduce memory usage when creating a lot
+     * of query objects during a request.
+     *
+     * @return Doctrine_Query   this object
+     */
+    public function free()
+    {
+        $this->reset();
+        $this->_parsers = array();
+        $this->_dqlParts = array();
+    }
+
+    /**
+     * serialize
+     * this method is automatically called when this Doctrine_Hydrate is serialized
+     *
+     * @return array    an array of serialized properties
+     */
+    public function serialize()
+    {
+        $vars = get_object_vars($this);
+    }
+
+    /**
+     * unseralize
+     * this method is automatically called everytime a Doctrine_Hydrate object is unserialized
+     *
+     * @param string $serialized                Doctrine_Record as serialized string
+     * @return void
+     */
+    public function unserialize($serialized)
+    {
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Abstract.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,2172 @@
+<?php
+/*
+ *  $Id: Query.php 1393 2007-05-19 17:49:16Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Abstract
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1393 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @todo        See {@link Doctrine_Query}
+ */
+abstract class Doctrine_Query_Abstract
+{
+    /**
+     * QUERY TYPE CONSTANTS
+     */
+
+    /**
+     * constant for SELECT queries
+     */
+    const SELECT = 0;
+
+    /**
+     * constant for DELETE queries
+     */
+    const DELETE = 1;
+
+    /**
+     * constant for UPDATE queries
+     */
+    const UPDATE = 2;
+
+    /**
+     * constant for INSERT queries
+     */
+    const INSERT = 3;
+
+    /**
+     * constant for CREATE queries
+     */
+    const CREATE = 4;
+
+    /** @todo document the query states (and the transitions between them). */
+    /**
+     * A query object is in CLEAN state when it has NO unparsed/unprocessed DQL parts.
+     */
+    const STATE_CLEAN  = 1;
+
+    /**
+     * A query object is in state DIRTY when it has DQL parts that have not yet been
+     * parsed/processed.
+     */
+    const STATE_DIRTY  = 2;
+
+    /**
+     * A query is in DIRECT state when ... ?
+     */
+    const STATE_DIRECT = 3;
+
+    /**
+     * A query object is on LOCKED state when ... ?
+     */
+    const STATE_LOCKED = 4;
+
+    /**
+     * @var array  Table alias map. Keys are SQL aliases and values DQL aliases.
+     */
+    protected $_tableAliasMap = array();
+
+    /**
+     * @var Doctrine_View  The view object used by this query, if any.
+     */
+    protected $_view;
+
+    /**
+     * @var integer $_state   The current state of this query.
+     */
+    protected $_state = Doctrine_Query::STATE_CLEAN;
+
+    /**
+     * @var array $params  The parameters of this query.
+     */
+    protected $_params = array('join' => array(),
+                               'where' => array(),
+                               'set' => array(),
+                               'having' => array());
+
+    /* Caching properties */
+    /**
+     * @var Doctrine_Cache_Interface  The cache driver used for caching result sets.
+     */
+    protected $_resultCache;
+    /**
+     * @var boolean $_expireResultCache  A boolean value that indicates whether or not
+     *                                   expire the result cache.
+     */
+    protected $_expireResultCache = false;
+    protected $_resultCacheTTL;
+
+    /**
+     * @var Doctrine_Cache_Interface  The cache driver used for caching queries.
+     */
+    protected $_queryCache;
+    protected $_expireQueryCache = false;
+    protected $_queryCacheTTL;
+
+
+    /**
+     * @var Doctrine_Connection  The connection used by this query object.
+     */
+    protected $_conn;
+
+
+    /**
+     * @var array $_sqlParts  The SQL query string parts. Filled during the DQL parsing process.
+     */
+    protected $_sqlParts = array(
+            'select'    => array(),
+            'distinct'  => false,
+            'forUpdate' => false,
+            'from'      => array(),
+            'set'       => array(),
+            'join'      => array(),
+            'where'     => array(),
+            'groupby'   => array(),
+            'having'    => array(),
+            'orderby'   => array(),
+            'limit'     => false,
+            'offset'    => false,
+            );
+
+    /**
+     * @var array $_dqlParts                an array containing all DQL query parts
+     */
+    protected $_dqlParts = array(
+                            'from'      => array(),
+                            'select'    => array(),
+                            'forUpdate' => false,
+                            'set'       => array(),
+                            'join'      => array(),
+                            'where'     => array(),
+                            'groupby'   => array(),
+                            'having'    => array(),
+                            'orderby'   => array(),
+                            'limit'     => array(),
+                            'offset'    => array(),
+                            );
+
+
+    /**
+     * @var array $_queryComponents   Two dimensional array containing the components of this query,
+     *                                informations about their relations and other related information.
+     *                                The components are constructed during query parsing.
+     *
+     *      Keys are component aliases and values the following:
+     *
+     *          table               table object associated with given alias
+     *
+     *          relation            the relation object owned by the parent
+     *
+     *          parent              the alias of the parent
+     *
+     *          agg                 the aggregates of this component
+     *
+     *          map                 the name of the column / aggregate value this
+     *                              component is mapped to a collection
+     */
+    protected $_queryComponents = array();
+
+	/**
+     * Stores the root DQL alias
+     *
+     * @var string
+     */
+    protected $_rootAlias = '';
+
+    /**
+     * @var integer $type                   the query type
+     *
+     * @see Doctrine_Query::* constants
+     */
+    protected $_type = self::SELECT;
+
+    /**
+     * @var Doctrine_Hydrator   The hydrator object used to hydrate query results.
+     */
+    protected $_hydrator;
+
+    /**
+     * @var Doctrine_Query_Tokenizer  The tokenizer that is used during the query parsing process.
+     */
+    protected $_tokenizer;
+
+    /**
+     * @var Doctrine_Query_Parser  The parser that is used for query parsing.
+     */
+    protected $_parser;
+
+    /**
+     * @var array $_tableAliasSeeds         A simple array keys representing table aliases and values
+     *                                      table alias seeds. The seeds are used for generating short table
+     *                                      aliases.
+     */
+    protected $_tableAliasSeeds = array();
+
+    /**
+     * @var array $_options                 an array of options
+     */
+    protected $_options    = array(
+                            'hydrationMode'      => Doctrine::HYDRATE_RECORD
+                            );
+
+    /**
+     * @var boolean
+     */
+    protected $_isLimitSubqueryUsed = false;
+
+    /**
+     * @var array components used in the DQL statement
+     */
+    protected $_components;
+
+    /**
+     * @var bool Boolean variable for whether or not the preQuery process has been executed
+     */
+    protected $_preQueried = false;
+
+    /**
+     * Constructor.
+     *
+     * @param Doctrine_Connection  The connection object the query will use.
+     * @param Doctrine_Hydrator_Abstract  The hydrator that will be used for generating result sets.
+     */
+    public function __construct(Doctrine_Connection $connection = null,
+            Doctrine_Hydrator_Abstract $hydrator = null)
+    {
+        if ($connection === null) {
+            $connection = Doctrine_Manager::getInstance()->getCurrentConnection();
+        }
+        if ($hydrator === null) {
+            $hydrator = new Doctrine_Hydrator();
+        }
+        $this->_conn = $connection;
+        $this->_hydrator = $hydrator;
+        $this->_tokenizer = new Doctrine_Query_Tokenizer();
+        $this->_resultCacheTTL = $this->_conn->getAttribute(Doctrine::ATTR_RESULT_CACHE_LIFESPAN);
+        $this->_queryCacheTTL = $this->_conn->getAttribute(Doctrine::ATTR_QUERY_CACHE_LIFESPAN);
+    }
+
+    /**
+     * setOption
+     *
+     * @param string $name      option name
+     * @param string $value     option value
+     * @return Doctrine_Query   this object
+     */
+    public function setOption($name, $value)
+    {
+        if ( ! isset($this->_options[$name])) {
+            throw new Doctrine_Query_Exception('Unknown option ' . $name);
+        }
+        $this->_options[$name] = $value;
+    }
+
+    /**
+     * hasTableAlias
+     * whether or not this object has given tableAlias
+     *
+     * @param string $tableAlias    the table alias to be checked
+     * @return boolean              true if this object has given alias, otherwise false
+     * @deprecated
+     */
+    public function hasTableAlias($sqlTableAlias)
+    {
+        return $this->hasSqlTableAlias($sqlTableAlias);
+    }
+
+    /**
+     * hasSqlTableAlias
+     * whether or not this object has given tableAlias
+     *
+     * @param string $tableAlias    the table alias to be checked
+     * @return boolean              true if this object has given alias, otherwise false
+     */
+    public function hasSqlTableAlias($sqlTableAlias)
+    {
+        return (isset($this->_tableAliasMap[$sqlTableAlias]));
+    }
+
+    /**
+     * getTableAliases
+     * returns all table aliases
+     *
+     * @return array        table aliases as an array
+     * @deprecated
+     */
+    public function getTableAliases()
+    {
+        return $this->getTableAliasMap();
+    }
+
+    /**
+     * getTableAliasMap
+     * returns all table aliases
+     *
+     * @return array        table aliases as an array
+     */
+    public function getTableAliasMap()
+    {
+        return $this->_tableAliasMap;
+    }
+
+    /**
+     * getDql
+     * returns the DQL query that is represented by this query object.
+     *
+     * the query is built from $_dqlParts
+     *
+     * @return string   the DQL query
+     */
+    public function getDql()
+    {
+        $q = '';
+        if ($this->_type == self::SELECT) {
+            $q .= ( ! empty($this->_dqlParts['select'])) ? 'SELECT ' . implode(', ', $this->_dqlParts['select']) : '';
+            $q .= ( ! empty($this->_dqlParts['from'])) ? ' FROM ' . implode(' ', $this->_dqlParts['from']) : '';
+        } else if ($this->_type == self::DELETE) {
+            $q .= 'DELETE';
+            $q .= ( ! empty($this->_dqlParts['from'])) ? ' FROM ' . implode(' ', $this->_dqlParts['from']) : '';
+        } else if ($this->_type == self::UPDATE) {
+            $q .= 'UPDATE ';
+            $q .= ( ! empty($this->_dqlParts['from'])) ? implode(' ', $this->_dqlParts['from']) : '';
+            $q .= ( ! empty($this->_dqlParts['set'])) ? ' SET ' . implode(' ', $this->_dqlParts['set']) : '';
+        }
+        $q .= ( ! empty($this->_dqlParts['where'])) ? ' WHERE ' . implode(' ', $this->_dqlParts['where']) : '';
+        $q .= ( ! empty($this->_dqlParts['groupby'])) ? ' GROUP BY ' . implode(', ', $this->_dqlParts['groupby']) : '';
+        $q .= ( ! empty($this->_dqlParts['having'])) ? ' HAVING ' . implode(' AND ', $this->_dqlParts['having']) : '';
+        $q .= ( ! empty($this->_dqlParts['orderby'])) ? ' ORDER BY ' . implode(', ', $this->_dqlParts['orderby']) : '';
+        $q .= ( ! empty($this->_dqlParts['limit'])) ? ' LIMIT ' . implode(' ', $this->_dqlParts['limit']) : '';
+        $q .= ( ! empty($this->_dqlParts['offset'])) ? ' OFFSET ' . implode(' ', $this->_dqlParts['offset']) : '';
+
+        return $q;
+    }
+
+
+
+    /**
+     * getQueryPart
+     * gets a query part from the query part array
+     *
+     * @param string $name          the name of the query part to be set
+     * @param string $part          query part string
+     * @throws Doctrine_Query_Exception   if trying to set unknown query part
+     * @return Doctrine_Query_Abstract  this object
+     * @deprecated
+     */
+    public function getQueryPart($part)
+    {
+        return $this->getSqlQueryPart($part);
+    }
+
+    /**
+     * getSqlQueryPart
+     * gets an SQL query part from the SQL query part array
+     *
+     * @param string $name          the name of the query part to be set
+     * @param string $part          query part string
+     * @throws Doctrine_Query_Exception   if trying to set unknown query part
+     * @return Doctrine_Hydrate     this object
+     */
+    public function getSqlQueryPart($part)
+    {
+        if ( ! isset($this->_sqlParts[$part])) {
+            throw new Doctrine_Query_Exception('Unknown SQL query part ' . $part);
+        }
+        return $this->_sqlParts[$part];
+    }
+
+    /**
+     * setQueryPart
+     * sets a query part in the query part array
+     *
+     * @param string $name          the name of the query part to be set
+     * @param string $part          query part string
+     * @throws Doctrine_Query_Exception   if trying to set unknown query part
+     * @return Doctrine_Hydrate     this object
+     * @deprecated
+     */
+    public function setQueryPart($name, $part)
+    {
+        return $this->setSqlQueryPart($name, $part);
+    }
+
+    /**
+     * setSqlQueryPart
+     * sets an SQL query part in the SQL query part array
+     *
+     * @param string $name          the name of the query part to be set
+     * @param string $part          query part string
+     * @throws Doctrine_Query_Exception   if trying to set unknown query part
+     * @return Doctrine_Hydrate     this object
+     */
+    public function setSqlQueryPart($name, $part)
+    {
+        if ( ! isset($this->_sqlParts[$name])) {
+            throw new Doctrine_Query_Exception('Unknown query part ' . $name);
+        }
+
+        if ($name !== 'limit' && $name !== 'offset') {
+            if (is_array($part)) {
+                $this->_sqlParts[$name] = $part;
+            } else {
+                $this->_sqlParts[$name] = array($part);
+            }
+        } else {
+            $this->_sqlParts[$name] = $part;
+        }
+
+        return $this;
+    }
+
+    /**
+     * addQueryPart
+     * adds a query part in the query part array
+     *
+     * @param string $name          the name of the query part to be added
+     * @param string $part          query part string
+     * @throws Doctrine_Query_Exception   if trying to add unknown query part
+     * @return Doctrine_Hydrate     this object
+     * @deprecated
+     */
+    public function addQueryPart($name, $part)
+    {
+        return $this->addSqlQueryPart($name, $part);
+    }
+
+    /**
+     * addSqlQueryPart
+     * adds an SQL query part to the SQL query part array
+     *
+     * @param string $name          the name of the query part to be added
+     * @param string $part          query part string
+     * @throws Doctrine_Query_Exception   if trying to add unknown query part
+     * @return Doctrine_Hydrate     this object
+     */
+    public function addSqlQueryPart($name, $part)
+    {
+        if ( ! isset($this->_sqlParts[$name])) {
+            throw new Doctrine_Query_Exception('Unknown query part ' . $name);
+        }
+        if (is_array($part)) {
+            $this->_sqlParts[$name] = array_merge($this->_sqlParts[$name], $part);
+        } else {
+            $this->_sqlParts[$name][] = $part;
+        }
+        return $this;
+    }
+
+    /**
+     * removeQueryPart
+     * removes a query part from the query part array
+     *
+     * @param string $name          the name of the query part to be removed
+     * @throws Doctrine_Query_Exception   if trying to remove unknown query part
+     * @return Doctrine_Hydrate     this object
+     * @deprecated
+     */
+    public function removeQueryPart($name)
+    {
+        return $this->removeSqlQueryPart($name);
+    }
+
+    /**
+     * removeSqlQueryPart
+     * removes a query part from the query part array
+     *
+     * @param string $name          the name of the query part to be removed
+     * @throws Doctrine_Query_Exception   if trying to remove unknown query part
+     * @return Doctrine_Hydrate     this object
+     */
+    public function removeSqlQueryPart($name)
+    {
+        if ( ! isset($this->_sqlParts[$name])) {
+            throw new Doctrine_Query_Exception('Unknown query part ' . $name);
+        }
+
+        if ($name == 'limit' || $name == 'offset') {
+            $this->_sqlParts[$name] = false;
+        } else {
+            $this->_sqlParts[$name] = array();
+        }
+
+        return $this;
+    }
+
+    /**
+     * removeDqlQueryPart
+     * removes a dql query part from the dql query part array
+     *
+     * @param string $name          the name of the query part to be removed
+     * @throws Doctrine_Query_Exception   if trying to remove unknown query part
+     * @return Doctrine_Hydrate     this object
+     */
+    public function removeDqlQueryPart($name)
+    {
+        if ( ! isset($this->_dqlParts[$name])) {
+            throw new Doctrine_Query_Exception('Unknown query part ' . $name);
+        }
+
+        if ($name == 'limit' || $name == 'offset') {
+            $this->_dqlParts[$name] = false;
+        } else {
+            $this->_dqlParts[$name] = array();
+        }
+
+        return $this;
+    }
+
+    /**
+     * getParams
+     *
+     * @return array
+     */
+    public function getParams($params = array())
+    {
+        return array_merge((array) $params, $this->_params['join'], $this->_params['set'], $this->_params['where'], $this->_params['having']);
+    }
+
+    /**
+     * Get the raw array of parameters
+     *
+     * @return array
+     */
+    public function getRawParams()
+    {
+      return $this->_params;
+    }
+
+    /**
+     * setParams
+     *
+     * @param array $params
+     */
+    public function setParams(array $params = array())
+    {
+        $this->_params = $params;
+    }
+
+    /**
+     * setView
+     * sets a database view this query object uses
+     * this method should only be called internally by doctrine
+     *
+     * @param Doctrine_View $view       database view
+     * @return void
+     */
+    public function setView(Doctrine_View $view)
+    {
+        $this->_view = $view;
+    }
+
+    /**
+     * getView
+     * returns the view associated with this query object (if any)
+     *
+     * @return Doctrine_View        the view associated with this query object
+     */
+    public function getView()
+    {
+        return $this->_view;
+    }
+
+    /**
+     * limitSubqueryUsed
+     *
+     * @return boolean
+     */
+    public function isLimitSubqueryUsed()
+    {
+        return $this->_isLimitSubqueryUsed;
+    }
+
+    /**
+     * Returns the inheritance condition for the passed componentAlias
+     * If no component alias is specified it defaults to the root component
+     *
+     * This function is used to append a SQL condition to models which have inheritance mapping
+     * The condition is applied to the FROM component in the WHERE, but the condition is applied to
+     * JOINS in the ON condition and not the WHERE
+     *
+     * @return string $str  SQL condition string
+     */
+    public function getInheritanceCondition($componentAlias)
+    {
+        $map = $this->_queryComponents[$componentAlias]['table']->inheritanceMap;
+
+        // No inheritance map so lets just return
+        if (empty($map)) {
+          return;
+        }
+
+        $tableAlias = $this->getSqlTableAlias($componentAlias);
+
+        if ($this->_type !== Doctrine_Query::SELECT) {
+            $tableAlias = '';
+        } else {
+            $tableAlias .= '.';
+        }
+
+        $field = key($map);
+        $value = current($map);
+        $identifier = $this->_conn->quoteIdentifier($tableAlias . $field);
+
+        return $identifier . ' = ' . $this->_conn->quote($value);;
+    }
+
+    /**
+     * getTableAlias
+     * some database such as Oracle need the identifier lengths to be < ~30 chars
+     * hence Doctrine creates as short identifier aliases as possible
+     *
+     * this method is used for the creation of short table aliases, its also
+     * smart enough to check if an alias already exists for given component (componentAlias)
+     *
+     * @param string $componentAlias    the alias for the query component to search table alias for
+     * @param string $tableName         the table name from which the table alias is being created
+     * @return string                   the generated / fetched short alias
+     * @deprecated
+     */
+    public function getTableAlias($componentAlias, $tableName = null)
+    {
+        return $this->getSqlTableAlias($componentAlias, $tableName);
+    }
+
+    /**
+     * getSqlTableAlias
+     * some database such as Oracle need the identifier lengths to be < ~30 chars
+     * hence Doctrine creates as short identifier aliases as possible
+     *
+     * this method is used for the creation of short table aliases, its also
+     * smart enough to check if an alias already exists for given component (componentAlias)
+     *
+     * @param string $componentAlias    the alias for the query component to search table alias for
+     * @param string $tableName         the table name from which the table alias is being created
+     * @return string                   the generated / fetched short alias
+     */
+    public function getSqlTableAlias($componentAlias, $tableName = null)
+    {
+        $alias = array_search($componentAlias, $this->_tableAliasMap);
+
+        if ($alias !== false) {
+            return $alias;
+        }
+
+        if ($tableName === null) {
+            throw new Doctrine_Query_Exception("Couldn't get short alias for " . $componentAlias);
+        }
+
+        return $this->generateTableAlias($componentAlias, $tableName);
+    }
+
+    /**
+     * generateNewTableAlias
+     * generates a new alias from given table alias
+     *
+     * @param string $tableAlias    table alias from which to generate the new alias from
+     * @return string               the created table alias
+     * @deprecated
+     */
+    public function generateNewTableAlias($oldAlias)
+    {
+        return $this->generateNewSqlTableAlias($oldAlias);
+    }
+
+    /**
+     * generateNewSqlTableAlias
+     * generates a new alias from given table alias
+     *
+     * @param string $tableAlias    table alias from which to generate the new alias from
+     * @return string               the created table alias
+     */
+    public function generateNewSqlTableAlias($oldAlias)
+    {
+        if (isset($this->_tableAliasMap[$oldAlias])) {
+            // generate a new alias
+            $name = substr($oldAlias, 0, 1);
+            $i    = ((int) substr($oldAlias, 1));
+
+            // Fix #1530: It was reaching unexistent seeds index
+            if ( ! isset($this->_tableAliasSeeds[$name])) {
+                $this->_tableAliasSeeds[$name] = 1;
+            }
+
+            $newIndex  = ($this->_tableAliasSeeds[$name] + (($i == 0) ? 1 : $i));
+
+            return $name . $newIndex;
+        }
+
+        return $oldAlias;
+    }
+
+    /**
+     * getTableAliasSeed
+     * returns the alias seed for given table alias
+     *
+     * @param string $tableAlias    table alias that identifies the alias seed
+     * @return integer              table alias seed
+     * @deprecated
+     */
+    public function getTableAliasSeed($sqlTableAlias)
+    {
+        return $this->getSqlTableAliasSeed($sqlTableAlias);
+    }
+
+    /**
+     * getSqlTableAliasSeed
+     * returns the alias seed for given table alias
+     *
+     * @param string $tableAlias    table alias that identifies the alias seed
+     * @return integer              table alias seed
+     */
+    public function getSqlTableAliasSeed($sqlTableAlias)
+    {
+        if ( ! isset($this->_tableAliasSeeds[$sqlTableAlias])) {
+            return 0;
+        }
+        return $this->_tableAliasSeeds[$sqlTableAlias];
+    }
+
+    /**
+     * hasAliasDeclaration
+     * whether or not this object has a declaration for given component alias
+     *
+     * @param string $componentAlias    the component alias the retrieve the declaration from
+     * @return boolean
+     */
+    public function hasAliasDeclaration($componentAlias)
+    {
+        return isset($this->_queryComponents[$componentAlias]);
+    }
+
+    /**
+     * getAliasDeclaration
+     * get the declaration for given component alias
+     *
+     * @param string $componentAlias    the component alias the retrieve the declaration from
+     * @return array                    the alias declaration
+     * @deprecated
+     */
+    public function getAliasDeclaration($componentAlias)
+    {
+        return $this->getQueryComponent($componentAlias);
+    }
+
+    /**
+     * getQueryComponent
+     * get the declaration for given component alias
+     *
+     * @param string $componentAlias    the component alias the retrieve the declaration from
+     * @return array                    the alias declaration
+     */
+    public function getQueryComponent($componentAlias)
+    {
+        if ( ! isset($this->_queryComponents[$componentAlias])) {
+            throw new Doctrine_Query_Exception('Unknown component alias ' . $componentAlias);
+        }
+
+        return $this->_queryComponents[$componentAlias];
+    }
+
+    /**
+     * copyAliases
+     * copy aliases from another Hydrate object
+     *
+     * this method is needed by DQL subqueries which need the aliases
+     * of the parent query
+     *
+     * @param Doctrine_Hydrate $query   the query object from which the
+     *                                  aliases are copied from
+     * @return Doctrine_Hydrate         this object
+     */
+    public function copySubqueryInfo(Doctrine_Query_Abstract $query)
+    {
+        $this->_params =& $query->_params;
+        $this->_tableAliasMap =& $query->_tableAliasMap;
+        $this->_queryComponents =& $query->_queryComponents;
+        $this->_tableAliasSeeds = $query->_tableAliasSeeds;
+        return $this;
+    }
+
+    /**
+     * getRootAlias
+     * returns the alias of the the root component
+     *
+     * @return array
+     */
+    public function getRootAlias()
+    {
+        if ( ! $this->_queryComponents) {
+          $this->getSql();
+        }
+
+        return $this->_rootAlias;
+    }
+
+    /**
+     * getRootDeclaration
+     * returns the root declaration
+     *
+     * @return array
+     */
+    public function getRootDeclaration()
+    {
+        $map = $this->_queryComponents[$this->_rootAlias];
+        return $map;
+    }
+
+    /**
+     * getRoot
+     * returns the root component for this object
+     *
+     * @return Doctrine_Table       root components table
+     */
+    public function getRoot()
+    {
+        $map = $this->_queryComponents[$this->_rootAlias];
+
+        if ( ! isset($map['table'])) {
+            throw new Doctrine_Query_Exception('Root component not initialized.');
+        }
+
+        return $map['table'];
+    }
+
+    /**
+     * generateTableAlias
+     * generates a table alias from given table name and associates
+     * it with given component alias
+     *
+     * @param string $componentAlias    the component alias to be associated with generated table alias
+     * @param string $tableName         the table name from which to generate the table alias
+     * @return string                   the generated table alias
+     * @deprecated
+     */
+    public function generateTableAlias($componentAlias, $tableName)
+    {
+        return $this->generateSqlTableAlias($componentAlias, $tableName);
+    }
+
+    /**
+     * generateSqlTableAlias
+     * generates a table alias from given table name and associates
+     * it with given component alias
+     *
+     * @param string $componentAlias    the component alias to be associated with generated table alias
+     * @param string $tableName         the table name from which to generate the table alias
+     * @return string                   the generated table alias
+     */
+    public function generateSqlTableAlias($componentAlias, $tableName)
+    {
+        preg_match('/([^_|\d])/', $tableName, $matches);
+        $char = strtolower($matches[0]);
+
+        $alias = $char;
+
+        if ( ! isset($this->_tableAliasSeeds[$alias])) {
+            $this->_tableAliasSeeds[$alias] = 1;
+        }
+
+        while (isset($this->_tableAliasMap[$alias])) {
+            if ( ! isset($this->_tableAliasSeeds[$alias])) {
+                $this->_tableAliasSeeds[$alias] = 1;
+            }
+            $alias = $char . ++$this->_tableAliasSeeds[$alias];
+        }
+
+        $this->_tableAliasMap[$alias] = $componentAlias;
+
+        return $alias;
+    }
+
+    /**
+     * getComponentAlias
+     * get component alias associated with given table alias
+     *
+     * @param string $sqlTableAlias    the SQL table alias that identifies the component alias
+     * @return string               component alias
+     */
+    public function getComponentAlias($sqlTableAlias)
+    {
+        $sqlTableAlias = trim($sqlTableAlias, '[]`"');
+        if ( ! isset($this->_tableAliasMap[$sqlTableAlias])) {
+            throw new Doctrine_Query_Exception('Unknown table alias ' . $sqlTableAlias);
+        }
+        return $this->_tableAliasMap[$sqlTableAlias];
+    }
+
+    /**
+     * calculateQueryCacheHash
+     * calculate hash key for query cache
+     *
+     * @return string    the hash
+     */
+    public function calculateQueryCacheHash()
+    {
+        $dql = $this->getDql();
+        $hash = md5($dql . 'DOCTRINE_QUERY_CACHE_SALT');
+        return $hash;
+    }
+
+    /**
+     * calculateResultCacheHash
+     * calculate hash key for result cache
+     *
+     * @param array $params
+     * @return string    the hash
+     */
+    public function calculateResultCacheHash($params = array())
+    {
+        $dql = $this->getDql();
+        $params = $this->getParams($params);
+        $conn = $this->getConnection();
+        $hash = md5($this->_hydrator->getHydrationMode() . $conn->getName() . $conn->getOption('dsn') . $dql . var_export($params, true));
+        return $hash;
+    }
+
+    /**
+     * _execute
+     *
+     * @param array $params
+     * @return PDOStatement  The executed PDOStatement.
+     */
+    protected function _execute($params)
+    {
+        $params = $this->_conn->convertBooleans($params);
+
+        if ( ! $this->_view) {
+            if ($this->_queryCache !== false && ($this->_queryCache || $this->_conn->getAttribute(Doctrine::ATTR_QUERY_CACHE))) {
+                $queryCacheDriver = $this->getQueryCacheDriver();
+                $hash = $this->calculateQueryCacheHash();
+                $cached = $queryCacheDriver->fetch($hash);
+
+                if ($cached) {
+                    $query = $this->_constructQueryFromCache($cached);
+                } else {
+                    $query = $this->getSqlQuery($params);
+                    // Check again because getSqlQuery() above could have flipped the _queryCache flag
+                    // if this query contains the limit sub query algorithm we don't need to cache it
+                    if ($this->_queryCache !== false && ($this->_queryCache || $this->_conn->getAttribute(Doctrine::ATTR_QUERY_CACHE))) {
+                        $serializedQuery = $this->getCachedForm($query);
+                        $queryCacheDriver->save($hash, $serializedQuery, $this->getQueryCacheLifeSpan());
+                    }
+                }
+            } else {
+                $query = $this->getSqlQuery($params);
+            }
+        } else {
+            $query = $this->_view->getSelectSql();
+        }
+
+        if ($this->isLimitSubqueryUsed() &&
+                $this->_conn->getAttribute(Doctrine::ATTR_DRIVER_NAME) !== 'mysql') {
+            $params = array_merge($params, $params);
+        }
+
+        if ($this->_type !== self::SELECT) {
+            return $this->_conn->exec($query, $params);
+        }
+
+        $stmt = $this->_conn->execute($query, $params);
+        return $stmt;
+    }
+
+    /**
+     * execute
+     * executes the query and populates the data set
+     *
+     * @param array $params
+     * @return Doctrine_Collection            the root collection
+     */
+    public function execute($params = array(), $hydrationMode = null)
+    {
+        if (empty($this->_dqlParts['from']) && empty($this->_sqlParts['from'])) {
+            throw new Doctrine_Query_Exception('You must have at least one component specified in your from.');
+        }
+
+        $preQueryParams = $this->getParams($params);
+
+        $this->_preQuery($preQueryParams);
+
+        if ($hydrationMode !== null) {
+            $this->_hydrator->setHydrationMode($hydrationMode);
+        }
+
+        $params = $this->getParams($params);
+
+        if ($this->_resultCache && $this->_type == self::SELECT) {
+            $cacheDriver = $this->getResultCacheDriver();
+            $hash = $this->calculateResultCacheHash($params);
+            $cached = ($this->_expireResultCache) ? false : $cacheDriver->fetch($hash);
+
+            if ($cached === false) {
+                // cache miss
+                $stmt = $this->_execute($params);
+                $this->_hydrator->setQueryComponents($this->_queryComponents);
+                $result = $this->_hydrator->hydrateResultSet($stmt, $this->_tableAliasMap);
+
+                $cached = $this->getCachedForm($result);
+                $cacheDriver->save($hash, $cached, $this->getResultCacheLifeSpan());
+            } else {
+                $result = $this->_constructQueryFromCache($cached);
+            }
+        } else {
+            $stmt = $this->_execute($params);
+
+            if (is_integer($stmt)) {
+                $result = $stmt;
+            } else {
+                $this->_hydrator->setQueryComponents($this->_queryComponents);
+                $result = $this->_hydrator->hydrateResultSet($stmt, $this->_tableAliasMap);
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * Get the dql call back for this query
+     *
+     * @return array $callback
+     */
+    protected function _getDqlCallback()
+    {
+        $callback = false;
+        if ( ! empty($this->_dqlParts['from'])) {
+            switch ($this->_type) {
+                case self::DELETE:
+                    $callback = array(
+                        'callback' => 'preDqlDelete',
+                        'const' => Doctrine_Event::RECORD_DQL_DELETE
+                    );
+                break;
+                case self::UPDATE:
+                    $callback = array(
+                        'callback' => 'preDqlUpdate',
+                        'const' => Doctrine_Event::RECORD_DQL_UPDATE
+                    );
+                break;
+                case self::SELECT:
+                    $callback = array(
+                        'callback' => 'preDqlSelect',
+                        'const' => Doctrine_Event::RECORD_DQL_SELECT
+                    );
+                break;
+            }
+        }
+
+        return $callback;
+    }
+
+    /**
+     * Pre query method which invokes the pre*Query() methods on the model instance or any attached
+     * record listeners
+     *
+     * @return void
+     */
+    protected function _preQuery($params = array())
+    {
+        if ( ! $this->_preQueried && $this->getConnection()->getAttribute('use_dql_callbacks')) {
+            $this->_preQueried = true;
+
+            $callback = $this->_getDqlCallback();
+
+            // if there is no callback for the query type, then we can return early
+            if ( ! $callback) {
+                return;
+            }
+
+            foreach ($this->_getDqlCallbackComponents($params) as $alias => $component) {
+                $table = $component['table'];
+                $record = $table->getRecordInstance();
+
+                // Trigger preDql*() callback event
+                $params = array('component' => $component, 'alias' => $alias);
+                $event = new Doctrine_Event($record, $callback['const'], $this, $params);
+
+                $record->$callback['callback']($event);
+                $table->getRecordListener()->$callback['callback']($event);
+            }
+        }
+
+        // Invoke preQuery() hook on Doctrine_Query for child classes which implement this hook
+        $this->preQuery();
+    }
+
+    /**
+     * Returns an array of components to execute the query callbacks for
+     *
+     * @param  array $params
+     * @return array $components
+     */
+    protected function _getDqlCallbackComponents($params = array())
+    {
+        $componentsBefore = array();
+        if ($this->isSubquery()) {
+            $componentsBefore = $this->getQueryComponents();
+        }
+
+        $copy = $this->copy();
+        $copy->getSqlQuery($params);
+        $componentsAfter = $copy->getQueryComponents();
+
+        if ($componentsBefore !== $componentsAfter) {
+            return array_diff($componentsAfter, $componentsBefore);
+        } else {
+            return $componentsAfter;
+        }
+    }
+
+    /**
+     * Blank hook methods which can be implemented in Doctrine_Query child classes
+     *
+     * @return void
+     */
+    public function preQuery()
+    {
+    }
+
+    /**
+     * Constructs the query from the cached form.
+     *
+     * @param string  The cached query, in a serialized form.
+     * @return array  The custom component that was cached together with the essential
+     *                query data. This can be either a result set (result caching)
+     *                or an SQL query string (query caching).
+     */
+    protected function _constructQueryFromCache($cached)
+    {
+        $cached = unserialize($cached);
+        $this->_tableAliasMap = $cached[2];
+        $customComponent = $cached[0];
+
+        $queryComponents = array();
+        $cachedComponents = $cached[1];
+        foreach ($cachedComponents as $alias => $components) {
+            $e = explode('.', $components['name']);
+            if (count($e) === 1) {
+                $manager = Doctrine_Manager::getInstance(); 
+                if ($manager->hasConnectionForComponent($e[0])) { 
+                    $this->_conn = $manager->getConnectionForComponent($e[0]); 
+                }
+                $queryComponents[$alias]['table'] = $this->_conn->getTable($e[0]);
+            } else {
+                $queryComponents[$alias]['parent'] = $e[0];
+                $queryComponents[$alias]['relation'] = $queryComponents[$e[0]]['table']->getRelation($e[1]);
+                $queryComponents[$alias]['table'] = $queryComponents[$alias]['relation']->getTable();
+            }
+            if (isset($components['agg'])) {
+                $queryComponents[$alias]['agg'] = $components['agg'];
+            }
+            if (isset($components['map'])) {
+                $queryComponents[$alias]['map'] = $components['map'];
+            }
+        }
+        $this->_queryComponents = $queryComponents;
+
+        return $customComponent;
+    }
+
+    /**
+     * getCachedForm
+     * returns the cached form of this query for given resultSet
+     *
+     * @param array $resultSet
+     * @return string           serialized string representation of this query
+     */
+    public function getCachedForm($customComponent = null)
+    {
+        $componentInfo = array();
+
+        foreach ($this->getQueryComponents() as $alias => $components) {
+            if ( ! isset($components['parent'])) {
+                $componentInfo[$alias]['name'] = $components['table']->getComponentName();
+            } else {
+                $componentInfo[$alias]['name'] = $components['parent'] . '.' . $components['relation']->getAlias();
+            }
+            if (isset($components['agg'])) {
+                $componentInfo[$alias]['agg'] = $components['agg'];
+            }
+            if (isset($components['map'])) {
+                $componentInfo[$alias]['map'] = $components['map'];
+            }
+        }
+
+        if ($customComponent instanceof Doctrine_Collection) {
+            foreach ($customComponent as $record) {
+                $record->serializeReferences(true);
+            }
+        }
+
+        return serialize(array($customComponent, $componentInfo, $this->getTableAliasMap()));
+    }
+
+    /**
+     * addSelect
+     * adds fields to the SELECT part of the query
+     *
+     * @param string $select        Query SELECT part
+     * @return Doctrine_Query
+     */
+    public function addSelect($select)
+    {
+        return $this->_addDqlQueryPart('select', $select, true);
+    }
+
+    /**
+     * addTableAlias
+     * adds an alias for table and associates it with given component alias
+     *
+     * @param string $componentAlias    the alias for the query component associated with given tableAlias
+     * @param string $tableAlias        the table alias to be added
+     * @return Doctrine_Hydrate
+     * @deprecated
+     */
+    public function addTableAlias($tableAlias, $componentAlias)
+    {
+        return $this->addSqlTableAlias($tableAlias, $componentAlias);
+    }
+
+    /**
+     * addSqlTableAlias
+     * adds an SQL table alias and associates it a component alias
+     *
+     * @param string $componentAlias    the alias for the query component associated with given tableAlias
+     * @param string $tableAlias        the table alias to be added
+     * @return Doctrine_Query_Abstract
+     */
+    public function addSqlTableAlias($sqlTableAlias, $componentAlias)
+    {
+        $this->_tableAliasMap[$sqlTableAlias] = $componentAlias;
+        return $this;
+    }
+
+    /**
+     * addFrom
+     * adds fields to the FROM part of the query
+     *
+     * @param string $from        Query FROM part
+     * @return Doctrine_Query
+     */
+    public function addFrom($from)
+    {
+        return $this->_addDqlQueryPart('from', $from, true);
+    }
+
+    /**
+     * addWhere
+     * adds conditions to the WHERE part of the query
+     *
+     * @param string $where         Query WHERE part
+     * @param mixed $params         an array of parameters or a simple scalar
+     * @return Doctrine_Query
+     */
+    public function addWhere($where, $params = array())
+    {
+        return $this->andWhere($where, $params);
+    }
+
+
+    /**
+     * Adds conditions to the WHERE part of the query
+     *
+     * @param string $where Query WHERE part
+     * @param mixed $params An array of parameters or a simple scalar
+     * @return Doctrine_Query
+     */
+    public function andWhere($where, $params = array())
+    {
+        if (is_array($params)) {
+            $this->_params['where'] = array_merge($this->_params['where'], $params);
+        } else {
+            $this->_params['where'][] = $params;
+        }
+
+        if ($this->_hasDqlQueryPart('where')) {
+            $this->_addDqlQueryPart('where', 'AND', true);
+        }
+
+        return $this->_addDqlQueryPart('where', $where, true);
+    }
+
+
+    /**
+     * Adds conditions to the WHERE part of the query
+     *
+     * @param string $where Query WHERE part
+     * @param mixed $params An array of parameters or a simple scalar
+     * @return Doctrine_Query
+     */
+    public function orWhere($where, $params = array())
+    {
+        if (is_array($params)) {
+            $this->_params['where'] = array_merge($this->_params['where'], $params);
+        } else {
+            $this->_params['where'][] = $params;
+        }
+
+        if ($this->_hasDqlQueryPart('where')) {
+            $this->_addDqlQueryPart('where', 'OR', true);
+        }
+
+        return $this->_addDqlQueryPart('where', $where, true);
+    }
+
+
+    /**
+     * whereIn
+     * adds IN condition to the query WHERE part
+     *
+     * @param string $expr          the operand of the IN
+     * @param mixed $params         an array of parameters or a simple scalar
+     * @param boolean $not          whether or not to use NOT in front of IN
+     * @return Doctrine_Query
+     */
+    public function whereIn($expr, $params = array(), $not = false)
+    {
+        return $this->andWhereIn($expr, $params, $not);
+    }
+
+
+    /**
+     * Adds IN condition to the query WHERE part
+     *
+     * @param string $expr The operand of the IN
+     * @param mixed $params An array of parameters or a simple scalar
+     * @param boolean $not Whether or not to use NOT in front of IN
+     * @return Doctrine_Query
+     */
+    public function andWhereIn($expr, $params = array(), $not = false)
+    {
+        // if there's no params, return (else we'll get a WHERE IN (), invalid SQL)
+        if ( ! count($params)) {
+            return $this;
+        }
+
+        if ($this->_hasDqlQueryPart('where')) {
+            $this->_addDqlQueryPart('where', 'AND', true);
+        }
+
+        return $this->_addDqlQueryPart('where', $this->_processWhereIn($expr, $params, $not), true);
+    }
+
+
+    /**
+     * Adds IN condition to the query WHERE part
+     *
+     * @param string $expr The operand of the IN
+     * @param mixed $params An array of parameters or a simple scalar
+     * @param boolean $not Whether or not to use NOT in front of IN
+     * @return Doctrine_Query
+     */
+    public function orWhereIn($expr, $params = array(), $not = false)
+    {
+        // if there's no params, return (else we'll get a WHERE IN (), invalid SQL)
+        if ( ! count($params)) {
+            return $this;
+        }
+
+        if ($this->_hasDqlQueryPart('where')) {
+            $this->_addDqlQueryPart('where', 'OR', true);
+        }
+
+        return $this->_addDqlQueryPart('where', $this->_processWhereIn($expr, $params, $not), true);
+    }
+
+
+    /**
+     * @nodoc
+     */
+    protected function _processWhereIn($expr, $params = array(), $not = false)
+    {
+        $params = (array) $params;
+
+        // if there's no params, return (else we'll get a WHERE IN (), invalid SQL)
+        if ( ! count($params)) {
+            throw new Doctrine_Query_Exception('You must pass at least one parameter when using an IN() condition.');
+        }
+
+        $a = array();
+        foreach ($params as $k => $value) {
+            if ($value instanceof Doctrine_Expression) {
+                $value = $value->getSql();
+                unset($params[$k]);
+            } else {
+                $value = '?';
+            }
+            $a[] = $value;
+        }
+
+        $this->_params['where'] = array_merge($this->_params['where'], $params);
+
+        return $expr . ($not === true ? ' NOT ':'') . ' IN (' . implode(', ', $a) . ')';
+    }
+
+
+    /**
+     * whereNotIn
+     * adds NOT IN condition to the query WHERE part
+     *
+     * @param string $expr          the operand of the NOT IN
+     * @param mixed $params         an array of parameters or a simple scalar
+     * @return Doctrine_Query
+     */
+    public function whereNotIn($expr, $params = array())
+    {
+        return $this->whereIn($expr, $params, true);
+    }
+
+
+    /**
+     * Adds NOT IN condition to the query WHERE part
+     *
+     * @param string $expr The operand of the NOT IN
+     * @param mixed $params An array of parameters or a simple scalar
+     * @return Doctrine_Query
+     */
+    public function andWhereNotIn($expr, $params = array())
+    {
+        return $this->andWhereIn($expr, $params, true);
+    }
+
+
+    /**
+     * Adds NOT IN condition to the query WHERE part
+     *
+     * @param string $expr The operand of the NOT IN
+     * @param mixed $params An array of parameters or a simple scalar
+     * @return Doctrine_Query
+     */
+    public function orWhereNotIn($expr, $params = array())
+    {
+        return $this->orWhereIn($expr, $params, true);
+    }
+
+    /**
+     * addGroupBy
+     * adds fields to the GROUP BY part of the query
+     *
+     * @param string $groupby       Query GROUP BY part
+     * @return Doctrine_Query
+     */
+    public function addGroupBy($groupby)
+    {
+        return $this->_addDqlQueryPart('groupby', $groupby, true);
+    }
+
+    /**
+     * addHaving
+     * adds conditions to the HAVING part of the query
+     *
+     * @param string $having        Query HAVING part
+     * @param mixed $params         an array of parameters or a simple scalar
+     * @return Doctrine_Query
+     */
+    public function addHaving($having, $params = array())
+    {
+        if (is_array($params)) {
+            $this->_params['having'] = array_merge($this->_params['having'], $params);
+        } else {
+            $this->_params['having'][] = $params;
+        }
+        return $this->_addDqlQueryPart('having', $having, true);
+    }
+
+    /**
+     * addOrderBy
+     * adds fields to the ORDER BY part of the query
+     *
+     * @param string $orderby       Query ORDER BY part
+     * @return Doctrine_Query
+     */
+    public function addOrderBy($orderby)
+    {
+        return $this->_addDqlQueryPart('orderby', $orderby, true);
+    }
+
+    /**
+     * select
+     * sets the SELECT part of the query
+     *
+     * @param string $select        Query SELECT part
+     * @return Doctrine_Query
+     */
+    public function select($select)
+    {
+        return $this->_addDqlQueryPart('select', $select);
+    }
+
+    /**
+     * distinct
+     * Makes the query SELECT DISTINCT.
+     *
+     * @param bool $flag            Whether or not the SELECT is DISTINCT (default true).
+     * @return Doctrine_Query
+     */
+    public function distinct($flag = true)
+    {
+        $this->_sqlParts['distinct'] = (bool) $flag;
+        return $this;
+    }
+
+    /**
+     * forUpdate
+     * Makes the query SELECT FOR UPDATE.
+     *
+     * @param bool $flag            Whether or not the SELECT is FOR UPDATE (default true).
+     * @return Doctrine_Query
+     */
+    public function forUpdate($flag = true)
+    {
+        $this->_sqlParts['forUpdate'] = (bool) $flag;
+        return $this;
+    }
+
+    /**
+     * delete
+     * sets the query type to DELETE
+     *
+     * @return Doctrine_Query
+     */
+    public function delete($from = null)
+    {
+        $this->_type = self::DELETE;
+        if ($from != null) {
+            return $this->_addDqlQueryPart('from', $from);
+        }
+        return $this;
+    }
+
+    /**
+     * update
+     * sets the UPDATE part of the query
+     *
+     * @param string $update        Query UPDATE part
+     * @return Doctrine_Query
+     */
+    public function update($from = null)
+    {
+        $this->_type = self::UPDATE;
+        if ($from != null) {
+            return $this->_addDqlQueryPart('from', $from);
+        }
+        return $this;
+    }
+
+    /**
+     * set
+     * sets the SET part of the query
+     *
+     * @param string $update        Query UPDATE part
+     * @return Doctrine_Query
+     */
+    public function set($key, $value, $params = null)
+    {
+        if (is_array($key)) {
+            foreach ($key as $k => $v) {
+                $this->set($k, '?', array($v));
+            }
+            return $this;
+        } else {
+            if ($params !== null) {
+                if (is_array($params)) {
+                    $this->_params['set'] = array_merge($this->_params['set'], $params);
+                } else {
+                    $this->_params['set'][] = $params;
+                }
+            }
+
+            return $this->_addDqlQueryPart('set', $key . ' = ' . $value, true);
+        }
+    }
+
+    /**
+     * from
+     * sets the FROM part of the query
+     *
+     * @param string $from          Query FROM part
+     * @return Doctrine_Query
+     */
+    public function from($from)
+    {
+        return $this->_addDqlQueryPart('from', $from);
+    }
+
+    /**
+     * innerJoin
+     * appends an INNER JOIN to the FROM part of the query
+     *
+     * @param string $join         Query INNER JOIN
+     * @return Doctrine_Query
+     */
+    public function innerJoin($join, $params = array())
+    {
+        if (is_array($params)) {
+            $this->_params['join'] = array_merge($this->_params['join'], $params);
+        } else {
+            $this->_params['join'][] = $params;
+        }
+
+        return $this->_addDqlQueryPart('from', 'INNER JOIN ' . $join, true);
+    }
+
+    /**
+     * leftJoin
+     * appends a LEFT JOIN to the FROM part of the query
+     *
+     * @param string $join         Query LEFT JOIN
+     * @return Doctrine_Query
+     */
+    public function leftJoin($join, $params = array())
+    {
+        if (is_array($params)) {
+            $this->_params['join'] = array_merge($this->_params['join'], $params);
+        } else {
+            $this->_params['join'][] = $params;
+        }
+
+        return $this->_addDqlQueryPart('from', 'LEFT JOIN ' . $join, true);
+    }
+
+    /**
+     * groupBy
+     * sets the GROUP BY part of the query
+     *
+     * @param string $groupby      Query GROUP BY part
+     * @return Doctrine_Query
+     */
+    public function groupBy($groupby)
+    {
+        return $this->_addDqlQueryPart('groupby', $groupby);
+    }
+
+    /**
+     * where
+     * sets the WHERE part of the query
+     *
+     * @param string $join         Query WHERE part
+     * @param mixed $params        an array of parameters or a simple scalar
+     * @return Doctrine_Query
+     */
+    public function where($where, $params = array())
+    {
+        $this->_params['where'] = array();
+
+        if (is_array($params)) {
+            $this->_params['where'] = $params;
+        } else {
+            $this->_params['where'][] = $params;
+        }
+
+        return $this->_addDqlQueryPart('where', $where);
+    }
+
+    /**
+     * having
+     * sets the HAVING part of the query
+     *
+     * @param string $having       Query HAVING part
+     * @param mixed $params        an array of parameters or a simple scalar
+     * @return Doctrine_Query
+     */
+    public function having($having, $params = array())
+    {
+        $this->_params['having'] = array();
+        if (is_array($params)) {
+            $this->_params['having'] = $params;
+        } else {
+            $this->_params['having'][] = $params;
+        }
+
+        return $this->_addDqlQueryPart('having', $having);
+    }
+
+    /**
+     * orderBy
+     * sets the ORDER BY part of the query
+     *
+     * @param string $orderby      Query ORDER BY part
+     * @return Doctrine_Query
+     */
+    public function orderBy($orderby)
+    {
+        return $this->_addDqlQueryPart('orderby', $orderby);
+    }
+
+    /**
+     * limit
+     * sets the Query query limit
+     *
+     * @param integer $limit        limit to be used for limiting the query results
+     * @return Doctrine_Query
+     */
+    public function limit($limit)
+    {
+        return $this->_addDqlQueryPart('limit', $limit);
+    }
+
+    /**
+     * offset
+     * sets the Query query offset
+     *
+     * @param integer $offset       offset to be used for paginating the query
+     * @return Doctrine_Query
+     */
+    public function offset($offset)
+    {
+        return $this->_addDqlQueryPart('offset', $offset);
+    }
+
+    /**
+     * getSql
+     * shortcut for {@link getSqlQuery()}.
+     *
+     * @param array $params (optional)
+     * @return string   sql query string
+     */
+    public function getSql($params = array())
+    {
+        return $this->getSqlQuery($params);
+    }
+
+    /**
+     * clear
+     * resets all the variables
+     *
+     * @return void
+     */
+    protected function clear()
+    {
+        $this->_sqlParts = array(
+                    'select'    => array(),
+                    'distinct'  => false,
+                    'forUpdate' => false,
+                    'from'      => array(),
+                    'set'       => array(),
+                    'join'      => array(),
+                    'where'     => array(),
+                    'groupby'   => array(),
+                    'having'    => array(),
+                    'orderby'   => array(),
+                    'limit'     => false,
+                    'offset'    => false,
+                    );
+    }
+
+    public function setHydrationMode($hydrationMode)
+    {
+        $this->_hydrator->setHydrationMode($hydrationMode);
+        return $this;
+    }
+
+    /**
+     * @deprecated
+     */
+    public function getAliasMap()
+    {
+        return $this->_queryComponents;
+    }
+
+    /**
+     * Gets the components of this query.
+     */
+    public function getQueryComponents()
+    {
+        return $this->_queryComponents;
+    }
+
+    /**
+     * Return the SQL parts.
+     *
+     * @return array The parts
+     * @deprecated
+     */
+    public function getParts()
+    {
+        return $this->getSqlParts();
+    }
+
+    /**
+     * Return the SQL parts.
+     *
+     * @return array The parts
+     */
+    public function getSqlParts()
+    {
+        return $this->_sqlParts;
+    }
+
+    /**
+     * getType
+     *
+     * returns the type of this query object
+     * by default the type is Doctrine_Query_Abstract::SELECT but if update() or delete()
+     * are being called the type is Doctrine_Query_Abstract::UPDATE and Doctrine_Query_Abstract::DELETE,
+     * respectively
+     *
+     * @see Doctrine_Query_Abstract::SELECT
+     * @see Doctrine_Query_Abstract::UPDATE
+     * @see Doctrine_Query_Abstract::DELETE
+     *
+     * @return integer      return the query type
+     */
+    public function getType()
+    {
+        return $this->_type;
+    }
+
+    /**
+     * useCache
+     *
+     * @param Doctrine_Cache_Interface|bool $driver      cache driver
+     * @param integer $timeToLive                        how long the cache entry is valid
+     * @return Doctrine_Hydrate         this object
+     * @deprecated Use useResultCache()
+     */
+    public function useCache($driver = true, $timeToLive = null)
+    {
+        return $this->useResultCache($driver, $timeToLive);
+    }
+
+    /**
+     * useResultCache
+     *
+     * @param Doctrine_Cache_Interface|bool $driver      cache driver
+     * @param integer $timeToLive                        how long the cache entry is valid
+     * @return Doctrine_Hydrate         this object
+     */
+    public function useResultCache($driver = true, $timeToLive = null)
+    {
+        if ($driver !== null && $driver !== true && ! ($driver instanceOf Doctrine_Cache_Interface)) {
+            $msg = 'First argument should be instance of Doctrine_Cache_Interface or null.';
+            throw new Doctrine_Query_Exception($msg);
+        }
+        $this->_resultCache = $driver;
+
+        if ($timeToLive !== null) {
+            $this->setResultCacheLifeSpan($timeToLive);
+        }
+        return $this;
+    }
+
+    /**
+     * useQueryCache
+     *
+     * @param Doctrine_Cache_Interface|bool $driver      cache driver
+     * @param integer $timeToLive                        how long the cache entry is valid
+     * @return Doctrine_Hydrate         this object
+     */
+    public function useQueryCache($driver = true, $timeToLive = null)
+    {
+        if ($driver !== null && $driver !== true && $driver !== false && ! ($driver instanceOf Doctrine_Cache_Interface)) {
+            $msg = 'First argument should be instance of Doctrine_Cache_Interface or null.';
+            throw new Doctrine_Query_Exception($msg);
+        }
+        $this->_queryCache = $driver;
+
+        if ($timeToLive !== null) {
+            $this->setQueryCacheLifeSpan($timeToLive);
+        }
+        return $this;
+    }
+
+    /**
+     * expireCache
+     *
+     * @param boolean $expire       whether or not to force cache expiration
+     * @return Doctrine_Hydrate     this object
+     * @deprecated Use expireResultCache()
+     */
+    public function expireCache($expire = true)
+    {
+        return $this->expireResultCache($expire);
+    }
+
+    /**
+     * expireCache
+     *
+     * @param boolean $expire       whether or not to force cache expiration
+     * @return Doctrine_Hydrate     this object
+     */
+    public function expireResultCache($expire = true)
+    {
+        $this->_expireResultCache = $expire;
+        return $this;
+    }
+
+    /**
+     * expireQueryCache
+     *
+     * @param boolean $expire       whether or not to force cache expiration
+     * @return Doctrine_Hydrate     this object
+     */
+    public function expireQueryCache($expire = true)
+    {
+        $this->_expireQueryCache = $expire;
+        return $this;
+    }
+
+    /**
+     * setCacheLifeSpan
+     *
+     * @param integer $timeToLive   how long the cache entry is valid
+     * @return Doctrine_Hydrate     this object
+     * @deprecated Use setResultCacheLifeSpan()
+     */
+    public function setCacheLifeSpan($timeToLive)
+    {
+        return $this->setResultCacheLifeSpan($timeToLive);
+    }
+
+    /**
+     * setResultCacheLifeSpan
+     *
+     * @param integer $timeToLive   how long the cache entry is valid (in seconds)
+     * @return Doctrine_Hydrate     this object
+     */
+    public function setResultCacheLifeSpan($timeToLive)
+    {
+        if ($timeToLive !== null) {
+            $timeToLive = (int) $timeToLive;
+        }
+        $this->_resultCacheTTL = $timeToLive;
+
+        return $this;
+    }
+
+    /**
+     * Gets the life span of the result cache in seconds.
+     *
+     * @return integer
+     */
+    public function getResultCacheLifeSpan()
+    {
+        return $this->_resultCacheTTL;
+    }
+
+    /**
+     * setQueryCacheLifeSpan
+     *
+     * @param integer $timeToLive   how long the cache entry is valid
+     * @return Doctrine_Hydrate     this object
+     */
+    public function setQueryCacheLifeSpan($timeToLive)
+    {
+        if ($timeToLive !== null) {
+            $timeToLive = (int) $timeToLive;
+        }
+        $this->_queryCacheTTL = $timeToLive;
+
+        return $this;
+    }
+
+    /**
+     * Gets the life span of the query cache the Query object is using.
+     *
+     * @return integer  The life span in seconds.
+     */
+    public function getQueryCacheLifeSpan()
+    {
+        return $this->_queryCacheTTL;
+    }
+
+    /**
+     * getCacheDriver
+     * returns the cache driver associated with this object
+     *
+     * @return Doctrine_Cache_Interface|boolean|null    cache driver
+     * @deprecated Use getResultCacheDriver()
+     */
+    public function getCacheDriver()
+    {
+        return $this->getResultCacheDriver();
+    }
+
+    /**
+     * getResultCacheDriver
+     * returns the cache driver used for caching result sets
+     *
+     * @return Doctrine_Cache_Interface|boolean|null    cache driver
+     */
+    public function getResultCacheDriver()
+    {
+        if ($this->_resultCache instanceof Doctrine_Cache_Interface) {
+            return $this->_resultCache;
+        } else {
+            return $this->_conn->getResultCacheDriver();
+        }
+    }
+
+    /**
+     * getQueryCacheDriver
+     * returns the cache driver used for caching queries
+     *
+     * @return Doctrine_Cache_Interface|boolean|null    cache driver
+     */
+    public function getQueryCacheDriver()
+    {
+        if ($this->_queryCache instanceof Doctrine_Cache_Interface) {
+            return $this->_queryCache;
+        } else {
+            return $this->_conn->getQueryCacheDriver();
+        }
+    }
+
+    /**
+     * getConnection
+     *
+     * @return Doctrine_Connection
+     */
+    public function getConnection()
+    {
+        return $this->_conn;
+    }
+
+    /**
+     * Checks if there's at least one DQL part defined to the internal parts collection.
+     *
+     * @param string $queryPartName  The name of the query part.
+     * @return boolean
+     */
+    protected function _hasDqlQueryPart($queryPartName)
+    {
+        return count($this->_dqlParts[$queryPartName]) > 0;
+    }
+
+
+    /**
+     * Adds a DQL part to the internal parts collection.
+     *
+     * @param string $queryPartName  The name of the query part.
+     * @param string $queryPart      The actual query part to add.
+     * @param boolean $append        Whether to append $queryPart to already existing
+     *                               parts under the same $queryPartName. Defaults to FALSE
+     *                               (previously added parts with the same name get overridden).
+     */
+    protected function _addDqlQueryPart($queryPartName, $queryPart, $append = false)
+    {
+        // We should prevent nullable query parts
+        if ($queryPart === null) {
+            throw new Doctrine_Query_Exception('Cannot define NULL as part of query when defining \'' . $queryPartName . '\'.');
+        }
+
+        if ($append) {
+            $this->_dqlParts[$queryPartName][] = $queryPart;
+        } else {
+            $this->_dqlParts[$queryPartName] = array($queryPart);
+        }
+
+        $this->_state = Doctrine_Query::STATE_DIRTY;
+        return $this;
+    }
+
+    /**
+     * _processDqlQueryPart
+     * parses given query part
+     *
+     * @param string $queryPartName     the name of the query part
+     * @param array $queryParts         an array containing the query part data
+     * @return Doctrine_Query           this object
+     * @todo Better description. "parses given query part" ??? Then wheres the difference
+     *       between process/parseQueryPart? I suppose this does something different.
+     */
+    protected function _processDqlQueryPart($queryPartName, $queryParts)
+    {
+        $this->removeSqlQueryPart($queryPartName);
+
+        if (is_array($queryParts) && ! empty($queryParts)) {
+            foreach ($queryParts as $queryPart) {
+                $parser = $this->_getParser($queryPartName);
+                $sql = $parser->parse($queryPart);
+                if (isset($sql)) {
+                    if ($queryPartName == 'limit' || $queryPartName == 'offset') {
+                        $this->setSqlQueryPart($queryPartName, $sql);
+                    } else {
+                        $this->addSqlQueryPart($queryPartName, $sql);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * _getParser
+     * parser lazy-loader
+     *
+     * @throws Doctrine_Query_Exception     if unknown parser name given
+     * @return Doctrine_Query_Part
+     * @todo Doc/Description: What is the parameter for? Which parsers are available?
+     */
+    protected function _getParser($name)
+    {
+        if ( ! isset($this->_parsers[$name])) {
+            $class = 'Doctrine_Query_' . ucwords(strtolower($name));
+
+            Doctrine::autoload($class);
+
+            if ( ! class_exists($class)) {
+                throw new Doctrine_Query_Exception('Unknown parser ' . $name);
+            }
+
+            $this->_parsers[$name] = new $class($this, $this->_tokenizer);
+        }
+
+        return $this->_parsers[$name];
+    }
+
+    /**
+     * Gets the SQL query that corresponds to this query object.
+     * The returned SQL syntax depends on the connection driver that is used
+     * by this query object at the time of this method call.
+     *
+     * @param array $params
+     */
+    abstract public function getSqlQuery($params = array());
+
+    /**
+     * parseDqlQuery
+     * parses a dql query
+     *
+     * @param string $query         query to be parsed
+     * @return Doctrine_Query_Abstract  this object
+     */
+    abstract public function parseDqlQuery($query);
+
+    /**
+     * @deprecated
+     */
+    public function parseQuery($query)
+    {
+        return $this->parseDqlQuery($query);
+    }
+
+    /**
+     * @deprecated
+     */
+    public function getQuery($params = array())
+    {
+        return $this->getSqlQuery($params);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Check.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,169 @@
+<?php
+/*
+ *  $Id: From.php 1080 2007-02-10 18:17:08Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Check
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Check
+{
+    /**
+     * @var Doctrine_Table $table           Doctrine_Table object
+     */
+    protected $table;
+
+    /**
+     * @var string $sql                     database specific sql CHECK constraint definition 
+     *                                      parsed from the given dql CHECK definition
+     */
+    protected $sql;
+    
+    protected $_tokenizer;
+
+    /**
+     * @param Doctrine_Table|string $table  Doctrine_Table object
+     */
+    public function __construct($table)
+    {
+        if ( ! ($table instanceof Doctrine_Table)) {
+            $table = Doctrine_Manager::getInstance()
+                        ->getCurrentConnection()
+                        ->getTable($table);
+        }
+        $this->table = $table;
+        $this->_tokenizer = new Doctrine_Query_Tokenizer();
+    }
+
+    /**
+     * getTable
+     * returns the table object associated with this object
+     *
+     * @return Doctrine_Connection
+     */
+    public function getTable()
+    {
+        return $this->table;
+    }
+
+    /**
+     * parse
+     *
+     * @param string $dql       DQL CHECK constraint definition
+     * @return string
+     */
+    public function parse($dql)
+    {
+        $this->sql = $this->parseClause($dql);
+    }
+
+    /**
+     * parseClause
+     *
+     * @param string $alias     component alias
+     * @param string $field     the field name
+     * @param mixed $value      the value of the field
+     * @return void
+     */
+    public function parseClause($dql)
+    {
+        $parts = $this->_tokenizer->sqlExplode($dql, ' AND ');
+
+        if (count($parts) > 1) {
+            $ret = array();
+            foreach ($parts as $part) {
+                $ret[] = $this->parseSingle($part);
+            }
+
+            $r = implode(' AND ', $ret);
+        } else {
+            $parts = $this->_tokenizer->quoteExplode($dql, ' OR ');
+            if (count($parts) > 1) {
+                $ret = array();
+                foreach ($parts as $part) {
+                    $ret[] = $this->parseClause($part);
+                }
+
+                $r = implode(' OR ', $ret);
+            } else {
+                $ret = $this->parseSingle($dql);
+                return $ret;
+            }
+        }
+        return '(' . $r . ')';
+    }
+    
+    public function parseSingle($part)
+    {
+        $e = explode(' ', $part);
+        
+        $e[0] = $this->parseFunction($e[0]);
+
+        switch ($e[1]) {
+            case '>':
+            case '<':
+            case '=':
+            case '!=':
+            case '<>':
+
+            break;
+            default:
+                throw new Doctrine_Query_Exception('Unknown operator ' . $e[1]);
+        }
+
+        return implode(' ', $e);
+    }
+    public function parseFunction($dql) 
+    {
+        if (($pos = strpos($dql, '(')) !== false) {
+            $func  = substr($dql, 0, $pos);
+            $value = substr($dql, ($pos + 1), -1);
+            
+            $expr  = $this->table->getConnection()->expression;
+
+            if ( ! method_exists($expr, $func)) {
+                throw new Doctrine_Query_Exception('Unknown function ' . $func);
+            }
+            
+            $func  = $expr->$func($value);
+        }
+        return $func;
+    }
+
+    /**
+     * getSql
+     *
+     * returns database specific sql CHECK constraint definition
+     * parsed from the given dql CHECK definition
+     *
+     * @return string
+     */
+    public function getSql()
+    {
+        return $this->sql;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Condition.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?php
+/*
+ *  $Id: Condition.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Condition
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+abstract class Doctrine_Query_Condition extends Doctrine_Query_Part
+{
+    /**
+     * DQL CONDITION PARSER
+     * parses the join condition/where/having part of the query string
+     *
+     * @param string $str
+     * @return string
+     */
+    public function parse($str)
+    {
+        $tmp = trim($str);
+        
+        $parts = $this->_tokenizer->bracketExplode($str, array(' OR '), '(', ')');
+
+        if (count($parts) > 1) {
+            $ret = array();
+            foreach ($parts as $part) {
+                $part = $this->_tokenizer->bracketTrim($part, '(', ')');
+                $ret[] = $this->parse($part);
+            }
+            $r = implode(' OR ', $ret);
+        } else {
+            $parts = $this->_tokenizer->bracketExplode($str, array(' AND '), '(', ')');
+            
+            // Ticket #1388: We need to make sure we're not splitting a BETWEEN ...  AND ... clause
+            $tmp = array();
+
+            for ($i = 0, $l = count($parts); $i < $l; $i++) {
+                $test = $this->_tokenizer->sqlExplode($parts[$i]);
+
+                if (count($test) == 3 && strtoupper($test[1]) == 'BETWEEN') {
+                    $tmp[] = $parts[$i] . ' AND ' . $parts[++$i];
+                } else {
+                    $tmp[] = $parts[$i];
+                }
+            }
+            
+            $parts = $tmp;
+            unset($tmp);
+
+            if (count($parts) > 1) {
+                $ret = array();
+                foreach ($parts as $part) {
+                    $part = $this->_tokenizer->bracketTrim($part, '(', ')');
+                    $ret[] = $this->parse($part);
+                }
+                $r = implode(' AND ', $ret);
+            } else {
+                // Fix for #710
+                if (substr($parts[0],0,1) == '(' && substr($parts[0], -1) == ')') {
+                    return $this->parse(substr($parts[0], 1, -1));
+                } else {
+                    // Processing NOT here
+                    if (strtoupper(substr($parts[0], 0, 4)) === 'NOT ') {
+                        $r = 'NOT ('.$this->parse(substr($parts[0], 4)).')';
+                    } else {
+                        return $this->load($parts[0]);
+                    }
+                }
+            }
+        }
+        
+        return '(' . $r . ')';
+    }
+
+    /**
+     * parses a literal value and returns the parsed value
+     *
+     * boolean literals are parsed to integers
+     * components are parsed to associated table aliases
+     *
+     * @param string $value         literal value to be parsed
+     * @return string
+     */
+    public function parseLiteralValue($value)
+    {
+        // check that value isn't a string
+        if (strpos($value, '\'') === false) {
+            // parse booleans
+            $value = $this->query->getConnection()
+                     ->dataDict->parseBoolean($value);
+
+            $a = explode('.', $value);
+
+            if (count($a) > 1) {
+            // either a float or a component..
+
+                if ( ! is_numeric($a[0])) {
+                    // a component found
+                    $field     = array_pop($a);
+                	  $reference = implode('.', $a);
+                    $value = $this->query->getConnection()->quoteIdentifier($this->query->getTableAlias($reference). '.' . $field);
+                }
+            }
+        } else {
+            // string literal found
+        }
+
+        return $value;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Filter.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,63 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Filter
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Filter implements Doctrine_Query_Filter_Interface
+{
+    /**
+     * preQuery
+     *
+     * Method for listening the preQuery method of Doctrine_Query and
+     * hooking into the query building procedure, doing any custom / specialized
+     * query building procedures that are neccessary.
+     *
+     * @return void
+     */
+    public function preQuery(Doctrine_Query $query)
+    {
+    
+    }
+
+    /**
+     * postQuery
+     *
+     * Method for listening the postQuery method of Doctrine_Query and
+     * to hook into the query building procedure, doing any custom / specialized
+     * post query procedures (for example logging) that are neccessary.
+     *
+     * @param Doctrine_Query $query
+     * @return void
+     */
+    public function postQuery(Doctrine_Query $query)
+    {
+    
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Filter/Chain.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,109 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Filter_Chain
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Filter_Chain
+{
+    /**
+     * @var array $_filters         an array of Doctrine_Query_Filter objects
+     */
+    protected $_filters = array();
+
+    /**
+     * add
+     *
+     * @param Doctrine_Query_Filter $filter
+     * @return void
+     */
+    public function add(Doctrine_Query_Filter $filter)
+    {
+        $this->_filters[] = $filter;
+    }
+
+    /**
+     * returns a Doctrine_Query_Filter on success
+     * and null on failure
+     *
+     * @param mixed $key
+     * @return mixed
+     */
+    public function get($key)
+    {
+        if ( ! isset($this->_filters[$key])) {
+            throw new Doctrine_Query_Exception('Unknown filter ' . $key);
+        }
+        return $this->_filters[$key];
+    }
+
+    /**
+     * set
+     *
+     * @param mixed $key
+     * @param Doctrine_Query_Filter $listener
+     * @return void
+     */
+    public function set($key, Doctrine_Query_Filter $listener)
+    {
+        $this->_filters[$key] = $listener;
+    }
+
+    /**
+     * preQuery
+     *
+     * Method for listening the preQuery method of Doctrine_Query and
+     * hooking into the query building procedure, doing any custom / specialized
+     * query building procedures that are neccessary.
+     *
+     * @return void
+     */
+    public function preQuery(Doctrine_Query $query)
+    {
+        foreach ($this->_filters as $filter) {
+            $filter->preQuery($query);
+        }
+    }
+
+    /**
+     * postQuery
+     *
+     * Method for listening the postQuery method of Doctrine_Query and
+     * to hook into the query building procedure, doing any custom / specialized
+     * post query procedures (for example logging) that are neccessary.
+     *
+     * @return void
+     */
+    public function postQuery(Doctrine_Query $query)
+    {
+        foreach ($this->_filters as $filter) {
+            $filter->postQuery($query);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Filter/Interface.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,57 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Filter_Interface
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+interface Doctrine_Query_Filter_Interface
+{
+
+    /**
+     * preQuery
+     *
+     * Method for listening the preQuery method of Doctrine_Query and
+     * hooking into the query building procedure, doing any custom / specialized
+     * query building procedures that are neccessary.
+     *
+     * @return void
+     */
+    public function preQuery(Doctrine_Query $query);
+
+    /**
+     * postQuery
+     *
+     * Method for listening the postQuery method of Doctrine_Query and
+     * to hook into the query building procedure, doing any custom / specialized
+     * post query procedures (for example logging) that are neccessary.
+     *
+     * @return void
+     */
+    public function postQuery(Doctrine_Query $query);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Forupdate.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,39 @@
+<?php
+/*
+ *  $Id: Where.php 1352 2007-05-15 10:07:05Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Forupdate
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1352 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Forupdate extends Doctrine_Query_Part
+{
+    public function parse($forUpdate) 
+    {
+        return (bool) $forUpdate;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/From.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,96 @@
+<?php
+/*
+ *  $Id: From.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_From
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_From extends Doctrine_Query_Part
+{
+    /**
+     * DQL FROM PARSER
+     * parses the FROM part of the query string
+     *
+     * @param string $str
+     * @param boolean $return if to return the parsed FROM and skip load()
+     * @return void
+     */
+    public function parse($str, $return = false)
+    {
+        $str = trim($str);
+        $parts = $this->_tokenizer->bracketExplode($str, 'JOIN');
+
+        $from = $return ? array() : null;
+
+        $operator = false;
+
+        switch (trim($parts[0])) {
+            case 'INNER':
+                $operator = ':';
+            case 'LEFT':
+                array_shift($parts);
+            break;
+        }
+
+        $last = '';
+
+        foreach ($parts as $k => $part) {
+            $part = trim($part);
+
+            if (empty($part)) {
+                continue;
+            }
+
+            $e = explode(' ', $part);
+
+            if (end($e) == 'INNER' || end($e) == 'LEFT') {
+                $last = array_pop($e);
+            }
+            $part = implode(' ', $e);
+
+            foreach ($this->_tokenizer->bracketExplode($part, ',') as $reference) {
+                $reference = trim($reference);
+                $e = explode(' ', $reference);
+                $e2 = explode('.', $e[0]);
+
+                if ($operator) {
+                    $e[0] = array_shift($e2) . $operator . implode('.', $e2);
+                }
+
+                if ($return) {
+                    $from[] = $e;
+                } else {
+                    $table = $this->query->load(implode(' ', $e));
+                }
+            }
+
+            $operator = ($last == 'INNER') ? ':' : '.';
+        }
+        return $from;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Groupby.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,52 @@
+<?php
+/*
+ *  $Id: Groupby.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Groupby
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Groupby extends Doctrine_Query_Part
+{
+    /**
+     * DQL GROUP BY PARSER
+     * parses the group by part of the query string
+     *
+     * @param string $str
+     * @return void
+     */
+    public function parse($str, $append = false)
+    {
+        $r = array();
+        foreach (explode(',', $str) as $reference) {
+            $reference = trim($reference);
+
+            $r[] = $this->query->parseClause($reference);
+        }
+        return implode(', ', $r);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Having.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,102 @@
+<?php
+/*
+ *  $Id: Having.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Having
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Having extends Doctrine_Query_Condition
+{
+    /**
+     * DQL Aggregate Function parser
+     *
+     * @param string $func
+     * @return mixed
+     */
+    private function parseAggregateFunction($func)
+    {
+        $pos = strpos($func, '(');
+
+        if ($pos !== false) {
+            $funcs  = array();
+
+            $name   = substr($func, 0, $pos);
+            $func   = substr($func, ($pos + 1), -1);
+            $params = $this->_tokenizer->bracketExplode($func, ',', '(', ')');
+
+            foreach ($params as $k => $param) {
+                $params[$k] = $this->parseAggregateFunction($param);
+            }
+
+            $funcs = $name . '(' . implode(', ', $params) . ')';
+
+            return $funcs;
+
+        } else {
+            if ( ! is_numeric($func)) {
+                $a = explode('.', $func);
+
+                if (count($a) > 1) {
+                    $field     = array_pop($a);
+                    $reference = implode('.', $a);
+                    $map       = $this->query->load($reference, false);
+                    $field     = $map['table']->getColumnName($field);
+                    $func      = $this->query->getTableAlias($reference) . '.' . $field;
+                } else {
+                    $field = end($a);
+                    $func  = $this->query->getAggregateAlias($field);
+                }
+                return $this->query->getConnection()->quoteIdentifier($func);
+            } else {
+                return $this->query->getConnection()->quoteIdentifier($func);
+            }
+        }
+    }
+
+
+    /**
+     * load
+     * returns the parsed query part
+     *
+     * @param string $having
+     * @return string
+     */
+    final public function load($having)
+    {
+        $tokens = $this->_tokenizer->bracketExplode($having, ' ', '(', ')');
+        $part = $this->parseAggregateFunction(array_shift($tokens));
+        $operator  = array_shift($tokens);
+        $value     = implode(' ', $tokens);
+        $part .= ' ' . $operator . ' ' . $value;
+        // check the RHS for aggregate functions
+        if (strpos($value, '(') !== false) {
+          $value = $this->parseAggregateFunction($value);
+        }
+        return $part;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/JoinCondition.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,156 @@
+<?php
+/*
+ *  $Id: JoinCondition.php 5843 2009-06-08 20:06:07Z hobodave $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_JoinCondition
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5843 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_JoinCondition extends Doctrine_Query_Condition
+{
+    public function load($condition)
+    {
+        $condition = trim($condition);
+        $e = $this->_tokenizer->sqlExplode($condition);
+
+        if (($l = count($e)) > 2) {
+            $leftExpr = $this->query->parseClause($e[0]);
+            $operator  = $e[1];
+
+            if ($l == 4) {
+                // FIX: "field NOT IN (XXX)" issue
+                // Related to ticket #1329
+                $operator .= ' ' . $e[2]; // Glue "NOT" and "IN"
+                $e[2] = $e[3]; // Move "(XXX)" to previous index
+
+                unset($e[3]); // Remove unused index
+            } else if ($l >= 5) {
+                // FIX: "field BETWEEN field2 AND field3" issue
+                // Related to ticket #1488
+                $e[2] .= ' ' . $e[3] . ' ' . $e[4];
+
+                unset($e[3], $e[4]); // Remove unused indexes
+            }
+
+            if (substr(trim($e[2]), 0, 1) != '(') {
+                $expr = new Doctrine_Expression($e[2], $this->query->getConnection());
+                $e[2] = $expr->getSql();
+            }
+
+            // We need to check for agg functions here
+            $rightMatches = array();
+            $hasRightAggExpression = $this->_processPossibleAggExpression($e[2], $rightMatches);
+
+            // Defining needed information
+            $value = $e[2];
+
+            if (substr($value, 0, 1) == '(') {
+                // trim brackets
+                $trimmed   = $this->_tokenizer->bracketTrim($value);
+                $trimmed_upper = strtoupper($trimmed);
+
+                if (substr($trimmed_upper, 0, 4) == 'FROM' || substr($trimmed_upper, 0, 6) == 'SELECT') {
+                    // subquery found
+                    $q     = $this->query->createSubquery()->parseQuery($trimmed, false);
+                    $value   = '(' . $q->getSql() . ')';
+                    $q->free();
+                } elseif (substr($trimmed_upper, 0, 4) == 'SQL:') {
+                    // Change due to bug "(" XXX ")"
+                    //$value = '(' . substr($trimmed, 4) . ')';
+                    $value = substr($trimmed, 4);
+                } else {
+                    // simple in expression found
+                    $e = $this->_tokenizer->sqlExplode($trimmed, ',');
+                    $value = array();
+
+                    foreach ($e as $part) {
+                        $value[] = $this->parseLiteralValue($part);
+                    }
+
+                    $value = '(' . implode(', ', $value) . ')';
+                }
+            } else {
+                // Possible expression found (field1 AND field2)
+                // In relation to ticket #1488
+                $e     = $this->_tokenizer->bracketExplode($value, array(' AND ', ' \&\& '), '(', ')');
+                $value = array();
+
+                foreach ($e as $part) {
+                    $value[] = $this->parseLiteralValue($part);
+                }
+
+                $value = implode(' AND ', $value);
+            }
+
+            switch ($operator) {
+                case '<':
+                case '>':
+                case '=':
+                case '!=':
+                default:
+                    $rightExpr = (($hasRightAggExpression) ? $rightMatches[1] . '(' : '')
+                              . $value
+                              . (($hasRightAggExpression) ? $rightMatches[3] . ')' : '') ;
+
+                    $condition  = $leftExpr . ' ' . $operator . ' ' . $rightExpr;
+            }
+
+            return $condition;
+        }
+
+        $parser = new Doctrine_Query_Where($this->query, $this->_tokenizer);
+
+        return $parser->parse($condition);
+    }
+
+
+    protected function _processPossibleAggExpression(& $expr, & $matches = array())
+    {
+        $hasAggExpr = preg_match('/(.*[^\s\(\=])\(([^\)]*)\)(.*)/', $expr, $matches);
+
+        if ($hasAggExpr) {
+            $expr = $matches[2];
+
+            // We need to process possible comma separated items
+            if (substr(trim($matches[3]), 0, 1) == ',') {
+                $xplod = $this->_tokenizer->sqlExplode(trim($matches[3], ' )'), ',');
+
+                $matches[3] = array();
+
+                foreach ($xplod as $part) {
+                    if ($part != '') {
+                        $matches[3][] = $this->parseLiteralValue($part);
+                    }
+                }
+
+                $matches[3] = '), ' . implode(', ', $matches[3]);
+            }
+        }
+
+        return $hasAggExpr;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Limit.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,39 @@
+<?php
+/*
+ *  $Id: Where.php 1352 2007-05-15 10:07:05Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Limit
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1352 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Limit extends Doctrine_Query_Part
+{
+    public function parse($limit) 
+    {
+        return (int) $limit;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Offset.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,39 @@
+<?php
+/*
+ *  $Id: Where.php 1352 2007-05-15 10:07:05Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Offset
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1352 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Offset extends Doctrine_Query_Part
+{
+    public function parse($offset)
+    {
+        return (int) $offset;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Orderby.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,53 @@
+<?php
+/*
+ *  $Id: Orderby.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Orderby
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Orderby extends Doctrine_Query_Part
+{
+    /**
+     * DQL ORDER BY PARSER
+     * parses the order by part of the query string
+     *
+     * @param string $str
+     * @return void
+     */
+    public function parse($str, $append = false)
+    {
+        $ret = array();
+
+        foreach (explode(',', trim($str)) as $r) {
+            $r = $this->query->parseClause($r);
+
+            $ret[] = $r;
+        }
+        return $ret;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Parser.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,35 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Parser
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ */
+class Doctrine_Query_Parser 
+{
+        
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Part.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,61 @@
+<?php
+/*
+ *  $Id: Part.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Part
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+abstract class Doctrine_Query_Part
+{
+    /**
+     * @var Doctrine_Query $query           the query object associated with this parser
+     */
+    protected $query;
+    
+    protected $_tokenizer;
+
+    /**
+     * @param Doctrine_Query $query         the query object associated with this parser
+     */
+    public function __construct($query, Doctrine_Query_Tokenizer $tokenizer = null)
+    {
+        $this->query = $query;
+        if ( ! $tokenizer) {
+            $tokenizer = new Doctrine_Query_Tokenizer();
+        }
+        $this->_tokenizer = $tokenizer;
+    }
+
+    /**
+     * @return Doctrine_Query $query        the query object associated with this parser
+     */
+    public function getQuery()
+    {
+        return $this->query;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Registry.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,82 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Registry
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ */
+class Doctrine_Query_Registry
+{
+    protected $_queries = array();
+
+    public function add($key, $query)
+    {
+        if ($query instanceof Doctrine_Query) {
+            $query = clone $query;
+        }
+
+    	if (strpos($key, '/') === false) {
+            $this->_queries[$key] = $query;
+        } else {
+            // namespace found
+            
+            $e = explode('/', $key);
+
+            $this->_queries[$e[0]][$e[1]] = $query;
+        }
+    }
+    
+    public function get($key, $namespace = null)
+    {
+        if (isset($namespace)) {
+            if ( ! isset($this->_queries[$namespace][$key])) {
+                throw new Doctrine_Query_Registry_Exception('A query with the name ' . $namespace . '/' . $key . ' does not exist.');
+            }
+            $query = $this->_queries[$namespace][$key];
+        } else {
+            if ( ! isset($this->_queries[$key])) {
+                throw new Doctrine_Query_Registry_Exception('A query with the name ' . $key . ' does not exist.');
+            }
+            $query = $this->_queries[$key];
+        }
+        
+        if ( ! ($query instanceof Doctrine_Query)) {
+            $query = Doctrine_Query::create()->parseQuery($query);
+        }
+        
+        return clone $query;
+    }
+    
+    
+    public function has($key, $namespace = null)
+    {
+        return isset($namespace) 
+            ? isset($this->_queries[$namespace][$key])
+            : isset($this->_queries[$key]);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Registry/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ */
+class Doctrine_Query_Registry_Exception extends Doctrine_Query_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Select.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,39 @@
+<?php
+/*
+ *  $Id: From.php 1080 2007-02-10 18:17:08Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Select
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Select extends Doctrine_Query_Part
+{
+    public function parse($dql) 
+    {
+        $this->query->parseSelect($dql);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Set.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,106 @@
+<?php
+/*
+ *  $Id: Set.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Set extends Doctrine_Query_Part
+{
+    public function parse($dql)
+    {
+	    $terms = $this->_tokenizer->sqlExplode($dql, ' ');
+        $termsTranslation = array();
+    	
+        foreach ($terms as $term) {
+	        $termOriginal = $term;
+	    
+	        // We need to check for agg functions here
+            $matches = array();
+            $hasAggExpression = $this->_processPossibleAggExpression($term, $matches);
+
+            $lftExpr = (($hasAggExpression) ? $matches[1] . '(' : '');
+            $rgtExpr = (($hasAggExpression) ? $matches[3] . ')' : '');
+	
+	        preg_match_all("/^([a-zA-Z0-9_]+[\.[a-zA-Z0-9_]+]*)(\sAS\s[a-zA-Z0-9_]+)?/i", $term, $m, PREG_SET_ORDER);
+            
+            if (isset($m[0])) {
+                $processed = array();
+                
+                foreach ($m as $piece) {
+                    $part = $piece[1];
+                    $e = explode('.', trim($part));
+
+                    $fieldName  = array_pop($e);
+                    $reference  = (count($e) > 0) ? implode('.', $e) : $this->query->getRootAlias();
+                    $aliasMap   = $this->query->getAliasDeclaration($reference);
+
+                    if ($aliasMap['table']->hasField($fieldName)) {	
+	                    $columnName = $aliasMap['table']->getColumnName($fieldName);
+                        $columnName = $aliasMap['table']->getConnection()->quoteIdentifier($columnName);
+
+                        $part = $columnName;
+                    }
+                    
+                    $processed[] = $part . (isset($piece[2]) ? $piece[2] : '');
+                }
+                
+                $termsTranslation[$termOriginal] = $lftExpr . implode(' ', $processed) . $rgtExpr;
+            }
+        } 
+
+        return strtr($dql, $termsTranslation);
+    }
+
+
+    protected function _processPossibleAggExpression(& $expr, & $matches = array())
+    {
+        $hasAggExpr = preg_match('/(.*[^\s\(\=])\(([^\)]*)\)(.*)/', $expr, $matches);
+        
+        if ($hasAggExpr) {
+            $expr = $matches[2];
+
+            // We need to process possible comma separated items
+            if (substr(trim($matches[3]), 0, 1) == ',') {
+                $xplod = $this->_tokenizer->sqlExplode(trim($matches[3], ' )'), ',');
+                
+                $matches[3] = array();
+                    
+                foreach ($xplod as $part) {
+                    if ($part != '') {
+                        $matches[3][] = $this->parseLiteralValue($part);
+                    }
+                }
+
+                $matches[3] = '), ' . implode(', ', $matches[3]);
+            }
+        }
+        
+        return $hasAggExpr;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Tokenizer.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,387 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Tokenizer
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @todo Give the tokenizer state, make it better work together with Doctrine_Query and maybe
+ *       take out commonly used string manipulation methods
+ *       into a stateless StringUtil? class. This tokenizer should be concerned with tokenizing
+ *       DQL strings.
+ */
+class Doctrine_Query_Tokenizer
+{
+
+    /**
+     * tokenizeQuery
+     * splits the given dql query into an array where keys
+     * represent different query part names and values are
+     * arrays splitted using sqlExplode method
+     *
+     * example:
+     *
+     * parameter:
+     *      $query = "SELECT u.* FROM User u WHERE u.name LIKE ?"
+     * returns:
+     *      array('select' => array('u.*'),
+     *            'from'   => array('User', 'u'),
+     *            'where'  => array('u.name', 'LIKE', '?'))
+     *
+     * @param string $query                 DQL query
+     * @throws Doctrine_Query_Exception     if some generic parsing error occurs
+     * @return array                        an array containing the query string parts
+     */
+    public function tokenizeQuery($query)
+    {
+        $parts = array();
+        $tokens = $this->sqlExplode($query, ' ');
+
+        foreach ($tokens as $index => $token) {
+            $token = trim($token);
+            switch (strtolower($token)) {
+                case 'delete':
+                case 'update':
+                case 'select':
+                case 'set':
+                case 'from':
+                case 'where':
+                case 'limit':
+                case 'offset':
+                case 'having':
+                    $p = $token;
+                    //$parts[$token] = array();
+                    $parts[$token] = '';
+                break;
+                case 'order':
+                case 'group':
+                    $i = ($index + 1);
+                    if (isset($tokens[$i]) && strtolower($tokens[$i]) === 'by') {
+                        $p = $token;
+                        $parts[$token] = '';
+                        //$parts[$token] = array();
+                    } else {
+                        $parts[$p] .= "$token ";
+                        //$parts[$p][] = $token;
+                    }
+                break;
+                case 'by':
+                    continue;
+                default:
+                    if ( ! isset($p)) {
+                        throw new Doctrine_Query_Tokenizer_Exception(
+                                "Couldn't tokenize query. Encountered invalid token: '$token'.");
+                    }
+
+                    $parts[$p] .= "$token ";
+                    //$parts[$p][] = $token;
+            }
+        }
+        return $parts;
+    }
+
+    /**
+     * trims brackets
+     *
+     * @param string $str
+     * @param string $e1        the first bracket, usually '('
+     * @param string $e2        the second bracket, usually ')'
+     */
+    public function bracketTrim($str, $e1 = '(', $e2 = ')')
+    {
+        if (substr($str, 0, 1) === $e1 && substr($str, -1) === $e2) {
+            return substr($str, 1, -1);
+        } else {
+            return $str;
+        }
+    }
+
+    /**
+     * bracketExplode
+     *
+     * example:
+     *
+     * parameters:
+     *      $str = (age < 20 AND age > 18) AND email LIKE 'John@example.com'
+     *      $d = ' AND '
+     *      $e1 = '('
+     *      $e2 = ')'
+     *
+     * would return an array:
+     *      array("(age < 20 AND age > 18)",
+     *            "email LIKE 'John@example.com'")
+     *
+     * @param string $str
+     * @param string $d         the delimeter which explodes the string
+     * @param string $e1        the first bracket, usually '('
+     * @param string $e2        the second bracket, usually ')'
+     *
+     */
+    public function bracketExplode($str, $d = ' ', $e1 = '(', $e2 = ')')
+    {
+        if (is_array($d)) {
+            $a = preg_split('#('.implode('|', $d).')#i', $str);
+            $d = stripslashes($d[0]);
+        } else {
+            $a = explode($d, $str);
+        }
+
+        $i = 0;
+        $term = array();
+        foreach($a as $key=>$val) {
+            if (empty($term[$i])) {
+                $term[$i] = trim($val);
+                $s1 = substr_count($term[$i], $e1);
+                $s2 = substr_count($term[$i], $e2);
+
+                if ($s1 == $s2) {
+                    $i++;
+                }
+            } else {
+                $term[$i] .= $d . trim($val);
+                $c1 = substr_count($term[$i], $e1);
+                $c2 = substr_count($term[$i], $e2);
+
+                if ($c1 == $c2) {
+                    $i++;
+                }
+            }
+        }
+        return $term;
+    }
+
+    /**
+     * quoteExplode
+     *
+     * example:
+     *
+     * parameters:
+     *      $str = email LIKE 'John@example.com'
+     *      $d = ' LIKE '
+     *
+     * would return an array:
+     *      array("email", "LIKE", "'John@example.com'")
+     *
+     * @param string $str
+     * @param string $d         the delimeter which explodes the string
+     */
+    public function quoteExplode($str, $d = ' ')
+    {
+        if (is_array($d)) {
+            $a = preg_split('/('.implode('|', $d).')/', $str);
+            $d = stripslashes($d[0]);
+        } else {
+            $a = explode($d, $str);
+        }
+
+        $i = 0;
+        $term = array();
+        foreach ($a as $key => $val) {
+            if (empty($term[$i])) {
+                $term[$i] = trim($val);
+
+                if ( ! (substr_count($term[$i], "'") & 1)) {
+                    $i++;
+                }
+            } else {
+                $term[$i] .= $d . trim($val);
+
+                if ( ! (substr_count($term[$i], "'") & 1)) {
+                    $i++;
+                }
+            }
+        }
+        return $term;
+    }
+
+    /**
+     * sqlExplode
+     *
+     * explodes a string into array using custom brackets and
+     * quote delimeters
+     *
+     *
+     * example:
+     *
+     * parameters:
+     *      $str = "(age < 20 AND age > 18) AND name LIKE 'John Doe'"
+     *      $d   = ' '
+     *      $e1  = '('
+     *      $e2  = ')'
+     *
+     * would return an array:
+     *      array('(age < 20 AND age > 18)',
+     *            'name',
+     *            'LIKE',
+     *            'John Doe')
+     *
+     * @param string $str
+     * @param string $d         the delimeter which explodes the string
+     * @param string $e1        the first bracket, usually '('
+     * @param string $e2        the second bracket, usually ')'
+     *
+     * @return array
+     */
+    public function sqlExplode($str, $d = ' ', $e1 = '(', $e2 = ')')
+    {
+        if ($d == ' ') {
+            $d = array(' ', '\s'); 
+        }
+        if (is_array($d)) {
+            $d = array_map('preg_quote', $d);
+
+            if (in_array(' ', $d)) {
+                $d[] = '\s';
+            }
+
+            $split = '#(' . implode('|', $d) . ')#';
+            $str = preg_split($split, $str);
+            $d = stripslashes($d[0]);
+        } else {
+            $str = explode($d, $str);
+        }
+
+        $i = 0;
+        $term = array();
+
+        foreach ($str as $key => $val) {
+            if (empty($term[$i])) {
+                $term[$i] = trim($val);
+
+                $s1 = substr_count($term[$i], $e1);
+                $s2 = substr_count($term[$i], $e2);
+
+                if (strpos($term[$i], '(') !== false) {
+                    if ($s1 == $s2) {
+                        $i++;
+                    }
+                } else {
+                    if ( ! (substr_count($term[$i], "'") & 1) &&
+                         ! (substr_count($term[$i], "\"") & 1)) {
+                        $i++;
+                    }
+                }
+            } else {
+                $term[$i] .= $d . trim($val);
+                $c1 = substr_count($term[$i], $e1);
+                $c2 = substr_count($term[$i], $e2);
+
+                if (strpos($term[$i], '(') !== false) {
+                    if ($c1 == $c2) {
+                        $i++;
+                    }
+                } else {
+                    if ( ! (substr_count($term[$i], "'") & 1) &&
+                           (substr_count($term[$i], "\\\'") & 1) &&
+                         ! (substr_count($term[$i], "\"") & 1)) {
+                        $i++;
+                    }
+                }
+            }
+        }
+        return $term;
+    }
+
+    /**
+     * clauseExplode
+     *
+     * explodes a string into array using custom brackets and
+     * quote delimeters
+     *
+     *
+     * example:
+     *
+     * parameters:
+     *      $str = "(age < 20 AND age > 18) AND name LIKE 'John Doe'"
+     *      $d   = ' '
+     *      $e1  = '('
+     *      $e2  = ')'
+     *
+     * would return an array:
+     *      array('(age < 20 AND age > 18)',
+     *            'name',
+     *            'LIKE',
+     *            'John Doe')
+     *
+     * @param string $str
+     * @param string $d         the delimeter which explodes the string
+     * @param string $e1        the first bracket, usually '('
+     * @param string $e2        the second bracket, usually ')'
+     *
+     * @return array
+     */
+    public function clauseExplode($str, array $d, $e1 = '(', $e2 = ')')
+    {
+        if (is_array($d)) {
+            $d = array_map('preg_quote', $d);
+
+            if (in_array(' ', $d)) {
+                $d[] = '\s';
+            }
+
+            $split = '#(' . implode('|', $d) . ')#';
+
+            $str = preg_split($split, $str, -1, PREG_SPLIT_DELIM_CAPTURE);
+        }
+
+        $i = 0;
+        $term = array();
+
+        foreach ($str as $key => $val) {
+            if ($key & 1) {
+                if (isset($term[($i - 1)]) && ! is_array($term[($i - 1)])) {
+                    $term[($i - 1)] = array($term[($i - 1)], $val);
+                }
+                continue;
+            }
+            if (empty($term[$i])) {
+                $term[$i] = $val;
+            } else {
+                $term[$i] .= $str[($key - 1)] . $val;
+            }
+
+            $c1 = substr_count($term[$i], $e1);
+            $c2 = substr_count($term[$i], $e2);
+
+            if (strpos($term[$i], '(') !== false) {
+                if ($c1 == $c2) {
+                    $i++;
+                }
+            } else {
+                if ( ! (substr_count($term[$i], "'") & 1) &&
+                     ! (substr_count($term[$i], "\"") & 1)) {
+                    $i++;
+                }
+            }
+        }
+
+        if (isset($term[$i - 1])) {
+            $term[$i - 1] = array($term[$i - 1], '');
+        }
+
+        return $term;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Tokenizer/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 2702 2007-10-03 21:43:22Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2702 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Tokenizer_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Where.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,157 @@
+<?php
+/*
+ *  $Id: Where.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Query_Where
+ *
+ * @package     Doctrine
+ * @subpackage  Query
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Query_Where extends Doctrine_Query_Condition
+{
+    public function load($where) 
+    {
+        $where = $this->_tokenizer->bracketTrim(trim($where));
+        $conn  = $this->query->getConnection();
+        $terms = $this->_tokenizer->sqlExplode($where);  
+
+        if (count($terms) > 1) {
+            if (substr($where, 0, 6) == 'EXISTS') {
+                return $this->parseExists($where, true);
+            } elseif (substr($where, 0, 10) == 'NOT EXISTS') {
+                return $this->parseExists($where, false);
+            }
+        }
+
+        if (count($terms) < 3) {
+            $terms = $this->_tokenizer->sqlExplode($where, array('=', '<', '<>', '>', '!='));
+        }
+
+        if (count($terms) > 1) {
+            $first = array_shift($terms);
+            $value = array_pop($terms);
+            $operator = trim(substr($where, strlen($first), -strlen($value)));
+            $table = null;
+            $field = null;
+
+            if (strpos($first, "'") === false && strpos($first, '(') === false) {
+                // normal field reference found
+                $a = explode('.', $first);
+        
+                $field = array_pop($a);
+                $reference = implode('.', $a);
+                
+                if (empty($reference)) {
+                    $map = $this->query->getRootDeclaration();  
+                    
+                    $alias = $this->query->getTableAlias($this->query->getRootAlias());
+                    $table = $map['table'];
+                } else {
+                    $map = $this->query->load($reference, false);
+    
+                    $alias = $this->query->getTableAlias($reference);
+                    $table = $map['table'];
+                }
+            }
+            $first = $this->query->parseClause($first);
+            
+            $sql = $first . ' ' . $operator . ' ' . $this->parseValue($value, $table, $field);
+        
+            return $sql;  
+        } else {
+            return $where;
+        }
+    }
+
+    public function parseValue($value, Doctrine_Table $table = null, $field = null)
+    {
+        $conn = $this->query->getConnection();
+
+        // If value is contained in paranthesis
+        if (substr($value, 0, 1) == '(') {
+            // trim brackets
+            $trimmed = $this->_tokenizer->bracketTrim($value);
+
+            // If subquery found which begins with FROM and SELECT
+            // FROM User u WHERE u.id IN(SELECT u.id FROM User u WHERE u.id = 1)
+            if (substr($trimmed, 0, 4) == 'FROM' ||
+                substr($trimmed, 0, 6) == 'SELECT') {
+
+                // subquery found
+                $q     = $this->query->createSubquery()->parseQuery($trimmed, false);
+                $sql   = $q->getSql();
+                $value = '(' . $sql . ')';
+                $q->free();
+            // If custom sql for custom subquery
+            // You can specify SQL: followed by any valid sql expression
+            // FROM User u WHERE u.id = SQL:(select id from user where id = 1)
+            } elseif (substr($trimmed, 0, 4) == 'SQL:') {
+                $value = '(' . substr($trimmed, 4) . ')';
+            // simple in expression found
+            } else {
+                $e = $this->_tokenizer->sqlExplode($trimmed, ',');
+
+                $value = array();
+
+                $index = false;
+
+                foreach ($e as $part) {
+                    $value[] = $this->parseLiteralValue($part);
+                }
+
+                $value = '(' . implode(', ', $value) . ')';
+            }
+        } else {
+            $value = $this->parseLiteralValue($value);
+        }
+        return $value;
+    }
+
+    /**
+     * parses an EXISTS expression
+     *
+     * @param string $where         query where part to be parsed
+     * @param boolean $negation     whether or not to use the NOT keyword
+     * @return string
+     */
+    public function parseExists($where, $negation)
+    {
+        $operator = ($negation) ? 'EXISTS' : 'NOT EXISTS';
+
+        $pos = strpos($where, '(');
+
+        if ($pos == false) {
+            throw new Doctrine_Query_Exception('Unknown expression, expected a subquery with () -marks');
+        }
+
+        $sub = $this->_tokenizer->bracketTrim(substr($where, $pos));
+
+        $q = $this->query->createSubquery()->parseQuery($sub, false);
+        $sql = $q->getSql();
+        $q->free();
+        return $operator . ' (' . $sql . ')';
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/RawSql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,449 @@
+<?php
+/*
+ *  $Id: RawSql.php 5860 2009-06-09 16:35:27Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_RawSql
+ *
+ * Doctrine_RawSql is an implementation of Doctrine_Query_Abstract that skips the entire
+ * DQL parsing procedure. The "DQL" that is passed to a RawSql query object for execution
+ * is considered to be plain SQL and will be used "as is". The only query part that is special
+ * in a RawSql query is the SELECT part, which has a special syntax that provides Doctrine
+ * with the necessary information to properly hydrate the query results.
+ *
+ * @package     Doctrine
+ * @subpackage  RawSql
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5860 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_RawSql extends Doctrine_Query_Abstract
+{
+    /**
+     * @var array $fields
+     */
+    private $fields = array();
+    
+	/**
+     * Constructor.
+     *
+     * @param Doctrine_Connection  The connection object the query will use.
+     * @param Doctrine_Hydrator_Abstract  The hydrator that will be used for generating result sets.
+     */
+    function __construct(Doctrine_Connection $connection = null, Doctrine_Hydrator_Abstract $hydrator = null) {
+        parent::__construct($connection, $hydrator);
+
+        // Fix #1472. It's alid to disable QueryCache since there's no DQL for RawSql.
+        // RawSql expects to be plain SQL + syntax for SELECT part. It is used as is in query execution.
+        $this->useQueryCache(false);
+    }
+
+
+    /**
+     * @deprecated
+     */
+    public function parseQueryPart($queryPartName, $queryPart, $append = false)
+    {
+        return $this->parseDqlQueryPart($queryPartName, $queryPart, $append);
+    }
+
+    /**
+     * parseDqlQueryPart
+     * parses given DQL query part. Overrides Doctrine_Query_Abstract::parseDqlQueryPart().
+     * This implementation does no parsing at all, except of the SELECT portion of the query
+     * which is special in RawSql queries. The entire remaining parts are used "as is", so
+     * the user of the RawSql query is responsible for writing SQL that is portable between
+     * different DBMS.
+     *
+     * @param string $queryPartName     the name of the query part
+     * @param string $queryPart         query part to be parsed
+     * @param boolean $append           whether or not to append the query part to its stack
+     *                                  if false is given, this method will overwrite
+     *                                  the given query part stack with $queryPart
+     * @return Doctrine_Query           this object
+     */
+ 	public function parseDqlQueryPart($queryPartName, $queryPart, $append = false)
+    {
+        if ($queryPartName == 'select') {
+     	    $this->_parseSelectFields($queryPart);
+     	    return $this;
+     	}
+     	if ( ! isset($this->_sqlParts[$queryPartName])) {
+     	    $this->_sqlParts[$queryPartName] = array();
+     	}
+     	
+     	if ( ! $append) {
+     	    $this->_sqlParts[$queryPartName] = array($queryPart);
+     	} else {
+     	    $this->_sqlParts[$queryPartName][] = $queryPart;
+     	}
+     	return $this;
+    }
+    
+    /**
+     * Adds a DQL query part. Overrides Doctrine_Query_Abstract::_addDqlQueryPart().
+     * This implementation for RawSql parses the new parts right away, generating the SQL.
+     */
+    protected function _addDqlQueryPart($queryPartName, $queryPart, $append = false)
+    {
+        return $this->parseQueryPart($queryPartName, $queryPart, $append);
+    }
+    
+    /**
+     * Add select parts to fields.
+     *
+     * @param $queryPart sting The name of the querypart
+     */
+    private function _parseSelectFields($queryPart){
+        preg_match_all('/{([^}{]*)}/U', $queryPart, $m);
+        $this->fields = $m[1];
+        $this->_sqlParts['select'] = array();
+    }
+    
+    /**
+     * parseDqlQuery
+     * parses an sql query and adds the parts to internal array.
+     * Overrides Doctrine_Query_Abstract::parseDqlQuery().
+     * This implementation simply tokenizes the provided query string and uses them
+     * as SQL parts right away.
+     *
+     * @param string $query     query to be parsed
+     * @return Doctrine_RawSql  this object
+     */
+    public function parseDqlQuery($query)
+    {
+        $this->_parseSelectFields($query);
+        $this->clear();
+
+        $tokens = $this->_tokenizer->sqlExplode($query, ' ');
+
+        $parts = array();
+        foreach ($tokens as $key => $part) {
+            $partLowerCase = strtolower($part);
+            switch ($partLowerCase) {
+                case 'select':
+                case 'from':
+                case 'where':
+                case 'limit':
+                case 'offset':
+                case 'having':
+                    $type = $partLowerCase;
+                    if ( ! isset($parts[$partLowerCase])) {
+                        $parts[$partLowerCase] = array();
+                    }
+                    break;
+                case 'order':
+                case 'group':
+                    $i = $key + 1;
+                    if (isset($tokens[$i]) && strtolower($tokens[$i]) === 'by') {
+                        $type = $partLowerCase . 'by';
+                        $parts[$type] = array();
+                    } else {
+                        //not a keyword so we add it to the previous type
+                        $parts[$type][] = $part;
+                    }
+                    break;
+                case 'by':
+                    continue;
+                default:
+                    //not a keyword so we add it to the previous type.
+                    if ( ! isset($parts[$type][0])) {
+                        $parts[$type][0] = $part;
+                    } else {
+                        // why does this add to index 0 and not append to the 
+                        // array. If it had done that one could have used 
+                        // parseQueryPart.
+                        $parts[$type][0] .= ' '.$part;
+                    }
+            }
+        }
+
+        $this->_sqlParts = $parts;
+        $this->_sqlParts['select'] = array();
+
+        return $this;
+    }
+
+    /**
+     * getSqlQuery
+     * builds the sql query.
+     *
+     * @return string       the built sql query
+     */
+    public function getSqlQuery($params = array())
+    {        
+        $select = array();
+
+        foreach ($this->fields as $field) {
+            $e = explode('.', $field);
+            if ( ! isset($e[1])) {
+                throw new Doctrine_RawSql_Exception('All selected fields in Sql query must be in format tableAlias.fieldName');
+            }
+            // try to auto-add component
+            if ( ! $this->hasSqlTableAlias($e[0])) {
+                try {
+                    $this->addComponent($e[0], ucwords($e[0]));
+                } catch (Doctrine_Exception $exception) {
+                    throw new Doctrine_RawSql_Exception('The associated component for table alias ' . $e[0] . ' couldn\'t be found.');
+                }
+            }
+
+            $componentAlias = $this->getComponentAlias($e[0]);
+            
+            if ($e[1] == '*') {
+                foreach ($this->_queryComponents[$componentAlias]['table']->getColumnNames() as $name) {
+                    $field = $e[0] . '.' . $name;
+
+                    $select[$componentAlias][$field] = $field . ' AS ' . $e[0] . '__' . $name;
+                }
+            } else {
+                $field = $e[0] . '.' . $e[1];
+                $select[$componentAlias][$field] = $field . ' AS ' . $e[0] . '__' . $e[1];
+            }
+        }
+
+        // force-add all primary key fields
+        if ( ! isset($this->_sqlParts['distinct']) || $this->_sqlParts['distinct'] != true) {
+            foreach ($this->getTableAliasMap() as $tableAlias => $componentAlias) {
+                $map = $this->_queryComponents[$componentAlias];
+
+                foreach ((array) $map['table']->getIdentifierColumnNames() as $key) {
+                    $field = $tableAlias . '.' . $key;
+
+                    if ( ! isset($this->_sqlParts['select'][$field])) {
+                        $select[$componentAlias][$field] = $field . ' AS ' . $tableAlias . '__' . $key;
+                    }
+                }
+            }
+        }
+
+        $q = 'SELECT ';
+
+        if (isset($this->_sqlParts['distinct']) && $this->_sqlParts['distinct'] == true) {
+            $q .= 'DISTINCT ';
+        }
+
+        // first add the fields of the root component
+        reset($this->_queryComponents);
+        $componentAlias = key($this->_queryComponents);
+
+        $this->_rootAlias = $componentAlias;
+        
+        $q .= implode(', ', $select[$componentAlias]);
+        unset($select[$componentAlias]);
+
+        foreach ($select as $component => $fields) {
+            if ( ! empty($fields)) {
+                $q .= ', ' . implode(', ', $fields);
+            }
+        }
+
+        $string = $this->getInheritanceCondition($this->getRootAlias());
+
+        if ( ! empty($string)) {
+            $this->_sqlParts['where'][] = $string;
+        }
+
+        $q .= ( ! empty($this->_sqlParts['from']))?    ' FROM '     . implode(' ', $this->_sqlParts['from']) : '';
+        $q .= ( ! empty($this->_sqlParts['where']))?   ' WHERE '    . implode(' AND ', $this->_sqlParts['where']) : '';
+        $q .= ( ! empty($this->_sqlParts['groupby']))? ' GROUP BY ' . implode(', ', $this->_sqlParts['groupby']) : '';
+        $q .= ( ! empty($this->_sqlParts['having']))?  ' HAVING '   . implode(' AND ', $this->_sqlParts['having']) : '';
+        $q .= ( ! empty($this->_sqlParts['orderby']))? ' ORDER BY ' . implode(', ', $this->_sqlParts['orderby']) : '';
+        $q .= ( ! empty($this->_sqlParts['limit']))?   ' LIMIT ' . implode(' ', $this->_sqlParts['limit']) : '';
+        $q .= ( ! empty($this->_sqlParts['offset']))?  ' OFFSET ' . implode(' ', $this->_sqlParts['offset']) : '';
+
+        if ( ! empty($string)) {
+            array_pop($this->_sqlParts['where']);
+        }
+        return $q;
+    }
+
+	/**
+     * getCountQuery
+     * builds the count query.
+     *
+     * @return string       the built sql query
+     */
+	public function getCountQuery($params = array())
+    {
+        //Doing COUNT( DISTINCT rootComponent.id )
+        //This is not correct, if the result is not hydrated by doctrine, but it mimics the behaviour of Doctrine_Query::getCountQuery
+        reset($this->_queryComponents);
+        $componentAlias = key($this->_queryComponents);
+
+        $this->_rootAlias = $componentAlias;
+
+        $tableAlias = $this->getSqlTableAlias($componentAlias);
+        $fields = array();
+
+        foreach ((array) $this->_queryComponents[$componentAlias]['table']->getIdentifierColumnNames() as $key) {
+        	$fields[] = $tableAlias . '.' . $key;
+        }
+
+        $q = 'SELECT COUNT( DISTINCT '.implode(',',$fields).') as num_results';
+
+        $string = $this->getInheritanceCondition($this->getRootAlias());
+        if ( ! empty($string)) {
+            $this->_sqlParts['where'][] = $string;
+        }
+
+        $q .= ( ! empty($this->_sqlParts['from']))?    ' FROM '     . implode(' ', $this->_sqlParts['from']) : '';
+        $q .= ( ! empty($this->_sqlParts['where']))?   ' WHERE '    . implode(' AND ', $this->_sqlParts['where']) : '';
+        $q .= ( ! empty($this->_sqlParts['groupby']))? ' GROUP BY ' . implode(', ', $this->_sqlParts['groupby']) : '';
+        $q .= ( ! empty($this->_sqlParts['having']))?  ' HAVING '   . implode(' AND ', $this->_sqlParts['having']) : '';
+
+        if ( ! empty($string)) {
+            array_pop($this->_sqlParts['where']);
+        }
+
+        return $q;
+    }
+
+	/**
+     * count
+     * fetches the count of the query
+     *
+     * This method executes the main query without all the
+     * selected fields, ORDER BY part, LIMIT part and OFFSET part.
+     *
+     * This is an exact copy of the Dql Version
+     *
+     * @see Doctrine_Query::count()
+     * @param array $params        an array of prepared statement parameters
+     * @return integer             the count of this query
+     */
+    public function count($params = array())
+    {
+        $q = $this->getCountQuery();
+
+        if ( ! is_array($params)) {
+            $params = array($params);
+        }
+
+        $params = array_merge($this->_params['join'], $this->_params['where'], $this->_params['having'], $params);
+
+        $results = $this->getConnection()->fetchAll($q, $params);
+
+        if (count($results) > 1) {
+            $count = count($results);
+        } else {
+            if (isset($results[0])) {
+                $results[0] = array_change_key_case($results[0], CASE_LOWER);
+                $count = $results[0]['num_results'];
+            } else {
+                $count = 0;
+            }
+        }
+
+        return (int) $count;
+    }
+
+    /**
+     * getFields
+     * returns the fields associated with this parser
+     *
+     * @return array    all the fields associated with this parser
+     */
+    public function getFields()
+    {
+        return $this->fields;
+    }
+
+    /**
+     * addComponent
+     *
+     * @param string $tableAlias
+     * @param string $componentName
+     * @return Doctrine_RawSql
+     */
+    public function addComponent($tableAlias, $path)
+    {
+        $tmp           = explode(' ', $path);
+        $originalAlias = (count($tmp) > 1) ? end($tmp) : null;
+
+        $e = explode('.', $tmp[0]);
+
+        $fullPath = $tmp[0];
+        $fullLength = strlen($fullPath);
+
+        $table = null;
+
+        $currPath = '';
+
+        if (isset($this->_queryComponents[$e[0]])) {
+            $table = $this->_queryComponents[$e[0]]['table'];
+
+            $currPath = $parent = array_shift($e);
+        }
+
+        foreach ($e as $k => $component) {
+            // get length of the previous path
+            $length = strlen($currPath);
+
+            // build the current component path
+            $currPath = ($currPath) ? $currPath . '.' . $component : $component;
+
+            $delimeter = substr($fullPath, $length, 1);
+
+            // if an alias is not given use the current path as an alias identifier
+            if (strlen($currPath) === $fullLength && isset($originalAlias)) {
+                $componentAlias = $originalAlias;
+            } else {
+                $componentAlias = $currPath;
+            }
+            if ( ! isset($table)) {
+                $conn = Doctrine_Manager::getInstance()
+                        ->getConnectionForComponent($component);
+                        
+                $table = $conn->getTable($component);
+                $this->_queryComponents[$componentAlias] = array('table' => $table);
+            } else {
+                $relation = $table->getRelation($component);
+
+                $this->_queryComponents[$componentAlias] = array('table'    => $relation->getTable(),
+                                                          'parent'   => $parent,
+                                                          'relation' => $relation);
+            }
+            $this->addSqlTableAlias($tableAlias, $componentAlias);
+
+            $parent = $currPath;
+        }
+
+        return $this;
+    }
+
+    /**
+     * calculateResultCacheHash
+     * calculate hash key for result cache
+     *
+     * @param array $params
+     * @return string    the hash
+     */
+    public function calculateResultCacheHash($params = array())
+    {
+        $sql = $this->getSql();
+        $conn = $this->getConnection();
+        $params = $this->getFlattenedParams($params);
+        $hash = md5($this->_hydrator->getHydrationMode() . $conn->getName() . $conn->getOption('dsn') . $sql . var_export($params, true));
+        return $hash;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/RawSql/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_RawSql_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  RawSql
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_RawSql_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,2198 @@
+<?php
+/*
+ *  $Id: Record.php 5877 2009-06-11 12:06:07Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Record
+ * All record classes should inherit this super class
+ *
+ * @package     Doctrine
+ * @subpackage  Record
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5877 $
+ */
+abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Countable, IteratorAggregate, Serializable
+{
+    /**
+     * STATE CONSTANTS
+     */
+
+    /**
+     * DIRTY STATE
+     * a Doctrine_Record is in dirty state when its properties are changed
+     */
+    const STATE_DIRTY       = 1;
+
+    /**
+     * TDIRTY STATE
+     * a Doctrine_Record is in transient dirty state when it is created
+     * and some of its fields are modified but it is NOT yet persisted into database
+     */
+    const STATE_TDIRTY      = 2;
+
+    /**
+     * CLEAN STATE
+     * a Doctrine_Record is in clean state when all of its properties are loaded from the database
+     * and none of its properties are changed
+     */
+    const STATE_CLEAN       = 3;
+
+    /**
+     * PROXY STATE
+     * a Doctrine_Record is in proxy state when its properties are not fully loaded
+     */
+    const STATE_PROXY       = 4;
+
+    /**
+     * NEW TCLEAN
+     * a Doctrine_Record is in transient clean state when it is created and none of its fields are modified
+     */
+    const STATE_TCLEAN      = 5;
+
+    /**
+     * LOCKED STATE
+     * a Doctrine_Record is temporarily locked during deletes and saves
+     *
+     * This state is used internally to ensure that circular deletes
+     * and saves will not cause infinite loops
+     */
+    const STATE_LOCKED     = 6;
+
+ 	/**
+ 	 * TLOCKED STATE
+ 	 * a Doctrine_Record is temporarily locked (and transient) during deletes and saves
+ 	 *
+ 	 * This state is used internally to ensure that circular deletes
+ 	 * and saves will not cause infinite loops
+ 	 */
+ 	const STATE_TLOCKED     = 7;
+
+
+    /**
+     * @var Doctrine_Node_<TreeImpl>        node object
+     */
+    protected $_node;
+
+    /**
+     * @var integer $_id                    the primary keys of this object
+     */
+    protected $_id           = array();
+
+    /**
+     * @var array $_data                    the record data
+     */
+    protected $_data         = array();
+
+    /**
+     * @var array $_values                  the values array, aggregate values and such are mapped into this array
+     */
+    protected $_values       = array();
+
+    /**
+     * @var integer $_state                 the state of this record
+     * @see STATE_* constants
+     */
+    protected $_state;
+
+    /**
+     * @var array $_modified                an array containing field names that have been modified
+     * @todo Better name? $_modifiedFields?
+     */
+    protected $_modified     = array();
+
+    /**
+     * @var Doctrine_Validator_ErrorStack   error stack object
+     */
+    protected $_errorStack;
+
+    /**
+     * @var array $_references              an array containing all the references
+     */
+    protected $_references     = array();
+
+    /**
+     * Doctrine_Collection of objects needing to be deleted on save
+     *
+     * @var string
+     */
+    protected $_pendingDeletes = array();
+
+    /**
+     * Array of custom accessors for cache
+     *
+     * @var array
+     */
+    protected static $_customAccessors = array();
+
+    /**
+     * Array of custom mutators for cache
+     *
+     * @var array
+     */
+    protected static $_customMutators = array();
+
+    /**
+     * Whether or not to serialize references when a Doctrine_Record is serialized
+     *
+     * @var boolean
+     */
+    protected $_serializeReferences = false;
+
+    /**
+     * @var integer $index                  this index is used for creating object identifiers
+     */
+    private static $_index = 1;
+
+    /**
+     * @var integer $oid                    object identifier, each Record object has a unique object identifier
+     */
+    private $_oid;
+
+    /**
+     * constructor
+     * @param Doctrine_Table|null $table       a Doctrine_Table object or null,
+     *                                         if null the table object is retrieved from current connection
+     *
+     * @param boolean $isNewEntry              whether or not this record is transient
+     *
+     * @throws Doctrine_Connection_Exception   if object is created using the new operator and there are no
+     *                                         open connections
+     * @throws Doctrine_Record_Exception       if the cleanData operation fails somehow
+     */
+    public function __construct($table = null, $isNewEntry = false)
+    {
+        if (isset($table) && $table instanceof Doctrine_Table) {
+            $this->_table = $table;
+            $exists = ( ! $isNewEntry);
+        } else {
+            // get the table of this class
+            $class = get_class($this);
+            $this->_table = Doctrine::getTable($class);
+            $exists = false;
+        }
+
+        // Check if the current connection has the records table in its registry
+        // If not this record is only used for creating table definition and setting up
+        // relations.
+        if ( ! $this->_table->getConnection()->hasTable($this->_table->getComponentName())) {
+            return;
+        }
+
+        $this->_oid = self::$_index;
+
+        self::$_index++;
+
+        // get the data array
+        $this->_data = $this->_table->getData();
+
+        // get the column count
+        $count = count($this->_data);
+
+        $this->_values = $this->cleanData($this->_data);
+
+        $this->prepareIdentifiers($exists);
+
+        if ( ! $exists) {
+            if ($count > count($this->_values)) {
+                $this->_state = Doctrine_Record::STATE_TDIRTY;
+            } else {
+                $this->_state = Doctrine_Record::STATE_TCLEAN;
+            }
+
+            // set the default values for this record
+            $this->assignDefaultValues();
+        } else {
+            $this->_state = Doctrine_Record::STATE_CLEAN;
+
+            if ($count < $this->_table->getColumnCount()) {
+                $this->_state  = Doctrine_Record::STATE_PROXY;
+            }
+        }
+
+        $repository = $this->_table->getRepository();
+        $repository->add($this);
+
+        $this->construct();
+    }
+
+    /**
+     * Set whether or not to serialize references.
+     * This is used by caching since we want to serialize references when caching
+     * but not when just normally serializing a instance
+     *
+     * @param boolean $bool
+     * @return boolean $bool
+     */
+    public function serializeReferences($bool = null)
+    {
+        if ( ! is_null($bool)) {
+            $this->_serializeReferences = $bool;
+        }
+        return $this->_serializeReferences;
+    }
+
+    /**
+     * _index
+     *
+     * @return integer
+     */
+    public static function _index()
+    {
+        return self::$_index;
+    }
+
+    /**
+     * setUp
+     * this method is used for setting up relations and attributes
+     * it should be implemented by child classes
+     *
+     * @return void
+     */
+    public function setUp()
+    { }
+    /**
+     * construct
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the constructor procedure
+     *
+     * @return void
+     */
+    public function construct()
+    { }
+    /**
+     * getOid
+     * returns the object identifier
+     *
+     * @return integer
+     */
+    public function getOid()
+    {
+        return $this->_oid;
+    }
+    public function oid()
+    {
+        return $this->_oid;
+    }
+
+    /**
+     * isValid
+     *
+     * @return boolean  whether or not this record is valid
+     */
+    public function isValid()
+    {
+        if ( ! $this->_table->getAttribute(Doctrine::ATTR_VALIDATE)) {
+            return true;
+        }
+        // Clear the stack from any previous errors.
+        $this->getErrorStack()->clear();
+
+        // Run validation process
+        $event = new Doctrine_Event($this, Doctrine_Event::RECORD_VALIDATE);
+        $this->preValidate($event);
+        $this->getTable()->getRecordListener()->preValidate($event);
+        
+        if ( ! $event->skipOperation) {
+        
+            $validator = new Doctrine_Validator();
+            $validator->validateRecord($this);
+            $this->validate();
+            if ($this->_state == self::STATE_TDIRTY || $this->_state == self::STATE_TCLEAN) {
+                $this->validateOnInsert();
+            } else {
+                $this->validateOnUpdate();
+            }
+        }
+
+        $this->getTable()->getRecordListener()->postValidate($event);
+        $this->postValidate($event);
+
+        return $this->getErrorStack()->count() == 0 ? true : false;
+    }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the validation procedure, doing any custom / specialized
+     * validations that are neccessary.
+     */
+    protected function validate()
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the validation procedure only when the record is going to be
+     * updated.
+     */
+    protected function validateOnUpdate()
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the validation procedure only when the record is going to be
+     * inserted into the data store the first time.
+     */
+    protected function validateOnInsert()
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the serializing procedure.
+     */
+    public function preSerialize($event)
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the serializing procedure.
+     */
+    public function postSerialize($event)
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the serializing procedure.
+     */
+    public function preUnserialize($event)
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the serializing procedure.
+     */
+    public function postUnserialize($event)
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the saving procedure.
+     */
+    public function preSave($event)
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the saving procedure.
+     */
+    public function postSave($event)
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the deletion procedure.
+     */
+    public function preDelete($event)
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the deletion procedure.
+     */
+    public function postDelete($event)
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the saving procedure only when the record is going to be
+     * updated.
+     */
+    public function preUpdate($event)
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the saving procedure only when the record is going to be
+     * updated.
+     */
+    public function postUpdate($event)
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the saving procedure only when the record is going to be
+     * inserted into the data store the first time.
+     */
+    public function preInsert($event)
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the saving procedure only when the record is going to be
+     * inserted into the data store the first time.
+     */
+    public function postInsert($event)
+    { }
+
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the validation procedure. Useful for cleaning up data before 
+     * validating it.
+     */
+    public function preValidate($event)
+    { }
+    /**
+     * Empty template method to provide concrete Record classes with the possibility
+     * to hook into the validation procedure.
+     */
+    public function postValidate($event)
+    { }
+
+    /**
+     * Empty template method to provide Record classes with the ability to alter DQL select
+     * queries at runtime
+     */
+    public function preDqlSelect($event)
+    { }
+
+    /**
+     * Empty template method to provide Record classes with the ability to alter DQL update
+     * queries at runtime
+     */
+    public function preDqlUpdate($event)
+    { }
+
+    /**
+     * Empty template method to provide Record classes with the ability to alter DQL delete
+     * queries at runtime
+     */
+    public function preDqlDelete($event)
+    { }
+
+    /**
+     * Get the record error stack as a human readable string.
+     * Useful for outputting errors to user via web browser
+     *
+     * @return string $message
+     */
+    public function getErrorStackAsString()
+    {
+        $errorStack = $this->getErrorStack();
+
+        if (count($errorStack)) {
+            $message = sprintf("Validation failed in class %s\n\n", get_class($this));
+
+            $message .= "  " . count($errorStack) . " field" . (count($errorStack) > 1 ?  's' : null) . " had validation error" . (count($errorStack) > 1 ?  's' : null) . ":\n\n";
+            foreach ($errorStack as $field => $errors) {
+                $message .= "    * " . count($errors) . " validator" . (count($errors) > 1 ?  's' : null) . " failed on $field (" . implode(", ", $errors) . ")\n";
+            }
+            return $message;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * getErrorStack
+     *
+     * @return Doctrine_Validator_ErrorStack    returns the errorStack associated with this record
+     */
+    public function getErrorStack()
+    {
+        if ( ! $this->_errorStack) {
+            $this->_errorStack = new Doctrine_Validator_ErrorStack(get_class($this));
+        }
+        
+        return $this->_errorStack;
+    }
+
+    /**
+     * errorStack
+     * assigns / returns record errorStack
+     *
+     * @param Doctrine_Validator_ErrorStack          errorStack to be assigned for this record
+     * @return void|Doctrine_Validator_ErrorStack    returns the errorStack associated with this record
+     */
+    public function errorStack($stack = null)
+    {
+        if ($stack !== null) {
+            if ( ! ($stack instanceof Doctrine_Validator_ErrorStack)) {
+               throw new Doctrine_Record_Exception('Argument should be an instance of Doctrine_Validator_ErrorStack.');
+            }
+            $this->_errorStack = $stack;
+        } else {
+            return $this->getErrorStack();
+        }
+    }
+
+    /**
+     * Assign the inheritance column values
+     *
+     * @return void
+     */
+    public function assignInheritanceValues()
+    {
+        $map = $this->_table->inheritanceMap;
+        foreach ($map as $k => $v) {
+            $k = $this->_table->getFieldName($k);
+            $old = $this->get($k, false);
+
+            if (((string) $old !== (string) $v || $old === null) && !in_array($k, $this->_modified)) {
+                $this->set($k, $v);
+            }
+        }
+    }
+
+    /**
+     * setDefaultValues
+     * sets the default values for records internal data
+     *
+     * @param boolean $overwrite                whether or not to overwrite the already set values
+     * @return boolean
+     */
+    public function assignDefaultValues($overwrite = false)
+    {
+        if ( ! $this->_table->hasDefaultValues()) {
+            return false;
+        }
+        foreach ($this->_data as $column => $value) {
+            $default = $this->_table->getDefaultValueOf($column);
+
+            if ($default === null) {
+                continue;
+            }
+
+            if ($value === self::$_null || $overwrite) {
+                $this->_data[$column] = $default;
+                $this->_modified[]    = $column;
+                $this->_state = Doctrine_Record::STATE_TDIRTY;
+            }
+        }
+    }
+
+    /**
+     * cleanData
+     * leaves the $data array only with values whose key is a field inside this
+     * record and returns the values that were removed from $data.  Also converts
+     * any values of 'null' to objects of type Doctrine_Null.
+     *
+     * @param array $data       data array to be cleaned
+     * @return array $tmp       values cleaned from data
+     */
+    public function cleanData(&$data)
+    {
+        $tmp = $data;
+        $data = array();
+
+        foreach ($this->getTable()->getFieldNames() as $fieldName) {
+            if (isset($tmp[$fieldName])) {
+                $data[$fieldName] = $tmp[$fieldName];
+            } else if (array_key_exists($fieldName, $tmp)) {
+                $data[$fieldName] = self::$_null;
+            } else if (!isset($this->_data[$fieldName])) {
+                $data[$fieldName] = self::$_null;
+            }
+            unset($tmp[$fieldName]);
+        }
+
+        return $tmp;
+    }
+
+    /**
+     * hydrate
+     * hydrates this object from given array
+     *
+     * @param array $data
+     * @return boolean
+     */
+    public function hydrate(array $data, $overwriteLocalChanges = true)
+    {
+        if ($overwriteLocalChanges) {
+            $this->_values = array_merge($this->_values, $this->cleanData($data));
+            $this->_data = array_merge($this->_data, $data);
+        } else {
+            $this->_values = array_merge($this->cleanData($data), $this->_values);
+            $this->_data = array_merge($data, $this->_data);
+        }
+
+        if ( ! $this->isModified() && count($this->_values) < $this->_table->getColumnCount()) {
+            $this->_state = self::STATE_PROXY;
+        }
+    }
+
+    /**
+     * prepareIdentifiers
+     * prepares identifiers for later use
+     *
+     * @param boolean $exists               whether or not this record exists in persistent data store
+     * @return void
+     */
+    private function prepareIdentifiers($exists = true)
+    {
+        switch ($this->_table->getIdentifierType()) {
+            case Doctrine::IDENTIFIER_AUTOINC:
+            case Doctrine::IDENTIFIER_SEQUENCE:
+            case Doctrine::IDENTIFIER_NATURAL:
+                $name = $this->_table->getIdentifier();
+                if (is_array($name)) {
+                    $name = $name[0];
+                }
+                if ($exists) {
+                    if (isset($this->_data[$name]) && $this->_data[$name] !== self::$_null) {
+                        $this->_id[$name] = $this->_data[$name];
+                    }
+                }
+                break;
+            case Doctrine::IDENTIFIER_COMPOSITE:
+                $names = $this->_table->getIdentifier();
+
+                foreach ($names as $name) {
+                    if ($this->_data[$name] === self::$_null) {
+                        $this->_id[$name] = null;
+                    } else {
+                        $this->_id[$name] = $this->_data[$name];
+                    }
+                }
+                break;
+        }
+    }
+
+    /**
+     * serialize
+     * this method is automatically called when this Doctrine_Record is serialized
+     *
+     * @return array
+     */
+    public function serialize()
+    {
+        $event = new Doctrine_Event($this, Doctrine_Event::RECORD_SERIALIZE);
+
+        $this->preSerialize($event);
+        $this->getTable()->getRecordListener()->preSerialize($event);
+
+        $vars = get_object_vars($this);
+
+        if ( ! $this->serializeReferences()) {
+            unset($vars['_references']);
+        }
+        unset($vars['_table']);
+        unset($vars['_errorStack']);
+        unset($vars['_filter']);
+        unset($vars['_node']);
+
+        $data = $this->_data;
+        if ($this->exists()) {
+            $data = array_merge($data, $this->_id);
+        }
+
+        foreach ($data as $k => $v) {
+            if ($v instanceof Doctrine_Record && $this->_table->getTypeOf($k) != 'object') {
+                unset($vars['_data'][$k]);
+            } elseif ($v === self::$_null) {
+                unset($vars['_data'][$k]);
+            } else {
+                switch ($this->_table->getTypeOf($k)) {
+                    case 'array':
+                    case 'object':
+                        $vars['_data'][$k] = serialize($vars['_data'][$k]);
+                        break;
+                    case 'gzip':
+                        $vars['_data'][$k] = gzcompress($vars['_data'][$k]);
+                        break;
+                }
+            }
+        }
+
+        $str = serialize($vars);
+
+        $this->postSerialize($event);
+        $this->getTable()->getRecordListener()->postSerialize($event);
+
+        return $str;
+    }
+
+    /**
+     * unseralize
+     * this method is automatically called everytime a Doctrine_Record object is unserialized
+     *
+     * @param string $serialized                Doctrine_Record as serialized string
+     * @throws Doctrine_Record_Exception        if the cleanData operation fails somehow
+     * @return void
+     */
+    public function unserialize($serialized)
+    {
+        $event = new Doctrine_Event($this, Doctrine_Event::RECORD_UNSERIALIZE);
+        
+        $manager    = Doctrine_Manager::getInstance();
+        $connection = $manager->getConnectionForComponent(get_class($this));
+
+        $this->_oid = self::$_index;
+        self::$_index++;
+
+        $this->_table = $connection->getTable(get_class($this));
+        
+        $this->preUnserialize($event);
+        $this->getTable()->getRecordListener()->preUnserialize($event);
+
+        $array = unserialize($serialized);
+
+        foreach($array as $k => $v) {
+            $this->$k = $v;
+        }
+
+        foreach ($this->_data as $k => $v) {
+            switch ($this->_table->getTypeOf($k)) {
+                case 'array':
+                case 'object':
+                    $this->_data[$k] = unserialize($this->_data[$k]);
+                    break;
+                case 'gzip':
+                   $this->_data[$k] = gzuncompress($this->_data[$k]);
+                    break;
+                case 'enum':
+                    $this->_data[$k] = $this->_table->enumValue($k, $this->_data[$k]);
+                    break;
+
+            }
+        }
+
+        $this->_table->getRepository()->add($this);
+
+        $this->cleanData($this->_data);
+
+        $this->prepareIdentifiers($this->exists());
+
+        $this->postUnserialize($event);
+        $this->getTable()->getRecordListener()->postUnserialize($event);
+    }
+
+    /**
+     * state
+     * returns / assigns the state of this record
+     *
+     * @param integer|string $state                 if set, this method tries to set the record state to $state
+     * @see Doctrine_Record::STATE_* constants
+     *
+     * @throws Doctrine_Record_State_Exception      if trying to set an unknown state
+     * @return null|integer
+     */
+    public function state($state = null)
+    {
+        if ($state == null) {
+            return $this->_state;
+        }
+        
+        $err = false;
+        if (is_integer($state)) {
+            if ($state >= 1 && $state <= 7) {
+                $this->_state = $state;
+            } else {
+                $err = true;
+            }
+        } else if (is_string($state)) {
+            $upper = strtoupper($state);
+
+            $const = 'Doctrine_Record::STATE_' . $upper;
+            if (defined($const)) {
+                $this->_state = constant($const);
+            } else {
+                $err = true;
+            }
+        }
+
+        if ($this->_state === Doctrine_Record::STATE_TCLEAN ||
+                $this->_state === Doctrine_Record::STATE_CLEAN) {
+            $this->_modified = array();
+        }
+
+        if ($err) {
+            throw new Doctrine_Record_State_Exception('Unknown record state ' . $state);
+        }
+    }
+
+    /**
+     * refresh
+     * refresh internal data from the database
+     *
+     * @param bool $deep                        If true, fetch also current relations. Caution: this deletes
+     *                                          any aggregated values you may have queried beforee
+     *
+     * @throws Doctrine_Record_Exception        When the refresh operation fails (when the database row
+     *                                          this record represents does not exist anymore)
+     * @return boolean
+     */
+    public function refresh($deep = false)
+    {
+        $id = $this->identifier();
+        if ( ! is_array($id)) {
+            $id = array($id);
+        }
+        if (empty($id)) {
+            return false;
+        }
+        $id = array_values($id);
+
+        $overwrite = $this->getTable()->getAttribute(Doctrine::ATTR_HYDRATE_OVERWRITE);
+        $this->getTable()->setAttribute(Doctrine::ATTR_HYDRATE_OVERWRITE, true);
+
+        if ($deep) {
+            $query = $this->getTable()->createQuery();
+            foreach (array_keys($this->_references) as $name) {
+                $query->leftJoin(get_class($this) . '.' . $name);
+            }
+            $query->where(implode(' = ? AND ', (array)$this->getTable()->getIdentifier()) . ' = ?');
+            $this->clearRelated();
+            $record = $query->fetchOne($id);
+        } else {
+            // Use HYDRATE_ARRAY to avoid clearing object relations
+            $record = $this->getTable()->find($id, Doctrine::HYDRATE_ARRAY);
+            if ($record) {
+                $this->hydrate($record);
+            }
+        }
+
+        $this->getTable()->setAttribute(Doctrine::ATTR_HYDRATE_OVERWRITE, $overwrite);
+
+        if ($record === false) {
+            throw new Doctrine_Record_Exception('Failed to refresh. Record does not exist.');
+        }
+
+        $this->_modified = array();
+
+        $this->prepareIdentifiers();
+
+        $this->_state = Doctrine_Record::STATE_CLEAN;
+
+        return $this;
+    }
+
+    /**
+     * refresh
+     * refresh data of related objects from the database
+     *
+     * @param string $name              name of a related component.
+     *                                  if set, this method only refreshes the specified related component
+     *
+     * @return Doctrine_Record          this object
+     */
+    public function refreshRelated($name = null)
+    {
+        if (is_null($name)) {
+            foreach ($this->_table->getRelations() as $rel) {
+                $this->_references[$rel->getAlias()] = $rel->fetchRelatedFor($this);
+            }
+        } else {
+            $rel = $this->_table->getRelation($name);
+            $this->_references[$name] = $rel->fetchRelatedFor($this);
+        }
+    }
+
+    /**
+     * clearRelated
+     * unsets all the relationships this object has
+     *
+     * (references to related objects still remain on Table objects)
+     */
+    public function clearRelated()
+    {
+        $this->_references = array();
+    }
+
+    /**
+     * getTable
+     * returns the table object for this record
+     *
+     * @return Doctrine_Table        a Doctrine_Table object
+     */
+    public function getTable()
+    {
+        return $this->_table;
+    }
+
+    /**
+     * getData
+     * return all the internal data
+     *
+     * @return array                        an array containing all the properties
+     */
+    public function getData()
+    {
+        return $this->_data;
+    }
+
+    /**
+     * rawGet
+     * returns the value of a property, if the property is not yet loaded
+     * this method does NOT load it
+     *
+     * @param $name                         name of the property
+     * @throws Doctrine_Record_Exception    if trying to get an unknown property
+     * @return mixed
+     */
+    public function rawGet($fieldName)
+    {
+        if ( ! isset($this->_data[$fieldName])) {
+            throw new Doctrine_Record_Exception('Unknown property '. $fieldName);
+        }
+        if ($this->_data[$fieldName] === self::$_null) {
+            return null;
+        }
+
+        return $this->_data[$fieldName];
+    }
+
+    /**
+     * load
+     * Loads all the uninitialized properties from the database.
+     * Used to move a record from PROXY to CLEAN/DIRTY state.
+     *
+     * @return boolean
+     */
+    public function load(array $data = array())
+    {
+        // only load the data from database if the Doctrine_Record is in proxy state
+        if ($this->_state == Doctrine_Record::STATE_PROXY) {
+            $id = $this->identifier();
+            
+            if ( ! is_array($id)) {
+                $id = array($id);
+            }
+            
+            if (empty($id)) {
+                return false;
+            }
+
+            $data = empty($data) ? $this->getTable()->find($id, Doctrine::HYDRATE_ARRAY) : $data;
+            
+            foreach ($data as $field => $value) {
+               if ( ! isset($this->_data[$field]) || $this->_data[$field] === self::$_null) {
+                   // Ticket #2031: null value was causing removal of field during load
+                   if ($value === null) { 
+                       $value = self::$_null; 
+                   }
+
+                   $this->_data[$field] = $value;
+               }
+            }
+            
+            if ($this->isModified()) {
+               $this->_state = Doctrine_Record::STATE_DIRTY;
+            } else if (count($data) >= $this->_table->getColumnCount()) {
+                $this->_state = Doctrine_Record::STATE_CLEAN;
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * get
+     * returns a value of a property or a related component
+     *
+     * @param mixed $name                       name of the property or related component
+     * @param boolean $load                     whether or not to invoke the loading procedure
+     * @throws Doctrine_Record_Exception        if trying to get a value of unknown property / related component
+     * @return mixed
+     */
+    public function get($fieldName, $load = true)
+    {
+        if ($this->_table->getAttribute(Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE)) {
+            $componentName = $this->_table->getComponentName();
+
+            $accessor = isset(self::$_customAccessors[$componentName][$fieldName])
+                ? self::$_customAccessors[$componentName][$fieldName]
+                : 'get' . Doctrine_Inflector::classify($fieldName);
+
+            if (isset(self::$_customAccessors[$componentName][$fieldName]) || method_exists($this, $accessor)) {
+                self::$_customAccessors[$componentName][$fieldName] = $accessor;
+                return $this->$accessor($load);
+            }
+        }
+
+        return $this->_get($fieldName, $load);
+    }
+
+    protected function _get($fieldName, $load = true)
+    {
+        $value = self::$_null;
+
+        if (array_key_exists($fieldName, $this->_data)) {
+            // check if the value is the Doctrine_Null object located in self::$_null)
+            if ($this->_data[$fieldName] === self::$_null && $load) {
+                $this->load();
+            }
+
+            if ($this->_data[$fieldName] === self::$_null) {
+                $value = null;
+            } else {
+                $value = $this->_data[$fieldName];
+            }
+            return $value;
+        }
+
+        if (array_key_exists($fieldName, $this->_values)) {
+            return $this->_values[$fieldName];
+        }
+        
+        try {
+            if ( ! isset($this->_references[$fieldName]) && $load) {
+                $rel = $this->_table->getRelation($fieldName);
+                $this->_references[$fieldName] = $rel->fetchRelatedFor($this);
+            }
+
+            if ($this->_references[$fieldName] === self::$_null) {
+                return null;
+            }
+
+            return $this->_references[$fieldName];
+        } catch (Doctrine_Table_Exception $e) {
+            $success = false;
+            foreach ($this->_table->getFilters() as $filter) {
+                try {
+                    $value = $filter->filterGet($this, $fieldName);
+                    $success = true;
+                } catch (Doctrine_Exception $e) {}
+            }
+            if ($success) {
+                return $value;
+            } else {
+                throw $e;
+            }
+        }
+    }
+
+    /**
+     * mapValue
+     * This simple method is used for mapping values to $values property.
+     * Usually this method is used internally by Doctrine for the mapping of
+     * aggregate values.
+     *
+     * @param string $name                  the name of the mapped value
+     * @param mixed $value                  mixed value to be mapped
+     * @return void
+     */
+    public function mapValue($name, $value)
+    {
+        $this->_values[$name] = $value;
+    }
+
+    /**
+     * set
+     * method for altering properties and Doctrine_Record references
+     * if the load parameter is set to false this method will not try to load uninitialized record data
+     *
+     * @param mixed $name                   name of the property or reference
+     * @param mixed $value                  value of the property or reference
+     * @param boolean $load                 whether or not to refresh / load the uninitialized record data
+     *
+     * @throws Doctrine_Record_Exception    if trying to set a value for unknown property / related component
+     * @throws Doctrine_Record_Exception    if trying to set a value of wrong type for related component
+     *
+     * @return Doctrine_Record
+     */
+    public function set($fieldName, $value, $load = true)
+    {
+        if ($this->_table->getAttribute(Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE)) {
+            $componentName = $this->_table->getComponentName();
+            $mutator = isset(self::$_customMutators[$componentName][$fieldName]) ? self::$_customMutators[$componentName][$fieldName]:'set' . Doctrine_Inflector::classify($fieldName);
+            if (isset(self::$_customMutators[$componentName][$fieldName]) || method_exists($this, $mutator)) {
+                self::$_customMutators[$componentName][$fieldName] = $mutator;
+                return $this->$mutator($value, $load);
+            }
+        }
+        return $this->_set($fieldName, $value, $load);
+    }
+
+    protected function _set($fieldName, $value, $load = true)
+    {
+        if (isset($this->_data[$fieldName])) {
+            $type = $this->_table->getTypeOf($fieldName);
+            if ($value instanceof Doctrine_Record) {
+                $id = $value->getIncremented();
+
+                if ($id !== null && $type !== 'object') {
+                    $value = $id;
+                }
+            }
+
+            if ($load) {
+                $old = $this->get($fieldName, $load);
+            } else {
+                $old = $this->_data[$fieldName];
+            }
+            
+            if ($this->_isValueModified($type, $old, $value)) {
+                if ($value === null) {
+                    $default = $this->_table->getDefaultValueOf($fieldName); 
+                    $value = ($default === null) ? self::$_null : $default;
+                }
+                $this->_data[$fieldName] = $value;
+                $this->_modified[] = $fieldName;
+
+                switch ($this->_state) {
+                    case Doctrine_Record::STATE_CLEAN:
+                    case Doctrine_Record::STATE_PROXY:
+                        $this->_state = Doctrine_Record::STATE_DIRTY;
+                        break;
+                    case Doctrine_Record::STATE_TCLEAN:
+                        $this->_state = Doctrine_Record::STATE_TDIRTY;
+                        break;
+                }
+            }
+        } else {
+            try {
+                $this->coreSetRelated($fieldName, $value);
+            } catch (Doctrine_Table_Exception $e) {
+                $success = false;
+                foreach ($this->_table->getFilters() as $filter) {
+                    try {
+                        $value = $filter->filterSet($this, $fieldName, $value);
+                        $success = true;
+                    } catch (Doctrine_Exception $e) {}
+                }
+                if ($success) {
+                    return $value;
+                } else {
+                    throw $e;
+                }
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Check if a value has changed according to Doctrine
+     * Doctrine is loose with type checking in the same ways PHP is for consistancy of behavior
+     *
+     * This function basically says if what is being set is of Doctrine type boolean and something
+     * like current_value == 1 && new_value = true would not be considered modified
+     *
+     * Simply doing $old !== $new will return false for boolean columns would mark the field as modified
+     * and change it in the database when it is not necessary
+     *
+     * @param string $type  Doctrine type of the column
+     * @param string $old   Old value
+     * @param string $new   New value
+     * @return boolean $modified  Whether or not Doctrine considers the value modified
+     */
+    protected function _isValueModified($type, $old, $new)
+    {
+        if ($type == 'boolean' && (is_bool($old) || is_numeric($old)) && (is_bool($new) || is_numeric($new)) && $old == $new) {
+            return false;
+        } else if (in_array($type, array('decimal', 'float')) && is_numeric($old) && is_numeric($new)) {
+            return $old * 100 != $new * 100;
+        } else if (in_array($type, array('integer', 'int')) && is_numeric($old) && is_numeric($new)) {
+            return (int) $old !== (int) $new;
+        } else {
+            return $old !== $new;
+        }
+    }
+
+    /**
+     * DESCRIBE WHAT THIS METHOD DOES, PLEASE!
+     * @todo Refactor. What about composite keys?
+     */
+    public function coreSetRelated($name, $value)
+    {
+        $rel = $this->_table->getRelation($name);
+        
+        if ($value === null) {
+            $value = self::$_null;
+        }
+        
+        // one-to-many or one-to-one relation
+        if ($rel instanceof Doctrine_Relation_ForeignKey || $rel instanceof Doctrine_Relation_LocalKey) {
+            if ( ! $rel->isOneToOne()) {
+                // one-to-many relation found
+                if ( ! ($value instanceof Doctrine_Collection)) {
+                    throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Collection when setting one-to-many references.");
+                }
+
+                if (isset($this->_references[$name])) {
+                    $this->_references[$name]->setData($value->getData());
+
+                    return $this;
+                }
+            } else {
+                $localFieldName = $this->_table->getFieldName($rel->getLocal());
+
+                if ($value !== self::$_null) {
+                    $relatedTable = $value->getTable();
+                    $foreignFieldName = $relatedTable->getFieldName($rel->getForeign());
+                }
+
+                // one-to-one relation found
+                if ( ! ($value instanceof Doctrine_Record) && ! ($value instanceof Doctrine_Null)) {
+                    throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Record or Doctrine_Null when setting one-to-one references.");
+                }
+
+                if ($rel instanceof Doctrine_Relation_LocalKey) {
+                    if ($value !== self::$_null &&  ! empty($foreignFieldName) && $foreignFieldName != $value->getTable()->getIdentifier()) {
+                        $this->set($localFieldName, $value->rawGet($foreignFieldName), false);
+                    } else {
+                        // FIX: Ticket #1280 fits in this situation
+                        $this->set($localFieldName, $value, false);
+                    }
+                } elseif ($value !== self::$_null) {
+                    // We should only be able to reach $foreignFieldName if we have a Doctrine_Record on hands
+                    $value->set($foreignFieldName, $this, false);
+                }
+            }
+        } else if ($rel instanceof Doctrine_Relation_Association) {
+            // join table relation found
+            if ( ! ($value instanceof Doctrine_Collection)) {
+                throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Collection when setting many-to-many references.");
+            }
+        }
+
+        $this->_references[$name] = $value;
+    }
+
+    /**
+     * contains
+     *
+     * @param string $name
+     * @return boolean
+     */
+    public function contains($fieldName)
+    {
+        if (isset($this->_data[$fieldName])) {
+            // this also returns true if the field is a Doctrine_Null.
+            // imho this is not correct behavior.
+            return true;
+        }
+        if (isset($this->_id[$fieldName])) {
+            return true;
+        }
+        if (isset($this->_values[$fieldName])) {
+            return true;
+        }
+        if (isset($this->_references[$fieldName]) &&
+            $this->_references[$fieldName] !== self::$_null) {
+
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @param string $name
+     * @return void
+     */
+    public function __unset($name)
+    {
+        if (isset($this->_data[$name])) {
+            $this->_data[$name] = array();
+        } else if (isset($this->_references[$name])) {
+            if ($this->_references[$name] instanceof Doctrine_Record) {
+                $this->_pendingDeletes[] = $this->$name;
+                $this->_references[$name] = self::$_null;
+            } elseif ($this->_references[$name] instanceof Doctrine_Collection) {
+                $this->_pendingDeletes[] = $this->$name;
+                $this->_references[$name]->setData(array());
+            }
+        }
+    }
+
+    /**
+     * getPendingDeletes
+     *
+     * @return array Array of Doctrine_Records instances which need to be deleted on save
+     */
+    public function getPendingDeletes()
+    {
+        return $this->_pendingDeletes;
+    }
+
+    /**
+     * applies the changes made to this object into database
+     * this method is smart enough to know if any changes are made
+     * and whether to use INSERT or UPDATE statement
+     *
+     * this method also saves the related components
+     *
+     * @param Doctrine_Connection $conn                 optional connection parameter
+     * @return void
+     */
+    public function save(Doctrine_Connection $conn = null)
+    {
+        if ($conn === null) {
+            $conn = $this->_table->getConnection();
+        }
+        $conn->unitOfWork->saveGraph($this);
+    }
+
+    /**
+     * Tries to save the object and all its related components.
+     * In contrast to Doctrine_Record::save(), this method does not
+     * throw an exception when validation fails but returns TRUE on
+     * success or FALSE on failure.
+     *
+     * @param Doctrine_Connection $conn                 optional connection parameter
+     * @return TRUE if the record was saved sucessfully without errors, FALSE otherwise.
+     */
+    public function trySave(Doctrine_Connection $conn = null) {
+        try {
+            $this->save($conn);
+            return true;
+        } catch (Doctrine_Validator_Exception $ignored) {
+            return false;
+        }
+    }
+
+    /**
+     * replace
+     * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
+     * query, except that if there is already a row in the table with the same
+     * key field values, the REPLACE query just updates its values instead of
+     * inserting a new row.
+     *
+     * The REPLACE type of query does not make part of the SQL standards. Since
+     * practically only MySQL and SQLIte implement it natively, this type of
+     * query isemulated through this method for other DBMS using standard types
+     * of queries inside a transaction to assure the atomicity of the operation.
+     *
+     * @param Doctrine_Connection $conn             optional connection parameter
+     * @throws Doctrine_Connection_Exception        if some of the key values was null
+     * @throws Doctrine_Connection_Exception        if there were no key fields
+     * @throws Doctrine_Connection_Exception        if something fails at database level
+     * @return integer                              number of rows affected
+     */
+    public function replace(Doctrine_Connection $conn = null)
+    {
+        if ($conn === null) {
+            $conn = $this->_table->getConnection();
+        }
+
+        if ($this->exists()) {
+            return $this->save();
+        } else {
+            if ($this->isValid()) {
+                $identifier = (array) $this->getTable()->getIdentifier();
+                $data = $this->getPrepared();
+                return $conn->replace($this->_table, $data, $identifier);
+            } else {
+                return false;
+            }
+        }
+    }
+
+    /**
+     * returns an array of modified fields and associated values
+     * @return array
+     * @todo What about a better name? getModifiedFields?
+     */
+    public function getModified()
+    {
+        $a = array();
+
+        foreach ($this->_modified as $k => $v) {
+            $a[$v] = $this->_data[$v];
+        }
+        return $a;
+    }
+
+    /**
+     * REDUNDANT?
+     */
+    public function modifiedFields()
+    {
+        $a = array();
+
+        foreach ($this->_modified as $k => $v) {
+            $a[$v] = $this->_data[$v];
+        }
+        return $a;
+    }
+
+    /**
+     * getPrepared
+     *
+     * returns an array of modified fields and values with data preparation
+     * adds column aggregation inheritance and converts Records into primary key values
+     *
+     * @param array $array
+     * @return array
+     * @todo What about a little bit more expressive name? getPreparedData?
+     */
+    public function getPrepared(array $array = array())
+    {
+        $a = array();
+
+        if (empty($array)) {
+            $modifiedFields = $this->_modified;
+        }
+
+        foreach ($modifiedFields as $field) {
+            $type = $this->_table->getTypeOf($field);
+
+            if ($this->_data[$field] === self::$_null) {
+                $a[$field] = null;
+                continue;
+            }
+
+            switch ($type) {
+                case 'array':
+                case 'object':
+                    $a[$field] = serialize($this->_data[$field]);
+                    break;
+                case 'gzip':
+                    $a[$field] = gzcompress($this->_data[$field],5);
+                    break;
+                case 'boolean':
+                    $a[$field] = $this->getTable()->getConnection()->convertBooleans($this->_data[$field]);
+                break;
+                default:
+                    if ($this->_data[$field] instanceof Doctrine_Record) {
+                        $a[$field] = $this->_data[$field]->getIncremented();
+                        if ($a[$field] !== null) {
+                            $this->_data[$field] = $a[$field];
+                        }
+                    } else {
+                        $a[$field] = $this->_data[$field];
+                    }
+                    /** TODO:
+                    if ($this->_data[$v] === null) {
+                        throw new Doctrine_Record_Exception('Unexpected null value.');
+                    }
+                    */
+            }
+        }
+
+        return $a;
+    }
+
+    /**
+     * count
+     * this class implements countable interface
+     *
+     * @return integer          the number of columns in this record
+     */
+    public function count()
+    {
+        return count($this->_data);
+    }
+
+    /**
+     * alias for count()
+     *
+     * @return integer          the number of columns in this record
+     */
+    public function columnCount()
+    {
+        return $this->count();
+    }
+
+    /**
+     * toArray
+     * returns the record as an array
+     *
+     * @param boolean $deep - Return also the relations
+     * @return array
+     */
+    public function toArray($deep = true, $prefixKey = false)
+    {
+        if ($this->_state == self::STATE_LOCKED || $this->_state == self::STATE_TLOCKED) {
+            return false;
+        }
+        
+        $stateBeforeLock = $this->_state;
+        $this->_state = $this->exists() ? self::STATE_LOCKED : self::STATE_TLOCKED;
+        
+        $a = array();
+
+        foreach ($this as $column => $value) {
+            if ($value === self::$_null || is_object($value)) {
+                $value = null;
+            }
+
+            $columnValue = $this->get($column);
+            $a[$column] = ($columnValue instanceof Doctrine_Record) 
+                ? $columnValue->toArray($deep, $prefixKey) : $columnValue;
+        }
+
+        if ($this->_table->getIdentifierType() ==  Doctrine::IDENTIFIER_AUTOINC) {
+            $i      = $this->_table->getIdentifier();
+            $a[$i]  = $this->getIncremented();
+        }
+        
+        if ($deep) {
+            foreach ($this->_references as $key => $relation) {
+                if ( ! $relation instanceof Doctrine_Null) {
+                    $a[$key] = $relation->toArray($deep, $prefixKey);
+                }
+            }
+        }
+
+        // [FIX] Prevent mapped Doctrine_Records from being displayed fully
+        foreach ($this->_values as $key => $value) {
+            $a[$key] = ($value instanceof Doctrine_Record)  
+                ? $value->toArray($deep, $prefixKey) : $value;
+        }
+        
+        $this->_state = $stateBeforeLock;
+
+        return $a;
+    }
+
+    /**
+     * Merges this record with an array of values
+     * or with another existing instance of this object
+     *
+     * @param  mixed $data Data to merge. Either another instance of this model or an array
+     * @param  bool  $deep Bool value for whether or not to merge the data deep
+     * @return void
+     */
+    public function merge($data, $deep = true)
+    {
+        if ($data instanceof $this) {
+            $array = $data->toArray($deep);
+        } else if (is_array($data)) {
+            $array = $data;
+        }
+
+        return $this->fromArray($array, $deep);
+    }
+
+    /**
+     * Import data from a php array
+     *
+     * @param   string $array Php array of data
+     * @param   bool   $deep  Bool value for whether or not to merge the data deep
+     * @return  void
+     */
+    public function fromArray(array $array, $deep = true)
+    {
+        $refresh = false;
+        foreach ($array as $key => $value) {
+            if ($key == '_identifier') {
+                $refresh = true;
+                $this->assignIdentifier($value);
+                continue;
+            }
+
+            if ($deep && $this->getTable()->hasRelation($key)) {
+                if ( ! $this->$key) {
+                    $this->refreshRelated($key);
+                }
+
+                if (is_array($value)) {
+                    $this->$key->fromArray($value, $deep);
+                }
+            } else if ($this->getTable()->hasField($key)) {
+                $this->set($key, $value);
+            } else {
+	            $method = 'set' . Doctrine_Inflector::classify($key);
+
+	            try {
+	                if (is_callable(array($this, $method))) {
+	                    $this->$method($value);
+	                }
+	            } catch (Doctrine_Record_Exception $e) {}
+	        }
+        }
+
+        if ($refresh) {
+            $this->refresh();
+        }
+    }
+
+    /**
+     * Synchronizes a Doctrine_Record and its relations with data from an array
+     *
+     * it expects an array representation of a Doctrine_Record similar to the return
+     * value of the toArray() method. If the array contains relations it will create
+     * those that don't exist, update the ones that do, and delete the ones missing
+     * on the array but available on the Doctrine_Record
+     *
+     * @param array $array representation of a Doctrine_Record
+     */
+    public function synchronizeWithArray(array $array, $deep = true)
+    {
+        $refresh = false;
+        foreach ($array as $key => $value) {
+            if ($key == '_identifier') {
+                $refresh = true;
+                $this->assignIdentifier($value);
+                continue;
+            }
+
+            if ($deep && $this->getTable()->hasRelation($key)) {
+                if ( ! $this->$key) {
+                    $this->refreshRelated($key);
+                }
+
+                if (is_array($value)) {
+                    $this->get($key)->synchronizeWithArray($value);
+                }
+            } else if ($this->getTable()->hasField($key)) {
+                $this->set($key, $value);
+            }
+        }
+
+        // eliminate relationships missing in the $array
+        foreach ($this->_references as $name => $obj) {
+            if ( ! isset($array[$name])) {
+                unset($this->$name);
+            }
+        }
+
+        if ($refresh) {
+            $this->refresh();
+        }
+    }
+
+    /**
+     * exportTo
+     *
+     * @param string $type Format type: xml, yml, json
+     * @param string $deep Whether or not to export deep in to all relationships
+     * @return mixed $exported
+     */
+    public function exportTo($type, $deep = true)
+    {
+        if ($type == 'array') {
+            return $this->toArray($deep);
+        } else {
+            return Doctrine_Parser::dump($this->toArray($deep, true), $type);
+        }
+    }
+
+    /**
+     * importFrom
+     *
+     * Import data from an external data source
+     *
+     * @param string $type  Format type: xml, yml, json
+     * @param string $data  Data to be parsed and imported
+     * @return void
+     */
+    public function importFrom($type, $data)
+    {
+        if ($type == 'array') {
+            return $this->fromArray($data);
+        } else {
+            return $this->fromArray(Doctrine_Parser::load($data, $type));
+        }
+    }
+
+    /**
+     * exists
+     * returns true if this record is persistent, otherwise false
+     *
+     * @return boolean
+     */
+    public function exists()
+    {
+        return ($this->_state !== Doctrine_Record::STATE_TCLEAN  &&
+                $this->_state !== Doctrine_Record::STATE_TDIRTY  &&
+                $this->_state !== Doctrine_Record::STATE_TLOCKED &&
+                $this->_state !== null);
+    }
+
+    /**
+     * isModified
+     * returns true if this record was modified, otherwise false
+     *
+     * @return boolean
+     */
+    public function isModified()
+    {
+        return ($this->_state === Doctrine_Record::STATE_DIRTY ||
+                $this->_state === Doctrine_Record::STATE_TDIRTY);
+    }
+
+    /**
+     * method for checking existence of properties and Doctrine_Record references
+     * @param mixed $name               name of the property or reference
+     * @return boolean
+     */
+    public function hasRelation($fieldName)
+    {
+        if (isset($this->_data[$fieldName]) || isset($this->_id[$fieldName])) {
+            return true;
+        }
+        return $this->_table->hasRelation($fieldName);
+    }
+
+    /**
+     * getIterator
+     * @return Doctrine_Record_Iterator     a Doctrine_Record_Iterator that iterates through the data
+     */
+    public function getIterator()
+    {
+        return new Doctrine_Record_Iterator($this);
+    }
+
+    /**
+     * deletes this data access object and all the related composites
+     * this operation is isolated by a transaction
+     *
+     * this event can be listened by the onPreDelete and onDelete listeners
+     *
+     * @return boolean      true on success, false on failure
+     */
+    public function delete(Doctrine_Connection $conn = null)
+    {
+        if ($conn == null) {
+            $conn = $this->_table->getConnection();
+        }
+        return $conn->unitOfWork->delete($this);
+    }
+
+    /**
+     * copy
+     * returns a copy of this object
+     *
+     * @return Doctrine_Record
+     */
+    public function copy($deep = false)
+    {
+        $data = $this->_data;
+
+        if ($this->_table->getIdentifierType() === Doctrine::IDENTIFIER_AUTOINC) {
+            $id = $this->_table->getIdentifier();
+
+            unset($data[$id]);
+        }
+
+        $ret = $this->_table->create($data);
+        $modified = array();
+
+        foreach ($data as $key => $val) {
+            if ( ! ($val instanceof Doctrine_Null)) {
+                $ret->_modified[] = $key;
+            }
+        }
+
+        if ($deep) {
+            foreach ($this->_references as $key => $value) {
+                if ($value instanceof Doctrine_Collection) {
+                    foreach ($value as $record) {
+                        $ret->{$key}[] = $record->copy($deep);
+                    }
+                } else if($value instanceof Doctrine_Record) {
+                    $ret->set($key, $value->copy($deep));
+                }
+            }
+        }
+
+        return $ret;
+    }
+
+    /**
+     * assignIdentifier
+     *
+     * @param integer $id
+     * @return void
+     */
+    public function assignIdentifier($id = false)
+    {
+        if ($id === false) {
+            $this->_id       = array();
+            $this->_data     = $this->cleanData($this->_data);
+            $this->_state    = Doctrine_Record::STATE_TCLEAN;
+            $this->_modified = array();
+        } elseif ($id === true) {
+            $this->prepareIdentifiers(true);
+            $this->_state    = Doctrine_Record::STATE_CLEAN;
+            $this->_modified = array();
+        } else {
+            if (is_array($id)) {
+                foreach ($id as $fieldName => $value) {
+                    $this->_id[$fieldName] = $value;
+                    $this->_data[$fieldName] = $value;
+                }
+            } else {
+                $name = $this->_table->getIdentifier();
+                $this->_id[$name] = $id;
+                $this->_data[$name] = $id;
+            }
+            $this->_state = Doctrine_Record::STATE_CLEAN;
+            $this->_modified = array();
+        }
+    }
+
+    /**
+     * returns the primary keys of this object
+     *
+     * @return array
+     */
+    public function identifier()
+    {
+        return $this->_id;
+    }
+
+    /**
+     * returns the value of autoincremented primary key of this object (if any)
+     *
+     * @return integer
+     * @todo Better name?
+     */
+    final public function getIncremented()
+    {
+        $id = current($this->_id);
+        if ($id === false) {
+            return null;
+        }
+
+        return $id;
+    }
+
+    /**
+     * getLast
+     * this method is used internally be Doctrine_Query
+     * it is needed to provide compatibility between
+     * records and collections
+     *
+     * @return Doctrine_Record
+     */
+    public function getLast()
+    {
+        return $this;
+    }
+
+    /**
+     * hasRefence
+     * @param string $name
+     * @return boolean
+     */
+    public function hasReference($name)
+    {
+        return isset($this->_references[$name]);
+    }
+
+    /**
+     * reference
+     *
+     * @param string $name
+     */
+    public function reference($name)
+    {
+        if (isset($this->_references[$name])) {
+            return $this->_references[$name];
+        }
+    }
+
+    /**
+     * obtainReference
+     *
+     * @param string $name
+     * @throws Doctrine_Record_Exception        if trying to get an unknown related component
+     */
+    public function obtainReference($name)
+    {
+        if (isset($this->_references[$name])) {
+            return $this->_references[$name];
+        }
+        throw new Doctrine_Record_Exception("Unknown reference $name");
+    }
+
+    /**
+     * getReferences
+     * @return array    all references
+     */
+    public function getReferences()
+    {
+        return $this->_references;
+    }
+
+    /**
+     * setRelated
+     *
+     * @param string $alias
+     * @param Doctrine_Access $coll
+     */
+    final public function setRelated($alias, Doctrine_Access $coll)
+    {
+        $this->_references[$alias] = $coll;
+    }
+
+    /**
+     * loadReference
+     * loads a related component
+     *
+     * @throws Doctrine_Table_Exception             if trying to load an unknown related component
+     * @param string $name
+     * @return void
+     */
+    public function loadReference($name)
+    {
+        $rel = $this->_table->getRelation($name);
+        $this->_references[$name] = $rel->fetchRelatedFor($this);
+    }
+
+    /**
+     * call
+     *
+     * @param string|array $callback    valid callback
+     * @param string $column            column name
+     * @param mixed arg1 ... argN       optional callback arguments
+     * @return Doctrine_Record
+     */
+    public function call($callback, $column)
+    {
+        $args = func_get_args();
+        array_shift($args);
+
+        if (isset($args[0])) {
+            $fieldName = $args[0];
+            $args[0] = $this->get($fieldName);
+
+            $newvalue = call_user_func_array($callback, $args);
+
+            $this->_data[$fieldName] = $newvalue;
+        }
+        return $this;
+    }
+
+    /**
+     * getter for node assciated with this record
+     *
+     * @return mixed if tree returns Doctrine_Node otherwise returns false
+     */
+    public function getNode()
+    {
+        if ( ! $this->_table->isTree()) {
+            return false;
+        }
+
+        if ( ! isset($this->_node)) {
+            $this->_node = Doctrine_Node::factory($this,
+                                              $this->getTable()->getOption('treeImpl'),
+                                              $this->getTable()->getOption('treeOptions')
+                                              );
+        }
+
+        return $this->_node;
+    }
+
+    public function unshiftFilter(Doctrine_Record_Filter $filter)
+    {
+        return $this->_table->unshiftFilter($filter);
+    }
+
+    /**
+     * unlink
+     * removes links from this record to given records
+     * if no ids are given, it removes all links
+     *
+     * @param string $alias     related component alias
+     * @param array $ids        the identifiers of the related records
+     * @return Doctrine_Record  this object
+     */
+    public function unlink($alias, $ids = array())
+    {
+        $ids = (array) $ids;
+
+        $q = new Doctrine_Query();
+
+        $rel = $this->getTable()->getRelation($alias);
+
+        if ($rel instanceof Doctrine_Relation_Association) {
+            $q->delete()
+              ->from($rel->getAssociationTable()->getComponentName())
+              ->where($rel->getLocal() . ' = ?', array_values($this->identifier()));
+
+            if (count($ids) > 0) {
+                $q->whereIn($rel->getForeign(), $ids);
+            }
+
+            $q->execute();
+
+        } else if ($rel instanceof Doctrine_Relation_ForeignKey) {
+            $q->update($rel->getTable()->getComponentName())
+              ->set($rel->getForeign(), '?', array(null))
+              ->addWhere($rel->getForeign() . ' = ?', array_values($this->identifier()));
+
+            if (count($ids) > 0) {
+                $q->whereIn($rel->getTable()->getIdentifier(), $ids);
+            }
+
+            $q->execute();
+        }
+        if (isset($this->_references[$alias])) {
+            foreach ($this->_references[$alias] as $k => $record) {
+                if (in_array(current($record->identifier()), $ids)) {
+                    $this->_references[$alias]->remove($k);
+                }
+            }
+            $this->_references[$alias]->takeSnapshot();
+        }
+        return $this;
+    }
+
+    /**
+     * link
+     * creates links from this record to given records
+     *
+     * @param string $alias     related component alias
+     * @param array $ids        the identifiers of the related records
+     * @return Doctrine_Record  this object
+     */
+    public function link($alias, $ids)
+    {
+        $ids = (array) $ids;
+
+        if ( ! count($ids)) {
+            return $this;
+        }
+
+        $identifier = array_values($this->identifier());
+        $identifier = array_shift($identifier);
+
+        $rel = $this->getTable()->getRelation($alias);
+
+        if ($rel instanceof Doctrine_Relation_Association) {
+
+            $modelClassName = $rel->getAssociationTable()->getComponentName();
+            $localFieldName = $rel->getLocalFieldName();
+            $localFieldDef  = $rel->getAssociationTable()->getColumnDefinition($localFieldName);
+            if ($localFieldDef['type'] == 'integer') {
+                $identifier = (integer) $identifier;
+            }
+            $foreignFieldName = $rel->getForeignFieldName();
+            $foreignFieldDef  = $rel->getAssociationTable()->getColumnDefinition($foreignFieldName);
+            if ($foreignFieldDef['type'] == 'integer') {
+                foreach ($ids as $i => $id) {
+                    $ids[$i] = (integer) $id;
+                }
+            }
+            foreach ($ids as $id) {
+                $record = new $modelClassName;
+                $record[$localFieldName] = $identifier;
+                $record[$foreignFieldName] = $id;
+                $record->save();
+            }
+
+        } else if ($rel instanceof Doctrine_Relation_ForeignKey) {
+
+            $q = new Doctrine_Query();
+
+            $q->update($rel->getTable()->getComponentName())
+              ->set($rel->getForeign(), '?', array_values($this->identifier()));
+
+            if (count($ids) > 0) {
+                $q->whereIn($rel->getTable()->getIdentifier(), $ids);
+            }
+
+            $q->execute();
+
+        } else if ($rel instanceof Doctrine_Relation_LocalKey) {
+
+            $q = new Doctrine_Query();
+
+            $q->update($this->getTable()->getComponentName())
+              ->set($rel->getLocalFieldName(), '?', $ids);
+
+            if (count($ids) > 0) {
+                $q->whereIn($rel->getTable()->getIdentifier(), array_values($this->identifier()));
+            }
+
+            $q->execute();
+
+        }
+
+        return $this;
+    }
+
+
+    /**
+     * __call
+     * this method is a magic method that is being used for method overloading
+     *
+     * the function of this method is to try to find given method from the templates
+     * this record is using and if it finds given method it will execute it
+     *
+     * So, in sense, this method replicates the usage of mixins (as seen in some programming languages)
+     *
+     * @param string $method        name of the method
+     * @param array $args           method arguments
+     * @return mixed                the return value of the given method
+     */
+    public function __call($method, $args)
+    {
+        if (($template = $this->_table->getMethodOwner($method)) !== false) {
+            $template->setInvoker($this);
+            return call_user_func_array(array($template, $method), $args);
+        }
+
+        foreach ($this->_table->getTemplates() as $template) {
+            if (is_callable(array($template, $method))) {
+                $template->setInvoker($this);
+                $this->_table->setMethodOwner($method, $template);
+
+                return call_user_func_array(array($template, $method), $args);
+            }
+        }
+
+        throw new Doctrine_Record_Exception(sprintf('Unknown method %s::%s', get_class($this), $method));
+    }
+
+    /**
+     * used to delete node from tree - MUST BE USE TO DELETE RECORD IF TABLE ACTS AS TREE
+     *
+     */
+    public function deleteNode()
+    {
+        $this->getNode()->delete();
+    }
+    
+    /**
+     * Helps freeing the memory occupied by the entity.
+     * Cuts all references the entity has to other entities and removes the entity
+     * from the instance pool.
+     * Note: The entity is no longer useable after free() has been called. Any operations
+     * done with the entity afterwards can lead to unpredictable results.
+     */
+    public function free($deep = false)
+    {
+        if ($this->_state != self::STATE_LOCKED && $this->_state != self::STATE_TLOCKED) {
+            $this->_state = $this->exists() ? self::STATE_LOCKED : self::STATE_TLOCKED;
+
+            $this->_table->getRepository()->evict($this->_oid);
+            $this->_table->removeRecord($this);
+            $this->_data = array();
+            $this->_id = array();
+
+            if ($deep) {
+                foreach ($this->_references as $name => $reference) {
+                    if ( ! ($reference instanceof Doctrine_Null)) {
+                        $reference->free($deep);
+                    }
+                }
+            }
+
+            $this->_references = array();
+        }
+    }
+
+    /**
+     * __toString alias
+     *
+     * @return string $dump
+     */
+    public function toString()
+    {
+        return Doctrine::dump(get_object_vars($this));
+    }
+
+    /**
+     * returns a string representation of this object
+     */
+    public function __toString()
+    {
+        return (string) $this->_oid;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Abstract.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,325 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Record_Abstract
+ *
+ * @package     Doctrine
+ * @subpackage  Record
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ */
+abstract class Doctrine_Record_Abstract extends Doctrine_Access
+{
+    /**
+     * @param Doctrine_Table $_table     reference to associated Doctrine_Table instance
+     */
+    protected $_table;
+
+    public function setTableDefinition()
+    {
+
+    }
+    public function setUp()
+    {
+    	
+    }	
+
+
+    /**
+     * getTable
+     * returns the associated table object
+     *
+     * @return Doctrine_Table               the associated table object
+     */
+    public function getTable()
+    {
+        return $this->_table;
+    }
+
+    /**
+     * addListener
+     *
+     * @param Doctrine_EventListener_Interface|Doctrine_Overloadable $listener
+     * @return Doctrine_Record
+     */
+    public function addListener($listener, $name = null)
+    {
+        $this->_table->addRecordListener($listener, $name = null);
+
+        return $this;
+    }
+
+    /**
+     * getListener
+     *
+     * @return Doctrine_EventListener_Interface|Doctrine_Overloadable
+     */
+    public function getListener()
+    {
+        return $this->_table->getRecordListener();
+    }
+
+    /**
+     * setListener
+     *
+     * @param Doctrine_EventListener_Interface|Doctrine_Overloadable $listener
+     * @return Doctrine_Record
+     */
+    public function setListener($listener)
+    {
+        $this->_table->setRecordListener($listener);
+
+        return $this;
+    }
+
+    /**
+     * index
+     * defines or retrieves an index
+     * if the second parameter is set this method defines an index
+     * if not this method retrieves index named $name
+     *
+     * @param string $name              the name of the index
+     * @param array $definition         the definition array
+     * @return mixed
+     */
+    public function index($name, array $definition = array())
+    {
+        if ( ! $definition) {
+            return $this->_table->getIndex($name);
+        } else {
+            return $this->_table->addIndex($name, $definition);
+        }
+    }
+    public function setAttribute($attr, $value)
+    {
+        $this->_table->setAttribute($attr, $value);
+    }
+    public function setTableName($tableName)
+    {
+        $this->_table->setTableName($tableName);
+    }
+    public function setInheritanceMap($map)
+    {
+        $this->_table->setOption('inheritanceMap', $map);
+    }
+
+    public function setSubclasses($map)
+    {
+        if (isset($map[get_class($this)])) {
+            // fix for #1621 
+            $mapFieldNames = $map[get_class($this)]; 
+            $mapColumnNames = array(); 
+
+            foreach ($mapFieldNames as $fieldName => $val) { 
+                $mapColumnNames[$this->getTable()->getColumnName($fieldName)] = $val; 
+            }
+ 
+            $this->_table->setOption('inheritanceMap', $mapColumnNames);
+            return;
+        }
+        $this->_table->setOption('subclasses', array_keys($map));
+    }
+
+    /**
+     * attribute
+     * sets or retrieves an option
+     *
+     * @see Doctrine::ATTR_* constants   availible attributes
+     * @param mixed $attr
+     * @param mixed $value
+     * @return mixed
+     */
+    public function attribute($attr, $value)
+    {
+        if ($value == null) {
+            if (is_array($attr)) {
+                foreach ($attr as $k => $v) {
+                    $this->_table->setAttribute($k, $v);
+                }
+            } else {
+                return $this->_table->getAttribute($attr);
+            }
+        } else {
+            $this->_table->setAttribute($attr, $value);
+        }    
+    }
+
+    /**
+     * option
+     * sets or retrieves an option
+     *
+     * @see Doctrine_Table::$options    availible options
+     * @param mixed $name               the name of the option
+     * @param mixed $value              options value
+     * @return mixed
+     */
+    public function option($name, $value = null)
+    {
+        if ($value === null) {
+            if (is_array($name)) {
+                foreach ($name as $k => $v) {
+                    $this->_table->setOption($k, $v);
+                }
+            } else {
+                return $this->_table->getOption($name);
+            }
+        } else {
+            $this->_table->setOption($name, $value);
+        }
+    }
+
+    /**
+     * hasOne
+     * binds One-to-One aggregate relation
+     *
+     * @param string $componentName     the name of the related component
+     * @param string $options           relation options
+     * @see Doctrine_Relation::_$definition
+     * @return Doctrine_Record          this object
+     */
+    public function hasOne()
+    {
+        $this->_table->bind(func_get_args(), Doctrine_Relation::ONE);
+
+        return $this;
+    }
+
+    /**
+     * hasMany
+     * binds One-to-Many / Many-to-Many aggregate relation
+     *
+     * @param string $componentName     the name of the related component
+     * @param string $options           relation options
+     * @see Doctrine_Relation::_$definition
+     * @return Doctrine_Record          this object
+     */
+    public function hasMany()
+    {
+        $this->_table->bind(func_get_args(), Doctrine_Relation::MANY);
+
+        return $this;
+    }
+
+    /**
+     * hasColumn
+     * sets a column definition
+     *
+     * @param string $name
+     * @param string $type
+     * @param integer $length
+     * @param mixed $options
+     * @return void
+     */
+    public function hasColumn($name, $type, $length = 2147483647, $options = "")
+    {
+        $this->_table->setColumn($name, $type, $length, $options);
+    }
+    public function hasColumns(array $definitions)
+    {
+        foreach ($definitions as $name => $options) {
+            $length = isset($options['length']) ? $options['length']:null;
+            $this->hasColumn($name, $options['type'], $length, $options);
+        }
+    }
+
+    /**
+     * bindQueryParts
+     * binds query parts to given component
+     *
+     * @param array $queryParts         an array of pre-bound query parts
+     * @return Doctrine_Record          this object
+     */
+    public function bindQueryParts(array $queryParts)
+    {
+    	$this->_table->bindQueryParts($queryParts);
+
+        return $this;
+    }
+
+    public function loadGenerator(Doctrine_Record_Generator $generator)
+    {
+    	$generator->initialize($this->_table);
+
+        $this->_table->addGenerator($generator, get_class($generator));
+    }
+
+
+    /**
+     * actAs
+     * loads the given plugin
+     *
+     * @param mixed $tpl
+     * @param array $options
+     */
+    public function actAs($tpl, array $options = array())
+    {
+        if ( ! is_object($tpl)) {
+            $className = 'Doctrine_Template_' . $tpl;
+
+            if (class_exists($className, true)) {
+                $tpl = new $className($options);
+            } else if (class_exists($tpl, true)) {
+                $tpl = new $tpl($options);
+            } else {
+                throw new Doctrine_Record_Exception('Could not load behavior named: "' . $tpl . '"');
+            }
+        }
+
+        if ( ! ($tpl instanceof Doctrine_Template)) {
+            throw new Doctrine_Record_Exception('Loaded behavior class is not an instance of Doctrine_Template.');
+        }
+
+        $className = get_class($tpl);
+
+        $this->_table->addTemplate($className, $tpl);
+
+        $tpl->setInvoker($this);
+        $tpl->setTable($this->_table);
+        $tpl->setUp();
+        $tpl->setTableDefinition();
+
+        return $this;
+    }
+
+    /**
+     * check
+     * adds a check constraint
+     *
+     * @param mixed $constraint     either a SQL constraint portion or an array of CHECK constraints
+     * @param string $name          optional constraint name
+     * @return Doctrine_Record      this object
+     */
+    public function check($constraint, $name = null)
+    {
+        if (is_array($constraint)) {
+            foreach ($constraint as $name => $def) {
+                $this->_table->addCheckConstraint($def, $name);
+            }
+        } else {
+            $this->_table->addCheckConstraint($constraint, $name);
+        }
+        return $this;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Record
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Record_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Filter.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,62 @@
+<?php
+/*
+ *  $Id: Record.php 1298 2007-05-01 19:26:03Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Record_Filter
+ * Filters the record getters and setters
+ *
+ * @package     Doctrine
+ * @subpackage  Record
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1298 $
+ */
+abstract class Doctrine_Record_Filter
+{
+    protected $_table;
+
+    public function setTable(Doctrine_Table $table)
+    {
+        $this->_table = $table;
+    }
+    public function getTable()
+    {
+        return $this->_table;
+    }
+
+    /**
+     * filterSet
+     * defines an implementation for filtering the set() method of Doctrine_Record
+     *
+     * @param mixed $name                       name of the property or related component
+     */
+    abstract public function filterSet(Doctrine_Record $record, $name, $value);
+
+    /**
+     * filterGet
+     * defines an implementation for filtering the get() method of Doctrine_Record
+     *
+     * @param mixed $name                       name of the property or related component
+     */
+    abstract public function filterGet(Doctrine_Record $record, $name);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Filter/Compound.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,96 @@
+<?php
+/*
+ *  $Id: Record.php 1298 2007-05-01 19:26:03Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Record_Filter_Compound
+ *
+ * @package     Doctrine
+ * @subpackage  Record
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1298 $
+ */
+class Doctrine_Record_Filter_Compound extends Doctrine_Record_Filter
+{
+    protected $_aliases = array();
+
+    public function __construct(array $aliases)
+    {
+        $this->_aliases = $aliases;
+    }
+    public function init()
+    {
+    	// check that all aliases exist
+    	foreach ($this->_aliases as $alias) {
+            $this->_table->getRelation($alias);
+    	}
+    }
+
+    /**
+     * filterSet
+     * defines an implementation for filtering the set() method of Doctrine_Record
+     *
+     * @param mixed $name                       name of the property or related component
+     */
+    public function filterSet(Doctrine_Record $record, $name, $value)
+    {
+        foreach ($this->_aliases as $alias) {
+            if ( ! $record->exists()) {
+                if (isset($record[$alias][$name])) {
+                    $record[$alias][$name] = $value;
+                    
+                    return $record;
+                }
+            } else {
+                if (isset($record[$alias][$name])) {
+                    $record[$alias][$name] = $value;
+                }
+
+                return $record;
+            }
+        }
+        throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $name, get_class($record)));
+    }
+
+    /**
+     * filterGet
+     * defines an implementation for filtering the get() method of Doctrine_Record
+     *
+     * @param mixed $name                       name of the property or related component
+     */
+    public function filterGet(Doctrine_Record $record, $name)
+    {
+        foreach ($this->_aliases as $alias) {
+            if ( ! $record->exists()) {
+                if (isset($record[$alias][$name])) {
+                    return $record[$alias][$name];
+                }
+            } else {
+                if (isset($record[$alias][$name])) {
+                    return $record[$alias][$name];
+                }
+            }
+        }
+        throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $name, get_class($record)));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Filter/Standard.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,57 @@
+<?php
+/*
+ *  $Id: Record.php 1298 2007-05-01 19:26:03Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Record_Filter_Standard
+ * Filters the record getters and setters
+ *
+ * @package     Doctrine
+ * @subpackage  Record
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1298 $
+ */
+class Doctrine_Record_Filter_Standard extends Doctrine_Record_Filter
+{
+    /**
+     * filterSet
+     * defines an implementation for filtering the set() method of Doctrine_Record
+     *
+     * @param mixed $name                       name of the property or related component
+     */
+    public function filterSet(Doctrine_Record $record, $name, $value)
+    {
+        throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $name, get_class($record)));
+    }
+
+    /**
+     * filterGet
+     * defines an implementation for filtering the get() method of Doctrine_Record
+     *
+     * @param mixed $name                       name of the property or related component
+     */
+    public function filterGet(Doctrine_Record $record, $name)
+    {
+        throw new Doctrine_Record_UnknownPropertyException(sprintf('Unknown record property / related component "%s" on "%s"', $name, get_class($record)));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Generator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,374 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Record_Generator
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @package     Doctrine
+ * @subpackage  Plugin
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+abstract class Doctrine_Record_Generator extends Doctrine_Record_Abstract
+{
+    /**
+     * _options
+     *
+     * @var array $_options     an array of plugin specific options
+     */
+    protected $_options = array('generateFiles'  => false,
+                                'generatePath'   => false,
+                                'builderOptions' => array(),
+                                'identifier'     => false,
+                                'table'          => false,
+                                'pluginTable'    => false,
+                                'children'       => array());
+
+    /**
+     * _initialized
+     *
+     * @var bool $_initialized
+     */
+    protected $_initialized = false;
+
+    /**
+     * __get
+     * an alias for getOption
+     *
+     * @param string $option
+     */
+    public function __get($option)
+    {
+        if (isset($this->_options[$option])) {
+            return $this->_options[$option];
+        }
+        return null;
+    }
+
+    /**
+     * __isset
+     *
+     * @param string $option
+     */
+    public function __isset($option) 
+    {
+        return isset($this->_options[$option]);
+    }
+
+    /**
+     * returns the value of an option
+     *
+     * @param $option       the name of the option to retrieve
+     * @return mixed        the value of the option
+     */
+    public function getOption($name)
+    {
+        if ( ! isset($this->_options[$name])) {
+            throw new Doctrine_Exception('Unknown option ' . $name);
+        }
+        
+        return $this->_options[$name];
+    }
+
+    /**
+     * sets given value to an option
+     *
+     * @param $option       the name of the option to be changed
+     * @param $value        the value of the option
+     * @return Doctrine_Plugin  this object
+     */
+    public function setOption($name, $value)
+    {
+        $this->_options[$name] = $value;
+        
+        return $this;
+    }
+
+    /**
+     * addChild
+     *
+     * Add child record generator 
+     *
+     * @param  Doctrine_Record_Generator $generator 
+     * @return void
+     */
+    public function addChild($generator)
+    {
+        $this->_options['children'][] = $generator;
+    }
+
+    /**
+     * getOptions
+     *
+     * returns all options and their associated values
+     *
+     * @return array    all options as an associative array
+     */
+    public function getOptions()
+    {
+        return $this->_options;
+    }
+
+    /**
+     * initialize
+     *
+     * Initialize the plugin. Call in Doctrine_Template setTableDefinition() in order to initiate a generator in a template
+     * SEE: Doctrine_Template_I18n for an example
+     *
+     * @param  Doctrine_Table $table 
+     * @return void
+     */
+    public function initialize(Doctrine_Table $table)
+    {
+      	if ($this->_initialized) {
+      	    return false;
+      	}
+        
+        $this->_initialized = true;
+
+        $this->initOptions();
+
+        $table->addGenerator($this, get_class($this));
+
+        $this->_options['table'] = $table;
+
+        $this->_options['className'] = str_replace('%CLASS%',
+                                                   $this->_options['table']->getComponentName(),
+                                                   $this->_options['className']);
+
+        // check that class doesn't exist (otherwise we cannot create it)
+        if ($this->_options['generateFiles'] === false && class_exists($this->_options['className'], false)) {
+            return false;
+        }
+
+        $this->buildTable();
+
+        $fk = $this->buildForeignKeys($this->_options['table']);
+
+        $this->_table->setColumns($fk);
+
+        $this->buildRelation();
+
+        $this->setTableDefinition();
+        $this->setUp();
+
+        $definition = array();
+        $definition['columns'] = $this->_table->getColumns();
+        $definition['tableName'] = $this->_table->getTableName();
+        $definition['actAs'] = $this->_table->getTemplates();
+
+        $this->generateClass($definition);
+
+        $this->buildChildDefinitions();
+
+        $this->_table->initIdentifier();
+    }
+
+    public function buildTable()
+    {
+        // Bind model 
+        $conn = $this->_options['table']->getConnection();
+        $conn->getManager()->bindComponent($this->_options['className'], $conn->getName());
+
+        // Create table
+        $this->_table = new Doctrine_Table($this->_options['className'], $conn);
+
+        // If custom table name set then lets use it
+        if (isset($this->_options['tableName']) && $this->_options['tableName']) {
+            $this->_table->setTableName($this->_options['tableName']);
+        }
+
+        // Maintain some options from the parent table
+        $options = $this->_options['table']->getOptions();
+
+        $newOptions = array();
+        $maintain = array('type', 'collate', 'charset'); // This list may need updating
+        foreach ($maintain as $key) {
+            if (isset($options[$key])) {
+                $newOptions[$key] = $options[$key];
+            }
+        }
+
+        $this->_table->setOptions($newOptions);
+
+        $conn->addTable($this->_table);
+    }
+
+    /** 
+     * empty template method for providing the concrete plugins the ability
+     * to initialize options before the actual definition is being built
+     *
+     * @return void
+     */
+    public function initOptions()
+    {
+        
+    }
+
+    /**
+     * buildChildDefinitions
+     *
+     * @return void
+     */
+    public function buildChildDefinitions()
+    {
+        if ( ! isset($this->_options['children'])) {
+            throw new Doctrine_Record_Exception("Unknown option 'children'.");
+        }
+
+        foreach ($this->_options['children'] as $child) {
+            if ($child instanceof Doctrine_Template) {
+                if ($child->getPlugin() !== null) {
+                    $this->_table->addGenerator($child->getPlugin(), get_class($child->getPlugin()));
+                }
+
+                $this->_table->addTemplate(get_class($child), $child);
+
+                $child->setInvoker($this);
+                $child->setTable($this->_table);
+                $child->setTableDefinition();
+                $child->setUp();
+            } else {
+                $this->_table->addGenerator($child, get_class($child));
+                $child->initialize($this->_table);
+            }
+        }
+    }
+
+    /**
+     * buildForeignKeys
+     *
+     * generates foreign keys for the plugin table based on the owner table
+     *
+     * the foreign keys generated by this method can be used for 
+     * setting the relations between the owner and the plugin classes
+     *
+     * @param Doctrine_Table $table     the table object that owns the plugin
+     * @return array                    an array of foreign key definitions
+     */
+    public function buildForeignKeys(Doctrine_Table $table)
+    {
+        $fk = array();
+
+        foreach ((array) $table->getIdentifier() as $column) {
+            $def = $table->getDefinitionOf($column);
+
+            unset($def['autoincrement']);
+            unset($def['sequence']);
+            unset($def['primary']);
+
+            $col = $column;
+
+            $def['primary'] = true;
+            $fk[$col] = $def;
+        }
+        return $fk;
+    }
+
+    /**
+     * buildLocalRelation
+     *
+     * @return void
+     */
+    public function buildLocalRelation()
+    {
+        $options = array('local'    => $this->_options['table']->getIdentifier(),
+                         'foreign'  => $this->_options['table']->getIdentifier(),
+                         'type'     => Doctrine_Relation::MANY);
+
+        $options['type'] = Doctrine_Relation::ONE;
+        $options['onDelete'] = 'CASCADE';
+        $options['onUpdate'] = 'CASCADE';
+
+        $this->_table->getRelationParser()->bind($this->_options['table']->getComponentName(), $options);
+    }
+
+    /**
+     * buildForeignRelation
+     *
+     * @param string $alias Alias of the foreign relation
+     * @return void
+     */
+    public function buildForeignRelation($alias = null)
+    {
+        $options = array('local'    => $this->_options['table']->getIdentifier(),
+                         'foreign'  => $this->_options['table']->getIdentifier(),
+                         'type'     => Doctrine_Relation::MANY);
+
+        $aliasStr = '';
+
+        if ($alias !== null) {
+            $aliasStr = ' as ' . $alias;
+        }
+
+        $this->_options['table']->getRelationParser()->bind($this->_table->getComponentName() . $aliasStr,
+                                                            $options);
+    }
+
+    /**
+     * buildRelation
+     *
+     * this method can be used for generating the relation from the plugin 
+     * table to the owner table. By default buildForeignRelation() and buildLocalRelation() are called
+     * Those methods can be overridden or this entire method can be overridden
+     *
+     * @return void
+     */
+    public function buildRelation()
+    {
+    	$this->buildForeignRelation();
+        $this->buildLocalRelation();
+    }
+
+    /**
+     * generateClass
+     *
+     * generates the class definition for plugin class
+     *
+     * @param array $definition  Definition array defining columns, relations and options
+     *                           for the model
+     * @return void
+     */
+    public function generateClass(array $definition = array())
+    {
+        $definition['className'] = $this->_options['className'];
+
+        $builder = new Doctrine_Import_Builder();
+
+        if ($this->_options['generateFiles']) {
+            if (isset($this->_options['generatePath']) && $this->_options['generatePath']) {
+                $builder->setTargetPath($this->_options['generatePath']);
+                $builderOptions = isset($this->_options['builderOptions']) ? (array) $this->_options['builderOptions']:array();
+                $builder->setOptions($builderOptions);
+                $builder->buildRecord($definition);
+            } else {
+                throw new Doctrine_Record_Exception('If you wish to generate files then you must specify the path to generate the files in.');
+            }
+        } else {
+            $def = $builder->buildDefinition($definition);
+
+            eval($def);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Iterator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,81 @@
+<?php
+/*
+ *  $Id: Iterator.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Record_Iterator
+ *
+ * @package     Doctrine
+ * @subpackage  Record
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Record_Iterator extends ArrayIterator
+{
+    /**
+     * @var Doctrine_Record $record
+     */
+    private $record;
+
+    /**
+     * @var Doctrine_Null $null
+     */
+    private static $null;
+
+    /**
+     * constructor
+     *
+     * @param Doctrine_Record $record
+     */
+    public function __construct(Doctrine_Record $record)
+    {
+        $this->record = $record;
+        parent::__construct($record->getData());
+    }
+
+    /**
+     * initNullObject
+     *
+     * @param Doctrine_Null $null
+     */
+    public static function initNullObject(Doctrine_Null $null)
+    {
+        self::$null = $null;
+    }
+
+    /**
+     * current
+     *
+     * @return mixed
+     */
+    public function current()
+    {
+        $value = parent::current();
+
+        if ($value === self::$null) {
+            return null;
+        } else {
+            return $value;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Listener.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,91 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Record_Listener
+ *
+ * @package     Doctrine
+ * @subpackage  Record
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ */
+class Doctrine_Record_Listener implements Doctrine_Record_Listener_Interface
+{
+    public function preSerialize(Doctrine_Event $event)
+    { }
+
+    public function postSerialize(Doctrine_Event $event)
+    { }
+
+    public function preUnserialize(Doctrine_Event $event)
+    { }
+
+    public function postUnserialize(Doctrine_Event $event)
+    { }
+
+    public function preDqlSelect(Doctrine_Event $event)
+    { }
+
+    public function preSave(Doctrine_Event $event)
+    { }
+
+    public function postSave(Doctrine_Event $event)
+    { }
+
+    public function preDqlDelete(Doctrine_Event $event)
+    { }
+
+    public function preDelete(Doctrine_Event $event)
+    { }
+
+    public function postDelete(Doctrine_Event $event)
+    { }
+
+    public function preDqlUpdate(Doctrine_Event $event)
+    { }
+
+    public function preUpdate(Doctrine_Event $event)
+    { }
+
+    public function postUpdate(Doctrine_Event $event)
+    { }
+
+    public function preInsert(Doctrine_Event $event)
+    { }
+
+    public function postInsert(Doctrine_Event $event)
+    { }
+
+    public function preHydrate(Doctrine_Event $event)
+    { }
+
+    public function postHydrate(Doctrine_Event $event)
+    { }
+
+    public function preValidate(Doctrine_Event $event)
+    { }
+    
+    public function postValidate(Doctrine_Event $event)
+    { }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Listener/Chain.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,223 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Record_Listener_Chain
+ * this class represents a chain of different listeners,
+ * useful for having multiple listeners listening the events at the same time
+ *
+ * @package     Doctrine
+ * @subpackage  Record
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ */
+class Doctrine_Record_Listener_Chain extends Doctrine_Access implements Doctrine_Record_Listener_Interface
+{
+    /**
+     * @var array $listeners        an array containing all listeners
+     */
+    protected $_listeners = array();
+
+    /**
+     * add
+     * adds a listener to the chain of listeners
+     *
+     * @param object $listener
+     * @param string $name
+     * @return void
+     */
+    public function add($listener, $name = null)
+    {
+        if ( ! ($listener instanceof Doctrine_Record_Listener_Interface) &&
+             ! ($listener instanceof Doctrine_Overloadable)) {
+
+            throw new Doctrine_EventListener_Exception("Couldn't add eventlistener. Record listeners should implement either Doctrine_Record_Listener_Interface or Doctrine_Overloadable");
+        }
+        if ($name === null) {
+            $this->_listeners[] = $listener;
+        } else {
+            $this->_listeners[$name] = $listener;
+        }
+    }
+
+    /**
+     * returns a Doctrine_Record_Listener on success
+     * and null on failure
+     *
+     * @param mixed $key
+     * @return mixed
+     */
+    public function get($key)
+    {
+        if ( ! isset($this->_listeners[$key])) {
+            return null;
+        }
+        return $this->_listeners[$key];
+    }
+
+    /**
+     * set
+     *
+     * @param mixed $key
+     * @param Doctrine_Record_Listener $listener    listener to be added
+     * @return Doctrine_Record_Listener_Chain       this object
+     */
+    public function set($key, $listener)
+    {
+        $this->_listeners[$key] = $listener;
+    }
+
+    public function preSerialize(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preSerialize($event);
+        }
+    }
+
+    public function postSerialize(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postSerialize($event);
+        }
+    }
+
+    public function preUnserialize(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preUnserialize($event);
+        }
+    }
+
+    public function postUnserialize(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postUnserialize($event);
+        }
+    }
+
+    public function preDqlSelect(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preDqlSelect($event);
+        }
+    }
+
+    public function preSave(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preSave($event);
+        }
+    }
+
+    public function postSave(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postSave($event);
+        }
+    }
+
+    public function preDqlDelete(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preDqlDelete($event);
+        }
+    }
+
+    public function preDelete(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preDelete($event);
+        }
+    }
+
+    public function postDelete(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postDelete($event);
+        }
+    }
+
+    public function preDqlUpdate(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preDqlUpdate($event);
+        }
+    }
+
+    public function preUpdate(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preUpdate($event);
+        }
+    }
+
+    public function postUpdate(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postUpdate($event);
+        }
+    }
+
+    public function preInsert(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preInsert($event);
+        }
+    }
+
+    public function postInsert(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postInsert($event);
+        }
+    }
+
+    public function preHydrate(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->preHydrate($event);
+        }
+    }
+
+    public function postHydrate(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postHydrate($event);
+        }
+    }
+    
+    public function preValidate(Doctrine_Event $event)
+    { 
+        foreach ($this->_listeners as $listener) {
+            $listener->preValidate($event);
+        }
+    }
+    
+    public function postValidate(Doctrine_Event $event)
+    {
+        foreach ($this->_listeners as $listener) {
+            $listener->postValidate($event);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/Listener/Interface.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,62 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Record_Listener
+ *
+ * @package     Doctrine
+ * @subpackage  Record
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ */
+interface Doctrine_Record_Listener_Interface
+{
+    public function preSerialize(Doctrine_Event $event);
+
+    public function postSerialize(Doctrine_Event $event);
+
+    public function preUnserialize(Doctrine_Event $event);
+
+    public function postUnserialize(Doctrine_Event $event);
+
+    public function preSave(Doctrine_Event $event);
+
+    public function postSave(Doctrine_Event $event);
+
+    public function preDelete(Doctrine_Event $event);
+
+    public function postDelete(Doctrine_Event $event);
+
+    public function preUpdate(Doctrine_Event $event);
+
+    public function postUpdate(Doctrine_Event $event);
+
+    public function preInsert(Doctrine_Event $event);
+
+    public function postInsert(Doctrine_Event $event);
+    
+    public function preHydrate(Doctrine_Event $event);
+    
+    public function postHydrate(Doctrine_Event $event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/State/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Record
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Record_State_Exception extends Doctrine_Record_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Record/UnknownPropertyException.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 4252 2008-04-19 07:37:53Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Record_UnknownPropertyException
+ *
+ * @package     Doctrine
+ * @subpackage  Record
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 4252 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Record_UnknownPropertyException extends Doctrine_Record_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,373 @@
+<?php
+/*
+ *  $Id: Relation.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Relation
+ * This class represents a relation between components
+ *
+ * @package     Doctrine
+ * @subpackage  Relation
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+abstract class Doctrine_Relation implements ArrayAccess
+{
+    /**
+     * RELATION CONSTANTS
+     */
+
+    /**
+     * constant for ONE_TO_ONE and MANY_TO_ONE relationships
+     */
+    const ONE   = 0;
+    
+    /**
+     * constant for MANY_TO_MANY and ONE_TO_MANY relationships
+     */
+    const MANY  = 1;
+    
+    // TRUE => mandatory, everything else is just a default value. this should be refactored
+    // since TRUE can bot be used as a default value this way. All values should be default values.
+    protected $definition = array('alias'       => true,
+                                  'foreign'     => true,
+                                  'local'       => true,
+                                  'class'       => true,
+                                  'type'        => true,
+                                  'table'       => true,
+                                  'localTable'  => true,
+                                  'name'        => null,
+                                  'refTable'    => null,
+                                  'onDelete'    => null,
+                                  'onUpdate'    => null,
+                                  'deferred'    => null,
+                                  'deferrable'  => null,
+                                  'constraint'  => null,
+                                  'equal'       => false,
+                                  'cascade'     => array(), // application-level cascades
+                                  'owningSide'  => false, // whether this is the owning side
+                                  'refClassRelationAlias' => null,
+                                  );
+
+    /**
+     * constructor
+     *
+     * @param array $definition         an associative array with the following structure:
+     *          name                    foreign key constraint name
+     *
+     *          local                   the local field(s)
+     *
+     *          foreign                 the foreign reference field(s)
+     *
+     *          table                   the foreign table object
+     *
+     *          localTable              the local table object
+     *
+     *          refTable                the reference table object (if any)
+     *
+     *          onDelete                referential delete action
+     *  
+     *          onUpdate                referential update action
+     *
+     *          deferred                deferred constraint checking 
+     *
+     *          alias                   relation alias
+     *
+     *          type                    the relation type, either Doctrine_Relation::ONE or Doctrine_Relation::MANY
+     *
+     *          constraint              boolean value, true if the relation has an explicit referential integrity constraint
+     *
+     * 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
+     */
+    public function __construct(array $definition)
+    {
+        $def = array();
+        foreach ($this->definition as $key => $val) {
+            if ( ! isset($definition[$key]) && $val) {
+                throw new Doctrine_Exception($key . ' is required!');
+            }
+            if (isset($definition[$key])) {
+                $def[$key] = $definition[$key];
+            } else {
+                $def[$key] = $this->definition[$key];          
+            }
+        }
+        $this->definition = $def;
+    }
+
+    /**
+     * hasConstraint
+     * whether or not this relation has an explicit constraint
+     *
+     * @return boolean
+     */
+    public function hasConstraint()
+    {
+        return ($this->definition['constraint'] ||
+                ($this->definition['onUpdate']) ||
+                ($this->definition['onDelete']));
+    }
+    public function isDeferred()
+    {
+        return $this->definition['deferred'];
+    }
+
+    public function isDeferrable()
+    {
+        return $this->definition['deferrable'];
+    }
+    public function isEqual()
+    {
+        return $this->definition['equal'];
+    }
+
+    public function offsetExists($offset)
+    {
+        return isset($this->definition[$offset]);
+    }
+
+    public function offsetGet($offset)
+    {
+        if (isset($this->definition[$offset])) {
+            return $this->definition[$offset];
+        }
+        
+        return null;
+    }
+
+    public function offsetSet($offset, $value)
+    {
+        if (isset($this->definition[$offset])) {
+            $this->definition[$offset] = $value;
+        }
+    }
+
+    public function offsetUnset($offset)
+    {
+        $this->definition[$offset] = false;
+    }
+
+    /**
+     * toArray
+     *
+     * @return array
+     */
+    public function toArray() 
+    {
+        return $this->definition;
+    }
+
+    /**
+     * getAlias
+     * returns the relation alias
+     *
+     * @return string
+     */
+    final public function getAlias()
+    {
+        return $this->definition['alias'];
+    }
+
+    /**
+     * getType
+     * returns the relation type, either 0 or 1
+     *
+     * @see Doctrine_Relation MANY_* and ONE_* constants
+     * @return integer
+     */
+    final public function getType()
+    {
+        return $this->definition['type'];
+    }
+    
+    /**
+     * Checks whether this relation cascades deletions to the related objects
+     * on the application level.
+     *
+     * @return boolean
+     */
+    public function isCascadeDelete()
+    {
+        return in_array('delete', $this->definition['cascade']);
+    }
+
+    /**
+     * getTable
+     * returns the foreign table object
+     *
+     * @return object Doctrine_Table
+     */
+    final public function getTable()
+    {
+        return Doctrine_Manager::getInstance()
+               ->getConnectionForComponent($this->definition['class'])
+               ->getTable($this->definition['class']);
+    }
+
+    /**
+     * getClass
+     * returns the name of the related class
+     *
+     * @return object Doctrine_Record
+     */
+    final public function getClass()
+    {
+        return $this->definition['class'];
+    }
+
+    /**
+     * getLocal
+     * returns the name of the local column
+     *
+     * @return string
+     */
+    final public function getLocal()
+    {
+        return $this->definition['local'];
+    }
+    
+    /**
+     * getLocalFieldName
+     * returns the field name of the local column
+     */
+    final public function getLocalFieldName()
+    {
+        return $this->definition['localTable']->getFieldName($this->definition['local']);
+    }
+
+    /**
+     * getLocalColumnName
+     * returns the column name of the local column
+     *
+     * @return string $columnName
+     */
+    final public function getLocalColumnName()
+    {
+        return $this->definition['localTable']->getColumnName($this->definition['local']);
+    }
+
+    /**
+     * getForeign
+     * returns the name of the foreignkey column where
+     * the localkey column is pointing at
+     *
+     * @return string
+     */
+    final public function getForeign()
+    {
+        return $this->definition['foreign'];
+    }
+    
+    /**
+     * getLocalFieldName
+     * returns the field name of the foreign column
+     */
+    final public function getForeignFieldName()
+    {
+        return $this->definition['table']->getFieldName($this->definition['foreign']);
+    }
+
+    /**
+     * getForeignColumnName
+     * returns the column name of the foreign column
+     *
+     * @return string $columnName
+     */
+    final public function getForeignColumnName()
+    {
+       return $this->definition['table']->getColumnName($this->definition['foreign']);
+    }
+
+    /**
+     * isOneToOne
+     * returns whether or not this relation is a one-to-one relation
+     *
+     * @return boolean
+     */
+    final public function isOneToOne()
+    {
+        return ($this->definition['type'] == Doctrine_Relation::ONE);
+    }
+
+    /**
+     * getRelationDql
+     *
+     * @param integer $count
+     * @return string
+     */
+    public function getRelationDql($count)
+    {
+        $component = $this->getTable()->getComponentName();
+
+        $dql  = 'FROM ' . $component
+              . ' WHERE ' . $component . '.' . $this->definition['foreign']
+              . ' IN (' . substr(str_repeat('?, ', $count), 0, -2) . ')';
+
+        return $dql;
+    }
+
+    /**
+     * fetchRelatedFor
+     *
+     * fetches a component related to given record
+     *
+     * @param Doctrine_Record $record
+     * @return Doctrine_Record|Doctrine_Collection
+     */
+    abstract public function fetchRelatedFor(Doctrine_Record $record);
+
+    /**
+     * __toString
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        $r[] = "<pre>";
+        foreach ($this->definition as $k => $v) {
+            if (is_object($v)) {
+                $v = 'Object(' . get_class($v) . ')';
+            }
+            $r[] = $k . ' : ' . $v;
+        }
+        $r[] = "</pre>";
+        return implode("\n", $r);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/Association.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,134 @@
+<?php
+/*
+ *  $Id: Association.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Relation_Association    this class takes care of association mapping
+ *                         (= many-to-many relationships, where the relationship is handled with an additional relational table
+ *                         which holds 2 foreign keys)
+ *
+ *
+ * @package     Doctrine
+ * @subpackage  Relation
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Relation_Association extends Doctrine_Relation
+{
+    /**
+     * @return Doctrine_Table
+     */
+    public function getAssociationFactory()
+    {
+        return $this->definition['refTable'];
+    }
+    public function getAssociationTable()
+    {
+        return $this->definition['refTable'];
+    }
+
+    /**
+     * getRelationDql
+     *
+     * @param integer $count
+     * @return string
+     */
+    public function getRelationDql($count, $context = 'record')
+    {
+        $table = $this->definition['refTable'];
+        $component = $this->definition['refTable']->getComponentName();
+        
+        switch ($context) {
+            case "record":
+                $sub  = substr(str_repeat("?, ", $count),0,-2);
+                $dql  = 'FROM ' . $this->getTable()->getComponentName();
+                $dql .= '.' . $component;
+                $dql .= ' WHERE ' . $this->getTable()->getComponentName()
+                . '.' . $component . '.' . $this->getLocalRefColumnName() . ' IN (' . $sub . ')';
+                break;
+            case "collection":
+                $sub  = substr(str_repeat("?, ", $count),0,-2);
+                $dql  = 'FROM ' . $component . '.' . $this->getTable()->getComponentName();
+                $dql .= ' WHERE ' . $component . '.' . $this->getLocalRefColumnName() . ' IN (' . $sub . ')';
+                break;
+        }
+
+        return $dql;
+    }
+
+    /**
+     * getLocalRefColumnName
+     * returns the column name of the local reference column
+     */
+    final public function getLocalRefColumnName()
+    {
+	    return $this->definition['refTable']->getColumnName($this->definition['local']);
+    }
+
+    /**
+     * getLocalRefFieldName
+     * returns the field name of the local reference column
+     */
+    final public function getLocalRefFieldName()
+    {
+	    return $this->definition['refTable']->getFieldName($this->definition['local']);
+    }
+
+    /**
+     * getForeignRefColumnName
+     * returns the column name of the foreign reference column
+     */
+    final public function getForeignRefColumnName()
+    {
+	    return $this->definition['refTable']->getColumnName($this->definition['foreign']);
+    }
+
+    /**
+     * getForeignRefFieldName
+     * returns the field name of the foreign reference column
+     */
+    final public function getForeignRefFieldName()
+    {
+	    return $this->definition['refTable']->getFieldName($this->definition['foreign']);
+    }
+
+    /**
+     * fetchRelatedFor
+     *
+     * fetches a component related to given record
+     *
+     * @param Doctrine_Record $record
+     * @return Doctrine_Record|Doctrine_Collection
+     */
+    public function fetchRelatedFor(Doctrine_Record $record)
+    {
+        $id = $record->getIncremented();
+        if (empty($id) || ! $this->definition['table']->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) {
+            $coll = new Doctrine_Collection($this->getTable());
+        } else {
+            $coll = $this->getTable()->getConnection()->query($this->getRelationDql(1), array($id));
+        }
+        $coll->setReference($record, $this);
+        return $coll;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/Association/Self.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,111 @@
+<?php
+/*
+ *  $Id: Self.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Relation_Association_Self
+ *
+ * @package     Doctrine
+ * @subpackage  Relation
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Relation_Association_Self extends Doctrine_Relation_Association
+{
+    /**
+     * getRelationDql
+     *
+     * @param integer $count
+     * @return string
+     */
+    public function getRelationDql($count, $context = 'record')
+    {
+        switch ($context) {
+            case 'record':
+                $identifierColumnNames = $this->definition['table']->getIdentifierColumnNames();
+                $identifier = array_pop($identifierColumnNames);
+                $sub    = 'SELECT '.$this->definition['foreign'] 
+                        . ' FROM '.$this->definition['refTable']->getTableName()
+                        . ' WHERE '.$this->definition['local']
+                        . ' = ?';
+
+                $sub2   = 'SELECT '.$this->definition['local']
+                        . ' FROM '.$this->definition['refTable']->getTableName()
+                        . ' WHERE '.$this->definition['foreign']
+                        . ' = ?';
+
+                $dql  = 'FROM ' . $this->definition['table']->getComponentName()
+                      . '.' . $this->definition['refTable']->getComponentName()
+                      . ' WHERE ' . $this->definition['table']->getComponentName()
+                      . '.' . $identifier 
+                      . ' IN (' . $sub . ')'
+                      . ' || ' . $this->definition['table']->getComponentName() 
+                      . '.' . $identifier
+                      . ' IN (' . $sub2 . ')';
+                break;
+            case 'collection':
+                $sub  = substr(str_repeat('?, ', $count),0,-2);
+                $dql  = 'FROM '.$this->definition['refTable']->getComponentName()
+                      . '.' . $this->definition['table']->getComponentName()
+                      . ' WHERE '.$this->definition['refTable']->getComponentName()
+                      . '.' . $this->definition['local'] . ' IN (' . $sub . ')';
+        };
+
+        return $dql;
+    }
+
+    public function fetchRelatedFor(Doctrine_Record $record)
+    {
+        $id      = $record->getIncremented();
+
+        $q = new Doctrine_RawSql();
+
+        $assocTable = $this->getAssociationFactory()->getTableName();
+        $tableName  = $record->getTable()->getTableName();
+        $identifierColumnNames = $record->getTable()->getIdentifierColumnNames();
+        $identifier = array_pop($identifierColumnNames);
+
+        $sub     = 'SELECT '.$this->getForeign().
+                   ' FROM '.$assocTable.
+                   ' WHERE '.$this->getLocal().
+                   ' = ?';
+
+        $sub2   = 'SELECT '.$this->getLocal().
+                  ' FROM '.$assocTable.
+                  ' WHERE '.$this->getForeign().
+                  ' = ?';
+
+        $q->select('{'.$tableName.'.*}, {'.$assocTable.'.*}')
+          ->from($tableName . ' INNER JOIN '.$assocTable.' ON '.
+                 $tableName . '.' . $identifier . ' = ' . $assocTable . '.' . $this->getLocal() . ' OR ' .
+                 $tableName . '.' . $identifier . ' = ' . $assocTable . '.' . $this->getForeign()
+                 )
+          ->where($tableName.'.'.$identifier.' IN ('.$sub.') OR '.
+                  $tableName.'.'.$identifier.' IN ('.$sub2.')'
+                );
+        $q->addComponent($tableName,  $record->getTable()->getComponentName());
+        $q->addComponent($assocTable, $record->getTable()->getComponentName(). '.' . $this->getAssociationFactory()->getComponentName());
+
+        return $q->execute(array($id, $id));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 1344 2007-05-12 23:27:16Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */        
+
+/**
+ * Doctrine_Relation_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Relation
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1344 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Relation_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/ForeignKey.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,100 @@
+<?php
+/*
+ *  $Id: ForeignKey.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Relation_ForeignKey
+ * This class represents a foreign key relation
+ *
+ * @package     Doctrine
+ * @subpackage  Relation
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Relation_ForeignKey extends Doctrine_Relation
+{
+    /**
+     * fetchRelatedFor
+     *
+     * fetches a component related to given record
+     *
+     * @param Doctrine_Record $record
+     * @return Doctrine_Record|Doctrine_Collection
+     */
+    public function fetchRelatedFor(Doctrine_Record $record)
+    {
+        $id = array();
+        $localTable = $record->getTable();
+        foreach ((array) $this->definition['local'] as $local) {
+           $value = $record->get($localTable->getFieldName($local));
+           if (isset($value)) {
+               $id[] = $value;
+           }
+        }
+        if ($this->isOneToOne()) {
+            if ( ! $record->exists() || empty($id) || 
+                 ! $this->definition['table']->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) {
+                
+                $related = $this->getTable()->create();
+            } else {
+                $dql  = 'FROM ' . $this->getTable()->getComponentName()
+                      . ' WHERE ' . $this->getCondition();
+
+                $coll = $this->getTable()->getConnection()->query($dql, $id);
+                $related = $coll[0];
+            }
+
+            $related->set($related->getTable()->getFieldName($this->definition['foreign']),
+                    $record, false);
+        } else {
+
+            if ( ! $record->exists() || empty($id) || 
+                 ! $this->definition['table']->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) {
+                
+                $related = new Doctrine_Collection($this->getTable());
+            } else {
+                $query      = $this->getRelationDql(1);
+                $related    = $this->getTable()->getConnection()->query($query, $id);
+            }
+            $related->setReference($record, $this);
+        }
+        return $related;
+    }
+
+    /**
+     * getCondition
+     *
+     * @param string $alias
+     */
+    public function getCondition($alias = null)
+    {
+        if ( ! $alias) {
+           $alias = $this->getTable()->getComponentName();
+        }
+        $conditions = array();
+        foreach ((array) $this->definition['foreign'] as $foreign) {
+            $conditions[] = $alias . '.' . $foreign . ' = ?';
+        }
+        return implode(' AND ', $conditions);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/LocalKey.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,82 @@
+<?php
+/*
+ *  $Id: LocalKey.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Relation_LocalKey
+ * This class represents a local key relation
+ *
+ * @package     Doctrine
+ * @subpackage  Relation
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Relation_LocalKey extends Doctrine_Relation
+{
+    /**
+     * fetchRelatedFor
+     *
+     * fetches a component related to given record
+     *
+     * @param Doctrine_Record $record
+     * @return Doctrine_Record|Doctrine_Collection
+     */
+    public function fetchRelatedFor(Doctrine_Record $record)
+    {
+        $localFieldName = $record->getTable()->getFieldName($this->definition['local']);
+        $id = $record->get($localFieldName);
+
+        if (is_null($id) || ! $this->definition['table']->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) {
+            $related = $this->getTable()->create();
+        } else {
+            $dql  = 'FROM ' . $this->getTable()->getComponentName()
+                 . ' WHERE ' . $this->getCondition();
+
+            $related = $this->getTable()
+                            ->getConnection()
+                            ->query($dql, array($id))
+                            ->getFirst();
+            
+            if ( ! $related || empty($related)) {
+                $related = $this->getTable()->create();
+            }
+        }
+
+        $record->set($localFieldName, $related, false);
+
+        return $related;
+    }
+
+    /**
+     * getCondition
+     *
+     * @param string $alias
+     */
+    public function getCondition($alias = null)
+    {
+        if ( ! $alias) {
+           $alias = $this->getTable()->getComponentName();
+        }
+        return $alias . '.' . $this->definition['foreign'] . ' = ?';
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/Nest.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,125 @@
+<?php
+/*
+ *  $Id: Self.php 1434 2007-05-22 15:57:17Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Relation_Association_Self
+ *
+ * @package     Doctrine
+ * @subpackage  Relation
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1434 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Relation_Nest extends Doctrine_Relation_Association
+{
+    /**
+     * getRelationDql
+     *
+     * @param integer $count
+     * @return string
+     */
+    /*public function getRelationDql($count, $context = 'record')
+    {
+        switch ($context) {
+            case 'record':
+                $identifierColumnNames = $this->definition['table']->getIdentifierColumnNames();
+                $identifier = array_pop($identifierColumnNames);
+                $sub    = 'SELECT '.$this->definition['foreign'] 
+                        . ' FROM '.$this->definition['refTable']->getTableName()
+                        . ' WHERE '.$this->definition['local']
+                        . ' = ?';
+
+                $sub2   = 'SELECT '.$this->definition['local']
+                        . ' FROM '.$this->definition['refTable']->getTableName()
+                        . ' WHERE '.$this->definition['foreign']
+                        . ' = ?';
+
+                $dql  = 'FROM ' . $this->definition['table']->getComponentName()
+                      . '.' . $this->definition['refTable']->getComponentName()
+                      . ' WHERE ' . $this->definition['table']->getComponentName()
+                      . '.' . $identifier 
+                      . ' IN (' . $sub . ')'
+                      . ' || ' . $this->definition['table']->getComponentName() 
+                      . '.' . $identifier
+                      . ' IN (' . $sub2 . ')';
+                break;
+            case 'collection':
+                $sub  = substr(str_repeat('?, ', $count),0,-2);
+                $dql  = 'FROM '.$this->definition['refTable']->getComponentName()
+                      . '.' . $this->definition['table']->getComponentName()
+                      . ' WHERE '.$this->definition['refTable']->getComponentName()
+                      . '.' . $this->definition['local'] . ' IN (' . $sub . ')';
+        };
+
+        return $dql;
+    }*/
+
+    public function fetchRelatedFor(Doctrine_Record $record)
+    {
+        $id = $record->getIncremented();
+
+        if (empty($id) || ! $this->definition['table']->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) {
+            return new Doctrine_Collection($this->getTable());
+        } else {
+            $q = new Doctrine_RawSql($this->getTable()->getConnection());
+
+            $assocTable = $this->getAssociationFactory()->getTableName();
+            $tableName  = $record->getTable()->getTableName();
+            $identifierColumnNames = $record->getTable()->getIdentifierColumnNames();
+            $identifier = array_pop($identifierColumnNames);
+    
+            $sub = 'SELECT ' . $this->getForeignRefColumnName()
+                 . ' FROM ' . $assocTable 
+                 . ' WHERE ' . $this->getLocalRefColumnName() 
+                 . ' = ?';
+
+            $condition[] = $tableName . '.' . $identifier . ' IN (' . $sub . ')';
+            $joinCondition[] = $tableName . '.' . $identifier . ' = ' . $assocTable . '.' . $this->getForeignRefColumnName();
+
+            if ($this->definition['equal']) {
+                $sub2   = 'SELECT ' . $this->getLocalRefColumnName()
+                        . ' FROM '  . $assocTable
+                        . ' WHERE ' . $this->getForeignRefColumnName()
+                        . ' = ?';
+
+                $condition[] = $tableName . '.' . $identifier . ' IN (' . $sub2 . ')';
+                $joinCondition[] = $tableName . '.' . $identifier . ' = ' . $assocTable . '.' . $this->getLocalRefColumnName();
+            }
+            $q->select('{'.$tableName.'.*}, {'.$assocTable.'.*}')
+              ->from($tableName . ' INNER JOIN ' . $assocTable . ' ON ' . implode(' OR ', $joinCondition))
+              ->where(implode(' OR ', $condition));
+            $q->addComponent($tableName,  $this->getClass());
+            
+            $path = $this->getClass(). '.' . $this->getAssociationFactory()->getComponentName();
+            if ($this->definition['refClassRelationAlias']) {
+                $path = $this->getClass(). '.' . $this->definition['refClassRelationAlias'];
+            }
+            $q->addComponent($assocTable, $path);
+
+            $params = ($this->definition['equal']) ? array($id, $id) : array($id);
+            $res = $q->execute($params);
+
+            return $res;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/Parser.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,529 @@
+<?php
+/*
+ *  $Id: Table.php 1397 2007-05-19 19:54:15Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Relation_Parser
+ *
+ * @package     Doctrine
+ * @subpackage  Relation
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision: 1397 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @todo Composite key support?
+ */
+class Doctrine_Relation_Parser 
+{
+    /**
+     * @var Doctrine_Table $_table          the table object this parser belongs to
+     */
+    protected $_table;
+
+    /**
+     * @var array $_relations               an array containing all the Doctrine_Relation objects for this table
+     */
+    protected $_relations = array();
+
+    /**
+     * @var array $_pending                 relations waiting for parsing
+     */
+    protected $_pending   = array();
+
+    /**
+     * constructor
+     *
+     * @param Doctrine_Table $table         the table object this parser belongs to
+     */
+    public function __construct(Doctrine_Table $table) 
+    {
+        $this->_table = $table;
+    }
+
+    /**
+     * getTable
+     *
+     * @return Doctrine_Table   the table object this parser belongs to
+     */
+    public function getTable()
+    {
+        return $this->_table;
+    }
+
+    /**
+     * getPendingRelation
+     *
+     * @return array            an array defining a pending relation
+     */
+    public function getPendingRelation($name) 
+    {
+        if ( ! isset($this->_pending[$name])) {
+            throw new Doctrine_Relation_Exception('Unknown pending relation ' . $name);
+        }
+        
+        return $this->_pending[$name];
+    }
+
+    /**
+     * getPendingRelations
+     *
+     * @return array            an array containing all the pending relations
+     */
+    public function getPendingRelations() 
+    {
+        return $this->_pending;
+    }
+
+    /**
+     * unsetPendingRelations
+     * Removes a relation. Warning: this only affects pending relations
+     *
+     * @param string            relation to remove
+     */
+    public function unsetPendingRelations($name) 
+    {
+       unset($this->_pending[$name]);
+    }
+
+    /**
+     * Check if a relation alias exists
+     *
+     * @param string $name 
+     * @return boolean $bool
+     */
+    public function hasRelation($name)
+    {
+        if ( ! isset($this->_pending[$name]) && ! isset($this->_relations[$name])) {
+            return false;
+        }
+        
+        return true;
+    }
+
+    /**
+     * binds a relation
+     *
+     * @param string $name
+     * @param string $field
+     * @return void
+     */
+    public function bind($name, $options = array())
+    {
+        $e    = explode(' as ', $name);
+        $e    = array_map('trim', $e);
+        $name = $e[0];
+        $alias = isset($e[1]) ? $e[1] : $name;
+
+        if ( ! isset($options['type'])) {
+            throw new Doctrine_Relation_Exception('Relation type not set.');
+        }
+
+        if ($this->hasRelation($alias)) {
+            unset($this->relations[$alias]);
+            unset($this->_pending[$alias]);
+        }
+
+        $this->_pending[$alias] = array_merge($options, array('class' => $name, 'alias' => $alias));
+        
+        return $this->_pending[$alias];
+    }
+
+    /**
+     * getRelation
+     *
+     * @param string $alias      relation alias
+     */
+    public function getRelation($alias, $recursive = true)
+    {
+        if (isset($this->_relations[$alias])) {
+            return $this->_relations[$alias];
+        }
+       
+        if (isset($this->_pending[$alias])) {
+            $def = $this->_pending[$alias];
+            $identifierColumnNames = $this->_table->getIdentifierColumnNames();
+            $idColumnName = array_pop($identifierColumnNames);
+            
+            // check if reference class name exists
+            // if it does we are dealing with association relation
+            if (isset($def['refClass'])) {
+                $def = $this->completeAssocDefinition($def);
+                $localClasses = array_merge($this->_table->getOption('parents'), array($this->_table->getComponentName()));
+                
+                $backRefRelationName = isset($def['refClassRelationAlias']) ?
+                        $def['refClassRelationAlias'] : $def['refClass'];
+                if ( ! isset($this->_pending[$backRefRelationName]) && ! isset($this->_relations[$backRefRelationName])) {
+
+                    $parser = $def['refTable']->getRelationParser();
+                    
+                    if ( ! $parser->hasRelation($this->_table->getComponentName())) {
+                        $parser->bind($this->_table->getComponentName(),
+                                      array('type'    => Doctrine_Relation::ONE,
+                                            'local'   => $def['local'],
+                                            'foreign' => $idColumnName,
+                                            'localKey' => true,
+                                            ));
+                    }
+
+                    if ( ! $this->hasRelation($backRefRelationName)) {
+                        if (in_array($def['class'], $localClasses)) {
+                            $this->bind($def['refClass'] . " as " . $backRefRelationName, array(
+                                    'type' => Doctrine_Relation::MANY,
+                                    'foreign' => $def['foreign'],
+                                    'local'   => $idColumnName));
+                        } else {
+                            $this->bind($def['refClass'] . " as " . $backRefRelationName, array(
+                                    'type' => Doctrine_Relation::MANY,
+                                    'foreign' => $def['local'],
+                                    'local'   => $idColumnName));
+                        }
+                    }
+                }
+                if (in_array($def['class'], $localClasses)) {
+                    $rel = new Doctrine_Relation_Nest($def);
+                } else {
+                    $rel = new Doctrine_Relation_Association($def);
+                }
+            } else {
+                // simple foreign key relation
+                $def = $this->completeDefinition($def);
+
+                if (isset($def['localKey'])) {
+                    $rel = new Doctrine_Relation_LocalKey($def);
+
+                    // Automatically index foreign keys which are not primary
+                    $foreign = (array) $def['foreign'];
+                    foreach ($foreign as $fk) {
+                        if ( ! $rel->getTable()->isIdentifier($fk)) {
+                            $rel->getTable()->addIndex($fk, array('fields' => array($fk)));
+                        }
+                    }
+                } else {
+                    $rel = new Doctrine_Relation_ForeignKey($def);
+                }
+            }
+            if (isset($rel)) {
+                // unset pending relation
+                unset($this->_pending[$alias]);
+                $this->_relations[$alias] = $rel;
+                return $rel;
+            }
+        }
+        if ($recursive) {
+            $this->getRelations();
+
+            return $this->getRelation($alias, false);
+        } else {
+            throw new Doctrine_Table_Exception('Unknown relation alias ' . $alias);
+        }
+    }
+
+    /**
+     * getRelations
+     * returns an array containing all relation objects
+     *
+     * @return array        an array of Doctrine_Relation objects
+     */
+    public function getRelations()
+    {
+        foreach ($this->_pending as $k => $v) {
+            $this->getRelation($k);
+        }
+
+        return $this->_relations;
+    }
+
+    /**
+     * getImpl
+     * returns the table class of the concrete implementation for given template
+     * if the given template is not a template then this method just returns the
+     * table class for the given record
+     *
+     * @param string $template
+     */
+    public function getImpl($template)
+    {
+        $conn = $this->_table->getConnection();
+
+        if (in_array('Doctrine_Template', class_parents($template))) {
+            $impl = $this->_table->getImpl($template);
+            
+            if ($impl === null) {
+                throw new Doctrine_Relation_Parser_Exception("Couldn't find concrete implementation for template " . $template);
+            }
+        } else {
+            $impl = $template;
+        }
+
+        return $conn->getTable($impl);
+    }
+
+    /**
+     * Completes the given association definition
+     *
+     * @param array $def    definition array to be completed
+     * @return array        completed definition array
+     */
+    public function completeAssocDefinition($def) 
+    {
+        $conn = $this->_table->getConnection();
+        $def['table'] = $this->getImpl($def['class']);
+        $def['localTable'] = $this->_table;
+        $def['class'] = $def['table']->getComponentName();
+        $def['refTable'] = $this->getImpl($def['refClass']);
+
+        $id = $def['refTable']->getIdentifierColumnNames();
+
+        if (count($id) > 1) {
+            if ( ! isset($def['foreign'])) {
+                // foreign key not set
+                // try to guess the foreign key
+    
+                $def['foreign'] = ($def['local'] === $id[0]) ? $id[1] : $id[0];
+            }
+            if ( ! isset($def['local'])) {
+                // foreign key not set
+                // try to guess the foreign key
+                $def['local'] = ($def['foreign'] === $id[0]) ? $id[1] : $id[0];
+            }
+        } else {
+
+            if ( ! isset($def['foreign'])) {
+                // foreign key not set
+                // try to guess the foreign key
+    
+                $columns = $this->getIdentifiers($def['table']);
+    
+                $def['foreign'] = $columns;
+            }
+            if ( ! isset($def['local'])) {
+                // local key not set
+                // try to guess the local key
+                $columns = $this->getIdentifiers($this->_table);
+    
+                $def['local'] = $columns;
+            }
+        }
+        return $def;
+    }
+
+    /** 
+     * getIdentifiers
+     * gives a list of identifiers from given table
+     *
+     * the identifiers are in format:
+     * [componentName].[identifier]
+     *
+     * @param Doctrine_Table $table     table object to retrieve identifiers from
+     */
+    public function getIdentifiers(Doctrine_Table $table)
+    {
+        $componentNameToLower = strtolower($table->getComponentName());
+        if (is_array($table->getIdentifier())) {
+            $columns = array();      
+            foreach ((array) $table->getIdentifierColumnNames() as $identColName) {
+                $columns[] = $componentNameToLower . '_' . $identColName;
+            }
+        } else {
+            $columns = $componentNameToLower . '_' . $table->getColumnName(
+                    $table->getIdentifier());
+        }
+
+        return $columns;
+    }
+
+    /**
+     * guessColumns
+     *
+     * @param array $classes                    an array of class names
+     * @param Doctrine_Table $foreignTable      foreign table object
+     * @return array                            an array of column names
+     */
+    public function guessColumns(array $classes, Doctrine_Table $foreignTable)
+    {
+        $conn = $this->_table->getConnection();
+
+        foreach ($classes as $class) {
+            try {
+                $table   = $conn->getTable($class);
+            } catch (Doctrine_Table_Exception $e) {
+                continue;
+            }
+            $columns = $this->getIdentifiers($table);
+            $found   = true;
+
+            foreach ((array) $columns as $column) {
+                if ( ! $foreignTable->hasColumn($column)) {
+                    $found = false;
+                    break;
+                }
+            }
+            if ($found) {
+                break;
+            }
+        }
+        
+        if ( ! $found) {
+            throw new Doctrine_Relation_Exception("Couldn't find columns.");
+        }
+
+        return $columns;
+    }
+
+    /**
+     * Completes the given definition
+     *
+     * @param array $def    definition array to be completed
+     * @return array        completed definition array
+     * @todo Description: What does it mean to complete a definition? What is done (not how)?
+     *       Refactor (too long & nesting level)
+     */
+    public function completeDefinition($def)
+    {
+        $conn = $this->_table->getConnection();
+        $def['table'] = $this->getImpl($def['class']);
+        $def['localTable'] = $this->_table;
+        $def['class'] = $def['table']->getComponentName();
+
+        $foreignClasses = array_merge($def['table']->getOption('parents'), array($def['class']));
+        $localClasses   = array_merge($this->_table->getOption('parents'), array($this->_table->getComponentName()));
+
+        $localIdentifierColumnNames = $this->_table->getIdentifierColumnNames();
+        $localIdentifierCount = count($localIdentifierColumnNames);
+        $localIdColumnName = array_pop($localIdentifierColumnNames);
+        $foreignIdentifierColumnNames = $def['table']->getIdentifierColumnNames();
+        $foreignIdColumnName = array_pop($foreignIdentifierColumnNames);
+
+        if (isset($def['local'])) {
+            if ( ! isset($def['foreign'])) {
+                // local key is set, but foreign key is not
+                // try to guess the foreign key
+
+                if ($def['local'] === $localIdColumnName) {
+                    $def['foreign'] = $this->guessColumns($localClasses, $def['table']);
+                } else {
+                    // the foreign field is likely to be the
+                    // identifier of the foreign class
+                    $def['foreign'] = $foreignIdColumnName;
+                    $def['localKey'] = true;
+                }
+            } else {
+                if ($localIdentifierCount == 1) {
+                    if ($def['local'] == $localIdColumnName && isset($def['owningSide'])
+                            && $def['owningSide'] === true) {
+                        $def['localKey'] = true;
+                    } else if (($def['local'] !== $localIdColumnName && $def['type'] == Doctrine_Relation::ONE)) {
+                        $def['localKey'] = true;
+                    }
+                } else if ($localIdentifierCount > 1) {
+                    // It's a composite key and since 'foreign' can not point to a composite
+                    // key currently, we know that 'local' must be the foreign key.
+                    $def['localKey'] = true;
+                }
+            }
+        } else {
+            if (isset($def['foreign'])) {
+                // local key not set, but foreign key is set
+                // try to guess the local key
+                if ($def['foreign'] === $foreignIdColumnName) {
+                    $def['localKey'] = true;
+                    try {
+                        $def['local'] = $this->guessColumns($foreignClasses, $this->_table);
+                    } catch (Doctrine_Relation_Exception $e) {
+                        $def['local'] = $localIdColumnName;
+                    }
+                } else {
+                    $def['local'] = $localIdColumnName;
+                }
+            } else {
+                // neither local or foreign key is being set
+                // try to guess both keys
+
+                $conn = $this->_table->getConnection();
+
+                // the following loops are needed for covering inheritance
+                foreach ($localClasses as $class) {
+                    $table = $conn->getTable($class);
+                    $identifierColumnNames = $table->getIdentifierColumnNames();
+                    $idColumnName = array_pop($identifierColumnNames);
+                    $column = strtolower($table->getComponentName())
+                            . '_' . $idColumnName;
+
+                    foreach ($foreignClasses as $class2) {
+                        $table2 = $conn->getTable($class2);
+                        if ($table2->hasColumn($column)) {
+                            $def['foreign'] = $column;
+                            $def['local'] = $idColumnName;
+                            return $def;
+                        }
+                    }
+                }
+
+                foreach ($foreignClasses as $class) {
+                    $table  = $conn->getTable($class);
+                    $identifierColumnNames = $table->getIdentifierColumnNames();
+                    $idColumnName = array_pop($identifierColumnNames);
+                    $column = strtolower($table->getComponentName())
+                            . '_' . $idColumnName;
+                
+                    foreach ($localClasses as $class2) {
+                        $table2 = $conn->getTable($class2);
+                        if ($table2->hasColumn($column)) {
+                            $def['foreign']  = $idColumnName;
+                            $def['local']    = $column;
+                            $def['localKey'] = true;
+                            return $def;
+                        }
+                    }
+                }
+
+                // auto-add columns and auto-build relation
+                $columns = array();
+                foreach ((array) $this->_table->getIdentifierColumnNames() as $id) {
+                    // ?? should this not be $this->_table->getComponentName() ??
+                    $column = strtolower($table->getComponentName())
+                            . '_' . $id;
+
+                    $col = $this->_table->getColumnDefinition($id);
+                    $type = $col['type'];
+                    $length = $col['length'];
+
+                    unset($col['type']);
+                    unset($col['length']);
+                    unset($col['autoincrement']);
+                    unset($col['sequence']);
+                    unset($col['primary']);
+
+                    $def['table']->setColumn($column, $type, $length, $col);
+                    
+                    $columns[] = $column;
+                }
+                if (count($columns) > 1) {
+                    $def['foreign'] = $columns;
+                } else {
+                    $def['foreign'] = $columns[0];
+                }
+                $def['local'] = $localIdColumnName;
+            }
+        }
+        return $def;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Relation/Parser/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */        
+
+/**
+ * Doctrine_Relation_Parser_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Relation
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Relation_Parser_Exception extends Doctrine_Relation_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,287 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search extends Doctrine_Record_Generator
+{
+    const INDEX_FILES = 0;
+
+    const INDEX_TABLES = 1;
+
+    protected $_options = array('generateFiles' => false,
+                                'type'          => self::INDEX_TABLES,
+                                'className'     => '%CLASS%Index',
+                                'generatePath'  => false,
+                                'table'         => null,
+                                'batchUpdates'  => false,
+                                'pluginTable'   => false,
+                                'fields'        => array(),
+                                'connection'    => null,
+                                'children'      => array());
+    /**
+     * __construct 
+     * 
+     * @param array $options 
+     * @return void
+     */
+    public function __construct(array $options)
+    {
+        $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
+        
+        if ( ! isset($this->_options['analyzer'])) {
+            $this->_options['analyzer'] = 'Doctrine_Search_Analyzer_Standard';
+        }
+        
+        $this->_options['analyzer'] = new $this->_options['analyzer'];
+
+        if ( ! isset($this->_options['connection'])) {
+            $this->_options['connection'] = Doctrine_Manager::connection();
+        }
+    }
+
+    /**
+     * Searchable keyword search
+     * 
+     * @param string $string Keyword string to search for
+     * @param Doctrine_Query $query Query object to alter. Adds where condition to limit the results using the search index
+     * @return mixed The Doctrine_Collection or array of ids and relevancy
+     */
+    public function search($string, $query = null)
+    {
+        $q = new Doctrine_Search_Query($this->_table);
+
+        if ($query instanceof Doctrine_Query) {
+            $q->query($string, false);
+
+            $newQuery = $query->copy();
+            $query->getSql();
+            $key = (array) $this->getOption('table')->getIdentifier();
+            $newQuery->addWhere($query->getRootAlias() . '.'.current($key).' IN (SQL:' . $q->getSql() . ')', $q->getParams());
+
+            return $newQuery;
+        } else {
+            $q->query($string);
+            return $this->_options['connection']->fetchAll($q->getSql(), $q->getParams());
+        }
+    }
+    
+    /**
+     * analyze 
+     * 
+     * @param string $text 
+     * @return void
+     */
+    public function analyze($text)
+    {
+        return $this->_options['analyzer']->analyze($text);
+    }
+
+    /**
+     * updateIndex
+     * updates the index
+     *
+     * @param Doctrine_Record $record
+     * @return integer
+     */
+    public function updateIndex(array $data)
+    {
+        $this->initialize($this->_options['table']);
+
+        $fields = $this->getOption('fields');
+        $class  = $this->getOption('className');
+        $name   = $this->getOption('table')->getComponentName();
+        $conn   = $this->getOption('table')->getConnection();
+        $identifier = $this->_options['table']->getIdentifier();
+
+        $q = Doctrine_Query::create()->delete()
+                                     ->from($class);
+        foreach ((array) $identifier as $id) {
+            $q->addWhere($id . ' = ?', array($data[$id]));
+        }
+        $q->execute();
+
+        if ($this->_options['batchUpdates'] === true) {
+            $index = new $class(); 
+
+            foreach ((array) $this->_options['table']->getIdentifier() as $id) {
+                $index->$id = $data[$id];
+            }
+
+            $index->save();
+        } else {
+            foreach ($fields as $field) {
+
+                $value = isset($data[$field]) ? $data[$field] : null;
+
+                $terms = $this->analyze($value);
+
+                foreach ($terms as $pos => $term) {
+                    $index = new $class();
+
+                    $index->keyword = $term;
+                    $index->position = $pos;
+                    $index->field = $field;
+                    foreach ((array) $this->_options['table']->getIdentifier() as $id) {
+                        $index->$id = $data[$id];
+                    }
+
+                    $index->save();
+                }
+            }
+        }
+    }
+
+    /**
+     * readTableData 
+     * 
+     * @param mixed $limit 
+     * @param mixed $offset 
+     * @return Doctrine_Collection The collection of results
+     */
+    public function readTableData($limit = null, $offset = null)
+    {
+        $this->initialize($this->_options['table']);
+
+        $conn      = $this->_options['table']->getConnection();
+        $tableName = $this->_options['table']->getTableName();
+        $id        = $this->_options['table']->getIdentifier();
+
+        $query = 'SELECT * FROM ' . $conn->quoteIdentifier($tableName)
+               . ' WHERE ' . $conn->quoteIdentifier($id)
+               . ' IN (SELECT ' . $conn->quoteIdentifier($id)
+               . ' FROM ' . $conn->quoteIdentifier($this->_table->getTableName())
+               . ' WHERE keyword IS NULL) OR ' . $conn->quoteIdentifier($id)
+               . ' NOT IN (SELECT ' . $conn->quoteIdentifier($id)
+               . ' FROM ' . $conn->quoteIdentifier($this->_table->getTableName()) . ')';
+
+        $query = $conn->modifyLimitQuery($query, $limit, $offset);
+
+        return $conn->fetchAll($query);
+    }
+
+    /**
+     * batchUpdateIndex 
+     * 
+     * @param mixed $limit 
+     * @param mixed $offset 
+     * @return void
+     */
+    public function batchUpdateIndex($limit = null, $offset = null)
+    {
+        $this->initialize($this->_options['table']);
+
+        $id        = $this->_options['table']->getIdentifier();
+        $class     = $this->_options['className'];
+        $fields    = $this->_options['fields'];
+        $conn      = $this->_options['connection'];
+        try {
+
+            $conn->beginTransaction();
+
+            $rows = $this->readTableData($limit, $offset);
+
+            $ids = array();
+            foreach ($rows as $row) {
+                $ids[] = $row[$id];
+            }
+
+            $placeholders = str_repeat('?, ', count($ids));
+            $placeholders = substr($placeholders, 0, strlen($placeholders) - 2);
+
+            $sql = 'DELETE FROM ' 
+                  . $conn->quoteIdentifier($this->_table->getTableName())
+                  . ' WHERE ' . $conn->quoteIdentifier($id) . ' IN (' . substr($placeholders, 0) . ')';
+
+            $conn->exec($sql, $ids);
+
+            foreach ($rows as $row) {
+                foreach ($fields as $field) {
+                    $data  = $row[$field];
+        
+                    $terms = $this->analyze($data);
+        
+                    foreach ($terms as $pos => $term) {
+                        $index = new $class();
+        
+                        $index->keyword = $term;
+                        $index->position = $pos;
+                        $index->field = $field;
+                        
+                        foreach ((array) $id as $identifier) {
+                            $index->$identifier = $row[$identifier];
+                        }
+    
+                        $index->save();
+                    }
+                }
+            }
+
+            $conn->commit();
+        } catch (Doctrine_Exception $e) {
+            $conn->rollback();
+        }
+    }
+
+    /**
+     * buildDefinition 
+     * 
+     * @return void
+     */
+    public function setTableDefinition()
+    {
+    	if ( ! isset($this->_options['table'])) {
+    	    throw new Doctrine_Record_Exception("Unknown option 'table'.");
+    	}
+
+        $componentName = $this->_options['table']->getComponentName();
+
+        $className = $this->getOption('className');
+
+        $autoLoad = (bool) ($this->_options['generateFiles']);
+        if (class_exists($className, $autoLoad)) {
+            return false;
+        }
+
+        $columns = array('keyword'  => array('type'    => 'string',
+                                             'length'  => 200,
+                                             'primary' => true,
+                                             ),
+                         'field'    => array('type'    => 'string',
+                                             'length'  => 50,
+                                             'primary' => true),
+                         'position' => array('type'    => 'integer',
+                                             'length'  => 8,
+                                             'primary' => true,
+                                             ));
+
+        $this->hasColumns($columns);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Analyzer.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,39 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Analyzer
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Analyzer implements Doctrine_Search_Analyzer_Interface
+{
+    public function analyze($text)
+    {
+    
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Analyzer/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Analyzer_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Analyzer_Exception extends Doctrine_Search_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Analyzer/Interface.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,36 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Analyzer_Interface
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+interface Doctrine_Search_Analyzer_Interface
+{
+    public function analyze($text);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Analyzer/Standard.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,290 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Analyzer_Standard
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Analyzer_Standard implements Doctrine_Search_Analyzer_Interface
+{
+    protected static $_stopwords = array(
+                            // Ticket #1787. Fixed searchable behavior numeric evaluation
+                            // Removed the numeric 0-9 from here
+                            'a',
+                            'about',
+                            'after',
+                            'all',
+                            'almost',
+                            'along',
+                            'also',
+                            'although',
+                            'amp',
+                            'an',
+                            'and',
+                            'another',
+                            'any',
+                            'are',
+                            'area',
+                            'arent',
+                            'around',
+                            'as',
+                            'at',
+                            'available',
+                            'back',
+                            'be',
+                            'because',
+                            'been',
+                            'before',
+                            'being',
+                            'best',
+                            'better',
+                            'big',
+                            'bit',
+                            'both',
+                            'but',
+                            'by',
+                            'c',
+                            'came',
+                            'can',
+                            'capable',
+                            'control',
+                            'could',
+                            'course',
+                            'd',
+                            'dan',
+                            'day',
+                            'decided',
+                            'did',
+                            'didn',
+                            'different',
+                            'div',
+                            'do',
+                            'doesn',
+                            'don',
+                            'down',
+                            'drive',
+                            'e',
+                            'each',
+                            'easily',
+                            'easy',
+                            'edition',
+                            'either',
+                            'end',
+                            'enough',
+                            'even',
+                            'every',
+                            'example',
+                            'few',
+                            'find',
+                            'first',
+                            'for',
+                            'found',
+                            'from',
+                            'get',
+                            'go',
+                            'going',
+                            'good',
+                            'got',
+                            'gt',
+                            'had',
+                            'hard',
+                            'has',
+                            'have',
+                            'he',
+                            'her',
+                            'here',
+                            'how',
+                            'i',
+                            'if',
+                            'in',
+                            'into',
+                            'is',
+                            'isn',
+                            'it',
+                            'just',
+                            'know',
+                            'last',
+                            'left',
+                            'li',
+                            'like',
+                            'little',
+                            'll',
+                            'long',
+                            'look',
+                            'lot',
+                            'lt',
+                            'm',
+                            'made',
+                            'make',
+                            'many',
+                            'mb',
+                            'me',
+                            'menu',
+                            'might',
+                            'mm',
+                            'more',
+                            'most',
+                            'much',
+                            'my',
+                            'name',
+                            'nbsp',
+                            'need',
+                            'new',
+                            'no',
+                            'not',
+                            'now',
+                            'number',
+                            'of',
+                            'off',
+                            'old',
+                            'on',
+                            'one',
+                            'only',
+                            'or',
+                            'original',
+                            'other',
+                            'our',
+                            'out',
+                            'over',
+                            'part',
+                            'place',
+                            'point',
+                            'pretty',
+                            'probably',
+                            'problem',
+                            'put',
+                            'quite',
+                            'quot',
+                            'r',
+                            're',
+                            'really',
+                            'results',
+                            'right',
+                            's',
+                            'same',
+                            'saw',
+                            'see',
+                            'set',
+                            'several',
+                            'she',
+                            'sherree',
+                            'should',
+                            'since',
+                            'size',
+                            'small',
+                            'so',
+                            'some',
+                            'something',
+                            'special',
+                            'still',
+                            'stuff',
+                            'such',
+                            'sure',
+                            'system',
+                            't',
+                            'take',
+                            'than',
+                            'that',
+                            'the',
+                            'their',
+                            'them',
+                            'then',
+                            'there',
+                            'these',
+                            'they',
+                            'thing',
+                            'things',
+                            'think',
+                            'this',
+                            'those',
+                            'though',
+                            'through',
+                            'time',
+                            'to',
+                            'today',
+                            'together',
+                            'too',
+                            'took',
+                            'two',
+                            'up',
+                            'us',
+                            'use',
+                            'used',
+                            'using',
+                            've',
+                            'very',
+                            'want',
+                            'was',
+                            'way',
+                            'we',
+                            'well',
+                            'went',
+                            'were',
+                            'what',
+                            'when',
+                            'where',
+                            'which',
+                            'while',
+                            'white',
+                            'who',
+                            'will',
+                            'with',
+                            'would',
+                            'yet',
+                            'you',
+                            'your',
+                            'yours'
+                            );
+
+    public function analyze($text)
+    {
+    	$text = preg_replace('/[\'`´"]/', '', $text);
+    	$text = Doctrine_Inflector::unaccent($text);
+        $text = preg_replace('/[^A-Za-z0-9]/', ' ', $text);
+        $text = str_replace('  ', ' ', $text);
+
+        $terms = explode(' ', $text);
+        
+        $ret = array();
+        if ( ! empty($terms)) {
+            foreach ($terms as $i => $term) {
+                if (empty($term)) {
+                    continue;
+                }
+                $lower = strtolower(trim($term));
+
+                if (in_array($lower, self::$_stopwords)) {
+                    continue;
+                }
+
+                $ret[$i] = $lower;
+            }
+        }
+        return $ret;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/File.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,80 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_File extends Doctrine_Search
+{
+    /**
+     * constructor
+     *
+     * @param array $options    an array of plugin options
+     */
+    public function __construct(array $options = array())
+    {
+        parent::__construct($options);
+
+        if ( ! isset($this->_options['resource'])) {
+            $table = new Doctrine_Table('File', Doctrine_Manager::connection());
+
+            $table->setColumn('url', 'string', 255, array('primary' => true));
+        }
+
+        if (empty($this->_options['fields'])) {
+            $this->_options['fields'] = array('url', 'content');
+        }
+
+        $this->initialize($table);
+    }
+    public function buildRelation()
+    {
+    	
+    }	
+    /**
+     * indexes given directory
+     *
+     * @param string $dir   the name of the directory to index
+     * @return void
+     */
+    public function indexDirectory($dir)
+    {
+        $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir),
+                                                RecursiveIteratorIterator::LEAVES_ONLY);
+                                                
+        foreach ($it as $file) {
+            if (strpos($file, DIRECTORY_SEPARATOR . '.svn') !== false) {
+                continue;
+            }
+
+            $this->updateIndex(array('url' => $file->getPathName(),
+                                     'content' => file_get_contents($file)));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Indexer.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,75 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Indexer
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Indexer
+{
+    public function indexDirectory($dir)
+    {
+        if ( ! file_exists($dir)) {
+           throw new Doctrine_Search_Indexer_Exception('Unknown directory ' . $dir);
+        }
+
+        $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY);
+
+        $files = array();
+        foreach ($it as $file) {
+            $name = $file->getPathName();
+            if (strpos($name, '.svn') === false) {
+                $files[] = $name;
+            }
+        }
+
+        $q = new Doctrine_Query();
+        $q->delete()
+          ->from('Doctrine_File f')
+          ->where('f.url LIKE ?', array($dir . '%'))
+          ->execute();
+
+        // clear the index
+        $q = new Doctrine_Query();
+        $q->delete()
+          ->from('Doctrine_File_Index i')
+          ->where('i.file_id = ?')
+          ->execute();
+
+
+        $conn = Doctrine_Manager::connection();
+
+        $coll = new Doctrine_Collection('Doctrine_File');
+
+        foreach ($files as $file) {
+            $coll[]->url = $file;
+        }
+        
+        $coll->save();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Indexer/Dir.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,47 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Indexer_Dir
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Indexer_Dir
+{
+    public function add($dir)
+    {
+        if ( ! file_exists($dir)) {
+           throw new Doctrine_Search_Indexer_Exception('Unknown directory ' . $dir);
+        }
+
+        $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY);
+        
+        foreach ($it as $file) {
+            $this->indexFile($file);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Indexer/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Indexer
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Indexer_Exception extends Doctrine_Search_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Listener.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,59 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Listener
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Listener extends Doctrine_Record_Listener 
+{
+    protected $_search;
+
+    public function __construct(Doctrine_Search $search)
+    {
+        $this->_search = $search;
+    }
+
+    public function preUpdate(Doctrine_Event $event)
+    {
+    }
+
+    public function postUpdate(Doctrine_Event $event)
+    {
+        $record = $event->getInvoker(); 
+
+        $this->_search->updateIndex($record->toArray()); 
+    }
+
+    public function postInsert(Doctrine_Event $event)
+    {
+        $record = $event->getInvoker();
+        
+        $this->_search->updateIndex($record->toArray());
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Parser.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,41 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Parser_Standard
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Parser
+{
+    public function parse($file)
+    {
+        $contents = file_get_contents($file);
+        
+        return array('url' => $file, 'contents' => $contents);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Query.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,245 @@
+<?php
+/*
+ *  $Id: Hook.php 1939 2007-07-05 23:47:48Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Query
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Query
+{
+
+    /**
+     * @var Doctrine_Table $_table          the index table
+     */
+    protected $_table = array();
+    
+    protected $_sql = '';
+    
+    protected $_params = array();
+    
+    protected $_words = array();
+    
+    protected $_tokenizer;
+
+    protected $_condition;
+
+    /**
+     * @param Doctrine_Table $_table        the index table
+     */
+    public function __construct($table)
+    {
+        if (is_string($table)) {
+           $table = Doctrine::getTable($table);
+        } else {
+            if ( ! $table instanceof Doctrine_Table) {
+                throw new Doctrine_Search_Exception('Invalid argument type. Expected instance of Doctrine_Table.');
+            }
+        }
+
+        $this->_tokenizer = new Doctrine_Query_Tokenizer();
+        $this->_table = $table;
+
+        $foreignId = current(array_diff($this->_table->getColumnNames(), array('keyword', 'field', 'position')));
+
+        $this->_condition = $foreignId . ' %s (SELECT ' . $foreignId . ' FROM ' . $this->_table->getTableName() . ' WHERE ';
+    }
+
+
+    public function query($text, $includeRelevance = true)
+    {
+        $text = trim($text);
+
+        $foreignId = current(array_diff($this->_table->getColumnNames(), array('keyword', 'field', 'position')));
+
+        $weighted = false;
+        if (strpos($text, '^') === false) {
+            if ($includeRelevance) {
+                $select = 'SELECT COUNT(keyword) AS relevance, ' . $foreignId;
+            } else {
+                $select = 'SELECT ' . $foreignId;
+            }
+        } else {
+            if ($includeRelevance) {
+                $select = 'SELECT SUM(sub_relevance) AS relevance, ' . $foreignId;
+            } else {
+                $select = 'SELECT ' . $foreignId;
+            }
+        }
+        
+        $from = 'FROM ' . $this->_table->getTableName();
+        $where = 'WHERE ';
+        $where .= $this->parseClause($text);
+
+        $groupby = 'GROUP BY ' . $foreignId;
+        if ($includeRelevance) {
+            $orderBy = 'ORDER BY relevance DESC';
+        } else {
+            $orderBy = null;
+        }
+        $this->_sql = $select . ' ' . $from . ' ' . $where . ' ' . $groupby;
+        if (isset($orderBy) && $orderBy !== null) {
+            $this->_sql .= ' ' . $orderBy;
+        }
+    }
+
+    public function parseClause($originalClause, $recursive = false)
+    {
+        $clause = $this->_tokenizer->bracketTrim($originalClause);
+        
+        $brackets = false;
+
+        if ($clause !== $originalClause) {
+            $brackets = true;
+        }
+
+        $foreignId = current(array_diff($this->_table->getColumnNames(), array('keyword', 'field', 'position')));
+        
+        $terms = $this->_tokenizer->sqlExplode($clause, ' OR ', '(', ')');
+
+        $ret = array();
+
+        if (count($terms) > 1) {
+            $leavesOnly = true;
+
+            foreach ($terms as $k => $term) {
+                if ($this->isExpression($term)) {
+                    $ret[$k] = $this->parseClause($term, true);
+                    $leavesOnly = false;
+                } else {
+                    $ret[$k] = $this->parseTerm($term);
+                }
+            }
+
+            $return = implode(' OR ', $ret);
+
+            if ($leavesOnly && $recursive) {
+                $return = sprintf($this->_condition, 'IN') . $return . ')';
+                $brackets = false;
+            }
+        } else {
+            $terms = $this->_tokenizer->sqlExplode($clause, ' ', '(', ')');
+            
+            if (count($terms) === 1 && ! $recursive) {
+                $return = $this->parseTerm($clause);
+            } else {
+                foreach ($terms as $k => $term) {
+                    $term = trim($term);
+    
+                    if ($term === 'AND') {
+                        continue;
+                    }
+    
+                    if (substr($term, 0, 1) === '-') {
+                        $operator = 'NOT IN';
+                        $term = substr($term, 1);
+                    } else {
+                        $operator = 'IN';
+                    }
+    
+                    if ($this->isExpression($term)) {
+                        $ret[$k] = $this->parseClause($term, true);
+                    } else {
+                        $ret[$k] = sprintf($this->_condition, $operator) . $this->parseTerm($term) . ')';
+                    }
+                }
+                $return = implode(' AND ', $ret);
+            }
+        }
+
+        if ($brackets) {
+            return '(' . $return . ')';
+        } else {
+            return $return;
+        }
+    }
+    public function isExpression($term)
+    {
+        if (strpos($term, '(') !== false) {
+            return true;
+        } else {
+            $terms = $this->_tokenizer->quoteExplode($term);
+            
+            return (count($terms) > 1);
+        }
+    }
+
+    public function parseTerm($term)
+    {
+        $negation = false;
+
+        if (strpos($term, "'") === false) {
+            $where = $this->parseWord($term);
+        } else {
+            $term = trim($term, "' ");
+
+            $terms = $this->_tokenizer->quoteExplode($term);
+            $where = $this->parseWord($terms[0]);
+
+            foreach ($terms as $k => $word) {
+                if ($k === 0) {
+                    continue;
+                }
+                $where .= ' AND (position + ' . $k . ') = (SELECT position FROM ' . $this->_table->getTableName() . ' WHERE ' . $this->parseWord($word) . ')';
+            }
+        }
+        return $where;
+    }
+    public function parseWord($word)
+    {
+        $this->_words[] = str_replace('*', '', $word);
+
+        if (strpos($word, '?') !== false ||
+            strpos($word, '*') !== false) {
+
+            $word = str_replace('*', '%', $word);
+
+            $where = 'keyword LIKE ?';
+
+            $params = array($word);
+        } else {
+            $where = 'keyword = ?';
+        }
+
+        $this->_params[] = $word;
+
+        return $where;
+    }
+
+    public function getWords()
+    {
+        return $this->_words;
+    }
+    public function getParams()
+    {
+        return $this->_params;
+    }
+    public function getSql()
+    {
+        return $this->_sql;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Search/Record.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,47 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Record
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Record extends Doctrine_Template
+{
+    public function setTableDefinition()
+    {
+        $this->hasColumn('keyword', 'string', 250, array('notnull' => true));
+        $this->hasColumn('field', 'string', 50, array('notnull' => true));
+        $this->hasColumn('position', 'integer', 8);
+        // depending on the identifiers of the owner record this record 
+        // has also one to many foreign key columns
+    }
+    public function setUp()
+    {
+        $this->hasOne('[Component]', array('onDelete' => 'CASCADE'));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,74 @@
+<?php
+/*
+ *  $Id: Sequence.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Sequence
+ * The base class for sequence handling drivers.
+ *
+ * @package     Doctrine
+ * @subpackage  Sequence
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Sequence extends Doctrine_Connection_Module
+{
+    /**
+     * Returns the next free id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     * @param bool              when true missing sequences are automatic created
+     *
+     * @return integer          next id in the given sequence
+     */
+    public function nextId($seqName, $ondemand = true)
+    {
+        throw new Doctrine_Sequence_Exception('method not implemented');
+    }
+
+    /**
+     * Returns the autoincrement ID if supported or $id or fetches the current
+     * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
+     *
+     * @param   string  name of the table into which a new row was inserted
+     * @param   string  name of the field into which a new row was inserted
+     */
+    public function lastInsertId($table = null, $field = null)
+    {
+        throw new Doctrine_Sequence_Exception('method not implemented');
+    }
+
+    /**
+     * Returns the current id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     *
+     * @return integer          current id in the given sequence
+     */
+    public function currId($seqName)
+    {
+        $this->warnings[] = 'database does not support getting current
+            sequence value, the sequence value was incremented';
+        return $this->nextId($seqName);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Db2.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,123 @@
+<?php
+/*
+ *  $Id: Db2.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Sequence_Db2
+ *
+ * @package     Doctrine
+ * @subpackage  Sequence
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Sequence_Db2 extends Doctrine_Sequence
+{
+    /**
+     * Return the most recent value from the specified sequence in the database.
+     * This is supported only on RDBMS brands that support sequences
+     * (e.g. Oracle, PostgreSQL, DB2).  Other RDBMS brands return null.
+     *
+     * @param string $sequenceName
+     * @return integer
+     * @throws Doctrine_Adapter_Db2_Exception
+     */
+    public function lastSequenceId($sequenceName)
+    {
+        $sql = 'SELECT PREVVAL FOR '
+             . $this->quoteIdentifier($this->conn->formatter->getSequenceName($sequenceName))
+             . ' AS VAL FROM SYSIBM.SYSDUMMY1';
+
+        $stmt   = $this->query($sql);
+        $result = $stmt->fetchAll(Doctrine::FETCH_ASSOC);
+        if ($result) {
+            return $result[0]['VAL'];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Generate a new value from the specified sequence in the database, and return it.
+     * This is supported only on RDBMS brands that support sequences
+     * (e.g. Oracle, PostgreSQL, DB2).  Other RDBMS brands return null.
+     *
+     * @param string $sequenceName
+     * @return integer
+     * @throws Doctrine_Adapter_Db2_Exception
+     */
+    public function nextSequenceId($sequenceName)
+    {
+        $this->_connect();
+        $sql = 'SELECT NEXTVAL FOR '
+             . $this->quoteIdentifier($this->conn->formatter->getSequenceName($sequenceName))
+             . ' AS VAL FROM SYSIBM.SYSDUMMY1';
+        $stmt = $this->query($sql);
+        $result = $stmt->fetchAll(Doctrine::FETCH_ASSOC);
+        if ($result) {
+            return $result[0]['VAL'];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the last ID generated automatically by an IDENTITY/AUTOINCREMENT column.
+     *
+     * As a convention, on RDBMS brands that support sequences
+     * (e.g. Oracle, PostgreSQL, DB2), this method forms the name of a sequence
+     * from the arguments and returns the last id generated by that sequence.
+     * On RDBMS brands that support IDENTITY/AUTOINCREMENT columns, this method
+     * returns the last value generated for such a column, and the table name
+     * argument is disregarded.
+     *
+     * The IDENTITY_VAL_LOCAL() function gives the last generated identity value
+     * in the current process, even if it was for a GENERATED column.
+     *
+     * @param string $tableName OPTIONAL
+     * @param string $primaryKey OPTIONAL
+     * @return integer
+     * @throws Doctrine_Adapter_Db2_Exception
+     */
+    public function lastInsertId($tableName = null, $primaryKey = null)
+    {
+        $this->_connect();
+
+        if ($tableName !== null) {
+            $sequenceName = $tableName;
+            if ($primaryKey) {
+                $sequenceName .= "_$primaryKey";
+            }
+            $sequenceName .= '_seq';
+            return $this->lastSequenceId($sequenceName);
+        }
+
+        $sql = 'SELECT IDENTITY_VAL_LOCAL() AS VAL FROM SYSIBM.SYSDUMMY1';
+        $stmt = $this->query($sql);
+        $result = $stmt->fetchAll(Doctrine::FETCH_ASSOC);
+        if ($result) {
+            return $result[0]['VAL'];
+        } else {
+            return null;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Sequence_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Sequence
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Sequence_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Firebird.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,107 @@
+<?php
+/*
+ *  $Id: Firebird.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Sequence_Firebird
+ *
+ * @package     Doctrine
+ * @subpackage  Sequence
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Sequence_Firebird extends Doctrine_Sequence
+{
+    /**
+     * Returns the next free id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     * @param bool              when true missing sequences are automatic created
+     *
+     * @return integer          next id in the given sequence
+     */
+    public function nextID($seqName, $onDemand = true)
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+
+        $query = 'SELECT GEN_ID(' . $sequenceName . ', 1) as the_value FROM RDB$DATABASE';
+        try {
+        
+            $result = $this->conn->fetchOne($query);
+
+        } catch(Doctrine_Connection_Exception $e) {
+            if ($onDemand && $e->getPortableCode() == Doctrine::ERR_NOSUCHTABLE) {
+                // Since we are creating the sequence on demand
+                // we know the first id = 1 so initialize the
+                // sequence at 2
+                try {
+                    $result = $this->conn->export->createSequence($seqName, 2);
+                } catch(Doctrine_Exception $e) {
+                    throw new Doctrine_Sequence_Exception('on demand sequence ' . $seqName . ' could not be created');
+                }
+                // First ID of a newly created sequence is 1
+                // return 1;
+                // BUT generators are not always reset, so return the actual value
+                return $this->currID($seqName);
+            }
+            throw $e;
+        }
+        return $result;
+    }
+
+    /**
+     * Returns the autoincrement ID if supported or $id or fetches the current
+     * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
+     *
+     * @param   string  name of the table into which a new row was inserted
+     * @param   string  name of the field into which a new row was inserted
+     */
+    public function lastInsertId($table = null, $field = null)
+    {
+        return $this->conn->getDbh()->lastInsertId();
+    }
+
+    /**
+     * Returns the current id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     *
+     * @return integer          current id in the given sequence
+     */
+    public function currId($seqName)
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+        
+
+        $query = 'SELECT GEN_ID(' . $sequenceName . ', 0) as the_value FROM RDB$DATABASE';
+        try {
+            $value = $this->conn->fetchOne($query);
+        } catch(Doctrine_Connection_Exception $e) {
+            throw new Doctrine_Sequence_Exception('Unable to select from ' . $seqName);
+        }
+        if ( ! is_numeric($value)) {
+            throw new Doctrine_Sequence_Exception('could not find value in sequence table');
+        }
+        return $value;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Informix.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Informix.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Sequence_Informix
+ *
+ * @package     Doctrine
+ * @subpackage  Sequence
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Sequence_Informix extends Doctrine_Sequence
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Mssql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,157 @@
+<?php
+/*
+ *  $Id: Mssql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Sequence_Mssql
+ *
+ * @package     Doctrine
+ * @subpackage  Sequence
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Sequence_Mssql extends Doctrine_Sequence
+{
+    /**
+     * Returns the next free id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     * @param bool              when true missing sequences are automatic created
+     *
+     * @return integer          next id in the given sequence
+     */
+    public function nextId($seqName, $onDemand = true)
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+        $seqcolName   = $this->conn->quoteIdentifier($this->conn->getAttribute(Doctrine::ATTR_SEQCOL_NAME), true);
+
+
+        if ($this->checkSequence($sequenceName)) {
+            $query = 'SET IDENTITY_INSERT ' . $sequenceName . ' OFF '
+                   . 'INSERT INTO ' . $sequenceName . ' DEFAULT VALUES';
+        } else {
+            $query = 'INSERT INTO ' . $sequenceName . ' (' . $seqcolName . ') VALUES (0)';
+        }
+        
+        try {
+
+            $this->conn->exec($query);
+
+        } catch(Doctrine_Connection_Exception $e) {
+            if ($onDemand && $e->getPortableCode() == Doctrine::ERR_NOSUCHTABLE) {
+                // Since we are creating the sequence on demand
+                // we know the first id = 1 so initialize the
+                // sequence at 2
+                try {
+                    $result = $this->conn->export->createSequence($seqName, 2);
+                } catch(Doctrine_Exception $e) {
+                    throw new Doctrine_Sequence_Exception('on demand sequence ' . $seqName . ' could not be created');
+                }
+                
+                /**
+                 * This could actually be a table that starts at 18.. oh well..
+                 * we will keep the fallback to return 1 in case we skip this.. which
+                 * should really not happen.. otherwise the returned values is biased.
+                 */
+                if ($this->checkSequence($seqName)) {
+                    return $this->lastInsertId($seqName);
+                }
+                
+                return 1;
+            }
+            throw $e;
+        }
+        
+        $value = $this->lastInsertId($sequenceName);
+
+        if (is_numeric($value)) {
+            $query = 'DELETE FROM ' . $sequenceName . ' WHERE ' . $seqcolName . ' < ' . $value;
+            
+            try {
+                $this->conn->exec($query);
+            } catch (Doctrine_Connection_Exception $e) {
+                throw new Doctrine_Sequence_Exception('Could not delete previous sequence from ' . $sequenceName . 
+                                                      ' at ' . __FILE__ . ' in ' . __FUNCTION__ . ' with the message: ' .
+                                                      $e->getMessage());
+            }
+        }
+        return $value;
+    }
+
+    /**
+     * Checks if there's a sequence that exists.
+     *
+     * @param  string $seqName     The sequence name to verify.
+     * @return bool   $tableExists The value if the table exists or not
+     * @access private
+     */
+    public function checkSequence($seqName)
+    {
+        $query = 'SELECT COUNT(1) FROM ' . $seqName;
+        try {
+            $this->conn->execute($query);
+        } catch (Doctrine_Connection_Exception $e) {
+            if ($e->getPortableCode() == Doctrine::ERR_NOSUCHTABLE) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Returns the autoincrement ID if supported or $id or fetches the current
+     * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
+     *
+     * @param   string  name of the table into which a new row was inserted
+     * @param   string  name of the field into which a new row was inserted
+     */
+    public function lastInsertId($table = null, $field = null)
+    {
+        $serverInfo = $this->conn->getServerVersion();
+        if (is_array($serverInfo)
+            && ! is_null($serverInfo['major'])
+            && $serverInfo['major'] >= 8) {
+
+            $query = 'SELECT SCOPE_IDENTITY()';
+
+        } else {
+            $query = 'SELECT @@IDENTITY';
+        }
+
+        return (string) floor((float) $this->conn->fetchOne($query));
+    }
+
+    /**
+     * Returns the current id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     *
+     * @return integer          current id in the given sequence
+     */
+    public function currId($seqName)
+    {
+        $this->warnings[] = 'database does not support getting current
+            sequence value, the sequence value was incremented';
+        return $this->nextId($seqName);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Mysql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,112 @@
+<?php
+/*
+ *  $Id: Mysql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Sequence_Mysql
+ *
+ * @package     Doctrine
+ * @subpackage  Sequence
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Sequence_Mysql extends Doctrine_Sequence
+{
+    /**
+     * Returns the next free id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     * @param bool              when true missing sequences are automatic created
+     *
+     * @return integer          next id in the given sequence
+     */
+    public function nextId($seqName, $onDemand = true)
+    {
+        $sequenceName  = $this->conn->quoteIdentifier($seqName, true);
+        $seqcolName    = $this->conn->quoteIdentifier($this->conn->getAttribute(Doctrine::ATTR_SEQCOL_NAME), true);
+        $query         = 'INSERT INTO ' . $sequenceName . ' (' . $seqcolName . ') VALUES (NULL)';
+        
+        try {
+
+            $this->conn->exec($query);
+
+        } catch(Doctrine_Connection_Exception $e) {
+            if ($onDemand && $e->getPortableCode() == Doctrine::ERR_NOSUCHTABLE) {
+                // Since we are creating the sequence on demand
+                // we know the first id = 1 so initialize the
+                // sequence at 2
+                try {
+                    $result = $this->conn->export->createSequence($seqName, 2);
+                } catch(Doctrine_Exception $e) {
+                    throw new Doctrine_Sequence_Exception('on demand sequence ' . $seqName . ' could not be created');
+                }
+                // First ID of a newly created sequence is 1
+                return 1;
+            }
+            throw $e;
+        }
+
+        $value = $this->lastInsertId();
+
+        if (is_numeric($value)) {
+            $query = 'DELETE FROM ' . $sequenceName . ' WHERE ' . $seqcolName . ' < ' . $value;
+            $this->conn->exec($query);
+            /**
+            TODO: is the following needed ?
+            if (PEAR::isError($result)) {
+                $this->warnings[] = 'nextID: could not delete previous sequence table values from '.$seq_name;
+            }
+            */
+        }
+        return $value;
+    }
+
+    /**
+     * Returns the autoincrement ID if supported or $id or fetches the current
+     * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
+     *
+     * @param string  name of the table into which a new row was inserted
+     * @param string  name of the field into which a new row was inserted
+     * @return integer|boolean
+     */
+    public function lastInsertId($table = null, $field = null)
+    {
+        return $this->conn->getDbh()->lastInsertId();
+    }
+
+    /**
+     * Returns the current id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     *
+     * @return integer          current id in the given sequence
+     */
+    public function currId($seqName)
+    {
+        $sequenceName   = $this->conn->quoteIdentifier($seqName, true);
+        $seqcolName     = $this->conn->quoteIdentifier($this->conn->getAttribute(Doctrine::ATTR_SEQCOL_NAME), true);
+        $query          = 'SELECT MAX(' . $seqcolName . ') FROM ' . $sequenceName;
+
+        return (int) $this->conn->fetchOne($query);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Oracle.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,96 @@
+<?php
+/*
+ *  $Id: Oracle.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Sequence_Oracle
+ *
+ * @package     Doctrine
+ * @subpackage  Sequence
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Sequence_Oracle extends Doctrine_Sequence
+{
+    /**
+     * Returns the next free id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     * @param bool onDemand     when true missing sequences are automatic created
+     *
+     * @return integer          next id in the given sequence
+     */
+    public function nextID($seqName, $onDemand = true)
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+        $query        = 'SELECT ' . $sequenceName . '.nextval FROM DUAL';
+
+        try {
+            $result = $this->conn->fetchOne($query);
+        } catch(Doctrine_Connection_Exception $e) {
+            if ($onDemand && $e->getPortableCode() == Doctrine::ERR_NOSUCHTABLE) {
+
+                try {
+                    $result = $this->conn->export->createSequence($seqName);
+                } catch(Doctrine_Exception $e) {
+                    throw new Doctrine_Sequence_Exception('on demand sequence ' . $seqName . ' could not be created');
+                }
+                return $this->nextId($seqName, false);
+            }
+            throw $e;
+        }
+        return $result;
+    }
+
+    /**
+     * Returns the autoincrement ID if supported or $id or fetches the current
+     * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
+     *
+     * @param   string  name of the table into which a new row was inserted
+     * @param   string  name of the field into which a new row was inserted
+     */
+    public function lastInsertID($table = null, $field = null)
+    {
+        $seqName = $table . (empty($field) ? '' : '_'.$field);
+        $sequenceName =  $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+
+        return $this->conn->fetchOne('SELECT ' . $sequenceName . '.currval FROM DUAL');
+    }
+
+    /**
+     * Returns the current id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     *
+     * @return integer          current id in the given sequence
+     */
+    public function currID($seqName)
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+        $query   = 'SELECT (last_number-1) FROM user_sequences';
+        $query  .= ' WHERE sequence_name=' . $this->conn->quote($sequenceName, 'text');
+        $query  .= ' OR sequence_name=' . $this->conn->quote(strtoupper($sequenceName), 'text');
+
+        return $this->conn->fetchOne($query);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Pgsql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,94 @@
+<?php
+/*
+ *  $Id: Pgsql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Sequence_Pgsql
+ *
+ * @package     Doctrine
+ * @subpackage  Sequence
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Sequence_Pgsql extends Doctrine_Sequence
+{
+    /**
+     * Returns the next free id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     * @param bool onDemand     when true missing sequences are automatic created
+     *
+     * @return integer          next id in the given sequence
+     */
+    public function nextId($seqName, $onDemand = true)
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+
+        $query = "SELECT NEXTVAL('" . $sequenceName . "')";
+        try {
+            $result = (int) $this->conn->fetchOne($query);
+        } catch(Doctrine_Connection_Exception $e) {
+            if ($onDemand && $e->getPortableCode() == Doctrine::ERR_NOSUCHTABLE) {
+
+                try {
+                    $result = $this->conn->export->createSequence($seqName);
+                } catch(Doctrine_Exception $e) {
+                    throw new Doctrine_Sequence_Exception('on demand sequence ' . $seqName . ' could not be created');
+                }
+                return $this->nextId($seqName, false);
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * lastInsertId
+     *
+     * Returns the autoincrement ID if supported or $id or fetches the current
+     * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
+     *
+     * @param   string  name of the table into which a new row was inserted
+     * @param   string  name of the field into which a new row was inserted
+     * @return integer      the autoincremented id
+     */
+    public function lastInsertId($table = null, $field = null)
+    {
+        $seqName = $table . (empty($field) ? '' : '_' . $field);
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+
+        return (int) $this->conn->fetchOne("SELECT CURRVAL('" . $sequenceName . "')");
+    }
+
+    /**
+     * Returns the current id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     *
+     * @return integer          current id in the given sequence
+     */
+    public function currId($seqName)
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+        return (int) $this->conn->fetchOne('SELECT last_value FROM ' . $sequenceName);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Sequence/Sqlite.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,114 @@
+<?php
+/*
+ *  $Id: Sqlite.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Sequence_Sqlite
+ *
+ * @package     Doctrine
+ * @subpackage  Sequence
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Sequence_Sqlite extends Doctrine_Sequence
+{
+    /**
+     * Returns the next free id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     * @param bool $onDemand    when true missing sequences are automatic created
+     *
+     * @return integer          next id in the given sequence
+     */
+    public function nextId($seqName, $onDemand = true)
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+        $seqcolName   = $this->conn->quoteIdentifier($this->conn->getAttribute(Doctrine::ATTR_SEQCOL_NAME), true);
+
+        $query        = 'INSERT INTO ' . $sequenceName . ' (' . $seqcolName . ') VALUES (NULL)';
+
+        try {
+
+            $this->conn->exec($query);
+
+        } catch(Doctrine_Connection_Exception $e) {
+            if ($onDemand && $e->getPortableCode() == Doctrine::ERR_NOSUCHTABLE) {
+                // Since we are creating the sequence on demand
+                // we know the first id = 1 so initialize the
+                // sequence at 2
+
+                try {
+                    $result = $this->conn->export->createSequence($seqName, 2);
+                } catch(Doctrine_Exception $e) {
+                    throw new Doctrine_Sequence_Exception('on demand sequence ' . $seqName . ' could not be created');
+                }
+                // First ID of a newly created sequence is 1
+                return 1;
+            }
+            throw $e;
+        }
+
+        $value = $this->conn->getDbh()->lastInsertId();
+
+        if (is_numeric($value)) {
+            $query = 'DELETE FROM ' . $sequenceName . ' WHERE ' . $seqcolName . ' < ' . $value;
+            
+            $this->conn->exec($query);
+            /**
+            TODO: is the following needed ?
+            $this->warnings[] = 'nextID: could not delete previous sequence table values from '.$seq_name;
+            */
+        }
+        return $value;
+    }
+
+    /**
+     * Returns the autoincrement ID if supported or $id or fetches the current
+     * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
+     *
+     * @param   string  name of the table into which a new row was inserted
+     * @param   string  name of the field into which a new row was inserted
+     * @return integer|boolean
+     */
+    public function lastInsertId($table = null, $field = null)
+    {
+        return $this->conn->getDbh()->lastInsertId();
+    }
+
+    /**
+     * Returns the current id of a sequence
+     *
+     * @param string $seqName   name of the sequence
+     *
+     * @return integer          current id in the given sequence
+     */
+    public function currId($seqName)
+    {
+        $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
+        $seqcolName   = $this->conn->quoteIdentifier($this->conn->getAttribute(Doctrine::ATTR_SEQCOL_NAME), true);
+
+        $query        = 'SELECT MAX(' . $seqcolName . ') FROM ' . $sequenceName;
+
+        return (int) $this->conn->fetchOne($query);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Table.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,2313 @@
+<?php
+/*
+ *  $Id: Table.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Table   represents a database table
+ *                  each Doctrine_Table holds the information of foreignKeys and associations
+ *
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @package     Doctrine
+ * @subpackage  Table
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Table extends Doctrine_Configurable implements Countable
+{
+    /**
+     * @var array $data                                 temporary data which is then loaded into Doctrine_Record::$_data
+     */
+    protected $_data             = array();
+
+    /**
+     * @var mixed $identifier   The field names of all fields that are part of the identifier/primary key
+     */
+    protected $_identifier = array();
+
+    /**
+     * @see Doctrine_Identifier constants
+     * @var integer $identifierType                     the type of identifier this table uses
+     */
+    protected $_identifierType;
+
+    /**
+     * @var Doctrine_Connection $conn                   Doctrine_Connection object that created this table
+     */
+    protected $_conn;
+
+    /**
+     * @var array $identityMap                          first level cache
+     */
+    protected $_identityMap        = array();
+
+    /**
+     * @var Doctrine_Table_Repository $repository       record repository
+     */
+    protected $_repository;
+
+    /**
+     * @var array $columns                  an array of column definitions,
+     *                                      keys are column names and values are column definitions
+     *
+     *                                      the definition array has atleast the following values:
+     *
+     *                                      -- type         the column type, eg. 'integer'
+     *                                      -- length       the column length, eg. 11
+     *
+     *                                      additional keys:
+     *                                      -- notnull      whether or not the column is marked as notnull
+     *                                      -- values       enum values
+     *                                      -- notblank     notblank validator + notnull constraint
+     *                                      ... many more
+     */
+    protected $_columns          = array();
+
+    /**
+     * @var array $_fieldNames            an array of field names. used to look up field names
+     *                                    from column names.
+     *                                    keys are column names and values are field names
+     */
+    protected $_fieldNames    = array();
+
+    /**
+     *
+     * @var array $_columnNames             an array of column names
+     *                                      keys are field names and values column names.
+     *                                      used to look up column names from field names.
+     *                                      this is the reverse lookup map of $_fieldNames.
+     */
+    protected $_columnNames = array();
+
+    /**
+     * @var integer $columnCount            cached column count, Doctrine_Record uses this column count in when
+     *                                      determining its state
+     */
+    protected $columnCount;
+
+    /**
+     * @var boolean $hasDefaultValues       whether or not this table has default values
+     */
+    protected $hasDefaultValues;
+
+    /**
+     * @var array $options                  an array containing all options
+     *
+     *      -- name                         name of the component, for example component name of the GroupTable is 'Group'
+     *
+     *      -- parents                      the parent classes of this component
+     *
+     *      -- declaringClass               name of the table definition declaring class (when using inheritance the class
+     *                                      that defines the table structure can be any class in the inheritance hierarchy,
+     *                                      hence we need reflection to check out which class actually calls setTableDefinition)
+     *
+     *      -- tableName                    database table name, in most cases this is the same as component name but in some cases
+     *                                      where one-table-multi-class inheritance is used this will be the name of the inherited table
+     *
+     *      -- sequenceName                 Some databases need sequences instead of auto incrementation primary keys,
+     *                                      you can set specific sequence for your table by calling setOption('sequenceName', $seqName)
+     *                                      where $seqName is the name of the desired sequence
+     *
+     *      -- enumMap                      enum value arrays
+     *
+     *      -- inheritanceMap               inheritanceMap is used for inheritance mapping, keys representing columns and values
+     *                                      the column values that should correspond to child classes
+     *
+     *      -- type                         table type (mysql example: INNODB)
+     *
+     *      -- charset                      character set
+     *
+     *      -- foreignKeys                  the foreign keys of this table
+     *
+     *      -- checks                       the check constraints of this table, eg. 'price > dicounted_price'
+     *
+     *      -- collate                      collate attribute
+     *
+     *      -- indexes                      the index definitions of this table
+     *
+     *      -- treeImpl                     the tree implementation of this table (if any)
+     *
+     *      -- treeOptions                  the tree options
+     *
+     *      -- queryParts                   the bound query parts
+     *
+     *      -- versioning
+     */
+    protected $_options      = array('name'           => null,
+                                     'tableName'      => null,
+                                     'sequenceName'   => null,
+                                     'inheritanceMap' => array(),
+                                     'enumMap'        => array(),
+                                     'type'           => null,
+                                     'charset'        => null,
+                                     'collate'        => null,
+                                     'treeImpl'       => null,
+                                     'treeOptions'    => array(),
+                                     'indexes'        => array(),
+                                     'parents'        => array(),
+                                     'joinedParents'  => array(),
+                                     'queryParts'     => array(),
+                                     'versioning'     => null,
+                                     'subclasses'     => array(),
+                                     );
+
+    /**
+     * @var Doctrine_Tree $tree                 tree object associated with this table
+     */
+    protected $_tree;
+
+    /**
+     * @var Doctrine_Relation_Parser $_parser   relation parser object
+     */
+    protected $_parser;
+
+    /**
+     * @see Doctrine_Template
+     * @var array $_templates                   an array containing all templates attached to this table
+     */
+    protected $_templates   = array();
+
+    /**
+     * @see Doctrine_Record_Filter
+     * @var array $_filters                     an array containing all record filters attached to this table
+     */
+    protected $_filters     = array();
+
+    /**
+     * @see Doctrine_Record_Generator
+     * @var array $_generators                  an array containing all generators attached to this table
+     */
+    protected $_generators     = array();
+
+    /**
+     * @var array $_invokedMethods              method invoker cache
+     */
+    protected $_invokedMethods = array();
+
+    /**
+     * @var Doctrine_Record $record             empty instance of the given model
+     */
+    protected $record;
+
+    /**
+     * the constructor
+     *
+     * @throws Doctrine_Connection_Exception    if there are no opened connections
+     * @param string $name                      the name of the component
+     * @param Doctrine_Connection $conn         the connection associated with this table
+     */
+    public function __construct($name, Doctrine_Connection $conn, $initDefinition = false)
+    {
+        $this->_conn = $conn;
+
+        $this->setParent($this->_conn);
+
+        $this->_options['name'] = $name;
+        $this->_parser = new Doctrine_Relation_Parser($this);
+
+        if ($initDefinition) {
+            $this->record = $this->initDefinition();
+
+            $this->initIdentifier();
+
+            $this->record->setUp();
+
+            // if tree, set up tree
+            if ($this->isTree()) {
+                $this->getTree()->setUp();
+            }
+        } else {
+            if ( ! isset($this->_options['tableName'])) {
+                $this->setTableName(Doctrine_Inflector::tableize($this->_options['name']));
+            }
+        }
+        $this->_filters[]  = new Doctrine_Record_Filter_Standard();
+        $this->_repository = new Doctrine_Table_Repository($this);
+        
+        $this->construct();
+    }
+    
+    /**
+     * construct
+     * Empty template method to provide concrete Table classes with the possibility
+     * to hook into the constructor procedure
+     *
+     * @return void
+     */
+    public function construct()
+    { }
+
+    /**
+     * Initializes the in-memory table definition.
+     *
+     * @param string $name
+     */
+    public function initDefinition()
+    {
+        $name = $this->_options['name'];
+        if ( ! class_exists($name) || empty($name)) {
+            throw new Doctrine_Exception("Couldn't find class " . $name);
+        }
+        $record = new $name($this);
+
+        $names = array();
+
+        $class = $name;
+
+        // get parent classes
+
+        do {
+            if ($class === 'Doctrine_Record') {
+                break;
+            }
+
+            $name = $class;
+            $names[] = $name;
+        } while ($class = get_parent_class($class));
+
+        if ($class === false) {
+            throw new Doctrine_Table_Exception('Class "' . $name . '" must be a child class of Doctrine_Record');
+        }
+
+        // reverse names
+        $names = array_reverse($names);
+        // save parents
+        array_pop($names);
+        $this->_options['parents'] = $names;
+
+        // create database table
+        if (method_exists($record, 'setTableDefinition')) {
+            $record->setTableDefinition();
+            // get the declaring class of setTableDefinition method
+            $method = new ReflectionMethod($this->_options['name'], 'setTableDefinition');
+            $class = $method->getDeclaringClass();
+
+        } else {
+            $class = new ReflectionClass($class);
+        }
+
+        $this->_options['joinedParents'] = array();
+
+        foreach (array_reverse($this->_options['parents']) as $parent) {
+
+            if ($parent === $class->getName()) {
+                continue;
+            }
+            $ref = new ReflectionClass($parent);
+
+            if ($ref->isAbstract() || ! $class->isSubClassOf($parent)) {
+                continue;
+            }
+            $parentTable = $this->_conn->getTable($parent);
+
+            $found = false;
+            $parentColumns = $parentTable->getColumns();
+
+            foreach ($parentColumns as $columnName => $definition) {
+                if ( ! isset($definition['primary']) || $definition['primary'] === false) {
+                    if (isset($this->_columns[$columnName])) {
+                        $found = true;
+                        break;
+                    } else {
+                        if ( ! isset($parentColumns[$columnName]['owner'])) {
+                            $parentColumns[$columnName]['owner'] = $parentTable->getComponentName();
+                        }
+
+                        $this->_options['joinedParents'][] = $parentColumns[$columnName]['owner'];
+                    }
+                } else {
+                    unset($parentColumns[$columnName]);
+                }
+            }
+
+            if ($found) {
+                continue;
+            }
+
+            foreach ($parentColumns as $columnName => $definition) {
+                $fullName = $columnName . ' as ' . $parentTable->getFieldName($columnName);
+                $this->setColumn($fullName, $definition['type'], $definition['length'], $definition, true);
+            }
+
+            break;
+        }
+
+        $this->_options['joinedParents'] = array_values(array_unique($this->_options['joinedParents']));
+
+        $this->_options['declaringClass'] = $class;
+
+        // set the table definition for the given tree implementation
+        if ($this->isTree()) {
+            $this->getTree()->setTableDefinition();
+        }
+
+        $this->columnCount = count($this->_columns);
+
+        if ( ! isset($this->_options['tableName'])) {
+            $this->setTableName(Doctrine_Inflector::tableize($class->getName()));
+        }
+
+        return $record;
+    }
+
+    /**
+     * Initializes the table identifier(s)/primary key(s)
+     *
+     * @return void
+     */
+    public function initIdentifier()
+    {
+        switch (count($this->_identifier)) {
+            case 0:
+                if ( ! empty($this->_options['joinedParents'])) {
+                    $root = current($this->_options['joinedParents']);
+
+                    $table = $this->_conn->getTable($root);
+
+                    $this->_identifier = $table->getIdentifier();
+
+                    $this->_identifierType = ($table->getIdentifierType() !== Doctrine::IDENTIFIER_AUTOINC)
+                                            ? $table->getIdentifierType() : Doctrine::IDENTIFIER_NATURAL;
+
+                    // add all inherited primary keys
+                    foreach ((array) $this->_identifier as $id) {
+                        $definition = $table->getDefinitionOf($id);
+
+                        // inherited primary keys shouldn't contain autoinc
+                        // and sequence definitions
+                        unset($definition['autoincrement']);
+                        unset($definition['sequence']);
+
+                        // add the inherited primary key column
+                        $fullName = $id . ' as ' . $table->getFieldName($id);
+                        $this->setColumn($fullName, $definition['type'], $definition['length'],
+                                $definition, true);
+                    }
+                } else {
+                    $definition = array('type' => 'integer',
+                                        'length' => 20,
+                                        'autoincrement' => true,
+                                        'primary' => true);
+                    $this->setColumn('id', $definition['type'], $definition['length'], $definition, true);
+                    $this->_identifier = 'id';
+                    $this->_identifierType = Doctrine::IDENTIFIER_AUTOINC;
+                }
+                $this->columnCount++;
+                break;
+            case 1:
+                foreach ($this->_identifier as $pk) {
+                    $e = $this->getDefinitionOf($pk);
+
+                    $found = false;
+
+                    foreach ($e as $option => $value) {
+                        if ($found) {
+                            break;
+                        }
+
+                        $e2 = explode(':', $option);
+
+                        switch (strtolower($e2[0])) {
+                            case 'autoincrement':
+                            case 'autoinc':
+                                if ($value !== false) {
+                                    $this->_identifierType = Doctrine::IDENTIFIER_AUTOINC;
+                                    $found = true;
+                                }
+                                break;
+                            case 'seq':
+                            case 'sequence':
+                                $this->_identifierType = Doctrine::IDENTIFIER_SEQUENCE;
+                                $found = true;
+
+                                if (is_string($value)) {
+                                    $this->_options['sequenceName'] = $value;
+                                } else {
+                                    if (($sequence = $this->getAttribute(Doctrine::ATTR_DEFAULT_SEQUENCE)) !== null) {
+                                        $this->_options['sequenceName'] = $sequence;
+                                    } else {
+                                        $this->_options['sequenceName'] = $this->_conn->formatter->getSequenceName($this->_options['tableName']);
+                                    }
+                                }
+                                break;
+                        }
+                    }
+                    if ( ! isset($this->_identifierType)) {
+                        $this->_identifierType = Doctrine::IDENTIFIER_NATURAL;
+                    }
+                }
+
+                $this->_identifier = $pk;
+
+                break;
+            default:
+                $this->_identifierType = Doctrine::IDENTIFIER_COMPOSITE;
+        }
+    }
+
+    /**
+     * Gets the owner of a column.
+     * The owner of a column is the name of the component in a hierarchy that
+     * defines the column.
+     *
+     * @param string $columnName   The column name
+     * @return string  The name of the owning/defining component
+     */
+    public function getColumnOwner($columnName)
+    {
+        if (isset($this->_columns[$columnName]['owner'])) {
+            return $this->_columns[$columnName]['owner'];
+        } else {
+            return $this->getComponentName();
+        }
+    }
+
+    /**
+     * Gets the record instance for this table. The Doctrine_Table instance always holds at least one
+     * instance of a model so that it can be reused for several things, but primarily it is first
+     * used to instantiate all the internal in memory meta data
+     *
+     * @return object  Empty instance of the record
+     */
+    public function getRecordInstance()
+    {
+        if ( ! $this->record) {
+            $this->record = new $this->_options['name'];
+        }
+        return $this->record;
+    }
+
+    /**
+     * Checks whether a column is inherited from a component further up in the hierarchy.
+     *
+     * @param $columnName  The column name
+     * @return boolean  TRUE if column is inherited, FALSE otherwise.
+     */
+    public function isInheritedColumn($columnName)
+    {
+        return (isset($this->_columns[$columnName]['owner']));
+    }
+
+    /**
+     * Checks whether a field is part of the table identifier/primary key field(s).
+     *
+     * @param string $fieldName  The field name
+     * @return boolean  TRUE if the field is part of the table identifier/primary key field(s),
+     *                  FALSE otherwise.
+     */
+    public function isIdentifier($fieldName)
+    {
+        return ($fieldName === $this->getIdentifier() ||
+                in_array($fieldName, (array) $this->getIdentifier()));
+    }
+
+    /**
+     * Checks whether a field identifier is of type autoincrement
+     *
+     * @return boolean TRUE  if the identifier is autoincrement
+     *                 FALSE otherwise
+     */
+    public function isIdentifierAutoincrement()
+    {
+        return $this->getIdentifierType() === Doctrine::IDENTIFIER_AUTOINC;
+    }
+
+    /**
+     * Checks whether a field identifier is a composite key.
+     *
+     * @return boolean TRUE  if the identifier is a composite key,
+     *                 FALSE otherwise
+     */
+    public function isIdentifierComposite()
+    {
+        return $this->getIdentifierType() === Doctrine::IDENTIFIER_COMPOSITE;
+    }
+
+    /**
+     * getMethodOwner
+     *
+     * @param string $method
+     * @return void
+     */
+    public function getMethodOwner($method)
+    {
+        return (isset($this->_invokedMethods[$method])) ?
+                      $this->_invokedMethods[$method] : false;
+    }
+
+    /**
+     * setMethodOwner
+     *
+     * @param string $method
+     * @param string $class
+     */
+    public function setMethodOwner($method, $class)
+    {
+        $this->_invokedMethods[$method] = $class;
+    }
+
+    /**
+     * export
+     * exports this table to database based on column and option definitions
+     *
+     * @throws Doctrine_Connection_Exception    if some error other than Doctrine::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 export()
+    {
+        $this->_conn->export->exportTable($this);
+    }
+
+    /**
+     * getExportableFormat
+     * returns exportable presentation of this object
+     *
+     * @return array
+     */
+    public function getExportableFormat($parseForeignKeys = true)
+    {
+        $columns = array();
+        $primary = array();
+
+        foreach ($this->getColumns() as $name => $definition) {
+
+            if (isset($definition['owner'])) {
+                continue;
+            }
+
+            switch ($definition['type']) {
+                case 'boolean':
+                    if (isset($definition['default'])) {
+                        $definition['default'] = $this->getConnection()->convertBooleans($definition['default']);
+                    }
+                    break;
+            }
+            $columns[$name] = $definition;
+
+            if (isset($definition['primary']) && $definition['primary']) {
+                $primary[] = $name;
+            }
+        }
+
+        $options['foreignKeys'] = isset($this->_options['foreignKeys']) ?
+                $this->_options['foreignKeys'] : array();
+
+        if ($parseForeignKeys && $this->getAttribute(Doctrine::ATTR_EXPORT)
+                & Doctrine::EXPORT_CONSTRAINTS) {
+
+            $constraints = array();
+
+            $emptyIntegrity = array('onUpdate' => null,
+                                    'onDelete' => null);
+
+            foreach ($this->getRelations() as $name => $relation) {
+                $fk = $relation->toArray();
+                $fk['foreignTable'] = $relation->getTable()->getTableName();
+
+                if ($relation->getTable() === $this && in_array($relation->getLocal(), $primary)) {
+                    if ($relation->hasConstraint()) {
+                        throw new Doctrine_Table_Exception("Badly constructed integrity constraints. Cannot define constraint of different fields in the same table.");
+                    }
+                    continue;
+                }
+
+                $integrity = array('onUpdate' => $fk['onUpdate'],
+                                   'onDelete' => $fk['onDelete']);
+
+                if ($relation instanceof Doctrine_Relation_LocalKey) {
+                    $def = array('local'        => $relation->getLocalColumnName(),
+                                 'foreign'      => $relation->getForeignColumnName(),
+                                 'foreignTable' => $relation->getTable()->getTableName());
+
+                    if (($key = array_search($def, $options['foreignKeys'])) === false) {
+                        $options['foreignKeys'][] = $def;
+                        if ($integrity !== $emptyIntegrity) {
+                            $constraints[] = $integrity;
+                        }
+                    } else {
+                        if ($integrity !== $emptyIntegrity) {
+                            $constraints[$key] = $integrity;
+                        }
+                    }
+                }
+            }
+
+            foreach ($constraints as $k => $def) {
+                $options['foreignKeys'][$k] = array_merge($options['foreignKeys'][$k], $def);
+            }
+        }
+
+        $options['primary'] = $primary;
+
+        return array('tableName' => $this->getOption('tableName'),
+                     'columns'   => $columns,
+                     'options'   => array_merge($this->getOptions(), $options));
+    }
+
+    /**
+     * getRelationParser
+     * return the relation parser associated with this table
+     *
+     * @return Doctrine_Relation_Parser     relation parser object
+     */
+    public function getRelationParser()
+    {
+        return $this->_parser;
+    }
+
+    /**
+     * __get
+     * an alias for getOption
+     *
+     * @param string $option
+     */
+    public function __get($option)
+    {
+        if (isset($this->_options[$option])) {
+            return $this->_options[$option];
+        }
+        return null;
+    }
+
+    /**
+     * __isset
+     *
+     * @param string $option
+     */
+    public function __isset($option)
+    {
+        return isset($this->_options[$option]);
+    }
+
+    /**
+     * getOptions
+     * returns all options of this table and the associated values
+     *
+     * @return array    all options and their values
+     */
+    public function getOptions()
+    {
+        return $this->_options;
+    }
+
+    /**
+     * setOptions
+     *
+     * @param string $options
+     * @return void
+     */
+    public function setOptions($options)
+    {
+        foreach ($options as $key => $value) {
+            $this->setOption($key, $value);
+        }
+    }
+
+    /**
+     * addForeignKey
+     *
+     * adds a foreignKey to this table
+     *
+     * @return void
+     */
+    public function addForeignKey(array $definition)
+    {
+        $this->_options['foreignKeys'][] = $definition;
+    }
+
+    /**
+     * addCheckConstraint
+     *
+     * adds a check constraint to this table
+     *
+     * @return void
+     */
+    public function addCheckConstraint($definition, $name)
+    {
+        if (is_string($name)) {
+            $this->_options['checks'][$name] = $definition;
+        } else {
+            $this->_options['checks'][] = $definition;
+        }
+
+        return $this;
+    }
+
+    /**
+     * addIndex
+     *
+     * adds an index to this table
+     *
+     * @return void
+     */
+    public function addIndex($index, array $definition)
+    {
+        if (isset($definition['fields'])) {
+	        foreach ((array) $definition['fields'] as $key => $field) {
+		        if (is_numeric($key)) {
+                    $definition['fields'][$key] = $this->getColumnName($field);
+                } else {
+                    $columnName = $this->getColumnName($key);
+
+                    unset($definition['fields'][$key]);
+
+                    $definition['fields'][$columnName] = $field;
+                }
+            }
+        }
+
+        $this->_options['indexes'][$index] = $definition;
+    }
+
+    /**
+     * getIndex
+     *
+     * @return array|boolean        array on success, FALSE on failure
+     */
+    public function getIndex($index)
+    {
+        if (isset($this->_options['indexes'][$index])) {
+            return $this->_options['indexes'][$index];
+        }
+
+        return false;
+    }
+
+    /**
+     * DESCRIBE WHAT THIS METHOD DOES, PLEASE!
+     *
+     * @todo Name proposal: addRelation
+     */
+    public function bind($args, $type)
+    {
+        $options = ( ! isset($args[1])) ? array() : $args[1];
+        $options['type'] = $type;
+
+        $this->_parser->bind($args[0], $options);
+    }
+
+    /**
+     * hasRelation
+     *
+     * @param string $alias      the relation to check if exists
+     * @return boolean           true if the relation exists otherwise false
+     */
+    public function hasRelation($alias)
+    {
+        return $this->_parser->hasRelation($alias);
+    }
+
+    /**
+     * getRelation
+     *
+     * @param string $alias      relation alias
+     */
+    public function getRelation($alias, $recursive = true)
+    {
+        return $this->_parser->getRelation($alias, $recursive);
+    }
+
+    /**
+     * getRelations
+     * returns an array containing all relation objects
+     *
+     * @return array        an array of Doctrine_Relation objects
+     */
+    public function getRelations()
+    {
+        return $this->_parser->getRelations();
+    }
+
+    /**
+     * createQuery
+     * creates a new Doctrine_Query object and adds the component name
+     * of this table as the query 'from' part
+     *
+     * @param string Optional alias name for component aliasing.
+     *
+     * @return Doctrine_Query
+     */
+    public function createQuery($alias = '')
+    {
+        if ( ! empty($alias)) {
+            $alias = ' ' . trim($alias);
+        }
+        return Doctrine_Query::create($this->_conn)->from($this->getComponentName() . $alias);
+    }
+
+    /**
+     * getRepository
+     *
+     * @return Doctrine_Table_Repository
+     */
+    public function getRepository()
+    {
+        return $this->_repository;
+    }
+
+    /**
+     * setOption
+     * sets an option and returns this object in order to
+     * allow flexible method chaining
+     *
+     * @see Doctrine_Table::$_options   for available options
+     * @param string $name              the name of the option to set
+     * @param mixed $value              the value of the option
+     * @return Doctrine_Table           this object
+     */
+    public function setOption($name, $value)
+    {
+        switch ($name) {
+            case 'name':
+            case 'tableName':
+                break;
+            case 'enumMap':
+            case 'inheritanceMap':
+            case 'index':
+            case 'treeOptions':
+                if ( ! is_array($value)) {
+                throw new Doctrine_Table_Exception($name . ' should be an array.');
+                }
+                break;
+        }
+        $this->_options[$name] = $value;
+    }
+
+    /**
+     * getOption
+     * returns the value of given option
+     *
+     * @param string $name  the name of the option
+     * @return mixed        the value of given option
+     */
+    public function getOption($name)
+    {
+        if (isset($this->_options[$name])) {
+            return $this->_options[$name];
+        }
+        return null;
+    }
+
+    /**
+     * getColumnName
+     *
+     * returns a column name for column alias
+     * if the actual name for the alias cannot be found
+     * this method returns the given alias
+     *
+     * @param string $alias         column alias
+     * @return string               column name
+     */
+    public function getColumnName($fieldName)
+    {
+        // FIX ME: This is being used in places where an array is passed, but it should not be an array
+        // For example in places where Doctrine should support composite foreign/primary keys
+        $fieldName = is_array($fieldName) ? $fieldName[0]:$fieldName;
+
+        if (isset($this->_columnNames[$fieldName])) {
+            return $this->_columnNames[$fieldName];
+        }
+
+        return strtolower($fieldName);
+    }
+
+    /**
+     * getColumnDefinition
+     *
+     * @param string $columnName
+     * @return void
+     */
+    public function getColumnDefinition($columnName)
+    {
+        if ( ! isset($this->_columns[$columnName])) {
+            return false;
+        }
+        return $this->_columns[$columnName];
+    }
+
+    /**
+     * getColumnAlias
+     *
+     * returns a column alias for a column name
+     * if no alias can be found the column name is returned.
+     *
+     * @param string $columnName    column name
+     * @return string               column alias
+     */
+    public function getFieldName($columnName)
+    {
+        if (isset($this->_fieldNames[$columnName])) {
+            return $this->_fieldNames[$columnName];
+        }
+        return $columnName;
+    }
+    public function setColumns(array $definitions)
+    {
+        foreach ($definitions as $name => $options) {
+            $this->setColumn($name, $options['type'], $options['length'], $options);
+        }
+    }
+    /**
+     * setColumn
+     *
+     * @param string $name
+     * @param string $type
+     * @param integer $length
+     * @param mixed $options
+     * @param boolean $prepend   Whether to prepend or append the new column to the column list.
+     *                           By default the column gets appended.
+     * @throws Doctrine_Table_Exception     if trying use wrongly typed parameter
+     * @return void
+     */
+    public function setColumn($name, $type, $length = null, $options = array(), $prepend = false)
+    {
+        if (is_string($options)) {
+            $options = explode('|', $options);
+        }
+
+        foreach ($options as $k => $option) {
+            if (is_numeric($k)) {
+                if ( ! empty($option)) {
+                    $options[$option] = true;
+                }
+                unset($options[$k]);
+            }
+        }
+
+        // extract column name & field name
+        if (stripos($name, ' as '))
+        {
+            if (strpos($name, ' as')) {
+                $parts = explode(' as ', $name);
+            } else {
+                $parts = explode(' AS ', $name);
+            }
+
+            if (count($parts) > 1) {
+                $fieldName = $parts[1];
+            } else {
+                $fieldName = $parts[0];
+            }
+
+            $name = strtolower($parts[0]);
+        } else {
+            $fieldName = $name;
+            $name = strtolower($name);
+        }
+
+        $name = trim($name);
+        $fieldName = trim($fieldName);
+
+        if ($prepend) {
+            $this->_columnNames = array_merge(array($fieldName => $name), $this->_columnNames);
+            $this->_fieldNames = array_merge(array($name => $fieldName), $this->_fieldNames);
+        } else {
+            $this->_columnNames[$fieldName] = $name;
+            $this->_fieldNames[$name] = $fieldName;
+        }
+
+        if ($length == null) {
+            switch ($type) {
+                case 'decimal':
+                    $length = 18;
+                break;
+                case 'string':
+                case 'clob':
+                case 'float':
+                case 'integer':
+                case 'array':
+                case 'object':
+                case 'blob':
+                case 'gzip':
+                    // use php int max
+                    $length = 2147483647;
+                break;
+                case 'boolean':
+                    $length = 1;
+                case 'date':
+                    // YYYY-MM-DD ISO 8601
+                    $length = 10;
+                case 'time':
+                    // HH:NN:SS+00:00 ISO 8601
+                    $length = 14;
+                case 'timestamp':
+                    // YYYY-MM-DDTHH:MM:SS+00:00 ISO 8601
+                    $length = 25;
+                break;
+            }
+        }
+
+        $options['type'] = $type;
+        $options['length'] = $length;
+
+        if ($prepend) {
+            $this->_columns = array_merge(array($name => $options), $this->_columns);
+        } else {
+            $this->_columns[$name] = $options;
+        }
+
+        if (isset($options['primary']) && $options['primary']) {
+            if (isset($this->_identifier)) {
+                $this->_identifier = (array) $this->_identifier;
+            }
+            if ( ! in_array($fieldName, $this->_identifier)) {
+                $this->_identifier[] = $fieldName;
+            }
+        }
+        if (isset($options['default'])) {
+            $this->hasDefaultValues = true;
+        }
+    }
+
+    /**
+     * hasDefaultValues
+     * returns true if this table has default values, otherwise false
+     *
+     * @return boolean
+     */
+    public function hasDefaultValues()
+    {
+        return $this->hasDefaultValues;
+    }
+
+    /**
+     * getDefaultValueOf
+     * returns the default value(if any) for given column
+     *
+     * @param string $fieldName
+     * @return mixed
+     */
+    public function getDefaultValueOf($fieldName)
+    {
+        $columnName = $this->getColumnName($fieldName);
+        if ( ! isset($this->_columns[$columnName])) {
+            throw new Doctrine_Table_Exception("Couldn't get default value. Column ".$columnName." doesn't exist.");
+        }
+        if (isset($this->_columns[$columnName]['default'])) {
+            return $this->_columns[$columnName]['default'];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getIdentifier()
+    {
+        return $this->_identifier;
+    }
+
+    /**
+     * @return integer
+     */
+    public function getIdentifierType()
+    {
+        return $this->_identifierType;
+    }
+
+    /**
+     * hasColumn
+     * @return boolean
+     */
+    public function hasColumn($columnName)
+    {
+        return isset($this->_columns[strtolower($columnName)]);
+    }
+
+    /**
+     * hasField
+     * @return boolean
+     */
+    public function hasField($fieldName)
+    {
+        return isset($this->_columnNames[$fieldName]);
+    }
+
+    /**
+     * sets the connection for this class
+     *
+     * @params Doctrine_Connection      a connection object
+     * @return Doctrine_Table           this object
+     */
+    public function setConnection(Doctrine_Connection $conn)
+    {
+        $this->_conn = $conn;
+
+        $this->setParent($this->_conn);
+
+        return $this;
+    }
+
+    /**
+     * returns the connection associated with this table (if any)
+     *
+     * @return Doctrine_Connection|null     the connection object
+     */
+    public function getConnection()
+    {
+        return $this->_conn;
+    }
+
+    /**
+     * creates a new record
+     *
+     * @param $array             an array where keys are field names and
+     *                           values representing field values
+     * @return Doctrine_Record   the created record object
+     */
+    public function create(array $array = array())
+    {
+        $record = new $this->_options['name']($this, true);
+        $record->fromArray($array);
+
+        return $record;
+    }
+    
+    /**
+     * adds a named query in the query registry
+     *
+     * @param $queryKey  Query key name
+     * @param $query      DQL string or Doctrine_Query object
+     * @return void
+	 */
+	public function addNamedQuery($queryKey, $query)
+    {
+        $registry = Doctrine_Manager::getInstance()->getQueryRegistry();
+        $registry->add($this->getComponentName() . '/' . $queryKey, $query);
+    }
+    
+    /**
+     * creates a named query in the query registry
+     *
+     * @param $queryKey  Query key name
+     * @return Doctrine_Query
+	 */
+	public function createNamedQuery($queryKey)
+    {
+        $queryRegistry = Doctrine_Manager::getInstance()->getQueryRegistry();
+
+        if (strpos($queryKey, '/') !== false) {
+            $e = explode('/', $queryKey);
+            
+            return $queryRegistry->get($e[1], $e[0]);
+        }
+
+        return $queryRegistry->get($queryKey, $this->getComponentName());
+    }
+
+
+    /**
+     * finds a record by its identifier
+     *
+     * @param mixed $name         Database Row ID or Query Name defined previously as a NamedQuery
+     * @param mixed $params       This argument is the hydration mode (Doctrine::HYDRATE_ARRAY or 
+     *                            Doctrine::HYDRATE_RECORD) if first param is a Database Row ID. 
+     *                            Otherwise this argument expect an array of query params.
+     * @param int $hydrationMode  Optional Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD if 
+     *                            first argument is a NamedQuery
+     * @return mixed              Doctrine_Collection, array, Doctrine_Record or false if no result
+     */
+    public function find()
+    {
+        $num_args = func_num_args();
+
+        // Named Query or IDs
+        $name = func_get_arg(0);
+        
+        if (is_null($name)) { 
+            return false;
+        }
+
+        $ns = $this->getComponentName();
+        $m = $name;
+        
+        // Check for possible cross-access
+        if ( ! is_array($name) && strpos($name, '/') !== false) {
+            list($ns, $m) = explode('/', $name);
+        }
+
+        // Define query to be used
+        if (
+            ! is_array($name) && 
+            Doctrine_Manager::getInstance()->getQueryRegistry()->has($m, $ns)
+        ) {
+            // We're dealing with a named query
+            $q = $this->createNamedQuery($name);
+
+            // Parameters construction
+            $params = ($num_args >= 2) ? func_get_arg(1) : array();
+
+            // Hydration mode
+            $hydrationMode = ($num_args == 3) ? func_get_arg(2) : null;
+
+            // Executing query
+            $res = $q->execute($params, $hydrationMode);
+        } else {
+            // We're passing a single ID or an array of IDs
+            $q = $this->createQuery('dctrn_find')
+                ->where('dctrn_find.' . implode(' = ? AND dctrn_find.', (array) $this->getIdentifier()) . ' = ?')
+                ->limit(1);
+                
+            // Parameters construction
+            $params = is_array($name) ? array_values($name) : array($name);
+
+            // Hydration mode
+            $hydrationMode = ($num_args == 2) ? func_get_arg(1) : null;
+            
+            // Executing query
+            $res = $q->fetchOne($params, $hydrationMode);
+        }
+
+        $q->free();
+        
+        return $res;
+    }
+
+    /**
+     * findAll
+     * returns a collection of records
+     *
+     * @param int $hydrationMode        Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD
+     * @return Doctrine_Collection
+     */
+    public function findAll($hydrationMode = null)
+    {
+        return $this->createQuery('dctrn_find')
+            ->execute(array(), $hydrationMode);
+    }
+
+    /**
+     * findBySql
+     * finds records with given SQL where clause
+     * returns a collection of records
+     *
+     * @param string $dql               DQL after WHERE clause
+     * @param array $params             query parameters
+     * @param int $hydrationMode        Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD
+     * @return Doctrine_Collection
+     *
+     * @todo This actually takes DQL, not SQL, but it requires column names
+     *       instead of field names. This should be fixed to use raw SQL instead.
+     */
+    public function findBySql($dql, $params = array(), $hydrationMode = null)
+    {
+        return $this->createQuery('dctrn_find')
+            ->where($dql)->execute($params, $hydrationMode);
+    }
+
+    /**
+     * findByDql
+     * finds records with given DQL where clause
+     * returns a collection of records
+     *
+     * @param string $dql               DQL after WHERE clause
+     * @param array $params             query parameters
+     * @param int $hydrationMode        Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD
+     * @return Doctrine_Collection
+     */
+    public function findByDql($dql, $params = array(), $hydrationMode = null)
+    {
+        $parser = new Doctrine_Query($this->_conn);
+        $component = $this->getComponentName();
+        $query = 'FROM ' . $component . ' dctrn_find WHERE ' . $dql;
+
+        return $parser->query($query, $params, $hydrationMode);
+    }
+    
+    /**
+     * findBy
+     *
+     * @param string $column
+     * @param string $value
+     * @param string $hydrationMode
+     * @return void
+     */
+    protected function findBy($fieldName, $value, $hydrationMode = null)
+    {
+        return $this->createQuery('dctrn_find')
+            ->where('dctrn_find.' . $fieldName . ' = ?', array($value))
+            ->execute(array(), $hydrationMode);
+    }
+
+    /**
+     * findOneBy
+     *
+     * @param string $column
+     * @param string $value
+     * @param string $hydrationMode
+     * @return void
+     */
+    protected function findOneBy($fieldName, $value, $hydrationMode = null)
+    {
+        return $this->createQuery('dctrn_find')
+                    ->where('dctrn_find.' . $fieldName . ' = ?', array($value))
+                    ->limit(1)
+                    ->fetchOne(array(), $hydrationMode);
+    }
+
+    /**
+     * execute
+     * fetches data using the provided queryKey and
+     * the associated query in the query registry
+     *
+     * if no query for given queryKey is being found a
+     * Doctrine_Query_Registry exception is being thrown
+     *
+     * @param string $queryKey      the query key
+     * @param array $params         prepared statement params (if any)
+     * @return mixed                the fetched data
+     */
+    public function execute($queryKey, $params = array(), $hydrationMode = Doctrine::HYDRATE_RECORD)
+    {
+        return $this->createNamedQuery($queryKey)->execute($params, $hydrationMode);
+    }
+
+    /**
+     * executeOne
+     * fetches data using the provided queryKey and
+     * the associated query in the query registry
+     *
+     * if no query for given queryKey is being found a
+     * Doctrine_Query_Registry exception is being thrown
+     *
+     * @param string $queryKey      the query key
+     * @param array $params         prepared statement params (if any)
+     * @return mixed                the fetched data
+     */
+    public function executeOne($queryKey, $params = array(), $hydrationMode = Doctrine::HYDRATE_RECORD)
+    {
+        return $this->createNamedQuery($queryKey)->fetchOne($params, $hydrationMode);
+    }
+
+    /**
+     * clear
+     * clears the first level cache (identityMap)
+     *
+     * @return void
+     * @todo what about a more descriptive name? clearIdentityMap?
+     */
+    public function clear()
+    {
+        $this->_identityMap = array();
+    }
+
+    /**
+     * addRecord
+     * adds a record to identity map
+     *
+     * @param Doctrine_Record $record       record to be added
+     * @return boolean
+     * @todo Better name? registerRecord?
+     */
+    public function addRecord(Doctrine_Record $record)
+    {
+        $id = implode(' ', $record->identifier());
+
+        if (isset($this->_identityMap[$id])) {
+            return false;
+        }
+
+        $this->_identityMap[$id] = $record;
+
+        return true;
+    }
+
+    /**
+     * removeRecord
+     * removes a record from the identity map, returning true if the record
+     * was found and removed and false if the record wasn't found.
+     *
+     * @param Doctrine_Record $record       record to be removed
+     * @return boolean
+     */
+    public function removeRecord(Doctrine_Record $record)
+    {
+        $id = implode(' ', $record->identifier());
+
+        if (isset($this->_identityMap[$id])) {
+            unset($this->_identityMap[$id]);
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * getRecord
+     * first checks if record exists in identityMap, if not
+     * returns a new record
+     *
+     * @return Doctrine_Record
+     */
+    public function getRecord()
+    {
+        if ( ! empty($this->_data)) {
+            $identifierFieldNames = $this->getIdentifier();
+
+            if ( ! is_array($identifierFieldNames)) {
+                $identifierFieldNames = array($identifierFieldNames);
+            }
+
+            $found = false;
+            foreach ($identifierFieldNames as $fieldName) {
+                if ( ! isset($this->_data[$fieldName])) {
+                    // primary key column not found return new record
+                    $found = true;
+                    break;
+                }
+                $id[] = $this->_data[$fieldName];
+            }
+
+            if ($found) {
+                $recordName = $this->getComponentName();
+                $record = new $recordName($this, true);
+                $this->_data = array();
+                return $record;
+            }
+            
+            $id = implode(' ', $id);
+
+            if (isset($this->_identityMap[$id])) {
+                $record = $this->_identityMap[$id];
+                if ($record->getTable()->getAttribute(Doctrine::ATTR_HYDRATE_OVERWRITE)) {
+                    $record->hydrate($this->_data);
+                    if ($record->state() == Doctrine_Record::STATE_PROXY) {
+                        if (count($this->_data) >= $this->getColumnCount()) {
+                            $record->state(Doctrine_Record::STATE_CLEAN);
+                        }
+                    }
+                } else {
+                    $record->hydrate($this->_data, false);
+                }
+            } else {
+                $recordName = $this->getComponentName();
+                $record = new $recordName($this);
+                $this->_identityMap[$id] = $record;
+            }
+            $this->_data = array();
+        } else {
+            $recordName = $this->getComponentName();
+            $record = new $recordName($this, true);
+        }
+
+        return $record;
+    }
+
+    /**
+     * Get the classname to return. Most often this is just the options['name']
+     *
+     * Check the subclasses option and the inheritanceMap for each subclass to see
+     * if all the maps in a subclass is met. If this is the case return that
+     * subclass name. If no subclasses match or if there are no subclasses defined
+     * return the name of the class for this tables record.
+     *
+     * @todo this function could use reflection to check the first time it runs
+     * if the subclassing option is not set.
+     *
+     * @return string The name of the class to create
+     * @deprecated
+     */
+    public function getClassnameToReturn()
+    {
+        if ( ! isset($this->_options['subclasses'])) {
+            return $this->_options['name'];
+        }
+        foreach ($this->_options['subclasses'] as $subclass) {
+            $table = $this->_conn->getTable($subclass);
+            $inheritanceMap = $table->getOption('inheritanceMap');
+            $nomatch = false;
+            foreach ($inheritanceMap as $key => $value) {
+                if ( ! isset($this->_data[$key]) || $this->_data[$key] != $value) {
+                    $nomatch = true;
+                    break;
+                }
+            }
+            if ( ! $nomatch) {
+                return $table->getComponentName();
+            }
+        }
+        return $this->_options['name'];
+    }
+
+    /**
+     * @param $id                       database row id
+     * @throws Doctrine_Find_Exception
+     */
+    final public function getProxy($id = null)
+    {
+        if ($id !== null) {
+            $identifierColumnNames = $this->getIdentifierColumnNames();
+            $query = 'SELECT ' . implode(', ', (array) $identifierColumnNames)
+                . ' FROM ' . $this->getTableName()
+                . ' WHERE ' . implode(' = ? && ', (array) $identifierColumnNames) . ' = ?';
+            $query = $this->applyInheritance($query);
+
+            $params = array_merge(array($id), array_values($this->_options['inheritanceMap']));
+
+            $this->_data = $this->_conn->execute($query, $params)->fetch(PDO::FETCH_ASSOC);
+
+            if ($this->_data === false)
+                return false;
+        }
+        return $this->getRecord();
+    }
+
+    /**
+     * applyInheritance
+     * @param $where                    query where part to be modified
+     * @return string                   query where part with column aggregation inheritance added
+     */
+    final public function applyInheritance($where)
+    {
+        if ( ! empty($this->_options['inheritanceMap'])) {
+            $a = array();
+            foreach ($this->_options['inheritanceMap'] as $field => $value) {
+                $a[] = $this->getColumnName($field) . ' = ?';
+            }
+            $i = implode(' AND ', $a);
+            $where .= ' AND ' . $i;
+        }
+        return $where;
+    }
+
+    /**
+     * count
+     *
+     * @return integer
+     */
+    public function count()
+    {
+        return $this->createQuery()->count();
+    }
+
+    /**
+     * @return Doctrine_Query  a Doctrine_Query object
+     */
+    public function getQueryObject()
+    {
+        $graph = new Doctrine_Query($this->getConnection());
+        $graph->load($this->getComponentName());
+        return $graph;
+    }
+
+    /**
+     * @param string $fieldName
+     * @return array
+     */
+    public function getEnumValues($fieldName)
+    {
+        $columnName = $this->getColumnName($fieldName);
+        if (isset($this->_columns[$columnName]['values'])) {
+            return $this->_columns[$columnName]['values'];
+        } else {
+            return array();
+        }
+    }
+
+    /**
+     * enumValue
+     *
+     * @param string $field
+     * @param integer $index
+     * @return mixed
+     */
+    public function enumValue($fieldName, $index)
+    {
+        if ($index instanceof Doctrine_Null) {
+            return $index;
+        }
+
+        $columnName = $this->getColumnName($fieldName);
+        if ( ! $this->_conn->getAttribute(Doctrine::ATTR_USE_NATIVE_ENUM)
+            && isset($this->_columns[$columnName]['values'][$index])
+        ) {
+            return $this->_columns[$columnName]['values'][$index];
+        }
+
+        return $index;
+    }
+
+    /**
+     * enumIndex
+     *
+     * @param string $field
+     * @param mixed $value
+     * @return mixed
+     */
+    public function enumIndex($fieldName, $value)
+    {
+        $values = $this->getEnumValues($fieldName);
+
+        $index = array_search($value, $values);
+        if ($index === false || !$this->_conn->getAttribute(Doctrine::ATTR_USE_NATIVE_ENUM)) {
+            return $index;
+        }
+        return $value;
+    }
+
+    /**
+     * validateField
+     *
+     * @param string $name
+     * @param string $value
+     * @param Doctrine_Record $record
+     * @return Doctrine_Validator_ErrorStack $errorStack
+     */
+    public function validateField($fieldName, $value, Doctrine_Record $record = null)
+    {
+        if ($record instanceof Doctrine_Record) {
+            $errorStack = $record->getErrorStack();
+        } else {
+            $record  = $this->create();
+            $errorStack = new Doctrine_Validator_ErrorStack($this->getOption('name'));
+        }
+
+        if ($value === self::$_null) {
+            $value = null;
+        } else if ($value instanceof Doctrine_Record && $value->exists()) {
+            $value = $value->getIncremented();
+        } else if ($value instanceof Doctrine_Record && ! $value->exists()) {
+            foreach($this->getRelations() as $relation) {
+                if ($fieldName == $relation->getLocalFieldName() && (get_class($value) == $relation->getClass() || is_subclass_of($value, $relation->getClass()))) {
+                    return $errorStack;
+                }
+            }
+        }
+
+        $dataType = $this->getTypeOf($fieldName);
+
+        // Validate field type, if type validation is enabled
+        if ($this->getAttribute(Doctrine::ATTR_VALIDATE) & Doctrine::VALIDATE_TYPES) {
+            if ( ! Doctrine_Validator::isValidType($value, $dataType)) {
+                $errorStack->add($fieldName, 'type');
+            }
+            if ($dataType == 'enum') {
+                $enumIndex = $this->enumIndex($fieldName, $value);
+                if ($enumIndex === false && $value !== null) {
+                    $errorStack->add($fieldName, 'enum');
+                }
+            }
+        }
+
+        // Validate field length, if length validation is enabled
+        if ($this->getAttribute(Doctrine::ATTR_VALIDATE) & Doctrine::VALIDATE_LENGTHS) {
+            if ( ! Doctrine_Validator::validateLength($value, $dataType, $this->getFieldLength($fieldName))) {
+                $errorStack->add($fieldName, 'length');
+            }
+        }
+
+        // Run all custom validators
+        foreach ($this->getFieldValidators($fieldName) as $validatorName => $args) {
+            if ( ! is_string($validatorName)) {
+                $validatorName = $args;
+                $args = array();
+            }
+
+            $validator = Doctrine_Validator::getValidator($validatorName);
+            $validator->invoker = $record;
+            $validator->field = $fieldName;
+            $validator->args = $args;
+            if ( ! $validator->validate($value)) {
+                $errorStack->add($fieldName, $validator);
+            }
+        }
+
+        return $errorStack;
+    }
+
+    /**
+     * getColumnCount
+     *
+     * @return integer      the number of columns in this table
+     */
+    public function getColumnCount()
+    {
+        return $this->columnCount;
+    }
+
+    /**
+     * returns all columns and their definitions
+     *
+     * @return array
+     */
+    public function getColumns()
+    {
+        return $this->_columns;
+    }
+
+    /**
+     * Removes the passed field name from the table schema information
+     *
+     * @return boolean
+     */
+    public function removeColumn($fieldName)
+    {
+        if ( ! $this->hasField($fieldName)) {
+          return false;
+        }
+
+        $columnName = $this->getColumnName($fieldName);
+        unset($this->_columnNames[$fieldName], $this->_fieldNames[$columnName], $this->_columns[$columnName]);
+        $this->columnCount = count($this->_columns);
+        return true;
+    }
+
+    /**
+     * returns an array containing all the column names.
+     *
+     * @return array
+     */
+    public function getColumnNames(array $fieldNames = null)
+    {
+        if ($fieldNames === null) {
+            return array_keys($this->_columns);
+        } else {
+           $columnNames = array();
+           foreach ($fieldNames as $fieldName) {
+               $columnNames[] = $this->getColumnName($fieldName);
+           }
+           return $columnNames;
+        }
+    }
+
+    /**
+     * returns an array with all the identifier column names.
+     *
+     * @return array
+     */
+    public function getIdentifierColumnNames()
+    {
+        return $this->getColumnNames((array) $this->getIdentifier());
+    }
+
+    /**
+     * returns an array containing all the field names.
+     *
+     * @return array
+     */
+    public function getFieldNames()
+    {
+        return array_values($this->_fieldNames);
+    }
+
+    /**
+     * getDefinitionOf
+     *
+     * @return mixed        array on success, false on failure
+     */
+    public function getDefinitionOf($fieldName)
+    {
+        $columnName = $this->getColumnName($fieldName);
+        return $this->getColumnDefinition($columnName);
+    }
+
+    /**
+     * getTypeOf
+     *
+     * @return mixed        string on success, false on failure
+     */
+    public function getTypeOf($fieldName)
+    {
+        return $this->getTypeOfColumn($this->getColumnName($fieldName));
+    }
+
+    /**
+     * getTypeOfColumn
+     *
+     * @return mixed  The column type or FALSE if the type cant be determined.
+     */
+    public function getTypeOfColumn($columnName)
+    {
+        return isset($this->_columns[$columnName]) ? $this->_columns[$columnName]['type'] : false;
+    }
+
+    /**
+     * setData
+     * doctrine uses this function internally
+     * users are strongly discouraged to use this function
+     *
+     * @param array $data               internal data
+     * @return void
+     */
+    public function setData(array $data)
+    {
+        $this->_data = $data;
+    }
+
+    /**
+     * returns internal data, used by Doctrine_Record instances
+     * when retrieving data from database
+     *
+     * @return array
+     */
+    public function getData()
+    {
+        return $this->_data;
+    }
+
+    /**
+     * prepareValue
+     * this method performs special data preparation depending on
+     * the type of the given column
+     *
+     * 1. It unserializes array and object typed columns
+     * 2. Uncompresses gzip typed columns
+     * 3. Gets the appropriate enum values for enum typed columns
+     * 4. Initializes special null object pointer for null values (for fast column existence checking purposes)
+     *
+     * example:
+     * <code type='php'>
+     * $field = 'name';
+     * $value = null;
+     * $table->prepareValue($field, $value); // Doctrine_Null
+     * </code>
+     *
+     * @throws Doctrine_Table_Exception     if unserialization of array/object typed column fails or
+     * @throws Doctrine_Table_Exception     if uncompression of gzip typed column fails         *
+     * @param string $field     the name of the field
+     * @param string $value     field value
+     * @param string $typeHint  Type hint used to pass in the type of the value to prepare
+     *                          if it is already known. This enables the method to skip
+     *                          the type determination. Used i.e. during hydration.
+     * @return mixed            prepared value
+     */
+    public function prepareValue($fieldName, $value, $typeHint = null)
+    {
+        if ($value === self::$_null) {
+            return self::$_null;
+        } else if ($value === null) {
+            return null;
+        } else {
+            $type = is_null($typeHint) ? $this->getTypeOf($fieldName) : $typeHint;
+
+            switch ($type) {
+                case 'integer':
+                case 'string';
+                    // don't do any casting here PHP INT_MAX is smaller than what the databases support
+                break;
+                case 'enum':
+                    return $this->enumValue($fieldName, $value);
+                break;
+                case 'boolean':
+                    return (boolean) $value;
+                break;
+                case 'array':
+                case 'object':
+                    if (is_string($value)) {
+                        $value = empty($value) ? null:unserialize($value);
+
+                        if ($value === false) {
+                            throw new Doctrine_Table_Exception('Unserialization of ' . $fieldName . ' failed.');
+                        }
+                        return $value;
+                    }
+                break;
+                case 'gzip':
+                    $value = gzuncompress($value);
+
+                    if ($value === false) {
+                        throw new Doctrine_Table_Exception('Uncompressing of ' . $fieldName . ' failed.');
+                    }
+                    return $value;
+                break;
+            }
+        }
+        return $value;
+    }
+
+    /**
+     * getTree
+     *
+     * getter for associated tree
+     *
+     * @return mixed  if tree return instance of Doctrine_Tree, otherwise returns false
+     */
+    public function getTree()
+    {
+        if (isset($this->_options['treeImpl'])) {
+            if ( ! $this->_tree) {
+                $options = isset($this->_options['treeOptions']) ? $this->_options['treeOptions'] : array();
+                $this->_tree = Doctrine_Tree::factory($this,
+                    $this->_options['treeImpl'],
+                    $options
+                );
+            }
+            return $this->_tree;
+        }
+        return false;
+    }
+
+    /**
+     * getComponentName
+     *
+     * @return void
+     */
+    public function getComponentName()
+    {
+        return $this->_options['name'];
+    }
+
+    /**
+     * getTableName
+     *
+     * @return void
+     */
+    public function getTableName()
+    {
+        return $this->_options['tableName'];
+    }
+
+    /**
+     * setTableName
+     *
+     * @param string $tableName
+     * @return void
+     */
+    public function setTableName($tableName)
+    {
+        $this->setOption('tableName', $this->_conn->formatter->getTableName($tableName));
+    }
+
+    /**
+     * isTree
+     *
+     * determine if table acts as tree
+     *
+     * @return mixed  if tree return true, otherwise returns false
+     */
+    public function isTree()
+    {
+        return ( ! is_null($this->_options['treeImpl'])) ? true : false;
+    }
+    
+    /**
+     * getTemplates
+     * returns all templates attached to this table
+     *
+     * @return array     an array containing all templates
+     */
+    public function getTemplates()
+    {
+        return $this->_templates;
+    }
+
+    /**
+     * getTemplate
+     *
+     * @param string $template
+     * @return void
+     */
+    public function getTemplate($template)
+    {
+        if ( ! isset($this->_templates[$template])) {
+            throw new Doctrine_Table_Exception('Template ' . $template . ' not loaded');
+        }
+
+        return $this->_templates[$template];
+    }
+
+    /**
+     * Check if the table has a template name
+     *
+     * @param string $template
+     * @return boolean $bool
+     */
+    public function hasTemplate($template)
+    {
+        return isset($this->_templates[$template]);
+    }
+
+    /**
+     * Add template to the table
+     *
+     * @param string $template
+     * @param Doctrine_Template $impl
+     * @return Doctrine_Table
+     */
+    public function addTemplate($template, Doctrine_Template $impl)
+    {
+        $this->_templates[$template] = $impl;
+
+        return $this;
+    }
+
+    /**
+     * Get all the generators for the table
+     *
+     * @return array $generators
+     */
+
+    public function getGenerators()
+    {
+        return $this->_generators;
+    }
+
+    /**
+     * Get generator instance for a passed name
+     *
+     * @param string $generator
+     * @return Doctrine_Record_Generator $generator
+     */
+    public function getGenerator($generator)
+    {
+        if ( ! isset($this->_generators[$generator])) {
+            throw new Doctrine_Table_Exception('Generator ' . $generator . ' not loaded');
+        }
+
+        return $this->_generators[$generator];
+    }
+
+    /**
+     * Check if a generator name exists
+     *
+     * @param string $generator
+     * @return void
+     */
+    public function hasGenerator($generator)
+    {
+        return isset($this->_generators[$generator]);
+    }
+
+    /**
+     * Add a generate to the table instance
+     *
+     * @param Doctrine_Record_Generator $generator
+     * @param string $name
+     * @return Doctrine_Table
+     */
+    public function addGenerator(Doctrine_Record_Generator $generator, $name = null)
+    {
+        if ($name === null) {
+            $this->_generators[] = $generator;
+        } else {
+            $this->_generators[$name] = $generator;
+        }
+        return $this;
+    }
+
+    /**
+     * bindQueryParts
+     * binds query parts to given component
+     *
+     * @param array $queryParts         an array of pre-bound query parts
+     * @return Doctrine_Record          this object
+     */
+    public function bindQueryParts(array $queryParts)
+    {
+        $this->_options['queryParts'] = $queryParts;
+
+        return $this;
+    }
+
+    /**
+     * bindQueryPart
+     * binds given value to given query part
+     *
+     * @param string $queryPart
+     * @param mixed $value
+     * @return Doctrine_Record          this object
+     */
+    public function bindQueryPart($queryPart, $value)
+    {
+        $this->_options['queryParts'][$queryPart] = $value;
+
+        return $this;
+    }
+
+    /**
+     * Gets the names of all validators that are applied on a field.
+     *
+     * @param string  The field name.
+     * @return array  The names of all validators that are applied on the specified field.
+     */
+    public function getFieldValidators($fieldName)
+    {
+        $validators = array();
+        $columnName = $this->getColumnName($fieldName);
+        // this loop is a dirty workaround to get the validators filtered out of
+        // the options, since everything is squeezed together currently
+        foreach ($this->_columns[$columnName] as $name => $args) {
+             if (empty($name)
+                    || $name == 'primary'
+                    || $name == 'protected'
+                    || $name == 'autoincrement'
+                    || $name == 'default'
+                    || $name == 'values'
+                    || $name == 'sequence'
+                    || $name == 'zerofill'
+                    || $name == 'owner'
+                    || $name == 'scale'
+                    || $name == 'type'
+                    || $name == 'length'
+                    || $name == 'fixed'
+                    || $name == 'comment') {
+                continue;
+            }
+            if ($name == 'notnull' && isset($this->_columns[$columnName]['autoincrement'])
+                    && $this->_columns[$columnName]['autoincrement'] === true) {
+                continue;
+            }
+            // skip it if it's explicitly set to FALSE (i.e. notnull => false)
+            if ($args === false) {
+                continue;
+            }
+            $validators[$name] = $args;
+        }
+
+        return $validators;
+    }
+
+    /**
+     * Gets the (maximum) length of a field.
+     */
+    public function getFieldLength($fieldName)
+    {
+        return $this->_columns[$this->getColumnName($fieldName)]['length'];
+    }
+
+    /**
+     * getBoundQueryPart
+     *
+     * @param string $queryPart
+     * @return string $queryPart
+     */
+    public function getBoundQueryPart($queryPart)
+    {
+        if ( ! isset($this->_options['queryParts'][$queryPart])) {
+            return null;
+        }
+
+        return $this->_options['queryParts'][$queryPart];
+    }
+
+    /**
+     * unshiftFilter
+     *
+     * @param  object Doctrine_Record_Filter $filter
+     * @return object $this
+     */
+    public function unshiftFilter(Doctrine_Record_Filter $filter)
+    {
+        $filter->setTable($this);
+
+        $filter->init();
+
+        array_unshift($this->_filters, $filter);
+
+        return $this;
+    }
+
+    /**
+     * getFilters
+     *
+     * @return array $filters
+     */
+    public function getFilters()
+    {
+        return $this->_filters;
+    }
+
+    /**
+     * returns a string representation of this object
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return Doctrine_Lib::getTableAsString($this);
+    }
+
+    /**
+     * Resolve the passed find by field name to the appropriate field name
+     * regardless of whether the user passes a column name, field name, or a Doctrine_Inflector::classified()
+     * version of their column name. It will be inflected with Doctrine_Inflector::tableize() 
+     * to get the column or field name
+     *
+     * @param string $name 
+     * @return string $fieldName
+     */
+    protected function _resolveFindByFieldName($name)
+    {
+        $fieldName = Doctrine_Inflector::tableize($name);
+        if ($this->hasColumn($name) || $this->hasField($name)) {
+            return $this->getFieldName($this->getColumnName($name));
+        } else if ($this->hasColumn($fieldName) || $this->hasField($fieldName)) {
+            return $this->getFieldName($this->getColumnName($fieldName));
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * __call
+     *
+     * Adds support for magic finders.
+     * findByColumnName, findByRelationAlias
+     * findById, findByContactId, etc.
+     *
+     * @return void
+     */
+    public function __call($method, $arguments)
+    {
+        $lcMethod = strtolower($method);
+
+        if (substr($lcMethod, 0, 6) == 'findby') {
+            $by = substr($method, 6, strlen($method));
+            $method = 'findBy';
+        } else if (substr($lcMethod, 0, 9) == 'findoneby') {
+            $by = substr($method, 9, strlen($method));
+            $method = 'findOneBy';
+        }
+
+        if (isset($by)) {
+            if ( ! isset($arguments[0])) {
+                throw new Doctrine_Table_Exception('You must specify the value to findBy');
+            }
+
+            $fieldName = $this->_resolveFindByFieldName($by);
+            $hydrationMode = isset($arguments[1]) ? $arguments[1]:null;
+            if ($this->hasField($fieldName)) {
+                return $this->$method($fieldName, $arguments[0], $hydrationMode);
+            } else if ($this->hasRelation($by)) {
+                $relation = $this->getRelation($by);
+
+                if ($relation['type'] === Doctrine_Relation::MANY) {
+                    throw new Doctrine_Table_Exception('Cannot findBy many relationship.');
+                }
+
+                return $this->$method($relation['local'], $arguments[0], $hydrationMode);
+            } else {
+                throw new Doctrine_Table_Exception('Cannot find by: ' . $by . '. Invalid column or relationship alias.');
+            }
+        }
+
+        // Forward the method on to the record instance and see if it has anything or one of its behaviors
+        try {
+            return call_user_func_array(array($this->getRecordInstance(), $method . 'TableProxy'), $arguments);
+        } catch (Doctrine_Record_UnknownPropertyException $e) {}
+
+        throw new Doctrine_Table_Exception(sprintf('Unknown method %s::%s', get_class($this), $method));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Table/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,41 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * thrown when user tries to initialize a new instance of Doctrine_Table,
+ * while there already exists an instance of that table
+ *
+ * @package     Doctrine
+ * @subpackage  Table
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Table_Exception extends Doctrine_Exception
+{
+    public function __construct($message = "Couldn't initialize table. One instance of this
+                            table already exists. Always use Doctrine_Session::getTable(\$name)
+                            to get on instance of a Doctrine_Table.") {
+        parent::__construct($message);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Table/Repository.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,163 @@
+<?php
+/*
+ *  $Id: Repository.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Repository
+ * each record is added into Doctrine_Repository at the same time they are created,
+ * loaded from the database or retrieved from the cache
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @package     Doctrine
+ * @subpackage  Table
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Table_Repository implements Countable, IteratorAggregate
+{
+    /**
+     * @var object Doctrine_Table $table
+     */
+    private $table;
+
+    /**
+     * @var array $registry
+     * an array of all records
+     * keys representing record object identifiers
+     */
+    private $registry = array();
+
+    /**
+     * constructor
+     *
+     * @param Doctrine_Table $table
+     */
+    public function __construct(Doctrine_Table $table)
+    {
+        $this->table = $table;
+    }
+
+    /**
+     * getTable
+     *
+     * @return object Doctrine_Table
+     */
+    public function getTable()
+    {
+        return $this->table;
+    }
+
+    /**
+     * add
+     *
+     * @param Doctrine_Record $record       record to be added into registry
+     * @return boolean
+     */
+    public function add(Doctrine_Record $record)
+    {
+        $oid = $record->getOID();
+
+        if (isset($this->registry[$oid])) {
+            return false;
+        }
+        $this->registry[$oid] = $record;
+
+        return true;
+    }
+
+    /**
+     * get
+     * @param integer $oid
+     * @throws Doctrine_Table_Repository_Exception
+     */
+    public function get($oid)
+    {
+        if ( ! isset($this->registry[$oid])) {
+            throw new Doctrine_Table_Repository_Exception("Unknown object identifier");
+        }
+        return $this->registry[$oid];
+    }
+
+    /**
+     * count
+     * Doctrine_Registry implements interface Countable
+     * @return integer                      the number of records this registry has
+     */
+    public function count()
+    {
+        return count($this->registry);
+    }
+
+    /**
+     * @param integer $oid                  object identifier
+     * @return boolean                      whether ot not the operation was successful
+     */
+    public function evict($oid)
+    {
+        if ( ! isset($this->registry[$oid])) {
+            return false;
+        }
+        unset($this->registry[$oid]);
+        return true;
+    }
+
+    /**
+     * @return integer                      number of records evicted
+     */
+    public function evictAll()
+    {
+        $evicted = 0;
+        foreach ($this->registry as $oid=>$record) {
+            if ($this->evict($oid)) {
+                $evicted++;
+            }
+        }
+        return $evicted;
+    }
+
+    /**
+     * getIterator
+     * @return ArrayIterator
+     */
+    public function getIterator()
+    {
+        return new ArrayIterator($this->registry);
+    }
+
+    /**
+     * contains
+     * @param integer $oid                  object identifier
+     */
+    public function contains($oid)
+    {
+        return isset($this->registry[$oid]);
+    }
+
+    /**
+     * loadAll
+     * @return void
+     */
+    public function loadAll()
+    {
+        $this->table->findAll();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Table/Repository/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Table_Repository_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Table
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Table_Repository_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,232 @@
+<?php
+/*
+ *  $Id: Task.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task
+ * 
+ * Abstract class used for writing Doctrine Tasks
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+abstract class Doctrine_Task
+{
+    public $dispatcher           =   null,
+           $taskName             =   null,
+           $description          =   null,
+           $arguments            =   array(),
+           $requiredArguments    =   array(),
+           $optionalArguments    =   array();
+
+    /**
+     * __construct
+     *
+     * Since this is an abstract classes that extend this must follow a patter of Doctrine_Task_{TASK_NAME}
+     * This is what determines the task name for executing it.
+     *
+     * @return void
+     */
+    public function __construct($dispatcher = null)
+    {
+        $this->dispatcher = $dispatcher;
+        
+        $this->taskName = str_replace('_', '-', Doctrine_Inflector::tableize(str_replace('Doctrine_Task_', '', get_class($this))));
+    }
+
+    /**
+     * notify
+     *
+     * @param string $notification 
+     * @return void
+     */
+    public function notify($notification = null)
+    {
+        if (is_object($this->dispatcher) && method_exists($this->dispatcher, 'notify')) {
+            $args = func_get_args();
+            
+            return call_user_func_array(array($this->dispatcher, 'notify'), $args);
+        } else if ( $notification !== null ) {
+            return $notification;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * ask
+     *
+     * @return void
+     */
+    public function ask()
+    {
+        $args = func_get_args();
+        
+        call_user_func_array(array($this, 'notify'), $args);
+        
+        $answer = strtolower(trim(fgets(STDIN)));
+        
+        return $answer;
+    }
+
+    /**
+     * execute
+     *
+     * Override with each task class
+     *
+     * @return void
+     * @abstract
+     */
+    abstract function execute();
+
+    /**
+     * validate
+     *
+     * Validates that all required fields are present
+     *
+     * @return bool true
+     */
+    public function validate()
+    {
+        $requiredArguments = $this->getRequiredArguments();
+        
+        foreach ($requiredArguments as $arg) {
+            if ( ! isset($this->arguments[$arg])) {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+
+    /**
+     * addArgument
+     *
+     * @param string $name 
+     * @param string $value 
+     * @return void
+     */
+    public function addArgument($name, $value)
+    {
+        $this->arguments[$name] = $value;
+    }
+
+    /**
+     * getArgument
+     *
+     * @param string $name 
+     * @param string $default 
+     * @return mixed
+     */
+    public function getArgument($name, $default = null)
+    {
+        if (isset($this->arguments[$name]) && $this->arguments[$name] !== null) {
+            return $this->arguments[$name];
+        } else {
+            return $default;
+        }
+    }
+
+    /**
+     * getArguments
+     *
+     * @return array $arguments
+     */
+    public function getArguments()
+    {
+        return $this->arguments;
+    }
+
+    /**
+     * setArguments
+     *
+     * @param array $args 
+     * @return void
+     */
+    public function setArguments(array $args)
+    {
+        $this->arguments = $args;
+    }
+
+    /**
+     * getTaskName
+     *
+     * @return string $taskName
+     */
+    public function getTaskName()
+    {
+        return $this->taskName;
+    }
+
+    /**
+     * getDescription
+     *
+     * @return string $description
+     */
+    public function getDescription()
+    {
+        return $this->description;
+    }
+
+    /**
+     * getRequiredArguments
+     *
+     * @return array $requiredArguments
+     */
+    public function getRequiredArguments()
+    {
+        return array_keys($this->requiredArguments);
+    }
+
+    /**
+     * getOptionalArguments
+     *
+     * @return array $optionalArguments
+     */
+    public function getOptionalArguments()
+    {
+        return array_keys($this->optionalArguments);
+    }
+
+    /**
+     * getRequiredArgumentsDescriptions
+     *
+     * @return array $requiredArgumentsDescriptions
+     */
+    public function getRequiredArgumentsDescriptions()
+    {
+        return $this->requiredArguments;
+    }
+
+    /**
+     * getOptionalArgumentsDescriptions
+     *
+     * @return array $optionalArgumentsDescriptions
+     */
+    public function getOptionalArgumentsDescriptions()
+    {
+        return $this->optionalArguments;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/BuildAll.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,65 @@
+<?php
+/*
+ *  $Id: BuildAll.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_BuildAll
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_BuildAll extends Doctrine_Task
+{
+    public $description          =   'Calls generate-models-from-yaml, create-db, and create-tables',
+           $requiredArguments    =   array(),
+           $optionalArguments    =   array();
+    
+    protected $models,
+              $tables;
+    
+    public function __construct($dispatcher = null)
+    {
+        parent::__construct($dispatcher);
+        
+        $this->models = new Doctrine_Task_GenerateModelsYaml($this->dispatcher);
+        $this->createDb = new Doctrine_Task_CreateDb($this->dispatcher);
+        $this->tables = new Doctrine_Task_CreateTables($this->dispatcher);
+        
+        $this->requiredArguments = array_merge($this->requiredArguments, $this->models->requiredArguments, $this->createDb->requiredArguments, $this->tables->requiredArguments);
+        $this->optionalArguments = array_merge($this->optionalArguments, $this->models->optionalArguments, $this->createDb->optionalArguments, $this->tables->optionalArguments);
+    }
+    
+    public function execute()
+    {
+        $this->models->setArguments($this->getArguments());
+        $this->models->execute();
+        
+        $this->createDb->setArguments($this->getArguments());
+        $this->createDb->execute();
+        
+        $this->tables->setArguments($this->getArguments());
+        $this->tables->execute();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/BuildAllLoad.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,58 @@
+<?php
+/*
+ *  $Id: BuildAllLoad.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_BuildAllLoad
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_BuildAllLoad extends Doctrine_Task
+{
+    public $description          =   'Calls build-all, and load-data',
+           $requiredArguments    =   array(),
+           $optionalArguments    =   array();
+    
+    public function __construct($dispatcher = null)
+    {
+        parent::__construct($dispatcher);
+
+        $this->buildAll = new Doctrine_Task_BuildAll($this->dispatcher);
+        $this->loadData = new Doctrine_Task_LoadData($this->dispatcher);
+        
+        $this->requiredArguments = array_merge($this->requiredArguments, $this->buildAll->requiredArguments, $this->loadData->requiredArguments);
+        $this->optionalArguments = array_merge($this->optionalArguments, $this->buildAll->optionalArguments, $this->loadData->optionalArguments);
+    }
+    
+    public function execute()
+    {
+        $this->buildAll->setArguments($this->getArguments());
+        $this->buildAll->execute();
+        
+        $this->loadData->setArguments($this->getArguments());
+        $this->loadData->execute();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/BuildAllReload.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,58 @@
+<?php
+/*
+ *  $Id: BuildAllReload.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_BuildAllReload
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_BuildAllReload extends Doctrine_Task
+{
+    public $description          =   'Calls rebuild-db and load-data',
+           $requiredArguments    =   array(),
+           $optionalArguments    =   array();
+    
+    public function __construct($dispatcher = null)
+    {
+        parent::__construct($dispatcher);
+
+        $this->rebuildDb = new Doctrine_Task_RebuildDb($this->dispatcher);
+        $this->loadData = new Doctrine_Task_LoadData($this->dispatcher);
+        
+        $this->requiredArguments = array_merge($this->requiredArguments, $this->rebuildDb->requiredArguments, $this->loadData->requiredArguments);
+        $this->optionalArguments = array_merge($this->optionalArguments, $this->rebuildDb->optionalArguments, $this->loadData->optionalArguments);
+    }
+    
+    public function execute()
+    {
+        $this->rebuildDb->setArguments($this->getArguments());
+        $this->rebuildDb->execute();
+        
+        $this->loadData->setArguments($this->getArguments());
+        $this->loadData->execute();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/Compile.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,46 @@
+<?php
+/*
+ *  $Id: Task.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_Compile
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_Compile extends Doctrine_Task
+{
+    public $description          =   'Compile doctrine classes in to one single php file',
+           $requiredArguments    =   array(),
+           $optionalArguments    =   array('drivers'        =>  'Specify list of drivers you wish to compile. Ex: mysql|mssql|sqlite',
+                                           'compiled_path'  =>  'The path where you want to write the compiled doctrine libs.');
+    
+    public function execute()
+    {
+        $compiledPath = Doctrine::compile($this->getArgument('compiled_path'), $this->getArgument('drivers', array()));
+        
+        $this->notify('Compiled Doctrine successfully to: ' . $compiledPath);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/CreateDb.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,48 @@
+<?php
+/*
+ *  $Id: CreateDb.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_CreateDb
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_CreateDb extends Doctrine_Task
+{
+    public $description          =   'Create all databases for your connections. If the database already exists, nothing happens.',
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        $results = Doctrine::createDatabases();
+        
+        foreach ($results as $name => $result) {
+            $msg = $result instanceof Exception ? 'Could not create database for connection: "' .$name . '." Failed with exception: ' . $result->getMessage():$result;
+            
+            $this->notify($msg);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/CreateTables.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: CreateTables.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_CreateTables
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_CreateTables extends Doctrine_Task
+{
+    public $description          =   'Create tables for all existing database connections. If table exists nothing happens.',
+           $requiredArguments    =   array('models_path' => 'Specify path to your models directory.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::createTablesFromModels($this->getArgument('models_path'));
+        
+        $this->notify('Created tables successfully');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/Dql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,73 @@
+<?php
+/*
+ *  $Id: Dql.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_Dql
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_Dql extends Doctrine_Task
+{
+    public $description          =   'Execute dql query and display the results',
+           $requiredArguments    =   array('models_path'    =>  'Specify path to your Doctrine_Record definitions.',
+                                           'dql_query'      =>  'Specify the complete dql query to execute.'),
+           $optionalArguments    =   array('params'         =>  'Comma separated list of the params to replace the ? tokens in the dql');
+
+    public function execute()
+    {
+        Doctrine::loadModels($this->getArgument('models_path'));
+
+        $dql = $this->getArgument('dql_query');
+
+        $query = new Doctrine_Query();
+
+        $params = $this->getArgument('params');
+        $params = $params ? explode(',', $params):array();
+
+        $this->notify('executing: "' . $dql . '" (' . implode(', ', $params) . ')');
+
+        $results = $query->query($dql, $params, Doctrine::HYDRATE_ARRAY);
+
+        $this->_printResults($results);
+    }
+
+    protected function _printResults($array)
+    {
+        $yaml = Doctrine_Parser::dump($array, 'yml');
+        $lines = explode("\n", $yaml);
+
+        unset($lines[0]);
+
+        foreach ($lines as $yamlLine) {
+            $line = trim($yamlLine);
+
+            if ($line) {
+                $this->notify($yamlLine);
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/DropDb.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,59 @@
+<?php
+/*
+ *  $Id: DropDb.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_DropDb
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_DropDb extends Doctrine_Task
+{
+    public $description          =   'Drop database for all existing connections',
+           $requiredArguments    =   array(),
+           $optionalArguments    =   array('force'  =>  'Whether or not to force the drop database task');
+
+    public function execute()
+    {
+        if ( ! $this->getArgument('force')) {
+            $answer = $this->ask('Are you sure you wish to drop your databases? (y/n)');
+
+            if ($answer != 'y') {
+                $this->notify('Successfully cancelled');
+
+                return;
+            }
+        }
+
+        $results = Doctrine::dropDatabases();
+
+        foreach ($results as $name => $result) {
+            $msg = $result instanceof Exception ? 'Could not drop database for connection: "' .$name . '." Failed with exception: ' . $result->getMessage():$result;
+
+            $this->notify($msg);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/DumpData.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,62 @@
+<?php
+/*
+ *  $Id: GenerateSql.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_DumpData
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_DumpData extends Doctrine_Task
+{
+    public $description          =   'Dump data to a yaml data fixture file.',
+           $requiredArguments    =   array('data_fixtures_path' =>  'Specify path to write the yaml data fixtures file to.',
+                                           'models_path'        =>  'Specify path to your Doctrine_Record definitions.'),
+           $optionalArguments    =   array();
+
+    public function execute()
+    {
+        $models = Doctrine::loadModels($this->getArgument('models_path')); 
+
+        if (empty($models)) { 
+            throw new Doctrine_Task_Exception('No models were loaded'); 
+        }
+
+        $path = $this->getArgument('data_fixtures_path');
+
+        if (is_array($path) && count($path) > 0) {
+            $path = $path[0];
+        }
+
+        if ( ! empty($path)) {
+            Doctrine::dumpData($path);
+
+            $this->notify(sprintf('Dumped data successfully to: %s', $path));
+        } else {
+            throw new Doctrine_Task_Exception('Unable to find data fixtures path.');
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateMigration.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,46 @@
+<?php
+/*
+ *  $Id: GenerateMigration.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateMigration
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateMigration extends Doctrine_Task
+{
+    public $description          =   'Generate new migration class definition',
+           $requiredArguments    =   array('class_name'      => 'Name of the migration class to generate',
+                                           'migrations_path' => 'Specify the complete path to your migration classes folder.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::generateMigrationClass($this->getArgument('class_name'), $this->getArgument('migrations_path'));
+        
+        $this->notify(sprintf('Generated migration class: %s successfully to %s', $this->getArgument('class_name'), $this->getArgument('migrations_path')));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateMigrationsDb.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: GenerateMigrationsDb.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateMigrationsDb
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateMigrationsDb extends Doctrine_Task
+{
+    public $description          =   'Generate migration classes for an existing database',
+           $requiredArguments    =   array('migrations_path' => 'Specify the complete path to your migration classes folder.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::generateMigrationsFromDb($this->getArgument('migrations_path'));
+        
+        $this->notify('Generated migration classes successfully from database');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateMigrationsModels.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,46 @@
+<?php
+/*
+ *  $Id: GenerateMigrationsModels.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateMigrationsModels
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateMigrationsModels extends Doctrine_Task
+{
+    public $description          =   'Generate migration classes for an existing set of models',
+           $requiredArguments    =   array('migrations_path' => 'Specify the path to your migration classes folder.',
+                                           'models_path'     => 'Specify the path to your doctrine models folder.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {   
+        Doctrine::generateMigrationsFromModels($this->getArgument('migrations_path'), $this->getArgument('models_path'));
+        
+        $this->notify('Generated migration classes successfully from models');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateModelsDb.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: GenerateModelsDb.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateModelsDb
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateModelsDb extends Doctrine_Task
+{
+    public $description          =   'Generates your Doctrine_Record definitions from your existing database connections.',
+           $requiredArguments    =   array('models_path'    =>  'Specify path to your Doctrine_Record definitions.'),
+           $optionalArguments    =   array('connection'     =>  'Optionally specify a single connection to generate the models for.');
+    
+    public function execute()
+    {
+        Doctrine::generateModelsFromDb($this->getArgument('models_path'), (array) $this->getArgument('connection'));
+        
+        $this->notify('Generated models successfully from databases');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateModelsYaml.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,46 @@
+<?php
+/*
+ *  $Id: GenerateModelsYaml.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateModelsYaml
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateModelsYaml extends Doctrine_Task
+{
+    public $description          =   'Generates your Doctrine_Record definitions from a Yaml schema file',
+           $requiredArguments    =   array('yaml_schema_path'   =>  'Specify the complete directory path to your yaml schema files.',
+                                           'models_path'        =>  'Specify complete path to your Doctrine_Record definitions.'),
+           $optionalArguments    =   array('generate_models_options'    =>  'Array of options for generating models');
+    
+    public function execute()
+    {
+        Doctrine::generateModelsFromYaml($this->getArgument('yaml_schema_path'), $this->getArgument('models_path'), $this->getArgument('generate_models_options', array()));
+        
+        $this->notify('Generated models successfully from YAML schema');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateSql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,56 @@
+<?php
+/*
+ *  $Id: GenerateSql.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateSql
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateSql extends Doctrine_Task
+{
+    public $description          =   'Generate sql for all existing database connections.',
+           $requiredArguments    =   array('models_path'    =>  'Specify complete path to your Doctrine_Record definitions.',
+                                           'sql_path'       =>  'Path to write the generated sql.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        if (is_dir($this->getArgument('sql_path'))) {
+            $path = $this->getArgument('sql_path') . DIRECTORY_SEPARATOR . 'schema.sql';
+        } else if (is_file($this->getArgument('sql_path'))) {
+            $path = $this->getArgument('sql_path');
+        } else {
+            throw new Doctrine_Task_Exception('Invalid sql path.');
+        }
+        
+        $sql = Doctrine::generateSqlFromModels($this->getArgument('models_path'));
+        
+        file_put_contents($path, $sql);
+        
+        $this->notify('Generated SQL successfully for models');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateYamlDb.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: GenerateYamlDb.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateYamlDb
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateYamlDb extends Doctrine_Task
+{
+    public $description          =   'Generates a Yaml schema file from an existing database',
+           $requiredArguments    =   array('yaml_schema_path'   =>  'Specify the path to your yaml schema files.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::generateYamlFromDb($this->getArgument('yaml_schema_path'));
+        
+        $this->notify('Generate YAML schema successfully from database');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/GenerateYamlModels.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,46 @@
+<?php
+/*
+ *  $Id: GenerateYamlModels.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateFromModels
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateYamlModels extends Doctrine_Task
+{
+    public $description          =   'Generates a Yaml schema file from existing Doctrine_Record definitions',
+           $requiredArguments    =   array('yaml_schema_path'   =>  'Specify the complete directory path to your yaml schema files.',
+                                           'models_path'        =>  'Specify complete path to your Doctrine_Record definitions.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::generateYamlFromModels($this->getArgument('yaml_schema_path'), $this->getArgument('models_path'));
+        
+        $this->notify('Generated YAML schema successfully from models');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/LoadData.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,47 @@
+<?php
+/*
+ *  $Id: LoadData.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_LoadData
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_LoadData extends Doctrine_Task
+{
+    public $description          =   'Load data from a yaml data fixture file.',
+           $requiredArguments    =   array('data_fixtures_path' =>  'Specify the complete path to load the yaml data fixtures files from.',
+                                           'models_path'        =>  'Specify path to your Doctrine_Record definitions.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::loadModels($this->getArgument('models_path'));
+        Doctrine::loadData($this->getArgument('data_fixtures_path'));
+        
+        $this->notify('Data was successfully loaded');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/Migrate.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: Migrate.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_Migrate
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_Migrate extends Doctrine_Task
+{
+    public $description          =   'Migrate database to latest version or the specified version',
+           $requiredArguments    =   array('migrations_path' => 'Specify path to your migrations directory.'),
+           $optionalArguments    =   array('version' => 'Version to migrate to. If you do not specify, the db will be migrated from the current version to the latest.');
+    
+    public function execute()
+    {
+        $version = Doctrine::migrate($this->getArgument('migrations_path'), $this->getArgument('version'));
+        
+        $this->notify('migrated successfully to version #' . $version);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Task/RebuildDb.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,58 @@
+<?php
+/*
+ *  $Id: RebuildDb.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_RebuildDb
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_RebuildDb extends Doctrine_Task
+{
+    public $description          =   'Drops and re-creates databases',
+           $requiredArguments    =   array(),
+           $optionalArguments    =   array();
+    
+    public function __construct($dispatcher = null)
+    {
+        parent::__construct($dispatcher);
+        
+        $this->dropDb = new Doctrine_Task_DropDb($this->dispatcher);
+        $this->buildAll = new Doctrine_Task_BuildAll($this->dispatcher);
+        
+        $this->requiredArguments = array_merge($this->requiredArguments, $this->dropDb->requiredArguments, $this->buildAll->requiredArguments);
+        $this->optionalArguments = array_merge($this->optionalArguments, $this->dropDb->optionalArguments, $this->buildAll->optionalArguments);
+    }
+    
+    public function execute()
+    {
+        $this->dropDb->setArguments($this->getArguments());
+        $this->dropDb->execute();
+        
+        $this->buildAll->setArguments($this->getArguments());
+        $this->buildAll->execute();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,152 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Base abstract class for defining templates which are the base of all behaviors that can be attached
+ * to your Doctrine models
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+abstract class Doctrine_Template extends Doctrine_Record_Abstract
+{
+    /**
+     * @var Doctrine_Record $_invoker     the record that invoked the last delegated call
+     */
+    protected $_invoker;
+
+    /**
+     * @var Doctrine_Record_Generator $_plugin
+     */
+    protected $_plugin;
+
+    /**
+     * Set the table object that this Template belongs to
+     *
+     * @var Doctrine_Table $table        the table object this Template belongs to
+     */
+    public function setTable(Doctrine_Table $table)
+    {
+        $this->_table = $table;
+    }
+
+    /**
+     * returns the associated table object
+     *
+     * @return Doctrine_Table               the associated table object
+     */
+    public function getTable()
+    {
+        return $this->_table;
+    }
+
+    /**
+     * sets the last used invoker
+     *
+     * @param Doctrine_Record $invoker      the record that invoked the last delegated call
+     * @return Doctrine_Template            this object
+     */
+    public function setInvoker(Doctrine_Record_Abstract $invoker)
+    {
+        $this->_invoker = $invoker;
+    }
+
+    /**
+     * returns the last used invoker
+     *
+     * @return Doctrine_Record              the record that invoked the last delegated call
+     */
+    public function getInvoker()
+    {
+        return $this->_invoker;
+    }
+
+    /**
+     * Adds a plugin as a child to this plugin
+     * 
+     * @param Doctrine_Template $template 
+     * @return Doctrine_Template. Chainable.
+     */
+    public function addChild(Doctrine_Template $template)
+    {
+        $this->_plugin->addChild($template);
+        
+        return $this;
+    }
+
+    /**
+     * Get plugin instance 
+     * 
+     * @return void
+     */
+    public function getPlugin()
+    {
+        return $this->_plugin;
+    }
+
+    /**
+     * get 
+     * 
+     * @param mixed $name 
+     * @return void
+     */
+    public function get($name) 
+    {
+        throw new Doctrine_Exception("Templates doesn't support accessors.");
+    }
+
+    /**
+     * set 
+     * 
+     * @param mixed $name 
+     * @param mixed $value 
+     * @return void
+     */
+    public function set($name, $value)
+    {
+        throw new Doctrine_Exception("Templates doesn't support accessors.");
+    }
+
+    /**
+     * Blank method for template setup 
+     * 
+     * @return void
+     */
+    public function setUp()
+    {
+
+    }
+
+    /**
+     * Blank method for template table definition
+     * 
+     * @return void
+     */
+    public function setTableDefinition()
+    {
+
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Geographical.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,133 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Easily add longitude and latitude columns to your records and use inherited functionality for 
+ * calculating distances
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jonwage@gmail.com>
+ */
+class Doctrine_Template_Geographical extends Doctrine_Template
+{
+    /**
+     * Array of geographical options
+     *
+     * @var string
+     */
+    protected $_options = array('latitude' =>  array('name'     =>  'latitude',
+                                                     'type'     =>  'float',
+                                                     'size'     =>  null,
+                                                     'options'  =>  array()),
+                                'longitude' => array('name'     =>  'longitude',
+                                                     'type'     =>  'float',
+                                                     'size'     =>  null,
+                                                     'options'  =>  array()));
+
+    /**
+     * __construct
+     *
+     * @param string $array 
+     * @return void
+     */
+    public function __construct(array $options = array())
+    {
+        $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
+    }
+
+    /**
+     * Set table definition for Geographical behavior
+     *
+     * @return void
+     */
+    public function setTableDefinition()
+    {
+        $this->hasColumn($this->_options['latitude']['name'], $this->_options['latitude']['type'], $this->_options['latitude']['size'], $this->_options['latitude']['options']);
+        $this->hasColumn($this->_options['longitude']['name'], $this->_options['longitude']['type'], $this->_options['longitude']['size'], $this->_options['longitude']['options']);
+    }
+
+    /**
+     * Initiate and get a distance query with the select parts for the number of kilometers and miles 
+     * between this record and other zipcode records in the database
+     *
+     * @return Doctrine_Query $query
+     */
+    public function getDistanceQuery()
+    {
+        $invoker = $this->getInvoker();
+        $query = $invoker->getTable()->createQuery();
+
+        $rootAlias = $query->getRootAlias();
+        $latName = $this->_options['latitude']['name'];
+        $longName = $this->_options['longitude']['name'];
+
+        $query->addSelect($rootAlias . '.*');
+
+        $sql = "((ACOS(SIN(%s * PI() / 180) * SIN(" . $rootAlias . "." . $latName . " * PI() / 180) + COS(%s * PI() / 180) * COS(" . $rootAlias . "." . $latName . " * PI() / 180) * COS((%s - " . $rootAlias . "." . $longName . ") * PI() / 180)) * 180 / PI()) * 60 * %s) as %s";
+
+        $milesSql = sprintf($sql, $invoker->get('latitude'), $invoker->get('latitude'), $invoker->get('longitude'), '1.1515', 'miles');
+        $query->addSelect($milesSql);
+
+        $kilometersSql = sprintf($sql, $invoker->get('latitude'), $invoker->get('latitude'), $invoker->get('longitude'), '1.1515 * 1.609344', 'kilometers');
+        $query->addSelect($kilometersSql);
+
+        return $query;
+    }
+
+    /**
+     * Get distance between this record and another
+     *
+     * @param string $Doctrine_Record 
+     * @param string $kilometers 
+     * @return integer
+     */
+    public function getDistance(Doctrine_Record $record, $kilometers = false)
+    {
+        $query = $this->getDistanceQuery($kilometers);
+        
+        $conditions = array();
+        $values = array();
+        foreach ((array) $record->getTable()->getIdentifier() as $id) {
+            $conditions[] = $query->getRootAlias() . '.' . $id . ' = ?';
+            $values[] = $record->get($id);
+        }
+
+        $where = implode(' AND ', $conditions);
+
+        $query->addWhere($where, $values);
+
+        $query->limit(1);
+
+        $result = $query->execute()->getFirst();
+        
+        if (isset($result['kilometers']) && $result['miles']) {
+            return $kilometers ? $result->get('kilometers'):$result->get('miles');
+        } else {
+            return 0;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/I18n.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,65 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Add multilingual capabilities to your Doctrine models
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Template_I18n extends Doctrine_Template
+{
+    /**
+     * __construct
+     *
+     * @param string $array 
+     * @return void
+     */
+    public function __construct(array $options = array())
+    {
+        $this->_plugin = new Doctrine_I18n($options);
+    }
+
+    /**
+     * Initialize the I18n plugin for the template
+     *
+     * @return void
+     */
+    public function setUp()
+    {
+        $this->_plugin->initialize($this->_table); 
+    }
+
+    /**
+     * Get the plugin instance for the I18n template
+     *
+     * @return void
+     */
+    public function getI18n()
+    {
+        return $this->_plugin;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Listener/Sluggable.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,221 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Easily create a slug for each record based on a specified set of fields
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Template_Listener_Sluggable extends Doctrine_Record_Listener
+{
+    /**
+     * Array of sluggable options
+     *
+     * @var string
+     */
+    protected $_options = array();
+
+    /**
+     * __construct
+     *
+     * @param string $array 
+     * @return void
+     */
+    public function __construct(array $options)
+    {
+        $this->_options = $options;
+    }
+
+    /**
+     * Set the slug value automatically when a record is inserted
+     *
+     * @param Doctrine_Event $event 
+     * @return void
+     */
+    public function preInsert(Doctrine_Event $event)
+    {
+        $record = $event->getInvoker();
+        $name = $record->getTable()->getFieldName($this->_options['name']);
+
+        if ( ! $record->$name) {
+            $record->$name = $this->buildSlugFromFields($record);
+        }
+    }
+
+    /**
+     * Set the slug value automatically when a record is updated if the options are configured
+     * to allow it
+     *
+     * @param Doctrine_Event $event 
+     * @return void
+     */
+    public function preUpdate(Doctrine_Event $event)
+    {
+        if (false !== $this->_options['unique']) {
+            $record = $event->getInvoker();
+            $name = $record->getTable()->getFieldName($this->_options['name']);
+
+            if ( ! $record->$name || (
+                false !== $this->_options['canUpdate'] && 
+                ! array_key_exists($name, $record->getModified())
+            )) {
+                $record->$name = $this->buildSlugFromFields($record);
+            } else if ( ! empty($record->$name) && 
+                false !== $this->_options['canUpdate'] && 
+                array_key_exists($name, $record->getModified()
+            )) {
+                $record->$name = $this->buildSlugFromSlugField($record);
+            }
+        }
+    }
+
+    /**
+     * Generate the slug for a given Doctrine_Record based on the configured options
+     *
+     * @param Doctrine_Record $record 
+     * @return string $slug
+     */
+    protected function buildSlugFromFields($record)
+    {
+        if (empty($this->_options['fields'])) {
+            if (method_exists($record, 'getUniqueSlug')) {
+                $value = $record->getUniqueSlug($record);
+            } else {
+                $value = (string) $record;
+            }
+        } else {
+            $value = '';
+
+            foreach ($this->_options['fields'] as $field) {
+                $value .= $record->$field . ' ';
+            }
+
+            if ($this->_options['unique'] === true) {   
+                return $this->getUniqueSlug($record, $value);
+            }
+        }
+
+        return call_user_func_array($this->_options['builder'], array($value, $record));
+    }
+
+    /**
+     * Generate the slug for a given Doctrine_Record slug field
+     *
+     * @param Doctrine_Record $record 
+     * @return string $slug
+     */
+    protected function buildSlugFromSlugField($record)
+    {
+        $name = $record->getTable()->getFieldName($this->_options['name']);
+        $value = $record->$name;
+
+        if ($this->_options['unique'] === true) {   
+            return $this->getUniqueSlug($record, $value);
+        }
+
+        return call_user_func_array($this->_options['builder'], array($value, $record));
+    }
+
+
+    /**
+     * Creates a unique slug for a given Doctrine_Record. This function enforces the uniqueness by 
+     * incrementing the values with a postfix if the slug is not unique
+     *
+     * @param Doctrine_Record $record 
+     * @param string $slugFromFields
+     * @return string $slug
+     */
+    public function getUniqueSlug($record, $slugFromFields) 
+    {
+        $name = $record->getTable()->getFieldName($this->_options['name']);
+		$proposal =  call_user_func_array($this->_options['builder'], array($slugFromFields, $record));
+        $slug = $proposal;
+
+        $whereString = 'r.' . $name . ' LIKE ?';
+        $whereParams = array($proposal.'%');
+        
+        if ($record->exists()) {
+            $identifier = $record->identifier();
+            $whereString .= ' AND r.' . implode(' != ? AND r.', $record->getTable()->getIdentifierColumnNames()) . ' != ?';
+            $whereParams = array_merge($whereParams, array_values($identifier));
+        }
+
+        foreach ($this->_options['uniqueBy'] as $uniqueBy) {
+            if (is_null($record->$uniqueBy)) {
+                $whereString .= ' AND r.'.$uniqueBy.' IS NULL';
+            } else {
+                $whereString .= ' AND r.'.$uniqueBy.' = ?';
+                $whereParams[] =  $record->$uniqueBy;
+            }
+        }
+
+        // Disable indexby to ensure we get all records
+        $originalIndexBy = $record->getTable()->getBoundQueryPart('indexBy');
+        $record->getTable()->bindQueryPart('indexBy', null);
+
+        $query = Doctrine_Query::create()
+        ->select('r.'.$name)
+        ->from(get_class($record).' r')
+        ->where($whereString , $whereParams)
+        ->setHydrationMode(Doctrine::HYDRATE_ARRAY);
+
+        // We need to introspect SoftDelete to check if we are not disabling unique records too
+        if ($record->getTable()->hasTemplate('Doctrine_Template_SoftDelete')) {
+	        $softDelete = $record->getTable()->getTemplate('Doctrine_Template_SoftDelete');
+	
+	        // we have to consider both situations here
+            $query->addWhere('(r.' . $softDelete->getOption('name') . ' = true OR r.' . $softDelete->getOption('name') . ' IS NOT NULL OR r.' . $softDelete->getOption('name') . ' = false OR r.' . $softDelete->getOption('name') . ' IS NULL)');
+        }
+
+        $similarSlugResult = $query->execute();
+        $query->free();
+
+        // Change indexby back
+        $record->getTable()->bindQueryPart('indexBy', $originalIndexBy);
+
+        $similarSlugs = array();
+        foreach ($similarSlugResult as $key => $value) {
+            $similarSlugs[$key] = $value[$name];
+        }
+
+        $i = 1;
+        while (in_array($slug, $similarSlugs)) {
+            $slug = call_user_func_array($this->_options['builder'], array($proposal.'-'.$i, $record)); 
+            $i++;
+        }
+
+        // If slug is longer then the column length then we need to trim it
+        // and try to generate a unique slug again
+        $length = $record->getTable()->getFieldLength($this->_options['name']);
+        if (strlen($slug) > $length) {
+            $slug = substr($slug, 0, $length - (strlen($i) + 1));
+            $slug = $this->getUniqueSlug($record, $slug);
+        }
+
+        return  $slug;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Listener/SoftDelete.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,119 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Listener for SoftDelete behavior which will allow you to turn on the behavior which
+ * sets a delete flag instead of actually deleting the record and all queries automatically
+ * include a check for the deleted flag to exclude deleted records.
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jonwage@gmail.com>
+ */
+class Doctrine_Template_Listener_SoftDelete extends Doctrine_Record_Listener
+{
+    /**
+     * Array of SoftDelete options
+     *
+     * @var string
+     */
+    protected $_options = array();
+
+    /**
+     * __construct
+     *
+     * @param string $options 
+     * @return void
+     */
+    public function __construct(array $options)
+    {
+        $this->_options = $options;
+    }
+
+    /**
+     * Skip the normal delete options so we can override it with our own
+     *
+     * @param Doctrine_Event $event
+     * @return void
+     */
+    public function preDelete(Doctrine_Event $event)
+    {
+        $event->skipOperation();
+    }
+
+    /**
+     * Implement postDelete() hook and set the deleted flag to true
+     *
+     * @param Doctrine_Event $event
+     * @return void
+     */
+    public function postDelete(Doctrine_Event $event)
+    {
+        $name = $this->_options['name'];
+        $event->getInvoker()->$name = true;
+        $event->getInvoker()->save();
+    }
+
+    /**
+     * Implement preDqlDelete() hook and modify a dql delete query so it updates the deleted flag
+     * instead of deleting the record
+     *
+     * @param Doctrine_Event $event
+     * @return void
+     */
+    public function preDqlDelete(Doctrine_Event $event)
+    {
+        $params = $event->getParams();
+        $field = $params['alias'] . '.' . $this->_options['name'];
+        $query = $event->getQuery();
+        if ( ! $query->contains($field)) {
+            $query->from('')->update($params['component']['table']->getOption('name') . ' ' . $params['alias']);
+            $query->set($field, '?', array('true'));
+            $query->addWhere(
+                $field . ' = ' . $query->getConnection()->convertBooleans(false) . ' OR ' . $field . ' IS NULL'
+            );
+        }
+    }
+
+    /**
+     * Implement preDqlSelect() hook and add the deleted flag to all queries for which this model 
+     * is being used in.
+     *
+     * @param Doctrine_Event $event 
+     * @return void
+     */
+    public function preDqlSelect(Doctrine_Event $event)
+    {
+        $params = $event->getParams();
+        $field = $params['alias'] . '.' . $this->_options['name'];
+        $query = $event->getQuery();
+        if ( ! $query->contains($field)) {
+            $query->addWhere(
+                $field . ' = ' . $query->getConnection()->convertBooleans(false) . ' OR ' . $field . ' IS NULL'
+            );
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Listener/Timestampable.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,138 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Listener for the Timestampable behavior which automatically sets the created
+ * and updated columns when a record is inserted and updated.
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Template_Listener_Timestampable extends Doctrine_Record_Listener
+{
+    /**
+     * Array of timestampable options
+     *
+     * @var string
+     */
+    protected $_options = array();
+
+    /**
+     * __construct
+     *
+     * @param string $options 
+     * @return void
+     */
+    public function __construct(array $options)
+    {
+        $this->_options = $options;
+    }
+
+    /**
+     * Set the created and updated Timestampable columns when a record is inserted
+     *
+     * @param Doctrine_Event $event
+     * @return void
+     */
+    public function preInsert(Doctrine_Event $event)
+    {
+        if ( ! $this->_options['created']['disabled']) {
+            $createdName = $event->getInvoker()->getTable()->getFieldName($this->_options['created']['name']);
+            $modified = $event->getInvoker()->getModified();
+            if ( ! isset($modified[$createdName])) {
+                $event->getInvoker()->$createdName = $this->getTimestamp('created');
+            }
+        }
+
+        if ( ! $this->_options['updated']['disabled'] && $this->_options['updated']['onInsert']) {
+            $updatedName = $event->getInvoker()->getTable()->getFieldName($this->_options['updated']['name']);
+            $modified = $event->getInvoker()->getModified();
+            if ( ! isset($modified[$updatedName])) {
+                $event->getInvoker()->$updatedName = $this->getTimestamp('updated');
+            }
+        }
+    }
+
+    /**
+     * Set updated Timestampable column when a record is updated
+     *
+     * @param Doctrine_Event $evet
+     * @return void
+     */
+    public function preUpdate(Doctrine_Event $event)
+    {
+        if ( ! $this->_options['updated']['disabled']) {
+            $updatedName = $event->getInvoker()->getTable()->getFieldName($this->_options['updated']['name']);
+            $modified = $event->getInvoker()->getModified();
+            if ( ! isset($modified[$updatedName])) {
+                $event->getInvoker()->$updatedName = $this->getTimestamp('updated');
+            }
+        }
+    }
+
+    /**
+     * Set the updated field for dql update queries
+     *
+     * @param Doctrine_Event $evet
+     * @return void
+     */
+    public function preDqlUpdate(Doctrine_Event $event)
+    {
+        if ( ! $this->_options['updated']['disabled']) {
+            $params = $event->getParams();
+            $updatedName = $event->getInvoker()->getTable()->getFieldName($this->_options['updated']['name']);
+            $field = $params['alias'] . '.' . $updatedName;
+            $query = $event->getQuery();
+
+            if ( ! $query->contains($field)) {
+                $query->set($field, '?', $this->getTimestamp('updated'));
+            }
+        }
+    }
+
+    /**
+     * Gets the timestamp in the correct format based on the way the behavior is configured
+     *
+     * @param string $type 
+     * @return void
+     */
+    public function getTimestamp($type)
+    {
+        $options = $this->_options[$type];
+
+        if ($options['expression'] !== false && is_string($options['expression'])) {
+            return new Doctrine_Expression($options['expression']);
+        } else {
+            if ($options['type'] == 'date') {
+                return date($options['format'], time());
+            } else if ($options['type'] == 'timestamp') {
+                return date($options['format'], time());
+            } else {
+                return time();
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/NestedSet.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,73 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine template which implements the custom NestedSet implementation
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Roman Borschel <roman@code-factory.org>
+ */
+class Doctrine_Template_NestedSet extends Doctrine_Template
+{
+    /**
+     * Array of options for NestedSet implementation
+     *
+     * @var array
+     */
+    private $_options;
+
+    /**
+     * __construct
+     *
+     * @param array $array 
+     * @return void
+     */
+    public function __construct(array $options = array())
+    {
+        $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
+    }
+
+    /**
+     * Set up NestedSet template
+     *
+     * @return void
+     */
+    public function setUp()
+    {
+        $this->_table->setOption('treeOptions', $this->_options);
+        $this->_table->setOption('treeImpl', 'NestedSet');
+    }
+
+    /**
+     * Call set table definition for the NestedSet behavior
+     *
+     * @return void
+     */
+    public function setTableDefinition()
+    {
+        $this->_table->getTree()->setTableDefinition();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Searchable.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,94 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_Searchable
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Template_Searchable extends Doctrine_Template
+{
+    /**
+     * __construct
+     *
+     * @param array $options 
+     * @return void
+     */
+    public function __construct(array $options = array())
+    {
+        $this->_plugin = new Doctrine_Search($options); 
+    }
+
+    /**
+     * Setup the Searchable template behavior
+     *
+     * @return void
+     */
+    public function setUp()
+    {
+        $this->_plugin->initialize($this->_table);
+
+        $this->addListener(new Doctrine_Search_Listener($this->_plugin));
+    }
+
+    /**
+     * Make the batchUpdateIndex() function available to the template so Doctrine_Record child classes
+     * with the behavior enabled can all the function
+     *
+     * @param integer $limit 
+     * @param integer $offset 
+     * @return void
+     */
+    public function batchUpdateIndex($limit = null, $offset = null)
+    {
+        $this->_plugin->batchUpdateIndex($limit, $offset);
+    }
+
+    /**
+     * Proxy method so the batch updating can be called from table classes
+     *
+     * @param integer $limit 
+     * @param integer $offset 
+     * @return void
+     */
+    public function batchUpdateIndexTableProxy($limit = null, $offset = null)
+    {
+        $this->batchUpdateIndex($limit, $offset);
+    }
+
+    /**
+     * Searchable keyword search proxy for Doctrine_Table
+     * 
+     * @param string $string Keyword string to search for
+     * @param Doctrine_Query $query Query object to alter. Adds where condition to limit the results using the search index
+     * @return mixed The Doctrine_Collection or array of ids and relevancy
+     */
+    public function searchTableProxy($string, $query = null)
+    {
+        return $this->_plugin->search($string, $query);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Sluggable.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,89 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_Sluggable
+ *
+ * Easily create a slug for each record based on a specified set of fields
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Template_Sluggable extends Doctrine_Template
+{
+    /**
+     * Array of Sluggable options
+     *
+     * @var string
+     */
+    protected $_options = array('name'          =>  'slug',
+                                'alias'         =>  null,
+                                'type'          =>  'string',
+                                'length'        =>  255,
+                                'unique'        =>  true,
+                                'options'       =>  array(),
+                                'fields'        =>  array(),
+                                'uniqueBy'      =>  array(),
+                                'uniqueIndex'   =>  true,
+                                'canUpdate'     =>  false,
+                                'builder'       =>  array('Doctrine_Inflector', 'urlize'),
+                                'indexName'     =>  'sluggable'
+    );
+
+    /**
+     * __construct
+     *
+     * @param string $array 
+     * @return void
+     */
+    public function __construct(array $options = array())
+    {
+        $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
+    }
+
+    /**
+     * Set table definition for Sluggable behavior
+     *
+     * @return void
+     */
+    public function setTableDefinition()
+    {
+        $name = $this->_options['name'];
+        if ($this->_options['alias']) {
+            $name .= ' as ' . $this->_options['alias'];
+        }
+        $this->hasColumn($name, $this->_options['type'], $this->_options['length'], $this->_options['options']);
+        
+        if ($this->_options['unique'] == true && $this->_options['uniqueIndex'] == true && ! empty($this->_options['fields'])) {
+            $indexFields = array($this->_options['name']);
+            $indexFields = array_merge($indexFields, $this->_options['uniqueBy']);
+            $this->index($this->_options['indexName'], array('fields' => $indexFields,
+                                                             'type' => 'unique'));
+        }
+
+        $this->addListener(new Doctrine_Template_Listener_Sluggable($this->_options));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/SoftDelete.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,79 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_SoftDelete
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jonwage@gmail.com>
+ */
+class Doctrine_Template_SoftDelete extends Doctrine_Template
+{
+    /**
+     * Array of SoftDelete options
+     *
+     * @var string
+     */
+    protected $_options = array('name'          =>  'deleted',
+                                'type'          =>  'boolean',
+                                'length'        =>  1,
+                                'options'       =>  array('default' => false,
+                                                          'notnull' => true,
+                                                          ),
+    );
+
+    /**
+     * __construct
+     *
+     * @param string $array
+     * @return void
+     */
+    public function __construct(array $options = array())
+    {
+        $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
+    }
+
+    /**
+     * Set table definition for SoftDelete behavior
+     *
+     * @return void
+     */
+    public function setTableDefinition()
+    {
+        $this->hasColumn($this->_options['name'], $this->_options['type'], $this->_options['length'], $this->_options['options']);
+
+        $this->addListener(new Doctrine_Template_Listener_SoftDelete($this->_options));
+    }
+
+    /**
+     * @nodoc
+     */
+    public function getOption($name)
+    {
+        return $this->_options[$name];
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Timestampable.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,95 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_Timestampable
+ *
+ * Easily add created and updated at timestamps to your doctrine records that are automatically set
+ * when records are saved
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Template_Timestampable extends Doctrine_Template
+{
+    /**
+     * Array of Timestampable options
+     *
+     * @var string
+     */
+    protected $_options = array('created' =>  array('name'          =>  'created_at',
+                                                    'alias'         =>  null,
+                                                    'type'          =>  'timestamp',
+                                                    'format'        =>  'Y-m-d H:i:s',
+                                                    'disabled'      =>  false,
+                                                    'expression'    =>  false,
+                                                    'options'       =>  array()),
+                                'updated' =>  array('name'          =>  'updated_at',
+                                                    'alias'         =>  null,
+                                                    'type'          =>  'timestamp',
+                                                    'format'        =>  'Y-m-d H:i:s',
+                                                    'disabled'      =>  false,
+                                                    'expression'    =>  false,
+                                                    'onInsert'      =>  true,
+                                                    'options'       =>  array()));
+
+    /**
+     * __construct
+     *
+     * @param string $array 
+     * @return void
+     */
+    public function __construct(array $options = array())
+    {
+        $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
+    }
+
+    /**
+     * Set table definition for Timestampable behavior
+     *
+     * @return void
+     */
+    public function setTableDefinition()
+    {
+        if( ! $this->_options['created']['disabled']) {
+            $name = $this->_options['created']['name'];
+            if ($this->_options['created']['alias']) {
+                $name .= ' as ' . $this->_options['created']['alias'];
+            }
+            $this->hasColumn($name, $this->_options['created']['type'], null, $this->_options['created']['options']);
+        }
+
+        if( ! $this->_options['updated']['disabled']) {
+            $name = $this->_options['updated']['name'];
+            if ($this->_options['updated']['alias']) {
+                $name .= ' as ' . $this->_options['updated']['alias'];
+            }
+            $this->hasColumn($name, $this->_options['updated']['type'], null, $this->_options['updated']['options']);
+        }
+
+        $this->addListener(new Doctrine_Template_Listener_Timestampable($this->_options));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Template/Versionable.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,102 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_Versionable
+ *
+ * Add revisioning/audit log to your models
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Template_Versionable extends Doctrine_Template
+{
+    /**
+     * __construct
+     *
+     * @param array $options
+     * @return void
+     */
+    public function __construct(array $options = array())
+    {
+        $this->_plugin = new Doctrine_AuditLog($options);
+    }
+
+    /**
+     * Setup the Versionable behavior for the template
+     *
+     * @return void
+     */
+    public function setUp()
+    {
+        if ($this->_plugin->getOption('auditLog')) {
+            $this->_plugin->initialize($this->_table);
+        }
+
+        $this->hasColumn('version', 'integer', 8);
+
+        $this->addListener(new Doctrine_AuditLog_Listener($this->_plugin));
+    }
+
+    /**
+     * Get plugin for Versionable template
+     *
+     * @return void
+     */
+    public function getAuditLog()
+    {
+        return $this->_plugin;
+    }
+
+     /**
+     * revert
+     * reverts this record to given version, this method only works if versioning plugin
+     * is enabled
+     *
+     * @throws Doctrine_Record_Exception    if given version does not exist
+     * @param integer $version      an integer > 1
+     * @return Doctrine_Record      this object
+     */
+    public function revert($version)
+    {
+        $auditLog = $this->_plugin;
+
+        if ( ! $auditLog->getOption('auditLog')) {
+            throw new Doctrine_Record_Exception('Audit log is turned off, no version history is recorded.');
+        }
+
+        $data = $auditLog->getVersion($this->getInvoker(), $version);
+
+        if ( ! isset($data[0])) {
+            throw new Doctrine_Record_Exception('Version ' . $version . ' does not exist!');
+        }
+
+        $this->getInvoker()->merge($data[0]);
+
+
+        return $this->getInvoker();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,514 @@
+<?php
+/*
+ *  $Id: Transaction.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Transaction
+ * Handles transaction savepoint and isolation abstraction
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @package     Doctrine
+ * @subpackage  Transaction
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Transaction extends Doctrine_Connection_Module
+{
+    /**
+     * Doctrine_Transaction is in sleep state when it has no active transactions
+     */
+    const STATE_SLEEP       = 0;
+
+    /**
+     * Doctrine_Transaction is in active state when it has one active transaction
+     */
+    const STATE_ACTIVE      = 1;
+
+    /**
+     * Doctrine_Transaction is in busy state when it has multiple active transactions
+     */
+    const STATE_BUSY        = 2;
+
+    /**
+     * @var integer $_nestingLevel      The current nesting level of this transaction.
+     *                                  A nesting level of 0 means there is currently no active
+     *                                  transaction.
+     */
+    protected $_nestingLevel = 0;
+    
+    /**
+     * @var integer $_internalNestingLevel  The current internal nesting level of this transaction.
+     *                                      "Internal" means transactions started by Doctrine itself.
+     *                                      Therefore the internal nesting level is always
+     *                                      lower or equal to the overall nesting level.
+     *                                      A level of 0 means there is currently no active
+     *                                      transaction that was initiated by Doctrine itself.
+     */
+    protected $_internalNestingLevel = 0;
+
+    /**
+     * @var array $invalid                  an array containing all invalid records within this transaction
+     * @todo What about a more verbose name? $invalidRecords?
+     */
+    protected $invalid          = array();
+
+    /**
+     * @var array $savepoints               an array containing all savepoints
+     */
+    protected $savePoints       = array();
+
+    /**
+     * @var array $_collections             an array of Doctrine_Collection objects that were affected during the Transaction
+     */
+    protected $_collections     = array();
+
+    /**
+     * addCollection
+     * adds a collection in the internal array of collections
+     *
+     * at the end of each commit this array is looped over and
+     * of every collection Doctrine then takes a snapshot in order
+     * to keep the collections up to date with the database
+     *
+     * @param Doctrine_Collection $coll     a collection to be added
+     * @return Doctrine_Transaction         this object
+     */
+    public function addCollection(Doctrine_Collection $coll)
+    {
+        $this->_collections[] = $coll;
+
+        return $this;
+    }
+
+    /**
+     * getState
+     * returns the state of this transaction module.
+     *
+     * @see Doctrine_Connection_Transaction::STATE_* constants
+     * @return integer          the connection state
+     */
+    public function getState()
+    {
+        switch ($this->_nestingLevel) {
+            case 0:
+                return Doctrine_Transaction::STATE_SLEEP;
+                break;
+            case 1:
+                return Doctrine_Transaction::STATE_ACTIVE;
+                break;
+            default:
+                return Doctrine_Transaction::STATE_BUSY;
+        }
+    }
+
+    /**
+     * addInvalid
+     * adds record into invalid records list
+     *
+     * @param Doctrine_Record $record
+     * @return boolean        false if record already existed in invalid records list,
+     *                        otherwise true
+     */
+    public function addInvalid(Doctrine_Record $record)
+    {
+        if (in_array($record, $this->invalid, true)) {
+            return false;
+        }
+        $this->invalid[] = $record;
+        return true;
+    }
+
+
+   /**
+    * Return the invalid records
+    *
+    * @return array An array of invalid records
+    */ 
+    public function getInvalid()
+    {
+        return $this->invalid;
+    }
+
+    /**
+     * getTransactionLevel
+     * get the current transaction nesting level
+     *
+     * @return integer
+     */
+    public function getTransactionLevel()
+    {
+        return $this->_nestingLevel;
+    }
+    
+    public function getInternalTransactionLevel()
+    {
+        return $this->_internalNestingLevel;
+    }
+
+    /**
+     * beginTransaction
+     * Start a transaction or set a savepoint.
+     *
+     * if trying to set a savepoint and there is no active transaction
+     * a new transaction is being started
+     *
+     * This method should only be used by userland-code to initiate transactions.
+     * To initiate a transaction from inside Doctrine use {@link beginInternalTransaction()}.
+     *
+     * Listeners: onPreTransactionBegin, onTransactionBegin
+     *
+     * @param string $savepoint                 name of a savepoint to set
+     * @throws Doctrine_Transaction_Exception   if the transaction fails at database level     
+     * @return integer                          current transaction nesting level
+     */
+    public function beginTransaction($savepoint = null)
+    {
+        $this->conn->connect();
+        
+        $listener = $this->conn->getAttribute(Doctrine::ATTR_LISTENER);
+
+        if ( ! is_null($savepoint)) {
+            $this->savePoints[] = $savepoint;
+
+            $event = new Doctrine_Event($this, Doctrine_Event::SAVEPOINT_CREATE);
+
+            $listener->preSavepointCreate($event);
+
+            if ( ! $event->skipOperation) {
+                $this->createSavePoint($savepoint);
+            }
+
+            $listener->postSavepointCreate($event);
+        } else {
+            if ($this->_nestingLevel == 0) {
+                $event = new Doctrine_Event($this, Doctrine_Event::TX_BEGIN);
+
+                $listener->preTransactionBegin($event);
+
+                if ( ! $event->skipOperation) {
+                    try {
+                        $this->_doBeginTransaction();
+                    } catch (Exception $e) {
+                        throw new Doctrine_Transaction_Exception($e->getMessage());
+                    }
+                }
+                $listener->postTransactionBegin($event);
+            }
+        }
+
+        $level = ++$this->_nestingLevel;
+
+        return $level;
+    }
+
+    /**
+     * Commit the database changes done during a transaction that is in
+     * progress or release a savepoint. This function may only be called when
+     * auto-committing is disabled, otherwise it will fail.
+     *
+     * Listeners: preTransactionCommit, postTransactionCommit
+     *
+     * @param string $savepoint                 name of a savepoint to release
+     * @throws Doctrine_Transaction_Exception   if the transaction fails at database level
+     * @throws Doctrine_Validator_Exception     if the transaction fails due to record validations
+     * @return boolean                          false if commit couldn't be performed, true otherwise
+     */
+    public function commit($savepoint = null)
+    {
+        if ($this->_nestingLevel == 0) {
+            throw new Doctrine_Transaction_Exception("Commit failed. There is no active transaction.");
+        }
+        
+        $this->conn->connect();
+
+        $listener = $this->conn->getAttribute(Doctrine::ATTR_LISTENER);
+
+        if ( ! is_null($savepoint)) {
+            $this->_nestingLevel -= $this->removeSavePoints($savepoint);
+
+            $event = new Doctrine_Event($this, Doctrine_Event::SAVEPOINT_COMMIT);
+
+            $listener->preSavepointCommit($event);
+
+            if ( ! $event->skipOperation) {
+                $this->releaseSavePoint($savepoint);
+            }
+
+            $listener->postSavepointCommit($event);
+        } else {
+                 
+            if ($this->_nestingLevel == 1 || $this->_internalNestingLevel == 1) {
+                if ( ! empty($this->invalid)) {
+                    if ($this->_internalNestingLevel == 1) {
+                        $tmp = $this->invalid;
+                        $this->invalid = array();
+                        throw new Doctrine_Validator_Exception($tmp);
+                    }
+                }
+                if ($this->_nestingLevel == 1) {
+                    // take snapshots of all collections used within this transaction
+                    foreach ($this->_collections as $coll) {
+                        $coll->takeSnapshot();
+                    }
+                    $this->_collections = array();
+
+                    $event = new Doctrine_Event($this, Doctrine_Event::TX_COMMIT);
+
+                    $listener->preTransactionCommit($event);
+                    if ( ! $event->skipOperation) {
+                        $this->_doCommit();
+                    }
+                    $listener->postTransactionCommit($event);
+                }
+            }
+            
+            if ($this->_nestingLevel > 0) {
+                $this->_nestingLevel--;
+            }            
+            if ($this->_internalNestingLevel > 0) {
+                $this->_internalNestingLevel--;
+            } 
+        }
+
+        return true;
+    }
+
+    /**
+     * rollback
+     * Cancel any database changes done during a transaction or since a specific
+     * savepoint that is in progress. This function may only be called when
+     * auto-committing is disabled, otherwise it will fail. Therefore, a new
+     * transaction is implicitly started after canceling the pending changes.
+     *
+     * this method can be listened with onPreTransactionRollback and onTransactionRollback
+     * eventlistener methods
+     *
+     * @param string $savepoint                 name of a savepoint to rollback to   
+     * @throws Doctrine_Transaction_Exception   if the rollback operation fails at database level
+     * @return boolean                          false if rollback couldn't be performed, true otherwise
+     * @todo Shouldnt this method only commit a rollback if the transactionLevel is 1
+     *       (STATE_ACTIVE)? Explanation: Otherwise a rollback that is triggered from inside doctrine
+     *       in an (emulated) nested transaction would lead to a complete database level
+     *       rollback even though the client code did not yet want to do that.
+     *       In other words: if the user starts a transaction doctrine shouldnt roll it back.
+     *       Doctrine should only roll back transactions started by doctrine. Thoughts?
+     */
+    public function rollback($savepoint = null)
+    {
+        if ($this->_nestingLevel == 0) {
+            throw new Doctrine_Transaction_Exception("Rollback failed. There is no active transaction.");
+        }
+        
+        $this->conn->connect();
+
+        if ($this->_internalNestingLevel >= 1 && $this->_nestingLevel > 1) {
+            $this->_internalNestingLevel--;
+            $this->_nestingLevel--;
+            return false;
+        } else if ($this->_nestingLevel > 1) {
+            $this->_nestingLevel--;
+            return false;
+        }
+
+        $listener = $this->conn->getAttribute(Doctrine::ATTR_LISTENER);
+
+        if ( ! is_null($savepoint)) {
+            $this->_nestingLevel -= $this->removeSavePoints($savepoint);
+
+            $event = new Doctrine_Event($this, Doctrine_Event::SAVEPOINT_ROLLBACK);
+
+            $listener->preSavepointRollback($event);
+            
+            if ( ! $event->skipOperation) {
+                $this->rollbackSavePoint($savepoint);
+            }
+
+            $listener->postSavepointRollback($event);
+        } else {
+            $event = new Doctrine_Event($this, Doctrine_Event::TX_ROLLBACK);
+    
+            $listener->preTransactionRollback($event);
+            
+            if ( ! $event->skipOperation) {
+                $this->_nestingLevel = 0;
+                $this->_internalNestingLevel = 0;
+                try {
+                    $this->_doRollback();
+                } catch (Exception $e) {
+                    throw new Doctrine_Transaction_Exception($e->getMessage());
+                }
+            }
+
+            $listener->postTransactionRollback($event);
+        }
+
+        return true;
+    }
+
+    /**
+     * releaseSavePoint
+     * creates a new savepoint
+     *
+     * @param string $savepoint     name of a savepoint to create
+     * @return void
+     */
+    protected function createSavePoint($savepoint)
+    {
+        throw new Doctrine_Transaction_Exception('Savepoints not supported by this driver.');
+    }
+
+    /**
+     * releaseSavePoint
+     * releases given savepoint
+     *
+     * @param string $savepoint     name of a savepoint to release
+     * @return void
+     */
+    protected function releaseSavePoint($savepoint)
+    {
+        throw new Doctrine_Transaction_Exception('Savepoints not supported by this driver.');
+    }
+
+    /**
+     * rollbackSavePoint
+     * releases given savepoint
+     *
+     * @param string $savepoint     name of a savepoint to rollback to
+     * @return void
+     */
+    protected function rollbackSavePoint($savepoint)
+    {
+        throw new Doctrine_Transaction_Exception('Savepoints not supported by this driver.');
+    }
+    
+    /**
+     * Performs the rollback.
+     */
+    protected function _doRollback()
+    {
+        $this->conn->getDbh()->rollback();
+    }
+    
+    /**
+     * Performs the commit.
+     */
+    protected function _doCommit()
+    {
+        $this->conn->getDbh()->commit();
+    }
+    
+    /**
+     * Begins a database transaction.
+     */
+    protected function _doBeginTransaction()
+    {
+        $this->conn->getDbh()->beginTransaction();
+    }
+
+    /**
+     * removeSavePoints
+     * removes a savepoint from the internal savePoints array of this transaction object
+     * and all its children savepoints
+     *
+     * @param sring $savepoint      name of the savepoint to remove
+     * @return integer              removed savepoints
+     */
+    private function removeSavePoints($savepoint)
+    {
+        $this->savePoints = array_values($this->savePoints);
+
+        $found = false;
+        $i = 0;
+
+        foreach ($this->savePoints as $key => $sp) {
+            if ( ! $found) {
+                if ($sp === $savepoint) {
+                    $found = true;
+                }
+            }
+            if ($found) {
+                $i++;
+                unset($this->savePoints[$key]);
+            }
+        }
+
+        return $i;
+    }
+
+    /**
+     * setIsolation
+     *
+     * Set the transacton isolation level.
+     * (implemented by the connection drivers)
+     *
+     * example:
+     *
+     * <code>
+     * $tx->setIsolation('READ UNCOMMITTED');
+     * </code>
+     *
+     * @param   string  standard isolation level
+     *                  READ UNCOMMITTED (allows dirty reads)
+     *                  READ COMMITTED (prevents dirty reads)
+     *                  REPEATABLE READ (prevents nonrepeatable reads)
+     *                  SERIALIZABLE (prevents phantom reads)
+     *
+     * @throws Doctrine_Transaction_Exception           if the feature is not supported by the driver
+     * @throws PDOException                             if something fails at the PDO level
+     * @return void
+     */
+    public function setIsolation($isolation)
+    {
+        throw new Doctrine_Transaction_Exception('Transaction isolation levels not supported by this driver.');
+    }
+
+    /**
+     * getTransactionIsolation
+     *
+     * fetches the current session transaction isolation level
+     *
+     * note: some drivers may support setting the transaction isolation level
+     * but not fetching it
+     *
+     * @throws Doctrine_Transaction_Exception           if the feature is not supported by the driver
+     * @throws PDOException                             if something fails at the PDO level
+     * @return string                                   returns the current session transaction isolation level
+     */
+    public function getIsolation()
+    {
+        throw new Doctrine_Transaction_Exception('Fetching transaction isolation level not supported by this driver.');
+    }
+    
+    /**
+     * Initiates a transaction.
+     *
+     * This method must only be used by Doctrine itself to initiate transactions.
+     * Userland-code must use {@link beginTransaction()}.
+     */
+    public function beginInternalTransaction($savepoint = null)
+    {
+        $this->_internalNestingLevel++;
+        return $this->beginTransaction($savepoint);
+    }
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Transaction_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Transaction
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @link        www.phpdoctrine.org
+ */
+class Doctrine_Transaction_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Firebird.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,140 @@
+<?php
+/*
+ *  $Id: Firebird.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @package     Doctrine
+ * @subpackage  Transaction
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Transaction_Firebird extends Doctrine_Transaction
+{
+    /**
+     * createSavepoint
+     * creates a new savepoint
+     *
+     * @param string $savepoint     name of a savepoint to set
+     * @return void
+     */
+    protected function createSavePoint($savepoint)
+    {
+        $query = 'SAVEPOINT ' . $savepoint;
+
+        return $this->conn->execute($query);
+    }
+
+    /**
+     * releaseSavePoint
+     * releases given savepoint
+     *
+     * @param string $savepoint     name of a savepoint to release
+     * @return void
+     */
+    protected function releaseSavePoint($savepoint)
+    {
+        $query = 'RELEASE SAVEPOINT ' . $savepoint;
+
+        return $this->conn->execute($query);
+    }
+
+    /**
+     * rollbackSavePoint
+     * releases given savepoint
+     *
+     * @param string $savepoint     name of a savepoint to rollback to
+     * @return void
+     */
+    protected function rollbackSavePoint($savepoint)
+    {
+        $query = 'ROLLBACK TO SAVEPOINT '.$savepoint;
+
+        return $this->conn->execute($query);
+    }
+
+    /**
+     * Set the transacton isolation level.
+     *
+     * @param   string  standard isolation level (SQL-92)
+     *                  READ UNCOMMITTED (allows dirty reads)
+     *                  READ COMMITTED (prevents dirty reads)
+     *                  REPEATABLE READ (prevents nonrepeatable reads)
+     *                  SERIALIZABLE (prevents phantom reads)
+     *
+     * @param   array some transaction options:
+     *                  'wait' => 'WAIT' | 'NO WAIT'
+     *                  'rw'   => 'READ WRITE' | 'READ ONLY'
+     *
+     * @throws PDOException                         if something fails at the PDO level
+     * @throws Doctrine_Transaction_Exception       if using unknown isolation level or unknown wait option
+     * @return void
+     */
+    public function setIsolation($isolation, $options = array()) {
+        switch ($isolation) {
+            case 'READ UNCOMMITTED':
+                $nativeIsolation = 'READ COMMITTED RECORD_VERSION';
+                break;
+            case 'READ COMMITTED':
+                $nativeIsolation = 'READ COMMITTED NO RECORD_VERSION';
+                break;
+            case 'REPEATABLE READ':
+                $nativeIsolation = 'SNAPSHOT';
+                break;
+            case 'SERIALIZABLE':
+                $nativeIsolation = 'SNAPSHOT TABLE STABILITY';
+                break;
+            default:
+                throw new Doctrine_Transaction_Exception('isolation level is not supported: ' . $isolation);
+        }
+
+        $rw = $wait = '';
+
+        if (isset($options['wait'])) {
+            switch ($options['wait']) {
+                case 'WAIT':
+                case 'NO WAIT':
+                    $wait = ' ' . $options['wait'];
+                break;
+                default:
+                    throw new Doctrine_Transaction_Exception('wait option is not supported: ' . $options['wait']);
+            }
+        }
+
+        if (isset($options['rw'])) {
+            switch ($options['rw']) {
+                case 'READ ONLY':
+                case 'READ WRITE':
+                    $rw = ' ' . $options['rw'];
+                    break;
+                default:
+                    throw new Doctrine_Transaction_Exception('wait option is not supported: ' . $options['rw']);
+            }
+        }
+
+        $query = 'SET TRANSACTION' . $rw . $wait .' ISOLATION LEVEL ' . $nativeIsolation;
+
+        $this->conn->execute($query);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Informix.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Informix.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @package     Doctrine
+ * @subpackage  Transaction
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Transaction_Informix extends Doctrine_Transaction
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Mock.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,36 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Transaction_Mock
+ * This class is used for testing purposes
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @package     Doctrine
+ * @subpackage  Transaction
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ */
+class Doctrine_Transaction_Mock extends Doctrine_Transaction
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Mssql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,92 @@
+<?php
+/*
+ *  $Id: Mssql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @package     Doctrine
+ * @subpackage  Transaction
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Transaction_Mssql extends Doctrine_Transaction
+{
+    /**
+     * Set the transacton isolation level.
+     *
+     * @param   string  standard isolation level (SQL-92)
+     *      portable modes:
+     *                  READ UNCOMMITTED (allows dirty reads)
+     *                  READ COMMITTED (prevents dirty reads)
+     *                  REPEATABLE READ (prevents nonrepeatable reads)
+     *                  SERIALIZABLE (prevents phantom reads)
+     *      mssql specific modes:
+     *                  SNAPSHOT
+     *
+     * @link http://msdn2.microsoft.com/en-us/library/ms173763.aspx
+     * @throws PDOException                         if something fails at the PDO level
+     * @throws Doctrine_Transaction_Exception       if using unknown isolation level or unknown wait option
+     * @return void
+     */
+    public function setIsolation($isolation, $options = array()) {
+        switch ($isolation) {
+            case 'READ UNCOMMITTED':
+            case 'READ COMMITTED':
+            case 'REPEATABLE READ':
+            case 'SERIALIZABLE':
+            case 'SNAPSHOT':
+                break;
+            default:
+                throw new Doctrine_Transaction_Exception('isolation level is not supported: ' . $isolation);
+        }
+
+        $query = 'SET TRANSACTION ISOLATION LEVEL ' . $isolation;
+
+        $this->conn->execute($query);
+    }
+    
+    /**
+     * Performs the rollback.
+     */
+    protected function _doRollback()
+    {
+        $this->conn->getDbh()->exec('ROLLBACK TRANSACTION');
+    }
+    
+    /**
+     * Performs the commit.
+     */
+    protected function _doCommit()
+    {
+        $this->conn->getDbh()->exec('COMMIT TRANSACTION');
+    }
+    
+    /**
+     * Begins a database transaction.
+     */
+    protected function _doBeginTransaction()
+    {
+        $this->conn->getDbh()->exec('BEGIN TRANSACTION');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Mysql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,116 @@
+<?php
+/*
+ *  $Id: Mysql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @package     Doctrine
+ * @subpackage  Transaction
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Transaction_Mysql extends Doctrine_Transaction
+{
+    /**
+     * createSavepoint
+     * creates a new savepoint
+     *
+     * @param string $savepoint     name of a savepoint to set
+     * @return void
+     */
+    protected function createSavePoint($savepoint)
+    {
+        $query = 'SAVEPOINT ' . $savepoint;
+
+        return $this->conn->execute($query);
+    }
+
+    /**
+     * releaseSavePoint
+     * releases given savepoint
+     *
+     * @param string $savepoint     name of a savepoint to release
+     * @return void
+     */
+    protected function releaseSavePoint($savepoint)
+    {
+        $query = 'RELEASE SAVEPOINT ' . $savepoint;
+
+        return $this->conn->execute($query);
+    }
+
+    /**
+     * rollbackSavePoint
+     * releases given savepoint
+     *
+     * @param string $savepoint     name of a savepoint to rollback to
+     * @return void
+     */
+    protected function rollbackSavePoint($savepoint)
+    {
+        $query = 'ROLLBACK TO SAVEPOINT ' . $savepoint;
+
+        return $this->conn->execute($query);
+    }
+
+    /**
+     * Set the transacton isolation level.
+     *
+     * @param   string  standard isolation level
+     *                  READ UNCOMMITTED (allows dirty reads)
+     *                  READ COMMITTED (prevents dirty reads)
+     *                  REPEATABLE READ (prevents nonrepeatable reads)
+     *                  SERIALIZABLE (prevents phantom reads)
+     *
+     * @throws Doctrine_Transaction_Exception           if using unknown isolation level
+     * @throws PDOException                             if something fails at the PDO level
+     * @return void
+     */
+    public function setIsolation($isolation)
+    {
+        switch ($isolation) {
+            case 'READ UNCOMMITTED':
+            case 'READ COMMITTED':
+            case 'REPEATABLE READ':
+            case 'SERIALIZABLE':
+                break;
+            default:
+                throw new Doctrine_Transaction_Exception('Isolation level ' . $isolation . ' is not supported.');
+        }
+
+        $query = 'SET SESSION TRANSACTION ISOLATION LEVEL ' . $isolation;
+
+        return $this->conn->execute($query);
+    }
+
+    /**
+     * getTransactionIsolation
+     *
+     * @return string               returns the current session transaction isolation level
+     */
+    public function getIsolation()
+    {
+        return $this->conn->fetchOne('SELECT @@tx_isolation');
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Oracle.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,106 @@
+<?php
+/*
+ *  $Id: Oracle.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @package     Doctrine
+ * @subpackage  Transaction
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Transaction_Oracle extends Doctrine_Transaction
+{
+    /**
+     * createSavepoint
+     * creates a new savepoint
+     *
+     * @param string $savepoint     name of a savepoint to set
+     * @return void
+     */
+    protected function createSavePoint($savepoint)
+    {
+        $query = 'SAVEPOINT ' . $savepoint;
+
+        return $this->conn->execute($query);
+    }
+
+    /**
+     * releaseSavePoint
+     * releases given savepoint
+     *
+     * @param string $savepoint     name of a savepoint to release
+     * @return void
+     */
+    protected function releaseSavePoint($savepoint)
+    {
+        // oracle doesn't support manual releasing of savepoints
+        return true;
+    }
+
+    /**
+     * rollbackSavePoint
+     * releases given savepoint
+     *
+     * @param string $savepoint     name of a savepoint to rollback to
+     * @return void
+     */
+    protected function rollbackSavePoint($savepoint)
+    {
+        $query = 'ROLLBACK TO SAVEPOINT ' . $savepoint;
+
+        return $this->conn->execute($query);
+    }
+
+    /**
+     * Set the transacton isolation level.
+     *
+     * @param   string  standard isolation level
+     *                  READ UNCOMMITTED (allows dirty reads)
+     *                  READ COMMITTED (prevents dirty reads)
+     *                  REPEATABLE READ (prevents nonrepeatable reads)
+     *                  SERIALIZABLE (prevents phantom reads)
+     * @throws PDOException                         if something fails at the PDO level
+     * @throws Doctrine_Transaction_Exception       if using unknown isolation level
+     * @return void
+     */
+    public function setIsolation($isolation)
+    {
+        switch ($isolation) {
+            case 'READ UNCOMMITTED':
+                $isolation = 'READ COMMITTED';
+                break;
+            case 'READ COMMITTED':
+            case 'REPEATABLE READ':
+            case 'SERIALIZABLE':
+                $isolation = 'SERIALIZABLE';
+                break;
+            default:
+                throw new Doctrine_Transaction_Exception('Isolation level ' . $isolation . ' is not supported.');
+        }
+
+        $query = 'ALTER SESSION SET ISOLATION_LEVEL = ' . $isolation;
+        return $this->conn->execute($query);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Pgsql.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,105 @@
+<?php
+/*
+ *  $Id: Pgsql.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Paul Cooper <pgc@ucecom.com> (PEAR MDB2 Pgsql driver)
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @package     Doctrine
+ * @subpackage  Transaction
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Transaction_Pgsql extends Doctrine_Transaction
+{
+    /**
+     * createSavepoint
+     * creates a new savepoint
+     *
+     * @param string $savepoint     name of a savepoint to set
+     * @return void
+     */
+    protected function createSavePoint($savepoint)
+    {
+        $query = 'SAVEPOINT ' . $savepoint;
+
+        return $this->conn->execute($query);
+    }
+
+    /**
+     * releaseSavePoint
+     * releases given savepoint
+     *
+     * @param string $savepoint     name of a savepoint to release
+     * @return void
+     */
+    protected function releaseSavePoint($savepoint)
+    {
+        $query = 'RELEASE SAVEPOINT ' . $savepoint;
+
+        return $this->conn->execute($query);
+    }
+
+    /**
+     * rollbackSavePoint
+     * releases given savepoint
+     *
+     * @param string $savepoint     name of a savepoint to rollback to
+     * @return void
+     */
+    protected function rollbackSavePoint($savepoint)
+    {
+        $query = 'ROLLBACK TO SAVEPOINT ' . $savepoint;
+
+        return $this->conn->execute($query);
+    }
+
+    /**
+     * Set the transacton isolation level.
+     *
+     * @param   string  standard isolation level
+     *                  READ UNCOMMITTED (allows dirty reads)
+     *                  READ COMMITTED (prevents dirty reads)
+     *                  REPEATABLE READ (prevents nonrepeatable reads)
+     *                  SERIALIZABLE (prevents phantom reads)
+     * @throws PDOException                         if something fails at the PDO level
+     * @throws Doctrine_Transaction_Exception       if using unknown isolation level or unknown wait option
+     * @return void
+     */
+    public function setIsolation($isolation)
+    {
+        switch ($isolation) {
+            case 'READ UNCOMMITTED':
+            case 'READ COMMITTED':
+            case 'REPEATABLE READ':
+            case 'SERIALIZABLE':
+                break;
+            default:
+                throw new Doctrine_Transaction_Exception('Isolation level '.$isolation.' is not supported.');
+        }
+
+        $query = 'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL ' . $isolation;
+        return $this->conn->execute($query);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Transaction/Sqlite.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,66 @@
+<?php
+/*
+ *  $Id: Sqlite.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @package     Doctrine
+ * @subpackage  Transaction
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Transaction_Sqlite extends Doctrine_Transaction
+{
+    /**
+     * Set the transacton isolation level.
+     *
+     * @param   string  standard isolation level
+     *                  READ UNCOMMITTED (allows dirty reads)
+     *                  READ COMMITTED (prevents dirty reads)
+     *                  REPEATABLE READ (prevents nonrepeatable reads)
+     *                  SERIALIZABLE (prevents phantom reads)
+     * @throws PDOException                         if something fails at the PDO level
+     * @throws Doctrine_Transaction_Exception       if using unknown isolation level
+     * @return void
+     */
+    public function setIsolation($isolation)
+    {
+        switch ($isolation) {
+            case 'READ UNCOMMITTED':
+                $isolation = 0;
+                break;
+            case 'READ COMMITTED':
+            case 'REPEATABLE READ':
+            case 'SERIALIZABLE':
+                $isolation = 1;
+                break;
+            default:
+                throw new Doctrine_Transaction_Exception('Isolation level ' . $isolation . 'is not supported.');
+        }
+
+        $query = 'PRAGMA read_uncommitted = ' . $isolation;
+
+        return $this->conn->execute($query);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Tree.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,131 @@
+<?php
+/*
+ *  $Id: Tree.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+                 
+/**
+ * Doctrine_Tree
+ *
+ * @package     Doctrine
+ * @subpackage  Tree
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Tree
+{
+    /**
+     * @param object $table   reference to associated Doctrine_Table instance
+     */
+    protected $table;
+
+    /**
+     * @param array $options
+     */
+    protected $options = array();
+    
+    protected $_baseComponent;
+
+    /**
+     * constructor, creates tree with reference to table and any options
+     *
+     * @param object $table                     instance of Doctrine_Table
+     * @param array $options                    options
+     */
+    public function __construct(Doctrine_Table $table, $options)
+    {
+        $this->table = $table;
+        $this->options = $options;
+        $this->_baseComponent = $table->getComponentName();
+        $class = $this->_baseComponent;
+        if ($table->getOption('inheritanceMap')) {
+            $subclasses = $table->getOption('subclasses');
+            while (in_array($class, $subclasses)) {
+                $class = get_parent_class($class);
+            }
+            $this->_baseComponent = $class;
+        }
+        //echo $this->_baseComponent;
+    }
+
+    /**
+     * Used to define table attributes required for the given implementation
+     *
+     * @throws Doctrine_Tree_Exception          if table attributes have not been defined
+     */
+    public function setTableDefinition()
+    {
+        throw new Doctrine_Tree_Exception('Table attributes have not been defined for this Tree implementation.');
+    }
+
+    /**
+     * this method is used for setting up relations and attributes and should be used by specific implementations
+     *
+     */
+    public function setUp()
+    {
+    }
+
+    /**
+     * factory method to return tree instance based upon chosen implementation
+     *
+     * @param object $table                     instance of Doctrine_Table
+     * @param string $impName                   implementation (NestedSet, AdjacencyList, MaterializedPath)
+     * @param array $options                    options
+     * @return object $options                  instance of Doctrine_Node
+     * @throws Doctrine_Exception               if class does not extend Doctrine_Tree
+     */
+    public static function factory(Doctrine_Table $table, $implName, $options = array())
+    {
+        $class = 'Doctrine_Tree_' . $implName;
+        if ( ! class_exists($class)) {
+            throw new Doctrine_Exception('The chosen class must extend Doctrine_Tree');
+        }
+        return new $class($table, $options);
+    }
+
+    /**
+     * gets tree attribute value
+     *        
+     */     
+    public function getAttribute($name)
+    {
+      return isset($this->options[$name]) ? $this->options[$name] : null;
+    }
+
+    /**
+     * sets tree attribute value
+     *
+     * @param mixed            
+     */
+    public function setAttribute($name, $value)
+    {
+      $this->options[$name] = $value;
+    }
+
+    /**
+     * Returns the base tree component.
+     */
+    public function getBaseComponent()
+    {
+        return $this->_baseComponent;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Tree/AdjacencyList.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: AdjacencyList.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Tree_AdjacencyList
+ *
+ * @package     Doctrine
+ * @subpackage  Tree
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Tree_AdjacencyList extends Doctrine_Tree implements Doctrine_Tree_Interface
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Tree/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Tree_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Tree
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Tree_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Tree/Interface.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,67 @@
+<?php
+/*
+ *  $Id: Interface.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Tree_Interface
+ *
+ * @package     Doctrine
+ * @subpackage  Tree
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+interface Doctrine_Tree_Interface {
+
+    /**
+     * creates root node from given record or from a new record
+     *
+     * @param object $record                    instance of Doctrine_Record
+     */
+    public function createRoot(Doctrine_Record $record = null);
+
+    /**
+     * returns root node
+     *
+     * @return object $record                   instance of Doctrine_Record
+     */
+    public function findRoot($root_id = 1);
+
+    /**
+     * optimised method to returns iterator for traversal of the entire tree from root
+     *
+     * @param array $options                    options
+     * @param integer $fetchmode  One of the Doctrine::HYDRATE_* constants.
+     * @return object $iterator                 instance of Doctrine_Node_<Implementation>_PreOrderIterator
+     */
+    public function fetchTree($options = array(), $hydrationMode = null);
+
+    /**
+     * optimised method that returns iterator for traversal of the tree from the given record primary key
+     *
+     * @param mixed $pk                         primary key as used by table::find() to locate node to traverse tree from
+     * @param array $options                    options
+     * @param integer $fetchmode                One of the Doctrine::HYDRATE_* constants.
+     * @return iterator                         instance of Doctrine_Node_<Implementation>_PreOrderIterator
+     */
+    public function fetchBranch($pk, $options = array(), $hydrationMode = null);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Tree/MaterializedPath.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: MaterializedPath.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Tree_MaterializedPath
+ *
+ * @package     Doctrine
+ * @subpackage  Tree
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Tree_MaterializedPath extends Doctrine_Tree implements Doctrine_Tree_Interface
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Tree/NestedSet.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,366 @@
+<?php
+/*
+ *  $Id: NestedSet.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Tree_NestedSet
+ *
+ * @package     Doctrine
+ * @subpackage  Tree
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ * @author      Roman Borschel <roman@code-factory.org>
+ */
+class Doctrine_Tree_NestedSet extends Doctrine_Tree implements Doctrine_Tree_Interface
+{
+    private $_baseQuery;
+    private $_baseAlias = "base";
+
+    /**
+     * constructor, creates tree with reference to table and sets default root options
+     *
+     * @param object $table                     instance of Doctrine_Table
+     * @param array $options                    options
+     */
+    public function __construct(Doctrine_Table $table, $options)
+    {
+        // set default many root attributes
+        $options['hasManyRoots'] = isset($options['hasManyRoots']) ? $options['hasManyRoots'] : false;
+        if ($options['hasManyRoots']) {
+            $options['rootColumnName'] = isset($options['rootColumnName']) ? $options['rootColumnName'] : 'root_id';
+        }
+
+        parent::__construct($table, $options);
+    }
+
+    /**
+     * used to define table attributes required for the NestetSet implementation
+     * adds lft and rgt columns for corresponding left and right values
+     *
+     */
+    public function setTableDefinition()
+    {
+        if (($root = $this->getAttribute('rootColumnName')) && (!$this->table->hasColumn($root))) {
+            $this->table->setColumn($root, 'integer', 4);
+        }
+
+        $this->table->setColumn('lft', 'integer', 4);
+        $this->table->setColumn('rgt', 'integer', 4);
+        $this->table->setColumn('level', 'integer', 2);
+    }
+
+    /**
+     * Creates root node from given record or from a new record.
+     *
+     * Note: When using a tree with multiple root nodes (hasManyRoots), you MUST pass in a
+     * record to use as the root. This can either be a new/transient record that already has
+     * the root id column set to some numeric value OR a persistent record. In the latter case
+     * the records id will be assigned to the root id. You must use numeric columns for the id
+     * and root id columns.
+     *
+     * @param object $record        instance of Doctrine_Record
+     */
+    public function createRoot(Doctrine_Record $record = null)
+    {
+        if ($this->getAttribute('hasManyRoots')) {
+            if ( ! $record || ( ! $record->exists() && $record->getNode()->getRootValue() <= 0)
+                    || $record->getTable()->isIdentifierComposite()) {
+                throw new Doctrine_Tree_Exception("Node must have a root id set or must "
+                        . " be persistent and have a single-valued numeric primary key in order to"
+                        . " be created as a root node. Automatic assignment of a root id on"
+                        . " transient/new records is no longer supported.");
+            }
+            
+            if ($record->exists() && $record->getNode()->getRootValue() <= 0) {
+                // Default: root_id = id
+                $identifier = $record->getTable()->getIdentifier();
+                $record->getNode()->setRootValue($record->get($identifier));
+            }
+        }
+        
+        if ( ! $record) {
+            $record = $this->table->create();
+        }
+
+        $record->set('lft', '1');
+        $record->set('rgt', '2');
+        $record->set('level', 0);
+
+        $record->save();
+
+        return $record;
+    }
+
+    /**
+     * returns root node
+     *
+     * @return object $record        instance of Doctrine_Record
+     * @deprecated Use fetchRoot()
+     */
+    public function findRoot($rootId = 1)
+    {
+        return $this->fetchRoot($rootId);
+    }
+
+    /**
+     * Fetches a/the root node.
+     *
+     * @param integer $rootId
+     * @todo Better $rootid = null and exception if $rootId == null && hasManyRoots?
+     *       Fetching with id = 1 is too magical and cant work reliably anyway.
+     */
+    public function fetchRoot($rootId = 1)
+    {
+        $q = $this->getBaseQuery();
+        $q = $q->addWhere($this->_baseAlias . '.lft = ?', 1);
+
+        // if tree has many roots, then specify root id
+        $q = $this->returnQueryWithRootId($q, $rootId);
+        $data = $q->execute();
+
+        if (count($data) <= 0) {
+            return false;
+        }
+
+        if ($data instanceof Doctrine_Collection) {
+            $root = $data->getFirst();
+            $root['level'] = 0;
+        } else if (is_array($data)) {
+            $root = array_shift($data);
+            $root['level'] = 0;
+        } else {
+            throw new Doctrine_Tree_Exception("Unexpected data structure returned.");
+        }
+
+        return $root;
+    }
+
+    /**
+     * Fetches a tree.
+     *
+     * @param array $options  Options
+     * @param integer $fetchmode  One of the Doctrine::HYDRATE_* constants.
+     * @return mixed          The tree or FALSE if the tree could not be found.
+     */
+    public function fetchTree($options = array(), $hydrationMode = null)
+    {
+        // fetch tree
+        $q = $this->getBaseQuery();
+
+        $depth = isset($options['depth']) ? $options['depth'] : null;
+
+        $q->addWhere($this->_baseAlias . ".lft >= ?", 1);
+
+        // if tree has many roots, then specify root id
+        $rootId = isset($options['root_id']) ? $options['root_id'] : '1';
+        if (is_array($rootId)) {
+            $q->addOrderBy($this->_baseAlias . "." . $this->getAttribute('rootColumnName') .
+                    ", " . $this->_baseAlias . ".lft ASC");
+        } else {
+            $q->addOrderBy($this->_baseAlias . ".lft ASC");
+        }
+
+        if ( ! is_null($depth)) { 
+            $q->addWhere($this->_baseAlias . ".level BETWEEN ? AND ?", array(0, $depth)); 
+        }
+
+        $q = $this->returnQueryWithRootId($q, $rootId);
+
+        $tree = $q->execute(array(), $hydrationMode);
+
+        if (count($tree) <= 0) {
+            return false;
+        }
+
+        return $tree;
+    }
+
+    /**
+     * Fetches a branch of a tree.
+     *
+     * @param mixed $pk              primary key as used by table::find() to locate node to traverse tree from
+     * @param array $options         Options.
+     * @param integer $fetchmode  One of the Doctrine::HYDRATE_* constants.
+     * @return mixed                 The branch or FALSE if the branch could not be found.
+     * @todo Only fetch the lft and rgt values of the initial record. more is not needed.
+     */
+    public function fetchBranch($pk, $options = array(), $hydrationMode = null)
+    {
+        $record = $this->table->find($pk);
+        if ( ! ($record instanceof Doctrine_Record) || !$record->exists()) {
+            // TODO: if record doesn't exist, throw exception or similar?
+            return false;
+        }
+
+        $depth = isset($options['depth']) ? $options['depth'] : null;
+
+        $q = $this->getBaseQuery();
+        $params = array($record->get('lft'), $record->get('rgt'));
+        $q->addWhere($this->_baseAlias . ".lft >= ? AND " . $this->_baseAlias . ".rgt <= ?", $params)
+                ->addOrderBy($this->_baseAlias . ".lft asc");
+
+        if ( ! is_null($depth)) { 
+            $q->addWhere($this->_baseAlias . ".level BETWEEN ? AND ?", array($record->get('level'), $record->get('level')+$depth)); 
+        }        
+
+        $q = $this->returnQueryWithRootId($q, $record->getNode()->getRootValue());
+
+        return $q->execute(array(), $hydrationMode);
+    }
+
+    /**
+     * Fetches all root nodes. If the tree has only one root this is the same as
+     * fetchRoot().
+     *
+     * @return mixed  The root nodes.
+     */
+    public function fetchRoots()
+    {
+        $q = $this->getBaseQuery();
+        $q = $q->addWhere($this->_baseAlias . '.lft = ?', 1);
+        return $q->execute();
+    }
+
+    /**
+     * calculates the next available root id
+     *
+     * @return integer
+     * @deprecated THIS METHOD IS DEPRECATED. ROOT IDS ARE NO LONGER AUTOMATICALLY GENERATED.
+     *             ROOT ID MUST BE ASSIGNED MANUALLY OR USING THE DEFAULT BEHAVIOR WHERE
+     *             ROOT_ID = ID. SEE createRoot() FOR DETAILS.
+     */
+    public function getNextRootId()
+    {
+        return $this->getMaxRootId() + 1;
+    }
+
+    /**
+     * calculates the current max root id
+     *
+     * @return integer
+     * @deprecated THIS METHOD IS DEPRECATED. ROOT IDS ARE NO LONGER AUTOMATICALLY GENERATED.
+     *             ROOT ID MUST BE ASSIGNED MANUALLY OR USING THE DEFAULT BEHAVIOR WHERE
+     *             ROOT_ID = ID. SEE createRoot() FOR DETAILS.
+     */
+    public function getMaxRootId()
+    {
+        $component = $this->table->getComponentName();
+        $column = $this->getAttribute('rootColumnName');
+
+        // cannot get this dql to work, cannot retrieve result using $coll[0]->max
+        //$dql = "SELECT MAX(c.$column) FROM $component c";
+
+        $dql = 'SELECT c.' . $column . ' FROM ' . $component . ' c ORDER BY c.' . $column . ' DESC LIMIT 1';
+
+        $coll = $this->table->getConnection()->query($dql);
+
+        if ($coll->count() > 0) {
+            $max = $coll->getFirst()->get($column);
+            $max = ! is_null($max) ? $max : 0;
+        } else {
+            $max = 0;
+        }
+
+        return $max;
+    }
+
+    /**
+     * returns parsed query with root id where clause added if applicable
+     *
+     * @param object    $query    Doctrine_Query
+     * @param integer   $root_id  id of destination root
+     * @return object   Doctrine_Query
+     */
+    public function returnQueryWithRootId($query, $rootId = 1)
+    {
+        if ($root = $this->getAttribute('rootColumnName')) {
+            if (is_array($rootId)) {
+               $query->addWhere($root . ' IN (' . implode(',', array_fill(0, count($rootId), '?')) . ')',
+                       $rootId);
+            } else {
+               $query->addWhere($root . ' = ?', $rootId);
+            }
+        }
+
+        return $query;
+    }
+
+    /**
+     * Enter description here...
+     *
+     * @param array $options
+     * @return unknown
+     */
+    public function getBaseQuery()
+    {
+        if ( ! isset($this->_baseQuery)) {
+            $this->_baseQuery = $this->_createBaseQuery();
+        }
+        return $this->_baseQuery->copy();
+    }
+
+    /**
+     * Enter description here...
+     *
+     */
+    public function getBaseAlias()
+    {
+        return $this->_baseAlias;
+    }
+
+    /**
+     * Enter description here...
+     *
+     */
+    private function _createBaseQuery()
+    {
+        $this->_baseAlias = "base";
+        $q = new Doctrine_Query();
+        $q->select($this->_baseAlias . ".*")->from($this->getBaseComponent() . " " . $this->_baseAlias);
+        return $q;
+    }
+
+    /**
+     * Enter description here...
+     *
+     * @param Doctrine_Query $query
+     */
+    public function setBaseQuery(Doctrine_Query $query)
+    {
+        $this->_baseAlias = $query->getRootAlias();
+        $query->addSelect($this->_baseAlias . ".lft, " . $this->_baseAlias . ".rgt, ". $this->_baseAlias . ".level");
+        if ($this->getAttribute('rootColumnName')) {
+            $query->addSelect($this->_baseAlias . "." . $this->getAttribute('rootColumnName'));
+        }
+        $this->_baseQuery = $query;
+    }
+
+    /**
+     * Enter description here...
+     *
+     */
+    public function resetBaseQuery()
+    {
+        $this->_baseQuery = $this->_createBaseQuery();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Util.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Util
+ *
+ * @package     Doctrine
+ * @subpackage  Util
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Util extends Doctrine_Connection_Module
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,189 @@
+<?php
+/*
+ *  $Id: Validator.php 5814 2009-06-03 16:26:59Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * This class is responsible for performing all validations on record properties
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5814 $
+ * @author      Roman Borschel <roman@code-factory.org>
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator extends Doctrine_Locator_Injectable
+{
+    /**
+     * @var array $validators           an array of validator objects
+     */
+    private static $validators = array();
+
+    /**
+     * Get a validator instance for the passed $name
+     *
+     * @param  string   $name  Name of the validator or the validator class name
+     * @return Doctrine_Validator_Interface $validator
+     */
+    public static function getValidator($name)
+    {
+        if ( ! isset(self::$validators[$name])) {
+            $class = 'Doctrine_Validator_' . ucwords(strtolower($name));
+            if (class_exists($class)) {
+                self::$validators[$name] = new $class;
+            } else if (class_exists($name)) {
+                self::$validators[$name] = new $name;
+            } else {
+                throw new Doctrine_Exception("Validator named '$name' not available.");
+            }
+
+        }
+        return self::$validators[$name];
+    }
+
+    /**
+     * Validates a given record and saves possible errors in Doctrine_Validator::$stack
+     *
+     * @param  Doctrine_Record $record
+     * @return void
+     */
+    public function validateRecord(Doctrine_Record $record)
+    {
+        $table = $record->getTable();
+
+        // if record is transient all fields will be validated
+        // if record is persistent only the modified fields will be validated
+        $fields = $record->exists() ? $record->getModified():$record->getData();
+        foreach ($fields as $fieldName => $value) {
+            $table->validateField($fieldName, $value, $record);
+        }
+    }
+
+    /**
+     * Validates the length of a field.
+     *
+     * @param  string  $value         Value to validate
+     * @param  string  $type          Type of field being validated
+     * @param  string  $maximumLength Maximum length allowed for the column
+     * @return boolean $success       True/false for whether the value passed validation
+     */
+    public static function validateLength($value, $type, $maximumLength)
+    {
+        if ($type == 'timestamp' || $type == 'integer' || $type == 'enum') {
+            return true;
+        } else if ($type == 'array' || $type == 'object') {
+            $length = strlen(serialize($value));
+        } else if ($type == 'decimal' || $type == 'float') {
+            $value = abs($value);
+            $e = explode('.', $value);
+            $length = strlen($e[0]);
+            if (isset($e[1])) {
+                $length = $length + strlen($e[1]);
+            }
+        } else {
+            $length = self::getStringLength($value);
+        }
+        if ($length > $maximumLength) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Get length of passed string. Will use multibyte character functions if they exist
+     *
+     * @param string $string 
+     * @return integer $length
+     */
+    public static function getStringLength($string)
+    {
+        if (function_exists('iconv_strlen')) {
+            return iconv_strlen($string, 'UTF-8');
+        } else if (function_exists('mb_strlen')) {
+            return mb_strlen($string, 'utf8');
+        } else {
+            return strlen(utf8_decode($string));
+        }
+    }
+
+    /**
+     * Whether or not errors exist on this validator
+     *
+     * @return boolean True/false for whether or not this validate instance has error
+     */
+    public function hasErrors()
+    {
+        return (count($this->stack) > 0);
+    }
+
+    /**
+     * Validate the type of the passed variable
+     *
+     * @param  mixed  $var   Variable to validate
+     * @param  string $type  Type of the variable expected
+     * @return boolean
+     */
+     public static function isValidType($var, $type)
+     {
+         if ($var instanceof Doctrine_Expression) {
+             return true;
+         } else if ($var === null) {
+             return true;
+         } else if (is_object($var)) {
+             return $type == 'object';
+         }
+
+         switch ($type) {
+             case 'float':
+             case 'double':
+             case 'decimal':
+                 return (string)$var == strval(floatval($var));
+             case 'integer':
+                 return (string)$var == strval(round(floatval($var)));
+             case 'string':
+                 return is_string($var) || is_numeric($var);
+             case 'blob':
+             case 'clob':
+             case 'gzip':
+                 return is_string($var);
+             case 'array':
+                 return is_array($var);
+             case 'object':
+                 return is_object($var);
+             case 'boolean':
+                 return is_bool($var) || (is_numeric($var) && ($var == 0 || $var == 1));
+             case 'timestamp':
+                 $validator = self::getValidator('timestamp');
+                 return $validator->validate($var);
+             case 'time':
+                 $validator = self::getValidator('time');
+                 return $validator->validate($var);
+             case 'date':
+                 $validator = self::getValidator('date');
+                 return $validator->validate($var);
+             case 'enum':
+                 return is_string($var) || is_int($var);
+             default:
+                 return false;
+         }
+     }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Country.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,305 @@
+<?php
+/*
+ *  $Id: Country.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Country
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Country
+{
+    private static $countries = array(
+        'ad' =>    'Andorra',
+        'ae' =>    'United Arab Emirates',
+        'af' =>    'Afghanistan',
+        'ag' =>    'Antigua and Barbuda',
+        'ai' =>    'Anguilla',
+        'al' =>    'Albania',
+        'am' =>    'Armenia',
+        'an' =>    'Netherlands Antilles',
+        'ao' =>    'Angola',
+        'aq' =>    'Antarctica',
+        'ar' =>    'Argentina',
+        'as' =>    'American Samoa',
+        'at' =>    'Austria',
+        'au' =>    'Australia',
+        'aw' =>    'Aruba',
+        'az' =>    'Azerbaijan',
+        'ba' =>    'Bosnia Hercegovina',
+        'bb' =>    'Barbados',
+        'bd' =>    'Bangladesh',
+        'be' =>    'Belgium',
+        'bf' =>    'Burkina Faso',
+        'bg' =>    'Bulgaria',
+        'bh' =>    'Bahrain',
+        'bi' =>    'Burundi',
+        'bj' =>    'Benin',
+        'bm' =>    'Bermuda',
+        'bn' =>    'Brunei Darussalam',
+        'bo' =>    'Bolivia',
+        'br' =>    'Brazil',
+        'bs' =>    'Bahamas',
+        'bt' =>    'Bhutan',
+        'bv' =>    'Bouvet Island',
+        'bw' =>    'Botswana',
+        'by' =>    'Belarus (Byelorussia)',
+        'bz' =>    'Belize',
+        'ca' =>    'Canada',
+        'cc' =>    'Cocos Islands',
+        'cd' =>    'Congo, The Democratic Republic of the',
+        'cf' =>    'Central African Republic',
+        'cg' =>    'Congo',
+        'ch' =>    'Switzerland',
+        'ci' =>    'Ivory Coast',
+        'ck' =>    'Cook Islands',
+        'cl' =>    'Chile',
+        'cm' =>    'Cameroon',
+        'cn' =>    'China',
+        'co' =>    'Colombia',
+        'cr' =>    'Costa Rica',
+        'cs' =>    'Czechoslovakia',
+        'cu' =>    'Cuba',
+        'cv' =>    'Cape Verde',
+        'cx' =>    'Christmas Island',
+        'cy' =>    'Cyprus',
+        'cz' =>    'Czech Republic',
+        'de' =>    'Germany',
+        'dj' =>    'Djibouti',
+        'dk' =>    'Denmark',
+        'dm' =>    'Dominica',
+        'do' =>    'Dominican Republic',
+        'dz' =>    'Algeria',
+        'ec' =>    'Ecuador',
+        'ee' =>    'Estonia',
+        'eg' =>    'Egypt',
+        'eh' =>    'Western Sahara',
+        'er' =>    'Eritrea',
+        'es' =>    'Spain',
+        'et' =>    'Ethiopia',
+        'fi' =>    'Finland',
+        'fj' =>    'Fiji',
+        'fk' =>    'Falkland Islands',
+        'fm' =>    'Micronesia',
+        'fo' =>    'Faroe Islands',
+        'fr' =>    'France',
+        'fx' =>    'France, Metropolitan FX',
+        'ga' =>    'Gabon',
+        'gb' =>    'United Kingdom (Great Britain)',
+        'gd' =>    'Grenada',
+        'ge' =>    'Georgia',
+        'gf' =>    'French Guiana',
+        'gh' =>    'Ghana',
+        'gi' =>    'Gibraltar',
+        'gl' =>    'Greenland',
+        'gm' =>    'Gambia',
+        'gn' =>    'Guinea',
+        'gp' =>    'Guadeloupe',
+        'gq' =>    'Equatorial Guinea',
+        'gr' =>    'Greece',
+        'gs' =>    'South Georgia and the South Sandwich Islands',
+        'gt' =>    'Guatemala',
+        'gu' =>    'Guam',
+        'gw' =>    'Guinea-bissau',
+        'gy' =>    'Guyana',
+        'hk' =>    'Hong Kong',
+        'hm' =>    'Heard and McDonald Islands',
+        'hn' =>    'Honduras',
+        'hr' =>    'Croatia',
+        'ht' =>    'Haiti',
+        'hu' =>    'Hungary',
+        'id' =>    'Indonesia',
+        'ie' =>    'Ireland',
+        'il' =>    'Israel',
+        'in' =>    'India',
+        'io' =>    'British Indian Ocean Territory',
+        'iq' =>    'Iraq',
+        'ir' =>    'Iran',
+        'is' =>    'Iceland',
+        'it' =>    'Italy',
+        'jm' =>    'Jamaica',
+        'jo' =>    'Jordan',
+        'jp' =>    'Japan',
+        'ke' =>    'Kenya',
+        'kg' =>    'Kyrgyzstan',
+        'kh' =>    'Cambodia',
+        'ki' =>    'Kiribati',
+        'km' =>    'Comoros',
+        'kn' =>    'Saint Kitts and Nevis',
+        'kp' =>    'North Korea',
+        'kr' =>    'South Korea',
+        'kw' =>    'Kuwait',
+        'ky' =>    'Cayman Islands',
+        'kz' =>    'Kazakhstan',
+        'la' =>    'Laos',
+        'lb' =>    'Lebanon',
+        'lc' =>    'Saint Lucia',
+        'li' =>    'Lichtenstein',
+        'lk' =>    'Sri Lanka',
+        'lr' =>    'Liberia',
+        'ls' =>    'Lesotho',
+        'lt' =>    'Lithuania',
+        'lu' =>    'Luxembourg',
+        'lv' =>    'Latvia',
+        'ly' =>    'Libya',
+        'ma' =>    'Morocco',
+        'mc' =>    'Monaco',
+        'md' =>    'Moldova Republic',
+        'mg' =>    'Madagascar',
+        'mh' =>    'Marshall Islands',
+        'mk' =>    'Macedonia, The Former Yugoslav Republic of',
+        'ml' =>    'Mali',
+        'mm' =>    'Myanmar',
+        'mn' =>    'Mongolia',
+        'mo' =>    'Macau',
+        'mp' =>    'Northern Mariana Islands',
+        'mq' =>    'Martinique',
+        'mr' =>    'Mauritania',
+        'ms' =>    'Montserrat',
+        'mt' =>    'Malta',
+        'mu' =>    'Mauritius',
+        'mv' =>    'Maldives',
+        'mw' =>    'Malawi',
+        'mx' =>    'Mexico',
+        'my' =>    'Malaysia',
+        'mz' =>    'Mozambique',
+        'na' =>    'Namibia',
+        'nc' =>    'New Caledonia',
+        'ne' =>    'Niger',
+        'nf' =>    'Norfolk Island',
+        'ng' =>    'Nigeria',
+        'ni' =>    'Nicaragua',
+        'nl' =>    'Netherlands',
+        'no' =>    'Norway',
+        'np' =>    'Nepal',
+        'nr' =>    'Nauru',
+        'nt' =>    'Neutral Zone',
+        'nu' =>    'Niue',
+        'nz' =>    'New Zealand',
+        'om' =>    'Oman',
+        'pa' =>    'Panama',
+        'pe' =>    'Peru',
+        'pf' =>    'French Polynesia',
+        'pg' =>    'Papua New Guinea',
+        'ph' =>    'Philippines',
+        'pk' =>    'Pakistan',
+        'pl' =>    'Poland',
+        'pm' =>    'St. Pierre and Miquelon',
+        'pn' =>    'Pitcairn',
+        'pr' =>    'Puerto Rico',
+        'pt' =>    'Portugal',
+        'pw' =>    'Palau',
+        'py' =>    'Paraguay',
+        'qa' =>    'Qatar',
+        're' =>    'Reunion',
+        'ro' =>    'Romania',
+        'ru' =>    'Russia',
+        'rw' =>    'Rwanda',
+        'sa' =>    'Saudi Arabia',
+        'sb' =>    'Solomon Islands',
+        'sc' =>    'Seychelles',
+        'sd' =>    'Sudan',
+        'se' =>    'Sweden',
+        'sg' =>    'Singapore',
+        'sh' =>    'St. Helena',
+        'si' =>    'Slovenia',
+        'sj' =>    'Svalbard and Jan Mayen Islands',
+        'sk' =>    'Slovakia (Slovak Republic)',
+        'sl' =>    'Sierra Leone',
+        'sm' =>    'San Marino',
+        'sn' =>    'Senegal',
+        'so' =>    'Somalia',
+        'sr' =>    'Suriname',
+        'st' =>    'Sao Tome and Principe',
+        'sv' =>    'El Salvador',
+        'sy' =>    'Syria',
+        'sz' =>    'Swaziland',
+        'tc' =>    'Turks and Caicos Islands',
+        'td' =>    'Chad',
+        'tf' =>    'French Southern Territories',
+        'tg' =>    'Togo',
+        'th' =>    'Thailand',
+        'tj' =>    'Tajikistan',
+        'tk' =>    'Tokelau',
+        'tm' =>    'Turkmenistan',
+        'tn' =>    'Tunisia',
+        'to' =>    'Tonga',
+        'tp' =>    'East Timor',
+        'tr' =>    'Turkey',
+        'tt' =>    'Trinidad, Tobago',
+        'tv' =>    'Tuvalu',
+        'tw' =>    'Taiwan',
+        'tz' =>    'Tanzania',
+        'ua' =>    'Ukraine',
+        'ug' =>    'Uganda',
+        'uk' =>    'United Kingdom',
+        'um' =>    'United States Minor Islands',
+        'us' =>    'United States of America',
+        'uy' =>    'Uruguay',
+        'uz' =>    'Uzbekistan',
+        'va' =>    'Vatican City',
+        'vc' =>    'Saint Vincent, Grenadines',
+        've' =>    'Venezuela',
+        'vg' =>    'Virgin Islands (British)',
+        'vi' =>    'Virgin Islands (USA)',
+        'vn' =>    'Viet Nam',
+        'vu' =>    'Vanuatu',
+        'wf' =>    'Wallis and Futuna Islands',
+        'ws' =>    'Samoa',
+        'ye' =>    'Yemen',
+        'yt' =>    'Mayotte',
+        'yu' =>    'Yugoslavia',
+        'za' =>    'South Africa',
+        'zm' =>    'Zambia',
+        'zr' =>    'Zaire',
+        'zw' =>    'Zimbabwe');
+
+    /**
+     * returns all available country codes
+     *
+     * @return array
+     */
+    public static function getCountries()
+    {
+        return self::$countries;
+    }
+
+    /**
+     * checks if given value is a valid country code
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+        $value = strtolower($value);
+
+        return isset(self::$countries[$value]);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Creditcard.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,85 @@
+<?php
+/*
+ *  $Id: Creditcard.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Creditcard
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Creditcard
+{                                                         
+    /**
+     * checks if given value is a valid credit card number
+     *
+     * @link http://www.owasp.org/index.php/OWASP_Validation_Regex_Repository
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+        $cardType = "";
+        $card_regexes = array(
+            "/^4\d{12}(\d\d\d){0,1}$/"      => 'visa',
+            "/^5[12345]\d{14}$/"            => 'mastercard',
+            "/^3[47]\d{13}$/"               => 'amex',
+            "/^6011\d{12}$/"                => 'discover',
+            "/^30[012345]\d{11}$/"          => 'diners',
+            "/^3[68]\d{12}$/"               => 'diners',
+        );
+        foreach ($card_regexes as $regex => $type) {
+            if (preg_match($regex, $value)) {
+                 $cardType = $type;
+                 break;
+            }
+        }
+        if ( ! $cardType) {
+            return false;
+        }
+        /* mod 10 checksum algorithm */
+        $revcode = strrev($value);
+        $checksum = 0;
+        for ($i = 0; $i < strlen($revcode); $i++) {
+            $currentNum = intval($revcode[$i]);
+            if ($i & 1) {               /* Odd position */
+                 $currentNum *= 2;
+            }
+            /* Split digits and add. */
+            $checksum += $currentNum % 10;
+            if ($currentNum > 9) {
+                 $checksum += 1;
+            }
+        }
+        if ($checksum % 10 == 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Date.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,55 @@
+<?php
+/*
+ *  $Id: Date.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Date
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Date
+{
+    /**
+     * checks if given value is a valid date
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+        $e = explode('-', $value);
+
+        if (count($e) !== 3) {
+            return false;
+        }
+        $e2 = explode(' ', $e[2]);
+        $e[2] = $e2[0];
+        return checkdate($e[1], $e[2], $e[0]);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Driver.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,116 @@
+<?php
+/*
+ *  $Id: Notnull.php 1080 2007-02-10 18:17:08Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Driver
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Driver
+{
+    /**
+     * @var array $_args     an array of plugin specific args
+     */
+    protected $_args = array();
+
+    /**
+     * __get
+     * an alias for getOption
+     *
+     * @param string $arg
+     */
+    public function __get($arg)
+    {
+        if (isset($this->_args[$arg])) {
+            return $this->_args[$arg];
+        }
+        return null;
+    }
+
+    /**
+     * __isset
+     *
+     * @param string $arg
+     */
+    public function __isset($arg)
+    {
+        return isset($this->_args[$arg]);
+    }
+
+    /**
+     * sets given value to an argument
+     *
+     * @param $arg          the name of the option to be changed
+     * @param $value        the value of the option
+     * @return Doctrine_Validator_Driver    this object
+     */
+    public function __set($arg, $value)
+    {
+        $this->_args[$arg] = $value;
+        
+        return $this;
+    }
+
+    /**
+     * returns the value of an argument
+     *
+     * @param $arg          the name of the option to retrieve
+     * @return mixed        the value of the option
+     */
+    public function getArg($arg)
+    {
+        if ( ! isset($this->_args[$arg])) {
+            throw new Doctrine_Validator_Exception('Unknown option ' . $arg);
+        }
+        
+        return $this->_args[$arg];
+    }
+
+    /**
+     * sets given value to an argument
+     *
+     * @param $arg          the name of the option to be changed
+     * @param $value        the value of the option
+     * @return Doctrine_Validator_Driver    this object
+     */
+    public function setArg($arg, $value)
+    {
+        $this->_args[$arg] = $value;
+        
+        return $this;
+    }
+
+    /**
+     * returns all args and their associated values
+     *
+     * @return array    all args as an associative array
+     */
+    public function getArgs()
+    {
+        return $this->_args;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Email.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,85 @@
+<?php
+/*
+ *  $Id: Email.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Email
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Email
+{
+    /**
+     * checks if given value is a valid email address
+     *
+     * @link http://iamcal.com/publish/articles/php/parsing_email/pdf/
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+        if (isset($this->args)) {
+            $parts = explode('@', $value);
+        
+            if (isset($parts[1]) && $parts[1] && function_exists('checkdnsrr')) {
+                if ( ! checkdnsrr($parts[1], 'MX')) {
+                    return false;
+                }
+            }
+        }
+
+        $e = explode('.', $value);
+        $tld = end($e);
+        if (preg_match("/[^a-zA-Z]/", $tld)) {
+            return false;
+        }
+
+        $qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';
+        $dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';
+        $atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';
+        $quotedPair = '\\x5c[\\x00-\\x7f]';
+        $domainLiteral = "\\x5b($dtext|$quotedPair)*\\x5d";
+        $quotedString = "\\x22($qtext|$quotedPair)*\\x22";
+        $domainRef = $atom;
+        $subDomain = "($domainRef|$domainLiteral)";
+        $word = "($atom|$quotedString)";
+        $domain = "$subDomain(\\x2e$subDomain)+";
+        /*
+          following pseudocode to allow strict checking - ask pookey about this if you're puzzled
+
+          if ($this->getValidationOption('strict_checking') == true) {
+              $domain = "$sub_domain(\\x2e$sub_domain)*";
+          }
+        */
+        $localPart = "$word(\\x2e$word)*";
+        $addrSpec = "$localPart\\x40$domain";
+
+        return (bool) preg_match("!^$addrSpec$!D", $value);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/ErrorStack.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,185 @@
+<?php
+/*
+ *  $Id: ErrorStack.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_ErrorStack
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Roman Borschel <roman@code-factory.org>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Validator_ErrorStack extends Doctrine_Access implements Countable, IteratorAggregate
+{
+    /**
+     * The errors of the error stack.
+     *
+     * @var array
+     */
+    protected $_errors = array();
+
+    /**
+     * Array of validators that failed
+     *
+     * @var array
+     */
+    protected $_validators = array();
+
+    /**
+     * Get model class name for the error stack
+     *
+     * @var string
+     */
+    protected $_className;
+
+    /**
+     * Constructor
+     *
+     */
+    public function __construct($className)
+    {
+        $this->_className = $className;
+    }
+
+    /**
+     * Adds an error to the stack.
+     *
+     * @param string $invalidFieldName
+     * @param string $errorType
+     */
+    public function add($invalidFieldName, $errorCode = 'general')
+    {
+        // FIXME: In the future the error stack should contain nothing but validator objects
+        if (is_object($errorCode) && strpos(get_class($errorCode), 'Doctrine_Validator_') !== false) {
+            $validator = $errorCode;
+            $this->_validators[$invalidFieldName][] = $validator;
+            $className = get_class($errorCode);
+            $errorCode = strtolower(substr($className, strlen('Doctrine_Validator_'), strlen($className)));
+        }
+
+        $this->_errors[$invalidFieldName][] = $errorCode;
+    }
+
+    /**
+     * Removes all existing errors for the specified field from the stack.
+     *
+     * @param string $fieldName
+     */
+    public function remove($fieldName)
+    {
+        if (isset($this->_errors[$fieldName])) {
+            unset($this->_errors[$fieldName]);
+        }
+    }
+
+    /**
+     * Get errors for field
+     *
+     * @param string $fieldName
+     * @return mixed
+     */
+    public function get($fieldName)
+    {
+        return isset($this->_errors[$fieldName]) ? $this->_errors[$fieldName] : null;
+    }
+
+    /**
+     * Alias for add()
+     *
+     * @param string $fieldName
+     * @param string $errorCode
+     * @return void
+     */
+    public function set($fieldName, $errorCode)
+    {
+        $this->add($fieldName, $errorCode);
+    }
+
+    /**
+     * Check if a field has an error
+     *
+     * @param string $fieldName
+     * @return boolean
+     */
+    public function contains($fieldName)
+    {
+        return array_key_exists($fieldName, $this->_errors);
+    }
+
+    /**
+     * Removes all errors from the stack.
+     *
+     * @return void
+     */
+    public function clear()
+    {
+        $this->_errors = array();
+    }
+
+    /**
+     * Enter description here...
+     *
+     * @return unknown
+     */
+    public function getIterator()
+    {
+        return new ArrayIterator($this->_errors);
+    }
+
+    public function toArray()
+    {
+        return $this->_errors;
+    }
+
+    /**
+     * Count the number of errors
+     *
+     * @return integer
+     */
+    public function count()
+    {
+        return count($this->_errors);
+    }
+
+    /**
+     * Get the classname where the errors occured
+     *
+     * @return string
+     */
+    public function getClassname()
+    {
+        return $this->_className;
+    }
+
+    /**
+     * Get array of failed validators
+     *
+     * @return array
+     */
+    public function getValidators()
+    {
+        return $this->_validators;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,89 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_Validator_Exception extends Doctrine_Exception implements Countable, IteratorAggregate
+{
+    /**
+     * @var array $invalid
+     */
+    private $invalid = array();
+
+    /**
+     * @param Doctrine_Validator $validator
+     */
+    public function __construct(array $invalid)
+    {
+        $this->invalid = $invalid;
+        parent::__construct($this->generateMessage());
+    }
+
+    public function getInvalidRecords()
+    {
+        return $this->invalid;
+    }
+
+    public function getIterator()
+    {
+        return new ArrayIterator($this->invalid);
+    }
+
+    public function count()
+    {
+        return count($this->invalid);
+    }
+
+    /**
+     * Generate a message with all classes that have exceptions
+     */
+    private function generateMessage()
+    {
+        $message = '';
+        foreach ($this->invalid as $record) {
+            $message .= $record->getErrorStackAsString();
+        }
+        return $message;
+    }
+
+    /**
+     * This method will apply the value of the $function variable as a user_func 
+     * to tall errorstack objects in the exception
+     *
+     * @param mixed Either string with function name or array with object, 
+     * functionname. See call_user_func in php manual for more inforamtion
+     */
+    public function inspect($function)
+    {
+        foreach ($this->invalid as $record) {
+            call_user_func($function, $record->getErrorStack());
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Future.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,79 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Future
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Roman Borschel <roman@code-factory.org>
+ */
+class Doctrine_Validator_Future
+{
+    /**
+     * checks if the given value is a valid date in the future.
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+        $e = explode('-', $value);
+
+        if (count($e) !== 3) {
+            return false;
+        }
+        
+        if (is_array($this->args) && isset($this->args['timezone'])) {
+            switch (strtolower($this->args['timezone'])) {
+                case 'gmt':
+                    $now = gmdate("U") - date("Z");
+                    break;
+                default:
+                    $now = getdate();
+                    break;
+            }
+        } else {
+            $now = getdate();
+        }
+        
+        if ($now['year'] > $e[0]) {
+            return false;
+        } else if ($now['year'] == $e[0]) {
+            if ($now['mon'] > $e[1]) {
+                return false;
+            } else if ($now['mon'] == $e[1]) {
+                return $now['mday'] < $e[2];
+            } else {
+                return true;
+            }
+        } else {
+            return true;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Htmlcolor.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,51 @@
+<?php
+/*
+ *  $Id: Htmlcolor.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_HtmlColor
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_HtmlColor
+{
+    /**
+     * checks if given value is a valid html color code
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+        if ( ! preg_match("/^#{0,1}[0-9a-fA-F]{6}$/", $value)) {
+            return false;
+        }
+        return true;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Ip.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,48 @@
+<?php
+/*
+ *  $Id: Ip.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Ip
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Ip
+{
+    /**
+     * checks if given value is valid ip address
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+        return (bool) ip2long(str_replace("\0", '', $value));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Minlength.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,52 @@
+<?php
+/*
+ *  $Id: Minlength.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Regexp
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Gijs van Dulmen <gijs@vandulmen.net>
+ */
+class Doctrine_Validator_Minlength 
+{
+    /**
+     * checks if given value is more length than the minimum length required
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+        if (isset($this->args) && strlen($value) < $this->args) {
+            return false;
+        }
+
+        return true;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Nospace.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,48 @@
+<?php
+/*
+ *  $Id: Nospace.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Nospace
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Nospace extends Doctrine_Validator_Driver
+{
+    /**
+     * checks that value doesn't contain any space chars
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+        return ($value === null || ! preg_match('/\s/', $value));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Notblank.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,46 @@
+<?php
+/*
+ *  $Id: Notblank.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Notblank
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Notblank extends Doctrine_Validator_Driver
+{
+    /**
+     * checks that value isn't blank
+     * a value is blank when its either null or contains only space characters
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        return (trim($value) !== '' && $value !== null);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Notnull.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: Notnull.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Notnull
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Notnull extends Doctrine_Validator_Driver
+{
+    /**
+     * checks that given value isn't null
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        return ($value !== null);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Past.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,79 @@
+<?php
+/*
+ *  $Id: Date.php 2367 2007-09-02 20:00:27Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Past
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Roman Borschel <roman@code-factory.org>
+ */
+class Doctrine_Validator_Past
+{
+    /**
+     * checks if the given value is a valid date in the past.
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+        $e = explode('-', $value);
+
+        if (count($e) !== 3) {
+            return false;
+        }
+        
+        if (is_array($this->args) && isset($this->args['timezone'])) {
+            switch (strtolower($this->args['timezone'])) {
+                case 'gmt':
+                    $now = gmdate("U") - date("Z");
+                    break;
+                default:
+                    $now = getdate();
+                    break;
+            }
+        } else {
+            $now = getdate();
+        }
+        
+        if ($now['year'] < $e[0]) {
+            return false;
+        } else if ($now['year'] == $e[0]) {
+            if ($now['mon'] < $e[1]) {
+                return false;
+            } else if ($now['mon'] == $e[1]) {
+                return $now['mday'] > $e[2];
+            } else {
+                return true;
+            }
+        } else {
+            return true;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Range.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,54 @@
+<?php
+/*
+ *  $Id: Range.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Range
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Range
+{
+    /**
+     * checks if value is within given range
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+        if (isset($this->args[0]) && $value < $this->args[0]) {
+            return false;
+        }
+        if (isset($this->args[1]) && $value > $this->args[1]) {
+            return false;
+        }
+        return true;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Readonly.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,43 @@
+<?php
+/*
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Readonly
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @author      Adam Huttler <ahuttler@geminisbs.com>
+ */
+class Doctrine_Validator_Readonly
+{
+    /**
+     * checks if value has been modified
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        $modified = $this->invoker->getModified();
+        
+        return array_key_exists($this->field, $modified) ? false : true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Regexp.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,65 @@
+<?php
+/*
+ *  $Id: Regexp.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Regexp
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Regexp
+{
+    /**
+     * checks if given value satisfies a regular expression
+     *
+     * @param mixed $value
+     * @param mixed $args
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+        if ( ! isset($this->args)) {
+           return true;
+        }
+        if (is_array($this->args)) {
+            foreach ($this->args as $regexp) {
+                if ( ! preg_match($regexp, $value)) {
+                    return false;
+                }
+            }
+            return true;
+        } else {
+            if (preg_match($this->args, $value)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Time.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,66 @@
+<?php
+/*
+ *  $Id: Time.php 3884 2008-02-22 18:26:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Time
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3884 $
+ * @author      Mark Pearson <mark.pearson0@googlemail.com>
+ */
+class Doctrine_Validator_Time
+{
+    /**
+     * validate
+     *
+     * checks if given value is a valid time
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+
+		if ( ! preg_match('/^\s*(\d{2}):(\d{2})(:(\d{2}))?(\.(\d{1,6}))?([+-]\d{1,2}(:(\d{2}))?)?\s*$/', $value, $matches)) {
+            return false;
+        }
+
+        $hh = (isset($matches[1])) ? intval($matches[1]) : 0;
+        $mm = (isset($matches[2])) ? intval($matches[2]) : 0;
+        $ss = (isset($matches[4])) ? intval($matches[4]) : 0;
+        $ms = (isset($matches[6])) ? intval($matches[6]) : 0;
+        $tz_hh = (isset($matches[7])) ? intval($matches[7]) : 0;
+        $tz_mm = (isset($matches[9])) ? intval($matches[9]) : 0;
+
+        return 	($hh >= 0 && $hh <= 23) &&
+				($mm >= 0 && $mm <= 59) &&
+				($ss >= 0 && $ss <= 59) &&
+				($tz_hh >= -13 && $tz_hh <= 14) &&
+				($tz_mm >= 0 && $tz_mm <= 59) ;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Timestamp.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,64 @@
+<?php
+/*
+ *  $Id: Timestamp.php 3884 2008-02-22 18:26:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Timestamp
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3884 $
+ * @author      Mark Pearson <mark.pearson0@googlemail.com>
+ */
+class Doctrine_Validator_Timestamp
+{
+    /**
+     * checks if given value is a valid timestamp (YYYY-MM-DD HH:MM:SS)
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+
+        $e = explode(' ', trim($value));
+        $date = isset($e[0]) ? $e[0]:null;
+        $time = isset($e[1]) ? $e[1]:null;
+
+        $dateValidator = Doctrine_Validator::getValidator('date');
+        $timeValidator = Doctrine_Validator::getValidator('time');
+
+        if ( ! $dateValidator->validate($date)) {
+            return false;
+        }
+
+        if ( ! $timeValidator->validate($time)) {
+            return false;
+        } 
+
+        return true;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Unique.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,81 @@
+<?php
+/*
+ *  $Id: Unique.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Unique
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Unique
+{
+    /**
+     * checks if given value is unique
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+
+        $table = $this->invoker->getTable();
+        $conn = $table->getConnection();
+        $pks = $table->getIdentifierColumnNames();
+
+        if (is_array($pks)) {
+            for ($i = 0, $l = count($pks); $i < $l; $i++) {
+                $pks[$i] = $conn->quoteIdentifier($pks[$i]);
+            }
+            
+            $pks = join(',', $pks);
+        }
+
+        $sql = 'SELECT ' . $pks . ' FROM ' . $conn->quoteIdentifier($table->getTableName()) 
+             . ' WHERE ' . $conn->quoteIdentifier($table->getColumnName($this->field)) . ' = ?';
+        
+        $values = array();
+        $values[] = $value;
+        
+        // If the record is not new we need to add primary key checks because its ok if the 
+        // unique value already exists in the database IF the record in the database is the same
+        // as the one that is validated here.
+        $state = $this->invoker->state();
+        if ( ! ($state == Doctrine_Record::STATE_TDIRTY || $state == Doctrine_Record::STATE_TCLEAN)) {
+            foreach ((array) $table->getIdentifierColumnNames() as $pk) {
+                $sql .= ' AND ' . $conn->quoteIdentifier($pk) . ' != ?';
+                $values[] = $this->invoker->$pk;
+            }
+        }
+        
+        $stmt  = $table->getConnection()->getDbh()->prepare($sql);
+        $stmt->execute($values);
+
+        return ( ! is_array($stmt->fetch()));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Unsigned.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,60 @@
+<?php
+/*
+ *  $Id: Enum.php 1080 2007-02-10 18:17:08Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Unsigned
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Unsigned
+{
+    /**
+     * checks if given value is a valid unsigned integer or float
+     *
+     * valid values: null, '', 5, '5', 5.9, '5.9'
+     * invalid values: -5, '-5', 'five', -5.9, '-5.9', '5.5.5'
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value) || $value == '') {
+            return true;
+        }
+        if (preg_match('/[^0-9\-\.]/', $value)) {
+            return false;
+        }
+
+        if ((double) $value >= 0)
+        {
+            return true;
+        }
+
+        return false;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Validator/Usstate.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,108 @@
+<?php
+/*
+ *  $Id: Usstate.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Usstate
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Usstate
+{
+    private static $states = array(
+                'AK' => true,
+                'AL' => true,
+                'AR' => true,
+                'AZ' => true,
+                'CA' => true,
+                'CO' => true,
+                'CT' => true,
+                'DC' => true,
+                'DE' => true,
+                'FL' => true,
+                'GA' => true,
+                'HI' => true,
+                'IA' => true,
+                'ID' => true,
+                'IL' => true,
+                'IN' => true,
+                'KS' => true,
+                'KY' => true,
+                'LA' => true,
+                'MA' => true,
+                'MD' => true,
+                'ME' => true,
+                'MI' => true,
+                'MN' => true,
+                'MO' => true,
+                'MS' => true,
+                'MT' => true,
+                'NC' => true,
+                'ND' => true,
+                'NE' => true,
+                'NH' => true,
+                'NJ' => true,
+                'NM' => true,
+                'NV' => true,
+                'NY' => true,
+                'OH' => true,
+                'OK' => true,
+                'OR' => true,
+                'PA' => true,
+                'PR' => true,
+                'RI' => true,
+                'SC' => true,
+                'SD' => true,
+                'TN' => true,
+                'TX' => true,
+                'UT' => true,
+                'VA' => true,
+                'VI' => true,
+                'VT' => true,
+                'WA' => true,
+                'WI' => true,
+                'WV' => true,
+                'WY' => true
+            );
+    public function getStates()
+    {
+        return self::$states;
+    }
+
+    /**
+     * checks if given value is a valid US state code
+     *
+     * @param string $args
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (is_null($value)) {
+            return true;
+        }
+        return isset(self::$states[$value]);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/View.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,192 @@
+<?php
+/*
+ *  $Id: View.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_View
+ *
+ * this class represents a database view
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @package     Doctrine
+ * @subpackage  View
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_View
+{
+    /**
+     * SQL DROP constant
+     */
+    const DROP   = 'DROP VIEW %s';
+
+    /**
+     * SQL CREATE constant
+     */
+    const CREATE = 'CREATE VIEW %s AS %s';
+
+    /**
+     * SQL SELECT constant
+     */
+    const SELECT = 'SELECT * FROM %s';
+
+    /**
+     * @var string $name                the name of the view
+     */
+    protected $_name;
+
+    /**
+     * @var Doctrine_Query $query       the DQL query object this view is hooked into
+     */
+    protected $_query;
+
+    /**
+     * @var Doctrine_Connection $conn   the connection object
+     */
+    protected $_conn;
+
+    /**
+     * @var string $_dql The view dql string
+     */
+    protected $_dql;
+
+    /**
+     * @var string $_sql The view sql string
+     */
+    protected $_sql;
+
+    /**
+     * constructor
+     *
+     * @param Doctrine_Query $query
+     */
+    public function __construct(Doctrine_Query $query, $viewName)
+    {
+        $this->_name  = $viewName;
+        $this->_query = $query;
+        $this->_query->setView($this);
+        $this->_conn   = $query->getConnection();
+        $this->_dql = $query->getDql();
+        $this->_sql = $query->getSql();
+    }
+
+    /**
+     * returns the associated query object
+     *
+     * @return Doctrine_Query
+     */
+    public function getQuery()
+    {
+        return $this->_query;
+    }
+
+    /**
+     * returns the name of this view
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->_name;
+    }
+
+    /**
+     * returns the connection object
+     *
+     * @return Doctrine_Connection
+     */
+    public function getConnection()
+    {
+        return $this->_conn;
+    }
+
+    /**
+     * creates this view
+     *
+     * @throws Doctrine_View_Exception
+     * @return void
+     */
+    public function create()
+    {
+        $sql = sprintf(self::CREATE, $this->_name, $this->_query->getQuery());
+        try {
+            $this->_conn->execute($sql);
+        } catch(Doctrine_Exception $e) {
+            throw new Doctrine_View_Exception($e->__toString());
+        }
+    }
+
+    /**
+     * drops this view from the database
+     *
+     * @throws Doctrine_View_Exception
+     * @return void
+     */
+    public function drop()
+    {
+        try {
+            $this->_conn->execute(sprintf(self::DROP, $this->_name));
+        } catch(Doctrine_Exception $e) {
+            throw new Doctrine_View_Exception($e->__toString());
+        }
+    }
+
+    /**
+     * returns a collection of Doctrine_Record objects
+     *
+     * @return Doctrine_Collection
+     */
+    public function execute()
+    {
+        return $this->_query->execute();
+    }
+
+    /**
+     * returns the select sql for this view
+     *
+     * @return string
+     */
+    public function getSelectSql()
+    {
+        return sprintf(self::SELECT, $this->_name);
+    }
+
+    /**
+     * Get the view sql string
+     *
+     * @return string $sql
+     */
+    public function getViewSql()
+    {
+        return $this->_sql;
+    }
+
+    /**
+     * Get the view dql string
+     *
+     * @return string $dql
+     */
+    public function getViewDql()
+    {
+        return $this->_dql;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/View/Exception.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 5801 2009-06-02 17:30:27Z piccoloprincipe $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  View
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 5801 $
+ */
+class Doctrine_View_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/widget/sfWidgetFormDoctrineChoice.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,120 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfWidgetFormDoctrineChoice represents a choice widget for a model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfWidgetFormDoctrineChoice.class.php 11540 2008-09-14 15:23:55Z fabien $
+ */
+class sfWidgetFormDoctrineChoice extends sfWidgetFormChoice
+{
+  /**
+   * @see sfWidget
+   */
+  public function __construct($options = array(), $attributes = array())
+  {
+    $options['choices'] = new sfCallable(array($this, 'getChoices'));
+
+    parent::__construct($options, $attributes);
+  }
+
+  /**
+   * Constructor.
+   *
+   * Available options:
+   *
+   *  * model:        The model class (required)
+   *  * add_empty:    Whether to add a first empty value or not (false by default)
+   *                  If the option is not a Boolean, the value will be used as the text value
+   *  * method:       The method to use to display object values (__toString by default)
+   *  * key_method:   The method to use to display the object keys (getPrimaryKey by default)
+   *  * order_by:     An array composed of two fields:
+   *                    * The column to order by the results (must be in the PhpName format)
+   *                    * asc or desc
+   *  * query:        A query to use when retrieving objects
+   *  * connection:   The Doctrine connection to use (null by default)
+   *  * multiple:     true if the select tag must allow multiple selections
+   *  * table_method: The method to use to display the object keys (getPrimaryKey by default)
+   *
+   * @see sfWidgetFormSelect
+   */
+  protected function configure($options = array(), $attributes = array())
+  {
+    $this->addRequiredOption('model');
+    $this->addOption('add_empty', false);
+    $this->addOption('method', '__toString');
+    $this->addOption('key_method', 'getPrimaryKey');
+    $this->addOption('order_by', null);
+    $this->addOption('query', null);
+    $this->addOption('connection', null);
+    $this->addOption('multiple', false);
+    $this->addOption('table_method', null);
+
+    parent::configure($options, $attributes);
+  }
+
+  /**
+   * Returns the choices associated to the model.
+   *
+   * @return array An array of choices
+   */
+  public function getChoices()
+  {
+    $choices = array();
+    if (false !== $this->getOption('add_empty'))
+    {
+      $choices[''] = true === $this->getOption('add_empty') ? '' : $this->getOption('add_empty');
+    }
+
+    if (is_null($this->getOption('table_method')))
+    {
+      $query = is_null($this->getOption('query')) ? Doctrine::getTable($this->getOption('model'))->createQuery() : $this->getOption('query');
+      if ($order = $this->getOption('order_by'))
+      {
+        $query->addOrderBy($order[0] . ' ' . $order[1]);
+      }
+      $objects = $query->execute();
+    } else {
+      $tableMethod = $this->getOption('table_method');
+      $results = Doctrine::getTable($this->getOption('model'))->$tableMethod();
+      if ($results instanceof Doctrine_Query)
+      {
+        $objects = $results->execute();
+      } else if ($results instanceof Doctrine_Collection) {
+        $objects = $results;
+      } else if ($results instanceof Doctrine_Record) {
+        $objects = new Doctrine_Collection($this->getOption('model'));
+        $objects[] = $results;
+      } else {
+        $objects = array();
+      }
+    }
+
+    $method = $this->getOption('method');
+    $keyMethod = $this->getOption('key_method');
+
+    foreach ($objects as $object)
+    {
+      try
+      {
+        $choices[$object->$keyMethod()] = $object->$method();
+      } catch (Exception $e) {
+        throw $e;
+      }
+    }
+
+    return $choices;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/widget/sfWidgetFormDoctrineChoiceMany.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfWidgetFormDoctrineChoice represents a choice widget for a model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfWidgetFormDoctrineChoice.class.php 11540 2008-09-14 15:23:55Z fabien $
+ */
+class sfWidgetFormDoctrineChoiceMany extends sfWidgetFormDoctrineChoice
+{
+  /**
+   * Constructor.
+   *
+   * @see sfWidgetFormDoctrineChoice
+   */
+  protected function configure($options = array(), $attributes = array())
+  {
+    parent::configure($options, $attributes);
+
+    $this->setOption('multiple', true);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/widget/sfWidgetFormDoctrineSelect.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,103 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfWidgetFormDoctrineSelect represents a select HTML tag for a model.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfWidgetFormDoctrineSelect.class.php 7746 2008-03-05 12:10:27Z fabien $
+ */
+class sfWidgetFormDoctrineSelect extends sfWidgetFormSelect
+{
+  /**
+   * @see sfWidget
+   */
+  public function __construct($options = array(), $attributes = array())
+  {
+    $options['choices'] = new sfCallable(array($this, 'getChoices'));
+
+    parent::__construct($options, $attributes);
+  }
+
+  /**
+   * Constructor.
+   *
+   * Available options:
+   *
+   *  * model:      The model class (required)
+   *  * add_empty:  Whether to add a first empty value or not (false by default)
+   *                If the option is not a Boolean, the value will be used as the text value
+   *  * method:     The method to use to display object values (__toString by default)
+   *  * order_by:   An array composed of two fields:
+   *                  * The column to order by the results (must be in the PhpName format)
+   *                  * asc or desc
+   *  * alias:      The alias for the main component involved in the query
+   *  * query:      A query to use when retrieving objects
+   *  * connection: The Doctrine connection to use (null by default)
+   *  * multiple:   true if the select tag must allow multiple selections
+   *
+   * @see sfWidgetFormSelect
+   */
+  protected function configure($options = array(), $attributes = array())
+  {
+    $this->addRequiredOption('model');
+    $this->addOption('add_empty', false);
+    $this->addOption('method', '__toString');
+    $this->addOption('order_by', null);
+    $this->addOption('alias', 'a');
+    $this->addOption('query', null);
+    $this->addOption('connection', null);
+    $this->addOption('multiple', false);
+
+    parent::configure($options, $attributes);
+  }
+
+  /**
+   * Returns the choices associated to the model.
+   *
+   * @return array An array of choices
+   */
+  public function getChoices()
+  {
+    $choices = array();
+    if (false !== $this->getOption('add_empty'))
+    {
+      $choices[''] = true === $this->getOption('add_empty') ? '' : $this->getOption('add_empty');
+    }
+
+    $a = $this->getOption('alias');
+    $q = is_null($this->getOption('query'))
+        ? Doctrine::getTable($this->getOption('model'))->createQuery($a)
+        : $this->getOption('query');
+
+    if ($order = $this->getOption('order_by'))
+    {
+      $q->orderBy("$a." . $order[0] . ' ' . $order[1]);
+    }
+
+    $objects = $q->execute();
+    $method = $this->getOption('method');
+    foreach ($objects as $object)
+    {
+        $choices[is_array($value = $object->getPrimaryKey()) ? current($value) : $value] = $object->$method();
+    }
+
+    return $choices;
+  }
+
+  public function __clone()
+  {
+    $this->setOption('choices', new sfCallable(array($this, 'getChoices')));
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/lib/widget/sfWidgetFormDoctrineSelectMany.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) Jonathan H. Wage <jonwage@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfWidgetFormDoctrineSelectMany represents a select HTML tag for a model where you can select multiple values.
+ *
+ * @package    symfony
+ * @subpackage doctrine
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     Jonathan H. Wage <jonwage@gmail.com>
+ * @version    SVN: $Id: sfWidgetFormDoctrineSelectMany.class.php 7147 2008-01-22 11:11:01Z fabien $
+ */
+class sfWidgetFormDoctrineSelectMany extends sfWidgetFormDoctrineSelect
+{
+  /**
+   * Constructor.
+   *
+   * @see sfWidgetFormDoctrineSelect
+   */
+  protected function configure($options = array(), $attributes = array())
+  {
+    parent::configure($options, $attributes);
+
+    $this->setOption('multiple', true);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/bin/coverage.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+define('SYMFONY_LIB_DIR', realpath(dirname(__FILE__).'/../../../..'));
+
+require(SYMFONY_LIB_DIR.'/vendor/lime/lime.php');
+require(SYMFONY_LIB_DIR.'/util/sfFinder.class.php');
+
+$h = new lime_harness(new lime_output_color());
+$h->base_dir = realpath(dirname(__FILE__).'/..');
+
+// unit tests
+$h->register_glob($h->base_dir.'/unit/*/*Test.php');
+$h->register_glob($h->base_dir.'/unit/*/*/*Test.php');
+
+// functional tests
+$h->register_glob($h->base_dir.'/functional/*Test.php');
+$h->register_glob($h->base_dir.'/functional/*/*Test.php');
+
+$c = new lime_coverage($h);
+$c->extension = '.class.php';
+$c->verbose = false;
+$c->base_dir = realpath(dirname(__FILE__).'/../lib');
+
+$finder = sfFinder::type('file')->name('*.php')->prune('vendor')->prune('test')->prune('data');
+$c->register($finder->in($c->base_dir));
+$c->run();
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/bin/prove.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+define('SYMFONY_LIB_DIR', realpath(dirname(__FILE__).'/../../../..'));
+
+require(SYMFONY_LIB_DIR.'/vendor/lime/lime.php');
+require(SYMFONY_LIB_DIR.'/util/sfFinder.class.php');
+
+$h = new lime_harness(new lime_output_color());
+$h->base_dir = realpath(dirname(__FILE__).'/..');
+
+$h->register(sfFinder::type('file')->prune('fixtures')->name('*Test.php')->in(array(
+  // unit tests
+  $h->base_dir.'/unit',
+  // functional tests
+  $h->base_dir.'/functional'
+)));
+
+exit($h->run() ? 0 : 1);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/bootstrap/functional.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+include(dirname(__FILE__).'/../../../../../test/bootstrap/unit.php');
+
+if (!isset($root_dir))
+{
+  $root_dir = realpath(dirname(__FILE__).sprintf('/../%s/fixtures', isset($type) ? $type : 'functional'));
+}
+
+include $root_dir.'/config/ProjectConfiguration.class.php';
+$configuration = ProjectConfiguration::getApplicationConfiguration($app, 'test', isset($debug) ? $debug : true);
+sfContext::createInstance($configuration);
+
+function sf_functional_test_shutdown()
+{
+  sfToolkit::clearDirectory(sfConfig::get('sf_cache_dir'));
+  sfToolkit::clearDirectory(sfConfig::get('sf_log_dir'));
+  $databases = glob(sfConfig::get('sf_data_dir') . '/*.sqlite');
+  foreach ($databases as $database)
+  {
+    unlink($database);
+  }
+}
+
+// remove all cache
+sf_functional_test_shutdown();
+
+$configuration->initializeDoctrine();
+if (isset($fixtures))
+{
+  $configuration->loadFixtures($fixtures);
+}
+
+register_shutdown_function('sf_functional_test_shutdown');
+
+return true;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/bootstrap/unit.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * 
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+include(dirname(__FILE__).'/../../../../../test/bootstrap/unit.php');
+
+include(dirname(__FILE__).'/../../../../autoload/sfSimpleAutoload.class.php');
+$autoload = sfSimpleAutoload::getInstance(sfToolkit::getTmpDir().DIRECTORY_SEPARATOR.sprintf('sf_autoload_unit_doctrine_%s.data', md5(__FILE__)));
+$autoload->addDirectory(realpath(dirname(__FILE__).'/../../lib'));
+$autoload->register();
+
+$_test_dir = realpath(dirname(__FILE__).'/..');
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/EnvironmentSetupTest.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ * 
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+$app = 'frontend';
+$fixtures = 'fixtures/fixtures.yml';
+require_once(dirname(__FILE__).'/../bootstrap/functional.php');
+
+$t = new lime_test(12, new lime_output_color());
+
+// Make sure Author records were populated properly
+$q = Doctrine_Query::create()
+  ->from('Author a');
+$results = $q->fetchArray();
+
+$t->is(count($results), 2);
+$t->is($results[0]['name'], 'Jonathan H. Wage');
+$t->is($results[1]['name'], 'Fabien POTENCIER');
+
+// Make sure data fixtures were loaded
+$q = Doctrine_Query::create()
+  ->from('Article a')
+  ->leftJoin('a.Translation t');
+
+$articles = $q->fetchArray();
+$t->is($articles[0]['Translation']['en']['title'], 'English Title');
+
+$manager = Doctrine_Manager::getInstance();
+$conn1 = $manager->getConnection('doctrine1');
+$conn2 = $manager->getConnection('doctrine2');
+$conn3 = $manager->getConnection('doctrine3');
+
+// Make sure all connections are created properly from databases.yml
+$t->is(count($manager), 3);
+$t->is($conn1->getOption('dsn'), 'sqlite:' . sfConfig::get('sf_data_dir') . '/database1.sqlite');
+$t->is($conn2->getOption('dsn'), 'sqlite:' . sfConfig::get('sf_data_dir') . '/database2.sqlite');
+$t->is($conn3->getOption('dsn'), 'sqlite:' . sfConfig::get('sf_data_dir') . '/database3.sqlite');
+
+// Set globally by ProjectConfiguration::configureDoctrine()
+$t->is($manager->getAttribute('validate'), true);
+
+// We disable validation for the doctrine2 connection in ProjectConfiguration::configureDoctrineConnectionDoctrine2()
+$t->is($conn2->getAttribute('validate'), false);
+
+// We set export attribute on the connection in databases.yml
+$t->is($conn3->getAttribute('export'), Doctrine::EXPORT_TABLES);
+
+$article = new ReflectionClass('Article');
+$parent = new ReflectionClass('myDoctrineRecord');
+$t->is($article->isSubclassOf($parent), true);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/FormTest.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,75 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ * 
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+$app = 'frontend';
+require_once(dirname(__FILE__).'/../bootstrap/functional.php');
+
+$t = new lime_test(13, new lime_output_color());
+
+// test for ticket #4935
+$user = new User();
+$profile = $user->getProfile();
+
+$userForm = new UserForm($user);
+$profileForm = new ProfileForm($profile);
+unset($profileForm['id'], $profileForm['user_id']);
+
+$userForm->embedForm('Profile', $profileForm);
+
+$data = array('username' => 'jwage',
+              'password' => 'changeme',
+              'Profile'  => array(
+                  'first_name' => 'Jonathan',
+                  'last_name'  => 'Wage'
+                ));
+
+$userForm->bind($data);
+$userForm->save();
+
+$t->is($user->getId() > 0, true);
+$t->is($user->getId(), $profile->getUserId());
+$t->is($user->getUsername(), 'jwage');
+$t->is($profile->getFirstName(), 'Jonathan');
+
+$userCount = Doctrine_Query::create()
+  ->from('User u')
+  ->count();
+
+$t->is($userCount, 1);
+
+$profileCount = Doctrine_Query::create()
+  ->from('Profile p')
+  ->count();
+
+$t->is($profileCount, 1);
+
+$widget = new sfWidgetFormDoctrineChoice(array('model' => 'User'));
+$t->is($widget->getChoices(), array(1 => 1));
+
+$widget = new sfWidgetFormDoctrineChoice(array('model' => 'User', 'key_method' => 'getUsername', 'method' => 'getPassword'));
+$t->is($widget->getChoices(), array('jwage' => '4cb9c8a8048fd02294477fcb1a41191a'));
+
+$widget = new sfWidgetFormDoctrineChoice(array('model' => 'User', 'key_method' => 'getUsername', 'method' => 'getPassword'));
+$t->is($widget->getChoices(), array('jwage' => '4cb9c8a8048fd02294477fcb1a41191a'));
+
+$methods = array(
+  'widgetChoiceTableMethod1',
+  'widgetChoiceTableMethod2',
+  'widgetChoiceTableMethod3'
+);
+
+foreach ($methods as $method)
+{
+  $widget = new sfWidgetFormDoctrineChoice(array('model' => 'User', 'table_method' => $method));
+  $t->is($widget->getChoices(), array(1 => 1));
+}
+
+$widget = new sfWidgetFormDoctrineChoice(array('model' => 'User', 'table_method' => 'widgetChoiceTableMethod4'));
+$t->is($widget->getChoices(), array());
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/I18nTest.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,178 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ * 
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+$app = 'frontend';
+require_once(dirname(__FILE__).'/../bootstrap/functional.php');
+
+$t = new lime_test(11, new lime_output_color());
+
+$article = new Article();
+$article->title = 'test';
+$t->is($article->Translation['en']->title, 'test');
+
+sfContext::getInstance()->getUser()->setCulture('fr');
+$article->title = 'fr test';
+$t->is($article->Translation['fr']->title, 'fr test');
+
+$t->is($article->getTitle(), $article->title);
+$article->setTitle('test');
+$t->is($article->getTitle(), 'test');
+
+$article->setTestColumn('test');
+$t->is($article->getTestColumn(), 'test');
+$t->is($article->Translation['fr']['test_column'], 'test');
+
+$article->free(true);
+
+class MyArticleForm extends ArticleForm
+{
+  public function configure()
+  {
+    parent::configure();
+
+    $this->embedI18n(array('en', 'fr'));
+
+    $authorForm = new AuthorForm($this->object->Author);
+    unset($authorForm['id']);
+
+    $this->embedForm('Author', $authorForm);
+
+    unset($this['author_id']);
+  }
+
+  public function updateDefaultsFromObject()
+  {
+    parent::updateDefaultsFromObject();
+  }
+}
+
+$article = new Article();
+$articleForm = new MyArticleForm($article);
+
+$data = array(
+  'is_on_homepage' => 1,
+  'Author' => array(
+    'name' => 'i18n author test'),
+  'en' => array(
+    'title' => 'english title',
+    'body'  => 'english body'),
+  'fr' => array(
+    'title' => 'french title',
+    'body'  => 'french body')
+);
+
+$articleForm->bind($data);
+$t->is($articleForm->isValid(), true);
+
+$values = array(
+  'is_on_homepage' => true,
+  'Author' => 
+  array(
+    'name' => 'i18n author test',
+  ),
+  'en' => 
+  array(
+    'title' => 'english title',
+    'body' => 'english body',
+    'test_column' => '',
+    'slug' => '',
+  ),
+  'fr' => 
+  array(
+    'title' => 'french title',
+    'body' => 'french body',
+    'test_column' => '',
+    'slug' => '',
+  ),
+  'id' => null,
+  'created_at' => null,
+  'updated_at' => null,
+);
+
+$t->is($articleForm->getValues(), $values);
+
+$articleForm->save();
+
+$expected = array(
+  'id' => $article->id,
+  'author_id' => $article->Author->id,
+  'is_on_homepage' => true,
+  'created_at' => $article->created_at,
+  'updated_at' => $article->updated_at,
+  'Translation' => 
+  array(
+    'en' => 
+    array(
+      'id' => $article->id,
+      'title' => 'english title',
+      'body' => 'english body',
+      'test_column' => '',
+      'lang' => 'en',
+      'slug' => 'english-title',
+    ),
+    'fr' => 
+    array(
+      'id' => $article->id,
+      'title' => 'french title',
+      'body' => 'french body',
+      'test_column' => '',
+      'lang' => 'fr',
+      'slug' => 'french-title',
+    ),
+  ),
+  'Author' => 
+  array(
+    'id' => $article->Author->id,
+    'name' => 'i18n author test',
+  ),
+);
+
+$t->is($article->toArray(true), $expected);
+
+$articleForm->updateDefaultsFromObject();
+
+$expected = array(
+  'id' => $article->id,
+  'author_id' => $article->author_id,
+  'is_on_homepage' => true,
+  'created_at' => $article->created_at,
+  'updated_at' => $article->updated_at,
+  'en' => 
+  array(
+    'id' => $article->id,
+    'title' => 'english title',
+    'body' => 'english body',
+    'test_column' => '',
+    'lang' => 'en',
+    'slug' => 'english-title',
+  ),
+  'fr' => 
+  array(
+    'id' => $article->id,
+    'title' => 'french title',
+    'body' => 'french body',
+    'test_column' => '',
+    'lang' => 'fr',
+    'slug' => 'french-title',
+  ),
+  'Author' => 
+  array(
+    'id' => $article->Author->id,
+    'name' => 'i18n author test',
+  ),
+);
+
+$t->is($articleForm->getDefaults(), $expected);
+
+$article = new Article();
+sfContext::getInstance()->getUser()->setCulture('en');
+$article->title = 'test';
+sfContext::getInstance()->getUser()->setCulture('fr');
+$t->is($article->title, 'test');
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/PagerTest.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,69 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ * 
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+$app = 'frontend';
+require_once(dirname(__FILE__).'/../bootstrap/functional.php');
+
+$t = new lime_test(11, new lime_output_color());
+
+$total = 50;
+for ($i = 0; $i < $total; $i++)
+{
+  $author = new Author();
+  $author->name = 'Author #' . $i;
+  $author->save();
+}
+
+$numPerPage = 25;
+$pager = new sfDoctrinePager('Author', $numPerPage);
+$pager->setTableMethod('testTableMethod');
+$pager->setPage(1);
+$pager->init();
+
+$t->is($pager->getQuery()->getSql(), 'SELECT a.id AS a__id, a.name AS a__name FROM author a WHERE a.id > 0 LIMIT 25');
+
+$pager->setPage(2);
+$pager->init();
+
+$t->is($pager->getQuery()->getSql(), 'SELECT a.id AS a__id, a.name AS a__name FROM author a WHERE a.id > 0 LIMIT 25 OFFSET 25');
+
+$results = $pager->getResults();
+
+$t->is(gettype($results), 'object');
+$t->is(get_class($results), 'Doctrine_Collection');
+$t->is(count($results), $numPerPage);
+$t->is($pager->getQuery()->count(), $total);
+$t->is($pager->getCountQuery()->count(), $total);
+
+$pager = new sfDoctrinePager('Author', $numPerPage);
+$pager->setTableMethod('testTableMethod');
+$pager->setPage(1);
+$pager->init();
+
+$results = $pager->getResults('array');
+
+$t->is(gettype($results), 'array');
+$t->is(count($results), $numPerPage);
+
+$pager = new sfDoctrinePager('Author', $numPerPage);
+$pager->setTableMethod('testTableMethod2');
+$pager->setQuery(Doctrine_Query::create()->from('Author a')->where('a.id < 9999999'));
+$pager->setPage(1);
+$pager->init();
+
+$t->is($pager->getQuery()->getSql(), 'SELECT a.id AS a__id, a.name AS a__name FROM author a WHERE a.id < 9999999 AND a.id > 0 LIMIT 25');
+
+
+$pager = new sfDoctrinePager('Author', $numPerPage);
+$pager->setQuery(Doctrine_Query::create()->from('Author a')->where('a.id < 9999999'));
+$pager->setPage(1);
+$pager->init();
+
+$t->is($pager->getQuery()->getSql(), 'SELECT a.id AS a__id, a.name AS a__name FROM author a WHERE a.id < 9999999 LIMIT 25');
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/Ticket/5269Test.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ * 
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+$app = 'frontend';
+require_once(dirname(__FILE__).'/../../bootstrap/functional.php');
+
+$t = new lime_test(1, new lime_output_color());
+
+class TestUserForm extends UserForm
+{
+  public function configure()
+  {
+    parent::configure();
+    unset($this['test']);
+  }
+}
+
+$user = new User();
+$user->username = 'nullvaluetest';
+$user->password = 'changeme';
+$user->test = 'test';
+$user->save();
+$user->free();
+unset($user);
+
+$user = Doctrine::getTable('User')->findOneByUsername('nullvaluetest');
+$userForm = new TestUserForm($user);
+$userForm->bind(array('id' => $user->id, 'username' => 'nullvaluetest', 'password' => 'changeme2'));
+if ($userForm->isValid())
+{
+  $userForm->save();
+}
+
+$user->free();
+unset($user);
+
+$user = Doctrine::getTable('User')->findOneByUsername('nullvaluetest');
+$t->is($user->toArray(), array('id' => 1, 'username' => 'nullvaluetest', 'password' => 'b0660f0b8b989971524762330aea5449', 'test' => 'test'));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/UniqueTest.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ * 
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+$app = 'frontend';
+require_once(dirname(__FILE__).'/../bootstrap/functional.php');
+
+$t = new lime_test(2, new lime_output_color());
+
+$data = array(
+  'unique_test1' => 'test',
+  'unique_test2' => 'test',
+  'unique_test3' => 'test',
+  'unique_test4' => 'test'
+);
+
+$uniqueTestForm = new UniqueTestForm();
+$uniqueTestForm->bind($data);
+$uniqueTestForm->save();
+
+$uniqueTestForm = new UniqueTestForm();
+$uniqueTestForm->bind($data);
+$t->is($uniqueTestForm->isValid(), false);
+$t->is((string) $uniqueTestForm->getErrorSchema(), 'An object with the same "unique_test1" already exist. An object with the same "unique_test1, unique_test2" already exist. An object with the same "unique_test4" already exist.');
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/app.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,2 @@
+# default values
+#all:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/backendConfiguration.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,8 @@
+<?php
+
+class backendConfiguration extends sfApplicationConfiguration
+{
+  public function configure()
+  {
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/cache.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,4 @@
+default:
+  enabled:     off
+  with_layout: false
+  lifetime:    86400
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/factories.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,132 @@
+prod:
+  logger:
+    class:   sfNoLogger
+    param:
+      level:   err
+      loggers: ~
+
+cli:
+  controller:
+    class: sfConsoleController
+  request:
+    class: sfConsoleRequest
+  response:
+    class: sfConsoleResponse
+
+test:
+  storage:
+    class: sfSessionTestStorage
+    param:
+      session_path: %SF_TEST_CACHE_DIR%/sessions
+
+  response:
+    class: sfWebResponse
+    param:
+      send_http_headers: false
+
+all:
+  routing:
+    class: sfPatternRouting
+    param:
+      generate_shortest_url:            true
+      extra_parameters_as_query_string: true
+
+#all:
+#  controller:
+#    class: sfFrontWebController
+#
+#  request:
+#    class: sfWebRequest
+#    param:
+#      logging:           %SF_LOGGING_ENABLED%
+#      path_info_array:   SERVER
+#      path_info_key:     PATH_INFO
+#      relative_url_root: ~
+#      formats:
+#        txt:  text/plain
+#        js:   [application/javascript, application/x-javascript, text/javascript]
+#        css:  text/css
+#        json: [application/json, application/x-json]
+#        xml:  [text/xml, application/xml, application/x-xml]
+#        rdf:  application/rdf+xml
+#        atom: application/atom+xml
+#
+#  response:
+#    class: sfWebResponse
+#    param:
+#      logging:           %SF_LOGGING_ENABLED%
+#      charset:           %SF_CHARSET%
+#      send_http_headers: true
+#
+#  user:
+#    class: myUser
+#    param:
+#      timeout:         1800
+#      logging:         %SF_LOGGING_ENABLED%
+#      use_flash:       true
+#      default_culture: %SF_DEFAULT_CULTURE%
+#
+#  storage:
+#    class: sfSessionStorage
+#    param:
+#      session_name: symfony
+#
+#  view_cache:
+#    class: sfFileCache
+#    param:
+#      automatic_cleaning_factor: 0
+#      cache_dir:                 %SF_TEMPLATE_CACHE_DIR%
+#      lifetime:                  86400
+#      prefix:                    %SF_APP_DIR%/template
+#
+#  i18n:
+#    class: sfI18N
+#    param:
+#      source:               XLIFF
+#      debug:                off
+#      untranslated_prefix:  "[T]"
+#      untranslated_suffix:  "[/T]"
+#      cache:
+#        class: sfFileCache
+#        param:
+#          automatic_cleaning_factor: 0
+#          cache_dir:                 %SF_I18N_CACHE_DIR%
+#          lifetime:                  31556926
+#          prefix:                    %SF_APP_DIR%/i18n
+#
+#  routing:
+#    class: sfPatternRouting
+#    param:
+#      load_configuration:               true
+#      suffix:                           ''
+#      default_module:                   default
+#      default_action:                   index
+#      debug:                            %SF_DEBUG%
+#      logging:                          %SF_LOGGING_ENABLED%
+#      generate_shortest_url:            false
+#      extra_parameters_as_query_string: false
+#      cache:
+#        class: sfFileCache
+#        param:
+#          automatic_cleaning_factor: 0
+#          cache_dir:                 %SF_CONFIG_CACHE_DIR%/routing
+#          lifetime:                  31556926
+#          prefix:                    %SF_APP_DIR%/routing
+#
+#  logger:
+#    class: sfAggregateLogger
+#    param:
+#      level: debug
+#      loggers:
+#        sf_web_debug:
+#          class: sfWebDebugLogger
+#          param:
+#            level: debug
+#            condition:       %SF_WEB_DEBUG%
+#            xdebug_logging:  true
+#            web_debug_class: sfWebDebug
+#        sf_file_debug:
+#          class: sfFileLogger
+#          param:
+#            level: debug
+#            file: %SF_LOG_DIR%/%SF_APP%_%SF_ENVIRONMENT%.log
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/filters.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,8 @@
+rendering: ~
+security:  ~
+
+# insert your own filters here
+
+cache:     ~
+common:    ~
+execution: ~
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/routing.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,109 @@
+doctrine_route_test1:
+  url:   /doctrine/route/test1
+  class: sfDoctrineRoute
+  options: { model: Article, type: object, method_for_query: retrieveArticle1 }
+  param: { module: doctrine_route_test, action: index }
+
+doctrine_route_test2:
+  url:   /doctrine/route/test2
+  class: sfDoctrineRoute
+  options: { model: Article, type: object, method: retrieveArticle2 }
+  param: { module: doctrine_route_test, action: index }
+
+doctrine_route_test3:
+  url:   /doctrine/route/test3
+  class: sfDoctrineRoute
+  options: { model: Article, type: list, method: retrieveArticle3 }
+  param: { module: doctrine_route_test, action: index }
+
+doctrine_route_test4:
+  url:   /doctrine/route/test4
+  class: sfDoctrineRoute
+  options: { model: Article, type: list, method: retrieveArticle4 }
+  param: { module: doctrine_route_test, action: index }
+
+doctrine_route_test5:
+  url:   /doctrine/route/test5/:id/:testing_non_column
+  class: sfDoctrineRoute
+  options: { model: Article, type: object }
+  param: { module: doctrine_route_test, action: index }
+
+doctrine_route_test6:
+  url:   /doctrine/route/test6/:slug/:testing_non_column
+  class: sfDoctrineRoute
+  options: { model: Article, type: object }
+  param: { module: doctrine_route_test, action: index }
+
+doctrine_route_test7:
+  url:   /doctrine/route/test7/:testing_non_column
+  class: sfDoctrineRoute
+  options: { model: Article, type: list }
+  param: { module: doctrine_route_test, action: index }
+
+doctrine_route_test8:
+  url:   /doctrine/route/test8/:id/:slug/:title/:testing_non_column2
+  class: sfDoctrineRoute
+  options: { model: Article, type: object }
+  param: { module: doctrine_route_test, action: index }
+
+doctrine_route_test9:
+  url:   /doctrine/route/test9/:id/:slug/:title/:testing_non_column
+  class: sfDoctrineRoute
+  options: { model: Article, type: object, method: routeTest9 }
+  param: { module: doctrine_route_test, action: index }
+
+doctrine_route_test10:
+  url:   /doctrine/route/test10/:is_on_homepage/:testing_non_column
+  class: sfDoctrineRoute
+  options: { model: Article, type: list, method_for_query: routeTest10 }
+  param: { module: doctrine_route_test, action: index }
+
+user:
+  class: sfDoctrineRouteCollection
+  options:
+    model:               User
+    module:              users
+    prefix_path:         users
+    column:              id
+    with_wildcard_routes: true
+
+subscription:
+  class: sfDoctrineRouteCollection
+  options:
+    model:               Subscription
+    module:              subscriptions
+    prefix_path:         subscriptions
+    column:              id
+    with_wildcard_routes: true
+
+author:
+  class: sfDoctrineRouteCollection
+  options:
+    model:               Author
+    module:              authors
+    prefix_path:         authors
+    column:              id
+    with_wildcard_routes: true
+
+my_articles:
+  class: sfDoctrineRouteCollection
+  options:
+    model:               Article
+    module:              my_articles
+    prefix_path:         my_articles
+    column:              id
+    with_wildcard_routes: true
+
+article:
+  class: sfDoctrineRouteCollection
+  options:
+    model:               Article
+    module:              articles
+    prefix_path:         articles
+    column:              id
+    with_wildcard_routes: true
+
+# default rules
+homepage:
+  url:   /
+  param: { module: default, action: index }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/security.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,2 @@
+default:
+  is_secure: off
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/settings.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,93 @@
+prod:
+  .settings:
+    no_script_name:         off
+    logging_enabled:        off
+
+dev:
+  .settings:
+    error_reporting:        <?php echo (E_ALL | E_STRICT)."\n" ?>
+    web_debug:              on
+    cache:                  off
+    no_script_name:         off
+    etag:                   off
+
+test:
+  .settings:
+    error_reporting:        <?php echo ((E_ALL | E_STRICT) ^ E_NOTICE)."\n" ?>
+    cache:                  off
+    web_debug:              off
+    no_script_name:         off
+    etag:                   off
+
+all:
+  .settings:
+    # Form security secret (CSRF protection)
+    csrf_secret:       false     # Unique secret to enable CSRF protection or false to disable
+
+    # Output escaping settings
+    escaping_strategy:      false            # Determines how variables are made available to templates. Accepted values: on, off.
+    escaping_method:        ESC_SPECIALCHARS # Function or helper used for escaping. Accepted values: ESC_RAW, ESC_ENTITIES, ESC_JS, ESC_JS_NO_ENTITIES, and ESC_SPECIALCHARS.
+
+#all:
+#  .actions:
+#    error_404_module:       default   # To be called when a 404 error is raised
+#    error_404_action:       error404  # Or when the requested URL doesn't match any route
+#
+#    login_module:           default   # To be called when a non-authenticated user
+#    login_action:           login     # Tries to access a secure page
+#
+#    secure_module:          default   # To be called when a user doesn't have
+#    secure_action:          secure    # The credentials required for an action
+#
+#    module_disabled_module: default   # To be called when a user requests 
+#    module_disabled_action: disabled  # A module disabled in the module.yml
+#
+#  .settings:
+#    # Optional features. Deactivating unused features boots performance a bit.
+#    use_database:           on        # Enable database manager. Set to off if you don't use a database.
+#    i18n:                   off       # Enable interface translation. Set to off if your application should not be translated.
+#    check_symfony_version:  off       # Enable check of symfony version for every request. Set to on to have symfony clear the cache automatically when the framework is upgraded. Set to off if you always clear the cache after an upgrade.
+#    compressed:             off       # Enable PHP response compression. Set to on to compress the outgoing HTML via the PHP handler.
+#    check_lock:             off       # Enable the application lock system triggered by the clear-cache and disable tasks. Set to on to have all requests to disabled applications redirected to the $sf_symfony_lib_dir/exception/data/unavailable.php page.
+#
+#    # Routing settings
+#    no_script_name:         off       # Enable the front controller name in generated URLs
+#
+#    # Validation settings, used for error generation by the Validation helper
+#    validation_error_prefix:    ' &darr;&nbsp;'
+#    validation_error_suffix:    ' &nbsp;&darr;'
+#    validation_error_class:     form_error
+#    validation_error_id_prefix: error_for_
+#
+#    # Cache settings
+#    cache:                  off       # Enable the template cache
+#    etag:                   on        # Enable etag handling
+#
+#    # Logging and debugging settings
+#    web_debug:              off       # Enable the web debug toolbar
+#    error_reporting:        <?php echo (E_PARSE | E_COMPILE_ERROR | E_ERROR | E_CORE_ERROR | E_USER_ERROR)."\n" ?> # Determines which events are logged.
+#
+#    # Assets paths
+#    rich_text_js_dir:       js/tiny_mce
+#    admin_web_dir:          /sf/sf_admin
+#    web_debug_web_dir:      /sf/sf_web_debug
+#    calendar_web_dir:       /sf/calendar
+#
+#    # Helpers included in all templates by default
+#    standard_helpers:       [Partial, Cache, Form]
+#
+#    # Activated modules from plugins or from the symfony core
+#    enabled_modules:        [default]
+#
+#    # Charset used for the response
+#    charset:                utf-8
+#
+#    # Miscellaneous
+#    strip_comments:         on         # Remove comments in core framework classes as defined in the core_compile.yml
+#    max_forwards:           5
+#
+#    # Logging
+#    logging_enabled:        on
+#
+#    # i18n
+#    default_culture:        en        # Default user culture
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/config/view.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,17 @@
+default:
+  http_metas:
+    content-type: text/html
+
+  metas:
+    #title:        symfony project
+    #description:  symfony project
+    #keywords:     symfony, project
+    #language:     en
+    #robots:       index, follow
+
+  stylesheets:    [main.css]
+
+  javascripts:    []
+
+  has_layout:     on
+  layout:         layout
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/lib/myUser.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,5 @@
+<?php
+
+class myUser extends sfBasicSecurityUser
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/modules/doctrine_route_test/actions/actions.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * doctrine_route_test actions.
+ *
+ * @package    symfony12
+ * @subpackage doctrine_route_test
+ * @author     Your name here
+ * @version    SVN: $Id: actions.class.php 12479 2008-10-31 10:54:40Z fabien $
+ */
+class doctrine_route_testActions extends sfActions
+{
+  public function executeIndex(sfWebRequest $request)
+  {
+    try {
+      $this->object = $this->getRoute()->getObjects();
+    } catch (Exception $e) {
+      try {
+        $this->object = $this->getRoute()->getObject();
+      } catch (Exception $e) {
+        return sfView::NONE;
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/modules/doctrine_route_test/templates/indexSuccess.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,1 @@
+<?php echo get_class($object) ?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/modules/my_articles/actions/actions.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,16 @@
+<?php
+
+require_once dirname(__FILE__).'/../lib/my_articlesGeneratorConfiguration.class.php';
+require_once dirname(__FILE__).'/../lib/my_articlesGeneratorHelper.class.php';
+
+/**
+ * my_articles actions.
+ *
+ * @package    symfony12
+ * @subpackage my_articles
+ * @author     Your name here
+ * @version    SVN: $Id: actions.class.php 12474 2008-10-31 10:41:27Z fabien $
+ */
+class my_articlesActions extends autoMy_articlesActions
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/modules/my_articles/config/generator.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,21 @@
+generator:
+  class: sfDoctrineGenerator
+  param:
+    model_class:           Article
+    theme:                 admin
+    non_verbose_templates: true
+    with_show:             false
+    singular:              ~
+    plural:                ~
+    route_prefix:          my_articles
+    with_doctrine_route:     1
+
+    config:
+      actions: ~
+      fields:  ~
+      list:
+        table_method: testAdminGenTableMethod
+      filter:  ~
+      form:    ~
+      edit:    ~
+      new:     ~
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/modules/my_articles/lib/my_articlesGeneratorConfiguration.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * my_articles module configuration.
+ *
+ * @package    symfony12
+ * @subpackage my_articles
+ * @author     Your name here
+ * @version    SVN: $Id: configuration.php 12474 2008-10-31 10:41:27Z fabien $
+ */
+class my_articlesGeneratorConfiguration extends BaseMy_articlesGeneratorConfiguration
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/modules/my_articles/lib/my_articlesGeneratorHelper.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * my_articles module helper.
+ *
+ * @package    symfony12
+ * @subpackage my_articles
+ * @author     Your name here
+ * @version    SVN: $Id: helper.php 12474 2008-10-31 10:41:27Z fabien $
+ */
+class my_articlesGeneratorHelper extends BaseMy_articlesGeneratorHelper
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/backend/templates/layout.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <?php include_http_metas() ?>
+    <?php include_metas() ?>
+    <?php include_title() ?>
+    <link rel="shortcut icon" href="/favicon.ico" />
+  </head>
+  <body>
+    <?php echo $sf_content ?>
+  </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/app.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,2 @@
+# default values
+#all:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/cache.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,4 @@
+default:
+  enabled:     off
+  with_layout: false
+  lifetime:    86400
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/factories.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,125 @@
+prod:
+  logger:
+    class:   sfNoLogger
+    param:
+      level:   err
+      loggers: ~
+
+cli:
+  controller:
+    class: sfConsoleController
+  request:
+    class: sfConsoleRequest
+  response:
+    class: sfConsoleResponse
+
+test:
+  storage:
+    class: sfSessionTestStorage
+    param:
+      session_path: %SF_TEST_CACHE_DIR%/sessions
+
+  response:
+    class: sfWebResponse
+    param:
+      send_http_headers: false
+
+#all:
+#  controller:
+#    class: sfFrontWebController
+#
+#  request:
+#    class: sfWebRequest
+#    param:
+#      logging:           %SF_LOGGING_ENABLED%
+#      path_info_array:   SERVER
+#      path_info_key:     PATH_INFO
+#      relative_url_root: ~
+#      formats:
+#        txt:  text/plain
+#        js:   [application/javascript, application/x-javascript, text/javascript]
+#        css:  text/css
+#        json: [application/json, application/x-json]
+#        xml:  [text/xml, application/xml, application/x-xml]
+#        rdf:  application/rdf+xml
+#        atom: application/atom+xml
+#
+#  response:
+#    class: sfWebResponse
+#    param:
+#      logging:           %SF_LOGGING_ENABLED%
+#      charset:           %SF_CHARSET%
+#      send_http_headers: true
+#
+#  user:
+#    class: myUser
+#    param:
+#      timeout:         1800
+#      logging:         %SF_LOGGING_ENABLED%
+#      use_flash:       true
+#      default_culture: %SF_DEFAULT_CULTURE%
+#
+#  storage:
+#    class: sfSessionStorage
+#    param:
+#      session_name: symfony
+#
+#  view_cache:
+#    class: sfFileCache
+#    param:
+#      automatic_cleaning_factor: 0
+#      cache_dir:                 %SF_TEMPLATE_CACHE_DIR%
+#      lifetime:                  86400
+#      prefix:                    %SF_APP_DIR%/template
+#
+#  i18n:
+#    class: sfI18N
+#    param:
+#      source:               XLIFF
+#      debug:                off
+#      untranslated_prefix:  "[T]"
+#      untranslated_suffix:  "[/T]"
+#      cache:
+#        class: sfFileCache
+#        param:
+#          automatic_cleaning_factor: 0
+#          cache_dir:                 %SF_I18N_CACHE_DIR%
+#          lifetime:                  31556926
+#          prefix:                    %SF_APP_DIR%/i18n
+#
+#  routing:
+#    class: sfPatternRouting
+#    param:
+#      load_configuration:               true
+#      suffix:                           ''
+#      default_module:                   default
+#      default_action:                   index
+#      debug:                            %SF_DEBUG%
+#      logging:                          %SF_LOGGING_ENABLED%
+#      generate_shortest_url:            false
+#      extra_parameters_as_query_string: false
+#      cache:
+#        class: sfFileCache
+#        param:
+#          automatic_cleaning_factor: 0
+#          cache_dir:                 %SF_CONFIG_CACHE_DIR%/routing
+#          lifetime:                  31556926
+#          prefix:                    %SF_APP_DIR%/routing
+#
+#  logger:
+#    class: sfAggregateLogger
+#    param:
+#      level: debug
+#      loggers:
+#        sf_web_debug:
+#          class: sfWebDebugLogger
+#          param:
+#            level: debug
+#            condition:       %SF_WEB_DEBUG%
+#            xdebug_logging:  true
+#            web_debug_class: sfWebDebug
+#        sf_file_debug:
+#          class: sfFileLogger
+#          param:
+#            level: debug
+#            file: %SF_LOG_DIR%/%SF_APP%_%SF_ENVIRONMENT%.log
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/filters.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,8 @@
+rendering: ~
+security:  ~
+
+# insert your own filters here
+
+cache:     ~
+common:    ~
+execution: ~
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/frontendConfiguration.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,8 @@
+<?php
+
+class frontendConfiguration extends sfApplicationConfiguration
+{
+  public function configure()
+  {
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/routing.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+# default rules
+homepage:
+  url:   /
+  param: { module: default, action: index }
+
+default_symfony:
+  url:   /symfony/:action/*
+  param: { module: default }
+
+default_index:
+  url:   /:module
+  param: { action: index }
+
+default:
+  url:   /:module/:action/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/security.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,2 @@
+default:
+  is_secure: off
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/settings.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,93 @@
+prod:
+  .settings:
+    no_script_name:         off
+    logging_enabled:        off
+
+dev:
+  .settings:
+    error_reporting:        <?php echo (E_ALL | E_STRICT)."\n" ?>
+    web_debug:              on
+    cache:                  off
+    no_script_name:         off
+    etag:                   off
+
+test:
+  .settings:
+    error_reporting:        <?php echo ((E_ALL | E_STRICT) ^ E_NOTICE)."\n" ?>
+    cache:                  off
+    web_debug:              off
+    no_script_name:         off
+    etag:                   off
+
+all:
+  .settings:
+    # Form security secret (CSRF protection)
+    csrf_secret:       false     # Unique secret to enable CSRF protection or false to disable
+
+    # Output escaping settings
+    escaping_strategy:      false            # Determines how variables are made available to templates. Accepted values: on, off.
+    escaping_method:        ESC_SPECIALCHARS # Function or helper used for escaping. Accepted values: ESC_RAW, ESC_ENTITIES, ESC_JS, ESC_JS_NO_ENTITIES, and ESC_SPECIALCHARS.
+
+#all:
+#  .actions:
+#    error_404_module:       default   # To be called when a 404 error is raised
+#    error_404_action:       error404  # Or when the requested URL doesn't match any route
+#
+#    login_module:           default   # To be called when a non-authenticated user
+#    login_action:           login     # Tries to access a secure page
+#
+#    secure_module:          default   # To be called when a user doesn't have
+#    secure_action:          secure    # The credentials required for an action
+#
+#    module_disabled_module: default   # To be called when a user requests 
+#    module_disabled_action: disabled  # A module disabled in the module.yml
+#
+#  .settings:
+#    # Optional features. Deactivating unused features boots performance a bit.
+#    use_database:           on        # Enable database manager. Set to off if you don't use a database.
+#    i18n:                   off       # Enable interface translation. Set to off if your application should not be translated.
+#    check_symfony_version:  off       # Enable check of symfony version for every request. Set to on to have symfony clear the cache automatically when the framework is upgraded. Set to off if you always clear the cache after an upgrade.
+#    compressed:             off       # Enable PHP response compression. Set to on to compress the outgoing HTML via the PHP handler.
+#    check_lock:             off       # Enable the application lock system triggered by the clear-cache and disable tasks. Set to on to have all requests to disabled applications redirected to the $sf_symfony_lib_dir/exception/data/unavailable.php page.
+#
+#    # Routing settings
+#    no_script_name:         off       # Enable the front controller name in generated URLs
+#
+#    # Validation settings, used for error generation by the Validation helper
+#    validation_error_prefix:    ' &darr;&nbsp;'
+#    validation_error_suffix:    ' &nbsp;&darr;'
+#    validation_error_class:     form_error
+#    validation_error_id_prefix: error_for_
+#
+#    # Cache settings
+#    cache:                  off       # Enable the template cache
+#    etag:                   on        # Enable etag handling
+#
+#    # Logging and debugging settings
+#    web_debug:              off       # Enable the web debug toolbar
+#    error_reporting:        <?php echo (E_PARSE | E_COMPILE_ERROR | E_ERROR | E_CORE_ERROR | E_USER_ERROR)."\n" ?> # Determines which events are logged.
+#
+#    # Assets paths
+#    rich_text_js_dir:       js/tiny_mce
+#    admin_web_dir:          /sf/sf_admin
+#    web_debug_web_dir:      /sf/sf_web_debug
+#    calendar_web_dir:       /sf/calendar
+#
+#    # Helpers included in all templates by default
+#    standard_helpers:       [Partial, Cache, Form]
+#
+#    # Activated modules from plugins or from the symfony core
+#    enabled_modules:        [default]
+#
+#    # Charset used for the response
+#    charset:                utf-8
+#
+#    # Miscellaneous
+#    strip_comments:         on         # Remove comments in core framework classes as defined in the core_compile.yml
+#    max_forwards:           5
+#
+#    # Logging
+#    logging_enabled:        on
+#
+#    # i18n
+#    default_culture:        en        # Default user culture
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/config/view.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,17 @@
+default:
+  http_metas:
+    content-type: text/html
+
+  metas:
+    #title:        symfony project
+    #description:  symfony project
+    #keywords:     symfony, project
+    #language:     en
+    robots:       index, follow
+
+  stylesheets:    [main]
+
+  javascripts:    []
+
+  has_layout:     on
+  layout:         layout
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/lib/myUser.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,5 @@
+<?php
+
+class myUser extends sfBasicSecurityUser
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/modules/articles/actions/actions.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * articles actions.
+ *
+ * @package    symfony12
+ * @subpackage articles
+ * @author     Your name here
+ * @version    SVN: $Id: actions.class.php 8507 2008-04-17 17:32:20Z fabien $
+ */
+class articlesActions extends sfActions
+{
+  public function executeIndex()
+  {
+    $this->articleList = $this->getArticleTable()->findAll();
+  }
+
+  public function executeCreate()
+  {
+    $this->form = new ArticleForm();
+
+    $this->setTemplate('edit');
+  }
+
+  public function executeEdit($request)
+  {
+    $this->form = $this->getArticleForm($request->getParameter('id'));
+  }
+
+  public function executeUpdate($request)
+  {
+    $this->forward404Unless($request->isMethod('post'));
+
+    $this->form = $this->getArticleForm($request->getParameter('id'));
+
+    $this->form->bind($request->getParameter('article'));
+    if ($this->form->isValid())
+    {
+      $article = $this->form->save();
+
+      $this->redirect('articles/edit?id='.$article->get('id'));
+    }
+
+    $this->setTemplate('edit');
+  }
+
+  public function executeDelete($request)
+  {
+    $this->forward404Unless($article = $this->getArticleById($request->getParameter('id')));
+
+    $article->delete();
+
+    $this->redirect('articles/index');
+  }
+  
+  private function getArticleTable()
+  {
+    return Doctrine::getTable('Article');
+  }
+  
+  private function getArticleById($id)
+  {
+    return $this->getArticleTable()->find($id);
+  }
+  
+  private function getArticleForm($id)
+  {
+    $article = $this->getArticleById($id);
+    
+    if ($article instanceof Article)
+    {
+      return new ArticleForm($article);
+    }
+    else
+    {
+      return new ArticleForm();
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/modules/articles/templates/editSuccess.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,58 @@
+<?php $article = $form->getObject() ?>
+<h1><?php echo $form->isNew() ? 'New' : 'Edit' ?> Articles</h1>
+
+<form action="<?php echo url_for('articles/update'.(!$form->isNew() ? '?id='.$article->get('id') : '')) ?>" method="post" <?php $form->isMultipart() and print 'enctype="multipart/form-data" ' ?>>
+  <table>
+    <tfoot>
+      <tr>
+        <td colspan="2">
+          &nbsp;<a href="<?php echo url_for('articles/index') ?>">Cancel</a>
+          <?php if (!$form->isNew()): ?>
+            &nbsp;<?php echo link_to('Delete', 'articles/delete?id='.$article->get('id'), array('post' => true, 'confirm' => 'Are you sure?')) ?>
+          <?php endif; ?>
+          <input type="submit" value="Save" />
+        </td>
+      </tr>
+    </tfoot>
+    <tbody>
+      <?php echo $form->renderGlobalErrors() ?>
+      <tr>
+        <th><label for="article_author_id">Author id</label></th>
+        <td>
+          <?php echo $form['author_id']->renderError() ?>
+          <?php echo $form['author_id'] ?>
+        </td>
+      </tr>
+      <tr>
+        <th><label for="article_created_at">Created at</label></th>
+        <td>
+          <?php echo $form['created_at']->renderError() ?>
+          <?php echo $form['created_at'] ?>
+        </td>
+      </tr>
+      <tr>
+        <th><label for="article_updated_at">Updated at</label></th>
+        <td>
+          <?php echo $form['updated_at']->renderError() ?>
+          <?php echo $form['updated_at'] ?>
+        </td>
+      </tr>
+      <tr>
+        <th><label for="article_en">En</label></th>
+        <td>
+          <?php echo $form['en']->renderError() ?>
+          <?php echo $form['en'] ?>
+        </td>
+      </tr>
+      <tr>
+        <th><label for="article_fr">Fr</label></th>
+        <td>
+          <?php echo $form['fr']->renderError() ?>
+          <?php echo $form['fr'] ?>
+
+        <?php echo $form['id'] ?>
+        </td>
+      </tr>
+    </tbody>
+  </table>
+</form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/modules/articles/templates/indexSuccess.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,24 @@
+<h1>Articles List</h1>
+
+<table>
+  <thead>
+    <tr>
+      <th>Id</th>
+      <th>Author</th>
+      <th>Created at</th>
+      <th>Updated at</th>
+    </tr>
+  </thead>
+  <tbody>
+    <?php foreach ($articleList as $article): ?>
+    <tr>
+      <td><a href="<?php echo url_for('articles/edit?id='.$article->get('id')) ?>"><?php echo $article->getid() ?></a></td>
+      <td><?php echo $article->getAuthor() ?></td>
+      <td><?php echo $article->getcreated_at() ?></td>
+      <td><?php echo $article->getupdated_at() ?></td>
+    </tr>
+    <?php endforeach; ?>
+  </tbody>
+</table>
+
+<a href="<?php echo url_for('articles/create') ?>">Create</a>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/apps/frontend/templates/layout.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+
+<?php include_http_metas() ?>
+<?php include_metas() ?>
+
+<?php include_title() ?>
+
+<link rel="shortcut icon" href="/favicon.ico" />
+
+</head>
+<body>
+
+<?php echo $sf_content ?>
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/config/ProjectConfiguration.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,48 @@
+<?php
+
+require_once dirname(__FILE__).'/../../../../../../autoload/sfCoreAutoload.class.php';
+sfCoreAutoload::register();
+
+class ProjectConfiguration extends sfProjectConfiguration
+{
+  public function setup()
+  {
+    $this->enableAllPluginsExcept(array('sfPropelPlugin', 'sfCompat10Plugin'));
+  }
+
+  public function initializeDoctrine()
+  {
+    chdir(sfConfig::get('sf_root_dir'));
+
+    $task = new sfDoctrineBuildAllTask($this->dispatcher, new sfFormatter());
+    $task->run(array(), array('--env=test'));
+  }
+
+  public function loadFixtures($fixtures)
+  {
+    $path = sfConfig::get('sf_data_dir') . '/' . $fixtures;
+    if ( ! file_exists($path)) {
+      throw new sfException('Invalid data fixtures file');
+    }
+    chdir(sfConfig::get('sf_root_dir'));
+    $task = new sfDoctrineLoadDataTask($this->dispatcher, new sfFormatter());
+    $task->run(array(), array('--env=test', '--dir=' . $path));
+  }
+
+  public function configureDoctrine(Doctrine_Manager $manager)
+  {
+    $manager->setAttribute('validate', true);
+
+    $options = array('baseClassName' => 'myDoctrineRecord');
+    sfConfig::set('doctrine_model_builder_options', $options);
+  }
+
+  public function configureDoctrineConnection(Doctrine_Connection $connection)
+  {
+  }
+
+  public function configureDoctrineConnectionDoctrine2(Doctrine_Connection $connection)
+  {
+    $connection->setAttribute('validate', false);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/config/databases.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+all:
+  doctrine1:
+    class:          sfDoctrineDatabase
+    param:
+      dsn:          sqlite:///%SF_DATA_DIR%/database1.sqlite
+  doctrine2:
+    class:          sfDoctrineDatabase
+    param:
+      dsn:          sqlite:///%SF_DATA_DIR%/database2.sqlite
+  doctrine3:
+    class:          sfDoctrineDatabase
+    param:
+      dsn:          sqlite:///%SF_DATA_DIR%/database3.sqlite
+      attributes:
+        export:     tables
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/config/doctrine/schema.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,126 @@
+---
+Article:
+  actAs:
+    I18n:
+      fields: [title, body, test_column]
+      actAs:
+        Sluggable:
+          fields: [title]
+          uniqueBy: [lang, title]
+    Timestampable:
+  columns:
+    author_id: integer
+    is_on_homepage: boolean
+    title: string(255)
+    body: string(255)
+    test_column: string(255)
+  relations:
+    Author:
+      foreignAlias: Articles
+
+CamelCase:
+  columns:
+    article_id: integer
+    testCamelCase: string(255)
+  relations:
+    Article:
+      foreignAlias: camelCase
+
+Author:
+  columns:
+    name: string(255)
+
+Subscription:
+  connection: doctrine2
+  columns:
+    name: string(255)
+    status:
+      type: enum
+      values: [New, Active, Pending, Expired]
+
+User:
+  columns:
+    username:
+      type: string(255)
+      unique: true
+    password: string(255)
+    test: string(255)
+  relations:
+    Groups:
+      class: Group
+      refClass: UserGroup
+      foreignAlias: Users
+    Permissions:
+      class: Permission
+      refClass: UserPermission
+      foreignAlias: Users
+
+UniqueTest:
+  columns:
+    unique_test1:
+      type: string(255)
+      unique: true
+    unique_test2: string(255)
+    unique_test3: string(255)
+    unique_test4: string(255)
+  indexes:
+    unique_test:
+      fields: [unique_test1, unique_test2]
+      type: unique
+    unique_test2:
+      fields:
+        unique_test4:
+          sorting: ASC
+          length: 10
+      type: unique
+
+
+Profile:
+  columns:
+    user_id: integer
+    first_name: string(255)
+    last_name: string(255)
+  relations:
+    User:
+      foreignType: one
+
+Group:
+  tableName: groups
+  columns:
+    name: string(255)
+  relations:
+    Permissions:
+      class: Permission
+      refClass: GroupPermission
+      foreignAlias: Groups
+
+Permission:
+  columns:
+    name: string(255)
+
+UserGroup:
+  columns:
+    user_id:
+      type: integer
+      primary: true
+    group_id:
+      type: integer
+      primary: true
+
+UserPermission:
+  columns:
+    user_id:
+      type: integer
+      primary: true
+    permission_id:
+      type: integer
+      primary: true
+
+GroupPermission:
+  columns:
+    group_id:
+      type: integer
+      primary: true
+    permission_id:
+      type: integer
+      primary: true
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/config/propel.ini	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,49 @@
+propel.targetPackage       = lib.model
+propel.packageObjectModel  = true
+propel.project             = symfony12
+propel.database            = mysql
+propel.database.createUrl  = mysql://root@localhost/
+propel.database.url        = mysql://root@localhost/symfony12
+
+propel.addGenericAccessors = true
+propel.addGenericMutators  = true
+propel.addTimeStamp        = false
+
+propel.schema.validate     = false
+
+; directories
+propel.home                    = .
+propel.output.dir              = /Users/jwage/Sites/symfony12
+propel.schema.dir              = ${propel.output.dir}/config
+propel.conf.dir                = ${propel.output.dir}/config
+propel.phpconf.dir             = ${propel.output.dir}/config
+propel.sql.dir                 = ${propel.output.dir}/data/sql
+propel.runtime.conf.file       = runtime-conf.xml
+propel.php.dir                 = ${propel.output.dir}
+propel.default.schema.basename = schema
+propel.datadump.mapper.from    = *schema.xml
+propel.datadump.mapper.to      = *data.xml
+
+; builder settings
+propel.builder.peer.class              = plugins.sfPropelPlugin.lib.propel.builder.SfPeerBuilder
+propel.builder.object.class            = plugins.sfPropelPlugin.lib.propel.builder.SfObjectBuilder
+propel.builder.objectstub.class        = plugins.sfPropelPlugin.lib.propel.builder.SfExtensionObjectBuilder
+propel.builder.peerstub.class          = plugins.sfPropelPlugin.lib.propel.builder.SfExtensionPeerBuilder
+propel.builder.objectmultiextend.class = plugins.sfPropelPlugin.lib.propel.builder.SfMultiExtendObjectBuilder
+propel.builder.mapbuilder.class        = plugins.sfPropelPlugin.lib.propel.builder.SfMapBuilderBuilder
+propel.builder.interface.class         = propel.engine.builder.om.php5.PHP5InterfaceBuilder
+propel.builder.node.class              = propel.engine.builder.om.php5.PHP5NodeBuilder
+propel.builder.nodepeer.class          = propel.engine.builder.om.php5.PHP5NodePeerBuilder
+propel.builder.nodestub.class          = propel.engine.builder.om.php5.PHP5ExtensionNodeBuilder
+propel.builder.nodepeerstub.class      = propel.engine.builder.om.php5.PHP5ExtensionNodePeerBuilder
+
+propel.builder.addIncludes = false
+propel.builder.addComments = false
+
+propel.builder.addBehaviors = false
+
+propel.mysql.tableType = InnoDB
+
+propel.defaultTimeStampFormat = Y-m-d H:i:s
+propel.defaultTimeFormat = H:i:s
+propel.defaultDateFormat = Y-m-d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/config/properties.ini	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,2 @@
+[symfony]
+  name=symfony12
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/config/rsync_exclude.txt	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,5 @@
+.svn
+/web/uploads/*
+/cache/*
+/log/*
+/web/*_dev.php
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/data/fixtures/fixtures.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,59 @@
+---
+Article:
+  Article_1:
+    Author: jwage
+    is_on_homepage: false
+    Translation:
+      en:
+        title: English Title
+        body: English Body
+      fr:
+        title: French Title
+        body: French Body
+  Article_2:
+    Author: fabpot
+    Translation:
+      en:
+        title: English Title 2
+        body: English Body 2
+      fr:
+        title: French Title 2
+        body: French Body 2
+
+Author:
+  jwage:
+    name: Jonathan H. Wage
+  fabpot:
+    name: Fabien POTENCIER
+
+Subscription:
+  Subscription_1:
+    name: Subscription #1
+
+User:
+  User_1:
+    username: jwage
+    password: changeme
+    Profile:
+      first_name: Jonathan
+      last_name: Wage
+    Groups: [Group_1]
+    Permissions: [Permission_3]
+
+Group:
+  Group_1:
+    name: Group 1
+    Permissions: [Permission_1, Permission_2]
+  Group_2:
+    name: Group 2
+    Permissions: [Permission_3, Permission_4]
+
+Permission:
+  Permission_1:
+    name: Permission 1
+  Permission_2:
+    name: Permission 2
+  Permission_3:
+    name: Permission 3
+  Permission_4:
+    name: Permission 4
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/data/sql/schema.sql	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,14 @@
+CREATE TABLE article (id INTEGER PRIMARY KEY AUTOINCREMENT, author_id INTEGER, is_on_homepage INTEGER, created_at DATETIME, updated_at DATETIME);
+CREATE TABLE author (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(255));
+CREATE TABLE camel_case (id INTEGER PRIMARY KEY AUTOINCREMENT, article_id INTEGER, testcamelcase VARCHAR(255));
+CREATE TABLE groups (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(255));
+CREATE TABLE group_permission (group_id INTEGER, permission_id INTEGER, PRIMARY KEY(group_id, permission_id));
+CREATE TABLE permission (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(255));
+CREATE TABLE profile (id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER, first_name VARCHAR(255), last_name VARCHAR(255));
+CREATE TABLE unique_test (id INTEGER PRIMARY KEY AUTOINCREMENT, unique_test1 VARCHAR(255) UNIQUE, unique_test2 VARCHAR(255), unique_test3 VARCHAR(255), unique_test4 VARCHAR(255));
+CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR(255) UNIQUE, password VARCHAR(255), test VARCHAR(255));
+CREATE TABLE user_group (user_id INTEGER, group_id INTEGER, PRIMARY KEY(user_id, group_id));
+CREATE TABLE user_permission (user_id INTEGER, permission_id INTEGER, PRIMARY KEY(user_id, permission_id));
+CREATE UNIQUE INDEX unique_test_idx ON unique_test (unique_test1, unique_test2);
+CREATE UNIQUE INDEX unique_test2_idx ON unique_test (unique_test4 ASC);
+CREATE TABLE subscription (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(255), status VARCHAR(255));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/ArticleFormFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Article filter form.
+ *
+ * @package    filters
+ * @subpackage Article *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class ArticleFormFilter extends BaseArticleFormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/ArticleTranslationFormFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * ArticleTranslation filter form.
+ *
+ * @package    filters
+ * @subpackage ArticleTranslation *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class ArticleTranslationFormFilter extends BaseArticleTranslationFormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/AuthorFormFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Author filter form.
+ *
+ * @package    filters
+ * @subpackage Author *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class AuthorFormFilter extends BaseAuthorFormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/BaseFormFilterDoctrine.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Project filter form base class.
+ *
+ * @package    filters
+ *
+ * @version    SVN: $Id: sfDoctrineFormFilterBaseTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+abstract class BaseFormFilterDoctrine extends sfFormFilterDoctrine
+{
+  public function setup()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/GroupFormFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Group filter form.
+ *
+ * @package    filters
+ * @subpackage Group *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class GroupFormFilter extends BaseGroupFormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/GroupPermissionFormFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * GroupPermission filter form.
+ *
+ * @package    filters
+ * @subpackage GroupPermission *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class GroupPermissionFormFilter extends BaseGroupPermissionFormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/PermissionFormFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Permission filter form.
+ *
+ * @package    filters
+ * @subpackage Permission *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class PermissionFormFilter extends BasePermissionFormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/ProfileFormFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Profile filter form.
+ *
+ * @package    filters
+ * @subpackage Profile *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class ProfileFormFilter extends BaseProfileFormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/SubscriptionFormFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Subscription filter form.
+ *
+ * @package    filters
+ * @subpackage Subscription *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class SubscriptionFormFilter extends BaseSubscriptionFormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/UniqueTestFormFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * UniqueTest filter form.
+ *
+ * @package    filters
+ * @subpackage UniqueTest *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class UniqueTestFormFilter extends BaseUniqueTestFormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/UserFormFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * User filter form.
+ *
+ * @package    filters
+ * @subpackage User *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class UserFormFilter extends BaseUserFormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/UserGroupFormFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * UserGroup filter form.
+ *
+ * @package    filters
+ * @subpackage UserGroup *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class UserGroupFormFilter extends BaseUserGroupFormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/UserPermissionFormFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * UserPermission filter form.
+ *
+ * @package    filters
+ * @subpackage UserPermission *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class UserPermissionFormFilter extends BaseUserPermissionFormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/filter/doctrine/myDoctrineRecordFormFilter.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * myDoctrineRecord filter form.
+ *
+ * @package    filters
+ * @subpackage myDoctrineRecord *
+ * @version    SVN: $Id: sfDoctrineFormFilterTemplate.php 11675 2008-09-19 15:21:38Z fabien $
+ */
+class myDoctrineRecordFormFilter extends BasemyDoctrineRecordFormFilter
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/ArticleForm.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * Article form.
+ *
+ * @package    form
+ * @subpackage Article
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class ArticleForm extends BaseArticleForm
+{
+  public function configure()
+  {
+    $this->embedI18n(array('en', 'fr'));
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/ArticleTranslationForm.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * ArticleTranslation form.
+ *
+ * @package    form
+ * @subpackage ArticleTranslation
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class ArticleTranslationForm extends BaseArticleTranslationForm
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/AuthorForm.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Author form.
+ *
+ * @package    form
+ * @subpackage Author
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class AuthorForm extends BaseAuthorForm
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/BaseFormDoctrine.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * Project form base class.
+ *
+ * @package    form
+ * @version    SVN: $Id: sfDoctrineFormBaseTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+abstract class BaseFormDoctrine extends sfFormDoctrine
+{
+  public function setup()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/GroupForm.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Group form.
+ *
+ * @package    form
+ * @subpackage Group
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class GroupForm extends BaseGroupForm
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/GroupPermissionForm.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * GroupPermission form.
+ *
+ * @package    form
+ * @subpackage GroupPermission
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class GroupPermissionForm extends BaseGroupPermissionForm
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/PermissionForm.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Permission form.
+ *
+ * @package    form
+ * @subpackage Permission
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class PermissionForm extends BasePermissionForm
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/ProfileForm.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Profile form.
+ *
+ * @package    form
+ * @subpackage Profile
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class ProfileForm extends BaseProfileForm
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/SubscriptionForm.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Subscription form.
+ *
+ * @package    form
+ * @subpackage Subscription
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class SubscriptionForm extends BaseSubscriptionForm
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/UniqueTestForm.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * UniqueTest form.
+ *
+ * @package    form
+ * @subpackage UniqueTest
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class UniqueTestForm extends BaseUniqueTestForm
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/UserForm.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * User form.
+ *
+ * @package    form
+ * @subpackage User
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class UserForm extends BaseUserForm
+{
+  public function configure()
+  {
+    $profileForm = new ProfileForm($this->object->getProfile());
+    unset($profileForm['id'], $profileForm['user_id']);
+
+    $this->embedForm('Profile', $profileForm);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/UserGroupForm.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * UserGroup form.
+ *
+ * @package    form
+ * @subpackage UserGroup
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class UserGroupForm extends BaseUserGroupForm
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/UserPermissionForm.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * UserPermission form.
+ *
+ * @package    form
+ * @subpackage UserPermission
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class UserPermissionForm extends BaseUserPermissionForm
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/form/doctrine/myDoctrineRecordForm.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * myDoctrineRecord form.
+ *
+ * @package    form
+ * @subpackage myDoctrineRecord
+ * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
+ */
+class myDoctrineRecordForm extends BasemyDoctrineRecordForm
+{
+  public function configure()
+  {
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/Article.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class Article extends BaseArticle
+{
+  public function getTestingNonColumn()
+  {
+    return 'test-' . $this->slug;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/ArticleTable.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,49 @@
+<?php
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class ArticleTable extends Doctrine_Table
+{
+  public function retrieveArticle1(Doctrine_Query $query)
+  {
+    return $query->execute();
+  }
+
+  public function retrieveArticle2(array $parameters)
+  {
+    $query = $this->createQuery('a');
+    return $query->execute();
+  }
+
+  public function retrieveArticle3(array $parameters)
+  {
+    $query = $this->createQuery('a');
+    return $query->execute();
+  }
+
+  public function retrieveArticle4(array $parameters)
+  {
+    $query = $this->createQuery('a');
+    return $query->fetchOne();
+  }
+
+  public function routeTest9(array $parameters)
+  {
+    return Doctrine_Query::create()
+      ->from('Article a')
+      ->where('a.id = ?', $parameters['id'])
+      ->limit(1)
+      ->execute();
+  }
+
+  public function routeTest10(Doctrine_Query $q)
+  {
+    $q->orWhere($q->getRootAlias() . '.is_on_homepage = ?', 0);
+    return $q->fetchOne();
+  }
+
+  public function testAdminGenTableMethod(Doctrine_Query $q)
+  {
+    return $q;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/Author.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class Author extends BaseAuthor
+{
+  public function setName($name)
+  {
+    if ( ! $this->exists())
+    {
+      $author = Doctrine::getTable('Author')->findOneByName(trim($name));
+      if ($author)
+      {
+        $this->assignIdentifier($author->identifier());
+      } else {
+        return $this->_set('name', $name);
+      }
+    } else {
+      return $this->_set('name', $name);
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/AuthorTable.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,18 @@
+<?php
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class AuthorTable extends Doctrine_Table
+{
+  public function testTableMethod()
+  {
+    return $this->createQuery('a')
+      ->where('a.id > 0');
+  }
+
+  public function testTableMethod2(Doctrine_Query $q)
+  {
+    $q->addWhere('a.id > 0');
+    return $q;
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/Group.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class Group extends BaseGroup
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/GroupPermission.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class GroupPermission extends BaseGroupPermission
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/GroupPermissionTable.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,8 @@
+<?php
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class GroupPermissionTable extends Doctrine_Table
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/GroupTable.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,8 @@
+<?php
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class GroupTable extends Doctrine_Table
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/Permission.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class Permission extends BasePermission
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/PermissionTable.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,8 @@
+<?php
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class PermissionTable extends Doctrine_Table
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/Profile.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class Profile extends BaseProfile
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/ProfileTable.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,8 @@
+<?php
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class ProfileTable extends Doctrine_Table
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/Subscription.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class Subscription extends BaseSubscription
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/SubscriptionTable.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,8 @@
+<?php
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class SubscriptionTable extends Doctrine_Table
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UniqueTest.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class UniqueTest extends BaseUniqueTest
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UniqueTestTable.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,8 @@
+<?php
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class UniqueTestTable extends Doctrine_Table
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/User.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class User extends BaseUser
+{
+  public function setPassword($password)
+  {
+    return $this->_set('password', md5($password));
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UserGroup.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class UserGroup extends BaseUserGroup
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UserGroupTable.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,8 @@
+<?php
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class UserGroupTable extends Doctrine_Table
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UserPermission.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class UserPermission extends BaseUserPermission
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UserPermissionTable.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,8 @@
+<?php
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class UserPermissionTable extends Doctrine_Table
+{
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/model/doctrine/UserTable.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,30 @@
+<?php
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class UserTable extends Doctrine_Table
+{
+  public function widgetChoiceTableMethod1()
+  {
+    return $this->createQuery('u');
+  }
+
+  public function widgetChoiceTableMethod2()
+  {
+    return $this->widgetChoiceTableMethod1()
+      ->execute();
+  }
+
+  public function widgetChoiceTableMethod3()
+  {
+    return $this->widgetChoiceTableMethod1()
+      ->fetchOne();
+  }
+
+  public function widgetChoiceTableMethod4()
+  {
+    return $this->widgetChoiceTableMethod1()
+      ->where('1 = 0')
+      ->execute();
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/lib/myDoctrineRecord.class.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,5 @@
+<?php
+abstract class myDoctrineRecord extends sfDoctrineRecord
+{
+  
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/symfony	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+#!/usr/bin/env php
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ * 
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+chdir(dirname(__FILE__));
+require_once(dirname(__FILE__).'/config/ProjectConfiguration.class.php');
+$configuration = new ProjectConfiguration();
+include($configuration->getSymfonyLibDir().'/command/cli.php');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/test/bootstrap/functional.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+// guess current application
+if (!isset($app))
+{
+  $traces = debug_backtrace();
+  $caller = $traces[0];
+
+  $dirPieces = explode(DIRECTORY_SEPARATOR, dirname($caller['file']));
+  $app = array_pop($dirPieces);
+}
+
+require_once dirname(__FILE__).'/../../config/ProjectConfiguration.class.php';
+$configuration = ProjectConfiguration::getApplicationConfiguration($app, 'test', isset($debug) ? $debug : true);
+sfContext::createInstance($configuration);
+
+// remove all cache
+sfToolkit::clearDirectory(sfConfig::get('sf_app_cache_dir'));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/test/bootstrap/unit.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,15 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ * 
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+$_test_dir = realpath(dirname(__FILE__).'/..');
+
+require_once(dirname(__FILE__).'/../../config/ProjectConfiguration.class.php');
+$configuration = new ProjectConfiguration(realpath($_test_dir.'/..'));
+include($configuration->getSymfonyLibDir().'/vendor/lime/lime.php');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/.htaccess	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,22 @@
+Options +FollowSymLinks +ExecCGI
+
+<IfModule mod_rewrite.c>
+  RewriteEngine On
+
+  # uncomment the following line, if you are having trouble
+  # getting no_script_name to work
+  #RewriteBase /
+
+  # we skip all files with .something
+  #RewriteCond %{REQUEST_URI} \..+$
+  #RewriteCond %{REQUEST_URI} !\.html$
+  #RewriteRule .* - [L]
+
+  # we check if the .html version is here (caching)
+  RewriteRule ^$ index.html [QSA]
+  RewriteRule ^([^.]+)$ $1.html [QSA]
+  RewriteCond %{REQUEST_FILENAME} !-f
+
+  # no, so we redirect to our front web controller
+  RewriteRule ^(.*)$ index.php [QSA,L]
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/backend.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,7 @@
+<?php
+
+
+require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');
+
+$configuration = ProjectConfiguration::getApplicationConfiguration('backend', 'prod', false);
+sfContext::createInstance($configuration)->dispatch();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/backend_dev.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,13 @@
+<?php
+
+// this check prevents access to debug front controllers that are deployed by accident to production servers.
+// feel free to remove this, extend it or make something more sophisticated.
+if (!in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1')))
+{
+  die('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
+}
+
+require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');
+
+$configuration = ProjectConfiguration::getApplicationConfiguration('backend', 'dev', true);
+sfContext::createInstance($configuration)->dispatch();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/css/main.css	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,16 @@
+table {
+  border-collapse: collapse;
+  border: 1px solid #ccc;
+}
+
+table tr th {
+  padding: 6px;
+  background: #ccc;
+  color: #000;
+  border-collapse: collapse;
+}
+
+table tr td {
+  padding: 4px;
+  border: 1px solid #ccc;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/frontend.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,6 @@
+<?php
+
+require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');
+
+$configuration = ProjectConfiguration::getApplicationConfiguration('frontend', 'prod', false);
+sfContext::createInstance($configuration)->dispatch();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/frontend_dev.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,12 @@
+<?php
+// this check prevents access to debug front conrollers that are deployed by accident to production servers.
+// feel free to remove this, extend it or make something more sophisticated.
+if (!in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1')))
+{
+  die('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
+}
+
+require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');
+
+$configuration = ProjectConfiguration::getApplicationConfiguration('frontend', 'dev', true);
+sfContext::createInstance($configuration)->dispatch();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/index.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,6 @@
+<?php
+
+require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');
+
+$configuration = ProjectConfiguration::getApplicationConfiguration('frontend', 'prod', false);
+sfContext::createInstance($configuration)->dispatch();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/fixtures/web/robots.txt	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,2 @@
+#User-agent: *
+#Disallow:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/functional/sfDoctrineRecordTest.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ * 
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+$app = 'frontend';
+$fixtures = 'fixtures/fixtures.yml';
+require_once(dirname(__FILE__).'/../bootstrap/functional.php');
+
+$t = new lime_test(18, new lime_output_color());
+
+$authors = Doctrine::getTable('Author')->findAll();
+$t->is(count($authors), 2);
+
+$author = new Author();
+
+// Accessor overriding
+$author->setName('Jonathan H. Wage');
+$author->save();
+
+// Propel style accessors with column name
+$t->is($author->getName(), $author->name);
+
+// Propel style accessors for id
+// Also check new author was not created since Jonathan H. Wage exists in fixtures/fixtures.yml
+$t->is($author->getId(), 1);
+
+// Make sure we still have only 2 authors
+$authors = Doctrine::getTable('Author')->findAll();
+$t->is(count($authors), 2);
+
+$article = new Article();
+$article->title = 'test';
+
+// __toString() automatic column finder
+$t->is((string) $article, 'test');
+
+// Different style accessors
+$t->is($article->getAuthor_id(), $article->author_id);
+$t->is($article->getAuthorId(), $article->author_id);
+$t->is($article->getauthorId(), $article->author_id);
+$t->is($article->getAuthorID(), $article->author_id);
+$t->is($article->getauthor_id(), $article->author_id);
+
+// Camel case columns
+$camelCase = new CamelCase();
+$camelCase->testCamelCase = 'camel';
+$camelCase->setTestCamelCase('camel');
+
+$t->is($camelCase->getTestCamelCase(), 'camel');
+$t->is($camelCase->gettestCamelCase(), 'camel');
+$t->is($camelCase->gettestcamelcase(), 'camel');
+$t->is($camelCase->gettest_camel_case(), 'camel');
+$t->is($camelCase->getTest_camel_case(), 'camel');
+
+// Propel style accessors work with relationships
+$article->setAuthor($author);
+$t->is($article->Author, $author);
+$t->is($article->getAuthor(), $author);
+
+// Camel case with relationships
+$t->is($article->getCamelCase()->getTable()->getOption('name'), 'CamelCase');
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/unit/sfDoctrineColumnTest.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+include(dirname(__FILE__).'/../bootstrap/unit.php');
+
+$t = new lime_test(23, new lime_output_color());
+
+$conn = Doctrine_Manager::connection(new Doctrine_Adapter_Mock('mysql'));
+
+class Test extends sfDoctrineRecord
+{
+  public function setTableDefinition()
+  {
+    $this->hasColumn('name', 'string', 255, array('notblank' => true));
+    $this->hasColumn('test as TEST', 'string', 255);
+    $this->hasColumn('email', 'string', 255, array('email' => true, 'notnull' => true));
+  }
+
+  public function setUp()
+  {
+    $this->hasMany('TestRelation as TestRelations', array('local' => 'id', 'foreign' => 'test_id'));
+  }
+}
+
+class TestRelation extends sfDoctrineRecord
+{
+  public function setTableDefinition()
+  {
+    $this->hasColumn('name', 'string', 255);
+    $this->hasColumn('test_id', 'integer');
+  }
+
+  public function setUp()
+  {
+    $this->hasOne('Test', array('local' => 'test_id', 'foreign' => 'id'));
+  }
+}
+
+$column = new sfDoctrineColumn('name', Doctrine::getTable('Test'));
+$t->is($column->getName(), 'name');
+$t->is($column->getFieldName(), 'name');
+$t->is($column->getPhpName(), 'name');
+$t->is($column->isNotNull(), true);
+
+$column = new sfDoctrineColumn('test', Doctrine::getTable('Test'));
+$t->is($column->getName(), 'test');
+$t->is($column->getFieldName(), 'TEST');
+$t->is($column->getPhpName(), 'TEST');
+
+$t->is($column->getDoctrineType(), 'string');
+$t->is($column->getType(), 'VARCHAR');
+$t->is($column->getLength(), 255);
+$t->is($column->getSize(), 255);
+$t->is($column->hasDefinitionKey('length'), true);
+$t->is($column->getDefinitionKey('type'), 'string');
+$t->is($column->isNotNull(), false);
+
+// Is not null and has definition key
+$column = new sfDoctrineColumn('email', Doctrine::getTable('Test'));
+$t->is($column->isNotNull(), true);
+$t->is($column->hasDefinitionKey('email'), true);
+$t->is($column->getDefinitionKey('email'), true);
+
+// Is primary key
+$column = new sfDoctrineColumn('id', Doctrine::getTable('Test'));
+$t->is($column->isPrimaryKey(), true);
+
+// Relation/foreign key functions
+$column = new sfDoctrineColumn('test_id', Doctrine::getTable('TestRelation'));
+$t->is($column->isForeignKey(), true);
+$t->is($column->getForeignClassName(), 'Test');
+$t->is($column->getForeignTable()->getOption('name'), 'Test');
+$t->is($column->getTable()->getOption('name'), 'TestRelation');
+
+// Array access
+$t->is($column['type'], 'integer');
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/test/unit/sfDoctrineDatabaseTest.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+include(dirname(__FILE__).'/../bootstrap/unit.php');
+
+$t = new lime_test(1, new lime_output_color());
+
+$parameters = array(
+    'name'       => 'doctrine',
+    'dsn'        => 'sqlite::memory');
+
+class ProjectConfiguration extends sfProjectConfiguration
+{
+}
+
+$configuration = new ProjectConfiguration(dirname(__FILE__).'/../../lib', new sfEventDispatcher());
+
+$p = new sfDoctrineDatabase($parameters);
+$t->is($p->getDoctrineConnection()->getName(), 'doctrine', 'initialize() - creates a valid doctrine configuration from parameters');
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/web/css/default.css	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,269 @@
+#sf_admin_container a
+{
+  color: #464646;
+  text-decoration: none;
+}
+
+#sf_admin_container a:hover
+{
+  color: #000;
+  text-decoration: underline;
+}
+
+#sf_admin_container h1
+{
+  margin: 0;
+  padding: 0;
+  margin-bottom: 20px;
+}
+
+#sf_admin_container th
+{
+  background-color: #e7eef6;
+  white-space: nowrap;
+}
+
+#sf_admin_container td, #sf_admin_container th
+{
+  border: 0;
+  border-bottom: 1px solid #ddd;
+  border-top: 1px solid #ddd;
+  text-align: left;
+  vertical-align: top;
+}
+
+#sf_admin_container tr
+{
+  background-color: #fff;
+  border-left: 1px solid #ddd;
+  border-right: 1px solid #ddd;
+}
+
+#sf_admin_container ul.error_list
+{
+  margin: 0;
+  margin-bottom: 7px;
+  color: #d33;
+  border: none;
+  background-color: #f33;
+}
+
+#sf_admin_container ul.error_list li
+{
+  padding: 4px;
+  padding-left: 25px;
+  list-style: none;
+  color: #fff;
+  background: url(../images/error.png) no-repeat 4px 4px;
+}
+
+#sf_admin_container tr:hover
+{
+  background-color: #ffe;
+}
+
+#sf_admin_container input, #sf_admin_container textarea
+{
+  width: auto;
+}
+
+#sf_admin_container .radio_list, #sf_admin_container .checkbox_list
+{
+  margin: 0;
+}
+
+#sf_admin_container .radio_list li, #sf_admin_container .checkbox_list li
+{
+  list-style: none;
+  display: inline;
+}
+
+#sf_admin_container .double_list_select, #sf_admin_container .double_list_select-selected
+{
+  width: 12em;
+}
+
+#sf_admin_container .double_list_label
+{
+  font-weight: bold;
+}
+
+#sf_admin_container tfoot td
+{
+  margin: 0;
+  list-style: none;
+  text-align: right;
+}
+
+#sf_admin_container thead img, #sf_admin_container tfoot img
+{
+  vertical-align: middle;
+}
+
+#sf_admin_bar
+{
+  float: right;
+  margin-left: 20px;
+}
+
+.sf_admin_pagination
+{
+  float: right;
+}
+
+#sf_admin_container ul.sf_admin_td_actions
+{
+  margin: 0;
+  padding: 0;
+  list-style-type: none;
+}
+
+#sf_admin_container ul.sf_admin_td_actions li
+{
+  list-style-type: none;
+  display: inline;
+  margin-right: 10px;
+  font-size: 90%;
+}
+
+#sf_admin_container ul.sf_admin_actions
+{
+  margin: 10px 0;
+  list-style-type: none;
+}
+
+#sf_admin_container ul.sf_admin_actions li
+{
+  list-style-type: none;
+  display: inline;
+  margin-right: 10px;
+}
+
+#sf_admin_container ul li a
+{
+  padding-left: 20px;
+  background: url(../images/default.png) no-repeat 0 0;
+}
+
+#sf_admin_container ul li.sf_admin_action_new a
+{
+  background: url(../images/new.png) no-repeat 0 0;
+}
+
+#sf_admin_container ul li.sf_admin_action_delete a
+{
+  background: url(../images/delete.png) no-repeat 0 0;
+}
+
+#sf_admin_container ul li.sf_admin_action_list a
+{
+  background: url(../images/list.png) no-repeat 0 0;
+}
+
+#sf_admin_container ul li.sf_admin_action_edit a
+{
+  background: url(../images/edit.png) no-repeat 0 0;
+}
+
+#sf_admin_container .notice
+{
+  margin: 4px 0;
+  padding: 4px 4px 4px 30px;
+  background: url(../images/tick.png) no-repeat 10px 4px;
+  border-top: 1px solid #ddd;
+  border-bottom: 1px solid #ddd;
+  background-color: #ffc;
+}
+
+#sf_admin_container .error
+{
+  margin: 4px 0;
+  padding: 4px 4px 4px 30px;
+  background: url(../images/error.png) no-repeat 10px 4px;
+  border-top: 1px solid #ddd;
+  border-bottom: 1px solid #ddd;
+  background-color: #f33;
+  color: #fff;
+}
+
+#sf_admin_container .sf_admin_row_0 td
+{
+}
+
+#sf_admin_container .sf_admin_row_1 td
+{
+/*  background-color: #eee;*/
+}
+
+#sf_admin_container fieldset h2
+{
+  padding: 3px;
+  color: #333;
+  background-color: #ccf;
+  font-size: 11px;
+}
+
+#sf_admin_container fieldset
+{
+  margin-bottom: 3px;
+  border: 1px solid #ddd;
+  border-bottom: 0px;
+  background-color: #fff;
+}
+
+#sf_admin_container fieldset.collapsed * { display:none; }
+#sf_admin_container fieldset.collapsed h2, #sf_admin_container fieldset.collapsed { display:block !important; }
+#sf_admin_container fieldset.collapsed .collapse-toggle { display: inline !important; }
+#sf_admin_container fieldset.collapse h2 a.collapse-toggle { color:#ffc; }
+#sf_admin_container fieldset.collapse h2 a.collapse-toggle:hover { text-decoration:underline; }
+
+#sf_admin_container label
+{
+  display: block;
+  padding: 0 1em 3px 0;
+  float: left;
+  text-align: left;
+  width: 8em;
+  color: #666;
+  font-weight: normal !important;
+}
+
+#sf_admin_container ul label, #sf_admin_container td label
+{
+  display: inline;
+  float: none !important;
+}
+
+#sf_admin_container .sf_admin_form_row
+{
+  clear: both;
+  padding: 10px;
+  border-bottom: 1px solid #ddd;
+}
+
+#sf_admin_container .sf_admin_form_row .content
+{
+  padding-left: 9em;
+}
+
+#sf_admin_container .help
+{
+  padding-left: 9em;
+  color: #aaa;
+}
+
+#sf_admin_container td .help
+{
+  padding-left: 0;
+}
+
+#sf_admin_container .errors input, #sf_admin_container .errors select
+{
+  border: 1px solid #f22;
+}
+
+#sf_admin_container .sf_admin_list .sf_admin_boolean
+{
+  text-align: center;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfDoctrinePlugin/web/css/global.css	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+/* http://yui.yahooapis.com/2.6.0/build/reset/reset-min.css
+Copyright (c) 2008, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.6.0
+*/
+html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}del,ins{text-decoration:none;}
+
+/* http://yui.yahooapis.com/2.6.0/build/fonts/fonts-min.css
+Copyright (c) 2008, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.6.0
+*/
+body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}
+
+/* http://yui.yahooapis.com/2.6.0/build/base/base-min.css
+Copyright (c) 2008, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.6.0
+*/
+h1{font-size:138.5%;}h2{font-size:123.1%;}h3{font-size:108%;}h1,h2,h3{margin:1em 0;}h1,h2,h3,h4,h5,h6,strong{font-weight:bold;}abbr,acronym{border-bottom:1px dotted #000;cursor:help;} em{font-style:italic;}blockquote,ul,ol,dl{margin:1em;}ol,ul,dl{margin-left:2em;}ol li{list-style:decimal outside;}ul li{list-style:disc outside;}dl dd{margin-left:1em;}th,td{border:1px solid #000;padding:.5em;}th{font-weight:bold;text-align:center;}caption{margin-bottom:.5em;text-align:center;}p,fieldset,table,pre{margin-bottom:1em;}input[type=text],input[type=password],textarea{width:12.25em;*width:11.9em;}
+
+html
+{
+  background-color: #eee;
+}
+
+body
+{
+  padding: 30px;
+  text-align: left;
+}
Binary file web/thdProject/web/sfDoctrinePlugin/web/images/asc.png has changed
Binary file web/thdProject/web/sfDoctrinePlugin/web/images/default.png has changed
Binary file web/thdProject/web/sfDoctrinePlugin/web/images/delete.png has changed
Binary file web/thdProject/web/sfDoctrinePlugin/web/images/desc.png has changed
Binary file web/thdProject/web/sfDoctrinePlugin/web/images/edit.png has changed
Binary file web/thdProject/web/sfDoctrinePlugin/web/images/error.png has changed
Binary file web/thdProject/web/sfDoctrinePlugin/web/images/first.png has changed
Binary file web/thdProject/web/sfDoctrinePlugin/web/images/last.png has changed
Binary file web/thdProject/web/sfDoctrinePlugin/web/images/list.png has changed
Binary file web/thdProject/web/sfDoctrinePlugin/web/images/new.png has changed
Binary file web/thdProject/web/sfDoctrinePlugin/web/images/next.png has changed
Binary file web/thdProject/web/sfDoctrinePlugin/web/images/previous.png has changed
Binary file web/thdProject/web/sfDoctrinePlugin/web/images/tick.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/LICENSE	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,7 @@
+Copyright (c) 2004-2006 Fabien Potencier
+
+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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/LICENSE.prototype	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,16 @@
+Copyright (c) 2005-2008 Sam Stephenson
+
+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 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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/LICENSE.script.aculo.us	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,20 @@
+Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+
+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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/config/settings.yml	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,3 @@
+all:
+  .settings:
+    prototype_web_dir:      /sfProtoculousPlugin  #default 1.6.02 and 1.8 files. Can be changed to compressed files for production.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/lib/helper/JavascriptHelper.php	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,967 @@
+<?php
+
+require_once dirname(__FILE__).'/../../../../helper/JavascriptBaseHelper.php';
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ * (c) 2004 David Heinemeier Hansson
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * JavascriptHelper.
+ *
+ * @package    symfony
+ * @subpackage helper
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @author     John Christopher <john.christopher@symfony-project.com>
+ * @author     David Heinemeier Hansson
+ * @author     Fabian Lange <fabian.lange@symfony-project.com>
+ * @version    SVN: $Id: JavascriptHelper.php 19310 2009-06-16 12:41:07Z FabianLange $
+ */
+
+/*
+ * Provides a set of helpers to call remote methods using what has been labelled 
+ * AJAX[http://www.adaptivepath.com/publications/essays/archives/000385.php].
+ * This means that you can call actions in your controllers without reloading the page,
+ * but still update certain parts of it using injections into the DOM.
+ * The common use case is having a form that adds a new element to a list without reloading the page.
+ *
+ * To be able to use the JavaScript helpers, you must include the Prototype JavaScript Framework
+ * and for some functions script.aculo.us (which both come with symfony) on your pages.
+ * Choose one of these options:
+ *
+ * * Use <tt><?php echo javascript_include_tag :defaults ?></tt> in the HEAD section of your page (recommended):
+ *   The function will return references to the JavaScript files created by the +rails+ command in your
+ *   <tt>public/javascripts</tt> directory. Using it is recommended as the browser can then cache the libraries
+ *   instead of fetching all the functions anew on every request.
+ * * Use <tt><?php echo javascript_include_tag 'prototype' ?></tt>: As above, but will only include the Prototype core library,
+ *   which means you are able to use all basic AJAX functionality. For the script.aculo.us-based JavaScript helpers,
+ *   like visual effects, autocompletion, drag and drop and so on, you should use the method described above.
+ * * Use <tt><?php echo define_javascript_functions ?></tt>: this will copy all the JavaScript support functions within a single
+ *   script block.
+ *
+ * For documentation on +javascript_include_tag+ see ActionView::Helpers::AssetTagHelper.
+ *
+ * If you're the visual type, there's an AJAX movie[http://www.rubyonrails.com/media/video/rails-ajax.mov] demonstrating
+ * the use of form_remote_tag.
+ */
+
+  function get_callbacks()
+  {
+    static $callbacks;
+    if (!$callbacks)
+    {
+      $callbacks = array_merge(array(
+        'uninitialized', 'loading', 'loaded', 'interactive', 'complete', 'failure', 'success'
+        ), range(100, 599));
+    }
+
+    return $callbacks;
+  }
+
+  function get_ajax_options()
+  {
+    static $ajax_options;
+    if (!$ajax_options)
+    {
+      $ajax_options = array_merge(array(
+        'before', 'after', 'condition', 'url', 'asynchronous', 'method',
+        'insertion', 'position', 'form', 'with', 'update', 'script'
+        ), get_callbacks());
+    }
+
+    return $ajax_options;
+  }
+
+  /**
+   * Returns an html button to a remote action defined by 'url' (using the
+   * 'url_for()' format) that's called in the background using XMLHttpRequest.
+   *
+   * See link_to_remote() for details.
+   *
+   */
+  function button_to_remote($name, $options = array(), $html_options = array())
+  {
+    return button_to_function($name, remote_function($options), $html_options);
+  }
+
+  /**
+   * Returns a link to a remote action defined by 'url'
+   * (using the 'url_for()' format) that's called in the background using
+   * XMLHttpRequest. The result of that request can then be inserted into a
+   * DOM object whose id can be specified with 'update'.
+   * Usually, the result would be a partial prepared by the controller with
+   * either 'render_partial()'.
+   *
+   * Examples:
+   *  <?php echo link_to_remote('Delete this post'), array(
+   *    'update' => 'posts',
+   *    'url'    => 'destroy?id='.$post.id,
+   *  )) ?>
+   *  <?php echo link_to_remote(image_tag('refresh'), array(
+   *    'update' => 'emails',
+   *    'url'    => '@list_emails',
+   *  )) ?>
+   *
+   * You can also specify a hash for 'update' to allow for
+   * easy redirection of output to an other DOM element if a server-side error occurs:
+   *
+   * Example:
+   *  <?php echo link_to_remote('Delete this post', array(
+   *      'update' => array('success' => 'posts', 'failure' => 'error'),
+   *      'url'    => 'destroy?id='.$post.id,
+   *  )) ?>
+   *
+   * Optionally, you can use the 'position' parameter to influence
+   * how the target DOM element is updated. It must be one of
+   * 'before', 'top', 'bottom', or 'after'.
+   *
+   * By default, these remote requests are processed asynchronous during
+   * which various JavaScript callbacks can be triggered (for progress indicators and
+   * the likes). All callbacks get access to the 'request' object,
+   * which holds the underlying XMLHttpRequest.
+   *
+   * To access the server response, use 'request.responseText', to
+   * find out the HTTP status, use 'request.status'.
+   *
+   * Example:
+   *  <?php echo link_to_remote($word, array(
+   *    'url'      => '@undo?n='.$word_counter,
+   *    'complete' => 'undoRequestCompleted(request)'
+   *  )) ?>
+   *
+   * The callbacks that may be specified are (in order):
+   *
+   * 'loading'                 Called when the remote document is being
+   *                           loaded with data by the browser.
+   * 'loaded'                  Called when the browser has finished loading
+   *                           the remote document.
+   * 'interactive'             Called when the user can interact with the
+   *                           remote document, even though it has not
+   *                           finished loading.
+   * 'success'                 Called when the XMLHttpRequest is completed,
+   *                           and the HTTP status code is in the 2XX range.
+   * 'failure'                 Called when the XMLHttpRequest is completed,
+   *                           and the HTTP status code is not in the 2XX
+   *                           range.
+   * 'complete'                Called when the XMLHttpRequest is complete
+   *                           (fires after success/failure if they are present).,
+   *
+   * You can further refine 'success' and 'failure' by adding additional
+   * callbacks for specific status codes:
+   *
+   * Example:
+   *  <?php echo link_to_remote($word, array(
+   *       'url'     => '@rule',
+   *       '404'     => "alert('Not found...? Wrong URL...?')",
+   *       'failure' => "alert('HTTP Error ' + request.status + '!')",
+   *  )) ?>
+   *
+   * A status code callback overrides the success/failure handlers if present.
+   *
+   * If you for some reason or another need synchronous processing (that'll
+   * block the browser while the request is happening), you can specify
+   * 'type' => 'synchronous'.
+   *
+   * You can customize further browser side call logic by passing
+   * in JavaScript code snippets via some optional parameters. In
+   * their order of use these are:
+   *
+   * 'confirm'             Adds confirmation dialog.
+   * 'condition'           Perform remote request conditionally
+   *                       by this expression. Use this to
+   *                       describe browser-side conditions when
+   *                       request should not be initiated.
+   * 'before'              Called before request is initiated.
+   * 'after'               Called immediately after request was
+   *                       initiated and before 'loading'.
+   * 'submit'              Specifies the DOM element ID that's used
+   *                       as the parent of the form elements. By
+   *                       default this is the current form, but
+   *                       it could just as well be the ID of a
+   *                       table row or any other DOM element.
+   */
+  function link_to_remote($name, $options = array(), $html_options = array())
+  {
+    return link_to_function($name, remote_function($options), $html_options);
+  }
+
+  /**
+   * Periodically calls the specified url ('url') every 'frequency' seconds (default is 10).
+   * Usually used to update a specified div ('update') with the results of the remote call.
+   * The options for specifying the target with 'url' and defining callbacks is the same as 'link_to_remote()'.
+   */
+  function periodically_call_remote($options = array())
+  {
+    $frequency = isset($options['frequency']) ? $options['frequency'] : 10; // every ten seconds by default
+    $code = 'new PeriodicalExecuter(function() {'.remote_function($options).'}, '.$frequency.')';
+
+    return javascript_tag($code);
+  }
+
+  /**
+   * Returns a form tag that will submit using XMLHttpRequest in the background instead of the regular
+   * reloading POST arrangement. Even though it's using JavaScript to serialize the form elements, the form submission
+   * will work just like a regular submission as viewed by the receiving side (all elements available in 'params').
+   * The options for specifying the target with 'url' and defining callbacks are the same as 'link_to_remote()'.
+   *
+   * A "fall-through" target for browsers that don't do JavaScript can be specified
+   * with the 'action'/'method' options on '$options_html'
+   *
+   * Example:
+   *  <?php echo form_remote_tag(array(
+   *    'url'      => '@tag_add',
+   *    'update'   => 'question_tags',
+   *    'loading'  => "Element.show('indicator'); \$('tag').value = ''",
+   *    'complete' => "Element.hide('indicator');".visual_effect('highlight', 'question_tags'),
+   *  )) ?>
+   *
+   * The hash passed as a second argument is equivalent to the options (2nd) argument in the form_tag() helper.
+   *
+   * By default the fall-through action is the same as the one specified in the 'url'
+   * (and the default method is 'post').
+   */
+  function form_remote_tag($options = array(), $options_html = array())
+  {
+    $options = _parse_attributes($options);
+    $options_html = _parse_attributes($options_html);
+
+    $options['form'] = true;
+
+    $options_html['onsubmit'] = remote_function($options).' return false;';
+    $options_html['action'] = isset($options_html['action']) ? $options_html['action'] : url_for($options['url']);
+    $options_html['method'] = isset($options_html['method']) ? $options_html['method'] : 'post';
+
+    return tag('form', $options_html, true);
+  }
+
+  /**
+   *  Returns a button input tag that will submit form using XMLHttpRequest in the background instead of regular
+   *  reloading POST arrangement. The '$options' argument is the same as in 'form_remote_tag()'.
+   */
+  function submit_to_remote($name, $value, $options = array(), $options_html = array())
+  {
+    $options = _parse_attributes($options);
+    $options_html = _parse_attributes($options_html);
+
+    if (!isset($options['with']))
+    {
+      $options['with'] = 'Form.serialize(this.form)';
+    }
+
+    $options_html['type'] = 'button';
+    $options_html['onclick'] = remote_function($options).' return false;';
+    $options_html['name'] = $name;
+    $options_html['value'] = $value;
+
+    return tag('input', $options_html, false);
+  }
+
+  /**
+   *  Returns a image submit tag that will submit form using XMLHttpRequest in the background instead of regular
+   *  reloading POST arrangement. The '$options' argument is the same as in 'form_remote_tag()'.
+   */
+  function submit_image_to_remote($name, $source, $options = array(), $options_html = array())
+  {
+    $options = _parse_attributes($options);
+    $options_html = _parse_attributes($options_html);
+ 
+    if (!isset($options['with']))
+    {
+      $options['with'] = 'Form.serialize(this.form)';
+    }
+
+    $options_html['type'] = 'image';
+    $options_html['onclick'] = remote_function($options).' return false;';
+    $options_html['name'] = $name;
+    $options_html['src'] = image_path($source);
+
+    if (!isset($options_html['alt'])) 
+    {
+      $path_pos = strrpos($source, '/');
+      $dot_pos = strrpos($source, '.');
+      $begin = $path_pos ? $path_pos + 1 : 0;
+      $nb_str = ($dot_pos ? $dot_pos : strlen($source)) - $begin;
+      $options_html['alt'] = ucfirst(substr($source, $begin, $nb_str));
+    }
+ 
+    return tag('input', $options_html, false);
+  }
+
+  /**
+   * Returns a Javascript function (or expression) that will update a DOM element '$element_id'
+   * according to the '$options' passed.
+   *
+   * Possible '$options' are:
+   * 'content'            The content to use for updating. Can be left out if using block, see example.
+   * 'action'             Valid options are 'update' (assumed by default), 'empty', 'remove'
+   * 'position'           If the 'action' is 'update', you can optionally specify one of the following positions:
+   *                      'before', 'top', 'bottom', 'after'.
+   *
+   * Example:
+   *   <?php echo javascript_tag(
+   *      update_element_function('products', array(
+   *            'position' => 'bottom',
+   *            'content'  => "<p>New product!</p>",
+   *      ))
+   *   ) ?>
+   *
+   *
+   * This method can also be used in combination with remote method call
+   * where the result is evaluated afterwards to cause multiple updates on a page.
+   *
+   * Example:
+   *
+   *  # Calling view
+   *  <?php echo form_remote_tag(array(
+   *      'url'      => '@buy',
+   *      'complete' => evaluate_remote_response()
+   *  )) ?>
+   *  all the inputs here...
+   *
+   *  # Target action
+   *  public function executeBuy()
+   *  {
+   *     $this->product = ProductPeer::retrieveByPk(1);
+   *  }
+   *
+   *  # Returning view
+   *  <?php echo update_element_function('cart', array(
+   *      'action'   => 'update',
+   *      'position' => 'bottom',
+   *      'content'  => '<p>New Product: '.$product->getName().'</p>',
+   *  )) ?>
+   */
+  function update_element_function($element_id, $options = array())
+  {
+    sfContext::getInstance()->getResponse()->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype');
+
+    $content = escape_javascript(isset($options['content']) ? $options['content'] : '');
+
+    $value = isset($options['action']) ? $options['action'] : 'update';
+    switch ($value)
+    {
+      case 'update':
+        if (isset($options['position']) && $options['position'])
+        {
+          $javascript_function = "\$('$element_id').insert({'".$options['position']."':'$content'})";
+        }
+        else
+        {
+          $javascript_function = "\$('$element_id').update('$content')";
+        }
+        break;
+
+      case 'empty':
+        $javascript_function = "\$('$element_id').innerHTML = ''";
+        break;
+
+      case 'remove':
+        $javascript_function = "\$('$element_id').remove()";
+        break;
+
+      default:
+        throw new sfException('Invalid action, choose one of update, remove, empty.');
+    }
+
+    $javascript_function .= ";\n";
+
+    return (isset($options['binding']) ? $javascript_function.$options['binding'] : $javascript_function);
+  }
+
+  /**
+   * Returns 'eval(request.responseText)', which is the Javascript function that
+   * 'form_remote_tag()' can call in 'complete' to evaluate a multiple update return document
+   * using 'update_element_function()' calls.
+   */
+  function evaluate_remote_response()
+  {
+    return 'eval(request.responseText)';
+  }
+
+  /**
+   * Returns the javascript needed for a remote function.
+   * Takes the same arguments as 'link_to_remote()'.
+   *
+   * Example:
+   *   <select id="options" onchange="<?php echo remote_function(array('update' => 'options', 'url' => '@update_options')) ?>">
+   *     <option value="0">Hello</option>
+   *     <option value="1">World</option>
+   *   </select>
+   */
+  function remote_function($options)
+  {
+    sfContext::getInstance()->getResponse()->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype');
+
+    $javascript_options = _options_for_ajax($options);
+
+    $update = '';
+    if (isset($options['update']) && is_array($options['update']))
+    {
+      $update = array();
+      if (isset($options['update']['success']))
+      {
+        $update[] = "success:'".$options['update']['success']."'";
+      }
+      if (isset($options['update']['failure']))
+      {
+        $update[] = "failure:'".$options['update']['failure']."'";
+      }
+      $update = '{'.join(',', $update).'}';
+    }
+    else if (isset($options['update']))
+    {
+      $update .= "'".$options['update']."'";
+    }
+
+    $function = !$update ?  "new Ajax.Request(" : "new Ajax.Updater($update, ";
+
+    $function .= '\''.url_for($options['url']).'\'';
+    $function .= ', '.$javascript_options.')';
+
+    if (isset($options['before']))
+    {
+      $function = $options['before'].'; '.$function;
+    }
+    if (isset($options['after']))
+    {
+      $function = $function.'; '.$options['after'];
+    }
+    if (isset($options['condition']))
+    {
+      $function = 'if ('.$options['condition'].') { '.$function.'; }';
+    }
+    if (isset($options['confirm']))
+    {
+      $function = "if (window.confirm('".escape_javascript($options['confirm'])."')) { $function; }";
+      if (isset($options['cancel']))
+      {
+        $function = $function.' else { '.$options['cancel'].' }';
+      }
+    }
+
+    return $function.';';
+  }
+
+  /**
+   * Observes the field with the DOM ID specified by '$field_id' and makes
+   * an AJAX call when its contents have changed.
+   *
+   * Required '$options' are:
+   * 'url'                 'url_for()'-style options for the action to call
+   *                       when the field has changed.
+   *
+   * Additional options are:
+   * 'frequency'           The frequency (in seconds) at which changes to
+   *                       this field will be detected. Not setting this
+   *                       option at all or to a value equal to or less than
+   *                       zero will use event based observation instead of
+   *                       time based observation.
+   * 'update'              Specifies the DOM ID of the element whose
+   *                       innerHTML should be updated with the
+   *                       XMLHttpRequest response text.
+   * 'with'                A JavaScript expression specifying the
+   *                       parameters for the XMLHttpRequest. This defaults
+   *                       to 'value', which in the evaluated context
+   *                       refers to the new field value.
+   *
+   * Additionally, you may specify any of the options documented in
+   * link_to_remote().
+   */
+  function observe_field($field_id, $options = array())
+  {
+    sfContext::getInstance()->getResponse()->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype');
+
+    if (isset($options['frequency']) && $options['frequency'] > 0)
+    {
+      return _build_observer('Form.Element.Observer', $field_id, $options);
+    }
+    else
+    {
+      return _build_observer('Form.Element.EventObserver', $field_id, $options);
+    }
+  }
+
+  /**
+   * Like 'observe_field()', but operates on an entire form identified by the
+   * DOM ID '$form_id'. '$options' are the same as 'observe_field()', except
+   * the default value of the 'with' option evaluates to the
+   * serialized (request string) value of the form.
+   */
+  function observe_form($form_id, $options = array())
+  {
+    sfContext::getInstance()->getResponse()->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype');
+
+    if (isset($options['frequency']) && $options['frequency'] > 0)
+    {
+      return _build_observer('Form.Observer', $form_id, $options);
+    }
+    else
+    {
+      return _build_observer('Form.EventObserver', $form_id, $options);
+    }
+  }
+
+  /**
+   * Returns a JavaScript snippet to be used on the AJAX callbacks for starting
+   * visual effects.
+   *
+   * Example:
+   *  <?php echo link_to_remote('Reload', array(
+   *        'update'  => 'posts',
+   *        'url'     => '@reload',
+   *        'complete => visual_effect('highlight', 'posts', array('duration' => 0.5 )),
+   *  )) ?>
+   *
+   * If no '$element_id' is given, it assumes "element" which should be a local
+   * variable in the generated JavaScript execution context. This can be used
+   * for example with drop_receiving_element():
+   *
+   *  <?php echo drop_receving_element( ..., array(
+   *        ...
+   *        'loading' => visual_effect('fade'),
+   *  )) ?>
+   *
+   * This would fade the element that was dropped on the drop receiving element.
+   *
+   * You can change the behaviour with various options, see
+   * http://script.aculo.us for more documentation.
+   */
+  function visual_effect($name, $element_id = false, $js_options = array())
+  {
+    $response = sfContext::getInstance()->getResponse();
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/builder');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/effects');
+
+    $element = $element_id ? "'$element_id'" : 'element';
+
+    if (in_array($name, array('toggle_appear', 'toggle_blind', 'toggle_slide')))
+    {
+      return "new Effect.toggle($element, '".substr($name, 7)."', ".options_for_javascript($js_options).");";
+    }
+    else
+    {
+      return "new Effect.".sfInflector::camelize($name)."($element, ".options_for_javascript($js_options).");";
+    }
+  }
+
+  /**
+   * Makes the elements with the DOM ID specified by '$element_id' sortable
+   * by drag-and-drop and if an 'url' is specified make an AJAX call whenever
+   * the sort order has changed. By default, the action called gets the 
+   * serialized sortable element as parameters.
+   *
+   * Example:
+   *   <?php echo sortable_element($my_list, array(
+   *      'url' => '@order',
+   *   )) ?>
+   *
+   * In the example, the action gets a '$my_list' array parameter
+   * containing the values of the ids of elements the sortable consists
+   * of, in the current order.
+   *
+   * You can change the behaviour with various options, see
+   * http://script.aculo.us for more documentation.
+   */
+  function sortable_element($element_id, $options = array())
+  {
+    $response = sfContext::getInstance()->getResponse();
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/builder');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/effects');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/dragdrop');
+
+    if (!isset($options['with']))
+    {
+      $options['with'] = "Sortable.serialize('$element_id')";
+    }
+
+    if (!isset($options['onUpdate']) && isset($options['url']))
+    {
+      $options['onUpdate'] = "function(){".remote_function($options)."}";
+    }
+
+    foreach (get_ajax_options() as $key)
+    {
+      unset($options[$key]);
+    }
+
+    foreach (array('tag', 'overlap', 'constraint', 'handle') as $option)
+    {
+      if (isset($options[$option]))
+      {
+        $options[$option] = "'{$options[$option]}'";
+      }
+    }
+
+    if (isset($options['containment']))
+    {
+      $options['containment'] = array_or_string_for_javascript($options['containment']);
+    }
+
+    if (isset($options['hoverclass']))
+    {
+      $options['hoverclass'] = "'{$options['hoverclass']}'";
+    }
+
+    if (isset($options['only']))
+    {
+      $options['only'] = array_or_string_for_javascript($options['only']);
+    }
+
+    $scrollPosition = "";
+    if (isset($options['scroll']))
+    {
+      $options['scroll'] = array_or_string_for_javascript($options['scroll']);
+      $scrollPosition = "Position.includeScrollOffsets = true;";
+    }
+
+    return javascript_tag($scrollPosition."Sortable.create('$element_id', ".options_for_javascript($options).")");
+  }
+
+  /**
+   * Makes the element with the DOM ID specified by '$element_id' draggable.
+   *
+   * Example:
+   *   <?php echo draggable_element('my_image', array(
+   *      'revert' => true,
+   *   )) ?>
+   *
+   * You can change the behaviour with various options, see
+   * http://script.aculo.us for more documentation.
+   */
+  function draggable_element($element_id, $options = array())
+  {
+    $response = sfContext::getInstance()->getResponse();
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/builder');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/effects');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/dragdrop');
+
+    return javascript_tag("new Draggable('$element_id', ".options_for_javascript($options).")");
+  }
+
+  /**
+   * Makes the element with the DOM ID specified by '$element_id' receive
+   * dropped draggable elements (created by 'draggable_element()') and make an AJAX call.
+   * By default, the action called gets the DOM ID of the element as parameter.
+   *
+   * Example:
+   *   <?php drop_receiving_element('my_cart', array(
+   *      'url' => 'cart/add',
+   *   )) ?>
+   *
+   * You can change the behaviour with various options, see
+   * http://script.aculo.us for more documentation.
+   */
+  function drop_receiving_element($element_id, $options = array())
+  {
+    $response = sfContext::getInstance()->getResponse();
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/builder');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/effects');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/dragdrop');
+
+    if (!isset($options['with']))
+    {
+      $options['with'] = "'id=' + encodeURIComponent(element.id)";
+    }
+    if (!isset($options['onDrop']))
+    {
+      $options['onDrop'] = "function(element){".remote_function($options)."}";
+    }
+
+    foreach (get_ajax_options() as $key)
+    {
+      unset($options[$key]);
+    }
+
+    if (isset($options['accept']))
+    {
+      $options['accept'] = array_or_string_for_javascript($options['accept']);
+    }
+
+    if (isset($options['hoverclass']))
+    {
+      $options['hoverclass'] = "'{$options['hoverclass']}'";
+    }
+
+    return javascript_tag("Droppables.add('$element_id', ".options_for_javascript($options).")");
+  }
+
+  /**
+   * wrapper for script.aculo.us/prototype Ajax.Autocompleter.
+   * @param string name value of input field
+   * @param string default value for input field
+   * @param array input tag options. (size, autocomplete, etc...)
+   * @param array completion options. (use_style, etc...)
+   *
+   * @return string input field tag, div for completion results, and
+   *                 auto complete javascript tags
+   */
+  function input_auto_complete_tag($name, $value, $url, $tag_options = array(), $completion_options = array())
+  {
+    $context = sfContext::getInstance();
+
+    $tag_options = _convert_options($tag_options);
+
+    $response = $context->getResponse();
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/effects');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/controls');
+
+    $comp_options = _convert_options($completion_options);
+    if (isset($comp_options['use_style']) && $comp_options['use_style'] == true)
+    {
+      $response->addStylesheet(sfConfig::get('sf_prototype_web_dir').'/css/input_auto_complete_tag');
+    }
+
+    $tag_options['id'] = get_id_from_name(isset($tag_options['id']) ? $tag_options['id'] : $name);
+
+    $javascript  = tag('input', array_merge(array('type' => 'text', 'name' => $name, 'value' => $value), _convert_options($tag_options)));
+    $javascript .= content_tag('div', '' , array('id' => $tag_options['id'].'_auto_complete', 'class' => 'auto_complete'));
+    $javascript .= _auto_complete_field($tag_options['id'], $url, $comp_options);
+
+    return $javascript;
+  }
+
+  /**
+   * wrapper for script.aculo.us/prototype Ajax.InPlaceEditor.
+   * @param string name id of field that can be edited
+   * @param string url of module/action to be called when ok is clicked
+   * @param array editor tag options. (rows, cols, highlightcolor, highlightendcolor, etc...)
+   *
+   * @return string javascript to manipulate the id field to allow click and edit functionality
+   */
+  function input_in_place_editor_tag($name, $url, $editor_options = array())
+  {
+    $response = sfContext::getInstance()->getResponse();
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/effects');
+    $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/controls');
+
+    $editor_options = _convert_options($editor_options);
+    return _in_place_editor($name, $url, $editor_options);
+  }
+
+  /*
+   * Makes an HTML element specified by the DOM ID '$field_id' become an in-place
+   * editor of a property.
+   *
+   * A form is automatically created and displayed when the user clicks the element,
+   * something like this:
+   * <form id="myElement-in-place-edit-form" target="specified url">
+   *   <input name="value" text="The content of myElement"/>
+   *   <input type="submit" value="ok"/>
+   *   <a onclick="javascript to cancel the editing">cancel</a>
+   * </form>
+   *
+   * The form is serialized and sent to the server using an AJAX call, the action on
+   * the server should process the value and return the updated value in the body of
+   * the reponse. The element will automatically be updated with the changed value
+   * (as returned from the server).
+   *
+   * Required '$options' are:
+   * 'url'                 Specifies the url where the updated value should
+   *                       be sent after the user presses "ok".
+   *
+   * Some additional '$options' are:
+   * 'rows'                Number of rows (more than 1 will use a TEXTAREA)
+   * 'cancel_text'         The text on the cancel link. (default: "cancel")
+   * 'save_text'           The text on the save link. (default: "ok")
+   * 'external_control'    The id of an external control used to enter edit mode.
+   * 'options'             Pass through options to the AJAX call (see prototype's Ajax.Updater)
+   * 'with'                JavaScript snippet that should return what is to be sent
+   *                       in the AJAX call, 'form' is an implicit parameter
+   *
+   * for details see: http://mir.aculo.us/2007/7/17/in-place-editing-the-summer-2007-rewrite/
+   */
+    function _in_place_editor($field_id, $url, $options = array())
+    {
+      $javascript = "new Ajax.InPlaceEditor(";
+
+      $javascript .= "'$field_id', ";
+      $javascript .= array_or_string_for_javascript(url_for($url));
+
+      // translate symfony option names to InPlaceEditor options
+      if (isset($options['cancel_text']))
+      {
+        $options['cancelText'] = array_or_string_for_javascript($options['cancel_text']);
+        unset($options['cancel_text']);
+      }
+      if (isset($options['save_text']))
+      {
+        $options['okText'] = array_or_string_for_javascript($options['save_text']);
+        unset($options['save_text']);
+      }
+      if (isset($options['external_control']))
+      {
+        $options['externalControl'] = array_or_string_for_javascript($options['external_control']);
+        unset($options['external_control']);
+      }
+      if (isset($options['options']))
+      {
+        $options['ajaxOptions'] = $options['options'];
+        unset($options['options']);
+      }
+      if (isset($options['with']))
+      {
+        $options['callback'] = "function(form, value) { return ".$options['with']." }";
+        unset($options['with']);
+      }
+      if (isset($options['highlightcolor']))
+      {
+        $options['highlightColor'] = array_or_string_for_javascript($options['highlightcolor']);
+        unset($options['highlightcolor']);
+      }
+      if (isset($options['highlightendcolor']))
+      {
+        $options['highlightEndColor'] = array_or_string_for_javascript($options['highlightendcolor']);
+        unset($options['highlightendcolor']);
+      }
+      if (isset($options['loadTextURL']))
+      {
+        $options['loadTextURL'] =  array_or_string_for_javascript($options['loadTextURL']);
+      }
+
+      $javascript .= ', '.options_for_javascript($options);
+      $javascript .= ');';
+
+      return javascript_tag($javascript);
+    }
+
+  /**
+   * wrapper for script.aculo.us/prototype Ajax.Autocompleter.
+   * @param string id value of input field
+   * @param string url of module/action to execute for autocompletion
+   * @param array completion options
+   * @return string javascript tag for Ajax.Autocompleter
+   */
+  function _auto_complete_field($field_id, $url, $options = array())
+  {
+    $javascript = "new Ajax.Autocompleter(";
+
+    $javascript .= "'".get_id_from_name($field_id)."', ";
+    if (isset($options['update']))
+    {
+      $javascript .= "'".$options['update']."', ";
+    }
+    else
+    {
+      $javascript .= "'".get_id_from_name($field_id)."_auto_complete', ";
+    }
+
+    $javascript .= array_or_string_for_javascript(url_for($url));
+
+    $js_options = array();
+    if (isset($options['tokens']))
+    {
+      $js_options['tokens'] = array_or_string_for_javascript($options['tokens']);
+    }
+    if (isset ($options['with']))
+    {
+      $js_options['callback'] = "function(element, value) { return ".$options['with']."}";
+    }
+    if (isset($options['indicator']))
+    {
+      $js_options['indicator']  = array_or_string_for_javascript($options['indicator']);
+    }
+    if (isset($options['on_show']))
+    {
+      $js_options['onShow'] = $options['on_show'];
+    }
+    if (isset($options['on_hide']))
+    {
+      $js_options['onHide'] = $options['on_hide'];
+    }
+    if (isset($options['min_chars']))
+    {
+      $js_options['minChars'] = $options['min_chars'];
+    }
+    if (isset($options['frequency']))
+    {
+      $js_options['frequency'] = $options['frequency'];
+    }
+    if (isset($options['update_element']))
+    {
+      $js_options['updateElement'] = $options['update_element'];
+    }
+    if (isset($options['after_update_element']))
+    {
+      $js_options['afterUpdateElement'] = $options['after_update_element'];
+    }
+    if (isset($options['param_name'])) 
+    {
+      $js_options['paramName'] = "'".$options['param_name']."'";
+    }
+
+    $javascript .= ', '.options_for_javascript($js_options).');';
+
+    return javascript_tag($javascript);
+  }
+
+  function _options_for_ajax($options)
+  {
+    $js_options = _build_callbacks($options);
+
+    $js_options['asynchronous'] = (isset($options['type']) && ($options['type'] == 'synchronous')) ? false : true;
+    if (isset($options['method'])) $js_options['method'] = array_or_string_for_javascript($options['method']);
+    if (isset($options['position'])) $js_options['insertion'] = "Insertion.".sfInflector::camelize($options['position']);
+    $js_options['evalScripts'] = (!isset($options['script']) || $options['script'] == '0' || $options['script'] == false) ? false : true;
+
+    if (isset($options['form']))
+    {
+      $js_options['parameters'] = 'Form.serialize(this)';
+    }
+    else if (isset($options['submit']))
+    {
+      $js_options['parameters'] = "Form.serialize(document.getElementById('{$options['submit']}'))";
+    }
+    else if (isset($options['with']))
+    {
+      $js_options['parameters'] = $options['with'];
+    }
+
+    return options_for_javascript($js_options);
+  }
+
+  function _build_observer($klass, $name, $options = array())
+  {
+    if (!isset($options['with']) && isset($options['update']))
+    {
+      $options['with'] = 'value';
+    }
+
+    $callback = remote_function($options);
+
+    $javascript  = 'new '.$klass.'("'.$name.'", ';
+    if (isset($options['frequency']) && $options['frequency'] > 0)
+    {
+      $javascript .= $options['frequency'].", ";
+    }
+    $javascript .= "function(element, value) {";
+    $javascript .= $callback.'});';
+
+    return javascript_tag($javascript);
+  }
+
+  function _build_callbacks($options)
+  {
+    $callbacks = array();
+    foreach (get_callbacks() as $callback)
+    {
+      if (isset($options[$callback]))
+      {
+        $name = 'on'.ucfirst($callback);
+        $code = $options[$callback];
+        $callbacks[$name] = 'function(request, json){'.$code.'}';
+      }
+    }
+
+    return $callbacks;
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/web/css/input_auto_complete_tag.css	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,34 @@
+div.auto_complete
+{
+  width: 350px;
+  background: #fff;
+}
+
+div.auto_complete ul
+{
+  width: 100%;
+  margin: 0;
+  padding: 0;
+  list-style-type: none;
+  border: 1px solid #bbb;
+}
+
+div.auto_complete ul li
+{
+  margin: 0;
+  padding: 3px;
+  border-bottom: 1px solid #eee;
+  list-style-type: none;
+}
+
+div.auto_complete ul li.selected
+{
+  background-color: #ffb;
+}
+
+div.auto_complete ul strong.highlight
+{
+  margin: 0;
+  padding: 0;
+  color: #800;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/web/js/builder.js	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+  NODEMAP: {
+    AREA: 'map',
+    CAPTION: 'table',
+    COL: 'table',
+    COLGROUP: 'table',
+    LEGEND: 'fieldset',
+    OPTGROUP: 'select',
+    OPTION: 'select',
+    PARAM: 'object',
+    TBODY: 'table',
+    TD: 'table',
+    TFOOT: 'table',
+    TH: 'table',
+    THEAD: 'table',
+    TR: 'table'
+  },
+  // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+  //       due to a Firefox bug
+  node: function(elementName) {
+    elementName = elementName.toUpperCase();
+
+    // try innerHTML approach
+    var parentTag = this.NODEMAP[elementName] || 'div';
+    var parentElement = document.createElement(parentTag);
+    try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+      parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+    } catch(e) {}
+    var element = parentElement.firstChild || null;
+
+    // see if browser added wrapping tags
+    if(element && (element.tagName.toUpperCase() != elementName))
+      element = element.getElementsByTagName(elementName)[0];
+
+    // fallback to createElement approach
+    if(!element) element = document.createElement(elementName);
+
+    // abort if nothing could be created
+    if(!element) return;
+
+    // attributes (or text)
+    if(arguments[1])
+      if(this._isStringOrNumber(arguments[1]) ||
+        (arguments[1] instanceof Array) ||
+        arguments[1].tagName) {
+          this._children(element, arguments[1]);
+        } else {
+          var attrs = this._attributes(arguments[1]);
+          if(attrs.length) {
+            try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+              parentElement.innerHTML = "<" +elementName + " " +
+                attrs + "></" + elementName + ">";
+            } catch(e) {}
+            element = parentElement.firstChild || null;
+            // workaround firefox 1.0.X bug
+            if(!element) {
+              element = document.createElement(elementName);
+              for(attr in arguments[1])
+                element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+            }
+            if(element.tagName.toUpperCase() != elementName)
+              element = parentElement.getElementsByTagName(elementName)[0];
+          }
+        }
+
+    // text, or array of children
+    if(arguments[2])
+      this._children(element, arguments[2]);
+
+     return $(element);
+  },
+  _text: function(text) {
+     return document.createTextNode(text);
+  },
+
+  ATTR_MAP: {
+    'className': 'class',
+    'htmlFor': 'for'
+  },
+
+  _attributes: function(attributes) {
+    var attrs = [];
+    for(attribute in attributes)
+      attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+          '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+    return attrs.join(" ");
+  },
+  _children: function(element, children) {
+    if(children.tagName) {
+      element.appendChild(children);
+      return;
+    }
+    if(typeof children=='object') { // array can hold nodes and text
+      children.flatten().each( function(e) {
+        if(typeof e=='object')
+          element.appendChild(e);
+        else
+          if(Builder._isStringOrNumber(e))
+            element.appendChild(Builder._text(e));
+      });
+    } else
+      if(Builder._isStringOrNumber(children))
+        element.appendChild(Builder._text(children));
+  },
+  _isStringOrNumber: function(param) {
+    return(typeof param=='string' || typeof param=='number');
+  },
+  build: function(html) {
+    var element = this.node('div');
+    $(element).update(html.strip());
+    return element.down();
+  },
+  dump: function(scope) {
+    if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+    var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+      "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+      "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+      "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+      "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+      "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+    tags.each( function(tag){
+      scope[tag] = function() {
+        return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+      };
+    });
+  }
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/web/js/controls.js	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//           (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+//           (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+//  Richard Livsey
+//  Rahul Bhargava
+//  Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+  throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { };
+Autocompleter.Base = Class.create({
+  baseInitialize: function(element, update, options) {
+    element          = $(element);
+    this.element     = element;
+    this.update      = $(update);
+    this.hasFocus    = false;
+    this.changed     = false;
+    this.active      = false;
+    this.index       = 0;
+    this.entryCount  = 0;
+    this.oldElementValue = this.element.value;
+
+    if(this.setOptions)
+      this.setOptions(options);
+    else
+      this.options = options || { };
+
+    this.options.paramName    = this.options.paramName || this.element.name;
+    this.options.tokens       = this.options.tokens || [];
+    this.options.frequency    = this.options.frequency || 0.4;
+    this.options.minChars     = this.options.minChars || 1;
+    this.options.onShow       = this.options.onShow ||
+      function(element, update){
+        if(!update.style.position || update.style.position=='absolute') {
+          update.style.position = 'absolute';
+          Position.clone(element, update, {
+            setHeight: false,
+            offsetTop: element.offsetHeight
+          });
+        }
+        Effect.Appear(update,{duration:0.15});
+      };
+    this.options.onHide = this.options.onHide ||
+      function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+    if(typeof(this.options.tokens) == 'string')
+      this.options.tokens = new Array(this.options.tokens);
+    // Force carriage returns as token delimiters anyway
+    if (!this.options.tokens.include('\n'))
+      this.options.tokens.push('\n');
+
+    this.observer = null;
+
+    this.element.setAttribute('autocomplete','off');
+
+    Element.hide(this.update);
+
+    Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+    Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+  },
+
+  show: function() {
+    if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+    if(!this.iefix &&
+      (Prototype.Browser.IE) &&
+      (Element.getStyle(this.update, 'position')=='absolute')) {
+      new Insertion.After(this.update,
+       '<iframe id="' + this.update.id + '_iefix" '+
+       'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+       'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+      this.iefix = $(this.update.id+'_iefix');
+    }
+    if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+  },
+
+  fixIEOverlapping: function() {
+    Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+    this.iefix.style.zIndex = 1;
+    this.update.style.zIndex = 2;
+    Element.show(this.iefix);
+  },
+
+  hide: function() {
+    this.stopIndicator();
+    if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+    if(this.iefix) Element.hide(this.iefix);
+  },
+
+  startIndicator: function() {
+    if(this.options.indicator) Element.show(this.options.indicator);
+  },
+
+  stopIndicator: function() {
+    if(this.options.indicator) Element.hide(this.options.indicator);
+  },
+
+  onKeyPress: function(event) {
+    if(this.active)
+      switch(event.keyCode) {
+       case Event.KEY_TAB:
+       case Event.KEY_RETURN:
+         this.selectEntry();
+         Event.stop(event);
+       case Event.KEY_ESC:
+         this.hide();
+         this.active = false;
+         Event.stop(event);
+         return;
+       case Event.KEY_LEFT:
+       case Event.KEY_RIGHT:
+         return;
+       case Event.KEY_UP:
+         this.markPrevious();
+         this.render();
+         Event.stop(event);
+         return;
+       case Event.KEY_DOWN:
+         this.markNext();
+         this.render();
+         Event.stop(event);
+         return;
+      }
+     else
+       if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+         (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+    this.changed = true;
+    this.hasFocus = true;
+
+    if(this.observer) clearTimeout(this.observer);
+      this.observer =
+        setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+  },
+
+  activate: function() {
+    this.changed = false;
+    this.hasFocus = true;
+    this.getUpdatedChoices();
+  },
+
+  onHover: function(event) {
+    var element = Event.findElement(event, 'LI');
+    if(this.index != element.autocompleteIndex)
+    {
+        this.index = element.autocompleteIndex;
+        this.render();
+    }
+    Event.stop(event);
+  },
+
+  onClick: function(event) {
+    var element = Event.findElement(event, 'LI');
+    this.index = element.autocompleteIndex;
+    this.selectEntry();
+    this.hide();
+  },
+
+  onBlur: function(event) {
+    // needed to make click events working
+    setTimeout(this.hide.bind(this), 250);
+    this.hasFocus = false;
+    this.active = false;
+  },
+
+  render: function() {
+    if(this.entryCount > 0) {
+      for (var i = 0; i < this.entryCount; i++)
+        this.index==i ?
+          Element.addClassName(this.getEntry(i),"selected") :
+          Element.removeClassName(this.getEntry(i),"selected");
+      if(this.hasFocus) {
+        this.show();
+        this.active = true;
+      }
+    } else {
+      this.active = false;
+      this.hide();
+    }
+  },
+
+  markPrevious: function() {
+    if(this.index > 0) this.index--;
+      else this.index = this.entryCount-1;
+    this.getEntry(this.index).scrollIntoView(true);
+  },
+
+  markNext: function() {
+    if(this.index < this.entryCount-1) this.index++;
+      else this.index = 0;
+    this.getEntry(this.index).scrollIntoView(false);
+  },
+
+  getEntry: function(index) {
+    return this.update.firstChild.childNodes[index];
+  },
+
+  getCurrentEntry: function() {
+    return this.getEntry(this.index);
+  },
+
+  selectEntry: function() {
+    this.active = false;
+    this.updateElement(this.getCurrentEntry());
+  },
+
+  updateElement: function(selectedElement) {
+    if (this.options.updateElement) {
+      this.options.updateElement(selectedElement);
+      return;
+    }
+    var value = '';
+    if (this.options.select) {
+      var nodes = $(selectedElement).select('.' + this.options.select) || [];
+      if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+    } else
+      value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+    var bounds = this.getTokenBounds();
+    if (bounds[0] != -1) {
+      var newValue = this.element.value.substr(0, bounds[0]);
+      var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+      if (whitespace)
+        newValue += whitespace[0];
+      this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+    } else {
+      this.element.value = value;
+    }
+    this.oldElementValue = this.element.value;
+    this.element.focus();
+
+    if (this.options.afterUpdateElement)
+      this.options.afterUpdateElement(this.element, selectedElement);
+  },
+
+  updateChoices: function(choices) {
+    if(!this.changed && this.hasFocus) {
+      this.update.innerHTML = choices;
+      Element.cleanWhitespace(this.update);
+      Element.cleanWhitespace(this.update.down());
+
+      if(this.update.firstChild && this.update.down().childNodes) {
+        this.entryCount =
+          this.update.down().childNodes.length;
+        for (var i = 0; i < this.entryCount; i++) {
+          var entry = this.getEntry(i);
+          entry.autocompleteIndex = i;
+          this.addObservers(entry);
+        }
+      } else {
+        this.entryCount = 0;
+      }
+
+      this.stopIndicator();
+      this.index = 0;
+
+      if(this.entryCount==1 && this.options.autoSelect) {
+        this.selectEntry();
+        this.hide();
+      } else {
+        this.render();
+      }
+    }
+  },
+
+  addObservers: function(element) {
+    Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+    Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+  },
+
+  onObserverEvent: function() {
+    this.changed = false;
+    this.tokenBounds = null;
+    if(this.getToken().length>=this.options.minChars) {
+      this.getUpdatedChoices();
+    } else {
+      this.active = false;
+      this.hide();
+    }
+    this.oldElementValue = this.element.value;
+  },
+
+  getToken: function() {
+    var bounds = this.getTokenBounds();
+    return this.element.value.substring(bounds[0], bounds[1]).strip();
+  },
+
+  getTokenBounds: function() {
+    if (null != this.tokenBounds) return this.tokenBounds;
+    var value = this.element.value;
+    if (value.strip().empty()) return [-1, 0];
+    var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+    var offset = (diff == this.oldElementValue.length ? 1 : 0);
+    var prevTokenPos = -1, nextTokenPos = value.length;
+    var tp;
+    for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+      tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+      if (tp > prevTokenPos) prevTokenPos = tp;
+      tp = value.indexOf(this.options.tokens[index], diff + offset);
+      if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+    }
+    return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+  }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+  var boundary = Math.min(newS.length, oldS.length);
+  for (var index = 0; index < boundary; ++index)
+    if (newS[index] != oldS[index])
+      return index;
+  return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+  initialize: function(element, update, url, options) {
+    this.baseInitialize(element, update, options);
+    this.options.asynchronous  = true;
+    this.options.onComplete    = this.onComplete.bind(this);
+    this.options.defaultParams = this.options.parameters || null;
+    this.url                   = url;
+  },
+
+  getUpdatedChoices: function() {
+    this.startIndicator();
+
+    var entry = encodeURIComponent(this.options.paramName) + '=' +
+      encodeURIComponent(this.getToken());
+
+    this.options.parameters = this.options.callback ?
+      this.options.callback(this.element, entry) : entry;
+
+    if(this.options.defaultParams)
+      this.options.parameters += '&' + this.options.defaultParams;
+
+    new Ajax.Request(this.url, this.options);
+  },
+
+  onComplete: function(request) {
+    this.updateChoices(request.responseText);
+  }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+//                    text only at the beginning of strings in the
+//                    autocomplete array. Defaults to true, which will
+//                    match text at the beginning of any *word* in the
+//                    strings in the autocomplete array. If you want to
+//                    search anywhere in the string, additionally set
+//                    the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+//                   a partial match (unlike minChars, which defines
+//                   how many characters are required to do any match
+//                   at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+//                 Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+  initialize: function(element, update, array, options) {
+    this.baseInitialize(element, update, options);
+    this.options.array = array;
+  },
+
+  getUpdatedChoices: function() {
+    this.updateChoices(this.options.selector(this));
+  },
+
+  setOptions: function(options) {
+    this.options = Object.extend({
+      choices: 10,
+      partialSearch: true,
+      partialChars: 2,
+      ignoreCase: true,
+      fullSearch: false,
+      selector: function(instance) {
+        var ret       = []; // Beginning matches
+        var partial   = []; // Inside matches
+        var entry     = instance.getToken();
+        var count     = 0;
+
+        for (var i = 0; i < instance.options.array.length &&
+          ret.length < instance.options.choices ; i++) {
+
+          var elem = instance.options.array[i];
+          var foundPos = instance.options.ignoreCase ?
+            elem.toLowerCase().indexOf(entry.toLowerCase()) :
+            elem.indexOf(entry);
+
+          while (foundPos != -1) {
+            if (foundPos == 0 && elem.length != entry.length) {
+              ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+                elem.substr(entry.length) + "</li>");
+              break;
+            } else if (entry.length >= instance.options.partialChars &&
+              instance.options.partialSearch && foundPos != -1) {
+              if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+                partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+                  elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+                  foundPos + entry.length) + "</li>");
+                break;
+              }
+            }
+
+            foundPos = instance.options.ignoreCase ?
+              elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+              elem.indexOf(entry, foundPos + 1);
+
+          }
+        }
+        if (partial.length)
+          ret = ret.concat(partial.slice(0, instance.options.choices - ret.length));
+        return "<ul>" + ret.join('') + "</ul>";
+      }
+    }, options || { });
+  }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+  setTimeout(function() {
+    Field.activate(field);
+  }, 1);
+};
+
+Ajax.InPlaceEditor = Class.create({
+  initialize: function(element, url, options) {
+    this.url = url;
+    this.element = element = $(element);
+    this.prepareOptions();
+    this._controls = { };
+    arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+    Object.extend(this.options, options || { });
+    if (!this.options.formId && this.element.id) {
+      this.options.formId = this.element.id + '-inplaceeditor';
+      if ($(this.options.formId))
+        this.options.formId = '';
+    }
+    if (this.options.externalControl)
+      this.options.externalControl = $(this.options.externalControl);
+    if (!this.options.externalControl)
+      this.options.externalControlOnly = false;
+    this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+    this.element.title = this.options.clickToEditText;
+    this._boundCancelHandler = this.handleFormCancellation.bind(this);
+    this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+    this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+    this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+    this._boundWrapperHandler = this.wrapUp.bind(this);
+    this.registerListeners();
+  },
+  checkForEscapeOrReturn: function(e) {
+    if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+    if (Event.KEY_ESC == e.keyCode)
+      this.handleFormCancellation(e);
+    else if (Event.KEY_RETURN == e.keyCode)
+      this.handleFormSubmission(e);
+  },
+  createControl: function(mode, handler, extraClasses) {
+    var control = this.options[mode + 'Control'];
+    var text = this.options[mode + 'Text'];
+    if ('button' == control) {
+      var btn = document.createElement('input');
+      btn.type = 'submit';
+      btn.value = text;
+      btn.className = 'editor_' + mode + '_button';
+      if ('cancel' == mode)
+        btn.onclick = this._boundCancelHandler;
+      this._form.appendChild(btn);
+      this._controls[mode] = btn;
+    } else if ('link' == control) {
+      var link = document.createElement('a');
+      link.href = '#';
+      link.appendChild(document.createTextNode(text));
+      link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+      link.className = 'editor_' + mode + '_link';
+      if (extraClasses)
+        link.className += ' ' + extraClasses;
+      this._form.appendChild(link);
+      this._controls[mode] = link;
+    }
+  },
+  createEditField: function() {
+    var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+    var fld;
+    if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+      fld = document.createElement('input');
+      fld.type = 'text';
+      var size = this.options.size || this.options.cols || 0;
+      if (0 < size) fld.size = size;
+    } else {
+      fld = document.createElement('textarea');
+      fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+      fld.cols = this.options.cols || 40;
+    }
+    fld.name = this.options.paramName;
+    fld.value = text; // No HTML breaks conversion anymore
+    fld.className = 'editor_field';
+    if (this.options.submitOnBlur)
+      fld.onblur = this._boundSubmitHandler;
+    this._controls.editor = fld;
+    if (this.options.loadTextURL)
+      this.loadExternalText();
+    this._form.appendChild(this._controls.editor);
+  },
+  createForm: function() {
+    var ipe = this;
+    function addText(mode, condition) {
+      var text = ipe.options['text' + mode + 'Controls'];
+      if (!text || condition === false) return;
+      ipe._form.appendChild(document.createTextNode(text));
+    };
+    this._form = $(document.createElement('form'));
+    this._form.id = this.options.formId;
+    this._form.addClassName(this.options.formClassName);
+    this._form.onsubmit = this._boundSubmitHandler;
+    this.createEditField();
+    if ('textarea' == this._controls.editor.tagName.toLowerCase())
+      this._form.appendChild(document.createElement('br'));
+    if (this.options.onFormCustomization)
+      this.options.onFormCustomization(this, this._form);
+    addText('Before', this.options.okControl || this.options.cancelControl);
+    this.createControl('ok', this._boundSubmitHandler);
+    addText('Between', this.options.okControl && this.options.cancelControl);
+    this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+    addText('After', this.options.okControl || this.options.cancelControl);
+  },
+  destroy: function() {
+    if (this._oldInnerHTML)
+      this.element.innerHTML = this._oldInnerHTML;
+    this.leaveEditMode();
+    this.unregisterListeners();
+  },
+  enterEditMode: function(e) {
+    if (this._saving || this._editing) return;
+    this._editing = true;
+    this.triggerCallback('onEnterEditMode');
+    if (this.options.externalControl)
+      this.options.externalControl.hide();
+    this.element.hide();
+    this.createForm();
+    this.element.parentNode.insertBefore(this._form, this.element);
+    if (!this.options.loadTextURL)
+      this.postProcessEditField();
+    if (e) Event.stop(e);
+  },
+  enterHover: function(e) {
+    if (this.options.hoverClassName)
+      this.element.addClassName(this.options.hoverClassName);
+    if (this._saving) return;
+    this.triggerCallback('onEnterHover');
+  },
+  getText: function() {
+    return this.element.innerHTML.unescapeHTML();
+  },
+  handleAJAXFailure: function(transport) {
+    this.triggerCallback('onFailure', transport);
+    if (this._oldInnerHTML) {
+      this.element.innerHTML = this._oldInnerHTML;
+      this._oldInnerHTML = null;
+    }
+  },
+  handleFormCancellation: function(e) {
+    this.wrapUp();
+    if (e) Event.stop(e);
+  },
+  handleFormSubmission: function(e) {
+    var form = this._form;
+    var value = $F(this._controls.editor);
+    this.prepareSubmission();
+    var params = this.options.callback(form, value) || '';
+    if (Object.isString(params))
+      params = params.toQueryParams();
+    params.editorId = this.element.id;
+    if (this.options.htmlResponse) {
+      var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+      Object.extend(options, {
+        parameters: params,
+        onComplete: this._boundWrapperHandler,
+        onFailure: this._boundFailureHandler
+      });
+      new Ajax.Updater({ success: this.element }, this.url, options);
+    } else {
+      var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+      Object.extend(options, {
+        parameters: params,
+        onComplete: this._boundWrapperHandler,
+        onFailure: this._boundFailureHandler
+      });
+      new Ajax.Request(this.url, options);
+    }
+    if (e) Event.stop(e);
+  },
+  leaveEditMode: function() {
+    this.element.removeClassName(this.options.savingClassName);
+    this.removeForm();
+    this.leaveHover();
+    this.element.style.backgroundColor = this._originalBackground;
+    this.element.show();
+    if (this.options.externalControl)
+      this.options.externalControl.show();
+    this._saving = false;
+    this._editing = false;
+    this._oldInnerHTML = null;
+    this.triggerCallback('onLeaveEditMode');
+  },
+  leaveHover: function(e) {
+    if (this.options.hoverClassName)
+      this.element.removeClassName(this.options.hoverClassName);
+    if (this._saving) return;
+    this.triggerCallback('onLeaveHover');
+  },
+  loadExternalText: function() {
+    this._form.addClassName(this.options.loadingClassName);
+    this._controls.editor.disabled = true;
+    var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+    Object.extend(options, {
+      parameters: 'editorId=' + encodeURIComponent(this.element.id),
+      onComplete: Prototype.emptyFunction,
+      onSuccess: function(transport) {
+        this._form.removeClassName(this.options.loadingClassName);
+        var text = transport.responseText;
+        if (this.options.stripLoadedTextTags)
+          text = text.stripTags();
+        this._controls.editor.value = text;
+        this._controls.editor.disabled = false;
+        this.postProcessEditField();
+      }.bind(this),
+      onFailure: this._boundFailureHandler
+    });
+    new Ajax.Request(this.options.loadTextURL, options);
+  },
+  postProcessEditField: function() {
+    var fpc = this.options.fieldPostCreation;
+    if (fpc)
+      $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+  },
+  prepareOptions: function() {
+    this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+    Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+    [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+      Object.extend(this.options, defs);
+    }.bind(this));
+  },
+  prepareSubmission: function() {
+    this._saving = true;
+    this.removeForm();
+    this.leaveHover();
+    this.showSaving();
+  },
+  registerListeners: function() {
+    this._listeners = { };
+    var listener;
+    $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+      listener = this[pair.value].bind(this);
+      this._listeners[pair.key] = listener;
+      if (!this.options.externalControlOnly)
+        this.element.observe(pair.key, listener);
+      if (this.options.externalControl)
+        this.options.externalControl.observe(pair.key, listener);
+    }.bind(this));
+  },
+  removeForm: function() {
+    if (!this._form) return;
+    this._form.remove();
+    this._form = null;
+    this._controls = { };
+  },
+  showSaving: function() {
+    this._oldInnerHTML = this.element.innerHTML;
+    this.element.innerHTML = this.options.savingText;
+    this.element.addClassName(this.options.savingClassName);
+    this.element.style.backgroundColor = this._originalBackground;
+    this.element.show();
+  },
+  triggerCallback: function(cbName, arg) {
+    if ('function' == typeof this.options[cbName]) {
+      this.options[cbName](this, arg);
+    }
+  },
+  unregisterListeners: function() {
+    $H(this._listeners).each(function(pair) {
+      if (!this.options.externalControlOnly)
+        this.element.stopObserving(pair.key, pair.value);
+      if (this.options.externalControl)
+        this.options.externalControl.stopObserving(pair.key, pair.value);
+    }.bind(this));
+  },
+  wrapUp: function(transport) {
+    this.leaveEditMode();
+    // Can't use triggerCallback due to backward compatibility: requires
+    // binding + direct element
+    this._boundComplete(transport, this.element);
+  }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+  dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+  initialize: function($super, element, url, options) {
+    this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+    $super(element, url, options);
+  },
+
+  createEditField: function() {
+    var list = document.createElement('select');
+    list.name = this.options.paramName;
+    list.size = 1;
+    this._controls.editor = list;
+    this._collection = this.options.collection || [];
+    if (this.options.loadCollectionURL)
+      this.loadCollection();
+    else
+      this.checkForExternalText();
+    this._form.appendChild(this._controls.editor);
+  },
+
+  loadCollection: function() {
+    this._form.addClassName(this.options.loadingClassName);
+    this.showLoadingText(this.options.loadingCollectionText);
+    var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+    Object.extend(options, {
+      parameters: 'editorId=' + encodeURIComponent(this.element.id),
+      onComplete: Prototype.emptyFunction,
+      onSuccess: function(transport) {
+        var js = transport.responseText.strip();
+        if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+          throw('Server returned an invalid collection representation.');
+        this._collection = eval(js);
+        this.checkForExternalText();
+      }.bind(this),
+      onFailure: this.onFailure
+    });
+    new Ajax.Request(this.options.loadCollectionURL, options);
+  },
+
+  showLoadingText: function(text) {
+    this._controls.editor.disabled = true;
+    var tempOption = this._controls.editor.firstChild;
+    if (!tempOption) {
+      tempOption = document.createElement('option');
+      tempOption.value = '';
+      this._controls.editor.appendChild(tempOption);
+      tempOption.selected = true;
+    }
+    tempOption.update((text || '').stripScripts().stripTags());
+  },
+
+  checkForExternalText: function() {
+    this._text = this.getText();
+    if (this.options.loadTextURL)
+      this.loadExternalText();
+    else
+      this.buildOptionList();
+  },
+
+  loadExternalText: function() {
+    this.showLoadingText(this.options.loadingText);
+    var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+    Object.extend(options, {
+      parameters: 'editorId=' + encodeURIComponent(this.element.id),
+      onComplete: Prototype.emptyFunction,
+      onSuccess: function(transport) {
+        this._text = transport.responseText.strip();
+        this.buildOptionList();
+      }.bind(this),
+      onFailure: this.onFailure
+    });
+    new Ajax.Request(this.options.loadTextURL, options);
+  },
+
+  buildOptionList: function() {
+    this._form.removeClassName(this.options.loadingClassName);
+    this._collection = this._collection.map(function(entry) {
+      return 2 === entry.length ? entry : [entry, entry].flatten();
+    });
+    var marker = ('value' in this.options) ? this.options.value : this._text;
+    var textFound = this._collection.any(function(entry) {
+      return entry[0] == marker;
+    }.bind(this));
+    this._controls.editor.update('');
+    var option;
+    this._collection.each(function(entry, index) {
+      option = document.createElement('option');
+      option.value = entry[0];
+      option.selected = textFound ? entry[0] == marker : 0 == index;
+      option.appendChild(document.createTextNode(entry[1]));
+      this._controls.editor.appendChild(option);
+    }.bind(this));
+    this._controls.editor.disabled = false;
+    Field.scrollFreeActivate(this._controls.editor);
+  }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only  exists for a while,  in order to  let ****
+//**** users adapt to  the new API.  Read up on the new ****
+//**** API and convert your code to it ASAP!            ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+  if (!options) return;
+  function fallback(name, expr) {
+    if (name in options || expr === undefined) return;
+    options[name] = expr;
+  };
+  fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+    options.cancelLink == options.cancelButton == false ? false : undefined)));
+  fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+    options.okLink == options.okButton == false ? false : undefined)));
+  fallback('highlightColor', options.highlightcolor);
+  fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+  DefaultOptions: {
+    ajaxOptions: { },
+    autoRows: 3,                                // Use when multi-line w/ rows == 1
+    cancelControl: 'link',                      // 'link'|'button'|false
+    cancelText: 'cancel',
+    clickToEditText: 'Click to edit',
+    externalControl: null,                      // id|elt
+    externalControlOnly: false,
+    fieldPostCreation: 'activate',              // 'activate'|'focus'|false
+    formClassName: 'inplaceeditor-form',
+    formId: null,                               // id|elt
+    highlightColor: '#ffff99',
+    highlightEndColor: '#ffffff',
+    hoverClassName: '',
+    htmlResponse: true,
+    loadingClassName: 'inplaceeditor-loading',
+    loadingText: 'Loading...',
+    okControl: 'button',                        // 'link'|'button'|false
+    okText: 'ok',
+    paramName: 'value',
+    rows: 1,                                    // If 1 and multi-line, uses autoRows
+    savingClassName: 'inplaceeditor-saving',
+    savingText: 'Saving...',
+    size: 0,
+    stripLoadedTextTags: false,
+    submitOnBlur: false,
+    textAfterControls: '',
+    textBeforeControls: '',
+    textBetweenControls: ''
+  },
+  DefaultCallbacks: {
+    callback: function(form) {
+      return Form.serialize(form);
+    },
+    onComplete: function(transport, element) {
+      // For backward compatibility, this one is bound to the IPE, and passes
+      // the element directly.  It was too often customized, so we don't break it.
+      new Effect.Highlight(element, {
+        startcolor: this.options.highlightColor, keepBackgroundImage: true });
+    },
+    onEnterEditMode: null,
+    onEnterHover: function(ipe) {
+      ipe.element.style.backgroundColor = ipe.options.highlightColor;
+      if (ipe._effect)
+        ipe._effect.cancel();
+    },
+    onFailure: function(transport, ipe) {
+      alert('Error communication with the server: ' + transport.responseText.stripTags());
+    },
+    onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+    onLeaveEditMode: null,
+    onLeaveHover: function(ipe) {
+      ipe._effect = new Effect.Highlight(ipe.element, {
+        startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+        restorecolor: ipe._originalBackground, keepBackgroundImage: true
+      });
+    }
+  },
+  Listeners: {
+    click: 'enterEditMode',
+    keydown: 'checkForEscapeOrReturn',
+    mouseover: 'enterHover',
+    mouseout: 'leaveHover'
+  }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+  loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+  initialize: function(element, delay, callback) {
+    this.delay     = delay || 0.5;
+    this.element   = $(element);
+    this.callback  = callback;
+    this.timer     = null;
+    this.lastValue = $F(this.element);
+    Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+  },
+  delayedListener: function(event) {
+    if(this.lastValue == $F(this.element)) return;
+    if(this.timer) clearTimeout(this.timer);
+    this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+    this.lastValue = $F(this.element);
+  },
+  onTimerEvent: function() {
+    this.timer = null;
+    this.callback(this.element, $F(this.element));
+  }
+});
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/web/js/dragdrop.js	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,975 @@
+// script.aculo.us dragdrop.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//           (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+  throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+  drops: [],
+
+  remove: function(element) {
+    this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+  },
+
+  add: function(element) {
+    element = $(element);
+    var options = Object.extend({
+      greedy:     true,
+      hoverclass: null,
+      tree:       false
+    }, arguments[1] || { });
+
+    // cache containers
+    if(options.containment) {
+      options._containers = [];
+      var containment = options.containment;
+      if(Object.isArray(containment)) {
+        containment.each( function(c) { options._containers.push($(c)) });
+      } else {
+        options._containers.push($(containment));
+      }
+    }
+
+    if(options.accept) options.accept = [options.accept].flatten();
+
+    Element.makePositioned(element); // fix IE
+    options.element = element;
+
+    this.drops.push(options);
+  },
+
+  findDeepestChild: function(drops) {
+    deepest = drops[0];
+
+    for (i = 1; i < drops.length; ++i)
+      if (Element.isParent(drops[i].element, deepest.element))
+        deepest = drops[i];
+
+    return deepest;
+  },
+
+  isContained: function(element, drop) {
+    var containmentNode;
+    if(drop.tree) {
+      containmentNode = element.treeNode;
+    } else {
+      containmentNode = element.parentNode;
+    }
+    return drop._containers.detect(function(c) { return containmentNode == c });
+  },
+
+  isAffected: function(point, element, drop) {
+    return (
+      (drop.element!=element) &&
+      ((!drop._containers) ||
+        this.isContained(element, drop)) &&
+      ((!drop.accept) ||
+        (Element.classNames(element).detect(
+          function(v) { return drop.accept.include(v) } ) )) &&
+      Position.within(drop.element, point[0], point[1]) );
+  },
+
+  deactivate: function(drop) {
+    if(drop.hoverclass)
+      Element.removeClassName(drop.element, drop.hoverclass);
+    this.last_active = null;
+  },
+
+  activate: function(drop) {
+    if(drop.hoverclass)
+      Element.addClassName(drop.element, drop.hoverclass);
+    this.last_active = drop;
+  },
+
+  show: function(point, element) {
+    if(!this.drops.length) return;
+    var drop, affected = [];
+
+    this.drops.each( function(drop) {
+      if(Droppables.isAffected(point, element, drop))
+        affected.push(drop);
+    });
+
+    if(affected.length>0)
+      drop = Droppables.findDeepestChild(affected);
+
+    if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+    if (drop) {
+      Position.within(drop.element, point[0], point[1]);
+      if(drop.onHover)
+        drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+      if (drop != this.last_active) Droppables.activate(drop);
+    }
+  },
+
+  fire: function(event, element) {
+    if(!this.last_active) return;
+    Position.prepare();
+
+    if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+      if (this.last_active.onDrop) {
+        this.last_active.onDrop(element, this.last_active.element, event);
+        return true;
+      }
+  },
+
+  reset: function() {
+    if(this.last_active)
+      this.deactivate(this.last_active);
+  }
+};
+
+var Draggables = {
+  drags: [],
+  observers: [],
+
+  register: function(draggable) {
+    if(this.drags.length == 0) {
+      this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
+      this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+      this.eventKeypress  = this.keyPress.bindAsEventListener(this);
+
+      Event.observe(document, "mouseup", this.eventMouseUp);
+      Event.observe(document, "mousemove", this.eventMouseMove);
+      Event.observe(document, "keypress", this.eventKeypress);
+    }
+    this.drags.push(draggable);
+  },
+
+  unregister: function(draggable) {
+    this.drags = this.drags.reject(function(d) { return d==draggable });
+    if(this.drags.length == 0) {
+      Event.stopObserving(document, "mouseup", this.eventMouseUp);
+      Event.stopObserving(document, "mousemove", this.eventMouseMove);
+      Event.stopObserving(document, "keypress", this.eventKeypress);
+    }
+  },
+
+  activate: function(draggable) {
+    if(draggable.options.delay) {
+      this._timeout = setTimeout(function() {
+        Draggables._timeout = null;
+        window.focus();
+        Draggables.activeDraggable = draggable;
+      }.bind(this), draggable.options.delay);
+    } else {
+      window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+      this.activeDraggable = draggable;
+    }
+  },
+
+  deactivate: function() {
+    this.activeDraggable = null;
+  },
+
+  updateDrag: function(event) {
+    if(!this.activeDraggable) return;
+    var pointer = [Event.pointerX(event), Event.pointerY(event)];
+    // Mozilla-based browsers fire successive mousemove events with
+    // the same coordinates, prevent needless redrawing (moz bug?)
+    if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+    this._lastPointer = pointer;
+
+    this.activeDraggable.updateDrag(event, pointer);
+  },
+
+  endDrag: function(event) {
+    if(this._timeout) {
+      clearTimeout(this._timeout);
+      this._timeout = null;
+    }
+    if(!this.activeDraggable) return;
+    this._lastPointer = null;
+    this.activeDraggable.endDrag(event);
+    this.activeDraggable = null;
+  },
+
+  keyPress: function(event) {
+    if(this.activeDraggable)
+      this.activeDraggable.keyPress(event);
+  },
+
+  addObserver: function(observer) {
+    this.observers.push(observer);
+    this._cacheObserverCallbacks();
+  },
+
+  removeObserver: function(element) {  // element instead of observer fixes mem leaks
+    this.observers = this.observers.reject( function(o) { return o.element==element });
+    this._cacheObserverCallbacks();
+  },
+
+  notify: function(eventName, draggable, event) {  // 'onStart', 'onEnd', 'onDrag'
+    if(this[eventName+'Count'] > 0)
+      this.observers.each( function(o) {
+        if(o[eventName]) o[eventName](eventName, draggable, event);
+      });
+    if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+  },
+
+  _cacheObserverCallbacks: function() {
+    ['onStart','onEnd','onDrag'].each( function(eventName) {
+      Draggables[eventName+'Count'] = Draggables.observers.select(
+        function(o) { return o[eventName]; }
+      ).length;
+    });
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+  initialize: function(element) {
+    var defaults = {
+      handle: false,
+      reverteffect: function(element, top_offset, left_offset) {
+        var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+        new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+          queue: {scope:'_draggable', position:'end'}
+        });
+      },
+      endeffect: function(element) {
+        var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+        new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+          queue: {scope:'_draggable', position:'end'},
+          afterFinish: function(){
+            Draggable._dragging[element] = false
+          }
+        });
+      },
+      zindex: 1000,
+      revert: false,
+      quiet: false,
+      scroll: false,
+      scrollSensitivity: 20,
+      scrollSpeed: 15,
+      snap: false,  // false, or xy or [x,y] or function(x,y){ return [x,y] }
+      delay: 0
+    };
+
+    if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+      Object.extend(defaults, {
+        starteffect: function(element) {
+          element._opacity = Element.getOpacity(element);
+          Draggable._dragging[element] = true;
+          new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+        }
+      });
+
+    var options = Object.extend(defaults, arguments[1] || { });
+
+    this.element = $(element);
+
+    if(options.handle && Object.isString(options.handle))
+      this.handle = this.element.down('.'+options.handle, 0);
+
+    if(!this.handle) this.handle = $(options.handle);
+    if(!this.handle) this.handle = this.element;
+
+    if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+      options.scroll = $(options.scroll);
+      this._isScrollChild = Element.childOf(this.element, options.scroll);
+    }
+
+    Element.makePositioned(this.element); // fix IE
+
+    this.options  = options;
+    this.dragging = false;
+
+    this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+    Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+    Draggables.register(this);
+  },
+
+  destroy: function() {
+    Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+    Draggables.unregister(this);
+  },
+
+  currentDelta: function() {
+    return([
+      parseInt(Element.getStyle(this.element,'left') || '0'),
+      parseInt(Element.getStyle(this.element,'top') || '0')]);
+  },
+
+  initDrag: function(event) {
+    if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+      Draggable._dragging[this.element]) return;
+    if(Event.isLeftClick(event)) {
+      // abort on form elements, fixes a Firefox issue
+      var src = Event.element(event);
+      if((tag_name = src.tagName.toUpperCase()) && (
+        tag_name=='INPUT' ||
+        tag_name=='SELECT' ||
+        tag_name=='OPTION' ||
+        tag_name=='BUTTON' ||
+        tag_name=='TEXTAREA')) return;
+
+      var pointer = [Event.pointerX(event), Event.pointerY(event)];
+      var pos     = Position.cumulativeOffset(this.element);
+      this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+      Draggables.activate(this);
+      Event.stop(event);
+    }
+  },
+
+  startDrag: function(event) {
+    this.dragging = true;
+    if(!this.delta)
+      this.delta = this.currentDelta();
+
+    if(this.options.zindex) {
+      this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+      this.element.style.zIndex = this.options.zindex;
+    }
+
+    if(this.options.ghosting) {
+      this._clone = this.element.cloneNode(true);
+      this._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+      if (!this._originallyAbsolute)
+        Position.absolutize(this.element);
+      this.element.parentNode.insertBefore(this._clone, this.element);
+    }
+
+    if(this.options.scroll) {
+      if (this.options.scroll == window) {
+        var where = this._getWindowScroll(this.options.scroll);
+        this.originalScrollLeft = where.left;
+        this.originalScrollTop = where.top;
+      } else {
+        this.originalScrollLeft = this.options.scroll.scrollLeft;
+        this.originalScrollTop = this.options.scroll.scrollTop;
+      }
+    }
+
+    Draggables.notify('onStart', this, event);
+
+    if(this.options.starteffect) this.options.starteffect(this.element);
+  },
+
+  updateDrag: function(event, pointer) {
+    if(!this.dragging) this.startDrag(event);
+
+    if(!this.options.quiet){
+      Position.prepare();
+      Droppables.show(pointer, this.element);
+    }
+
+    Draggables.notify('onDrag', this, event);
+
+    this.draw(pointer);
+    if(this.options.change) this.options.change(this);
+
+    if(this.options.scroll) {
+      this.stopScrolling();
+
+      var p;
+      if (this.options.scroll == window) {
+        with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+      } else {
+        p = Position.page(this.options.scroll);
+        p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+        p[1] += this.options.scroll.scrollTop + Position.deltaY;
+        p.push(p[0]+this.options.scroll.offsetWidth);
+        p.push(p[1]+this.options.scroll.offsetHeight);
+      }
+      var speed = [0,0];
+      if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+      if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+      if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+      if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+      this.startScrolling(speed);
+    }
+
+    // fix AppleWebKit rendering
+    if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+    Event.stop(event);
+  },
+
+  finishDrag: function(event, success) {
+    this.dragging = false;
+
+    if(this.options.quiet){
+      Position.prepare();
+      var pointer = [Event.pointerX(event), Event.pointerY(event)];
+      Droppables.show(pointer, this.element);
+    }
+
+    if(this.options.ghosting) {
+      if (!this._originallyAbsolute)
+        Position.relativize(this.element);
+      delete this._originallyAbsolute;
+      Element.remove(this._clone);
+      this._clone = null;
+    }
+
+    var dropped = false;
+    if(success) {
+      dropped = Droppables.fire(event, this.element);
+      if (!dropped) dropped = false;
+    }
+    if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+    Draggables.notify('onEnd', this, event);
+
+    var revert = this.options.revert;
+    if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+    var d = this.currentDelta();
+    if(revert && this.options.reverteffect) {
+      if (dropped == 0 || revert != 'failure')
+        this.options.reverteffect(this.element,
+          d[1]-this.delta[1], d[0]-this.delta[0]);
+    } else {
+      this.delta = d;
+    }
+
+    if(this.options.zindex)
+      this.element.style.zIndex = this.originalZ;
+
+    if(this.options.endeffect)
+      this.options.endeffect(this.element);
+
+    Draggables.deactivate(this);
+    Droppables.reset();
+  },
+
+  keyPress: function(event) {
+    if(event.keyCode!=Event.KEY_ESC) return;
+    this.finishDrag(event, false);
+    Event.stop(event);
+  },
+
+  endDrag: function(event) {
+    if(!this.dragging) return;
+    this.stopScrolling();
+    this.finishDrag(event, true);
+    Event.stop(event);
+  },
+
+  draw: function(point) {
+    var pos = Position.cumulativeOffset(this.element);
+    if(this.options.ghosting) {
+      var r   = Position.realOffset(this.element);
+      pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+    }
+
+    var d = this.currentDelta();
+    pos[0] -= d[0]; pos[1] -= d[1];
+
+    if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+      pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+      pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+    }
+
+    var p = [0,1].map(function(i){
+      return (point[i]-pos[i]-this.offset[i])
+    }.bind(this));
+
+    if(this.options.snap) {
+      if(Object.isFunction(this.options.snap)) {
+        p = this.options.snap(p[0],p[1],this);
+      } else {
+      if(Object.isArray(this.options.snap)) {
+        p = p.map( function(v, i) {
+          return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this));
+      } else {
+        p = p.map( function(v) {
+          return (v/this.options.snap).round()*this.options.snap }.bind(this));
+      }
+    }}
+
+    var style = this.element.style;
+    if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+      style.left = p[0] + "px";
+    if((!this.options.constraint) || (this.options.constraint=='vertical'))
+      style.top  = p[1] + "px";
+
+    if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+  },
+
+  stopScrolling: function() {
+    if(this.scrollInterval) {
+      clearInterval(this.scrollInterval);
+      this.scrollInterval = null;
+      Draggables._lastScrollPointer = null;
+    }
+  },
+
+  startScrolling: function(speed) {
+    if(!(speed[0] || speed[1])) return;
+    this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+    this.lastScrolled = new Date();
+    this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+  },
+
+  scroll: function() {
+    var current = new Date();
+    var delta = current - this.lastScrolled;
+    this.lastScrolled = current;
+    if(this.options.scroll == window) {
+      with (this._getWindowScroll(this.options.scroll)) {
+        if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+          var d = delta / 1000;
+          this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+        }
+      }
+    } else {
+      this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+      this.options.scroll.scrollTop  += this.scrollSpeed[1] * delta / 1000;
+    }
+
+    Position.prepare();
+    Droppables.show(Draggables._lastPointer, this.element);
+    Draggables.notify('onDrag', this);
+    if (this._isScrollChild) {
+      Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+      Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+      Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+      if (Draggables._lastScrollPointer[0] < 0)
+        Draggables._lastScrollPointer[0] = 0;
+      if (Draggables._lastScrollPointer[1] < 0)
+        Draggables._lastScrollPointer[1] = 0;
+      this.draw(Draggables._lastScrollPointer);
+    }
+
+    if(this.options.change) this.options.change(this);
+  },
+
+  _getWindowScroll: function(w) {
+    var T, L, W, H;
+    with (w.document) {
+      if (w.document.documentElement && documentElement.scrollTop) {
+        T = documentElement.scrollTop;
+        L = documentElement.scrollLeft;
+      } else if (w.document.body) {
+        T = body.scrollTop;
+        L = body.scrollLeft;
+      }
+      if (w.innerWidth) {
+        W = w.innerWidth;
+        H = w.innerHeight;
+      } else if (w.document.documentElement && documentElement.clientWidth) {
+        W = documentElement.clientWidth;
+        H = documentElement.clientHeight;
+      } else {
+        W = body.offsetWidth;
+        H = body.offsetHeight;
+      }
+    }
+    return { top: T, left: L, width: W, height: H };
+  }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+  initialize: function(element, observer) {
+    this.element   = $(element);
+    this.observer  = observer;
+    this.lastValue = Sortable.serialize(this.element);
+  },
+
+  onStart: function() {
+    this.lastValue = Sortable.serialize(this.element);
+  },
+
+  onEnd: function() {
+    Sortable.unmark();
+    if(this.lastValue != Sortable.serialize(this.element))
+      this.observer(this.element)
+  }
+});
+
+var Sortable = {
+  SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+  sortables: { },
+
+  _findRootElement: function(element) {
+    while (element.tagName.toUpperCase() != "BODY") {
+      if(element.id && Sortable.sortables[element.id]) return element;
+      element = element.parentNode;
+    }
+  },
+
+  options: function(element) {
+    element = Sortable._findRootElement($(element));
+    if(!element) return;
+    return Sortable.sortables[element.id];
+  },
+
+  destroy: function(element){
+    element = $(element);
+    var s = Sortable.sortables[element.id];
+
+    if(s) {
+      Draggables.removeObserver(s.element);
+      s.droppables.each(function(d){ Droppables.remove(d) });
+      s.draggables.invoke('destroy');
+
+      delete Sortable.sortables[s.element.id];
+    }
+  },
+
+  create: function(element) {
+    element = $(element);
+    var options = Object.extend({
+      element:     element,
+      tag:         'li',       // assumes li children, override with tag: 'tagname'
+      dropOnEmpty: false,
+      tree:        false,
+      treeTag:     'ul',
+      overlap:     'vertical', // one of 'vertical', 'horizontal'
+      constraint:  'vertical', // one of 'vertical', 'horizontal', false
+      containment: element,    // also takes array of elements (or id's); or false
+      handle:      false,      // or a CSS class
+      only:        false,
+      delay:       0,
+      hoverclass:  null,
+      ghosting:    false,
+      quiet:       false,
+      scroll:      false,
+      scrollSensitivity: 20,
+      scrollSpeed: 15,
+      format:      this.SERIALIZE_RULE,
+
+      // these take arrays of elements or ids and can be
+      // used for better initialization performance
+      elements:    false,
+      handles:     false,
+
+      onChange:    Prototype.emptyFunction,
+      onUpdate:    Prototype.emptyFunction
+    }, arguments[1] || { });
+
+    // clear any old sortable with same element
+    this.destroy(element);
+
+    // build options for the draggables
+    var options_for_draggable = {
+      revert:      true,
+      quiet:       options.quiet,
+      scroll:      options.scroll,
+      scrollSpeed: options.scrollSpeed,
+      scrollSensitivity: options.scrollSensitivity,
+      delay:       options.delay,
+      ghosting:    options.ghosting,
+      constraint:  options.constraint,
+      handle:      options.handle };
+
+    if(options.starteffect)
+      options_for_draggable.starteffect = options.starteffect;
+
+    if(options.reverteffect)
+      options_for_draggable.reverteffect = options.reverteffect;
+    else
+      if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+        element.style.top  = 0;
+        element.style.left = 0;
+      };
+
+    if(options.endeffect)
+      options_for_draggable.endeffect = options.endeffect;
+
+    if(options.zindex)
+      options_for_draggable.zindex = options.zindex;
+
+    // build options for the droppables
+    var options_for_droppable = {
+      overlap:     options.overlap,
+      containment: options.containment,
+      tree:        options.tree,
+      hoverclass:  options.hoverclass,
+      onHover:     Sortable.onHover
+    };
+
+    var options_for_tree = {
+      onHover:      Sortable.onEmptyHover,
+      overlap:      options.overlap,
+      containment:  options.containment,
+      hoverclass:   options.hoverclass
+    };
+
+    // fix for gecko engine
+    Element.cleanWhitespace(element);
+
+    options.draggables = [];
+    options.droppables = [];
+
+    // drop on empty handling
+    if(options.dropOnEmpty || options.tree) {
+      Droppables.add(element, options_for_tree);
+      options.droppables.push(element);
+    }
+
+    (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+      var handle = options.handles ? $(options.handles[i]) :
+        (options.handle ? $(e).select('.' + options.handle)[0] : e);
+      options.draggables.push(
+        new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+      Droppables.add(e, options_for_droppable);
+      if(options.tree) e.treeNode = element;
+      options.droppables.push(e);
+    });
+
+    if(options.tree) {
+      (Sortable.findTreeElements(element, options) || []).each( function(e) {
+        Droppables.add(e, options_for_tree);
+        e.treeNode = element;
+        options.droppables.push(e);
+      });
+    }
+
+    // keep reference
+    this.sortables[element.id] = options;
+
+    // for onupdate
+    Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+  },
+
+  // return all suitable-for-sortable elements in a guaranteed order
+  findElements: function(element, options) {
+    return Element.findChildren(
+      element, options.only, options.tree ? true : false, options.tag);
+  },
+
+  findTreeElements: function(element, options) {
+    return Element.findChildren(
+      element, options.only, options.tree ? true : false, options.treeTag);
+  },
+
+  onHover: function(element, dropon, overlap) {
+    if(Element.isParent(dropon, element)) return;
+
+    if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+      return;
+    } else if(overlap>0.5) {
+      Sortable.mark(dropon, 'before');
+      if(dropon.previousSibling != element) {
+        var oldParentNode = element.parentNode;
+        element.style.visibility = "hidden"; // fix gecko rendering
+        dropon.parentNode.insertBefore(element, dropon);
+        if(dropon.parentNode!=oldParentNode)
+          Sortable.options(oldParentNode).onChange(element);
+        Sortable.options(dropon.parentNode).onChange(element);
+      }
+    } else {
+      Sortable.mark(dropon, 'after');
+      var nextElement = dropon.nextSibling || null;
+      if(nextElement != element) {
+        var oldParentNode = element.parentNode;
+        element.style.visibility = "hidden"; // fix gecko rendering
+        dropon.parentNode.insertBefore(element, nextElement);
+        if(dropon.parentNode!=oldParentNode)
+          Sortable.options(oldParentNode).onChange(element);
+        Sortable.options(dropon.parentNode).onChange(element);
+      }
+    }
+  },
+
+  onEmptyHover: function(element, dropon, overlap) {
+    var oldParentNode = element.parentNode;
+    var droponOptions = Sortable.options(dropon);
+
+    if(!Element.isParent(dropon, element)) {
+      var index;
+
+      var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+      var child = null;
+
+      if(children) {
+        var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+        for (index = 0; index < children.length; index += 1) {
+          if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+            offset -= Element.offsetSize (children[index], droponOptions.overlap);
+          } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+            child = index + 1 < children.length ? children[index + 1] : null;
+            break;
+          } else {
+            child = children[index];
+            break;
+          }
+        }
+      }
+
+      dropon.insertBefore(element, child);
+
+      Sortable.options(oldParentNode).onChange(element);
+      droponOptions.onChange(element);
+    }
+  },
+
+  unmark: function() {
+    if(Sortable._marker) Sortable._marker.hide();
+  },
+
+  mark: function(dropon, position) {
+    // mark on ghosting only
+    var sortable = Sortable.options(dropon.parentNode);
+    if(sortable && !sortable.ghosting) return;
+
+    if(!Sortable._marker) {
+      Sortable._marker =
+        ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+          hide().addClassName('dropmarker').setStyle({position:'absolute'});
+      document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+    }
+    var offsets = Position.cumulativeOffset(dropon);
+    Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+    if(position=='after')
+      if(sortable.overlap == 'horizontal')
+        Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+      else
+        Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+    Sortable._marker.show();
+  },
+
+  _tree: function(element, options, parent) {
+    var children = Sortable.findElements(element, options) || [];
+
+    for (var i = 0; i < children.length; ++i) {
+      var match = children[i].id.match(options.format);
+
+      if (!match) continue;
+
+      var child = {
+        id: encodeURIComponent(match ? match[1] : null),
+        element: element,
+        parent: parent,
+        children: [],
+        position: parent.children.length,
+        container: $(children[i]).down(options.treeTag)
+      };
+
+      /* Get the element containing the children and recurse over it */
+      if (child.container)
+        this._tree(child.container, options, child);
+
+      parent.children.push (child);
+    }
+
+    return parent;
+  },
+
+  tree: function(element) {
+    element = $(element);
+    var sortableOptions = this.options(element);
+    var options = Object.extend({
+      tag: sortableOptions.tag,
+      treeTag: sortableOptions.treeTag,
+      only: sortableOptions.only,
+      name: element.id,
+      format: sortableOptions.format
+    }, arguments[1] || { });
+
+    var root = {
+      id: null,
+      parent: null,
+      children: [],
+      container: element,
+      position: 0
+    };
+
+    return Sortable._tree(element, options, root);
+  },
+
+  /* Construct a [i] index for a particular node */
+  _constructIndex: function(node) {
+    var index = '';
+    do {
+      if (node.id) index = '[' + node.position + ']' + index;
+    } while ((node = node.parent) != null);
+    return index;
+  },
+
+  sequence: function(element) {
+    element = $(element);
+    var options = Object.extend(this.options(element), arguments[1] || { });
+
+    return $(this.findElements(element, options) || []).map( function(item) {
+      return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+    });
+  },
+
+  setSequence: function(element, new_sequence) {
+    element = $(element);
+    var options = Object.extend(this.options(element), arguments[2] || { });
+
+    var nodeMap = { };
+    this.findElements(element, options).each( function(n) {
+        if (n.id.match(options.format))
+            nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+        n.parentNode.removeChild(n);
+    });
+
+    new_sequence.each(function(ident) {
+      var n = nodeMap[ident];
+      if (n) {
+        n[1].appendChild(n[0]);
+        delete nodeMap[ident];
+      }
+    });
+  },
+
+  serialize: function(element) {
+    element = $(element);
+    var options = Object.extend(Sortable.options(element), arguments[1] || { });
+    var name = encodeURIComponent(
+      (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+    if (options.tree) {
+      return Sortable.tree(element, arguments[1]).children.map( function (item) {
+        return [name + Sortable._constructIndex(item) + "[id]=" +
+                encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+      }).flatten().join('&');
+    } else {
+      return Sortable.sequence(element, arguments[1]).map( function(item) {
+        return name + "[]=" + encodeURIComponent(item);
+      }).join('&');
+    }
+  }
+};
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+  if (!child.parentNode || child == element) return false;
+  if (child.parentNode == element) return true;
+  return Element.isParent(child.parentNode, element);
+};
+
+Element.findChildren = function(element, only, recursive, tagName) {
+  if(!element.hasChildNodes()) return null;
+  tagName = tagName.toUpperCase();
+  if(only) only = [only].flatten();
+  var elements = [];
+  $A(element.childNodes).each( function(e) {
+    if(e.tagName && e.tagName.toUpperCase()==tagName &&
+      (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+        elements.push(e);
+    if(recursive) {
+      var grandchildren = Element.findChildren(e, only, recursive, tagName);
+      if(grandchildren) elements.push(grandchildren);
+    }
+  });
+
+  return (elements.length>0 ? elements.flatten() : []);
+};
+
+Element.offsetSize = function (element, type) {
+  return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/web/js/effects.js	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,1130 @@
+// script.aculo.us effects.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+//  Justin Palmer (http://encytemedia.com/)
+//  Mark Pilgrim (http://diveintomark.org/)
+//  Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+  var color = '#';
+  if (this.slice(0,4) == 'rgb(') {
+    var cols = this.slice(4,this.length-1).split(',');
+    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+  } else {
+    if (this.slice(0,1) == '#') {
+      if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+      if (this.length==7) color = this.toLowerCase();
+    }
+  }
+  return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+  return $A($(element).childNodes).collect( function(node) {
+    return (node.nodeType==3 ? node.nodeValue :
+      (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+  }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+  return $A($(element).childNodes).collect( function(node) {
+    return (node.nodeType==3 ? node.nodeValue :
+      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+        Element.collectTextNodesIgnoreClass(node, className) : ''));
+  }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+  element = $(element);
+  element.setStyle({fontSize: (percent/100) + 'em'});
+  if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+  return element;
+};
+
+Element.getInlineOpacity = function(element){
+  return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+  try {
+    element = $(element);
+    var n = document.createTextNode(' ');
+    element.appendChild(n);
+    element.removeChild(n);
+  } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+  _elementDoesNotExistError: {
+    name: 'ElementDoesNotExistError',
+    message: 'The specified DOM element does not exist, but is required for this effect to operate'
+  },
+  Transitions: {
+    linear: Prototype.K,
+    sinoidal: function(pos) {
+      return (-Math.cos(pos*Math.PI)/2) + .5;
+    },
+    reverse: function(pos) {
+      return 1-pos;
+    },
+    flicker: function(pos) {
+      var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4;
+      return pos > 1 ? 1 : pos;
+    },
+    wobble: function(pos) {
+      return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5;
+    },
+    pulse: function(pos, pulses) {
+      return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5;
+    },
+    spring: function(pos) {
+      return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+    },
+    none: function(pos) {
+      return 0;
+    },
+    full: function(pos) {
+      return 1;
+    }
+  },
+  DefaultOptions: {
+    duration:   1.0,   // seconds
+    fps:        100,   // 100= assume 66fps max.
+    sync:       false, // true for combining
+    from:       0.0,
+    to:         1.0,
+    delay:      0.0,
+    queue:      'parallel'
+  },
+  tagifyText: function(element) {
+    var tagifyStyle = 'position:relative';
+    if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+    element = $(element);
+    $A(element.childNodes).each( function(child) {
+      if (child.nodeType==3) {
+        child.nodeValue.toArray().each( function(character) {
+          element.insertBefore(
+            new Element('span', {style: tagifyStyle}).update(
+              character == ' ' ? String.fromCharCode(160) : character),
+              child);
+        });
+        Element.remove(child);
+      }
+    });
+  },
+  multiple: function(element, effect) {
+    var elements;
+    if (((typeof element == 'object') ||
+        Object.isFunction(element)) &&
+       (element.length))
+      elements = element;
+    else
+      elements = $(element).childNodes;
+
+    var options = Object.extend({
+      speed: 0.1,
+      delay: 0.0
+    }, arguments[2] || { });
+    var masterDelay = options.delay;
+
+    $A(elements).each( function(element, index) {
+      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+    });
+  },
+  PAIRS: {
+    'slide':  ['SlideDown','SlideUp'],
+    'blind':  ['BlindDown','BlindUp'],
+    'appear': ['Appear','Fade']
+  },
+  toggle: function(element, effect) {
+    element = $(element);
+    effect = (effect || 'appear').toLowerCase();
+    var options = Object.extend({
+      queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+    }, arguments[2] || { });
+    Effect[element.visible() ?
+      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+  }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+  initialize: function() {
+    this.effects  = [];
+    this.interval = null;
+  },
+  _each: function(iterator) {
+    this.effects._each(iterator);
+  },
+  add: function(effect) {
+    var timestamp = new Date().getTime();
+
+    var position = Object.isString(effect.options.queue) ?
+      effect.options.queue : effect.options.queue.position;
+
+    switch(position) {
+      case 'front':
+        // move unstarted effects after this effect
+        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+            e.startOn  += effect.finishOn;
+            e.finishOn += effect.finishOn;
+          });
+        break;
+      case 'with-last':
+        timestamp = this.effects.pluck('startOn').max() || timestamp;
+        break;
+      case 'end':
+        // start effect after last queued effect has finished
+        timestamp = this.effects.pluck('finishOn').max() || timestamp;
+        break;
+    }
+
+    effect.startOn  += timestamp;
+    effect.finishOn += timestamp;
+
+    if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+      this.effects.push(effect);
+
+    if (!this.interval)
+      this.interval = setInterval(this.loop.bind(this), 15);
+  },
+  remove: function(effect) {
+    this.effects = this.effects.reject(function(e) { return e==effect });
+    if (this.effects.length == 0) {
+      clearInterval(this.interval);
+      this.interval = null;
+    }
+  },
+  loop: function() {
+    var timePos = new Date().getTime();
+    for(var i=0, len=this.effects.length;i<len;i++)
+      this.effects[i] && this.effects[i].loop(timePos);
+  }
+});
+
+Effect.Queues = {
+  instances: $H(),
+  get: function(queueName) {
+    if (!Object.isString(queueName)) return queueName;
+
+    return this.instances.get(queueName) ||
+      this.instances.set(queueName, new Effect.ScopedQueue());
+  }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+  position: null,
+  start: function(options) {
+    function codeForEvent(options,eventName){
+      return (
+        (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+        (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+      );
+    }
+    if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+    this.options      = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+    this.currentFrame = 0;
+    this.state        = 'idle';
+    this.startOn      = this.options.delay*1000;
+    this.finishOn     = this.startOn+(this.options.duration*1000);
+    this.fromToDelta  = this.options.to-this.options.from;
+    this.totalTime    = this.finishOn-this.startOn;
+    this.totalFrames  = this.options.fps*this.options.duration;
+
+    this.render = (function() {
+      function dispatch(effect, eventName) {
+        if (effect.options[eventName + 'Internal'])
+          effect.options[eventName + 'Internal'](effect);
+        if (effect.options[eventName])
+          effect.options[eventName](effect);
+      }
+
+      return function(pos) {
+        if (this.state === "idle") {
+          this.state = "running";
+          dispatch(this, 'beforeSetup');
+          if (this.setup) this.setup();
+          dispatch(this, 'afterSetup');
+        }
+        if (this.state === "running") {
+          pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
+          this.position = pos;
+          dispatch(this, 'beforeUpdate');
+          if (this.update) this.update(pos);
+          dispatch(this, 'afterUpdate');
+        }
+      };
+    })();
+
+    this.event('beforeStart');
+    if (!this.options.sync)
+      Effect.Queues.get(Object.isString(this.options.queue) ?
+        'global' : this.options.queue.scope).add(this);
+  },
+  loop: function(timePos) {
+    if (timePos >= this.startOn) {
+      if (timePos >= this.finishOn) {
+        this.render(1.0);
+        this.cancel();
+        this.event('beforeFinish');
+        if (this.finish) this.finish();
+        this.event('afterFinish');
+        return;
+      }
+      var pos   = (timePos - this.startOn) / this.totalTime,
+          frame = (pos * this.totalFrames).round();
+      if (frame > this.currentFrame) {
+        this.render(pos);
+        this.currentFrame = frame;
+      }
+    }
+  },
+  cancel: function() {
+    if (!this.options.sync)
+      Effect.Queues.get(Object.isString(this.options.queue) ?
+        'global' : this.options.queue.scope).remove(this);
+    this.state = 'finished';
+  },
+  event: function(eventName) {
+    if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+    if (this.options[eventName]) this.options[eventName](this);
+  },
+  inspect: function() {
+    var data = $H();
+    for(property in this)
+      if (!Object.isFunction(this[property])) data.set(property, this[property]);
+    return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+  }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+  initialize: function(effects) {
+    this.effects = effects || [];
+    this.start(arguments[1]);
+  },
+  update: function(position) {
+    this.effects.invoke('render', position);
+  },
+  finish: function(position) {
+    this.effects.each( function(effect) {
+      effect.render(1.0);
+      effect.cancel();
+      effect.event('beforeFinish');
+      if (effect.finish) effect.finish(position);
+      effect.event('afterFinish');
+    });
+  }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+  initialize: function(object, from, to) {
+    object = Object.isString(object) ? $(object) : object;
+    var args = $A(arguments), method = args.last(),
+      options = args.length == 5 ? args[3] : null;
+    this.method = Object.isFunction(method) ? method.bind(object) :
+      Object.isFunction(object[method]) ? object[method].bind(object) :
+      function(value) { object[method] = value };
+    this.start(Object.extend({ from: from, to: to }, options || { }));
+  },
+  update: function(position) {
+    this.method(position);
+  }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+  initialize: function() {
+    this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+  },
+  update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+  initialize: function(element) {
+    this.element = $(element);
+    if (!this.element) throw(Effect._elementDoesNotExistError);
+    // make this work on IE on elements without 'layout'
+    if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+      this.element.setStyle({zoom: 1});
+    var options = Object.extend({
+      from: this.element.getOpacity() || 0.0,
+      to:   1.0
+    }, arguments[1] || { });
+    this.start(options);
+  },
+  update: function(position) {
+    this.element.setOpacity(position);
+  }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+  initialize: function(element) {
+    this.element = $(element);
+    if (!this.element) throw(Effect._elementDoesNotExistError);
+    var options = Object.extend({
+      x:    0,
+      y:    0,
+      mode: 'relative'
+    }, arguments[1] || { });
+    this.start(options);
+  },
+  setup: function() {
+    this.element.makePositioned();
+    this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+    this.originalTop  = parseFloat(this.element.getStyle('top')  || '0');
+    if (this.options.mode == 'absolute') {
+      this.options.x = this.options.x - this.originalLeft;
+      this.options.y = this.options.y - this.originalTop;
+    }
+  },
+  update: function(position) {
+    this.element.setStyle({
+      left: (this.options.x  * position + this.originalLeft).round() + 'px',
+      top:  (this.options.y  * position + this.originalTop).round()  + 'px'
+    });
+  }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+  return new Effect.Move(element,
+    Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+  initialize: function(element, percent) {
+    this.element = $(element);
+    if (!this.element) throw(Effect._elementDoesNotExistError);
+    var options = Object.extend({
+      scaleX: true,
+      scaleY: true,
+      scaleContent: true,
+      scaleFromCenter: false,
+      scaleMode: 'box',        // 'box' or 'contents' or { } with provided values
+      scaleFrom: 100.0,
+      scaleTo:   percent
+    }, arguments[2] || { });
+    this.start(options);
+  },
+  setup: function() {
+    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+    this.elementPositioning = this.element.getStyle('position');
+
+    this.originalStyle = { };
+    ['top','left','width','height','fontSize'].each( function(k) {
+      this.originalStyle[k] = this.element.style[k];
+    }.bind(this));
+
+    this.originalTop  = this.element.offsetTop;
+    this.originalLeft = this.element.offsetLeft;
+
+    var fontSize = this.element.getStyle('font-size') || '100%';
+    ['em','px','%','pt'].each( function(fontSizeType) {
+      if (fontSize.indexOf(fontSizeType)>0) {
+        this.fontSize     = parseFloat(fontSize);
+        this.fontSizeType = fontSizeType;
+      }
+    }.bind(this));
+
+    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+    this.dims = null;
+    if (this.options.scaleMode=='box')
+      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+    if (/^content/.test(this.options.scaleMode))
+      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+    if (!this.dims)
+      this.dims = [this.options.scaleMode.originalHeight,
+                   this.options.scaleMode.originalWidth];
+  },
+  update: function(position) {
+    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+    if (this.options.scaleContent && this.fontSize)
+      this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+  },
+  finish: function(position) {
+    if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+  },
+  setDimensions: function(height, width) {
+    var d = { };
+    if (this.options.scaleX) d.width = width.round() + 'px';
+    if (this.options.scaleY) d.height = height.round() + 'px';
+    if (this.options.scaleFromCenter) {
+      var topd  = (height - this.dims[0])/2;
+      var leftd = (width  - this.dims[1])/2;
+      if (this.elementPositioning == 'absolute') {
+        if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+        if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+      } else {
+        if (this.options.scaleY) d.top = -topd + 'px';
+        if (this.options.scaleX) d.left = -leftd + 'px';
+      }
+    }
+    this.element.setStyle(d);
+  }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+  initialize: function(element) {
+    this.element = $(element);
+    if (!this.element) throw(Effect._elementDoesNotExistError);
+    var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+    this.start(options);
+  },
+  setup: function() {
+    // Prevent executing on elements not in the layout flow
+    if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+    // Disable background image during the effect
+    this.oldStyle = { };
+    if (!this.options.keepBackgroundImage) {
+      this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+      this.element.setStyle({backgroundImage: 'none'});
+    }
+    if (!this.options.endcolor)
+      this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+    if (!this.options.restorecolor)
+      this.options.restorecolor = this.element.getStyle('background-color');
+    // init color calculations
+    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+    this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+  },
+  update: function(position) {
+    this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+      return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+  },
+  finish: function() {
+    this.element.setStyle(Object.extend(this.oldStyle, {
+      backgroundColor: this.options.restorecolor
+    }));
+  }
+});
+
+Effect.ScrollTo = function(element) {
+  var options = arguments[1] || { },
+  scrollOffsets = document.viewport.getScrollOffsets(),
+  elementOffsets = $(element).cumulativeOffset();
+
+  if (options.offset) elementOffsets[1] += options.offset;
+
+  return new Effect.Tween(null,
+    scrollOffsets.top,
+    elementOffsets[1],
+    options,
+    function(p){ scrollTo(scrollOffsets.left, p.round()); }
+  );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+  element = $(element);
+  var oldOpacity = element.getInlineOpacity();
+  var options = Object.extend({
+    from: element.getOpacity() || 1.0,
+    to:   0.0,
+    afterFinishInternal: function(effect) {
+      if (effect.options.to!=0) return;
+      effect.element.hide().setStyle({opacity: oldOpacity});
+    }
+  }, arguments[1] || { });
+  return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+  element = $(element);
+  var options = Object.extend({
+  from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+  to:   1.0,
+  // force Safari to render floated elements properly
+  afterFinishInternal: function(effect) {
+    effect.element.forceRerendering();
+  },
+  beforeSetup: function(effect) {
+    effect.element.setOpacity(effect.options.from).show();
+  }}, arguments[1] || { });
+  return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+  element = $(element);
+  var oldStyle = {
+    opacity: element.getInlineOpacity(),
+    position: element.getStyle('position'),
+    top:  element.style.top,
+    left: element.style.left,
+    width: element.style.width,
+    height: element.style.height
+  };
+  return new Effect.Parallel(
+   [ new Effect.Scale(element, 200,
+      { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+     new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+     Object.extend({ duration: 1.0,
+      beforeSetupInternal: function(effect) {
+        Position.absolutize(effect.effects[0].element);
+      },
+      afterFinishInternal: function(effect) {
+         effect.effects[0].element.hide().setStyle(oldStyle); }
+     }, arguments[1] || { })
+   );
+};
+
+Effect.BlindUp = function(element) {
+  element = $(element);
+  element.makeClipping();
+  return new Effect.Scale(element, 0,
+    Object.extend({ scaleContent: false,
+      scaleX: false,
+      restoreAfterFinish: true,
+      afterFinishInternal: function(effect) {
+        effect.element.hide().undoClipping();
+      }
+    }, arguments[1] || { })
+  );
+};
+
+Effect.BlindDown = function(element) {
+  element = $(element);
+  var elementDimensions = element.getDimensions();
+  return new Effect.Scale(element, 100, Object.extend({
+    scaleContent: false,
+    scaleX: false,
+    scaleFrom: 0,
+    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+    restoreAfterFinish: true,
+    afterSetup: function(effect) {
+      effect.element.makeClipping().setStyle({height: '0px'}).show();
+    },
+    afterFinishInternal: function(effect) {
+      effect.element.undoClipping();
+    }
+  }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+  element = $(element);
+  var oldOpacity = element.getInlineOpacity();
+  return new Effect.Appear(element, Object.extend({
+    duration: 0.4,
+    from: 0,
+    transition: Effect.Transitions.flicker,
+    afterFinishInternal: function(effect) {
+      new Effect.Scale(effect.element, 1, {
+        duration: 0.3, scaleFromCenter: true,
+        scaleX: false, scaleContent: false, restoreAfterFinish: true,
+        beforeSetup: function(effect) {
+          effect.element.makePositioned().makeClipping();
+        },
+        afterFinishInternal: function(effect) {
+          effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+        }
+      });
+    }
+  }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+  element = $(element);
+  var oldStyle = {
+    top: element.getStyle('top'),
+    left: element.getStyle('left'),
+    opacity: element.getInlineOpacity() };
+  return new Effect.Parallel(
+    [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+      new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+    Object.extend(
+      { duration: 0.5,
+        beforeSetup: function(effect) {
+          effect.effects[0].element.makePositioned();
+        },
+        afterFinishInternal: function(effect) {
+          effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+        }
+      }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+  element = $(element);
+  var options = Object.extend({
+    distance: 20,
+    duration: 0.5
+  }, arguments[1] || {});
+  var distance = parseFloat(options.distance);
+  var split = parseFloat(options.duration) / 10.0;
+  var oldStyle = {
+    top: element.getStyle('top'),
+    left: element.getStyle('left') };
+    return new Effect.Move(element,
+      { x:  distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x: -distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x:  distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x: -distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x:  distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+        effect.element.undoPositioned().setStyle(oldStyle);
+  }}); }}); }}); }}); }}); }});
+};
+
+Effect.SlideDown = function(element) {
+  element = $(element).cleanWhitespace();
+  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+  var oldInnerBottom = element.down().getStyle('bottom');
+  var elementDimensions = element.getDimensions();
+  return new Effect.Scale(element, 100, Object.extend({
+    scaleContent: false,
+    scaleX: false,
+    scaleFrom: window.opera ? 0 : 1,
+    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+    restoreAfterFinish: true,
+    afterSetup: function(effect) {
+      effect.element.makePositioned();
+      effect.element.down().makePositioned();
+      if (window.opera) effect.element.setStyle({top: ''});
+      effect.element.makeClipping().setStyle({height: '0px'}).show();
+    },
+    afterUpdateInternal: function(effect) {
+      effect.element.down().setStyle({bottom:
+        (effect.dims[0] - effect.element.clientHeight) + 'px' });
+    },
+    afterFinishInternal: function(effect) {
+      effect.element.undoClipping().undoPositioned();
+      effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+    }, arguments[1] || { })
+  );
+};
+
+Effect.SlideUp = function(element) {
+  element = $(element).cleanWhitespace();
+  var oldInnerBottom = element.down().getStyle('bottom');
+  var elementDimensions = element.getDimensions();
+  return new Effect.Scale(element, window.opera ? 0 : 1,
+   Object.extend({ scaleContent: false,
+    scaleX: false,
+    scaleMode: 'box',
+    scaleFrom: 100,
+    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+    restoreAfterFinish: true,
+    afterSetup: function(effect) {
+      effect.element.makePositioned();
+      effect.element.down().makePositioned();
+      if (window.opera) effect.element.setStyle({top: ''});
+      effect.element.makeClipping().show();
+    },
+    afterUpdateInternal: function(effect) {
+      effect.element.down().setStyle({bottom:
+        (effect.dims[0] - effect.element.clientHeight) + 'px' });
+    },
+    afterFinishInternal: function(effect) {
+      effect.element.hide().undoClipping().undoPositioned();
+      effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+    }
+   }, arguments[1] || { })
+  );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+  return new Effect.Scale(element, window.opera ? 1 : 0, {
+    restoreAfterFinish: true,
+    beforeSetup: function(effect) {
+      effect.element.makeClipping();
+    },
+    afterFinishInternal: function(effect) {
+      effect.element.hide().undoClipping();
+    }
+  });
+};
+
+Effect.Grow = function(element) {
+  element = $(element);
+  var options = Object.extend({
+    direction: 'center',
+    moveTransition: Effect.Transitions.sinoidal,
+    scaleTransition: Effect.Transitions.sinoidal,
+    opacityTransition: Effect.Transitions.full
+  }, arguments[1] || { });
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    height: element.style.height,
+    width: element.style.width,
+    opacity: element.getInlineOpacity() };
+
+  var dims = element.getDimensions();
+  var initialMoveX, initialMoveY;
+  var moveX, moveY;
+
+  switch (options.direction) {
+    case 'top-left':
+      initialMoveX = initialMoveY = moveX = moveY = 0;
+      break;
+    case 'top-right':
+      initialMoveX = dims.width;
+      initialMoveY = moveY = 0;
+      moveX = -dims.width;
+      break;
+    case 'bottom-left':
+      initialMoveX = moveX = 0;
+      initialMoveY = dims.height;
+      moveY = -dims.height;
+      break;
+    case 'bottom-right':
+      initialMoveX = dims.width;
+      initialMoveY = dims.height;
+      moveX = -dims.width;
+      moveY = -dims.height;
+      break;
+    case 'center':
+      initialMoveX = dims.width / 2;
+      initialMoveY = dims.height / 2;
+      moveX = -dims.width / 2;
+      moveY = -dims.height / 2;
+      break;
+  }
+
+  return new Effect.Move(element, {
+    x: initialMoveX,
+    y: initialMoveY,
+    duration: 0.01,
+    beforeSetup: function(effect) {
+      effect.element.hide().makeClipping().makePositioned();
+    },
+    afterFinishInternal: function(effect) {
+      new Effect.Parallel(
+        [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+          new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+          new Effect.Scale(effect.element, 100, {
+            scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+            sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+        ], Object.extend({
+             beforeSetup: function(effect) {
+               effect.effects[0].element.setStyle({height: '0px'}).show();
+             },
+             afterFinishInternal: function(effect) {
+               effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+             }
+           }, options)
+      );
+    }
+  });
+};
+
+Effect.Shrink = function(element) {
+  element = $(element);
+  var options = Object.extend({
+    direction: 'center',
+    moveTransition: Effect.Transitions.sinoidal,
+    scaleTransition: Effect.Transitions.sinoidal,
+    opacityTransition: Effect.Transitions.none
+  }, arguments[1] || { });
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    height: element.style.height,
+    width: element.style.width,
+    opacity: element.getInlineOpacity() };
+
+  var dims = element.getDimensions();
+  var moveX, moveY;
+
+  switch (options.direction) {
+    case 'top-left':
+      moveX = moveY = 0;
+      break;
+    case 'top-right':
+      moveX = dims.width;
+      moveY = 0;
+      break;
+    case 'bottom-left':
+      moveX = 0;
+      moveY = dims.height;
+      break;
+    case 'bottom-right':
+      moveX = dims.width;
+      moveY = dims.height;
+      break;
+    case 'center':
+      moveX = dims.width / 2;
+      moveY = dims.height / 2;
+      break;
+  }
+
+  return new Effect.Parallel(
+    [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+      new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+      new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+    ], Object.extend({
+         beforeStartInternal: function(effect) {
+           effect.effects[0].element.makePositioned().makeClipping();
+         },
+         afterFinishInternal: function(effect) {
+           effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+       }, options)
+  );
+};
+
+Effect.Pulsate = function(element) {
+  element = $(element);
+  var options    = arguments[1] || { },
+    oldOpacity = element.getInlineOpacity(),
+    transition = options.transition || Effect.Transitions.linear,
+    reverser   = function(pos){
+      return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5);
+    };
+
+  return new Effect.Opacity(element,
+    Object.extend(Object.extend({  duration: 2.0, from: 0,
+      afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+    }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+  element = $(element);
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    width: element.style.width,
+    height: element.style.height };
+  element.makeClipping();
+  return new Effect.Scale(element, 5, Object.extend({
+    scaleContent: false,
+    scaleX: false,
+    afterFinishInternal: function(effect) {
+    new Effect.Scale(element, 1, {
+      scaleContent: false,
+      scaleY: false,
+      afterFinishInternal: function(effect) {
+        effect.element.hide().undoClipping().setStyle(oldStyle);
+      } });
+  }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+  initialize: function(element) {
+    this.element = $(element);
+    if (!this.element) throw(Effect._elementDoesNotExistError);
+    var options = Object.extend({
+      style: { }
+    }, arguments[1] || { });
+
+    if (!Object.isString(options.style)) this.style = $H(options.style);
+    else {
+      if (options.style.include(':'))
+        this.style = options.style.parseStyle();
+      else {
+        this.element.addClassName(options.style);
+        this.style = $H(this.element.getStyles());
+        this.element.removeClassName(options.style);
+        var css = this.element.getStyles();
+        this.style = this.style.reject(function(style) {
+          return style.value == css[style.key];
+        });
+        options.afterFinishInternal = function(effect) {
+          effect.element.addClassName(effect.options.style);
+          effect.transforms.each(function(transform) {
+            effect.element.style[transform.style] = '';
+          });
+        };
+      }
+    }
+    this.start(options);
+  },
+
+  setup: function(){
+    function parseColor(color){
+      if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+      color = color.parseColor();
+      return $R(0,2).map(function(i){
+        return parseInt( color.slice(i*2+1,i*2+3), 16 );
+      });
+    }
+    this.transforms = this.style.map(function(pair){
+      var property = pair[0], value = pair[1], unit = null;
+
+      if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+        value = value.parseColor();
+        unit  = 'color';
+      } else if (property == 'opacity') {
+        value = parseFloat(value);
+        if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+          this.element.setStyle({zoom: 1});
+      } else if (Element.CSS_LENGTH.test(value)) {
+          var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+          value = parseFloat(components[1]);
+          unit = (components.length == 3) ? components[2] : null;
+      }
+
+      var originalValue = this.element.getStyle(property);
+      return {
+        style: property.camelize(),
+        originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+        targetValue: unit=='color' ? parseColor(value) : value,
+        unit: unit
+      };
+    }.bind(this)).reject(function(transform){
+      return (
+        (transform.originalValue == transform.targetValue) ||
+        (
+          transform.unit != 'color' &&
+          (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+        )
+      );
+    });
+  },
+  update: function(position) {
+    var style = { }, transform, i = this.transforms.length;
+    while(i--)
+      style[(transform = this.transforms[i]).style] =
+        transform.unit=='color' ? '#'+
+          (Math.round(transform.originalValue[0]+
+            (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+          (Math.round(transform.originalValue[1]+
+            (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+          (Math.round(transform.originalValue[2]+
+            (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+        (transform.originalValue +
+          (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+            (transform.unit === null ? '' : transform.unit);
+    this.element.setStyle(style, true);
+  }
+});
+
+Effect.Transform = Class.create({
+  initialize: function(tracks){
+    this.tracks  = [];
+    this.options = arguments[1] || { };
+    this.addTracks(tracks);
+  },
+  addTracks: function(tracks){
+    tracks.each(function(track){
+      track = $H(track);
+      var data = track.values().first();
+      this.tracks.push($H({
+        ids:     track.keys().first(),
+        effect:  Effect.Morph,
+        options: { style: data }
+      }));
+    }.bind(this));
+    return this;
+  },
+  play: function(){
+    return new Effect.Parallel(
+      this.tracks.map(function(track){
+        var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+        var elements = [$(ids) || $$(ids)].flatten();
+        return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+      }).flatten(),
+      this.options
+    );
+  }
+});
+
+Element.CSS_PROPERTIES = $w(
+  'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+  'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+  'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+  'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+  'fontSize fontWeight height left letterSpacing lineHeight ' +
+  'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+  'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+  'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+  'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+  var style, styleRules = $H();
+  if (Prototype.Browser.WebKit)
+    style = new Element('div',{style:this}).style;
+  else {
+    String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+    style = String.__parseStyleElement.childNodes[0].style;
+  }
+
+  Element.CSS_PROPERTIES.each(function(property){
+    if (style[property]) styleRules.set(property, style[property]);
+  });
+
+  if (Prototype.Browser.IE && this.include('opacity'))
+    styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+  return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+  Element.getStyles = function(element) {
+    var css = document.defaultView.getComputedStyle($(element), null);
+    return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+      styles[property] = css[property];
+      return styles;
+    });
+  };
+} else {
+  Element.getStyles = function(element) {
+    element = $(element);
+    var css = element.currentStyle, styles;
+    styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+      results[property] = css[property];
+      return results;
+    });
+    if (!styles.opacity) styles.opacity = element.getOpacity();
+    return styles;
+  };
+}
+
+Effect.Methods = {
+  morph: function(element, style) {
+    element = $(element);
+    new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+    return element;
+  },
+  visualEffect: function(element, effect, options) {
+    element = $(element);
+    var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+    new Effect[klass](element, options);
+    return element;
+  },
+  highlight: function(element, options) {
+    element = $(element);
+    new Effect.Highlight(element, options);
+    return element;
+  }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+  'pulsate shake puff squish switchOff dropOut').each(
+  function(effect) {
+    Effect.Methods[effect] = function(element, options){
+      element = $(element);
+      Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+      return element;
+    };
+  }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+  function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/web/js/index.html	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,4 @@
+<html>
+<body>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/web/js/prototype.js	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,4320 @@
+/*  Prototype JavaScript framework, version 1.6.0.3
+ *  (c) 2005-2008 Sam Stephenson
+ *
+ *  Prototype is freely distributable under the terms of an MIT-style license.
+ *  For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+  Version: '1.6.0.3',
+
+  Browser: {
+    IE:     !!(window.attachEvent &&
+      navigator.userAgent.indexOf('Opera') === -1),
+    Opera:  navigator.userAgent.indexOf('Opera') > -1,
+    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 &&
+      navigator.userAgent.indexOf('KHTML') === -1,
+    MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+  },
+
+  BrowserFeatures: {
+    XPath: !!document.evaluate,
+    SelectorsAPI: !!document.querySelector,
+    ElementExtensions: !!window.HTMLElement,
+    SpecificElementExtensions:
+      document.createElement('div')['__proto__'] &&
+      document.createElement('div')['__proto__'] !==
+        document.createElement('form')['__proto__']
+  },
+
+  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+  emptyFunction: function() { },
+  K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+  Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+  create: function() {
+    var parent = null, properties = $A(arguments);
+    if (Object.isFunction(properties[0]))
+      parent = properties.shift();
+
+    function klass() {
+      this.initialize.apply(this, arguments);
+    }
+
+    Object.extend(klass, Class.Methods);
+    klass.superclass = parent;
+    klass.subclasses = [];
+
+    if (parent) {
+      var subclass = function() { };
+      subclass.prototype = parent.prototype;
+      klass.prototype = new subclass;
+      parent.subclasses.push(klass);
+    }
+
+    for (var i = 0; i < properties.length; i++)
+      klass.addMethods(properties[i]);
+
+    if (!klass.prototype.initialize)
+      klass.prototype.initialize = Prototype.emptyFunction;
+
+    klass.prototype.constructor = klass;
+
+    return klass;
+  }
+};
+
+Class.Methods = {
+  addMethods: function(source) {
+    var ancestor   = this.superclass && this.superclass.prototype;
+    var properties = Object.keys(source);
+
+    if (!Object.keys({ toString: true }).length)
+      properties.push("toString", "valueOf");
+
+    for (var i = 0, length = properties.length; i < length; i++) {
+      var property = properties[i], value = source[property];
+      if (ancestor && Object.isFunction(value) &&
+          value.argumentNames().first() == "$super") {
+        var method = value;
+        value = (function(m) {
+          return function() { return ancestor[m].apply(this, arguments) };
+        })(property).wrap(method);
+
+        value.valueOf = method.valueOf.bind(method);
+        value.toString = method.toString.bind(method);
+      }
+      this.prototype[property] = value;
+    }
+
+    return this;
+  }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+  for (var property in source)
+    destination[property] = source[property];
+  return destination;
+};
+
+Object.extend(Object, {
+  inspect: function(object) {
+    try {
+      if (Object.isUndefined(object)) return 'undefined';
+      if (object === null) return 'null';
+      return object.inspect ? object.inspect() : String(object);
+    } catch (e) {
+      if (e instanceof RangeError) return '...';
+      throw e;
+    }
+  },
+
+  toJSON: function(object) {
+    var type = typeof object;
+    switch (type) {
+      case 'undefined':
+      case 'function':
+      case 'unknown': return;
+      case 'boolean': return object.toString();
+    }
+
+    if (object === null) return 'null';
+    if (object.toJSON) return object.toJSON();
+    if (Object.isElement(object)) return;
+
+    var results = [];
+    for (var property in object) {
+      var value = Object.toJSON(object[property]);
+      if (!Object.isUndefined(value))
+        results.push(property.toJSON() + ': ' + value);
+    }
+
+    return '{' + results.join(', ') + '}';
+  },
+
+  toQueryString: function(object) {
+    return $H(object).toQueryString();
+  },
+
+  toHTML: function(object) {
+    return object && object.toHTML ? object.toHTML() : String.interpret(object);
+  },
+
+  keys: function(object) {
+    var keys = [];
+    for (var property in object)
+      keys.push(property);
+    return keys;
+  },
+
+  values: function(object) {
+    var values = [];
+    for (var property in object)
+      values.push(object[property]);
+    return values;
+  },
+
+  clone: function(object) {
+    return Object.extend({ }, object);
+  },
+
+  isElement: function(object) {
+    return !!(object && object.nodeType == 1);
+  },
+
+  isArray: function(object) {
+    return object != null && typeof object == "object" &&
+      'splice' in object && 'join' in object;
+  },
+
+  isHash: function(object) {
+    return object instanceof Hash;
+  },
+
+  isFunction: function(object) {
+    return typeof object == "function";
+  },
+
+  isString: function(object) {
+    return typeof object == "string";
+  },
+
+  isNumber: function(object) {
+    return typeof object == "number";
+  },
+
+  isUndefined: function(object) {
+    return typeof object == "undefined";
+  }
+});
+
+Object.extend(Function.prototype, {
+  argumentNames: function() {
+    var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
+      .replace(/\s+/g, '').split(',');
+    return names.length == 1 && !names[0] ? [] : names;
+  },
+
+  bind: function() {
+    if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+    var __method = this, args = $A(arguments), object = args.shift();
+    return function() {
+      return __method.apply(object, args.concat($A(arguments)));
+    }
+  },
+
+  bindAsEventListener: function() {
+    var __method = this, args = $A(arguments), object = args.shift();
+    return function(event) {
+      return __method.apply(object, [event || window.event].concat(args));
+    }
+  },
+
+  curry: function() {
+    if (!arguments.length) return this;
+    var __method = this, args = $A(arguments);
+    return function() {
+      return __method.apply(this, args.concat($A(arguments)));
+    }
+  },
+
+  delay: function() {
+    var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+    return window.setTimeout(function() {
+      return __method.apply(__method, args);
+    }, timeout);
+  },
+
+  defer: function() {
+    var args = [0.01].concat($A(arguments));
+    return this.delay.apply(this, args);
+  },
+
+  wrap: function(wrapper) {
+    var __method = this;
+    return function() {
+      return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+    }
+  },
+
+  methodize: function() {
+    if (this._methodized) return this._methodized;
+    var __method = this;
+    return this._methodized = function() {
+      return __method.apply(null, [this].concat($A(arguments)));
+    };
+  }
+});
+
+Date.prototype.toJSON = function() {
+  return '"' + this.getUTCFullYear() + '-' +
+    (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+    this.getUTCDate().toPaddedString(2) + 'T' +
+    this.getUTCHours().toPaddedString(2) + ':' +
+    this.getUTCMinutes().toPaddedString(2) + ':' +
+    this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+  these: function() {
+    var returnValue;
+
+    for (var i = 0, length = arguments.length; i < length; i++) {
+      var lambda = arguments[i];
+      try {
+        returnValue = lambda();
+        break;
+      } catch (e) { }
+    }
+
+    return returnValue;
+  }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+  initialize: function(callback, frequency) {
+    this.callback = callback;
+    this.frequency = frequency;
+    this.currentlyExecuting = false;
+
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  execute: function() {
+    this.callback(this);
+  },
+
+  stop: function() {
+    if (!this.timer) return;
+    clearInterval(this.timer);
+    this.timer = null;
+  },
+
+  onTimerEvent: function() {
+    if (!this.currentlyExecuting) {
+      try {
+        this.currentlyExecuting = true;
+        this.execute();
+      } finally {
+        this.currentlyExecuting = false;
+      }
+    }
+  }
+});
+Object.extend(String, {
+  interpret: function(value) {
+    return value == null ? '' : String(value);
+  },
+  specialChar: {
+    '\b': '\\b',
+    '\t': '\\t',
+    '\n': '\\n',
+    '\f': '\\f',
+    '\r': '\\r',
+    '\\': '\\\\'
+  }
+});
+
+Object.extend(String.prototype, {
+  gsub: function(pattern, replacement) {
+    var result = '', source = this, match;
+    replacement = arguments.callee.prepareReplacement(replacement);
+
+    while (source.length > 0) {
+      if (match = source.match(pattern)) {
+        result += source.slice(0, match.index);
+        result += String.interpret(replacement(match));
+        source  = source.slice(match.index + match[0].length);
+      } else {
+        result += source, source = '';
+      }
+    }
+    return result;
+  },
+
+  sub: function(pattern, replacement, count) {
+    replacement = this.gsub.prepareReplacement(replacement);
+    count = Object.isUndefined(count) ? 1 : count;
+
+    return this.gsub(pattern, function(match) {
+      if (--count < 0) return match[0];
+      return replacement(match);
+    });
+  },
+
+  scan: function(pattern, iterator) {
+    this.gsub(pattern, iterator);
+    return String(this);
+  },
+
+  truncate: function(length, truncation) {
+    length = length || 30;
+    truncation = Object.isUndefined(truncation) ? '...' : truncation;
+    return this.length > length ?
+      this.slice(0, length - truncation.length) + truncation : String(this);
+  },
+
+  strip: function() {
+    return this.replace(/^\s+/, '').replace(/\s+$/, '');
+  },
+
+  stripTags: function() {
+    return this.replace(/<\/?[^>]+>/gi, '');
+  },
+
+  stripScripts: function() {
+    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+  },
+
+  extractScripts: function() {
+    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+    return (this.match(matchAll) || []).map(function(scriptTag) {
+      return (scriptTag.match(matchOne) || ['', ''])[1];
+    });
+  },
+
+  evalScripts: function() {
+    return this.extractScripts().map(function(script) { return eval(script) });
+  },
+
+  escapeHTML: function() {
+    var self = arguments.callee;
+    self.text.data = this;
+    return self.div.innerHTML;
+  },
+
+  unescapeHTML: function() {
+    var div = new Element('div');
+    div.innerHTML = this.stripTags();
+    return div.childNodes[0] ? (div.childNodes.length > 1 ?
+      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+      div.childNodes[0].nodeValue) : '';
+  },
+
+  toQueryParams: function(separator) {
+    var match = this.strip().match(/([^?#]*)(#.*)?$/);
+    if (!match) return { };
+
+    return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+      if ((pair = pair.split('='))[0]) {
+        var key = decodeURIComponent(pair.shift());
+        var value = pair.length > 1 ? pair.join('=') : pair[0];
+        if (value != undefined) value = decodeURIComponent(value);
+
+        if (key in hash) {
+          if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+          hash[key].push(value);
+        }
+        else hash[key] = value;
+      }
+      return hash;
+    });
+  },
+
+  toArray: function() {
+    return this.split('');
+  },
+
+  succ: function() {
+    return this.slice(0, this.length - 1) +
+      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+  },
+
+  times: function(count) {
+    return count < 1 ? '' : new Array(count + 1).join(this);
+  },
+
+  camelize: function() {
+    var parts = this.split('-'), len = parts.length;
+    if (len == 1) return parts[0];
+
+    var camelized = this.charAt(0) == '-'
+      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+      : parts[0];
+
+    for (var i = 1; i < len; i++)
+      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+    return camelized;
+  },
+
+  capitalize: function() {
+    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+  },
+
+  underscore: function() {
+    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+  },
+
+  dasherize: function() {
+    return this.gsub(/_/,'-');
+  },
+
+  inspect: function(useDoubleQuotes) {
+    var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+      var character = String.specialChar[match[0]];
+      return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+    });
+    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+  },
+
+  toJSON: function() {
+    return this.inspect(true);
+  },
+
+  unfilterJSON: function(filter) {
+    return this.sub(filter || Prototype.JSONFilter, '#{1}');
+  },
+
+  isJSON: function() {
+    var str = this;
+    if (str.blank()) return false;
+    str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+  },
+
+  evalJSON: function(sanitize) {
+    var json = this.unfilterJSON();
+    try {
+      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+    } catch (e) { }
+    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+  },
+
+  include: function(pattern) {
+    return this.indexOf(pattern) > -1;
+  },
+
+  startsWith: function(pattern) {
+    return this.indexOf(pattern) === 0;
+  },
+
+  endsWith: function(pattern) {
+    var d = this.length - pattern.length;
+    return d >= 0 && this.lastIndexOf(pattern) === d;
+  },
+
+  empty: function() {
+    return this == '';
+  },
+
+  blank: function() {
+    return /^\s*$/.test(this);
+  },
+
+  interpolate: function(object, pattern) {
+    return new Template(this, pattern).evaluate(object);
+  }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+  escapeHTML: function() {
+    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+  },
+  unescapeHTML: function() {
+    return this.stripTags().replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+  }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+  if (Object.isFunction(replacement)) return replacement;
+  var template = new Template(replacement);
+  return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+  div:  document.createElement('div'),
+  text: document.createTextNode('')
+});
+
+String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);
+
+var Template = Class.create({
+  initialize: function(template, pattern) {
+    this.template = template.toString();
+    this.pattern = pattern || Template.Pattern;
+  },
+
+  evaluate: function(object) {
+    if (Object.isFunction(object.toTemplateReplacements))
+      object = object.toTemplateReplacements();
+
+    return this.template.gsub(this.pattern, function(match) {
+      if (object == null) return '';
+
+      var before = match[1] || '';
+      if (before == '\\') return match[2];
+
+      var ctx = object, expr = match[3];
+      var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+      match = pattern.exec(expr);
+      if (match == null) return before;
+
+      while (match != null) {
+        var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+        ctx = ctx[comp];
+        if (null == ctx || '' == match[3]) break;
+        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+        match = pattern.exec(expr);
+      }
+
+      return before + String.interpret(ctx);
+    });
+  }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+  each: function(iterator, context) {
+    var index = 0;
+    try {
+      this._each(function(value) {
+        iterator.call(context, value, index++);
+      });
+    } catch (e) {
+      if (e != $break) throw e;
+    }
+    return this;
+  },
+
+  eachSlice: function(number, iterator, context) {
+    var index = -number, slices = [], array = this.toArray();
+    if (number < 1) return array;
+    while ((index += number) < array.length)
+      slices.push(array.slice(index, index+number));
+    return slices.collect(iterator, context);
+  },
+
+  all: function(iterator, context) {
+    iterator = iterator || Prototype.K;
+    var result = true;
+    this.each(function(value, index) {
+      result = result && !!iterator.call(context, value, index);
+      if (!result) throw $break;
+    });
+    return result;
+  },
+
+  any: function(iterator, context) {
+    iterator = iterator || Prototype.K;
+    var result = false;
+    this.each(function(value, index) {
+      if (result = !!iterator.call(context, value, index))
+        throw $break;
+    });
+    return result;
+  },
+
+  collect: function(iterator, context) {
+    iterator = iterator || Prototype.K;
+    var results = [];
+    this.each(function(value, index) {
+      results.push(iterator.call(context, value, index));
+    });
+    return results;
+  },
+
+  detect: function(iterator, context) {
+    var result;
+    this.each(function(value, index) {
+      if (iterator.call(context, value, index)) {
+        result = value;
+        throw $break;
+      }
+    });
+    return result;
+  },
+
+  findAll: function(iterator, context) {
+    var results = [];
+    this.each(function(value, index) {
+      if (iterator.call(context, value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  grep: function(filter, iterator, context) {
+    iterator = iterator || Prototype.K;
+    var results = [];
+
+    if (Object.isString(filter))
+      filter = new RegExp(filter);
+
+    this.each(function(value, index) {
+      if (filter.match(value))
+        results.push(iterator.call(context, value, index));
+    });
+    return results;
+  },
+
+  include: function(object) {
+    if (Object.isFunction(this.indexOf))
+      if (this.indexOf(object) != -1) return true;
+
+    var found = false;
+    this.each(function(value) {
+      if (value == object) {
+        found = true;
+        throw $break;
+      }
+    });
+    return found;
+  },
+
+  inGroupsOf: function(number, fillWith) {
+    fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+    return this.eachSlice(number, function(slice) {
+      while(slice.length < number) slice.push(fillWith);
+      return slice;
+    });
+  },
+
+  inject: function(memo, iterator, context) {
+    this.each(function(value, index) {
+      memo = iterator.call(context, memo, value, index);
+    });
+    return memo;
+  },
+
+  invoke: function(method) {
+    var args = $A(arguments).slice(1);
+    return this.map(function(value) {
+      return value[method].apply(value, args);
+    });
+  },
+
+  max: function(iterator, context) {
+    iterator = iterator || Prototype.K;
+    var result;
+    this.each(function(value, index) {
+      value = iterator.call(context, value, index);
+      if (result == null || value >= result)
+        result = value;
+    });
+    return result;
+  },
+
+  min: function(iterator, context) {
+    iterator = iterator || Prototype.K;
+    var result;
+    this.each(function(value, index) {
+      value = iterator.call(context, value, index);
+      if (result == null || value < result)
+        result = value;
+    });
+    return result;
+  },
+
+  partition: function(iterator, context) {
+    iterator = iterator || Prototype.K;
+    var trues = [], falses = [];
+    this.each(function(value, index) {
+      (iterator.call(context, value, index) ?
+        trues : falses).push(value);
+    });
+    return [trues, falses];
+  },
+
+  pluck: function(property) {
+    var results = [];
+    this.each(function(value) {
+      results.push(value[property]);
+    });
+    return results;
+  },
+
+  reject: function(iterator, context) {
+    var results = [];
+    this.each(function(value, index) {
+      if (!iterator.call(context, value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  sortBy: function(iterator, context) {
+    return this.map(function(value, index) {
+      return {
+        value: value,
+        criteria: iterator.call(context, value, index)
+      };
+    }).sort(function(left, right) {
+      var a = left.criteria, b = right.criteria;
+      return a < b ? -1 : a > b ? 1 : 0;
+    }).pluck('value');
+  },
+
+  toArray: function() {
+    return this.map();
+  },
+
+  zip: function() {
+    var iterator = Prototype.K, args = $A(arguments);
+    if (Object.isFunction(args.last()))
+      iterator = args.pop();
+
+    var collections = [this].concat(args).map($A);
+    return this.map(function(value, index) {
+      return iterator(collections.pluck(index));
+    });
+  },
+
+  size: function() {
+    return this.toArray().length;
+  },
+
+  inspect: function() {
+    return '#<Enumerable:' + this.toArray().inspect() + '>';
+  }
+};
+
+Object.extend(Enumerable, {
+  map:     Enumerable.collect,
+  find:    Enumerable.detect,
+  select:  Enumerable.findAll,
+  filter:  Enumerable.findAll,
+  member:  Enumerable.include,
+  entries: Enumerable.toArray,
+  every:   Enumerable.all,
+  some:    Enumerable.any
+});
+function $A(iterable) {
+  if (!iterable) return [];
+  if (iterable.toArray) return iterable.toArray();
+  var length = iterable.length || 0, results = new Array(length);
+  while (length--) results[length] = iterable[length];
+  return results;
+}
+
+if (Prototype.Browser.WebKit) {
+  $A = function(iterable) {
+    if (!iterable) return [];
+    // In Safari, only use the `toArray` method if it's not a NodeList.
+    // A NodeList is a function, has an function `item` property, and a numeric
+    // `length` property. Adapted from Google Doctype.
+    if (!(typeof iterable === 'function' && typeof iterable.length ===
+        'number' && typeof iterable.item === 'function') && iterable.toArray)
+      return iterable.toArray();
+    var length = iterable.length || 0, results = new Array(length);
+    while (length--) results[length] = iterable[length];
+    return results;
+  };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+  _each: function(iterator) {
+    for (var i = 0, length = this.length; i < length; i++)
+      iterator(this[i]);
+  },
+
+  clear: function() {
+    this.length = 0;
+    return this;
+  },
+
+  first: function() {
+    return this[0];
+  },
+
+  last: function() {
+    return this[this.length - 1];
+  },
+
+  compact: function() {
+    return this.select(function(value) {
+      return value != null;
+    });
+  },
+
+  flatten: function() {
+    return this.inject([], function(array, value) {
+      return array.concat(Object.isArray(value) ?
+        value.flatten() : [value]);
+    });
+  },
+
+  without: function() {
+    var values = $A(arguments);
+    return this.select(function(value) {
+      return !values.include(value);
+    });
+  },
+
+  reverse: function(inline) {
+    return (inline !== false ? this : this.toArray())._reverse();
+  },
+
+  reduce: function() {
+    return this.length > 1 ? this : this[0];
+  },
+
+  uniq: function(sorted) {
+    return this.inject([], function(array, value, index) {
+      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+        array.push(value);
+      return array;
+    });
+  },
+
+  intersect: function(array) {
+    return this.uniq().findAll(function(item) {
+      return array.detect(function(value) { return item === value });
+    });
+  },
+
+  clone: function() {
+    return [].concat(this);
+  },
+
+  size: function() {
+    return this.length;
+  },
+
+  inspect: function() {
+    return '[' + this.map(Object.inspect).join(', ') + ']';
+  },
+
+  toJSON: function() {
+    var results = [];
+    this.each(function(object) {
+      var value = Object.toJSON(object);
+      if (!Object.isUndefined(value)) results.push(value);
+    });
+    return '[' + results.join(', ') + ']';
+  }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+  Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+  i || (i = 0);
+  var length = this.length;
+  if (i < 0) i = length + i;
+  for (; i < length; i++)
+    if (this[i] === item) return i;
+  return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+  i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+  var n = this.slice(0, i).reverse().indexOf(item);
+  return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+  if (!Object.isString(string)) return [];
+  string = string.strip();
+  return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+  Array.prototype.concat = function() {
+    var array = [];
+    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+    for (var i = 0, length = arguments.length; i < length; i++) {
+      if (Object.isArray(arguments[i])) {
+        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+          array.push(arguments[i][j]);
+      } else {
+        array.push(arguments[i]);
+      }
+    }
+    return array;
+  };
+}
+Object.extend(Number.prototype, {
+  toColorPart: function() {
+    return this.toPaddedString(2, 16);
+  },
+
+  succ: function() {
+    return this + 1;
+  },
+
+  times: function(iterator, context) {
+    $R(0, this, true).each(iterator, context);
+    return this;
+  },
+
+  toPaddedString: function(length, radix) {
+    var string = this.toString(radix || 10);
+    return '0'.times(length - string.length) + string;
+  },
+
+  toJSON: function() {
+    return isFinite(this) ? this.toString() : 'null';
+  }
+});
+
+$w('abs round ceil floor').each(function(method){
+  Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+  return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+  function toQueryPair(key, value) {
+    if (Object.isUndefined(value)) return key;
+    return key + '=' + encodeURIComponent(String.interpret(value));
+  }
+
+  return {
+    initialize: function(object) {
+      this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+    },
+
+    _each: function(iterator) {
+      for (var key in this._object) {
+        var value = this._object[key], pair = [key, value];
+        pair.key = key;
+        pair.value = value;
+        iterator(pair);
+      }
+    },
+
+    set: function(key, value) {
+      return this._object[key] = value;
+    },
+
+    get: function(key) {
+      // simulating poorly supported hasOwnProperty
+      if (this._object[key] !== Object.prototype[key])
+        return this._object[key];
+    },
+
+    unset: function(key) {
+      var value = this._object[key];
+      delete this._object[key];
+      return value;
+    },
+
+    toObject: function() {
+      return Object.clone(this._object);
+    },
+
+    keys: function() {
+      return this.pluck('key');
+    },
+
+    values: function() {
+      return this.pluck('value');
+    },
+
+    index: function(value) {
+      var match = this.detect(function(pair) {
+        return pair.value === value;
+      });
+      return match && match.key;
+    },
+
+    merge: function(object) {
+      return this.clone().update(object);
+    },
+
+    update: function(object) {
+      return new Hash(object).inject(this, function(result, pair) {
+        result.set(pair.key, pair.value);
+        return result;
+      });
+    },
+
+    toQueryString: function() {
+      return this.inject([], function(results, pair) {
+        var key = encodeURIComponent(pair.key), values = pair.value;
+
+        if (values && typeof values == 'object') {
+          if (Object.isArray(values))
+            return results.concat(values.map(toQueryPair.curry(key)));
+        } else results.push(toQueryPair(key, values));
+        return results;
+      }).join('&');
+    },
+
+    inspect: function() {
+      return '#<Hash:{' + this.map(function(pair) {
+        return pair.map(Object.inspect).join(': ');
+      }).join(', ') + '}>';
+    },
+
+    toJSON: function() {
+      return Object.toJSON(this.toObject());
+    },
+
+    clone: function() {
+      return new Hash(this);
+    }
+  }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+  initialize: function(start, end, exclusive) {
+    this.start = start;
+    this.end = end;
+    this.exclusive = exclusive;
+  },
+
+  _each: function(iterator) {
+    var value = this.start;
+    while (this.include(value)) {
+      iterator(value);
+      value = value.succ();
+    }
+  },
+
+  include: function(value) {
+    if (value < this.start)
+      return false;
+    if (this.exclusive)
+      return value < this.end;
+    return value <= this.end;
+  }
+});
+
+var $R = function(start, end, exclusive) {
+  return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+  getTransport: function() {
+    return Try.these(
+      function() {return new XMLHttpRequest()},
+      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+    ) || false;
+  },
+
+  activeRequestCount: 0
+};
+
+Ajax.Responders = {
+  responders: [],
+
+  _each: function(iterator) {
+    this.responders._each(iterator);
+  },
+
+  register: function(responder) {
+    if (!this.include(responder))
+      this.responders.push(responder);
+  },
+
+  unregister: function(responder) {
+    this.responders = this.responders.without(responder);
+  },
+
+  dispatch: function(callback, request, transport, json) {
+    this.each(function(responder) {
+      if (Object.isFunction(responder[callback])) {
+        try {
+          responder[callback].apply(responder, [request, transport, json]);
+        } catch (e) { }
+      }
+    });
+  }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+  onCreate:   function() { Ajax.activeRequestCount++ },
+  onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+  initialize: function(options) {
+    this.options = {
+      method:       'post',
+      asynchronous: true,
+      contentType:  'application/x-www-form-urlencoded',
+      encoding:     'UTF-8',
+      parameters:   '',
+      evalJSON:     true,
+      evalJS:       true
+    };
+    Object.extend(this.options, options || { });
+
+    this.options.method = this.options.method.toLowerCase();
+
+    if (Object.isString(this.options.parameters))
+      this.options.parameters = this.options.parameters.toQueryParams();
+    else if (Object.isHash(this.options.parameters))
+      this.options.parameters = this.options.parameters.toObject();
+  }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+  _complete: false,
+
+  initialize: function($super, url, options) {
+    $super(options);
+    this.transport = Ajax.getTransport();
+    this.request(url);
+  },
+
+  request: function(url) {
+    this.url = url;
+    this.method = this.options.method;
+    var params = Object.clone(this.options.parameters);
+
+    if (!['get', 'post'].include(this.method)) {
+      // simulate other verbs over post
+      params['_method'] = this.method;
+      this.method = 'post';
+    }
+
+    this.parameters = params;
+
+    if (params = Object.toQueryString(params)) {
+      // when GET, append parameters to URL
+      if (this.method == 'get')
+        this.url += (this.url.include('?') ? '&' : '?') + params;
+      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+        params += '&_=';
+    }
+
+    try {
+      var response = new Ajax.Response(this);
+      if (this.options.onCreate) this.options.onCreate(response);
+      Ajax.Responders.dispatch('onCreate', this, response);
+
+      this.transport.open(this.method.toUpperCase(), this.url,
+        this.options.asynchronous);
+
+      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+      this.transport.onreadystatechange = this.onStateChange.bind(this);
+      this.setRequestHeaders();
+
+      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+      this.transport.send(this.body);
+
+      /* Force Firefox to handle ready state 4 for synchronous requests */
+      if (!this.options.asynchronous && this.transport.overrideMimeType)
+        this.onStateChange();
+
+    }
+    catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  onStateChange: function() {
+    var readyState = this.transport.readyState;
+    if (readyState > 1 && !((readyState == 4) && this._complete))
+      this.respondToReadyState(this.transport.readyState);
+  },
+
+  setRequestHeaders: function() {
+    var headers = {
+      'X-Requested-With': 'XMLHttpRequest',
+      'X-Prototype-Version': Prototype.Version,
+      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+    };
+
+    if (this.method == 'post') {
+      headers['Content-type'] = this.options.contentType +
+        (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+      /* Force "Connection: close" for older Mozilla browsers to work
+       * around a bug where XMLHttpRequest sends an incorrect
+       * Content-length header. See Mozilla Bugzilla #246651.
+       */
+      if (this.transport.overrideMimeType &&
+          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+            headers['Connection'] = 'close';
+    }
+
+    // user-defined headers
+    if (typeof this.options.requestHeaders == 'object') {
+      var extras = this.options.requestHeaders;
+
+      if (Object.isFunction(extras.push))
+        for (var i = 0, length = extras.length; i < length; i += 2)
+          headers[extras[i]] = extras[i+1];
+      else
+        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+    }
+
+    for (var name in headers)
+      this.transport.setRequestHeader(name, headers[name]);
+  },
+
+  success: function() {
+    var status = this.getStatus();
+    return !status || (status >= 200 && status < 300);
+  },
+
+  getStatus: function() {
+    try {
+      return this.transport.status || 0;
+    } catch (e) { return 0 }
+  },
+
+  respondToReadyState: function(readyState) {
+    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+    if (state == 'Complete') {
+      try {
+        this._complete = true;
+        (this.options['on' + response.status]
+         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+         || Prototype.emptyFunction)(response, response.headerJSON);
+      } catch (e) {
+        this.dispatchException(e);
+      }
+
+      var contentType = response.getHeader('Content-type');
+      if (this.options.evalJS == 'force'
+          || (this.options.evalJS && this.isSameOrigin() && contentType
+          && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+        this.evalResponse();
+    }
+
+    try {
+      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+      Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+    } catch (e) {
+      this.dispatchException(e);
+    }
+
+    if (state == 'Complete') {
+      // avoid memory leak in MSIE: clean up
+      this.transport.onreadystatechange = Prototype.emptyFunction;
+    }
+  },
+
+  isSameOrigin: function() {
+    var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+    return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+      protocol: location.protocol,
+      domain: document.domain,
+      port: location.port ? ':' + location.port : ''
+    }));
+  },
+
+  getHeader: function(name) {
+    try {
+      return this.transport.getResponseHeader(name) || null;
+    } catch (e) { return null }
+  },
+
+  evalResponse: function() {
+    try {
+      return eval((this.transport.responseText || '').unfilterJSON());
+    } catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  dispatchException: function(exception) {
+    (this.options.onException || Prototype.emptyFunction)(this, exception);
+    Ajax.Responders.dispatch('onException', this, exception);
+  }
+});
+
+Ajax.Request.Events =
+  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+  initialize: function(request){
+    this.request = request;
+    var transport  = this.transport  = request.transport,
+        readyState = this.readyState = transport.readyState;
+
+    if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+      this.status       = this.getStatus();
+      this.statusText   = this.getStatusText();
+      this.responseText = String.interpret(transport.responseText);
+      this.headerJSON   = this._getHeaderJSON();
+    }
+
+    if(readyState == 4) {
+      var xml = transport.responseXML;
+      this.responseXML  = Object.isUndefined(xml) ? null : xml;
+      this.responseJSON = this._getResponseJSON();
+    }
+  },
+
+  status:      0,
+  statusText: '',
+
+  getStatus: Ajax.Request.prototype.getStatus,
+
+  getStatusText: function() {
+    try {
+      return this.transport.statusText || '';
+    } catch (e) { return '' }
+  },
+
+  getHeader: Ajax.Request.prototype.getHeader,
+
+  getAllHeaders: function() {
+    try {
+      return this.getAllResponseHeaders();
+    } catch (e) { return null }
+  },
+
+  getResponseHeader: function(name) {
+    return this.transport.getResponseHeader(name);
+  },
+
+  getAllResponseHeaders: function() {
+    return this.transport.getAllResponseHeaders();
+  },
+
+  _getHeaderJSON: function() {
+    var json = this.getHeader('X-JSON');
+    if (!json) return null;
+    json = decodeURIComponent(escape(json));
+    try {
+      return json.evalJSON(this.request.options.sanitizeJSON ||
+        !this.request.isSameOrigin());
+    } catch (e) {
+      this.request.dispatchException(e);
+    }
+  },
+
+  _getResponseJSON: function() {
+    var options = this.request.options;
+    if (!options.evalJSON || (options.evalJSON != 'force' &&
+      !(this.getHeader('Content-type') || '').include('application/json')) ||
+        this.responseText.blank())
+          return null;
+    try {
+      return this.responseText.evalJSON(options.sanitizeJSON ||
+        !this.request.isSameOrigin());
+    } catch (e) {
+      this.request.dispatchException(e);
+    }
+  }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+  initialize: function($super, container, url, options) {
+    this.container = {
+      success: (container.success || container),
+      failure: (container.failure || (container.success ? null : container))
+    };
+
+    options = Object.clone(options);
+    var onComplete = options.onComplete;
+    options.onComplete = (function(response, json) {
+      this.updateContent(response.responseText);
+      if (Object.isFunction(onComplete)) onComplete(response, json);
+    }).bind(this);
+
+    $super(url, options);
+  },
+
+  updateContent: function(responseText) {
+    var receiver = this.container[this.success() ? 'success' : 'failure'],
+        options = this.options;
+
+    if (!options.evalScripts) responseText = responseText.stripScripts();
+
+    if (receiver = $(receiver)) {
+      if (options.insertion) {
+        if (Object.isString(options.insertion)) {
+          var insertion = { }; insertion[options.insertion] = responseText;
+          receiver.insert(insertion);
+        }
+        else options.insertion(receiver, responseText);
+      }
+      else receiver.update(responseText);
+    }
+  }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+  initialize: function($super, container, url, options) {
+    $super(options);
+    this.onComplete = this.options.onComplete;
+
+    this.frequency = (this.options.frequency || 2);
+    this.decay = (this.options.decay || 1);
+
+    this.updater = { };
+    this.container = container;
+    this.url = url;
+
+    this.start();
+  },
+
+  start: function() {
+    this.options.onComplete = this.updateComplete.bind(this);
+    this.onTimerEvent();
+  },
+
+  stop: function() {
+    this.updater.options.onComplete = undefined;
+    clearTimeout(this.timer);
+    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+  },
+
+  updateComplete: function(response) {
+    if (this.options.decay) {
+      this.decay = (response.responseText == this.lastText ?
+        this.decay * this.options.decay : 1);
+
+      this.lastText = response.responseText;
+    }
+    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+  },
+
+  onTimerEvent: function() {
+    this.updater = new Ajax.Updater(this.container, this.url, this.options);
+  }
+});
+function $(element) {
+  if (arguments.length > 1) {
+    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+      elements.push($(arguments[i]));
+    return elements;
+  }
+  if (Object.isString(element))
+    element = document.getElementById(element);
+  return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+  document._getElementsByXPath = function(expression, parentElement) {
+    var results = [];
+    var query = document.evaluate(expression, $(parentElement) || document,
+      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+    for (var i = 0, length = query.snapshotLength; i < length; i++)
+      results.push(Element.extend(query.snapshotItem(i)));
+    return results;
+  };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+  // DOM level 2 ECMAScript Language Binding
+  Object.extend(Node, {
+    ELEMENT_NODE: 1,
+    ATTRIBUTE_NODE: 2,
+    TEXT_NODE: 3,
+    CDATA_SECTION_NODE: 4,
+    ENTITY_REFERENCE_NODE: 5,
+    ENTITY_NODE: 6,
+    PROCESSING_INSTRUCTION_NODE: 7,
+    COMMENT_NODE: 8,
+    DOCUMENT_NODE: 9,
+    DOCUMENT_TYPE_NODE: 10,
+    DOCUMENT_FRAGMENT_NODE: 11,
+    NOTATION_NODE: 12
+  });
+}
+
+(function() {
+  var element = this.Element;
+  this.Element = function(tagName, attributes) {
+    attributes = attributes || { };
+    tagName = tagName.toLowerCase();
+    var cache = Element.cache;
+    if (Prototype.Browser.IE && attributes.name) {
+      tagName = '<' + tagName + ' name="' + attributes.name + '">';
+      delete attributes.name;
+      return Element.writeAttribute(document.createElement(tagName), attributes);
+    }
+    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+    return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+  };
+  Object.extend(this.Element, element || { });
+  if (element) this.Element.prototype = element.prototype;
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+  visible: function(element) {
+    return $(element).style.display != 'none';
+  },
+
+  toggle: function(element) {
+    element = $(element);
+    Element[Element.visible(element) ? 'hide' : 'show'](element);
+    return element;
+  },
+
+  hide: function(element) {
+    element = $(element);
+    element.style.display = 'none';
+    return element;
+  },
+
+  show: function(element) {
+    element = $(element);
+    element.style.display = '';
+    return element;
+  },
+
+  remove: function(element) {
+    element = $(element);
+    element.parentNode.removeChild(element);
+    return element;
+  },
+
+  update: function(element, content) {
+    element = $(element);
+    if (content && content.toElement) content = content.toElement();
+    if (Object.isElement(content)) return element.update().insert(content);
+    content = Object.toHTML(content);
+    element.innerHTML = content.stripScripts();
+    content.evalScripts.bind(content).defer();
+    return element;
+  },
+
+  replace: function(element, content) {
+    element = $(element);
+    if (content && content.toElement) content = content.toElement();
+    else if (!Object.isElement(content)) {
+      content = Object.toHTML(content);
+      var range = element.ownerDocument.createRange();
+      range.selectNode(element);
+      content.evalScripts.bind(content).defer();
+      content = range.createContextualFragment(content.stripScripts());
+    }
+    element.parentNode.replaceChild(content, element);
+    return element;
+  },
+
+  insert: function(element, insertions) {
+    element = $(element);
+
+    if (Object.isString(insertions) || Object.isNumber(insertions) ||
+        Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+          insertions = {bottom:insertions};
+
+    var content, insert, tagName, childNodes;
+
+    for (var position in insertions) {
+      content  = insertions[position];
+      position = position.toLowerCase();
+      insert = Element._insertionTranslations[position];
+
+      if (content && content.toElement) content = content.toElement();
+      if (Object.isElement(content)) {
+        insert(element, content);
+        continue;
+      }
+
+      content = Object.toHTML(content);
+
+      tagName = ((position == 'before' || position == 'after')
+        ? element.parentNode : element).tagName.toUpperCase();
+
+      childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+      if (position == 'top' || position == 'after') childNodes.reverse();
+      childNodes.each(insert.curry(element));
+
+      content.evalScripts.bind(content).defer();
+    }
+
+    return element;
+  },
+
+  wrap: function(element, wrapper, attributes) {
+    element = $(element);
+    if (Object.isElement(wrapper))
+      $(wrapper).writeAttribute(attributes || { });
+    else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+    else wrapper = new Element('div', wrapper);
+    if (element.parentNode)
+      element.parentNode.replaceChild(wrapper, element);
+    wrapper.appendChild(element);
+    return wrapper;
+  },
+
+  inspect: function(element) {
+    element = $(element);
+    var result = '<' + element.tagName.toLowerCase();
+    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+      var property = pair.first(), attribute = pair.last();
+      var value = (element[property] || '').toString();
+      if (value) result += ' ' + attribute + '=' + value.inspect(true);
+    });
+    return result + '>';
+  },
+
+  recursivelyCollect: function(element, property) {
+    element = $(element);
+    var elements = [];
+    while (element = element[property])
+      if (element.nodeType == 1)
+        elements.push(Element.extend(element));
+    return elements;
+  },
+
+  ancestors: function(element) {
+    return $(element).recursivelyCollect('parentNode');
+  },
+
+  descendants: function(element) {
+    return $(element).select("*");
+  },
+
+  firstDescendant: function(element) {
+    element = $(element).firstChild;
+    while (element && element.nodeType != 1) element = element.nextSibling;
+    return $(element);
+  },
+
+  immediateDescendants: function(element) {
+    if (!(element = $(element).firstChild)) return [];
+    while (element && element.nodeType != 1) element = element.nextSibling;
+    if (element) return [element].concat($(element).nextSiblings());
+    return [];
+  },
+
+  previousSiblings: function(element) {
+    return $(element).recursivelyCollect('previousSibling');
+  },
+
+  nextSiblings: function(element) {
+    return $(element).recursivelyCollect('nextSibling');
+  },
+
+  siblings: function(element) {
+    element = $(element);
+    return element.previousSiblings().reverse().concat(element.nextSiblings());
+  },
+
+  match: function(element, selector) {
+    if (Object.isString(selector))
+      selector = new Selector(selector);
+    return selector.match($(element));
+  },
+
+  up: function(element, expression, index) {
+    element = $(element);
+    if (arguments.length == 1) return $(element.parentNode);
+    var ancestors = element.ancestors();
+    return Object.isNumber(expression) ? ancestors[expression] :
+      Selector.findElement(ancestors, expression, index);
+  },
+
+  down: function(element, expression, index) {
+    element = $(element);
+    if (arguments.length == 1) return element.firstDescendant();
+    return Object.isNumber(expression) ? element.descendants()[expression] :
+      Element.select(element, expression)[index || 0];
+  },
+
+  previous: function(element, expression, index) {
+    element = $(element);
+    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+    var previousSiblings = element.previousSiblings();
+    return Object.isNumber(expression) ? previousSiblings[expression] :
+      Selector.findElement(previousSiblings, expression, index);
+  },
+
+  next: function(element, expression, index) {
+    element = $(element);
+    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+    var nextSiblings = element.nextSiblings();
+    return Object.isNumber(expression) ? nextSiblings[expression] :
+      Selector.findElement(nextSiblings, expression, index);
+  },
+
+  select: function() {
+    var args = $A(arguments), element = $(args.shift());
+    return Selector.findChildElements(element, args);
+  },
+
+  adjacent: function() {
+    var args = $A(arguments), element = $(args.shift());
+    return Selector.findChildElements(element.parentNode, args).without(element);
+  },
+
+  identify: function(element) {
+    element = $(element);
+    var id = element.readAttribute('id'), self = arguments.callee;
+    if (id) return id;
+    do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+    element.writeAttribute('id', id);
+    return id;
+  },
+
+  readAttribute: function(element, name) {
+    element = $(element);
+    if (Prototype.Browser.IE) {
+      var t = Element._attributeTranslations.read;
+      if (t.values[name]) return t.values[name](element, name);
+      if (t.names[name]) name = t.names[name];
+      if (name.include(':')) {
+        return (!element.attributes || !element.attributes[name]) ? null :
+         element.attributes[name].value;
+      }
+    }
+    return element.getAttribute(name);
+  },
+
+  writeAttribute: function(element, name, value) {
+    element = $(element);
+    var attributes = { }, t = Element._attributeTranslations.write;
+
+    if (typeof name == 'object') attributes = name;
+    else attributes[name] = Object.isUndefined(value) ? true : value;
+
+    for (var attr in attributes) {
+      name = t.names[attr] || attr;
+      value = attributes[attr];
+      if (t.values[attr]) name = t.values[attr](element, value);
+      if (value === false || value === null)
+        element.removeAttribute(name);
+      else if (value === true)
+        element.setAttribute(name, name);
+      else element.setAttribute(name, value);
+    }
+    return element;
+  },
+
+  getHeight: function(element) {
+    return $(element).getDimensions().height;
+  },
+
+  getWidth: function(element) {
+    return $(element).getDimensions().width;
+  },
+
+  classNames: function(element) {
+    return new Element.ClassNames(element);
+  },
+
+  hasClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    var elementClassName = element.className;
+    return (elementClassName.length > 0 && (elementClassName == className ||
+      new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+  },
+
+  addClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    if (!element.hasClassName(className))
+      element.className += (element.className ? ' ' : '') + className;
+    return element;
+  },
+
+  removeClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    element.className = element.className.replace(
+      new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+    return element;
+  },
+
+  toggleClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    return element[element.hasClassName(className) ?
+      'removeClassName' : 'addClassName'](className);
+  },
+
+  // removes whitespace-only text node children
+  cleanWhitespace: function(element) {
+    element = $(element);
+    var node = element.firstChild;
+    while (node) {
+      var nextNode = node.nextSibling;
+      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+        element.removeChild(node);
+      node = nextNode;
+    }
+    return element;
+  },
+
+  empty: function(element) {
+    return $(element).innerHTML.blank();
+  },
+
+  descendantOf: function(element, ancestor) {
+    element = $(element), ancestor = $(ancestor);
+
+    if (element.compareDocumentPosition)
+      return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+    if (ancestor.contains)
+      return ancestor.contains(element) && ancestor !== element;
+
+    while (element = element.parentNode)
+      if (element == ancestor) return true;
+
+    return false;
+  },
+
+  scrollTo: function(element) {
+    element = $(element);
+    var pos = element.cumulativeOffset();
+    window.scrollTo(pos[0], pos[1]);
+    return element;
+  },
+
+  getStyle: function(element, style) {
+    element = $(element);
+    style = style == 'float' ? 'cssFloat' : style.camelize();
+    var value = element.style[style];
+    if (!value || value == 'auto') {
+      var css = document.defaultView.getComputedStyle(element, null);
+      value = css ? css[style] : null;
+    }
+    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+    return value == 'auto' ? null : value;
+  },
+
+  getOpacity: function(element) {
+    return $(element).getStyle('opacity');
+  },
+
+  setStyle: function(element, styles) {
+    element = $(element);
+    var elementStyle = element.style, match;
+    if (Object.isString(styles)) {
+      element.style.cssText += ';' + styles;
+      return styles.include('opacity') ?
+        element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+    }
+    for (var property in styles)
+      if (property == 'opacity') element.setOpacity(styles[property]);
+      else
+        elementStyle[(property == 'float' || property == 'cssFloat') ?
+          (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+            property] = styles[property];
+
+    return element;
+  },
+
+  setOpacity: function(element, value) {
+    element = $(element);
+    element.style.opacity = (value == 1 || value === '') ? '' :
+      (value < 0.00001) ? 0 : value;
+    return element;
+  },
+
+  getDimensions: function(element) {
+    element = $(element);
+    var display = element.getStyle('display');
+    if (display != 'none' && display != null) // Safari bug
+      return {width: element.offsetWidth, height: element.offsetHeight};
+
+    // All *Width and *Height properties give 0 on elements with display none,
+    // so enable the element temporarily
+    var els = element.style;
+    var originalVisibility = els.visibility;
+    var originalPosition = els.position;
+    var originalDisplay = els.display;
+    els.visibility = 'hidden';
+    els.position = 'absolute';
+    els.display = 'block';
+    var originalWidth = element.clientWidth;
+    var originalHeight = element.clientHeight;
+    els.display = originalDisplay;
+    els.position = originalPosition;
+    els.visibility = originalVisibility;
+    return {width: originalWidth, height: originalHeight};
+  },
+
+  makePositioned: function(element) {
+    element = $(element);
+    var pos = Element.getStyle(element, 'position');
+    if (pos == 'static' || !pos) {
+      element._madePositioned = true;
+      element.style.position = 'relative';
+      // Opera returns the offset relative to the positioning context, when an
+      // element is position relative but top and left have not been defined
+      if (Prototype.Browser.Opera) {
+        element.style.top = 0;
+        element.style.left = 0;
+      }
+    }
+    return element;
+  },
+
+  undoPositioned: function(element) {
+    element = $(element);
+    if (element._madePositioned) {
+      element._madePositioned = undefined;
+      element.style.position =
+        element.style.top =
+        element.style.left =
+        element.style.bottom =
+        element.style.right = '';
+    }
+    return element;
+  },
+
+  makeClipping: function(element) {
+    element = $(element);
+    if (element._overflow) return element;
+    element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+    if (element._overflow !== 'hidden')
+      element.style.overflow = 'hidden';
+    return element;
+  },
+
+  undoClipping: function(element) {
+    element = $(element);
+    if (!element._overflow) return element;
+    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+    element._overflow = null;
+    return element;
+  },
+
+  cumulativeOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+    } while (element);
+    return Element._returnOffset(valueL, valueT);
+  },
+
+  positionedOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+      if (element) {
+        if (element.tagName.toUpperCase() == 'BODY') break;
+        var p = Element.getStyle(element, 'position');
+        if (p !== 'static') break;
+      }
+    } while (element);
+    return Element._returnOffset(valueL, valueT);
+  },
+
+  absolutize: function(element) {
+    element = $(element);
+    if (element.getStyle('position') == 'absolute') return element;
+    // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+    var offsets = element.positionedOffset();
+    var top     = offsets[1];
+    var left    = offsets[0];
+    var width   = element.clientWidth;
+    var height  = element.clientHeight;
+
+    element._originalLeft   = left - parseFloat(element.style.left  || 0);
+    element._originalTop    = top  - parseFloat(element.style.top || 0);
+    element._originalWidth  = element.style.width;
+    element._originalHeight = element.style.height;
+
+    element.style.position = 'absolute';
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.width  = width + 'px';
+    element.style.height = height + 'px';
+    return element;
+  },
+
+  relativize: function(element) {
+    element = $(element);
+    if (element.getStyle('position') == 'relative') return element;
+    // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+    element.style.position = 'relative';
+    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
+    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.height = element._originalHeight;
+    element.style.width  = element._originalWidth;
+    return element;
+  },
+
+  cumulativeScrollOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.scrollTop  || 0;
+      valueL += element.scrollLeft || 0;
+      element = element.parentNode;
+    } while (element);
+    return Element._returnOffset(valueL, valueT);
+  },
+
+  getOffsetParent: function(element) {
+    if (element.offsetParent) return $(element.offsetParent);
+    if (element == document.body) return $(element);
+
+    while ((element = element.parentNode) && element != document.body)
+      if (Element.getStyle(element, 'position') != 'static')
+        return $(element);
+
+    return $(document.body);
+  },
+
+  viewportOffset: function(forElement) {
+    var valueT = 0, valueL = 0;
+
+    var element = forElement;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+
+      // Safari fix
+      if (element.offsetParent == document.body &&
+        Element.getStyle(element, 'position') == 'absolute') break;
+
+    } while (element = element.offsetParent);
+
+    element = forElement;
+    do {
+      if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
+        valueT -= element.scrollTop  || 0;
+        valueL -= element.scrollLeft || 0;
+      }
+    } while (element = element.parentNode);
+
+    return Element._returnOffset(valueL, valueT);
+  },
+
+  clonePosition: function(element, source) {
+    var options = Object.extend({
+      setLeft:    true,
+      setTop:     true,
+      setWidth:   true,
+      setHeight:  true,
+      offsetTop:  0,
+      offsetLeft: 0
+    }, arguments[2] || { });
+
+    // find page position of source
+    source = $(source);
+    var p = source.viewportOffset();
+
+    // find coordinate system to use
+    element = $(element);
+    var delta = [0, 0];
+    var parent = null;
+    // delta [0,0] will do fine with position: fixed elements,
+    // position:absolute needs offsetParent deltas
+    if (Element.getStyle(element, 'position') == 'absolute') {
+      parent = element.getOffsetParent();
+      delta = parent.viewportOffset();
+    }
+
+    // correct by body offsets (fixes Safari)
+    if (parent == document.body) {
+      delta[0] -= document.body.offsetLeft;
+      delta[1] -= document.body.offsetTop;
+    }
+
+    // set position
+    if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
+    if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
+    if (options.setWidth)  element.style.width = source.offsetWidth + 'px';
+    if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+    return element;
+  }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+  getElementsBySelector: Element.Methods.select,
+  childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+  write: {
+    names: {
+      className: 'class',
+      htmlFor:   'for'
+    },
+    values: { }
+  }
+};
+
+if (Prototype.Browser.Opera) {
+  Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+    function(proceed, element, style) {
+      switch (style) {
+        case 'left': case 'top': case 'right': case 'bottom':
+          if (proceed(element, 'position') === 'static') return null;
+        case 'height': case 'width':
+          // returns '0px' for hidden elements; we want it to return null
+          if (!Element.visible(element)) return null;
+
+          // returns the border-box dimensions rather than the content-box
+          // dimensions, so we subtract padding and borders from the value
+          var dim = parseInt(proceed(element, style), 10);
+
+          if (dim !== element['offset' + style.capitalize()])
+            return dim + 'px';
+
+          var properties;
+          if (style === 'height') {
+            properties = ['border-top-width', 'padding-top',
+             'padding-bottom', 'border-bottom-width'];
+          }
+          else {
+            properties = ['border-left-width', 'padding-left',
+             'padding-right', 'border-right-width'];
+          }
+          return properties.inject(dim, function(memo, property) {
+            var val = proceed(element, property);
+            return val === null ? memo : memo - parseInt(val, 10);
+          }) + 'px';
+        default: return proceed(element, style);
+      }
+    }
+  );
+
+  Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+    function(proceed, element, attribute) {
+      if (attribute === 'title') return element.title;
+      return proceed(element, attribute);
+    }
+  );
+}
+
+else if (Prototype.Browser.IE) {
+  // IE doesn't report offsets correctly for static elements, so we change them
+  // to "relative" to get the values, then change them back.
+  Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+    function(proceed, element) {
+      element = $(element);
+      // IE throws an error if element is not in document
+      try { element.offsetParent }
+      catch(e) { return $(document.body) }
+      var position = element.getStyle('position');
+      if (position !== 'static') return proceed(element);
+      element.setStyle({ position: 'relative' });
+      var value = proceed(element);
+      element.setStyle({ position: position });
+      return value;
+    }
+  );
+
+  $w('positionedOffset viewportOffset').each(function(method) {
+    Element.Methods[method] = Element.Methods[method].wrap(
+      function(proceed, element) {
+        element = $(element);
+        try { element.offsetParent }
+        catch(e) { return Element._returnOffset(0,0) }
+        var position = element.getStyle('position');
+        if (position !== 'static') return proceed(element);
+        // Trigger hasLayout on the offset parent so that IE6 reports
+        // accurate offsetTop and offsetLeft values for position: fixed.
+        var offsetParent = element.getOffsetParent();
+        if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+          offsetParent.setStyle({ zoom: 1 });
+        element.setStyle({ position: 'relative' });
+        var value = proceed(element);
+        element.setStyle({ position: position });
+        return value;
+      }
+    );
+  });
+
+  Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
+    function(proceed, element) {
+      try { element.offsetParent }
+      catch(e) { return Element._returnOffset(0,0) }
+      return proceed(element);
+    }
+  );
+
+  Element.Methods.getStyle = function(element, style) {
+    element = $(element);
+    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+    var value = element.style[style];
+    if (!value && element.currentStyle) value = element.currentStyle[style];
+
+    if (style == 'opacity') {
+      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+        if (value[1]) return parseFloat(value[1]) / 100;
+      return 1.0;
+    }
+
+    if (value == 'auto') {
+      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+        return element['offset' + style.capitalize()] + 'px';
+      return null;
+    }
+    return value;
+  };
+
+  Element.Methods.setOpacity = function(element, value) {
+    function stripAlpha(filter){
+      return filter.replace(/alpha\([^\)]*\)/gi,'');
+    }
+    element = $(element);
+    var currentStyle = element.currentStyle;
+    if ((currentStyle && !currentStyle.hasLayout) ||
+      (!currentStyle && element.style.zoom == 'normal'))
+        element.style.zoom = 1;
+
+    var filter = element.getStyle('filter'), style = element.style;
+    if (value == 1 || value === '') {
+      (filter = stripAlpha(filter)) ?
+        style.filter = filter : style.removeAttribute('filter');
+      return element;
+    } else if (value < 0.00001) value = 0;
+    style.filter = stripAlpha(filter) +
+      'alpha(opacity=' + (value * 100) + ')';
+    return element;
+  };
+
+  Element._attributeTranslations = {
+    read: {
+      names: {
+        'class': 'className',
+        'for':   'htmlFor'
+      },
+      values: {
+        _getAttr: function(element, attribute) {
+          return element.getAttribute(attribute, 2);
+        },
+        _getAttrNode: function(element, attribute) {
+          var node = element.getAttributeNode(attribute);
+          return node ? node.value : "";
+        },
+        _getEv: function(element, attribute) {
+          attribute = element.getAttribute(attribute);
+          return attribute ? attribute.toString().slice(23, -2) : null;
+        },
+        _flag: function(element, attribute) {
+          return $(element).hasAttribute(attribute) ? attribute : null;
+        },
+        style: function(element) {
+          return element.style.cssText.toLowerCase();
+        },
+        title: function(element) {
+          return element.title;
+        }
+      }
+    }
+  };
+
+  Element._attributeTranslations.write = {
+    names: Object.extend({
+      cellpadding: 'cellPadding',
+      cellspacing: 'cellSpacing'
+    }, Element._attributeTranslations.read.names),
+    values: {
+      checked: function(element, value) {
+        element.checked = !!value;
+      },
+
+      style: function(element, value) {
+        element.style.cssText = value ? value : '';
+      }
+    }
+  };
+
+  Element._attributeTranslations.has = {};
+
+  $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+      'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
+    Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+    Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+  });
+
+  (function(v) {
+    Object.extend(v, {
+      href:        v._getAttr,
+      src:         v._getAttr,
+      type:        v._getAttr,
+      action:      v._getAttrNode,
+      disabled:    v._flag,
+      checked:     v._flag,
+      readonly:    v._flag,
+      multiple:    v._flag,
+      onload:      v._getEv,
+      onunload:    v._getEv,
+      onclick:     v._getEv,
+      ondblclick:  v._getEv,
+      onmousedown: v._getEv,
+      onmouseup:   v._getEv,
+      onmouseover: v._getEv,
+      onmousemove: v._getEv,
+      onmouseout:  v._getEv,
+      onfocus:     v._getEv,
+      onblur:      v._getEv,
+      onkeypress:  v._getEv,
+      onkeydown:   v._getEv,
+      onkeyup:     v._getEv,
+      onsubmit:    v._getEv,
+      onreset:     v._getEv,
+      onselect:    v._getEv,
+      onchange:    v._getEv
+    });
+  })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+  Element.Methods.setOpacity = function(element, value) {
+    element = $(element);
+    element.style.opacity = (value == 1) ? 0.999999 :
+      (value === '') ? '' : (value < 0.00001) ? 0 : value;
+    return element;
+  };
+}
+
+else if (Prototype.Browser.WebKit) {
+  Element.Methods.setOpacity = function(element, value) {
+    element = $(element);
+    element.style.opacity = (value == 1 || value === '') ? '' :
+      (value < 0.00001) ? 0 : value;
+
+    if (value == 1)
+      if(element.tagName.toUpperCase() == 'IMG' && element.width) {
+        element.width++; element.width--;
+      } else try {
+        var n = document.createTextNode(' ');
+        element.appendChild(n);
+        element.removeChild(n);
+      } catch (e) { }
+
+    return element;
+  };
+
+  // Safari returns margins on body which is incorrect if the child is absolutely
+  // positioned.  For performance reasons, redefine Element#cumulativeOffset for
+  // KHTML/WebKit only.
+  Element.Methods.cumulativeOffset = function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      if (element.offsetParent == document.body)
+        if (Element.getStyle(element, 'position') == 'absolute') break;
+
+      element = element.offsetParent;
+    } while (element);
+
+    return Element._returnOffset(valueL, valueT);
+  };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+  // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+  Element.Methods.update = function(element, content) {
+    element = $(element);
+
+    if (content && content.toElement) content = content.toElement();
+    if (Object.isElement(content)) return element.update().insert(content);
+
+    content = Object.toHTML(content);
+    var tagName = element.tagName.toUpperCase();
+
+    if (tagName in Element._insertionTranslations.tags) {
+      $A(element.childNodes).each(function(node) { element.removeChild(node) });
+      Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+        .each(function(node) { element.appendChild(node) });
+    }
+    else element.innerHTML = content.stripScripts();
+
+    content.evalScripts.bind(content).defer();
+    return element;
+  };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+  Element.Methods.replace = function(element, content) {
+    element = $(element);
+
+    if (content && content.toElement) content = content.toElement();
+    if (Object.isElement(content)) {
+      element.parentNode.replaceChild(content, element);
+      return element;
+    }
+
+    content = Object.toHTML(content);
+    var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+    if (Element._insertionTranslations.tags[tagName]) {
+      var nextSibling = element.next();
+      var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+      parent.removeChild(element);
+      if (nextSibling)
+        fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+      else
+        fragments.each(function(node) { parent.appendChild(node) });
+    }
+    else element.outerHTML = content.stripScripts();
+
+    content.evalScripts.bind(content).defer();
+    return element;
+  };
+}
+
+Element._returnOffset = function(l, t) {
+  var result = [l, t];
+  result.left = l;
+  result.top = t;
+  return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+  var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+  if (t) {
+    div.innerHTML = t[0] + html + t[1];
+    t[2].times(function() { div = div.firstChild });
+  } else div.innerHTML = html;
+  return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+  before: function(element, node) {
+    element.parentNode.insertBefore(node, element);
+  },
+  top: function(element, node) {
+    element.insertBefore(node, element.firstChild);
+  },
+  bottom: function(element, node) {
+    element.appendChild(node);
+  },
+  after: function(element, node) {
+    element.parentNode.insertBefore(node, element.nextSibling);
+  },
+  tags: {
+    TABLE:  ['<table>',                '</table>',                   1],
+    TBODY:  ['<table><tbody>',         '</tbody></table>',           2],
+    TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],
+    TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+    SELECT: ['<select>',               '</select>',                  1]
+  }
+};
+
+(function() {
+  Object.extend(this.tags, {
+    THEAD: this.tags.TBODY,
+    TFOOT: this.tags.TBODY,
+    TH:    this.tags.TD
+  });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+  hasAttribute: function(element, attribute) {
+    attribute = Element._attributeTranslations.has[attribute] || attribute;
+    var node = $(element).getAttributeNode(attribute);
+    return !!(node && node.specified);
+  }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+    document.createElement('div')['__proto__']) {
+  window.HTMLElement = { };
+  window.HTMLElement.prototype = document.createElement('div')['__proto__'];
+  Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+  if (Prototype.BrowserFeatures.SpecificElementExtensions)
+    return Prototype.K;
+
+  var Methods = { }, ByTag = Element.Methods.ByTag;
+
+  var extend = Object.extend(function(element) {
+    if (!element || element._extendedByPrototype ||
+        element.nodeType != 1 || element == window) return element;
+
+    var methods = Object.clone(Methods),
+      tagName = element.tagName.toUpperCase(), property, value;
+
+    // extend methods for specific tags
+    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+    for (property in methods) {
+      value = methods[property];
+      if (Object.isFunction(value) && !(property in element))
+        element[property] = value.methodize();
+    }
+
+    element._extendedByPrototype = Prototype.emptyFunction;
+    return element;
+
+  }, {
+    refresh: function() {
+      // extend methods for all tags (Safari doesn't need this)
+      if (!Prototype.BrowserFeatures.ElementExtensions) {
+        Object.extend(Methods, Element.Methods);
+        Object.extend(Methods, Element.Methods.Simulated);
+      }
+    }
+  });
+
+  extend.refresh();
+  return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+  if (element.hasAttribute) return element.hasAttribute(attribute);
+  return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+  if (!methods) {
+    Object.extend(Form, Form.Methods);
+    Object.extend(Form.Element, Form.Element.Methods);
+    Object.extend(Element.Methods.ByTag, {
+      "FORM":     Object.clone(Form.Methods),
+      "INPUT":    Object.clone(Form.Element.Methods),
+      "SELECT":   Object.clone(Form.Element.Methods),
+      "TEXTAREA": Object.clone(Form.Element.Methods)
+    });
+  }
+
+  if (arguments.length == 2) {
+    var tagName = methods;
+    methods = arguments[1];
+  }
+
+  if (!tagName) Object.extend(Element.Methods, methods || { });
+  else {
+    if (Object.isArray(tagName)) tagName.each(extend);
+    else extend(tagName);
+  }
+
+  function extend(tagName) {
+    tagName = tagName.toUpperCase();
+    if (!Element.Methods.ByTag[tagName])
+      Element.Methods.ByTag[tagName] = { };
+    Object.extend(Element.Methods.ByTag[tagName], methods);
+  }
+
+  function copy(methods, destination, onlyIfAbsent) {
+    onlyIfAbsent = onlyIfAbsent || false;
+    for (var property in methods) {
+      var value = methods[property];
+      if (!Object.isFunction(value)) continue;
+      if (!onlyIfAbsent || !(property in destination))
+        destination[property] = value.methodize();
+    }
+  }
+
+  function findDOMClass(tagName) {
+    var klass;
+    var trans = {
+      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+      "FrameSet", "IFRAME": "IFrame"
+    };
+    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+    if (window[klass]) return window[klass];
+    klass = 'HTML' + tagName + 'Element';
+    if (window[klass]) return window[klass];
+    klass = 'HTML' + tagName.capitalize() + 'Element';
+    if (window[klass]) return window[klass];
+
+    window[klass] = { };
+    window[klass].prototype = document.createElement(tagName)['__proto__'];
+    return window[klass];
+  }
+
+  if (F.ElementExtensions) {
+    copy(Element.Methods, HTMLElement.prototype);
+    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+  }
+
+  if (F.SpecificElementExtensions) {
+    for (var tag in Element.Methods.ByTag) {
+      var klass = findDOMClass(tag);
+      if (Object.isUndefined(klass)) continue;
+      copy(T[tag], klass.prototype);
+    }
+  }
+
+  Object.extend(Element, Element.Methods);
+  delete Element.ByTag;
+
+  if (Element.extend.refresh) Element.extend.refresh();
+  Element.cache = { };
+};
+
+document.viewport = {
+  getDimensions: function() {
+    var dimensions = { }, B = Prototype.Browser;
+    $w('width height').each(function(d) {
+      var D = d.capitalize();
+      if (B.WebKit && !document.evaluate) {
+        // Safari <3.0 needs self.innerWidth/Height
+        dimensions[d] = self['inner' + D];
+      } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
+        // Opera <9.5 needs document.body.clientWidth/Height
+        dimensions[d] = document.body['client' + D]
+      } else {
+        dimensions[d] = document.documentElement['client' + D];
+      }
+    });
+    return dimensions;
+  },
+
+  getWidth: function() {
+    return this.getDimensions().width;
+  },
+
+  getHeight: function() {
+    return this.getDimensions().height;
+  },
+
+  getScrollOffsets: function() {
+    return Element._returnOffset(
+      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+      window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+  }
+};
+/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license.  Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+  initialize: function(expression) {
+    this.expression = expression.strip();
+
+    if (this.shouldUseSelectorsAPI()) {
+      this.mode = 'selectorsAPI';
+    } else if (this.shouldUseXPath()) {
+      this.mode = 'xpath';
+      this.compileXPathMatcher();
+    } else {
+      this.mode = "normal";
+      this.compileMatcher();
+    }
+
+  },
+
+  shouldUseXPath: function() {
+    if (!Prototype.BrowserFeatures.XPath) return false;
+
+    var e = this.expression;
+
+    // Safari 3 chokes on :*-of-type and :empty
+    if (Prototype.Browser.WebKit &&
+     (e.include("-of-type") || e.include(":empty")))
+      return false;
+
+    // XPath can't do namespaced attributes, nor can it read
+    // the "checked" property from DOM nodes
+    if ((/(\[[\w-]*?:|:checked)/).test(e))
+      return false;
+
+    return true;
+  },
+
+  shouldUseSelectorsAPI: function() {
+    if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
+
+    if (!Selector._div) Selector._div = new Element('div');
+
+    // Make sure the browser treats the selector as valid. Test on an
+    // isolated element to minimize cost of this check.
+    try {
+      Selector._div.querySelector(this.expression);
+    } catch(e) {
+      return false;
+    }
+
+    return true;
+  },
+
+  compileMatcher: function() {
+    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+        c = Selector.criteria, le, p, m;
+
+    if (Selector._cache[e]) {
+      this.matcher = Selector._cache[e];
+      return;
+    }
+
+    this.matcher = ["this.matcher = function(root) {",
+                    "var r = root, h = Selector.handlers, c = false, n;"];
+
+    while (e && le != e && (/\S/).test(e)) {
+      le = e;
+      for (var i in ps) {
+        p = ps[i];
+        if (m = e.match(p)) {
+          this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+            new Template(c[i]).evaluate(m));
+          e = e.replace(m[0], '');
+          break;
+        }
+      }
+    }
+
+    this.matcher.push("return h.unique(n);\n}");
+    eval(this.matcher.join('\n'));
+    Selector._cache[this.expression] = this.matcher;
+  },
+
+  compileXPathMatcher: function() {
+    var e = this.expression, ps = Selector.patterns,
+        x = Selector.xpath, le, m;
+
+    if (Selector._cache[e]) {
+      this.xpath = Selector._cache[e]; return;
+    }
+
+    this.matcher = ['.//*'];
+    while (e && le != e && (/\S/).test(e)) {
+      le = e;
+      for (var i in ps) {
+        if (m = e.match(ps[i])) {
+          this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+            new Template(x[i]).evaluate(m));
+          e = e.replace(m[0], '');
+          break;
+        }
+      }
+    }
+
+    this.xpath = this.matcher.join('');
+    Selector._cache[this.expression] = this.xpath;
+  },
+
+  findElements: function(root) {
+    root = root || document;
+    var e = this.expression, results;
+
+    switch (this.mode) {
+      case 'selectorsAPI':
+        // querySelectorAll queries document-wide, then filters to descendants
+        // of the context element. That's not what we want.
+        // Add an explicit context to the selector if necessary.
+        if (root !== document) {
+          var oldId = root.id, id = $(root).identify();
+          e = "#" + id + " " + e;
+        }
+
+        results = $A(root.querySelectorAll(e)).map(Element.extend);
+        root.id = oldId;
+
+        return results;
+      case 'xpath':
+        return document._getElementsByXPath(this.xpath, root);
+      default:
+       return this.matcher(root);
+    }
+  },
+
+  match: function(element) {
+    this.tokens = [];
+
+    var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+    var le, p, m;
+
+    while (e && le !== e && (/\S/).test(e)) {
+      le = e;
+      for (var i in ps) {
+        p = ps[i];
+        if (m = e.match(p)) {
+          // use the Selector.assertions methods unless the selector
+          // is too complex.
+          if (as[i]) {
+            this.tokens.push([i, Object.clone(m)]);
+            e = e.replace(m[0], '');
+          } else {
+            // reluctantly do a document-wide search
+            // and look for a match in the array
+            return this.findElements(document).include(element);
+          }
+        }
+      }
+    }
+
+    var match = true, name, matches;
+    for (var i = 0, token; token = this.tokens[i]; i++) {
+      name = token[0], matches = token[1];
+      if (!Selector.assertions[name](element, matches)) {
+        match = false; break;
+      }
+    }
+
+    return match;
+  },
+
+  toString: function() {
+    return this.expression;
+  },
+
+  inspect: function() {
+    return "#<Selector:" + this.expression.inspect() + ">";
+  }
+});
+
+Object.extend(Selector, {
+  _cache: { },
+
+  xpath: {
+    descendant:   "//*",
+    child:        "/*",
+    adjacent:     "/following-sibling::*[1]",
+    laterSibling: '/following-sibling::*',
+    tagName:      function(m) {
+      if (m[1] == '*') return '';
+      return "[local-name()='" + m[1].toLowerCase() +
+             "' or local-name()='" + m[1].toUpperCase() + "']";
+    },
+    className:    "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+    id:           "[@id='#{1}']",
+    attrPresence: function(m) {
+      m[1] = m[1].toLowerCase();
+      return new Template("[@#{1}]").evaluate(m);
+    },
+    attr: function(m) {
+      m[1] = m[1].toLowerCase();
+      m[3] = m[5] || m[6];
+      return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+    },
+    pseudo: function(m) {
+      var h = Selector.xpath.pseudos[m[1]];
+      if (!h) return '';
+      if (Object.isFunction(h)) return h(m);
+      return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+    },
+    operators: {
+      '=':  "[@#{1}='#{3}']",
+      '!=': "[@#{1}!='#{3}']",
+      '^=': "[starts-with(@#{1}, '#{3}')]",
+      '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+      '*=': "[contains(@#{1}, '#{3}')]",
+      '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+      '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+    },
+    pseudos: {
+      'first-child': '[not(preceding-sibling::*)]',
+      'last-child':  '[not(following-sibling::*)]',
+      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]',
+      'empty':       "[count(*) = 0 and (count(text()) = 0)]",
+      'checked':     "[@checked]",
+      'disabled':    "[(@disabled) and (@type!='hidden')]",
+      'enabled':     "[not(@disabled) and (@type!='hidden')]",
+      'not': function(m) {
+        var e = m[6], p = Selector.patterns,
+            x = Selector.xpath, le, v;
+
+        var exclusion = [];
+        while (e && le != e && (/\S/).test(e)) {
+          le = e;
+          for (var i in p) {
+            if (m = e.match(p[i])) {
+              v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+              exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+              e = e.replace(m[0], '');
+              break;
+            }
+          }
+        }
+        return "[not(" + exclusion.join(" and ") + ")]";
+      },
+      'nth-child':      function(m) {
+        return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+      },
+      'nth-last-child': function(m) {
+        return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+      },
+      'nth-of-type':    function(m) {
+        return Selector.xpath.pseudos.nth("position() ", m);
+      },
+      'nth-last-of-type': function(m) {
+        return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+      },
+      'first-of-type':  function(m) {
+        m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+      },
+      'last-of-type':   function(m) {
+        m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+      },
+      'only-of-type':   function(m) {
+        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+      },
+      nth: function(fragment, m) {
+        var mm, formula = m[6], predicate;
+        if (formula == 'even') formula = '2n+0';
+        if (formula == 'odd')  formula = '2n+1';
+        if (mm = formula.match(/^(\d+)$/)) // digit only
+          return '[' + fragment + "= " + mm[1] + ']';
+        if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+          if (mm[1] == "-") mm[1] = -1;
+          var a = mm[1] ? Number(mm[1]) : 1;
+          var b = mm[2] ? Number(mm[2]) : 0;
+          predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+          "((#{fragment} - #{b}) div #{a} >= 0)]";
+          return new Template(predicate).evaluate({
+            fragment: fragment, a: a, b: b });
+        }
+      }
+    }
+  },
+
+  criteria: {
+    tagName:      'n = h.tagName(n, r, "#{1}", c);      c = false;',
+    className:    'n = h.className(n, r, "#{1}", c);    c = false;',
+    id:           'n = h.id(n, r, "#{1}", c);           c = false;',
+    attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+    attr: function(m) {
+      m[3] = (m[5] || m[6]);
+      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+    },
+    pseudo: function(m) {
+      if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+      return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+    },
+    descendant:   'c = "descendant";',
+    child:        'c = "child";',
+    adjacent:     'c = "adjacent";',
+    laterSibling: 'c = "laterSibling";'
+  },
+
+  patterns: {
+    // combinators must be listed first
+    // (and descendant needs to be last combinator)
+    laterSibling: /^\s*~\s*/,
+    child:        /^\s*>\s*/,
+    adjacent:     /^\s*\+\s*/,
+    descendant:   /^\s/,
+
+    // selectors follow
+    tagName:      /^\s*(\*|[\w\-]+)(\b|$)?/,
+    id:           /^#([\w\-\*]+)(\b|$)/,
+    className:    /^\.([\w\-\*]+)(\b|$)/,
+    pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+    attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/,
+    attr:         /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+  },
+
+  // for Selector.match and Element#match
+  assertions: {
+    tagName: function(element, matches) {
+      return matches[1].toUpperCase() == element.tagName.toUpperCase();
+    },
+
+    className: function(element, matches) {
+      return Element.hasClassName(element, matches[1]);
+    },
+
+    id: function(element, matches) {
+      return element.id === matches[1];
+    },
+
+    attrPresence: function(element, matches) {
+      return Element.hasAttribute(element, matches[1]);
+    },
+
+    attr: function(element, matches) {
+      var nodeValue = Element.readAttribute(element, matches[1]);
+      return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+    }
+  },
+
+  handlers: {
+    // UTILITY FUNCTIONS
+    // joins two collections
+    concat: function(a, b) {
+      for (var i = 0, node; node = b[i]; i++)
+        a.push(node);
+      return a;
+    },
+
+    // marks an array of nodes for counting
+    mark: function(nodes) {
+      var _true = Prototype.emptyFunction;
+      for (var i = 0, node; node = nodes[i]; i++)
+        node._countedByPrototype = _true;
+      return nodes;
+    },
+
+    unmark: function(nodes) {
+      for (var i = 0, node; node = nodes[i]; i++)
+        node._countedByPrototype = undefined;
+      return nodes;
+    },
+
+    // mark each child node with its position (for nth calls)
+    // "ofType" flag indicates whether we're indexing for nth-of-type
+    // rather than nth-child
+    index: function(parentNode, reverse, ofType) {
+      parentNode._countedByPrototype = Prototype.emptyFunction;
+      if (reverse) {
+        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+          var node = nodes[i];
+          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+        }
+      } else {
+        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+      }
+    },
+
+    // filters out duplicates and extends all nodes
+    unique: function(nodes) {
+      if (nodes.length == 0) return nodes;
+      var results = [], n;
+      for (var i = 0, l = nodes.length; i < l; i++)
+        if (!(n = nodes[i])._countedByPrototype) {
+          n._countedByPrototype = Prototype.emptyFunction;
+          results.push(Element.extend(n));
+        }
+      return Selector.handlers.unmark(results);
+    },
+
+    // COMBINATOR FUNCTIONS
+    descendant: function(nodes) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        h.concat(results, node.getElementsByTagName('*'));
+      return results;
+    },
+
+    child: function(nodes) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        for (var j = 0, child; child = node.childNodes[j]; j++)
+          if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+      }
+      return results;
+    },
+
+    adjacent: function(nodes) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        var next = this.nextElementSibling(node);
+        if (next) results.push(next);
+      }
+      return results;
+    },
+
+    laterSibling: function(nodes) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        h.concat(results, Element.nextSiblings(node));
+      return results;
+    },
+
+    nextElementSibling: function(node) {
+      while (node = node.nextSibling)
+        if (node.nodeType == 1) return node;
+      return null;
+    },
+
+    previousElementSibling: function(node) {
+      while (node = node.previousSibling)
+        if (node.nodeType == 1) return node;
+      return null;
+    },
+
+    // TOKEN FUNCTIONS
+    tagName: function(nodes, root, tagName, combinator) {
+      var uTagName = tagName.toUpperCase();
+      var results = [], h = Selector.handlers;
+      if (nodes) {
+        if (combinator) {
+          // fastlane for ordinary descendant combinators
+          if (combinator == "descendant") {
+            for (var i = 0, node; node = nodes[i]; i++)
+              h.concat(results, node.getElementsByTagName(tagName));
+            return results;
+          } else nodes = this[combinator](nodes);
+          if (tagName == "*") return nodes;
+        }
+        for (var i = 0, node; node = nodes[i]; i++)
+          if (node.tagName.toUpperCase() === uTagName) results.push(node);
+        return results;
+      } else return root.getElementsByTagName(tagName);
+    },
+
+    id: function(nodes, root, id, combinator) {
+      var targetNode = $(id), h = Selector.handlers;
+      if (!targetNode) return [];
+      if (!nodes && root == document) return [targetNode];
+      if (nodes) {
+        if (combinator) {
+          if (combinator == 'child') {
+            for (var i = 0, node; node = nodes[i]; i++)
+              if (targetNode.parentNode == node) return [targetNode];
+          } else if (combinator == 'descendant') {
+            for (var i = 0, node; node = nodes[i]; i++)
+              if (Element.descendantOf(targetNode, node)) return [targetNode];
+          } else if (combinator == 'adjacent') {
+            for (var i = 0, node; node = nodes[i]; i++)
+              if (Selector.handlers.previousElementSibling(targetNode) == node)
+                return [targetNode];
+          } else nodes = h[combinator](nodes);
+        }
+        for (var i = 0, node; node = nodes[i]; i++)
+          if (node == targetNode) return [targetNode];
+        return [];
+      }
+      return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+    },
+
+    className: function(nodes, root, className, combinator) {
+      if (nodes && combinator) nodes = this[combinator](nodes);
+      return Selector.handlers.byClassName(nodes, root, className);
+    },
+
+    byClassName: function(nodes, root, className) {
+      if (!nodes) nodes = Selector.handlers.descendant([root]);
+      var needle = ' ' + className + ' ';
+      for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+        nodeClassName = node.className;
+        if (nodeClassName.length == 0) continue;
+        if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+          results.push(node);
+      }
+      return results;
+    },
+
+    attrPresence: function(nodes, root, attr, combinator) {
+      if (!nodes) nodes = root.getElementsByTagName("*");
+      if (nodes && combinator) nodes = this[combinator](nodes);
+      var results = [];
+      for (var i = 0, node; node = nodes[i]; i++)
+        if (Element.hasAttribute(node, attr)) results.push(node);
+      return results;
+    },
+
+    attr: function(nodes, root, attr, value, operator, combinator) {
+      if (!nodes) nodes = root.getElementsByTagName("*");
+      if (nodes && combinator) nodes = this[combinator](nodes);
+      var handler = Selector.operators[operator], results = [];
+      for (var i = 0, node; node = nodes[i]; i++) {
+        var nodeValue = Element.readAttribute(node, attr);
+        if (nodeValue === null) continue;
+        if (handler(nodeValue, value)) results.push(node);
+      }
+      return results;
+    },
+
+    pseudo: function(nodes, name, value, root, combinator) {
+      if (nodes && combinator) nodes = this[combinator](nodes);
+      if (!nodes) nodes = root.getElementsByTagName("*");
+      return Selector.pseudos[name](nodes, value, root);
+    }
+  },
+
+  pseudos: {
+    'first-child': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        if (Selector.handlers.previousElementSibling(node)) continue;
+          results.push(node);
+      }
+      return results;
+    },
+    'last-child': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        if (Selector.handlers.nextElementSibling(node)) continue;
+          results.push(node);
+      }
+      return results;
+    },
+    'only-child': function(nodes, value, root) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+          results.push(node);
+      return results;
+    },
+    'nth-child':        function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root);
+    },
+    'nth-last-child':   function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root, true);
+    },
+    'nth-of-type':      function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root, false, true);
+    },
+    'nth-last-of-type': function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root, true, true);
+    },
+    'first-of-type':    function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, "1", root, false, true);
+    },
+    'last-of-type':     function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, "1", root, true, true);
+    },
+    'only-of-type':     function(nodes, formula, root) {
+      var p = Selector.pseudos;
+      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+    },
+
+    // handles the an+b logic
+    getIndices: function(a, b, total) {
+      if (a == 0) return b > 0 ? [b] : [];
+      return $R(1, total).inject([], function(memo, i) {
+        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+        return memo;
+      });
+    },
+
+    // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+    nth: function(nodes, formula, root, reverse, ofType) {
+      if (nodes.length == 0) return [];
+      if (formula == 'even') formula = '2n+0';
+      if (formula == 'odd')  formula = '2n+1';
+      var h = Selector.handlers, results = [], indexed = [], m;
+      h.mark(nodes);
+      for (var i = 0, node; node = nodes[i]; i++) {
+        if (!node.parentNode._countedByPrototype) {
+          h.index(node.parentNode, reverse, ofType);
+          indexed.push(node.parentNode);
+        }
+      }
+      if (formula.match(/^\d+$/)) { // just a number
+        formula = Number(formula);
+        for (var i = 0, node; node = nodes[i]; i++)
+          if (node.nodeIndex == formula) results.push(node);
+      } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+        if (m[1] == "-") m[1] = -1;
+        var a = m[1] ? Number(m[1]) : 1;
+        var b = m[2] ? Number(m[2]) : 0;
+        var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+          for (var j = 0; j < l; j++)
+            if (node.nodeIndex == indices[j]) results.push(node);
+        }
+      }
+      h.unmark(nodes);
+      h.unmark(indexed);
+      return results;
+    },
+
+    'empty': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        // IE treats comments as element nodes
+        if (node.tagName == '!' || node.firstChild) continue;
+        results.push(node);
+      }
+      return results;
+    },
+
+    'not': function(nodes, selector, root) {
+      var h = Selector.handlers, selectorType, m;
+      var exclusions = new Selector(selector).findElements(root);
+      h.mark(exclusions);
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (!node._countedByPrototype) results.push(node);
+      h.unmark(exclusions);
+      return results;
+    },
+
+    'enabled': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (!node.disabled && (!node.type || node.type !== 'hidden'))
+          results.push(node);
+      return results;
+    },
+
+    'disabled': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (node.disabled) results.push(node);
+      return results;
+    },
+
+    'checked': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (node.checked) results.push(node);
+      return results;
+    }
+  },
+
+  operators: {
+    '=':  function(nv, v) { return nv == v; },
+    '!=': function(nv, v) { return nv != v; },
+    '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
+    '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
+    '*=': function(nv, v) { return nv == v || nv && nv.include(v); },
+    '$=': function(nv, v) { return nv.endsWith(v); },
+    '*=': function(nv, v) { return nv.include(v); },
+    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+    '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() +
+     '-').include('-' + (v || "").toUpperCase() + '-'); }
+  },
+
+  split: function(expression) {
+    var expressions = [];
+    expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+      expressions.push(m[1].strip());
+    });
+    return expressions;
+  },
+
+  matchElements: function(elements, expression) {
+    var matches = $$(expression), h = Selector.handlers;
+    h.mark(matches);
+    for (var i = 0, results = [], element; element = elements[i]; i++)
+      if (element._countedByPrototype) results.push(element);
+    h.unmark(matches);
+    return results;
+  },
+
+  findElement: function(elements, expression, index) {
+    if (Object.isNumber(expression)) {
+      index = expression; expression = false;
+    }
+    return Selector.matchElements(elements, expression || '*')[index || 0];
+  },
+
+  findChildElements: function(element, expressions) {
+    expressions = Selector.split(expressions.join(','));
+    var results = [], h = Selector.handlers;
+    for (var i = 0, l = expressions.length, selector; i < l; i++) {
+      selector = new Selector(expressions[i].strip());
+      h.concat(results, selector.findElements(element));
+    }
+    return (l > 1) ? h.unique(results) : results;
+  }
+});
+
+if (Prototype.Browser.IE) {
+  Object.extend(Selector.handlers, {
+    // IE returns comment nodes on getElementsByTagName("*").
+    // Filter them out.
+    concat: function(a, b) {
+      for (var i = 0, node; node = b[i]; i++)
+        if (node.tagName !== "!") a.push(node);
+      return a;
+    },
+
+    // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+    unmark: function(nodes) {
+      for (var i = 0, node; node = nodes[i]; i++)
+        node.removeAttribute('_countedByPrototype');
+      return nodes;
+    }
+  });
+}
+
+function $$() {
+  return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+  reset: function(form) {
+    $(form).reset();
+    return form;
+  },
+
+  serializeElements: function(elements, options) {
+    if (typeof options != 'object') options = { hash: !!options };
+    else if (Object.isUndefined(options.hash)) options.hash = true;
+    var key, value, submitted = false, submit = options.submit;
+
+    var data = elements.inject({ }, function(result, element) {
+      if (!element.disabled && element.name) {
+        key = element.name; value = $(element).getValue();
+        if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
+            submit !== false && (!submit || key == submit) && (submitted = true)))) {
+          if (key in result) {
+            // a key is already present; construct an array of values
+            if (!Object.isArray(result[key])) result[key] = [result[key]];
+            result[key].push(value);
+          }
+          else result[key] = value;
+        }
+      }
+      return result;
+    });
+
+    return options.hash ? data : Object.toQueryString(data);
+  }
+};
+
+Form.Methods = {
+  serialize: function(form, options) {
+    return Form.serializeElements(Form.getElements(form), options);
+  },
+
+  getElements: function(form) {
+    return $A($(form).getElementsByTagName('*')).inject([],
+      function(elements, child) {
+        if (Form.Element.Serializers[child.tagName.toLowerCase()])
+          elements.push(Element.extend(child));
+        return elements;
+      }
+    );
+  },
+
+  getInputs: function(form, typeName, name) {
+    form = $(form);
+    var inputs = form.getElementsByTagName('input');
+
+    if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+      var input = inputs[i];
+      if ((typeName && input.type != typeName) || (name && input.name != name))
+        continue;
+      matchingInputs.push(Element.extend(input));
+    }
+
+    return matchingInputs;
+  },
+
+  disable: function(form) {
+    form = $(form);
+    Form.getElements(form).invoke('disable');
+    return form;
+  },
+
+  enable: function(form) {
+    form = $(form);
+    Form.getElements(form).invoke('enable');
+    return form;
+  },
+
+  findFirstElement: function(form) {
+    var elements = $(form).getElements().findAll(function(element) {
+      return 'hidden' != element.type && !element.disabled;
+    });
+    var firstByIndex = elements.findAll(function(element) {
+      return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+    }).sortBy(function(element) { return element.tabIndex }).first();
+
+    return firstByIndex ? firstByIndex : elements.find(function(element) {
+      return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+    });
+  },
+
+  focusFirstElement: function(form) {
+    form = $(form);
+    form.findFirstElement().activate();
+    return form;
+  },
+
+  request: function(form, options) {
+    form = $(form), options = Object.clone(options || { });
+
+    var params = options.parameters, action = form.readAttribute('action') || '';
+    if (action.blank()) action = window.location.href;
+    options.parameters = form.serialize(true);
+
+    if (params) {
+      if (Object.isString(params)) params = params.toQueryParams();
+      Object.extend(options.parameters, params);
+    }
+
+    if (form.hasAttribute('method') && !options.method)
+      options.method = form.method;
+
+    return new Ajax.Request(action, options);
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+  focus: function(element) {
+    $(element).focus();
+    return element;
+  },
+
+  select: function(element) {
+    $(element).select();
+    return element;
+  }
+};
+
+Form.Element.Methods = {
+  serialize: function(element) {
+    element = $(element);
+    if (!element.disabled && element.name) {
+      var value = element.getValue();
+      if (value != undefined) {
+        var pair = { };
+        pair[element.name] = value;
+        return Object.toQueryString(pair);
+      }
+    }
+    return '';
+  },
+
+  getValue: function(element) {
+    element = $(element);
+    var method = element.tagName.toLowerCase();
+    return Form.Element.Serializers[method](element);
+  },
+
+  setValue: function(element, value) {
+    element = $(element);
+    var method = element.tagName.toLowerCase();
+    Form.Element.Serializers[method](element, value);
+    return element;
+  },
+
+  clear: function(element) {
+    $(element).value = '';
+    return element;
+  },
+
+  present: function(element) {
+    return $(element).value != '';
+  },
+
+  activate: function(element) {
+    element = $(element);
+    try {
+      element.focus();
+      if (element.select && (element.tagName.toLowerCase() != 'input' ||
+          !['button', 'reset', 'submit'].include(element.type)))
+        element.select();
+    } catch (e) { }
+    return element;
+  },
+
+  disable: function(element) {
+    element = $(element);
+    element.disabled = true;
+    return element;
+  },
+
+  enable: function(element) {
+    element = $(element);
+    element.disabled = false;
+    return element;
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+  input: function(element, value) {
+    switch (element.type.toLowerCase()) {
+      case 'checkbox':
+      case 'radio':
+        return Form.Element.Serializers.inputSelector(element, value);
+      default:
+        return Form.Element.Serializers.textarea(element, value);
+    }
+  },
+
+  inputSelector: function(element, value) {
+    if (Object.isUndefined(value)) return element.checked ? element.value : null;
+    else element.checked = !!value;
+  },
+
+  textarea: function(element, value) {
+    if (Object.isUndefined(value)) return element.value;
+    else element.value = value;
+  },
+
+  select: function(element, value) {
+    if (Object.isUndefined(value))
+      return this[element.type == 'select-one' ?
+        'selectOne' : 'selectMany'](element);
+    else {
+      var opt, currentValue, single = !Object.isArray(value);
+      for (var i = 0, length = element.length; i < length; i++) {
+        opt = element.options[i];
+        currentValue = this.optionValue(opt);
+        if (single) {
+          if (currentValue == value) {
+            opt.selected = true;
+            return;
+          }
+        }
+        else opt.selected = value.include(currentValue);
+      }
+    }
+  },
+
+  selectOne: function(element) {
+    var index = element.selectedIndex;
+    return index >= 0 ? this.optionValue(element.options[index]) : null;
+  },
+
+  selectMany: function(element) {
+    var values, length = element.length;
+    if (!length) return null;
+
+    for (var i = 0, values = []; i < length; i++) {
+      var opt = element.options[i];
+      if (opt.selected) values.push(this.optionValue(opt));
+    }
+    return values;
+  },
+
+  optionValue: function(opt) {
+    // extend element because hasAttribute may not be native
+    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+  initialize: function($super, element, frequency, callback) {
+    $super(callback, frequency);
+    this.element   = $(element);
+    this.lastValue = this.getValue();
+  },
+
+  execute: function() {
+    var value = this.getValue();
+    if (Object.isString(this.lastValue) && Object.isString(value) ?
+        this.lastValue != value : String(this.lastValue) != String(value)) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+  initialize: function(element, callback) {
+    this.element  = $(element);
+    this.callback = callback;
+
+    this.lastValue = this.getValue();
+    if (this.element.tagName.toLowerCase() == 'form')
+      this.registerFormCallbacks();
+    else
+      this.registerCallback(this.element);
+  },
+
+  onElementEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  },
+
+  registerFormCallbacks: function() {
+    Form.getElements(this.element).each(this.registerCallback, this);
+  },
+
+  registerCallback: function(element) {
+    if (element.type) {
+      switch (element.type.toLowerCase()) {
+        case 'checkbox':
+        case 'radio':
+          Event.observe(element, 'click', this.onElementEvent.bind(this));
+          break;
+        default:
+          Event.observe(element, 'change', this.onElementEvent.bind(this));
+          break;
+      }
+    }
+  }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+  KEY_BACKSPACE: 8,
+  KEY_TAB:       9,
+  KEY_RETURN:   13,
+  KEY_ESC:      27,
+  KEY_LEFT:     37,
+  KEY_UP:       38,
+  KEY_RIGHT:    39,
+  KEY_DOWN:     40,
+  KEY_DELETE:   46,
+  KEY_HOME:     36,
+  KEY_END:      35,
+  KEY_PAGEUP:   33,
+  KEY_PAGEDOWN: 34,
+  KEY_INSERT:   45,
+
+  cache: { },
+
+  relatedTarget: function(event) {
+    var element;
+    switch(event.type) {
+      case 'mouseover': element = event.fromElement; break;
+      case 'mouseout':  element = event.toElement;   break;
+      default: return null;
+    }
+    return Element.extend(element);
+  }
+});
+
+Event.Methods = (function() {
+  var isButton;
+
+  if (Prototype.Browser.IE) {
+    var buttonMap = { 0: 1, 1: 4, 2: 2 };
+    isButton = function(event, code) {
+      return event.button == buttonMap[code];
+    };
+
+  } else if (Prototype.Browser.WebKit) {
+    isButton = function(event, code) {
+      switch (code) {
+        case 0: return event.which == 1 && !event.metaKey;
+        case 1: return event.which == 1 && event.metaKey;
+        default: return false;
+      }
+    };
+
+  } else {
+    isButton = function(event, code) {
+      return event.which ? (event.which === code + 1) : (event.button === code);
+    };
+  }
+
+  return {
+    isLeftClick:   function(event) { return isButton(event, 0) },
+    isMiddleClick: function(event) { return isButton(event, 1) },
+    isRightClick:  function(event) { return isButton(event, 2) },
+
+    element: function(event) {
+      event = Event.extend(event);
+
+      var node          = event.target,
+          type          = event.type,
+          currentTarget = event.currentTarget;
+
+      if (currentTarget && currentTarget.tagName) {
+        // Firefox screws up the "click" event when moving between radio buttons
+        // via arrow keys. It also screws up the "load" and "error" events on images,
+        // reporting the document as the target instead of the original image.
+        if (type === 'load' || type === 'error' ||
+          (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
+            && currentTarget.type === 'radio'))
+              node = currentTarget;
+      }
+      if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
+      return Element.extend(node);
+    },
+
+    findElement: function(event, expression) {
+      var element = Event.element(event);
+      if (!expression) return element;
+      var elements = [element].concat(element.ancestors());
+      return Selector.findElement(elements, expression, 0);
+    },
+
+    pointer: function(event) {
+      var docElement = document.documentElement,
+      body = document.body || { scrollLeft: 0, scrollTop: 0 };
+      return {
+        x: event.pageX || (event.clientX +
+          (docElement.scrollLeft || body.scrollLeft) -
+          (docElement.clientLeft || 0)),
+        y: event.pageY || (event.clientY +
+          (docElement.scrollTop || body.scrollTop) -
+          (docElement.clientTop || 0))
+      };
+    },
+
+    pointerX: function(event) { return Event.pointer(event).x },
+    pointerY: function(event) { return Event.pointer(event).y },
+
+    stop: function(event) {
+      Event.extend(event);
+      event.preventDefault();
+      event.stopPropagation();
+      event.stopped = true;
+    }
+  };
+})();
+
+Event.extend = (function() {
+  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+    m[name] = Event.Methods[name].methodize();
+    return m;
+  });
+
+  if (Prototype.Browser.IE) {
+    Object.extend(methods, {
+      stopPropagation: function() { this.cancelBubble = true },
+      preventDefault:  function() { this.returnValue = false },
+      inspect: function() { return "[object Event]" }
+    });
+
+    return function(event) {
+      if (!event) return false;
+      if (event._extendedByPrototype) return event;
+
+      event._extendedByPrototype = Prototype.emptyFunction;
+      var pointer = Event.pointer(event);
+      Object.extend(event, {
+        target: event.srcElement,
+        relatedTarget: Event.relatedTarget(event),
+        pageX:  pointer.x,
+        pageY:  pointer.y
+      });
+      return Object.extend(event, methods);
+    };
+
+  } else {
+    Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__'];
+    Object.extend(Event.prototype, methods);
+    return Prototype.K;
+  }
+})();
+
+Object.extend(Event, (function() {
+  var cache = Event.cache;
+
+  function getEventID(element) {
+    if (element._prototypeEventID) return element._prototypeEventID[0];
+    arguments.callee.id = arguments.callee.id || 1;
+    return element._prototypeEventID = [++arguments.callee.id];
+  }
+
+  function getDOMEventName(eventName) {
+    if (eventName && eventName.include(':')) return "dataavailable";
+    return eventName;
+  }
+
+  function getCacheForID(id) {
+    return cache[id] = cache[id] || { };
+  }
+
+  function getWrappersForEventName(id, eventName) {
+    var c = getCacheForID(id);
+    return c[eventName] = c[eventName] || [];
+  }
+
+  function createWrapper(element, eventName, handler) {
+    var id = getEventID(element);
+    var c = getWrappersForEventName(id, eventName);
+    if (c.pluck("handler").include(handler)) return false;
+
+    var wrapper = function(event) {
+      if (!Event || !Event.extend ||
+        (event.eventName && event.eventName != eventName))
+          return false;
+
+      Event.extend(event);
+      handler.call(element, event);
+    };
+
+    wrapper.handler = handler;
+    c.push(wrapper);
+    return wrapper;
+  }
+
+  function findWrapper(id, eventName, handler) {
+    var c = getWrappersForEventName(id, eventName);
+    return c.find(function(wrapper) { return wrapper.handler == handler });
+  }
+
+  function destroyWrapper(id, eventName, handler) {
+    var c = getCacheForID(id);
+    if (!c[eventName]) return false;
+    c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+  }
+
+  function destroyCache() {
+    for (var id in cache)
+      for (var eventName in cache[id])
+        cache[id][eventName] = null;
+  }
+
+
+  // Internet Explorer needs to remove event handlers on page unload
+  // in order to avoid memory leaks.
+  if (window.attachEvent) {
+    window.attachEvent("onunload", destroyCache);
+  }
+
+  // Safari has a dummy event handler on page unload so that it won't
+  // use its bfcache. Safari <= 3.1 has an issue with restoring the "document"
+  // object when page is returned to via the back button using its bfcache.
+  if (Prototype.Browser.WebKit) {
+    window.addEventListener('unload', Prototype.emptyFunction, false);
+  }
+
+  return {
+    observe: function(element, eventName, handler) {
+      element = $(element);
+      var name = getDOMEventName(eventName);
+
+      var wrapper = createWrapper(element, eventName, handler);
+      if (!wrapper) return element;
+
+      if (element.addEventListener) {
+        element.addEventListener(name, wrapper, false);
+      } else {
+        element.attachEvent("on" + name, wrapper);
+      }
+
+      return element;
+    },
+
+    stopObserving: function(element, eventName, handler) {
+      element = $(element);
+      var id = getEventID(element), name = getDOMEventName(eventName);
+
+      if (!handler && eventName) {
+        getWrappersForEventName(id, eventName).each(function(wrapper) {
+          element.stopObserving(eventName, wrapper.handler);
+        });
+        return element;
+
+      } else if (!eventName) {
+        Object.keys(getCacheForID(id)).each(function(eventName) {
+          element.stopObserving(eventName);
+        });
+        return element;
+      }
+
+      var wrapper = findWrapper(id, eventName, handler);
+      if (!wrapper) return element;
+
+      if (element.removeEventListener) {
+        element.removeEventListener(name, wrapper, false);
+      } else {
+        element.detachEvent("on" + name, wrapper);
+      }
+
+      destroyWrapper(id, eventName, handler);
+
+      return element;
+    },
+
+    fire: function(element, eventName, memo) {
+      element = $(element);
+      if (element == document && document.createEvent && !element.dispatchEvent)
+        element = document.documentElement;
+
+      var event;
+      if (document.createEvent) {
+        event = document.createEvent("HTMLEvents");
+        event.initEvent("dataavailable", true, true);
+      } else {
+        event = document.createEventObject();
+        event.eventType = "ondataavailable";
+      }
+
+      event.eventName = eventName;
+      event.memo = memo || { };
+
+      if (document.createEvent) {
+        element.dispatchEvent(event);
+      } else {
+        element.fireEvent(event.eventType, event);
+      }
+
+      return Event.extend(event);
+    }
+  };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+  fire:          Event.fire,
+  observe:       Event.observe,
+  stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+  fire:          Element.Methods.fire.methodize(),
+  observe:       Element.Methods.observe.methodize(),
+  stopObserving: Element.Methods.stopObserving.methodize(),
+  loaded:        false
+});
+
+(function() {
+  /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+     Matthias Miller, Dean Edwards and John Resig. */
+
+  var timer;
+
+  function fireContentLoadedEvent() {
+    if (document.loaded) return;
+    if (timer) window.clearInterval(timer);
+    document.fire("dom:loaded");
+    document.loaded = true;
+  }
+
+  if (document.addEventListener) {
+    if (Prototype.Browser.WebKit) {
+      timer = window.setInterval(function() {
+        if (/loaded|complete/.test(document.readyState))
+          fireContentLoadedEvent();
+      }, 0);
+
+      Event.observe(window, "load", fireContentLoadedEvent);
+
+    } else {
+      document.addEventListener("DOMContentLoaded",
+        fireContentLoadedEvent, false);
+    }
+
+  } else {
+    document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+    $("__onDOMContentLoaded").onreadystatechange = function() {
+      if (this.readyState == "complete") {
+        this.onreadystatechange = null;
+        fireContentLoadedEvent();
+      }
+    };
+  }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+  Before: function(element, content) {
+    return Element.insert(element, {before:content});
+  },
+
+  Top: function(element, content) {
+    return Element.insert(element, {top:content});
+  },
+
+  Bottom: function(element, content) {
+    return Element.insert(element, {bottom:content});
+  },
+
+  After: function(element, content) {
+    return Element.insert(element, {after:content});
+  }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+  // set to true if needed, warning: firefox performance problems
+  // NOT neeeded for page scrolling, only if draggable contained in
+  // scrollable elements
+  includeScrollOffsets: false,
+
+  // must be called before calling withinIncludingScrolloffset, every time the
+  // page is scrolled
+  prepare: function() {
+    this.deltaX =  window.pageXOffset
+                || document.documentElement.scrollLeft
+                || document.body.scrollLeft
+                || 0;
+    this.deltaY =  window.pageYOffset
+                || document.documentElement.scrollTop
+                || document.body.scrollTop
+                || 0;
+  },
+
+  // caches x/y coordinate pair to use with overlap
+  within: function(element, x, y) {
+    if (this.includeScrollOffsets)
+      return this.withinIncludingScrolloffsets(element, x, y);
+    this.xcomp = x;
+    this.ycomp = y;
+    this.offset = Element.cumulativeOffset(element);
+
+    return (y >= this.offset[1] &&
+            y <  this.offset[1] + element.offsetHeight &&
+            x >= this.offset[0] &&
+            x <  this.offset[0] + element.offsetWidth);
+  },
+
+  withinIncludingScrolloffsets: function(element, x, y) {
+    var offsetcache = Element.cumulativeScrollOffset(element);
+
+    this.xcomp = x + offsetcache[0] - this.deltaX;
+    this.ycomp = y + offsetcache[1] - this.deltaY;
+    this.offset = Element.cumulativeOffset(element);
+
+    return (this.ycomp >= this.offset[1] &&
+            this.ycomp <  this.offset[1] + element.offsetHeight &&
+            this.xcomp >= this.offset[0] &&
+            this.xcomp <  this.offset[0] + element.offsetWidth);
+  },
+
+  // within must be called directly before
+  overlap: function(mode, element) {
+    if (!mode) return 0;
+    if (mode == 'vertical')
+      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+        element.offsetHeight;
+    if (mode == 'horizontal')
+      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+        element.offsetWidth;
+  },
+
+  // Deprecation layer -- use newer Element methods now (1.5.2).
+
+  cumulativeOffset: Element.Methods.cumulativeOffset,
+
+  positionedOffset: Element.Methods.positionedOffset,
+
+  absolutize: function(element) {
+    Position.prepare();
+    return Element.absolutize(element);
+  },
+
+  relativize: function(element) {
+    Position.prepare();
+    return Element.relativize(element);
+  },
+
+  realOffset: Element.Methods.cumulativeScrollOffset,
+
+  offsetParent: Element.Methods.getOffsetParent,
+
+  page: Element.Methods.viewportOffset,
+
+  clone: function(source, target, options) {
+    options = options || { };
+    return Element.clonePosition(target, source, options);
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+  function iter(name) {
+    return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+  }
+
+  instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+  function(element, className) {
+    className = className.toString().strip();
+    var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+    return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+  } : function(element, className) {
+    className = className.toString().strip();
+    var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+    if (!classNames && !className) return elements;
+
+    var nodes = $(element).getElementsByTagName('*');
+    className = ' ' + className + ' ';
+
+    for (var i = 0, child, cn; child = nodes[i]; i++) {
+      if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+          (classNames && classNames.all(function(name) {
+            return !name.toString().blank() && cn.include(' ' + name + ' ');
+          }))))
+        elements.push(Element.extend(child));
+    }
+    return elements;
+  };
+
+  return function(className, parentElement) {
+    return $(parentElement || document.body).getElementsByClassName(className);
+  };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+  initialize: function(element) {
+    this.element = $(element);
+  },
+
+  _each: function(iterator) {
+    this.element.className.split(/\s+/).select(function(name) {
+      return name.length > 0;
+    })._each(iterator);
+  },
+
+  set: function(className) {
+    this.element.className = className;
+  },
+
+  add: function(classNameToAdd) {
+    if (this.include(classNameToAdd)) return;
+    this.set($A(this).concat(classNameToAdd).join(' '));
+  },
+
+  remove: function(classNameToRemove) {
+    if (!this.include(classNameToRemove)) return;
+    this.set($A(this).without(classNameToRemove).join(' '));
+  },
+
+  toString: function() {
+    return $A(this).join(' ');
+  }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods();
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/web/js/scriptaculous.js	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,60 @@
+// script.aculo.us scriptaculous.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// 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.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+  Version: '1.8.2',
+  require: function(libraryName) {
+    // inserting via DOM fails in Safari 2.0, so brute force approach
+    document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+  },
+  REQUIRED_PROTOTYPE: '1.6.0.3',
+  load: function() {
+    function convertVersionString(versionString) {
+      var v = versionString.replace(/_.*|\./g, '');
+      v = parseInt(v + '0'.times(4-v.length));
+      return versionString.indexOf('_') > -1 ? v-1 : v;
+    }
+
+    if((typeof Prototype=='undefined') ||
+       (typeof Element == 'undefined') ||
+       (typeof Element.Methods=='undefined') ||
+       (convertVersionString(Prototype.Version) <
+        convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+       throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+        Scriptaculous.REQUIRED_PROTOTYPE);
+
+    var js = /scriptaculous\.js(\?.*)?$/;
+    $$('head script[src]').findAll(function(s) {
+      return s.src.match(js);
+    }).each(function(s) {
+      var path = s.src.replace(js, ''),
+      includes = s.src.match(/\?.*load=([a-z,]*)/);
+      (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+       function(include) { Scriptaculous.require(path+include+'.js') });
+    });
+  }
+};
+
+Scriptaculous.load();
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/web/js/slider.js	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+//  axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+//  onChange(value)
+//  onSlide(value)
+Control.Slider = Class.create({
+  initialize: function(handle, track, options) {
+    var slider = this;
+
+    if (Object.isArray(handle)) {
+      this.handles = handle.collect( function(e) { return $(e) });
+    } else {
+      this.handles = [$(handle)];
+    }
+
+    this.track   = $(track);
+    this.options = options || { };
+
+    this.axis      = this.options.axis || 'horizontal';
+    this.increment = this.options.increment || 1;
+    this.step      = parseInt(this.options.step || '1');
+    this.range     = this.options.range || $R(0,1);
+
+    this.value     = 0; // assure backwards compat
+    this.values    = this.handles.map( function() { return 0 });
+    this.spans     = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+    this.options.startSpan = $(this.options.startSpan || null);
+    this.options.endSpan   = $(this.options.endSpan || null);
+
+    this.restricted = this.options.restricted || false;
+
+    this.maximum   = this.options.maximum || this.range.end;
+    this.minimum   = this.options.minimum || this.range.start;
+
+    // Will be used to align the handle onto the track, if necessary
+    this.alignX = parseInt(this.options.alignX || '0');
+    this.alignY = parseInt(this.options.alignY || '0');
+
+    this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+    this.handleLength = this.isVertical() ?
+      (this.handles[0].offsetHeight != 0 ?
+        this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+      (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+        this.handles[0].style.width.replace(/px$/,""));
+
+    this.active   = false;
+    this.dragging = false;
+    this.disabled = false;
+
+    if (this.options.disabled) this.setDisabled();
+
+    // Allowed values array
+    this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+    if (this.allowedValues) {
+      this.minimum = this.allowedValues.min();
+      this.maximum = this.allowedValues.max();
+    }
+
+    this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+    this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
+    this.eventMouseMove = this.update.bindAsEventListener(this);
+
+    // Initialize handles in reverse (make sure first handle is active)
+    this.handles.each( function(h,i) {
+      i = slider.handles.length-1-i;
+      slider.setValue(parseFloat(
+        (Object.isArray(slider.options.sliderValue) ?
+          slider.options.sliderValue[i] : slider.options.sliderValue) ||
+         slider.range.start), i);
+      h.makePositioned().observe("mousedown", slider.eventMouseDown);
+    });
+
+    this.track.observe("mousedown", this.eventMouseDown);
+    document.observe("mouseup", this.eventMouseUp);
+    document.observe("mousemove", this.eventMouseMove);
+
+    this.initialized = true;
+  },
+  dispose: function() {
+    var slider = this;
+    Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+    Event.stopObserving(document, "mouseup", this.eventMouseUp);
+    Event.stopObserving(document, "mousemove", this.eventMouseMove);
+    this.handles.each( function(h) {
+      Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+    });
+  },
+  setDisabled: function(){
+    this.disabled = true;
+  },
+  setEnabled: function(){
+    this.disabled = false;
+  },
+  getNearestValue: function(value){
+    if (this.allowedValues){
+      if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+      if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+      var offset = Math.abs(this.allowedValues[0] - value);
+      var newValue = this.allowedValues[0];
+      this.allowedValues.each( function(v) {
+        var currentOffset = Math.abs(v - value);
+        if (currentOffset <= offset){
+          newValue = v;
+          offset = currentOffset;
+        }
+      });
+      return newValue;
+    }
+    if (value > this.range.end) return this.range.end;
+    if (value < this.range.start) return this.range.start;
+    return value;
+  },
+  setValue: function(sliderValue, handleIdx){
+    if (!this.active) {
+      this.activeHandleIdx = handleIdx || 0;
+      this.activeHandle    = this.handles[this.activeHandleIdx];
+      this.updateStyles();
+    }
+    handleIdx = handleIdx || this.activeHandleIdx || 0;
+    if (this.initialized && this.restricted) {
+      if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+        sliderValue = this.values[handleIdx-1];
+      if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+        sliderValue = this.values[handleIdx+1];
+    }
+    sliderValue = this.getNearestValue(sliderValue);
+    this.values[handleIdx] = sliderValue;
+    this.value = this.values[0]; // assure backwards compat
+
+    this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+      this.translateToPx(sliderValue);
+
+    this.drawSpans();
+    if (!this.dragging || !this.event) this.updateFinished();
+  },
+  setValueBy: function(delta, handleIdx) {
+    this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+      handleIdx || this.activeHandleIdx || 0);
+  },
+  translateToPx: function(value) {
+    return Math.round(
+      ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+      (value - this.range.start)) + "px";
+  },
+  translateToValue: function(offset) {
+    return ((offset/(this.trackLength-this.handleLength) *
+      (this.range.end-this.range.start)) + this.range.start);
+  },
+  getRange: function(range) {
+    var v = this.values.sortBy(Prototype.K);
+    range = range || 0;
+    return $R(v[range],v[range+1]);
+  },
+  minimumOffset: function(){
+    return(this.isVertical() ? this.alignY : this.alignX);
+  },
+  maximumOffset: function(){
+    return(this.isVertical() ?
+      (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+        this.track.style.height.replace(/px$/,"")) - this.alignY :
+      (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+        this.track.style.width.replace(/px$/,"")) - this.alignX);
+  },
+  isVertical:  function(){
+    return (this.axis == 'vertical');
+  },
+  drawSpans: function() {
+    var slider = this;
+    if (this.spans)
+      $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+    if (this.options.startSpan)
+      this.setSpan(this.options.startSpan,
+        $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+    if (this.options.endSpan)
+      this.setSpan(this.options.endSpan,
+        $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+  },
+  setSpan: function(span, range) {
+    if (this.isVertical()) {
+      span.style.top = this.translateToPx(range.start);
+      span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+    } else {
+      span.style.left = this.translateToPx(range.start);
+      span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+    }
+  },
+  updateStyles: function() {
+    this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+    Element.addClassName(this.activeHandle, 'selected');
+  },
+  startDrag: function(event) {
+    if (Event.isLeftClick(event)) {
+      if (!this.disabled){
+        this.active = true;
+
+        var handle = Event.element(event);
+        var pointer  = [Event.pointerX(event), Event.pointerY(event)];
+        var track = handle;
+        if (track==this.track) {
+          var offsets  = Position.cumulativeOffset(this.track);
+          this.event = event;
+          this.setValue(this.translateToValue(
+           (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+          ));
+          var offsets  = Position.cumulativeOffset(this.activeHandle);
+          this.offsetX = (pointer[0] - offsets[0]);
+          this.offsetY = (pointer[1] - offsets[1]);
+        } else {
+          // find the handle (prevents issues with Safari)
+          while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+            handle = handle.parentNode;
+
+          if (this.handles.indexOf(handle)!=-1) {
+            this.activeHandle    = handle;
+            this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+            this.updateStyles();
+
+            var offsets  = Position.cumulativeOffset(this.activeHandle);
+            this.offsetX = (pointer[0] - offsets[0]);
+            this.offsetY = (pointer[1] - offsets[1]);
+          }
+        }
+      }
+      Event.stop(event);
+    }
+  },
+  update: function(event) {
+   if (this.active) {
+      if (!this.dragging) this.dragging = true;
+      this.draw(event);
+      if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+      Event.stop(event);
+   }
+  },
+  draw: function(event) {
+    var pointer = [Event.pointerX(event), Event.pointerY(event)];
+    var offsets = Position.cumulativeOffset(this.track);
+    pointer[0] -= this.offsetX + offsets[0];
+    pointer[1] -= this.offsetY + offsets[1];
+    this.event = event;
+    this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+    if (this.initialized && this.options.onSlide)
+      this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+  },
+  endDrag: function(event) {
+    if (this.active && this.dragging) {
+      this.finishDrag(event, true);
+      Event.stop(event);
+    }
+    this.active = false;
+    this.dragging = false;
+  },
+  finishDrag: function(event, success) {
+    this.active = false;
+    this.dragging = false;
+    this.updateFinished();
+  },
+  updateFinished: function() {
+    if (this.initialized && this.options.onChange)
+      this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+    this.event = null;
+  }
+});
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/web/js/sound.js	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+  tracks: {},
+  _enabled: true,
+  template:
+    new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+  enable: function(){
+    Sound._enabled = true;
+  },
+  disable: function(){
+    Sound._enabled = false;
+  },
+  play: function(url){
+    if(!Sound._enabled) return;
+    var options = Object.extend({
+      track: 'global', url: url, replace: false
+    }, arguments[1] || {});
+
+    if(options.replace && this.tracks[options.track]) {
+      $R(0, this.tracks[options.track].id).each(function(id){
+        var sound = $('sound_'+options.track+'_'+id);
+        sound.Stop && sound.Stop();
+        sound.remove();
+      });
+      this.tracks[options.track] = null;
+    }
+
+    if(!this.tracks[options.track])
+      this.tracks[options.track] = { id: 0 };
+    else
+      this.tracks[options.track].id++;
+
+    options.id = this.tracks[options.track].id;
+    $$('body')[0].insert(
+      Prototype.Browser.IE ? new Element('bgsound',{
+        id: 'sound_'+options.track+'_'+options.id,
+        src: options.url, loop: 1, autostart: true
+      }) : Sound.template.evaluate(options));
+  }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+  if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+    Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>');
+  else
+    Sound.play = function(){};
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/thdProject/web/sfProtoculousPlugin/web/js/unittest.js	Mon Oct 05 16:58:06 2009 +0200
@@ -0,0 +1,568 @@
+// script.aculo.us unittest.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//           (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
+//           (c) 2005-2008 Michael Schuerig (http://www.schuerig.de/michael/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// experimental, Firefox-only
+Event.simulateMouse = function(element, eventName) {
+  var options = Object.extend({
+    pointerX: 0,
+    pointerY: 0,
+    buttons:  0,
+    ctrlKey:  false,
+    altKey:   false,
+    shiftKey: false,
+    metaKey:  false
+  }, arguments[2] || {});
+  var oEvent = document.createEvent("MouseEvents");
+  oEvent.initMouseEvent(eventName, true, true, document.defaultView, 
+    options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY, 
+    options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, 0, $(element));
+  
+  if(this.mark) Element.remove(this.mark);
+  this.mark = document.createElement('div');
+  this.mark.appendChild(document.createTextNode(" "));
+  document.body.appendChild(this.mark);
+  this.mark.style.position = 'absolute';
+  this.mark.style.top = options.pointerY + "px";
+  this.mark.style.left = options.pointerX + "px";
+  this.mark.style.width = "5px";
+  this.mark.style.height = "5px;";
+  this.mark.style.borderTop = "1px solid red;";
+  this.mark.style.borderLeft = "1px solid red;";
+  
+  if(this.step)
+    alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
+  
+  $(element).dispatchEvent(oEvent);
+};
+
+// Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
+// You need to downgrade to 1.0.4 for now to get this working
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
+Event.simulateKey = function(element, eventName) {
+  var options = Object.extend({
+    ctrlKey: false,
+    altKey: false,
+    shiftKey: false,
+    metaKey: false,
+    keyCode: 0,
+    charCode: 0
+  }, arguments[2] || {});
+
+  var oEvent = document.createEvent("KeyEvents");
+  oEvent.initKeyEvent(eventName, true, true, window, 
+    options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
+    options.keyCode, options.charCode );
+  $(element).dispatchEvent(oEvent);
+};
+
+Event.simulateKeys = function(element, command) {
+  for(var i=0; i<command.length; i++) {
+    Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
+  }
+};
+
+var Test = {};
+Test.Unit = {};
+
+// security exception workaround
+Test.Unit.inspect = Object.inspect;
+
+Test.Unit.Logger = Class.create();
+Test.Unit.Logger.prototype = {
+  initialize: function(log) {
+    this.log = $(log);
+    if (this.log) {
+      this._createLogTable();
+    }
+  },
+  start: function(testName) {
+    if (!this.log) return;
+    this.testName = testName;
+    this.lastLogLine = document.createElement('tr');
+    this.statusCell = document.createElement('td');
+    this.nameCell = document.createElement('td');
+    this.nameCell.className = "nameCell";
+    this.nameCell.appendChild(document.createTextNode(testName));
+    this.messageCell = document.createElement('td');
+    this.lastLogLine.appendChild(this.statusCell);
+    this.lastLogLine.appendChild(this.nameCell);
+    this.lastLogLine.appendChild(this.messageCell);
+    this.loglines.appendChild(this.lastLogLine);
+  },
+  finish: function(status, summary) {
+    if (!this.log) return;
+    this.lastLogLine.className = status;
+    this.statusCell.innerHTML = status;
+    this.messageCell.innerHTML = this._toHTML(summary);
+    this.addLinksToResults();
+  },
+  message: function(message) {
+    if (!this.log) return;
+    this.messageCell.innerHTML = this._toHTML(message);
+  },
+  summary: function(summary) {
+    if (!this.log) return;
+    this.logsummary.innerHTML = this._toHTML(summary);
+  },
+  _createLogTable: function() {
+    this.log.innerHTML =
+    '<div id="logsummary"></div>' +
+    '<table id="logtable">' +
+    '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
+    '<tbody id="loglines"></tbody>' +
+    '</table>';
+    this.logsummary = $('logsummary');
+    this.loglines = $('loglines');
+  },
+  _toHTML: function(txt) {
+    return txt.escapeHTML().replace(/\n/g,"<br/>");
+  },
+  addLinksToResults: function(){ 
+    $$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log
+      td.title = "Run only this test";
+      Event.observe(td, 'click', function(){ window.location.search = "?tests=" + td.innerHTML;});
+    });
+    $$("tr.passed .nameCell").each( function(td){ // todo: limit to children of this.log
+      td.title = "Run all tests";
+      Event.observe(td, 'click', function(){ window.location.search = "";});
+    });
+  }
+};
+
+Test.Unit.Runner = Class.create();
+Test.Unit.Runner.prototype = {
+  initialize: function(testcases) {
+    this.options = Object.extend({
+      testLog: 'testlog'
+    }, arguments[1] || {});
+    this.options.resultsURL = this.parseResultsURLQueryParameter();
+    this.options.tests      = this.parseTestsQueryParameter();
+    if (this.options.testLog) {
+      this.options.testLog = $(this.options.testLog) || null;
+    }
+    if(this.options.tests) {
+      this.tests = [];
+      for(var i = 0; i < this.options.tests.length; i++) {
+        if(/^test/.test(this.options.tests[i])) {
+          this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"]));
+        }
+      }
+    } else {
+      if (this.options.test) {
+        this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])];
+      } else {
+        this.tests = [];
+        for(var testcase in testcases) {
+          if(/^test/.test(testcase)) {
+            this.tests.push(
+               new Test.Unit.Testcase(
+                 this.options.context ? ' -> ' + this.options.titles[testcase] : testcase, 
+                 testcases[testcase], testcases["setup"], testcases["teardown"]
+               ));
+          }
+        }
+      }
+    }
+    this.currentTest = 0;
+    this.logger = new Test.Unit.Logger(this.options.testLog);
+    setTimeout(this.runTests.bind(this), 1000);
+  },
+  parseResultsURLQueryParameter: function() {
+    return window.location.search.parseQuery()["resultsURL"];
+  },
+  parseTestsQueryParameter: function(){
+    if (window.location.search.parseQuery()["tests"]){
+        return window.location.search.parseQuery()["tests"].split(',');
+    };
+  },
+  // Returns:
+  //  "ERROR" if there was an error,
+  //  "FAILURE" if there was a failure, or
+  //  "SUCCESS" if there was neither
+  getResult: function() {
+    var hasFailure = false;
+    for(var i=0;i<this.tests.length;i++) {
+      if (this.tests[i].errors > 0) {
+        return "ERROR";
+      }
+      if (this.tests[i].failures > 0) {
+        hasFailure = true;
+      }
+    }
+    if (hasFailure) {
+      return "FAILURE";
+    } else {
+      return "SUCCESS";
+    }
+  },
+  postResults: function() {
+    if (this.options.resultsURL) {
+      new Ajax.Request(this.options.resultsURL, 
+        { method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false });
+    }
+  },
+  runTests: function() {
+    var test = this.tests[this.currentTest];
+    if (!test) {
+      // finished!
+      this.postResults();
+      this.logger.summary(this.summary());
+      return;
+    }
+    if(!test.isWaiting) {
+      this.logger.start(test.name);
+    }
+    test.run();
+    if(test.isWaiting) {
+      this.logger.message("Waiting for " + test.timeToWait + "ms");
+      setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
+    } else {
+      this.logger.finish(test.status(), test.summary());
+      this.currentTest++;
+      // tail recursive, hopefully the browser will skip the stackframe
+      this.runTests();
+    }
+  },
+  summary: function() {
+    var assertions = 0;
+    var failures = 0;
+    var errors = 0;
+    var messages = [];
+    for(var i=0;i<this.tests.length;i++) {
+      assertions +=   this.tests[i].assertions;
+      failures   +=   this.tests[i].failures;
+      errors     +=   this.tests[i].errors;
+    }
+    return (
+      (this.options.context ? this.options.context + ': ': '') + 
+      this.tests.length + " tests, " + 
+      assertions + " assertions, " + 
+      failures   + " failures, " +
+      errors     + " errors");
+  }
+};
+
+Test.Unit.Assertions = Class.create();
+Test.Unit.Assertions.prototype = {
+  initialize: function() {
+    this.assertions = 0;
+    this.failures   = 0;
+    this.errors     = 0;
+    this.messages   = [];
+  },
+  summary: function() {
+    return (
+      this.assertions + " assertions, " + 
+      this.failures   + " failures, " +
+      this.errors     + " errors" + "\n" +
+      this.messages.join("\n"));
+  },
+  pass: function() {
+    this.assertions++;
+  },
+  fail: function(message) {
+    this.failures++;
+    this.messages.push("Failure: " + message);
+  },
+  info: function(message) {
+    this.messages.push("Info: " + message);
+  },
+  error: function(error) {
+    this.errors++;
+    this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")");
+  },
+  status: function() {
+    if (this.failures > 0) return 'failed';
+    if (this.errors > 0) return 'error';
+    return 'passed';
+  },
+  assert: function(expression) {
+    var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"';
+    try { expression ? this.pass() : 
+      this.fail(message); }
+    catch(e) { this.error(e); }
+  },
+  assertEqual: function(expected, actual) {
+    var message = arguments[2] || "assertEqual";
+    try { (expected == actual) ? this.pass() :
+      this.fail(message + ': expected "' + Test.Unit.inspect(expected) + 
+        '", actual "' + Test.Unit.inspect(actual) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertInspect: function(expected, actual) {
+    var message = arguments[2] || "assertInspect";
+    try { (expected == actual.inspect()) ? this.pass() :
+      this.fail(message + ': expected "' + Test.Unit.inspect(expected) + 
+        '", actual "' + Test.Unit.inspect(actual) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertEnumEqual: function(expected, actual) {
+    var message = arguments[2] || "assertEnumEqual";
+    try { $A(expected).length == $A(actual).length && 
+      expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ?
+        this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) + 
+          ', actual ' + Test.Unit.inspect(actual)); }
+    catch(e) { this.error(e); }
+  },
+  assertNotEqual: function(expected, actual) {
+    var message = arguments[2] || "assertNotEqual";
+    try { (expected != actual) ? this.pass() : 
+      this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertIdentical: function(expected, actual) { 
+    var message = arguments[2] || "assertIdentical"; 
+    try { (expected === actual) ? this.pass() : 
+      this.fail(message + ': expected "' + Test.Unit.inspect(expected) +  
+        '", actual "' + Test.Unit.inspect(actual) + '"'); } 
+    catch(e) { this.error(e); } 
+  },
+  assertNotIdentical: function(expected, actual) { 
+    var message = arguments[2] || "assertNotIdentical"; 
+    try { !(expected === actual) ? this.pass() : 
+      this.fail(message + ': expected "' + Test.Unit.inspect(expected) +  
+        '", actual "' + Test.Unit.inspect(actual) + '"'); } 
+    catch(e) { this.error(e); } 
+  },
+  assertNull: function(obj) {
+    var message = arguments[1] || 'assertNull';
+    try { (obj==null) ? this.pass() : 
+      this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertMatch: function(expected, actual) {
+    var message = arguments[2] || 'assertMatch';
+    var regex = new RegExp(expected);
+    try { (regex.exec(actual)) ? this.pass() :
+      this.fail(message + ' : regex: "' +  Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertHidden: function(element) {
+    var message = arguments[1] || 'assertHidden';
+    this.assertEqual("none", element.style.display, message);
+  },
+  assertNotNull: function(object) {
+    var message = arguments[1] || 'assertNotNull';
+    this.assert(object != null, message);
+  },
+  assertType: function(expected, actual) {
+    var message = arguments[2] || 'assertType';
+    try { 
+      (actual.constructor == expected) ? this.pass() : 
+      this.fail(message + ': expected "' + Test.Unit.inspect(expected) +  
+        '", actual "' + (actual.constructor) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertNotOfType: function(expected, actual) {
+    var message = arguments[2] || 'assertNotOfType';
+    try { 
+      (actual.constructor != expected) ? this.pass() : 
+      this.fail(message + ': expected "' + Test.Unit.inspect(expected) +  
+        '", actual "' + (actual.constructor) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertInstanceOf: function(expected, actual) {
+    var message = arguments[2] || 'assertInstanceOf';
+    try { 
+      (actual instanceof expected) ? this.pass() : 
+      this.fail(message + ": object was not an instance of the expected type"); }
+    catch(e) { this.error(e); } 
+  },
+  assertNotInstanceOf: function(expected, actual) {
+    var message = arguments[2] || 'assertNotInstanceOf';
+    try { 
+      !(actual instanceof expected) ? this.pass() : 
+      this.fail(message + ": object was an instance of the not expected type"); }
+    catch(e) { this.error(e); } 
+  },
+  assertRespondsTo: function(method, obj) {
+    var message = arguments[2] || 'assertRespondsTo';
+    try {
+      (obj[method] && typeof obj[method] == 'function') ? this.pass() : 
+      this.fail(message + ": object doesn't respond to [" + method + "]"); }
+    catch(e) { this.error(e); }
+  },
+  assertReturnsTrue: function(method, obj) {
+    var message = arguments[2] || 'assertReturnsTrue';
+    try {
+      var m = obj[method];
+      if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
+      m() ? this.pass() : 
+      this.fail(message + ": method returned false"); }
+    catch(e) { this.error(e); }
+  },
+  assertReturnsFalse: function(method, obj) {
+    var message = arguments[2] || 'assertReturnsFalse';
+    try {
+      var m = obj[method];
+      if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
+      !m() ? this.pass() : 
+      this.fail(message + ": method returned true"); }
+    catch(e) { this.error(e); }
+  },
+  assertRaise: function(exceptionName, method) {
+    var message = arguments[2] || 'assertRaise';
+    try { 
+      method();
+      this.fail(message + ": exception expected but none was raised"); }
+    catch(e) {
+      ((exceptionName == null) || (e.name==exceptionName)) ? this.pass() : this.error(e); 
+    }
+  },
+  assertElementsMatch: function() {
+    var expressions = $A(arguments), elements = $A(expressions.shift());
+    if (elements.length != expressions.length) {
+      this.fail('assertElementsMatch: size mismatch: ' + elements.length + ' elements, ' + expressions.length + ' expressions');
+      return false;
+    }
+    elements.zip(expressions).all(function(pair, index) {
+      var element = $(pair.first()), expression = pair.last();
+      if (element.match(expression)) return true;
+      this.fail('assertElementsMatch: (in index ' + index + ') expected ' + expression.inspect() + ' but got ' + element.inspect());
+    }.bind(this)) && this.pass();
+  },
+  assertElementMatches: function(element, expression) {
+    this.assertElementsMatch([element], expression);
+  },
+  benchmark: function(operation, iterations) {
+    var startAt = new Date();
+    (iterations || 1).times(operation);
+    var timeTaken = ((new Date())-startAt);
+    this.info((arguments[2] || 'Operation') + ' finished ' + 
+       iterations + ' iterations in ' + (timeTaken/1000)+'s' );
+    return timeTaken;
+  },
+  _isVisible: function(element) {
+    element = $(element);
+    if(!element.parentNode) return true;
+    this.assertNotNull(element);
+    if(element.style && Element.getStyle(element, 'display') == 'none')
+      return false;
+    
+    return this._isVisible(element.parentNode);
+  },
+  assertNotVisible: function(element) {
+    this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1]));
+  },
+  assertVisible: function(element) {
+    this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1]));
+  },
+  benchmark: function(operation, iterations) {
+    var startAt = new Date();
+    (iterations || 1).times(operation);
+    var timeTaken = ((new Date())-startAt);
+    this.info((arguments[2] || 'Operation') + ' finished ' + 
+       iterations + ' iterations in ' + (timeTaken/1000)+'s' );
+    return timeTaken;
+  }
+};
+
+Test.Unit.Testcase = Class.create();
+Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
+  initialize: function(name, test, setup, teardown) {
+    Test.Unit.Assertions.prototype.initialize.bind(this)();
+    this.name           = name;
+    
+    if(typeof test == 'string') {
+      test = test.gsub(/(\.should[^\(]+\()/,'#{0}this,');
+      test = test.gsub(/(\.should[^\(]+)\(this,\)/,'#{1}(this)');
+      this.test = function() {
+        eval('with(this){'+test+'}');
+      }
+    } else {
+      this.test = test || function() {};
+    }
+    
+    this.setup          = setup || function() {};
+    this.teardown       = teardown || function() {};
+    this.isWaiting      = false;
+    this.timeToWait     = 1000;
+  },
+  wait: function(time, nextPart) {
+    this.isWaiting = true;
+    this.test = nextPart;
+    this.timeToWait = time;
+  },
+  run: function() {
+    try {
+      try {
+        if (!this.isWaiting) this.setup.bind(this)();
+        this.isWaiting = false;
+        this.test.bind(this)();
+      } finally {
+        if(!this.isWaiting) {
+          this.teardown.bind(this)();
+        }
+      }
+    }
+    catch(e) { this.error(e); }
+  }
+});
+
+// *EXPERIMENTAL* BDD-style testing to please non-technical folk
+// This draws many ideas from RSpec http://rspec.rubyforge.org/
+
+Test.setupBDDExtensionMethods = function(){
+  var METHODMAP = {
+    shouldEqual:     'assertEqual',
+    shouldNotEqual:  'assertNotEqual',
+    shouldEqualEnum: 'assertEnumEqual',
+    shouldBeA:       'assertType',
+    shouldNotBeA:    'assertNotOfType',
+    shouldBeAn:      'assertType',
+    shouldNotBeAn:   'assertNotOfType',
+    shouldBeNull:    'assertNull',
+    shouldNotBeNull: 'assertNotNull',
+    
+    shouldBe:        'assertReturnsTrue',
+    shouldNotBe:     'assertReturnsFalse',
+    shouldRespondTo: 'assertRespondsTo'
+  };
+  var makeAssertion = function(assertion, args, object) { 
+   	this[assertion].apply(this,(args || []).concat([object]));
+  };
+  
+  Test.BDDMethods = {};   
+  $H(METHODMAP).each(function(pair) { 
+    Test.BDDMethods[pair.key] = function() { 
+       var args = $A(arguments); 
+       var scope = args.shift(); 
+       makeAssertion.apply(scope, [pair.value, args, this]); }; 
+  });
+  
+  [Array.prototype, String.prototype, Number.prototype, Boolean.prototype].each(
+    function(p){ Object.extend(p, Test.BDDMethods) }
+  );
+};
+
+Test.context = function(name, spec, log){
+  Test.setupBDDExtensionMethods();
+  
+  var compiledSpec = {};
+  var titles = {};
+  for(specName in spec) {
+    switch(specName){
+      case "setup":
+      case "teardown":
+        compiledSpec[specName] = spec[specName];
+        break;
+      default:
+        var testName = 'test'+specName.gsub(/\s+/,'-').camelize();
+        var body = spec[specName].toString().split('\n').slice(1);
+        if(/^\{/.test(body[0])) body = body.slice(1);
+        body.pop();
+        body = body.map(function(statement){ 
+          return statement.strip()
+        });
+        compiledSpec[testName] = body.join('\n');
+        titles[testName] = specName;
+    }
+  }
+  new Test.Unit.Runner(compiledSpec, { titles: titles, testLog: log || 'testlog', context: name });
+};
\ No newline at end of file