Last active
June 9, 2017 14:39
-
-
Save Kaapiii/1d681cde297563d9c426f2366beb4c4b to your computer and use it in GitHub Desktop.
Concrete5 - use a single EntityManager in version 5.7.5.6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// store location: application/src/Database | |
// Override the Core DatabaseServiceProvider | |
return array( | |
/** | |
* Core Providers | |
*/ | |
'providers' => array( | |
'core_database' => '\Application\Src\Database\DatabaseServiceProvider', | |
) | |
); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Application\Src\Database; | |
// store location: application/config | |
use Concrete\Core\Application\Application; | |
use Concrete\Core\Cache\Adapter\DoctrineCacheDriver; | |
use Concrete\Core\Database\Connection\Connection; | |
use Concrete\Core\Package\Package; | |
use Doctrine\ORM\EntityManager; | |
use Doctrine\ORM\Tools\Setup; | |
use Config; | |
use Database; | |
use Events; | |
class DatabaseManagerORM extends \Concrete\Core\Database\DatabaseManagerORM | |
{ | |
/** | |
* Makes a new entity manager instance for the given context | |
* (e.g. a package) or if no context object is given, for the application | |
* context. The options for the context are: | |
* - A package object, results in a package specific entity manager | |
* - The string 'core', results in a core specific entity manager | |
* - Null or omitted context, results in an application specific entity | |
* manager | |
* | |
* @param Connection $connection | |
* @param mixed $context | |
* @return \Doctrine\ORM\EntityManager | |
*/ | |
public static function makeEntityManager(Connection $connection, $context = null) | |
{ | |
if (is_object($context) && $context instanceof Package) { | |
$factory = $context->getEntityManagerFactory(); | |
} else { | |
if ($context === 'core') { | |
$path = DIR_BASE_CORE . '/' . DIRNAME_CLASSES; | |
//$factory = new EntityManagerFactory($path, $context); | |
} else { | |
$path = DIR_APPLICATION . '/' . DIRNAME_CLASSES; | |
} | |
$factory = new \Application\Src\Database\EntityManagerFactory($path, $context); | |
} | |
return $factory->create($connection); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Application\Src\Database; | |
// store location: application/src/Database | |
use Concrete\Core\Database\Connection\ConnectionFactory; | |
use Concrete\Core\Database\Driver\DriverManager; | |
use Concrete\Core\Foundation\Service\Provider as ServiceProvider; | |
class DatabaseServiceProvider extends ServiceProvider | |
{ | |
public function register() | |
{ | |
// Make both managers singletons | |
$this->app->singleton('Concrete\Core\Database\DatabaseManager'); | |
$this->app->singleton('Concrete\Core\Database\DatabaseManagerORM'); | |
// Bind both `database` and `database/orm` to their respective classes | |
$this->app->bind('database', 'Concrete\Core\Database\DatabaseManager'); | |
$this->app->bind('database/orm', '\Application\Src\Database\DatabaseManagerORM'); | |
// Bind a constructor for our DriverManager bootstrapped from config | |
$this->app->bind('Concrete\Core\Database\Driver\DriverManager', function ($app) { | |
$manager = new DriverManager($app); | |
$manager->configExtensions($app->make('config')->get('database.drivers')); | |
return $manager; | |
}); | |
// Bind a closure to support \Core::make('database/structure', $em); | |
$this->app->bind('database/structure', function ($app, $em) { | |
if (!is_array($em)) { | |
$em = array($em); | |
} | |
return $app->make('Concrete\Core\Database\DatabaseStructureManager', $em); | |
}); | |
// Bind default entity manager resolver | |
$this->app->bind('Doctrine\ORM\EntityManagerInterface', function ($app) { | |
return $app->make('Concrete\Core\Database\DatabaseManagerORM')->entityManager(); | |
}); | |
$this->app->bind('Doctrine\ORM\EntityManager', 'Doctrine\ORM\EntityManagerInterface'); | |
// Bind default connection resolver | |
$this->app->bind('Concrete\Core\Database\Connection\Connection', function ($app) { | |
return $app->make('Concrete\Core\Database\DatabaseManager')->connection(); | |
}); | |
$this->app->bind('Doctrine\DBAL\Connection', 'Concrete\Core\Database\Connection\Connection'); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Application\Src\Database; | |
// store location: application/src/Database | |
use Doctrine\ORM\EntityManager; | |
use Doctrine\ORM\Tools\Setup; | |
use Config; | |
use Database; | |
use Events; | |
/** | |
* EntityManagerFactory | |
* | |
* @author markus.liechti <[email protected]> | |
*/ | |
class EntityManagerFactory implements \Concrete\Core\Database\EntityManagerFactoryInterface{ | |
/** | |
* Create Application Specific EntityManager | |
* | |
* @param \Concrete\Core\Database\Connection\Connection $connection | |
* @return type | |
*/ | |
public function create(\Concrete\Core\Database\Connection\Connection $connection) { | |
$args = isset($_SERVER['argv']) ? $_SERVER['argv'] : null; | |
$environments = require DIR_APPLICATION . '/bootstrap/environments.php'; | |
$detector = new \Concrete\Core\Foundation\EnvironmentDetector(); | |
$env = $detector->detect($environments, $args); | |
if($env == 'production'){ | |
$cache = new \Concrete\Core\Cache\Adapter\DoctrineCacheDriver('cache/expensive'); | |
}else{ | |
$cache = new \Doctrine\Common\Cache\ArrayCache(); | |
} | |
$config = \Doctrine\ORM\Tools\Setup::createConfiguration( | |
Config::get('concrete.cache.doctrine_dev_mode'), | |
Config::get('database.proxy_classes'), | |
$cache | |
); | |
// Handling the automated creation of proxies | |
/*if($env == 'production'){ | |
$config->setAutoGenerateProxyClasses(false); | |
}else{ | |
$config->setAutoGenerateProxyClasses(true); | |
}*/ | |
// Customized | |
$path = DIR_APPLICATION . '/' . DIRNAME_CLASSES; | |
if ($context instanceof Package) { | |
$path = $context->getPackageEntitiesPath(); | |
} elseif ($context === 'core') { | |
$path = DIR_BASE_CORE . '/' . DIRNAME_CLASSES; | |
} elseif (is_object($context) && method_exists($context, 'getEntitiesPath')) { | |
$path = $context->getEntitiesPath(); | |
} | |
// Register the doctrine Annotations | |
\Doctrine\Common\Annotations\AnnotationRegistry::registerFile(DIR_BASE_CORE . '/vendor/doctrine/orm/lib/Doctrine/ORM' .'/Mapping/Driver/DoctrineAnnotations.php'); | |
\Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespace('Application\Src', DIR_BASE.'/application/src'); | |
// Create manualy the next function $config->newDefaultAnnotationDriver() | |
// To get a instance of the cached AnnotationReader | |
\Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredName('package'); | |
$annotationReader = new \Doctrine\Common\Annotations\AnnotationReader(); | |
// Ignore the Annotions of the SimpleAnnotationReader | |
\Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredName('Id'); | |
\Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredName('Table'); | |
\Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredName('Column'); | |
\Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredName('GeneratedValue'); | |
\Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredName('Entity'); | |
\Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredName('OneToMany'); | |
\Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredName('ManyToOne'); | |
\Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredName('JoinColumn'); | |
//@todo add some more possible annotions | |
// add different annotations to the ignoreing list | |
$cachedAnnotationReader = new \Doctrine\Common\Annotations\CachedReader($annotationReader, new \Doctrine\Common\Cache\ArrayCache()); | |
$driverChain = new \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain(); | |
// Register Concrete5 customized classes in application with YamlDriver | |
$yamlDir = DIR_CONFIG_SITE.DIRECTORY_SEPARATOR.'yaml'; | |
$yamlDriver = new \Doctrine\ORM\Mapping\Driver\YamlDriver($yamlDir); | |
$driverChain->addDriver($yamlDriver, 'Application\Src'); | |
// Legacy | |
// Collect Mapping Info of the Concrete5 core wiht the simple annotation reader and add it to the driver chain | |
// You can pass multiple paths/directories as array | |
$reader = new \Doctrine\Common\Annotations\SimpleAnnotationReader(); | |
$reader->addNamespace('Doctrine\ORM\Mapping'); | |
$cachedSimpleAnnotationReader = new \Doctrine\Common\Annotations\CachedReader($reader, new \Doctrine\Common\Cache\ArrayCache()); | |
// Acts as the main AnnotaionDriver | |
//$annotationDriver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($cachedAnnotationReader, DIR_BASE_CORE . '/' . DIRNAME_CLASSES); | |
//$driverChain->addDriver($annotationDriver, 'Concrete\Package\MyTestPackage'); | |
// Acts as an lecay AnnotationDriver -> Annotions of the core are mapped all automatically to \Doctrine\ORM\Mapping | |
$simpleAnnotationDriver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($cachedSimpleAnnotationReader, DIR_BASE_CORE . '/' . DIRNAME_CLASSES); | |
$driverChain->addDriver($simpleAnnotationDriver, 'Concrete\Core'); | |
// Register Gedmo Doctrine Extensions | |
// 1.) AbstractMapping vs Mapping @See https://github.com/Atlantic18/DoctrineExtensions/issues/790 | |
\Gedmo\DoctrineExtensions::registerMappingIntoDriverChainORM($driverChain, $cachedAnnotationReader); | |
//\Gedmo\DoctrineExtensions::registerAbstractMappingIntoDriverChainORM($driverChain, $cachedAnnotationReader); | |
// Inject DriverChain into the doctrine config | |
$config->setMetadataDriverImpl($driverChain); | |
// Concrete event | |
$event = new \Symfony\Component\EventDispatcher\GenericEvent(); | |
$event->setArgument('connection', $connection); | |
$event->setArgument('context', $context); | |
$event->setArgument('configuration', $config); | |
Events::dispatch('on_entity_manager_configure', $event); | |
$config = $event->getArgument('configuration'); | |
// Get EventManager | |
$evm = $connection->getEventManager(); | |
// Register the needed Gedmo extensions | |
self::registerEvents($evm,$cachedAnnotationReader); | |
// Inject the ORM EventManager into the EntityManager so ORM Events | |
// can be triggered. | |
return EntityManager::create($connection, $config, $evm); | |
} | |
/** | |
* Add event listeners to event manager (Doctrine Behavioral Extensions) | |
* | |
* return \Doctrine\Common\EventManager | |
*/ | |
protected static function registerEvents(\Doctrine\Common\EventManager $evm, \Doctrine\Common\Annotations\CachedReader $cachedAnnotationReader){ | |
//$cachedAnnotationReader = new \Doctrine\Common\Annotations\CachedReader(new \Doctrine\Common\Annotations\AnnotationReader(), new \Doctrine\Common\Cache\ArrayCache()); | |
// Sluggable | |
$sluggableListener = new \Gedmo\Sluggable\SluggableListener(); | |
$sluggableListener->setAnnotationReader($cachedAnnotationReader); | |
// Register custom Sluggifiers (Replace Special Characters) | |
$callable = array('\Application\Src\Product\Model\Event\Transliterator', 'replaceSecialSigns'); | |
$sluggableListener->setTransliterator($callable); | |
$evm->addEventSubscriber($sluggableListener); | |
// Tree | |
$treeListener = new \Gedmo\Tree\TreeListener(); | |
$treeListener->setAnnotationReader($cachedAnnotationReader); | |
$evm->addEventSubscriber($treeListener); | |
// Timestampable | |
$timestampableListener = new \Gedmo\Timestampable\TimestampableListener(); | |
$timestampableListener->setAnnotationReader($cachedAnnotationReader); | |
// The issue is here with SimpleAnnotationReader for Concrete and AnnotationReader for Gedmo | |
$evm->addEventSubscriber($timestampableListener); | |
// Blameable | |
$blameableListener = new \Gedmo\Blameable\BlameableListener(); | |
$blameableListener->setAnnotationReader($cachedAnnotationReader); | |
$user = new \Concrete\Core\User\User(); | |
if($user){ | |
$blameableListener->setUserValue($user->getUserID()); | |
} | |
$evm->addEventSubscriber($blameableListener); | |
// Translatable | |
$translatableListener = new \Gedmo\Translatable\TranslatableListener(); | |
$translatableListener->setAnnotationReader($cachedAnnotationReader); | |
// Get Concrete5 default locale | |
//$locale = \Localization::activeLocale(); // -> example "de_DE"; | |
//$locale = \Localization::activeLanguage(); // -> example "de"; | |
$locale = 'de'; | |
//$translatableListener->setTranslatableLocale($locale); | |
$translatableListener->setDefaultLocale($locale); | |
$translatableListener->setTranslationFallback(false); | |
//$translatableListener->setPersistDefaultLocaleTranslation(false); | |
$ms = \Concrete\Core\Multilingual\Page\Section\Section::getCurrentSection(); | |
if($ms){ | |
$locale = $ms->getLanguage(); | |
//\Doctrine\Common\Util\Debug::dump($locale); | |
$translatableListener->setTranslatableLocale($locale); | |
}else{ | |
//\Doctrine\Common\Util\Debug::dump($this->get('locale')); | |
// last fallback | |
$translatableListener->setTranslatableLocale('de'); | |
// Check if locale in request is set. | |
$requestLocale = self::get('locale'); | |
if(!empty($requestLocale)){ | |
$translatableListener->setTranslatableLocale(self::get('locale')); | |
} | |
} | |
$evm->addEventSubscriber($translatableListener); | |
// Sortable | |
$sortableListener = new \Gedmo\Sortable\SortableListener(); | |
$sortableListener->setAnnotationReader($cachedAnnotationReader); | |
$evm->addEventSubscriber($sortableListener); | |
} | |
/** | |
* Dublicate form the \Concrete\Core\ControllerAbstractController class | |
* | |
* Is used to place custom routes in a the mulitlingual section, so | |
* the correct transaltion is loaded by the gedmo translatable extension | |
* Example /fr/api/search/articles will triggert the content loading in english | |
* | |
* @param type $key | |
* @param type $defaultValue | |
* @return type | |
*/ | |
public static function get($key = null, $defaultValue = null) | |
{ | |
$sets = array(); | |
$request = \Request::getInstance(); | |
if ($key == null) { | |
return $_GET; | |
} | |
if (isset($sets[$key])) { | |
return $sets[$key]; | |
} | |
if (!isset($request)) { | |
$request = \Request::createFromGlobals(); | |
} | |
$val = $request->get($key, $defaultValue); | |
return $val; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment