partkeepr

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

commit ba6335ebcdf5233e6793db5b28312ab4f91a04c6
parent 4d29a4baea9fbb2f3970badb286318ec61a645f1
Author: Felicitus <felicitus@felicitus.org>
Date:   Wed, 21 Dec 2011 08:17:21 +0100

Finalized CLI setup including migration; web setup migration is missing yet

Diffstat:
Mconfig.php.template | 11+++++++++--
Msrc/backend/de/RaumZeitLabor/PartKeepr/Category/AbstractCategoryManager.php | 46++++++++++++++++++++++++++++++++++++++++++++++
Msrc/backend/de/RaumZeitLabor/PartKeepr/Distributor/DistributorManager.php | 14++++++++++++++
Msrc/backend/de/RaumZeitLabor/PartKeepr/Footprint/FootprintManager.php | 14++++++++++++++
Msrc/backend/de/RaumZeitLabor/PartKeepr/PartUnit/PartUnitManager.php | 11+++++++++++
Msrc/backend/de/RaumZeitLabor/PartKeepr/Setup/AbstractSetup.php | 10+++++++++-
Dsrc/backend/de/RaumZeitLabor/PartKeepr/Setup/DistributorSetup.php | 40----------------------------------------
Msrc/backend/de/RaumZeitLabor/PartKeepr/Setup/FootprintSetup.php | 24+-----------------------
Asrc/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/DistributorMigration.php | 34++++++++++++++++++++++++++++++++++
Asrc/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/FootprintMigration.php | 43+++++++++++++++++++++++++++++++++++++++++++
Asrc/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/PartCategoryMigration.php | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/PartDBMigration.php | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/PartMigration.php | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/StorageLocationMigration.php | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/backend/de/RaumZeitLabor/PartKeepr/Setup/PartCategorySetup.php | 63+--------------------------------------------------------------
Dsrc/backend/de/RaumZeitLabor/PartKeepr/Setup/PartSetup.php | 106-------------------------------------------------------------------------------
Msrc/backend/de/RaumZeitLabor/PartKeepr/Setup/Setup.php | 40++++++++++++++++++----------------------
Dsrc/backend/de/RaumZeitLabor/PartKeepr/Setup/StorageLocationSetup.php | 39---------------------------------------
Msrc/setup/js/SetupWizard.js | 1-
Mtesting/SetupDatabase.php | 105+++++++++++++++++++++----------------------------------------------------------
20 files changed, 533 insertions(+), 374 deletions(-)

