partkeepr

fork of partkeepr
git clone https://git.e1e0.net/partkeepr.git
Log | Files | Refs | Submodules | README | LICENSE

commit 4d29a4baea9fbb2f3970badb286318ec61a645f1
parent 60e1fa616bf12d413cf6e3c64b4d793676446d33
Author: Felicitus <felicitus@felicitus.org>
Date:   Wed, 21 Dec 2011 04:11:52 +0100

First working version of the installer. No support for databases other than MySQL, this will be changed soon.

Diffstat:
Mbuild.xml | 5+++++
Mconfig.php.template | 5+++++
Msrc/backend/de/RaumZeitLabor/PartKeepr/Manufacturer/ManufacturerManager.php | 17+++++++++++++++++
Msrc/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php | 34+++++++++++++++++++++++++---------
Asrc/backend/de/RaumZeitLabor/PartKeepr/Setup/AbstractSetup.php | 37+++++++++++++++++++++++++++++++++++++
Msrc/backend/de/RaumZeitLabor/PartKeepr/Setup/FootprintSetup.php | 55+++++++++++++++++++++++++++++++++++++++++--------------
Msrc/backend/de/RaumZeitLabor/PartKeepr/Setup/ManufacturerSetup.php | 50+++++++++++++++++++++++++++++++++-----------------
Msrc/backend/de/RaumZeitLabor/PartKeepr/Setup/PartCategorySetup.php | 7+++++--
Msrc/backend/de/RaumZeitLabor/PartKeepr/Setup/PartUnitSetup.php | 39+++++++++++++++++++--------------------
Asrc/backend/de/RaumZeitLabor/PartKeepr/Setup/SchemaMigrationSetup.php | 22++++++++++++++++++++++
Asrc/backend/de/RaumZeitLabor/PartKeepr/Setup/SchemaSetup.php | 16++++++++++++++++
Msrc/backend/de/RaumZeitLabor/PartKeepr/Setup/Setup.php | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/backend/de/RaumZeitLabor/PartKeepr/Setup/SiPrefixSetup.php | 47++++++++++++++++++++++-------------------------
Msrc/backend/de/RaumZeitLabor/PartKeepr/Setup/UnitSetup.php | 27++++++++++++++++++++++-----
Asrc/backend/de/RaumZeitLabor/PartKeepr/Setup/UserSetup.php | 31+++++++++++++++++++++++++++++++
Asrc/backend/de/RaumZeitLabor/PartKeepr/SiPrefix/SiPrefixManager.php | 44++++++++++++++++++++++++++++++++++++++++++++
Msrc/backend/de/RaumZeitLabor/PartKeepr/Unit/UnitManager.php | 20++++++++++++++++++++
Msrc/setup/index.html | 17++++++++++++-----
Msrc/setup/js/Cards/AbstractTestCard.js | 11++++++-----
Msrc/setup/js/Cards/DatabaseConnectivityTestCard.js | 6++----
Msrc/setup/js/Cards/DatabaseParametersCard.MySQL.js | 10++++++----
Msrc/setup/js/Cards/DatabaseParametersCard.js | 3++-
Asrc/setup/js/Cards/DatabaseSetupCard.js | 26++++++++++++++++++++++++++
Msrc/setup/js/Cards/PrequisitesTestCard.js | 26++++++--------------------
Asrc/setup/js/SetupSteps/AdminUserSetup.js | 15+++++++++++++++
Asrc/setup/js/SetupSteps/FootprintSetup.js | 15+++++++++++++++
Asrc/setup/js/SetupSteps/ManufacturerSetup.js | 15+++++++++++++++
Asrc/setup/js/SetupSteps/PartCategorySetup.js | 15+++++++++++++++
Asrc/setup/js/SetupSteps/PartUnitSetup.js | 15+++++++++++++++
Asrc/setup/js/SetupSteps/SchemaMigrationSetup.js | 15+++++++++++++++
Asrc/setup/js/SetupSteps/SchemaSetup.js | 15+++++++++++++++
Asrc/setup/js/SetupSteps/SiPrefixSetup.js | 15+++++++++++++++
Asrc/setup/js/SetupSteps/UnitSetup.js | 15+++++++++++++++
Msrc/setup/js/SetupTests/AbstractTest.js | 8+++++---
Msrc/setup/js/SetupWizard.js | 14++++++++++++++
Msrc/setup/js/TestResultPanel.js | 10+++++++++-
Msrc/setup/js/TestRunner.js | 18++++++++++++++++--
Asrc/setup/resources/images/ajax-loader.gif | 0
Asrc/setup/setup.php | 32++++++++++++++++++++++++++++++++
Msrc/setup/tests/check-database-connectivity.php | 36++++++++++--------------------------
Msrc/setup/tests/check-php-settings.php | 5+++++
Mtesting/SetupDatabase.php | 62+++++++++++++++-----------------------------------------------
42 files changed, 727 insertions(+), 216 deletions(-)

