Skip to content

Commit

Permalink
Fixed installer issues including table prefix not getting applied and…
Browse files Browse the repository at this point in the history
… persisting admin user.
  • Loading branch information
Alan Hartless authored and Alan Hartless committed Nov 27, 2014
1 parent 8efd6aa commit 4e6286a
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 87 deletions.
5 changes: 1 addition & 4 deletions app/bundles/CoreBundle/Config/services/events.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@
//Database table prefix
$container->setDefinition ('mautic.tblprefix_subscriber',
new Definition(
'Mautic\CoreBundle\EventListener\DoctrineEventsSubscriber',
array(
'%mautic.db_table_prefix%'
)
'Mautic\CoreBundle\EventListener\DoctrineEventsSubscriber'
)
)->addTag('doctrine.event_subscriber');
26 changes: 10 additions & 16 deletions app/bundles/CoreBundle/EventListener/DoctrineEventsSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,6 @@
*/
class DoctrineEventsSubscriber implements \Doctrine\Common\EventSubscriber
{

/**
* @var string
*/
protected $prefix = '';

/**
* @param string $prefix
*/
public function __construct($prefix)
{
$this->prefix = (string) $prefix;
}

/**
* {@inheritdoc}
*/
Expand All @@ -46,6 +32,11 @@ public function getSubscribedEvents()
*/
public function loadClassMetadata(LoadClassMetadataEventArgs $args)
{
if (defined('MAUTIC_INSTALLER') && !defined('MAUTIC_TABLE_PREFIX')) {
//only run this after the installer has set the MAUTIC_TABLE_PREFIX
return;
}

$classMetadata = $args->getClassMetadata();

// Do not re-apply the prefix in an inheritance hierarchy.
Expand All @@ -54,13 +45,16 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $args)
}

if (FALSE !== strpos($classMetadata->namespace, 'Mautic')) {
$classMetadata->setPrimaryTable(array('name' => $this->prefix . $classMetadata->getTableName()));
//if in the installer, use the prefix set by it rather than what is cached
$prefix = MAUTIC_TABLE_PREFIX;

$classMetadata->setPrimaryTable(array('name' => $prefix . $classMetadata->getTableName()));

foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY
&& isset($classMetadata->associationMappings[$fieldName]['joinTable']['name'])) {
$mappedTableName = $classMetadata->associationMappings[$fieldName]['joinTable']['name'];
$classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName;
$classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $prefix . $mappedTableName;
}
}

Expand Down
9 changes: 7 additions & 2 deletions app/bundles/CoreBundle/Factory/MauticFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,9 @@ public function getSchemaHelper($type, $name = null)
if ($type == "table") {
//get the column helper as well
$columnHelper = $this->getSchemaHelper('column');
$schemaHelpers[$type] = new $className($this->getDatabase(), $this->getParameter('db_table_prefix'), $columnHelper);
$schemaHelpers[$type] = new $className($this->getDatabase(), MAUTIC_TABLE_PREFIX, $columnHelper);
} else {
$schemaHelpers[$type] = new $className($this->getDatabase(), $this->getParameter('db_table_prefix'));
$schemaHelpers[$type] = new $className($this->getDatabase(), MAUTIC_TABLE_PREFIX);
}

}
Expand Down Expand Up @@ -292,6 +292,11 @@ public function getSystemParameters()
*/
public function getParameter($id)
{
if ($id == 'db_table_prefix' && defined('MAUTIC_TABLE_PREFIX')) {
//use the constant in case in the installer
return MAUTIC_TABLE_PREFIX;
}

return ($this->container->hasParameter('mautic.' . $id)) ?
$this->container->getParameter('mautic.' . $id) :
false;
Expand Down
10 changes: 8 additions & 2 deletions app/bundles/CoreBundle/MauticCoreBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace Mautic\CoreBundle;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Mautic\CoreBundle\DependencyInjection\Compiler;

Expand All @@ -33,7 +34,12 @@ public function build(ContainerBuilder $container)
public function boot()
{
//set the table prefix as a constant to be used in repositories requiring DBAL
$prefix = $this->container->getParameter('mautic.db_table_prefix');
defined('MAUTIC_TABLE_PREFIX') or define('MAUTIC_TABLE_PREFIX', $prefix);
$request = $this->container->get('mautic.factory')->getRequest();
if (strpos($request->getRequestUri(), 'installer') !== false) {
define('MAUTIC_INSTALLER', 1);
} else {
$prefix = $this->container->getParameter('mautic.db_table_prefix');
defined('MAUTIC_TABLE_PREFIX') or define('MAUTIC_TABLE_PREFIX', $prefix);
}
}
}
144 changes: 87 additions & 57 deletions app/bundles/InstallBundle/Controller/InstallController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@

use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\DriverManager;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\ORM\Tools\Setup;
use Mautic\CoreBundle\Controller\CommonController;
use Mautic\CoreBundle\EventListener\DoctrineEventsSubscriber;
use Mautic\InstallBundle\Configurator\Step\DoctrineStep;
use Mautic\UserBundle\Entity\User;
use Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader;
Expand Down Expand Up @@ -101,10 +103,14 @@ public function stepAction ($index = 0)
$dbParams['dbname'] = $dbParams['name'];
unset($dbParams['name']);