diff --git a/config.php.template b/config.php.template @@ -50,8 +50,15 @@ Configuration::setOption("partkeepr.database.driver", "pdo_mysql"); /*********************************************************************************************************************** - * END OF THE GENERAL CONFIGURATION SECTION - BELOW ARE CONFIGURATION SETTINGS WHICH DON'T NEED TO BE ADJUSTED ON - * A REGULAR BASIS + * CONFIGURATION SETTINGS FOR MIGRATING FROM PARTDB TO PARTKEEPR. LEAVE UNTOUCHED IF YOU DON'T HAVE PARTDB TO MIGRATE + **********************************************************************************************************************/ +Configuration::setOption("partkeepr.migration.partdb.hostname", "localhost"); +Configuration::setOption("partkeepr.migration.partdb.username", "partdb"); +Configuration::setOption("partkeepr.migration.partdb.password", "partdb"); +Configuration::setOption("partkeepr.migration.partdb.dbname", "partdb"); + +/*********************************************************************************************************************** + * END OF THE GENERAL CONFIGURATION SECTION - BELOW ARE CONFIGURATION SETTINGS WHICH USUALLY DON'T NEED TO BE ADJUSTED **********************************************************************************************************************/ diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Category/AbstractCategoryManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Category/AbstractCategoryManager.php @@ -142,6 +142,52 @@ abstract class AbstractCategoryManager extends Singleton { return PartKeepr::getEM()->createQuery($dql)->getSingleScalarResult(); } + /** + * Creates a category tree by an array of category names + * @param array $aCategoryNames + * @param Category A category where to start searching at + */ + public function createCategoryTreeByArray ($aCategoryNames, NodeWrapper $rootNode = null) { + if (count($aCategoryNames) == 0) { + return false; + } + + $categoryName = array_shift($aCategoryNames); + + if ($rootNode === null) { + $rootNode = $this->getRootNode(); + } + + $bFound = false; + foreach ($rootNode->getChildren() as $child) { + if ($child->getNode()->getName() == $categoryName) { + $bFound = true; + $category = $child->getNode(); + break; + } + } + + if ($bFound === false) { + $category = new $this->categoryClass(); + $category->setName($categoryName); + $category->setDescription(""); + $category->setParent($rootNode->getId()); + $this->addCategory($category); + } + + $result = $this->createCategoryTreeByArray($aCategoryNames,new NodeWrapper($category, $this->getNodeManager())); + + if ($result === false) { + return $category; + } else { + return $result; + } + } + + /** + * Loads a category by id + * @param string $id + */ protected function loadCategoryById($id) { $class = $this->categoryClass; diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Distributor/DistributorManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Distributor/DistributorManager.php @@ -91,4 +91,18 @@ class DistributorManager extends Singleton { PartKeepr::getEM()->remove($distributor); PartKeepr::getEM()->flush(); } + + /** + * Retrieves a distributor by its name. + * + * @param string $name The name of the distributor to retrieve + * @throws Doctrine\ORM\NoResultException If the distributor was not found + */ + public function getDistributorByName ($name) { + $dql = "SELECT d FROM de\RaumZeitLabor\PartKeepr\Distributor\Distributor d WHERE d.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/Footprint/FootprintManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Footprint/FootprintManager.php @@ -143,4 +143,18 @@ class FootprintManager extends Singleton { return $fp; } + + /** + * Retrieves a distributor by its name. + * + * @param string $name The name of the distributor to retrieve + * @throws Doctrine\ORM\NoResultException If the distributor was not found + */ + public function getFootprintByName ($name) { + $dql = "SELECT fp FROM de\RaumZeitLabor\PartKeepr\Footprint\Footprint fp WHERE fp.name = :name"; + $query = PartKeepr::getEM()->createQuery($dql); + $query->setParameter("name", $name); + + return $query->getSingleResult(); + } } diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/PartUnit/PartUnitManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/PartUnit/PartUnitManager.php @@ -74,6 +74,17 @@ class PartUnitManager extends Singleton { PartKeepr::getEM()->flush(); } + /** + * Returns the default part unit for this system + * + * @param none + * @return PartUnit The default part unit for this system + */ + public function getDefaultPartUnit () { + $dql = 'SELECT pu FROM de\RaumZeitLabor\PartKeepr\Part\PartUnit pu WHERE pu.is_default = 1'; + return PartKeepr::getEM()->createQuery($dql)->getSingleResult(); + } + public function setDefaultPartUnit ($id) { PartKeepr::getEM()->beginTransaction(); diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/AbstractSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/AbstractSetup.php @@ -7,6 +7,8 @@ use Doctrine\ORM\EntityManager; * Represents a basic setup step */ abstract class AbstractSetup { + private $console; + /** * Represents the Doctrine Entity Manager * @var Doctrine\ORM\EntityManager @@ -29,8 +31,14 @@ abstract class AbstractSetup { abstract public function run (); + public function setConsole ($console) { + $this->console = $console; + } + public function logMessage ($message) { - //echo "- ".$message."\n"; + if ($this->console) { + echo "- ".$message."\n"; + } $this->messages[] = $message; } } \ No newline at end of file diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/DistributorSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/DistributorSetup.php @@ -1,40 +0,0 @@ -<?php -namespace de\RaumZeitLabor\PartKeepr\Setup; - -use de\RaumZeitLabor\PartKeepr\PartKeepr, - de\RaumZeitLabor\PartKeepr\Distributor\Distributor, - de\RaumZeitLabor\PartKeepr\Setup\SiPrefixSetup; - -class DistributorSetup { - /** - * Holds the migrated distributors for easy access by id - * @var array - */ - private static $migratedDistributors = array(); - - /** - * Migrates the existing distributors - */ - public static function migrateDistributors () { - Setup::progress("Migrating distributors..."); - - $r = mysql_query("SELECT * FROM suppliers"); - while ($supplier = mysql_fetch_assoc($r)) { - Setup::progress(" - Migrating distributor ".$supplier["name"], true); - $distributor = new Distributor(); - $distributor->setName($supplier["name"]); - - DistributorSetup::$migratedDistributors[$supplier["id"]] = $distributor; - PartKeepr::getEM()->persist($distributor); - } - - } - - /** - * Returns the migrated distributor by it's ID from the old partdb - * @param int $id The distributor's ID from the old partdb - */ - public static function getMigratedDistributor ($id) { - return DistributorSetup::$migratedDistributors[$id]; - } -} diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/FootprintSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/FootprintSetup.php @@ -71,28 +71,6 @@ class FootprintSetup extends AbstractSetup { } /** - * Migrates the existing footprints from the PartDB. - */ - public static function migrateFootprints () { - $r = mysql_query("SELECT * FROM footprints"); - - while ($sFootprint = mysql_fetch_assoc($r)) { - Setup::progress(" - Migrating footprint ".$sFootprint["name"], true); - - $footprint = new Footprint(); - $footprint->setName(Setup::convertText($sFootprint["name"])); - - - $footprintCategory = FootprintSetup::addFootprintPath(explode("/", "Imported Footprints"), FootprintCategoryManager::getInstance()->getRootNode()); - $footprint->setCategory($footprintCategory->getNode()); - - $this->entityManager->persist($footprint); - - FootprintSetup::$migratedFootprints[$sFootprint["id"]] = $footprint; - } - } - - /** * Checks if the specified footprint exists * @param string $name The footprint name */ @@ -161,7 +139,7 @@ class FootprintSetup extends AbstractSetup { $footprint->getAttachments()->add($footprintAttachment); } catch (\Exception $e) { - echo "error with url ".$attachment["url"]."\n"; + //echo "error with url ".$attachment["url"]."\n"; } } diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/DistributorMigration.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/DistributorMigration.php @@ -0,0 +1,34 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\Setup\Migration\PartDB; + +use de\RaumZeitLabor\PartKeepr\PartKeepr, + de\RaumZeitLabor\PartKeepr\Distributor\Distributor, + de\RaumZeitLabor\PartKeepr\Distributor\DistributorManager, + de\RaumZeitLabor\PartKeepr\Setup\AbstractSetup; + +class DistributorMigration extends AbstractSetup { + /** + * Migrates the existing distributors + */ + public function run () { + $count = 0; + $skipped = 0; + $r = mysql_query("SELECT * FROM suppliers"); + while ($supplier = mysql_fetch_assoc($r)) { + $name = PartDBMigration::convertText($supplier["name"]); + try { + $distributor = DistributorManager::getInstance()->getDistributorByName($name); + $skipped++; + } catch (\Exception $e) { + $distributor = new Distributor(); + $distributor->setName($name); + + $this->entityManager->persist($distributor); + $count++; + } + } + + $this->entityManager->flush(); + $this->logMessage(sprintf("Migrated %d distributors, skipped %d because they already exist", $count, $skipped)); + } +} diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/FootprintMigration.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/FootprintMigration.php @@ -0,0 +1,43 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\Setup\Migration\PartDB; + +use de\RaumZeitLabor\PartKeepr\PartKeepr, + de\RaumZeitLabor\PartKeepr\Footprint\Footprint, + de\RaumZeitLabor\PartKeepr\Footprint\FootprintManager, + de\RaumZeitLabor\PartKeepr\FootprintCategory\FootprintCategoryManager, + de\RaumZeitLabor\PartKeepr\Setup\FootprintSetup; + +class FootprintMigration extends FootprintSetup { + /** + * Migrates the existing footprints + */ + public function run () { + $count = 0; + $skipped = 0; + + // Get or create node for the imported footprints + $footprintCategory = FootprintSetup::addFootprintPath(explode("/", "Imported Footprints"), FootprintCategoryManager::getInstance()->getRootNode()); + + $r = mysql_query("SELECT * FROM footprints"); + + while ($sFootprint = mysql_fetch_assoc($r)) { + $name = PartDBMigration::convertText($sFootprint["name"]); + + try { + FootprintManager::getInstance()->getFootprintByName($name); + $skipped++; + } catch (\Exception $e) { + $footprint = new Footprint(); + $footprint->setName($name); + + $footprint->setCategory($footprintCategory->getNode()); + + $this->entityManager->persist($footprint); + $count++; + } + } + + $this->entityManager->flush(); + $this->logMessage(sprintf("Migrated %d footprints, skipped %d because they already exist", $count, $skipped)); + } +} diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/PartCategoryMigration.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/PartCategoryMigration.php @@ -0,0 +1,50 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\Setup\Migration\PartDB; + +use de\RaumZeitLabor\PartKeepr\PartKeepr, + de\RaumZeitLabor\PartKeepr\PartCategory\PartCategory, + de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager, + de\RaumZeitLabor\PartKeepr\Setup\AbstractSetup; + +class PartCategoryMigration extends AbstractSetup { + private $categories = array(); + private static $migratedCategories = array(); + /** + * Migrates the old categories + */ + public function run () { + $this->addCategoryRecursive(0, array()); + + foreach ($this->categories as $oldid => $category) { + $newcategory = PartCategoryManager::getInstance()->createCategoryTreeByArray($category); + + self::$migratedCategories[$oldid] = $newcategory; + } + + } + + /** + * Creates the category tree, recursive + * @param array $aCategories the categories + * @param id $currentId The current ID to migrate + * @param Node $parent The parent node + */ + private function addCategoryRecursive ($parentId, $parents) { + $r = mysql_query("SELECT * FROM categories WHERE parentnode = ".intval($parentId)); + + while ($category = mysql_fetch_array($r)) { + $aCopy = $parents; + $aCopy[] = $category["name"]; + + $this->categories[$category["id"]] = $aCopy; + $this->addCategoryRecursive($category["id"], $aCopy); + } + } + + public static function getMigratedCategory ($id) { + if (!array_key_exists($id, self::$migratedCategories)) { + print_r(self::$migratedCategories); + } + return self::$migratedCategories[$id]; + } +} diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/PartDBMigration.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/PartDBMigration.php @@ -0,0 +1,73 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\Setup\Migration\PartDB; + +use de\RaumZeitLabor\PartKeepr\PartKeepr, + de\RaumZeitLabor\PartKeepr\Util\Configuration as PartKeeprConfiguration; + +declare(encoding = 'UTF-8'); + +class PartDBMigration { + /** + * Specifies if setup runs in console mode. + * @var boolean + */ + private $console = false; + + /** + * Runs the setup with all steps + */ + public function run () { + $this->runStep("all"); + } + + /** + * Sets console mode. + * + * In this mode, messages are directly written to the console. + */ + public function setConsole () { + $this->console = true; + } + + /** + * Runs a specific setup step, or all steps. + * @param string $step + * @throws \Exception + */ + public function runStep ($step) { + $entityManager = PartKeepr::getEM(); + + $aSteps = array( + "distributor" => new DistributorMigration($entityManager), + "footprint" => new FootprintMigration($entityManager), + "partcategory" => new PartCategoryMigration($entityManager), + "storagelocation" => new StorageLocationMigration($entityManager), + "part" => new PartMigration($entityManager) + ); + + if ($step == "all") { + foreach ($aSteps as $step) { + $step->setConsole($this->console); + $step->run(); + } + } else { + if (array_key_exists($step, $aSteps)) { + $aSteps[$step]->run(); + } else { + throw new \Exception(sprintf("Migration step %s doesn't exist", $step)); + } + } + } + + /** + * Converts strange escpaes in the database to "regular" text. + * @param string $string The string to convert + * @return string The converted string + */ + public static function convertText ($string) { + $string = stripslashes($string); + $string = html_entity_decode($string, ENT_QUOTES, 'UTF-8'); + $string = str_replace("&#937;", "Ω", $string); + return $string; + } +}+ \ No newline at end of file diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/PartMigration.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/PartMigration.php @@ -0,0 +1,131 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\Setup\Migration\PartDB; + +use de\RaumZeitLabor\PartKeepr\PartKeepr, + de\RaumZeitLabor\PartKeepr\Part\Part, + de\RaumZeitLabor\PartKeepr\Part\PartAttachment, + de\RaumZeitLabor\PartKeepr\Part\PartDistributor, + de\RaumZeitLabor\PartKeepr\Part\PartManager, + de\RaumZeitLabor\PartKeepr\Stock\StockEntry, + de\RaumZeitLabor\PartKeepr\Distributor\DistributorManager, + de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager, + de\RaumZeitLabor\PartKeepr\Footprint\FootprintManager, + de\RaumZeitLabor\PartKeepr\PartUnit\PartUnitManager, + de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocationManager, + de\RaumZeitLabor\PartKeepr\Setup\AbstractSetup; + +class PartMigration extends AbstractSetup { + /** + * Migrates the existing distributors + */ + public function run () { + $count = 0; + $skipped = 0; + $fc = 0; + + $r = mysql_query("SELECT * FROM parts"); + + while ($part = mysql_fetch_assoc($r)) { + $name = PartDBMigration::convertText($part["name"]); + + $oPart = new Part(); + $oPart->setName($name); + $oPart->setComment(PartDBMigration::convertText($part["comment"])); + + $oPart->setFootprint($this->getFootprintForPart($part["id"])); + $oPart->setReviewFlag(true); + $category = PartCategoryMigration::getMigratedCategory($part["id_category"]); + + if ($category === null) { + PartCategoryManager::getInstance()->getRootNode()->getNode(); + } else { + $oPart->setCategory($category); + } + + $oPart->setStorageLocation($this->getStorageLocationForPart($part["id"])); + $oPart->setMinStockLevel($part["mininstock"]); + $oPart->setPartUnit(PartUnitManager::getInstance()->getDefaultPartUnit()); + + $partDistributor = new PartDistributor(); + $partDistributor->setPart($oPart); + $partDistributor->setDistributor($this->getDistributorForPart($part["id"])); + $partDistributor->setOrderNumber($part["supplierpartnr"]); + $oPart->getDistributors()->add($partDistributor); + + + /* Add existing datasheets */ + $datasheetQuery = "SELECT datasheeturl FROM datasheets WHERE part_id = ".$part["id"]; + $r3 = mysql_query($datasheetQuery); + while ($res = mysql_fetch_assoc($r3)) { + try { + $attachment = new PartAttachment(); + $attachment->setPart($oPart); + $attachment->replaceFromURL($res["datasheeturl"]); + $attachment->setDescription(PartKeepr::i18n("Datasheet")); + $oPart->getAttachments()->add($attachment); + } catch (\Exception $e) { + Setup::progress(" - error with url ".$res["datasheeturl"].". Maybe the datasheet was not found."); + Setup::progress(" - The exception error was: ".$e->getMessage()); + } + } + + PartKeepr::getEM()->persist($oPart); + + $oStock = new StockEntry($oPart, $part["instock"]); + + $priceQuery = "SELECT AVG(preis) AS preis FROM preise WHERE part_id = ".$part["id"]; + + $r2 = mysql_query($priceQuery); + $res = mysql_fetch_assoc($r2); + + if ($res) { + if ($res["preis"] !== null) { + $oStock->setPrice(floatval($res["preis"])); + } + } + + PartKeepr::getEM()->persist($oStock); + + $fc++; + + // Flush every STEP_SIZE parts + if ($fc>PartMigration::STEP_SIZE) { + PartKeepr::getEM()->flush(); + $fc=0; + } + } + + $this->entityManager->flush(); + $this->logMessage(sprintf("Migrated %d parts, skipped %d because they already exist", $count, $skipped)); + } + + private function getFootprintForPart ($oldid) { + $r = mysql_query("SELECT footprints.name FROM footprints, parts WHERE footprints.id = parts.id_footprint AND parts.id = ".intval($oldid)); + + $data = mysql_fetch_assoc($r); + + return FootprintManager::getInstance()->getFootprintByName(PartDBMigration::convertText($data["name"])); + } + + private function getStorageLocationForPart ($oldid) { + $r = mysql_query("SELECT storeloc.name FROM storeloc, parts WHERE storeloc.id = parts.id_storeloc AND parts.id = ".intval($oldid)); + + $data = mysql_fetch_assoc($r); + + return StorageLocationManager::getInstance()->getStorageLocationByName(PartDBMigration::convertText($data["name"])); + } + + private function getDistributorForPart ($oldid) { + $r = mysql_query("SELECT suppliers.name FROM suppliers, parts WHERE suppliers.id = parts.id_supplier AND parts.id = ".intval($oldid)); + + $data = mysql_fetch_assoc($r); + + return DistributorManager::getInstance()->getDistributorByName(PartDBMigration::convertText($data["name"])); + } + + /** + * Defines the size of the records which are held in memory unless we flush to the DB. + * @var int + */ + const STEP_SIZE = 100; +} diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/StorageLocationMigration.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/StorageLocationMigration.php @@ -0,0 +1,51 @@ +<?php +namespace de\RaumZeitLabor\PartKeepr\Setup\Migration\PartDB; + +use de\RaumZeitLabor\PartKeepr\PartKeepr, + de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation, + de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocationManager, + de\RaumZeitLabor\PartKeepr\Setup\AbstractSetup; + +class StorageLocationMigration extends AbstractSetup { + /** + * Holds the migrated storage locations + * @var array + */ + private static $migratedStorageLocations = array(); + + /** + * Migrates the storage locations + */ + public function run () { + $count = 0; + $skipped = 0; + + $r = mysql_query("SELECT * FROM storeloc"); + + while ($store = mysql_fetch_assoc($r)) { + $name = PartDBMigration::convertText($store["name"]); + try { + $storageLocation = StorageLocationManager::getInstance()->getStorageLocationByName($name); + $skipped++; + } catch (\Exception $e) { + $oStorageLocation = new StorageLocation(); + $oStorageLocation->setName($name); + + $this->entityManager->persist($oStorageLocation); + $count++; + } + } + + $this->entityManager->flush(); + $this->logMessage(sprintf("Migrated %d storage locations, skipped %d because they already exist", $count, $skipped)); + + } + + /** + * Returns the storage location by id + * @param int $id + */ + public static function getMigratedStorageLocation ($id) { + return StorageLocationSetup::$migratedStorageLocations[$id]; + } +} diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/PartCategorySetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/PartCategorySetup.php @@ -5,13 +5,7 @@ use de\RaumZeitLabor\PartKeepr\PartKeepr, de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager, de\RaumZeitLabor\PartKeepr\PartCategory\PartCategory; -class PartCategorySetup { - /** - * Holds the migrated categories - * @var array - */ - private static $migratedCategories = array(); - +class PartCategorySetup extends AbstractSetup { /** * Sets up the root category node */ @@ -22,59 +16,4 @@ class PartCategorySetup { public function run () { $this->setupRootCategory(); } - - /** - * Migrates the old categories - */ - public static function migrateCategories () { - Setup::progress("Migrating part categories..."); - $r = mysql_query("SELECT * FROM categories"); - - $categories = array(); - - while ($cat = mysql_fetch_assoc($r)) { - $categories[] = $cat; - } - - PartCategorySetup::addCategoryRecursive($categories, 0, PartCategoryManager::getInstance()->getRootNode()); - } - - /** - * Creates the category tree, recursive - * @param array $aCategories the categories - * @param id $currentId The current ID to migrate - * @param Node $parent The parent node - */ - private static function addCategoryRecursive ($aCategories, $currentId, $parent) { - global $newCategories; - - foreach ($aCategories as $aCategory) { - if ($aCategory["parentnode"] == $currentId) { - Setup::progress(" - Adding ".$aCategory["name"], true); - $oCategory = new PartCategory(); - $oCategory->setName(Setup::convertText($aCategory["name"])); - $oCategory->setDescription(""); - $oCategory->setParent($parent->getId()); - - $category = PartCategoryManager::getInstance()->addCategory($oCategory); - - PartCategorySetup::addCategoryRecursive($aCategories, $aCategory["id"], $category); - - PartCategorySetup::$migratedCategories[$aCategory["id"]] = $oCategory; - } - } - - } - - /** - * Returns a migrated category by it's partdb id - * @param int $id the category partdb id - */ - public static function getMigratedCategory ($id) { - if (!array_key_exists($id, PartCategorySetup::$migratedCategories)) { - return null; - } - - return PartCategorySetup::$migratedCategories[$id]; - } } diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/PartSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/PartSetup.php @@ -1,106 +0,0 @@ -<?php -namespace de\RaumZeitLabor\PartKeepr\Setup; - -use de\RaumZeitLabor\PartKeepr\PartKeepr, - de\RaumZeitLabor\PartKeepr\Part\Part, - de\RaumZeitLabor\PartKeepr\Part\PartAttachment, - de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager, - de\RaumZeitLabor\PartKeepr\Setup\SiPrefixSetup, - de\RaumZeitLabor\PartKeepr\Part\PartDistributor, - de\RaumZeitLabor\PartKeepr\Stock\StockEntry, - de\RaumZeitLabor\PartKeepr\Part\PartManufacturer; - -class PartSetup { - /** - * Defines the size of the records which are held in memory unless we flush to the DB. - * @var int - */ - const STEP_SIZE = 100; - - /** - * Migrates the parts from partdb - */ - public static function migrateParts () { - $r = mysql_query("SELECT COUNT(*) AS count FROM parts"); - $cntArray = mysql_fetch_assoc($r); - - $count = $cntArray["count"]; - - $r = mysql_query("SELECT * FROM parts"); - - Setup::progress("Migrating parts..."); - $fc=0; - $cnt=0; - - while ($part = mysql_fetch_assoc($r)) { - $cnt++; - Setup::progress(" - Adding part ".$cnt."/".$count." ".Setup::convertText($part["name"]), true); - $oPart = new Part(); - $oPart->setName(Setup::convertText($part["name"])); - $oPart->setComment(Setup::convertText($part["comment"])); - $oPart->setFootprint(FootprintSetup::getFootprintForOldId($part["id_footprint"])); - $oPart->setReviewFlag(true); - $category = PartCategorySetup::getMigratedCategory($part["id_category"]); - - if ($category === null) { - PartCategoryManager::getInstance()->getRootNode()->getNode(); - } else { - $oPart->setCategory($category); - } - - $oPart->setStorageLocation(StorageLocationSetup::getMigratedStorageLocation($part["id_storeloc"])); - $oPart->setMinStockLevel($part["mininstock"]); - $oPart->setPartUnit(PartUnitSetup::getDefaultPartUnit()); - - $partDistributor = new PartDistributor(); - $partDistributor->setPart($oPart); - $partDistributor->setDistributor(DistributorSetup::getMigratedDistributor($part["id_supplier"])); - $partDistributor->setOrderNumber($part["supplierpartnr"]); - $oPart->getDistributors()->add($partDistributor); - - - /* Add existing datasheets */ - $datasheetQuery = "SELECT datasheeturl FROM datasheets WHERE part_id = ".$part["id"]; - $r3 = mysql_query($datasheetQuery); - while ($res = mysql_fetch_assoc($r3)) { - try { - $attachment = new PartAttachment(); - $attachment->setPart($oPart); - $attachment->replaceFromURL($res["datasheeturl"]); - $attachment->setDescription(PartKeepr::i18n("Datasheet")); - $oPart->getAttachments()->add($attachment); - } catch (\Exception $e) { - Setup::progress(" - error with url ".$res["datasheeturl"].". Maybe the datasheet was not found."); - Setup::progress(" - The exception error was: ".$e->getMessage()); - } - } - - PartKeepr::getEM()->persist($oPart); - - $oStock = new StockEntry($oPart, $part["instock"]); - - $priceQuery = "SELECT AVG(preis) AS preis FROM preise WHERE part_id = ".$part["id"]; - - $r2 = mysql_query($priceQuery); - $res = mysql_fetch_assoc($r2); - - if ($res) { - if ($res["preis"] !== null) { - $oStock->setPrice(floatval($res["preis"])); - } - } - - PartKeepr::getEM()->persist($oStock); - - $fc++; - - // Flush every STEP_SIZE parts - if ($fc>PartSetup::STEP_SIZE) { - PartKeepr::getEM()->flush(); - $fc=0; - } - - - } - } -} diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Setup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Setup.php @@ -8,17 +8,32 @@ declare(encoding = 'UTF-8'); class Setup { /** + * Specifies if setup runs in console mode. + * @var boolean + */ + private $console = false; + + /** * Defines if the setup runs in verbose mode. * @var boolean */ private static $verbose = false; /** - * Runs the setup. Right now, it only tests the prequisites. + * Runs the migration with all steps */ public function run () { $this->runStep("all"); } + + /** + * Sets console mode. + * + * In this mode, messages are directly written to the console. + */ + public function setConsole () { + $this->console = true; + } /** * Runs a specific setup step, or all steps. @@ -42,6 +57,7 @@ class Setup { if ($step == "all") { foreach ($aSteps as $step) { + $step->setConsole($this->console); $step->run(); } } else { @@ -52,7 +68,7 @@ class Setup { } } } - + /** * Tests for APC. Throws an exception if APC is missing or not active. * @throws \Exception @@ -72,18 +88,6 @@ class Setup { } /** - * Converts strange escpaes in the database to "regular" text. - * @param string $string The string to convert - * @return string The converted string - */ - public static function convertText ($string) { - $string = stripslashes($string); - $string = html_entity_decode($string, ENT_QUOTES, 'UTF-8'); - $string = str_replace("&#937;", "Ω", $string); - return $string; - } - - /** * Sets the verbose flag * @param boolean $verbose True if verbose output is wanted, false otherwise */ @@ -139,12 +143,4 @@ class Setup { 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/StorageLocationSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/StorageLocationSetup.php @@ -1,39 +0,0 @@ -<?php -namespace de\RaumZeitLabor\PartKeepr\Setup; - -use de\RaumZeitLabor\PartKeepr\PartKeepr, - de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation; - -class StorageLocationSetup { - /** - * Holds the migrated storage locations - * @var array - */ - private static $migratedStorageLocations = array(); - - /** - * Migrates the storage locations - */ - public static function migrateStorageLocations () { - Setup::progress("Migrating storage locations"); - - $r = mysql_query("SELECT * FROM storeloc"); - - while ($store = mysql_fetch_assoc($r)) { - Setup::progress(" - Migrating storage location ".$store["name"], true); - - $oStorageLocation = new StorageLocation(); - $oStorageLocation->setName(Setup::convertText($store["name"])); - PartKeepr::getEM()->persist($oStorageLocation); - StorageLocationSetup::$migratedStorageLocations[$store["id"]] = $oStorageLocation; - } - } - - /** - * Returns the storage location by id - * @param int $id - */ - public static function getMigratedStorageLocation ($id) { - return StorageLocationSetup::$migratedStorageLocations[$id]; - } -} diff --git a/src/setup/js/SetupWizard.js b/src/setup/js/SetupWizard.js @@ -70,7 +70,6 @@ Ext.define('PartKeeprSetup.SetupWizard', { }] })); - cards.push(Ext.create("PartKeeprSetup.PrequisitesTestCard")); cards.push(Ext.create("PartKeeprSetup.DatabaseParametersCard")); cards.push(Ext.create("PartKeeprSetup.DatabaseConnectivityTestCard")); diff --git a/testing/SetupDatabase.php b/testing/SetupDatabase.php @@ -4,45 +4,25 @@ namespace de\RaumZeitLabor\PartKeepr\Tests; declare(encoding = 'UTF-8'); use de\RaumZeitLabor\PartKeepr\PartKeepr; +use de\RaumZeitLabor\PartKeepr\Setup\Migration\PartDB\PartDBMigration; use de\RaumZeitLabor\PartKeepr\Util\Configuration; +use de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager; use de\RaumZeitLabor\PartKeepr\Setup\Setup; -use de\RaumZeitLabor\PartKeepr\Setup\FootprintSetup; -use de\RaumZeitLabor\PartKeepr\Setup\PartCategorySetup; -use de\RaumZeitLabor\PartKeepr\Setup\StorageLocationSetup; -use de\RaumZeitLabor\PartKeepr\Setup\SiPrefixSetup; -use de\RaumZeitLabor\PartKeepr\Setup\UnitSetup; -use de\RaumZeitLabor\PartKeepr\Setup\ManufacturerSetup; -use de\RaumZeitLabor\PartKeepr\Setup\DistributorSetup; -use de\RaumZeitLabor\PartKeepr\Setup\PartSetup; - declare(encoding = 'UTF-8'); include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php"); -/* Old things */ -use de\RaumZeitLabor\PartKeepr\User\User; -use de\RaumZeitLabor\PartKeepr\Part\PartUnit; -use de\RaumZeitLabor\PartKeepr\PartCategory\PartCategory; -use de\RaumZeitLabor\PartKeepr\Part\Part; -use de\RaumZeitLabor\PartKeepr\Setup\PartUnitSetup; -use de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation; -use de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager; -use de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManagerService; - -use de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerICLogo; -use de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer; -use de\RaumZeitLabor\PartKeepr\Distributor\Distributor; - - - PartKeepr::initialize(); $ask = true; $migration = false; +echo "PartKeepr Setup\n"; +echo "Use SetupDatabase.php --help for help\n\n"; + foreach ($_SERVER["argv"] as $arg) { switch ($arg) { case "--yes": @@ -58,10 +38,11 @@ foreach ($_SERVER["argv"] as $arg) { case "--help": echo "Usage: SetupDatabase.php [OPTION]\n\n"; echo "Actions performed by this script:\n"; - echo "* Drop the tables contained in the database for PartKeepr INCLUDING ALL DATA\n"; echo "* Creates the schema\n"; - echo "* Creates an admin user\n"; - echo "* Imports data from database partdb\n\n"; + echo "* Sets up the basic data\n"; + echo "* Imports data from database partdb (if specified)\n\n"; + echo "Please make sure to enter your database settings in the file config.php.\n"; + echo "Use the file config.php.template as template for your configuration.\n\n"; echo "Arguments:\n"; echo " --yes Assumes 'YES' for the security prompt. USE WITH CAUTION!\n"; echo " --migrate Also migrates the data from the old PartDB database\n"; @@ -74,7 +55,6 @@ foreach ($_SERVER["argv"] as $arg) { } if ($ask) { - echo "\n\n"; echo "If you are sure you want to do this, type YES and hit return.\n"; $fp = fopen('php://stdin', 'r'); @@ -89,64 +69,33 @@ if ($ask) { echo "Performing actions...\n"; -$setup = new Setup(); +$setup = new Setup(); +$setup->setConsole(); $setup->run(); -/*@mkdir("../data/images"); -@mkdir("../data/files"); -chmod("../data/images", 0777); -chmod("../data/files", 0777);*/ - -/* Create footprints */ - -$newFootprints = array(); -$newCategories = array(); if ($migration) { - mysql_connect("localhost", "partdb", "partdb"); + if (Configuration::getOption("partkeepr.migration.partdb.hostname", false) === false || + Configuration::getOption("partkeepr.migration.partdb.username", false) === false || + Configuration::getOption("partkeepr.migration.partdb.password", false) === false || + Configuration::getOption("partkeepr.migration.partdb.dbname", false) === false) { + + echo "Error migrating from partdb: One or more configuration settings are missing.\n"; + echo "Please make sure that you define the partkeepr.migration.partdb.* keys, as shown in config.php.template\n\n"; + echo "After adjusting the keys, you can safely re-run the setup, even if you already have worked with PartKeepr.\n"; + exit; + } + mysql_connect(Configuration::getOption("partkeepr.migration.partdb.hostname"), Configuration::getOption("partkeepr.migration.partdb.username"), Configuration::getOption("partkeepr.migration.partdb.password")); mysql_query("SET CHARACTER SET UTF8"); mysql_query("SET NAMES UTF8"); - mysql_select_db("partdb"); -} - - -/*if ($migration) { - FootprintSetup::migrateFootprints(); - PartKeepr::getEM()->flush(); -}*/ - -/*if ($migration) { - PartCategorySetup::migrateCategories(); -}*/ - -/* -if ($migration) { - StorageLocationSetup::migrateStorageLocations(); - PartKeepr::getEM()->flush(); -}*/ - - - -/* Add units */ -//UnitSetup::setupUnits(); -//PartKeepr::getEM()->flush(); - -/* Add Manufacturers */ -/*ManufacturerSetup::setupManufacturers(); -PartKeepr::getEM()->flush();*/ - -if ($migration) { - DistributorSetup::migrateDistributors(); - PartKeepr::getEM()->flush(); -} - -if ($migration) { - PartSetup::migrateParts(); - PartKeepr::getEM()->flush(); + mysql_select_db(Configuration::getOption("partkeepr.migration.partdb.dbname")); + + $migration = new PartDBMigration(); + $migration->setConsole(); + $migration->run(); } echo "All done.\n\n"; -echo "You need to execute `php doctrine.php migrations:migrate` in the PartKeepr root directory to apply migrations now.\n\n"; echo "Use the user 'admin' with password 'admin' to login. Access the frontend using the `frontend` directory.\n"; apc_clear_cache();