diff --git a/build.xml b/build.xml @@ -155,6 +155,11 @@ <include name="**/*.js"/> </fileset> </jsllint> + <jsllint> + <fileset dir="src/setup"> + <include name="**/*.js"/> + </fileset> + </jsllint> </target> <!-- Checks all PHP files for messy code. --> diff --git a/config.php.template b/config.php.template @@ -24,6 +24,11 @@ Configuration::setOption("partkeepr.database.hostname", "localhost"); Configuration::setOption("partkeepr.database.dbname", "partkeepr"); /** + * Specifies the MySQL database port + */ +Configuration::setOption("partkeepr.database.mysql_port", 3306); + +/** * Specifies the database driver. * * In general, we support any database platform also supported by DBAL. For details, see diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Manufacturer/ManufacturerManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Manufacturer/ManufacturerManager.php @@ -56,6 +56,7 @@ class ManufacturerManager extends Singleton { /** * Adds a new manufacturer by name + * * @param string $name The manufacturer name */ public function addManufacturer ($name) { @@ -70,11 +71,13 @@ class ManufacturerManager extends Singleton { /** * Loads a manufacturer by id + * * @param int $id The manufacturer id */ public function getManufacturer ($id) { return Manufacturer::loadById($id); } + /** * Deletes the manufacturer by id * @param int $id The manufacturer's id @@ -85,4 +88,18 @@ class ManufacturerManager extends Singleton { PartKeepr::getEM()->remove($manufacturer); PartKeepr::getEM()->flush(); } + + /** + * Retrieves a manufacturer by its name. + * + * @param string $name The name of the manufacturer to retrieve + * @throws Doctrine\ORM\NoResultException If the manufacturer was not found + */ + public function getManufacturerByName ($name) { + $dql = "SELECT m FROM de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer m WHERE m.name = :name"; + $query = PartKeepr::getEM()->createQuery($dql); + $query->setParameter("name", $name); + + return $query->getSingleResult(); + } } \ No newline at end of file diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php b/src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php @@ -103,18 +103,10 @@ class PartKeepr { $driverImpl = $config->newDefaultAnnotationDriver( array(__DIR__) - //array(__DIR__."/Session") - ); $config->setMetadataDriverImpl($driverImpl); - $connectionOptions = array( - 'driver' => PartKeeprConfiguration::getOption("partkeepr.database.driver","pdo_mysql"), - 'dbname' => PartKeeprConfiguration::getOption("partkeepr.database.dbname", "partkeepr"), - 'user' => PartKeeprConfiguration::getOption("partkeepr.database.username", "partkeepr"), - 'password' => PartKeeprConfiguration::getOption("partkeepr.database.password", "partkeepr"), - 'host' => PartKeeprConfiguration::getOption("partkeepr.database.hostname", "localhost") - ); + $connectionOptions = PartKeepr::createConnectionOptionsFromConfig(); if (extension_loaded("apc")) { $cache = new \Doctrine\Common\Cache\ApcCache(); @@ -139,6 +131,30 @@ class PartKeepr { self::$entityManager = EntityManager::create($connectionOptions, $config); } + public static function createConnectionOptionsFromConfig () { + $connectionOptions = array(); + + $driver = PartKeeprConfiguration::getOption("partkeepr.database.driver"); + + switch ($driver) { + case "pdo_mysql": + $connectionOptions["driver"] = "pdo_mysql"; + $connectionOptions["dbname"] = PartKeeprConfiguration::getOption("partkeepr.database.dbname", "partkeepr"); + $connectionOptions["user"] = PartKeeprConfiguration::getOption("partkeepr.database.username", "partkeepr"); + $connectionOptions["password"] = PartKeeprConfiguration::getOption("partkeepr.database.password", "partkeepr"); + $connectionOptions["host"] = PartKeeprConfiguration::getOption("partkeepr.database.host", "localhost"); + + if (PartKeeprConfiguration::getOption("partkeepr.database.mysql_port")) { + $connectionOptions["port"] = PartKeeprConfiguration::getOption("partkeepr.database.mysql_port"); + } + break; + default: + throw new \Exception(sprintf("Unknown driver %s", $driver)); + } + + return $connectionOptions; + } + /** * Returns the EntityManager. Shortcut for getEntityManager(). * @return Doctrine\ORM\EntityManager The EntityManager diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/AbstractSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/AbstractSetup.php @@ -0,0 +1,36 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\Setup; + +use Doctrine\ORM\EntityManager; + +/** + * Represents a basic setup step + */ +abstract class AbstractSetup { + /** + * Represents the Doctrine Entity Manager + * @var Doctrine\ORM\EntityManager + */ + protected $entityManager; + + /** + * Represents all messages which are logged during setup + * @var array + */ + private $messages = array(); + + /** + * Constructs the setup step. + * @param EntityManager $em The entity manager + */ + public function __construct (EntityManager $em) { + $this->entityManager = $em; + } + + abstract public function run (); + + public function logMessage ($message) { + //echo "- ".$message."\n"; + $this->messages[] = $message; + } +}+ \ No newline at end of file diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/FootprintSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/FootprintSetup.php @@ -10,7 +10,7 @@ use de\RaumZeitLabor\PartKeepr\Footprint\FootprintManager, de\RaumZeitLabor\PartKeepr\PartKeepr, de\RaumZeitLabor\PartKeepr\Setup\Setup; -class FootprintSetup { +class FootprintSetup extends AbstractSetup { /** * Holds the migrated footprints * @var array @@ -23,10 +23,15 @@ class FootprintSetup { /** * Creates the root node for the footprints */ - public static function setupRootNode () { + public function setupRootNode () { FootprintCategoryManager::getInstance()->ensureRootExists(); } + public function run () { + $this->setupRootNode(); + $this->importFootprintData(); + } + /** * Returns a footprint by it's partdb id * @param int $id The footprint id from the old partdb @@ -41,7 +46,7 @@ class FootprintSetup { * @param $path array The components of the path * @param $node Node The parent node */ - public static function addFootprintPath (Array $path, $node) { + public function addFootprintPath (Array $path, $node) { if (count($path) == 0) { return $node; } @@ -62,14 +67,13 @@ class FootprintSetup { $childNode = FootprintCategoryManager::getInstance()->addCategory($category); } - return FootprintSetup::addFootprintPath($path, $childNode); + return $this->addFootprintPath($path, $childNode); } /** * Migrates the existing footprints from the PartDB. */ public static function migrateFootprints () { - Setup::progress("Migrating footprints..."); $r = mysql_query("SELECT * FROM footprints"); while ($sFootprint = mysql_fetch_assoc($r)) { @@ -82,23 +86,45 @@ class FootprintSetup { $footprintCategory = FootprintSetup::addFootprintPath(explode("/", "Imported Footprints"), FootprintCategoryManager::getInstance()->getRootNode()); $footprint->setCategory($footprintCategory->getNode()); - PartKeepr::getEM()->persist($footprint); + $this->entityManager->persist($footprint); FootprintSetup::$migratedFootprints[$sFootprint["id"]] = $footprint; } } + + /** + * Checks if the specified footprint exists + * @param string $name The footprint name + */ + public function footprintExists ($name) { + $dql = "SELECT COUNT(fp) FROM de\RaumZeitLabor\PartKeepr\Footprint\Footprint fp WHERE fp.name = :name"; + $query = $this->entityManager->createQuery($dql); + $query->setParameter("name", $name); + + if ($query->getSingleScalarResult() == 0) { + return false; + } else { + return true; + } + } + /** * Imports the footprints * @throws \Exception */ - public static function importFootprintData () { - Setup::progress("Adding predefined footprints..."); + public function importFootprintData () { + $count = 0; + $skipped = 0; /* Import pre-defined footprints */ $data = Setup::loadYAML(self::FOOTPRINT_FILE); foreach ($data as $footprintName => $footprintData) { - Setup::progress(" - Adding footprint ".$footprintName, true); + /* Check if the footprint with the name already exists. If yes, skip the import for the single footprint */ + if ($this->footprintExists($footprintName)) { + $skipped++; + continue; + } $footprint = new Footprint(); $footprint->setName($footprintName); @@ -107,7 +133,7 @@ class FootprintSetup { } if (array_key_exists("category", $footprintData)) { - $footprintCategory = FootprintSetup::addFootprintPath(explode("/", $footprintData["category"]), FootprintCategoryManager::getInstance()->getRootNode()); + $footprintCategory = $this->addFootprintPath(explode("/", $footprintData["category"]), FootprintCategoryManager::getInstance()->getRootNode()); $footprint->setCategory($footprintCategory->getNode()); } @@ -137,15 +163,16 @@ class FootprintSetup { } catch (\Exception $e) { echo "error with url ".$attachment["url"]."\n"; } - - - } } } - PartKeepr::getEM()->persist($footprint); + $this->entityManager->persist($footprint); + $count++; } + + $this->entityManager->flush(); + $this->logMessage(sprintf("Imported %d footprints, skipped %d because they already existed", $count, $skipped)); } } diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/ManufacturerSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/ManufacturerSetup.php @@ -3,38 +3,54 @@ namespace de\RaumZeitLabor\PartKeepr\Setup; use de\RaumZeitLabor\PartKeepr\PartKeepr, de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer, + de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerManager, de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerICLogo, de\RaumZeitLabor\PartKeepr\Setup\SiPrefixSetup; -class ManufacturerSetup { +/** + * Sets up the manufacturers + */ +class ManufacturerSetup extends AbstractSetup { const MANUFACTURER_PATH = "../setup-data/manufacturers/"; const MANUFACTURER_FILE = "../setup-data/manufacturers/manufacturers.yaml"; + public function run () { + $this->setupManufacturers(); + } + /** * Sets up the manufacturers using the YAML file. * @param $yaml string The path to the manufacturers YAML file */ - public static function setupManufacturers () { - Setup::progress("Setting up Manufacturers..."); - + public function setupManufacturers () { + $count=0; + $skipped=0; $data = Setup::loadYAML(self::MANUFACTURER_FILE); foreach ($data as $mfgname => $logos) { - Setup::progress(" - Adding manufacturer ".$mfgname, true); - $manufacturer = new Manufacturer(); - $manufacturer->setName($mfgname); - - PartKeepr::getEM()->persist($manufacturer); - - foreach ($logos as $logo) { - $mfglogo = new ManufacturerICLogo(); - $mfglogo->setManufacturer($manufacturer); - $mfglogo->replace(self::MANUFACTURER_PATH . "images/". $logo); - $mfglogo->setOriginalFilename($logo); - - PartKeepr::getEM()->persist($mfglogo); + try { + ManufacturerManager::getInstance()->getManufacturerByName($mfgname); + $skipped++; + } catch (\Exception $e) { + $manufacturer = new Manufacturer(); + $manufacturer->setName($mfgname); + + $this->entityManager->persist($manufacturer); + + foreach ($logos as $logo) { + $mfglogo = new ManufacturerICLogo(); + $mfglogo->setManufacturer($manufacturer); + $mfglogo->replace(self::MANUFACTURER_PATH . "images/". $logo); + $mfglogo->setOriginalFilename($logo); + + $this->entityManager->persist($mfglogo); + } + $count++; } } + + $this->entityManager->flush(); + $this->logMessage(sprintf("Imported %d Manufacturers, skipped %d because they already exist", $count, $skipped)); } } diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/PartCategorySetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/PartCategorySetup.php @@ -15,11 +15,14 @@ class PartCategorySetup { /** * Sets up the root category node */ - public static function setupRootCategory () { - Setup::progress("Creating category root node..."); + public function setupRootCategory () { PartCategoryManager::getInstance()->ensureRootExists(); } + public function run () { + $this->setupRootCategory(); + } + /** * Migrates the old categories */ diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/PartUnitSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/PartUnitSetup.php @@ -4,7 +4,7 @@ namespace de\RaumZeitLabor\PartKeepr\Setup; use de\RaumZeitLabor\PartKeepr\PartKeepr, de\RaumZeitLabor\PartKeepr\Part\PartUnit; -class PartUnitSetup { +class PartUnitSetup extends AbstractSetup { /** * Holds the default unit * @var object @@ -12,25 +12,24 @@ class PartUnitSetup { private static $defaultUnit; /** - * Sets up the default part unit + * Sets up the default part unit if none exists */ - public static function setupPartUnits () { - Setup::progress("Setting up default part unit `Pieces`"); - $partUnit = new PartUnit(); - $partUnit->setName(PartKeepr::i18n("Pieces")); - $partUnit->setShortName(PartKeepr::i18n("pcs")); - $partUnit->setDefault(true); - - PartUnitSetup::$defaultUnit = $partUnit; - - PartKeepr::getEM()->persist($partUnit); - } - - /** - * Returns the default part unit - * @return PartUnit The part unit - */ - public static function getDefaultPartUnit () { - return PartUnitSetup::$defaultUnit; + public function run () { + $dql = "SELECT COUNT(p) FROM de\RaumZeitLabor\PartKeepr\Part\PartUnit p WHERE p.is_default = 1"; + $query = $this->entityManager->createQuery($dql); + + if ($query->getSingleScalarResult() == 0) { + $partUnit = new PartUnit(); + $partUnit->setName(PartKeepr::i18n("Pieces")); + $partUnit->setShortName(PartKeepr::i18n("pcs")); + $partUnit->setDefault(true); + + $this->entityManager->persist($partUnit); + $this->entityManager->flush(); + + $this->logMessage("Added default part unit"); + } else { + $this->logMessage("Skipped adding default part unit, because a default part unit already exists"); + } } } diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/SchemaMigrationSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/SchemaMigrationSetup.php @@ -0,0 +1,21 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\Setup; + +use de\RaumZeitLabor\PartKeepr\PartKeepr, + Doctrine\DBAL\Migrations\Migration, + Doctrine\DBAL\Migrations\Configuration\YamlConfiguration; +/** + * Updates (or creates) the database schema + */ +class SchemaMigrationSetup extends AbstractSetup { + public function run () { + $configuration = new YamlConfiguration($this->entityManager->getConnection()); + + $baseDir = dirname(dirname(dirname(dirname(dirname(dirname(__DIR__)))))); + $configuration->load($baseDir . "/migrations.yml"); + + $migration = new Migration($configuration); + $migration->migrate(); + $this->logMessage("Database Schema migrated to the latest version"); + } +}+ \ No newline at end of file diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/SchemaSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/SchemaSetup.php @@ -0,0 +1,15 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\Setup; + +use de\RaumZeitLabor\PartKeepr\PartKeepr; +/** + * Updates (or creates) the database schema + */ +class SchemaSetup extends AbstractSetup { + public function run () { + $tool = new \Doctrine\ORM\Tools\SchemaTool($this->entityManager); + $classes = PartKeepr::getClassMetaData(); + $tool->updateSchema($classes); + $this->logMessage("Database Schema created/updated"); + } +}+ \ No newline at end of file diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Setup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Setup.php @@ -1,7 +1,8 @@ <?php namespace de\RaumZeitLabor\PartKeepr\Setup; -use de\RaumZeitLabor\PartKeepr\PartKeepr; +use de\RaumZeitLabor\PartKeepr\PartKeepr, + de\RaumZeitLabor\PartKeepr\Util\Configuration as PartKeeprConfiguration; declare(encoding = 'UTF-8'); @@ -16,15 +17,40 @@ class Setup { * Runs the setup. Right now, it only tests the prequisites. */ public function run () { - $this->testPrequisites(); + $this->runStep("all"); } /** - * Tests all requires prequisites for the system. + * Runs a specific setup step, or all steps. + * @param string $step + * @throws \Exception */ - public function testPrequisites () { - $this->testAPC(); - $this->testMemoryLimit(); + public function runStep ($step) { + $entityManager = PartKeepr::getEM(); + + $aSteps = array( + "schema" => new SchemaSetup($entityManager), + "adminuser" => new UserSetup($entityManager), + "partunit" => new PartUnitSetup($entityManager), + "footprint" => new FootprintSetup($entityManager), + "partcategory" => new PartCategorySetup($entityManager), + "siprefix" => new SiPrefixSetup($entityManager), + "unit" => new UnitSetup($entityManager), + "manufacturer" => new ManufacturerSetup($entityManager), + "schemamigration" => new SchemaMigrationSetup($entityManager) + ); + + if ($step == "all") { + foreach ($aSteps as $step) { + $step->run(); + } + } else { + if (array_key_exists($step, $aSteps)) { + $aSteps[$step]->run(); + } else { + throw new \Exception(sprintf("Setup step %s doesn't exist", $step)); + } + } } /** @@ -91,4 +117,34 @@ class Setup { return \Symfony\Component\Yaml\Yaml::parse($file); } } + + /** + * Sets the database configuration array from $_REQUEST + */ + public static function setDatabaseConfigurationFromRequest () { + switch ($_REQUEST["driver"]) { + case "mysql": + PartKeeprConfiguration::setOption("partkeepr.database.driver","pdo_mysql"); + PartKeeprConfiguration::setOption("partkeepr.database.dbname", $_REQUEST["dbname"]); + PartKeeprConfiguration::setOption("partkeepr.database.username", $_REQUEST["user"]); + PartKeeprConfiguration::setOption("partkeepr.database.password", $_REQUEST["password"]); + PartKeeprConfiguration::setOption("partkeepr.database.hostname", $_REQUEST["host"]); + + if (isset($_REQUEST['port'])) { + PartKeeprConfiguration::setOption("partkeepr.database.mysql_port", $_REQUEST["port"]); + } + break; + default: + throw new \Exception(sprintf("Invalid driver %s specified.", $_REQUEST["driver"])); + break; + } + } + + /** + * Sets the database configuration from + * @param unknown_type $options + */ + public static function setDatabaseConfigurationFromOptions ($options) { + + } } \ No newline at end of file diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/SiPrefixSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/SiPrefixSetup.php @@ -2,9 +2,10 @@ namespace de\RaumZeitLabor\PartKeepr\Setup; use de\RaumZeitLabor\PartKeepr\PartKeepr, - de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefix; + de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefix, + de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefixManager; -class SiPrefixSetup { +class SiPrefixSetup extends AbstractSetup { const SIPREFIX_DATA_FILE = "../setup-data/siprefixes.yaml"; @@ -14,37 +15,33 @@ class SiPrefixSetup { */ private static $siPrefixes = array(); + public function run () { + $this->setupSiPrefixes(); + } + /** * Sets up the SI prefixes */ - public static function setupSiPrefixes () { - Setup::progress("Setting up SI-Prefixes..."); + public function setupSiPrefixes () { + $count = 0; + $skipped = 0; + $data = Setup::loadYAML(self::SIPREFIX_DATA_FILE); foreach ($data as $prefixName => $data) { - Setup::progress(" - Adding prefix ".$prefixName, true); - $prefix = new SiPrefix(); - $prefix->setPrefix($prefixName); - $prefix->setPower($data["power"]); - $prefix->setSymbol($data["symbol"]); - - self::$siPrefixes[] = $prefix; - - PartKeepr::getEM()->persist($prefix); - } - } - - /** - * Returns the SI prefix by symbol - * @param string $symbol The symbol to find - */ - public static function getSiPrefixBySymbol ($symbol) { - foreach (self::$siPrefixes as $prefix) { - if ($prefix->getSymbol() == $symbol) { - return $prefix; + if (!SiPrefixManager::getInstance()->siPrefixExists($prefixName)) { + $prefix = new SiPrefix(); + $prefix->setPrefix($prefixName); + $prefix->setPower($data["power"]); + $prefix->setSymbol($data["symbol"]); + $this->entityManager->persist($prefix); + $count++; + } else { + $skipped++; } } - return false; + $this->entityManager->flush(); + $this->logMessage(sprintf("Imported %d Si Prefixes, skipped %d", $count, $skipped)); } } diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/UnitSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/UnitSetup.php @@ -3,24 +3,34 @@ namespace de\RaumZeitLabor\PartKeepr\Setup; use de\RaumZeitLabor\PartKeepr\PartKeepr, de\RaumZeitLabor\PartKeepr\Unit\Unit, + de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefixManager, + de\RaumZeitLabor\PartKeepr\Unit\UnitManager, de\RaumZeitLabor\PartKeepr\Setup\SiPrefixSetup; -class UnitSetup { +class UnitSetup extends AbstractSetup { const UNIT_DATA_FILE = "../setup-data/units.yaml"; + + public function run () { + $this->setupUnits(); + } /** * Sets up the default units * @throws \Exception */ - public static function setupUnits () { - Setup::progress("Setting up Units..."); + public function setupUnits () { + $count = 0; + $skipped = 0; $data = Setup::loadYAML(self::UNIT_DATA_FILE); $aUnits = array(); foreach ($data as $unitName => $data) { - Setup::progress(" - Adding unit ".$unitName, true); + if (UnitManager::getInstance()->unitExists($unitName)) { + $skipped++; + continue; + } $unit = new Unit(); $unit->setName($unitName); $unit->setSymbol($data["symbol"]); @@ -31,7 +41,8 @@ class UnitSetup { } foreach ($data["prefixes"] as $prefix) { - $siPrefix = SiPrefixSetup::getSiPrefixBySymbol($prefix); + + $siPrefix = SiPrefixManager::getInstance()->getSiPrefixBySymbol($prefix); if ($siPrefix === false) { throw new \Exception("Unable to find prefix ".$prefix); } @@ -40,6 +51,12 @@ class UnitSetup { } PartKeepr::getEM()->persist($unit); + $count++; } + + $this->entityManager->flush(); + $this->logMessage(sprintf("Imported %d Units, skipped %d because they already exist", $count, $skipped)); } + + } diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/UserSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/UserSetup.php @@ -0,0 +1,30 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\Setup; + +use de\RaumZeitLabor\PartKeepr\User\User; + +/** + * Creates a new admin user, but only if no admin user exists. + */ +class UserSetup extends AbstractSetup { + public function run () { + $dql = "SELECT COUNT(u) FROM de\RaumZeitLabor\PartKeepr\User\User u WHERE u.username = :username OR u.admin = 1"; + $query = $this->entityManager->createQuery($dql); + $query->setParameter("username", "admin"); + + if ($query->getSingleScalarResult() == 0) { + $user = new User(); + $user->setUsername("admin"); + $user->setPassword("admin"); + $user->setAdmin(true); + + $this->entityManager->persist($user); + $this->entityManager->flush(); + + $this->logMessage("Admin User created"); + } else { + $this->logMessage( "Skipped admin user creation, because an user named 'admin'". + "or another user with an admin flag already exists"); + } + } +}+ \ No newline at end of file diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/SiPrefix/SiPrefixManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/SiPrefix/SiPrefixManager.php @@ -0,0 +1,43 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\SiPrefix; +declare(encoding = 'UTF-8'); + +use de\RaumZeitLabor\PartKeepr\Util\Singleton, + de\RaumZeitLabor\PartKeepr\PartKeepr; + +class SiPrefixManager extends Singleton { + public $siPrefixSymbolCache = array(); + + public function getSiPrefixBySymbol ($symbol) { + if (!is_array($this->siPrefixSymbolCache) || count($this->siPrefixSymbolCache) == 0) { + $this->createSiPrefixSymbolCache(); + } + + foreach ($this->siPrefixSymbolCache as $entry) { + if ($entry->getSymbol() == $symbol) { + return $entry; + } + } + + throw new \Exception(sprintf("Symbol '%s' not found", $symbol)); + } + + private function createSiPrefixSymbolCache () { + $dql = "SELECT sip FROM de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefix sip"; + $query = PartKeepr::getEM()->createQuery($dql); + + $this->siPrefixSymbolCache = $query->getResult(); + } + + public function siPrefixExists ($prefix) { + $dql = "SELECT COUNT(sip) FROM de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefix sip WHERE sip.prefix = :prefix"; + $query = PartKeepr::getEM()->createQuery($dql); + $query->setParameter("prefix", $prefix); + + if ($query->getSingleScalarResult() == 0) { + return false; + } else { + return true; + } + } +}+ \ No newline at end of file diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Unit/UnitManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Unit/UnitManager.php @@ -59,6 +59,26 @@ class UnitManager extends Singleton { return array("response" => array("totalCount" => count($aData), "data" => $aData)); } + public function getUnitByName ($name) { + $dql = "SELECT u FROM de\RaumZeitLabor\PartKeepr\Unit\Unit u WHERE u.name = :name"; + $query = PartKeepr::getEM()->createQuery($dql); + $query->setParameter("name", $name); + + return $query->getSingleResult(); + } + + public function unitExists ($name) { + $dql = "SELECT COUNT(u) FROM de\RaumZeitLabor\PartKeepr\Unit\Unit u WHERE u.name = :name"; + $query = PartKeepr::getEM()->createQuery($dql); + $query->setParameter("name", $name); + + if ($query->getSingleScalarResult() == 0) { + return false; + } else { + return true; + } + } + public function getUnit ($id) { $unit = PartKeepr::getEM()->find("de\RaumZeitLabor\PartKeepr\Unit\Unit", $id); diff --git a/src/setup/index.html b/src/setup/index.html @@ -10,14 +10,10 @@ <!-- Include the ExtJS CSS Theme --> <link rel="stylesheet" type="text/css" href="css/partkeepr-theme.css"/> - <link rel="stylesheet" type="text/css" href="js/Ext.ux/statusbar/css/statusbar.css"/> - <link rel="stylesheet" type="text/css" href="css/PartKeepr.css"/> <link rel="stylesheet" type="text/css" href="resources/css/setup.css"/> - <link href="js/wizard/resources/css/ext-ux-wiz.css" rel="stylesheet" type="text/css" /> + <link href="js/wizard/resources/css/ext-ux-wiz.css" rel="stylesheet" type="text/css" /> - <link rel="icon" href="favicon.ico"/> - <!-- Include the ExtJS JavaScript Library --> <script type="text/javascript" src="extjs/bootstrap.js"></script> <script type="text/javascript" src="extjs/ext-all-debug.js"></script> @@ -41,6 +37,7 @@ <script type="text/javascript" src="js/Cards/DatabaseParametersCard.MySQL.js"></script> <script type="text/javascript" src="js/Cards/DatabaseParametersCard.PostgreSQL.js"></script> <script type="text/javascript" src="js/Cards/DatabaseConnectivityTestCard.js"></script> + <script type="text/javascript" src="js/Cards/DatabaseSetupCard.js"></script> <script type="text/javascript" src="js/SetupTests/AbstractTest.js"></script> <script type="text/javascript" src="js/SetupTests/PHPTest.js"></script> @@ -50,6 +47,16 @@ <script type="text/javascript" src="js/SetupTests/PHPSettingsTest.js"></script> <script type="text/javascript" src="js/SetupTests/FilesystemPermissionTest.js"></script> + <script type="text/javascript" src="js/SetupSteps/SchemaSetup.js"></script> + <script type="text/javascript" src="js/SetupSteps/AdminUserSetup.js"></script> + <script type="text/javascript" src="js/SetupSteps/ManufacturerSetup.js"></script> + <script type="text/javascript" src="js/SetupSteps/PartCategorySetup.js"></script> + <script type="text/javascript" src="js/SetupSteps/PartUnitSetup.js"></script> + <script type="text/javascript" src="js/SetupSteps/SiPrefixSetup.js"></script> + <script type="text/javascript" src="js/SetupSteps/UnitSetup.js"></script> + <script type="text/javascript" src="js/SetupSteps/FootprintSetup.js"></script> + <script type="text/javascript" src="js/SetupSteps/SchemaMigrationSetup.js"></script> + <script type="text/javascript" src="js/PartKeeprSetup.js"></script> </head> <body> diff --git a/src/setup/js/Cards/AbstractTestCard.js b/src/setup/js/Cards/AbstractTestCard.js @@ -34,7 +34,6 @@ Ext.define('PartKeeprSetup.AbstractTestCard', { /** * Various Style Settings */ - title: 'Checking Database Connectivity', showTitle: true, titleCls: '', titleStyle: 'font-size: 2.5em;', @@ -65,6 +64,10 @@ Ext.define('PartKeeprSetup.AbstractTestCard', { this.retestButton ]; this.tests = new Array(); + + this.testRunner = Ext.create("PartKeeprSetup.TestRunner"); + this.testRunner.on("success", this.onTestSuccessful, this); + this.setupTests(); this.callParent(); this.on("activate", this.onActivate, this); @@ -100,12 +103,10 @@ Ext.define('PartKeeprSetup.AbstractTestCard', { runTests: function () { this.testResultPanel.clear(); - var tr = Ext.create("PartKeeprSetup.TestRunner"); - // We need to clone the test array, because we wouldn't be able to run all tests twice var clonedTests = this.tests.slice(0); - tr.run(clonedTests); - tr.on("success", this.onTestSuccessful, this); + this.testRunner.run(clonedTests, this.testResultPanel); + }, /** * When the card is activated, automatically invoke all tests. diff --git a/src/setup/js/Cards/DatabaseConnectivityTestCard.js b/src/setup/js/Cards/DatabaseConnectivityTestCard.js @@ -8,13 +8,11 @@ Ext.define('PartKeeprSetup.DatabaseConnectivityTestCard', { extend: 'PartKeeprSetup.AbstractTestCard', cardMessage: "Setup tests if the database is reachable. Please note that this may take a minute or two to display a status if your database is not reachable.", - + title: 'Checking Database Connectivity', /** * Sets up the tests */ setupTests: function () { - var j = Ext.create("PartKeeprSetup.DatabaseConnectivityTest"); - j.callback = this.testResultPanel; - this.tests.push(j); + this.tests.push(new PartKeeprSetup.DatabaseConnectivityTest()); } }); diff --git a/src/setup/js/Cards/DatabaseParametersCard.MySQL.js b/src/setup/js/Cards/DatabaseParametersCard.MySQL.js @@ -63,7 +63,7 @@ Ext.define('PartKeeprSetup.DatabaseParametersCard.MySQL', { validateOnBlur: true, validateOnChange: false, validator: function (value) { - if (value == "" || value == 0) { + if (value === "" || value === 0) { this.setValue(3306); } return true; @@ -100,8 +100,8 @@ Ext.define('PartKeeprSetup.DatabaseParametersCard.MySQL', { background: "none" }, items: [ - this.showHintCheckbox - ,{ + this.showHintCheckbox, + { border: false, style: 'overflow: auto;', width: "450px", @@ -137,7 +137,9 @@ Ext.define('PartKeeprSetup.DatabaseParametersCard.MySQL', { this.masterTemplate.overwrite(Ext.get("mysql-parameters-hint")); } - if (this.hostname.getValue() != "" && this.username.getValue() != "" && this.password.getValue() != "" && this.databaseName.getValue() != "") { + if (this.hostname.getValue() !== "" && this.username.getValue() !== "" && this.password.getValue() !== "" && + this.databaseName.getValue() !== "") { + this.paramsheet.ownerCt.ownerCt.nextButton.setDisabled(false); } diff --git a/src/setup/js/Cards/DatabaseParametersCard.js b/src/setup/js/Cards/DatabaseParametersCard.js @@ -61,7 +61,7 @@ Ext.define('PartKeeprSetup.DatabaseParametersCard', { var databaseTypes = Ext.create('Ext.data.Store', { fields: ['type', 'name'], data : [ - {"type":"mysql", "name":"MySQL"}, + {"type":"mysql", "name":"MySQL"} //For the first version, we only support MySQL as database //{"type":"postgresql", "name":"PostgreSQL"} ] @@ -96,6 +96,7 @@ Ext.define('PartKeeprSetup.DatabaseParametersCard', { break; default: this.databaseSettings.layout.setActiveItem(0); + break; } } else { this.databaseSettings.layout.setActiveItem(0); diff --git a/src/setup/js/Cards/DatabaseSetupCard.js b/src/setup/js/Cards/DatabaseSetupCard.js @@ -0,0 +1,26 @@ +/** + * This card tests the database connectivity for the MySQL database. + * + * Basically this submits all connection settings to a special PHP script, + * which then attempts to establish the database connection. + */ +Ext.define('PartKeeprSetup.DatabaseSetupCard', { + extend: 'PartKeeprSetup.AbstractTestCard', + + cardMessage: "PartKeepr is now being set-up.", + title: 'PartKeepr is now being set-up, please wait', + /** + * Sets up the tests + */ + setupTests: function () { + this.tests.push(new PartKeeprSetup.SchemaSetup()); + this.tests.push(new PartKeeprSetup.AdminUserSetup()); + this.tests.push(new PartKeeprSetup.PartUnitSetup()); + this.tests.push(new PartKeeprSetup.FootprintSetup()); + this.tests.push(new PartKeeprSetup.PartCategorySetup()); + this.tests.push(new PartKeeprSetup.SiPrefixSetup()); + this.tests.push(new PartKeeprSetup.UnitSetup()); + this.tests.push(new PartKeeprSetup.ManufacturerSetup()); + this.tests.push(new PartKeeprSetup.SchemaMigrationSetup()); + } +}); diff --git a/src/setup/js/Cards/PrequisitesTestCard.js b/src/setup/js/Cards/PrequisitesTestCard.js @@ -5,29 +5,15 @@ Ext.define('PartKeeprSetup.PrequisitesTestCard', { extend: 'PartKeeprSetup.AbstractTestCard', cardMessage: "Setup now checks if your server is capable of running PartKeepr.", - + title: 'Checking prequisites', /** * Sets up all tests */ setupTests: function () { - var j = Ext.create("PartKeeprSetup.PHPTest"); - j.callback = this.testResultPanel; - this.tests.push(j); - - var j = Ext.create("PartKeeprSetup.PHPPrequisitesTest"); - j.callback = this.testResultPanel; - this.tests.push(j); - - var j = Ext.create("PartKeeprSetup.PHPSettingsTest"); - j.callback = this.testResultPanel; - this.tests.push(j); - - var j = Ext.create("PartKeeprSetup.DoctrineTest"); - j.callback = this.testResultPanel; - this.tests.push(j); - - var j = Ext.create("PartKeeprSetup.FilesystemPermissionTest"); - j.callback = this.testResultPanel; - this.tests.push(j); + this.tests.push(new PartKeeprSetup.PHPTest()); + this.tests.push(new PartKeeprSetup.PHPPrequisitesTest()); + this.tests.push(new PartKeeprSetup.PHPSettingsTest()); + this.tests.push(new PartKeeprSetup.DoctrineTest()); + this.tests.push(new PartKeeprSetup.FilesystemPermissionTest()); } }); diff --git a/src/setup/js/SetupSteps/AdminUserSetup.js b/src/setup/js/SetupSteps/AdminUserSetup.js @@ -0,0 +1,14 @@ +/** + * Creates the administrative user + */ +Ext.define('PartKeeprSetup.AdminUserSetup', { + extend: 'PartKeeprSetup.AbstractTest', + url: 'setup.php', + name: "Database", + message: "Setting up the admin user", + + onBeforeRunTest: function () { + this.params = Ext.getCmp("database-parameters-card").dbparams; + this.params.step = "adminuser"; + } +});+ \ No newline at end of file diff --git a/src/setup/js/SetupSteps/FootprintSetup.js b/src/setup/js/SetupSteps/FootprintSetup.js @@ -0,0 +1,14 @@ +/** + * Sets up the footprints + */ +Ext.define('PartKeeprSetup.FootprintSetup', { + extend: 'PartKeeprSetup.AbstractTest', + url: 'setup.php', + name: "Database", + message: "Setting up the default footprints", + + onBeforeRunTest: function () { + this.params = Ext.getCmp("database-parameters-card").dbparams; + this.params.step = "footprint"; + } +});+ \ No newline at end of file diff --git a/src/setup/js/SetupSteps/ManufacturerSetup.js b/src/setup/js/SetupSteps/ManufacturerSetup.js @@ -0,0 +1,14 @@ +/** + * Sets up the Manufacturers + */ +Ext.define('PartKeeprSetup.ManufacturerSetup', { + extend: 'PartKeeprSetup.AbstractTest', + url: 'setup.php', + name: "Database", + message: "Setting up the default manufacturers", + + onBeforeRunTest: function () { + this.params = Ext.getCmp("database-parameters-card").dbparams; + this.params.step = "manufacturer"; + } +});+ \ No newline at end of file diff --git a/src/setup/js/SetupSteps/PartCategorySetup.js b/src/setup/js/SetupSteps/PartCategorySetup.js @@ -0,0 +1,14 @@ +/** + * Sets up the part categories + */ +Ext.define('PartKeeprSetup.PartCategorySetup', { + extend: 'PartKeeprSetup.AbstractTest', + url: 'setup.php', + name: "Database", + message: "Setting up part categories", + + onBeforeRunTest: function () { + this.params = Ext.getCmp("database-parameters-card").dbparams; + this.params.step = "partcategory"; + } +});+ \ No newline at end of file diff --git a/src/setup/js/SetupSteps/PartUnitSetup.js b/src/setup/js/SetupSteps/PartUnitSetup.js @@ -0,0 +1,14 @@ +/** + * Creates the part units + */ +Ext.define('PartKeeprSetup.PartUnitSetup', { + extend: 'PartKeeprSetup.AbstractTest', + url: 'setup.php', + name: "Database", + message: "Setting up the part units", + + onBeforeRunTest: function () { + this.params = Ext.getCmp("database-parameters-card").dbparams; + this.params.step = "partunit"; + } +});+ \ No newline at end of file diff --git a/src/setup/js/SetupSteps/SchemaMigrationSetup.js b/src/setup/js/SetupSteps/SchemaMigrationSetup.js @@ -0,0 +1,14 @@ +/** + * Migrates the schema to the latest version + */ +Ext.define('PartKeeprSetup.SchemaMigrationSetup', { + extend: 'PartKeeprSetup.AbstractTest', + url: 'setup.php', + name: "Database", + message: "Migrating the schema to the latest version", + + onBeforeRunTest: function () { + this.params = Ext.getCmp("database-parameters-card").dbparams; + this.params.step = "schemamigration"; + } +});+ \ No newline at end of file diff --git a/src/setup/js/SetupSteps/SchemaSetup.js b/src/setup/js/SetupSteps/SchemaSetup.js @@ -0,0 +1,14 @@ +/** + * Sets up the database schema + */ +Ext.define('PartKeeprSetup.SchemaSetup', { + extend: 'PartKeeprSetup.AbstractTest', + url: 'setup.php', + name: "Database", + message: "Setting up the database schema", + + onBeforeRunTest: function () { + this.params = Ext.getCmp("database-parameters-card").dbparams; + this.params.step = "schema"; + } +});+ \ No newline at end of file diff --git a/src/setup/js/SetupSteps/SiPrefixSetup.js b/src/setup/js/SetupSteps/SiPrefixSetup.js @@ -0,0 +1,14 @@ +/** + * Sets up the SI prefixes + */ +Ext.define('PartKeeprSetup.SiPrefixSetup', { + extend: 'PartKeeprSetup.AbstractTest', + url: 'setup.php', + name: "Database", + message: "Setting up the SI Prefixes", + + onBeforeRunTest: function () { + this.params = Ext.getCmp("database-parameters-card").dbparams; + this.params.step = "siprefix"; + } +});+ \ No newline at end of file diff --git a/src/setup/js/SetupSteps/UnitSetup.js b/src/setup/js/SetupSteps/UnitSetup.js @@ -0,0 +1,14 @@ +/** + * Sets up the default units + */ +Ext.define('PartKeeprSetup.UnitSetup', { + extend: 'PartKeeprSetup.AbstractTest', + url: 'setup.php', + name: "Database", + message: "Setting up the default units", + + onBeforeRunTest: function () { + this.params = Ext.getCmp("database-parameters-card").dbparams; + this.params.step = "unit"; + } +});+ \ No newline at end of file diff --git a/src/setup/js/SetupTests/AbstractTest.js b/src/setup/js/SetupTests/AbstractTest.js @@ -52,11 +52,13 @@ Ext.define('PartKeeprSetup.AbstractTest', { run: function () { this.onBeforeRunTest(); + this.callback.outputTestMessage(this); Ext.Ajax.request({ url: this.url, success: this.onSuccess, scope: this, - params: this.params + params: this.params, + timeout: 120000 }); }, @@ -69,7 +71,7 @@ Ext.define('PartKeeprSetup.AbstractTest', { onSuccess: function (response) { var obj = Ext.decode(response.responseText); - if (obj.error == false) { + if (obj.error === false) { this.success = true; } else { this.success = false; @@ -81,7 +83,7 @@ Ext.define('PartKeeprSetup.AbstractTest', { } if (this.success) { - this.fireEvent("complete"); + this.fireEvent("complete", this); } }, /** diff --git a/src/setup/js/SetupWizard.js b/src/setup/js/SetupWizard.js @@ -74,6 +74,20 @@ Ext.define('PartKeeprSetup.SetupWizard', { cards.push(Ext.create("PartKeeprSetup.PrequisitesTestCard")); cards.push(Ext.create("PartKeeprSetup.DatabaseParametersCard")); cards.push(Ext.create("PartKeeprSetup.DatabaseConnectivityTestCard")); + cards.push(Ext.create("PartKeeprSetup.DatabaseSetupCard")); + + cards.push(Ext.create('Ext.ux.wizard.Card', { + title: 'Setup Complete', + showTitle: true, + titleCls: '', + titleStyle: 'font-size: 2.5em;', + cls: 'x-partkeepr-setup-basecard', + items: [{ + border: false, + bodyStyle: 'background:none;', + html: "<b>PartKeepr is now set-up.</b><br/><br/>If possible, set your web server's document root to the <b>frontend</b> directory.<br/><br/>To open PartKeepr, open the 'frontend' directory using your browser.<br/><br/>The default username/password combination is <b>admin/admin</b>" + }] + })); return cards; } diff --git a/src/setup/js/TestResultPanel.js b/src/setup/js/TestResultPanel.js @@ -19,6 +19,14 @@ Ext.define('PartKeeprSetup.TestResultPanel', { this.removeAll(true); }, + outputTestMessage: function (test) { + var cmp = this.add({ + border: false, + html: test.message +'...<img src="resources/images/ajax-loader.gif" align="absbottom"/>' + }); + + test.outputCmp = cmp; + }, /** * Appends the specific test to the output panel, * and fires the error event if an error occured. @@ -35,7 +43,7 @@ Ext.define('PartKeeprSetup.TestResultPanel', { this.fireEvent("test-error"); } - this.add({ + test.outputCmp.body.replaceWith({ border: false, html: test.message +"..."+response }); diff --git a/src/setup/js/TestRunner.js b/src/setup/js/TestRunner.js @@ -20,15 +20,29 @@ Ext.define('PartKeeprSetup.TestRunner', { * * @param tests An array of tests */ - run: function (tests) { + run: function (tests, callback) { test = tests.shift(); + this.tests = tests; if (!test) { this.fireEvent("success"); return; } - test.on("complete", function () { this.run(tests); }, this); + test.callback = callback; + + /** + * We re-assign the event handler on each cycle due to the asynchronous nature of the ajax requests. + */ + test.on("complete", this.onTestComplete, this); test.run(); + }, + /** + * Callback when the test is complete + * @param test The test which was run + */ + onTestComplete: function (test) { + test.un(this.onTestComplete); + this.run(this.tests, test.callback); } }); \ No newline at end of file diff --git a/src/setup/resources/images/ajax-loader.gif b/src/setup/resources/images/ajax-loader.gif Binary files differ. diff --git a/src/setup/setup.php b/src/setup/setup.php @@ -0,0 +1,31 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\Setup; + +declare(encoding = 'UTF-8'); + +use de\RaumZeitLabor\PartKeepr\PartKeepr, + de\RaumZeitLabor\PartKeepr\Setup\Setup; + +declare(encoding = 'UTF-8'); + +include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php"); +PartKeepr::initializeClassLoaders(); + +try { + $onnectionOptions = Setup::setDatabaseConfigurationFromRequest(); +} catch (\Exception $e) { + echo json_encode(array("error" => true, "errormessage" => $e->getMessage())); + exit; +} + +PartKeepr::initialize(); + +$setup = new Setup(); + +try { + $setup->runStep($_REQUEST["step"]); + echo json_encode(array("error" => false)); +} catch (\Exception $e) { + echo json_encode(array("error" => true, "errormessage" => "An unexpected error occured during installation. The error message was:<br/><code>".$e->getMessage()."</code>")); + exit; +}+ \ No newline at end of file diff --git a/src/setup/tests/check-database-connectivity.php b/src/setup/tests/check-database-connectivity.php @@ -2,41 +2,25 @@ /** * Tests the connection to the database. */ -require_once 'Doctrine/Common/ClassLoader.php'; +include("../../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php"); use Doctrine\Common\ClassLoader; +use de\RaumZeitLabor\PartKeepr\PartKeepr, + de\RaumZeitLabor\PartKeepr\Setup\Setup; -$classLoader = new ClassLoader('Doctrine\DBAL'); -$classLoader->register(); - -$classLoader = new ClassLoader('Doctrine\Common'); -$classLoader->register(); +PartKeepr::initializeClassLoaders(); $config = new \Doctrine\DBAL\Configuration(); - /** * Check which driver we are going to use, and set the connection parameters accordingly. */ -switch ($_REQUEST["driver"]) { - case "mysql": - $connectionOptions = array( - 'driver' => "pdo_mysql", - 'dbname' => $_REQUEST["dbname"], - 'user' => $_REQUEST["user"], - 'password' => $_REQUEST["password"], - 'host' => $_REQUEST["host"], - 'charset' => 'utf8' - ); - - if (isset($_REQUEST['port'])) { - $connectionOptions['port'] = $_REQUEST['port']; - } - break; - default: - echo json_encode(array("error" => true, "errormessage" => "Unknown driver ".$_REQUEST["driver"])); - exit; - break; +try { + $onnectionOptions = Setup::setDatabaseConfigurationFromRequest(); + $connectionOptions = PartKeepr::createConnectionOptionsFromConfig(); +} catch (\Exception $e) { + echo json_encode(array("error" => true, "errormessage" => $e->getMessage())); + exit; } $conn = \Doctrine\DBAL\DriverManager::getConnection($connectionOptions, $config); diff --git a/src/setup/tests/check-php-settings.php b/src/setup/tests/check-php-settings.php @@ -4,5 +4,10 @@ if (ini_get("safe_mode")) { exit; } +if (ini_get("allow_url_fopen") == false) { + echo json_encode(array("error" => true, "errormessage" => "PHP allow_url_fopen is set to off. Right now, we require that it is set to ON. Please set<br/><code>allow_url_fopen = On</code> in your php.ini file.")); + exit; +} + echo json_encode(array("error" => false)); exit; \ No newline at end of file diff --git a/testing/SetupDatabase.php b/testing/SetupDatabase.php @@ -40,9 +40,6 @@ use de\RaumZeitLabor\PartKeepr\Distributor\Distributor; PartKeepr::initialize(); -$setup = new Setup(); -$setup->run(); - $ask = true; $migration = false; @@ -92,32 +89,13 @@ if ($ask) { echo "Performing actions...\n"; -@mkdir("../src/Proxies"); -@mkdir("../data"); -@mkdir("../data/images"); +$setup = new Setup(); +$setup->run(); + +/*@mkdir("../data/images"); @mkdir("../data/files"); chmod("../data/images", 0777); -chmod("../data/files", 0777); - -$tool = new \Doctrine\ORM\Tools\SchemaTool(PartKeepr::getEM()); - -$classes = PartKeepr::getClassMetaData(); - -Setup::progress("Dropping schema `".Configuration::getOption("partkeepr.database.dbname")."`"); -$tool->dropDatabase($classes); -Setup::progress("Creating schema `".Configuration::getOption("partkeepr.database.dbname")."`"); -$tool->createSchema($classes); - -Setup::progress("Setting up initial admin user"); -/* Create initial test user */ -$user = new User(); -$user->setUsername("admin"); -$user->setPassword("admin"); -$user->setAdmin(true); -PartKeepr::getEM()->persist($user); - -PartUnitSetup::setupPartUnits(); -PartKeepr::getEM()->flush(); +chmod("../data/files", 0777);*/ /* Create footprints */ @@ -131,41 +109,31 @@ if ($migration) { mysql_select_db("partdb"); } -FootprintSetup::setupRootNode(); -FootprintSetup::importFootprintData(); -PartKeepr::getEM()->flush(); -if ($migration) { +/*if ($migration) { FootprintSetup::migrateFootprints(); PartKeepr::getEM()->flush(); -} - -PartCategorySetup::setupRootCategory(); +}*/ -if ($migration) { +/*if ($migration) { PartCategorySetup::migrateCategories(); -} - +}*/ +/* if ($migration) { StorageLocationSetup::migrateStorageLocations(); PartKeepr::getEM()->flush(); -} - - -/* Add Si-Prefixes */ -SiPrefixSetup::setupSiPrefixes(); -PartKeepr::getEM()->flush(); +}*/ /* Add units */ -UnitSetup::setupUnits(); -PartKeepr::getEM()->flush(); +//UnitSetup::setupUnits(); +//PartKeepr::getEM()->flush(); /* Add Manufacturers */ -ManufacturerSetup::setupManufacturers(); -PartKeepr::getEM()->flush(); +/*ManufacturerSetup::setupManufacturers(); +PartKeepr::getEM()->flush();*/ if ($migration) { DistributorSetup::migrateDistributors();