$result = $this->performDatabaseInstallation($dbParams, $configurator, $step);
$result = $this->performDatabaseInstallation($dbParams);
if (is_array($result)) {
$flashes[] = $result;
} else {
//write the working database details to the configuration file
$configurator->mergeParameters($step->update($originalData));
$configurator->write();

$result = $this->performFixtureInstall($dbParams);
if (is_array($result)) {
$flashes[] = $result;
Expand Down Expand Up @@ -316,17 +322,12 @@ private function checkIfInstalled ()
/**
* Performs the database installation
*
* @param array $dbParams
* @param \Mautic\InstallBundle\Configurator\Configurator $configurator
* @param \Mautic\InstallBundle\Configurator\Step\StepInterface $step
* @param array $dbParams
*
* @return array|boolean Array containing the flash message data on a failure, boolean true on success
*/
private function performDatabaseInstallation ($dbParams, $configurator, $step)
private function performDatabaseInstallation ($dbParams)
{
$entityManager = $this->factory->getEntityManager($dbParams);
$metadatas = $entityManager->getMetadataFactory()->getAllMetadata();

$dbName = $dbParams['dbname'];
$dbParams['dbname'] = null;

Expand Down Expand Up @@ -366,6 +367,13 @@ private function performDatabaseInstallation ($dbParams, $configurator, $step)
//database does not exist so try to create it
$schemaManager = $db->getSchemaManager();
$schemaManager->createDatabase($dbName);

//close the connection and reconnect with the new database name
$db->close();

$dbParams['dbname'] = $dbName;
$db = DriverManager::getConnection($dbParams);
$schemaManager = $db->getSchemaManager();
} catch (\Exception $exception) {
$db->close();

Expand All @@ -386,8 +394,11 @@ private function performDatabaseInstallation ($dbParams, $configurator, $step)
$db->close();

return array(
'type' => 'error',
'msg' => 'mautic.installer.error.connecting.database'
'type' => 'error',
'msg' => 'mautic.installer.error.connecting.database',
'msgVars' => array(
'%exception%' => $e->getMessage()
)
);
}

Expand Down Expand Up @@ -455,6 +466,9 @@ private function performDatabaseInstallation ($dbParams, $configurator, $step)
}
}

$entityManager = $this->getEntityManager($dbParams);
$metadatas = $entityManager->getMetadataFactory()->getAllMetadata();

if (!empty($metadatas)) {
$schemaTool = new SchemaTool($entityManager);
$queries = $schemaTool->getCreateSchemaSql($metadatas);
Expand Down Expand Up @@ -488,39 +502,41 @@ private function performDatabaseInstallation ($dbParams, $configurator, $step)
}

/**
* Creates the admin user
* Installs data fixtures for the application
*
* @param \Symfony\Component\Form\Form $form
* @param array $dbParams
*
* @return array|bool Array containing the flash message data on a failure, boolean true on success
*/
private function performUserAddition ($form)
private function performFixtureInstall ()
{
try {
$entityManager = $this->getEntityManager();
$paths = array(dirname(__DIR__) . '/InstallFixtures/ORM');
$loader = new ContainerAwareLoader($this->container);

// Now we create the user
$data = $form->getData();
$user = new User();
foreach ($paths as $path) {
if (is_dir($path)) {
$loader->loadFromDirectory($path);
}
}

/** @var \Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface $encoder */
$encoder = $this->container->get('security.encoder_factory')->getEncoder($user);
$fixtures = $loader->getFixtures();

/** @var \Mautic\UserBundle\Model\RoleModel $model */
$model = $this->factory->getModel('user.role');
if (!$fixtures) {
throw new \InvalidArgumentException(
sprintf('Could not find any fixtures to load in: %s', "\n\n- " . implode("\n- ", $paths))
);
}

$user->setFirstName($data->firstname);
$user->setLastName($data->lastname);
$user->setUsername($data->username);
$user->setEmail($data->email);
$user->setPassword($encoder->encodePassword($data->password, $user->getSalt()));
$user->setRole($model->getEntity(1));
$entityManager->persist($user);
$entityManager->flush();
$purger = new ORMPurger($entityManager);
$purger->setPurgeMode(ORMPurger::PURGE_MODE_DELETE);
$executor = new ORMExecutor($entityManager, $purger);
$executor->execute($fixtures, true);
} catch (\Exception $exception) {
return array(
'type' => 'error',
'msg' => 'mautic.installer.error.creating.user',
'msg' => 'mautic.installer.error.adding.fixtures',
'msgVars' => array('%exception%' => $exception->getMessage())
);
}
Expand All @@ -529,41 +545,40 @@ private function performUserAddition ($form)
}

/**
* Installs data fixtures for the application
* Creates the admin user
*
* @param array $dbParams
* @param \Symfony\Component\Form\Form $form
*
* @return array|bool Array containing the flash message data on a failure, boolean true on success
*/
private function performFixtureInstall ()
private function performUserAddition ($form)
{
try {
$entityManager = $this->getEntityManager();
$paths = array(dirname(__DIR__) . '/InstallFixtures/ORM');
$loader = new ContainerAwareLoader($this->container);

foreach ($paths as $path) {
if (is_dir($path)) {
$loader->loadFromDirectory($path);
}
}
// Now we create the user
$data = $form->getData();
$user = new User();

$fixtures = $loader->getFixtures();
/** @var \Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface $encoder */
$encoder = $this->container->get('security.encoder_factory')->getEncoder($user);

if (!$fixtures) {
throw new \InvalidArgumentException(
sprintf('Could not find any fixtures to load in: %s', "\n\n- " . implode("\n- ", $paths))
);
}
/** @var \Mautic\UserBundle\Model\RoleModel $model */
$model = $this->factory->getModel('user.role');

$purger = new ORMPurger($entityManager);
$purger->setPurgeMode(ORMPurger::PURGE_MODE_DELETE);
$executor = new ORMExecutor($entityManager, $purger);
$executor->execute($fixtures, true);
$user->setFirstName($data->firstname);
$user->setLastName($data->lastname);
$user->setUsername($data->username);
$user->setEmail($data->email);
$user->setPassword($encoder->encodePassword($data->password, $user->getSalt()));
$user->setRole($model->getEntity(1));
$entityManager->persist($user);
$entityManager->flush();
} catch (\Exception $exception) {
die(var_Dump($exception));
return array(
'type' => 'error',
'msg' => 'mautic.installer.error.adding.fixtures',
'msg' => 'mautic.installer.error.creating.user',
'msgVars' => array('%exception%' => $exception->getMessage())
);
}
Expand All @@ -572,6 +587,8 @@ private function performFixtureInstall ()
}

/**
* Build an entity manager specific for the installer to prevent cache related issues
*
* @param $dbParams
*
* @return EntityManager
Expand All @@ -591,14 +608,15 @@ private function getEntityManager ($dbParams = array())
unset($dbParams['name']);
}

//get paths to entities
$bundles = $this->factory->getParameter('bundles');
$paths = array();
$paths = $namespaces = array();

//build entity namespaces
$bundles = $this->factory->getParameter('bundles');
foreach ($bundles as $b) {
$entityPath = $b['directory'] . '/Entity';
if (file_exists($entityPath)) {
$paths[] = $entityPath;
$namespaces['Mautic' . $b['bundle']] = $b['namespace'] . '\Entity';
}
}

Expand All @@ -607,17 +625,29 @@ private function getEntityManager ($dbParams = array())
$entityPath = $b['directory'] . '/Entity';
if (file_exists($entityPath)) {
$paths[] = $entityPath;
$namespaces[$b['bundle']] = $b['namespace'] . '\Entity';
}
}
$config = Setup::createAnnotationMetadataConfiguration($paths, true, null, null, false);
foreach ($namespaces as $alias => $namespace) {
$config->addEntityNamespace($alias, $namespace);
}

//set the table prefix
define('MAUTIC_TABLE_PREFIX', $dbParams['table_prefix']);

//reset database classes for fixtures that load from container and/or MauticFactory
$db = DriverManager::getConnection($dbParams);

//Add the event listener that adds the table prefix to entity metadata
$eventManager = new EventManager();
$eventManager->addEventSubscriber(new DoctrineEventsSubscriber());

$db = DriverManager::getConnection($dbParams, null, $eventManager);
$this->container->set('database_connection', $db);
$this->factory->setDatabase($db);

//create an entity manager with current DB details
$config = Setup::createAnnotationMetadataConfiguration($paths, true, null, null, false);
$entityManager = EntityManager::create($db, $config);
$entityManager = EntityManager::create($db, $config, $eventManager);

$this->container->set('doctrine.orm.entity_manager', $entityManager);
$this->factory->setEntityManager($entityManager);

Expand Down
2 changes: 1 addition & 1 deletion app/bundles/InstallBundle/Translations/en_US/flashes.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ mautic.installer.error.adding.fields="An error occurred while attempting to popu
mautic.installer.error.adding.fixtures="An error occurred while attempting to add default data: %exception%"
mautic.installer.error.creating.database="The database, %name%, could not be found or created due to permissions restrictions. Please manually create the database then try again."
mautic.installer.error.installing.data="An error occurred while attempting to install the data: %exception%"
mautic.installer.error.connecting.database="Could not connect to the database. Please double check the database parameters."
mautic.installer.error.connecting.database="An error occured while attempting to connect to the database: %exception%"
mautic.installer.error.creating.user="An error occurred while attempting to create the admin user: %exception%"
mautic.installer.error.database.exists="The database you've specified already exists and contains Mautic data."
mautic.installer.error.no.metadata="No metadata was found to create the database."
Expand Down
Loading

0 comments on commit 4e6286a

Please sign in to comment.