commit 605531f57ea5e6a6f38a27ec86637be27fd835a8
parent 017f7f1f1b38a3e9ac7461d1feac85b9c4647161
Author: felicitus <felicitus@felicitus.org>
Date: Sun, 24 Jun 2012 02:40:17 +0200
Merge branch 'master' of github.com:partkeepr/PartKeepr
Diffstat:
339 files changed, 14361 insertions(+), 13993 deletions(-)
diff --git a/build.properties b/build.properties
@@ -1,3 +1,4 @@
extjs.path=3rdparty/extjs
packagepath=/tmp/partkeepr-pkg
-source.php=src/backend/de/RaumZeitLabor/PartKeepr-
\ No newline at end of file
+source.php=src/backend/PartKeepr
+build.fast=1+
\ No newline at end of file
diff --git a/build.xml b/build.xml
@@ -14,6 +14,8 @@
<target name="clean">
<delete dir="reports" />
<delete dir="frontend" />
+ <delete dir="setup" />
+ <delete file="partkeepr.jsb3" />
</target>
<!-- Re-generates the proxies needed by Doctrine2 -->
@@ -90,12 +92,12 @@
<else>
<copy overwrite="true" todir="setup/js/wizard">
<fileset dir="3rdparty/ext-wizard/Ext.ux.Wizard">
- <include name="**"/>
+ <include name="**" />
</fileset>
</copy>
</else>
</if>
-
+
<echo>Copying src/setup</echo>
<if>
<isset property="build.fast" />
@@ -150,7 +152,7 @@
</if>
<echo>Copying Ext Statusbar</echo>
- <mkdir dir="frontend/js/Ext.ux/statusbar"/>
+ <mkdir dir="frontend/js/Ext.ux/statusbar" />
<if>
<isset property="build.fast" />
<then>
@@ -224,7 +226,7 @@
<phingcall target="build-setup" />
</target>
- <!-- Fast build uses rsync instead of standard file copy -->
+ <!-- Fast build uses rsync instead of standard file copy -->
<target name="build-fast">
<condition property="build.fast">
<or>
@@ -236,7 +238,7 @@
<fail unless="build.fast" message="Fast build only supported on Mac and Unix-like systems (rsync required)" />
<phingcall target="build" />
- </target>
+ </target>
<!--
Creates a new PartKeepr release.
@@ -327,7 +329,7 @@
<exec executable="sed">
<arg value="-i" />
<arg value="s/{V_GIT}/${partkeepr.version}/g" />
- <arg value="${packagepath}/src/backend/de/RaumZeitLabor/PartKeepr/PartKeeprVersion.php" />
+ <arg value="${packagepath}/src/backend/PartKeepr/PartKeeprVersion.php" />
</exec>
</target>
@@ -338,7 +340,7 @@
<format property="build.time" pattern="partkeepr-nightly-%Y%m%d" />
</tstamp>
- <property name="partkeepr.version" value="{build.time}-nightly" />
+ <property name="partkeepr.version" value="${build.time}" />
<phingcall target="set-version" />
<zip destfile="${build.time}.zip" basedir="${packagepath}" prefix="partkeepr-nightly/" />
diff --git a/cli-config.php b/cli-config.php
@@ -1,5 +1,5 @@
<?php
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
+use PartKeepr\PartKeepr;
$helpers = array(
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper(PartKeepr::getEM()->getConnection()),
diff --git a/config-test.php b/config-test.php
@@ -1,7 +1,7 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr;
+namespace PartKeepr;
-use de\RaumZeitLabor\PartKeepr\Util\Configuration;
+use PartKeepr\Util\Configuration;
Configuration::setOption("partkeepr.database.dbname", "partkeepr-test");
Configuration::setOption("partkeepr.database.driver", "pdo_sqlite");
diff --git a/config.php.template b/config.php.template
@@ -1,7 +1,7 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr;
+namespace PartKeepr;
-use de\RaumZeitLabor\PartKeepr\Util\Configuration;
+use PartKeepr\Util\Configuration;
/**
* Specifies the username for the database
diff --git a/cronjobs/CheckForUpdates.php b/cronjobs/CheckForUpdates.php
@@ -6,12 +6,12 @@
* @author felicitus
*
*/
-namespace de\RaumZeitLabor\PartKeepr\Cronjobs;
+namespace PartKeepr\Cronjobs;
-include(__DIR__."/../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include(__DIR__."/../src/backend/PartKeepr/PartKeepr.php");
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\CronLogger\CronLoggerManager;
+use PartKeepr\PartKeepr,
+ PartKeepr\CronLogger\CronLoggerManager;
PartKeepr::initialize();
diff --git a/cronjobs/CreateRSSFeed.php b/cronjobs/CreateRSSFeed.php
@@ -1,14 +1,14 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Cronjobs;
+namespace PartKeepr\Cronjobs;
-include(__DIR__."/../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include(__DIR__."/../src/backend/PartKeepr/PartKeepr.php");
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
-use de\RaumZeitLabor\PartKeepr\Util\Configuration;
+use PartKeepr\PartKeepr,
+ PartKeepr\Util\Configuration;
PartKeepr::initialize();
-$dql = PartKeepr::getEM()->createQuery("SELECT p FROM de\RaumZeitLabor\PartKeepr\Part\Part p ORDER BY p.createDate DESC");
+$dql = PartKeepr::getEM()->createQuery("SELECT p FROM PartKeepr\Part\Part p ORDER BY p.createDate DESC");
$dql->setMaxResults(40);
$parts = $dql->getResult();
diff --git a/cronjobs/CreateStatisticSnapshot.php b/cronjobs/CreateStatisticSnapshot.php
@@ -1,11 +1,11 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Cronjobs;
+namespace PartKeepr\Cronjobs;
-include(__DIR__."/../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include(__DIR__."/../src/backend/PartKeepr/PartKeepr.php");
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Statistic\StatisticSnapshotManager,
- de\RaumZeitLabor\PartKeepr\CronLogger\CronLoggerManager;
+use PartKeepr\PartKeepr,
+ PartKeepr\Statistic\StatisticSnapshotManager,
+ PartKeepr\CronLogger\CronLoggerManager;
PartKeepr::initialize();
StatisticSnapshotManager::getInstance()->createSnapshot();
diff --git a/cronjobs/UpdatePartCacheData.php b/cronjobs/UpdatePartCacheData.php
@@ -1,15 +1,15 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Cronjobs;
+namespace PartKeepr\Cronjobs;
-include(__DIR__."/../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include(__DIR__."/../src/backend/PartKeepr/PartKeepr.php");
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Statistic\StatisticSnapshotManager,
- de\RaumZeitLabor\PartKeepr\CronLogger\CronLoggerManager;
+use PartKeepr\PartKeepr,
+ PartKeepr\Statistic\StatisticSnapshotManager,
+ PartKeepr\CronLogger\CronLoggerManager;
PartKeepr::initialize();
-$query = PartKeepr::getEM()->createQuery("SELECT p FROM de\RaumZeitLabor\PartKeepr\Part\Part p");
+$query = PartKeepr::getEM()->createQuery("SELECT p FROM PartKeepr\Part\Part p");
$result = $query->getResult();
$fc = 0;
diff --git a/cronjobs/UpdateTipsOfTheDay.php b/cronjobs/UpdateTipsOfTheDay.php
@@ -8,13 +8,13 @@
* @author felicitus
*
*/
-namespace de\RaumZeitLabor\PartKeepr\Cronjobs;
+namespace PartKeepr\Cronjobs;
-include(__DIR__."/../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include(__DIR__."/../src/backend/PartKeepr/PartKeepr.php");
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\TipOfTheDay\TipOfTheDay,
- de\RaumZeitLabor\PartKeepr\CronLogger\CronLoggerManager;
+use PartKeepr\PartKeepr,
+ PartKeepr\TipOfTheDay\TipOfTheDay,
+ PartKeepr\CronLogger\CronLoggerManager;
PartKeepr::initialize();
diff --git a/doctrine.php b/doctrine.php
@@ -1,9 +1,9 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Foo;
+namespace PartKeepr\Foo;
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
+use PartKeepr\PartKeepr;
-include("src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("src/backend/PartKeepr/PartKeepr.php");
PartKeepr::initialize("");
// Variable $helperSet is defined inside cli-config.php
diff --git a/documentation/internals/NEW-RELEASE b/documentation/internals/NEW-RELEASE
@@ -30,3 +30,5 @@ The following steps describe how a new PartKeepr release is being built:
* Write a blog entry
* Push out notifications on twitter
+
+* Change irc topic to reflect the current version+
\ No newline at end of file
diff --git a/migrations.yml b/migrations.yml
@@ -2,4 +2,4 @@
name: PartKeepr
migrations_namespace: DoctrineMigrations
table_name: SchemaVersions
-migrations_directory: src/backend/de/RaumZeitLabor/PartKeepr/Versions-
\ No newline at end of file
+migrations_directory: src/backend/PartKeepr/Versions+
\ No newline at end of file
diff --git a/scripts/UpdateCategoryPathCache.php b/scripts/UpdateCategoryPathCache.php
@@ -4,14 +4,14 @@
*
* This script needs to be called after changing the partkeepr.category.path_separator.
*/
-namespace de\RaumZeitLabor\PartKeepr\Scripts;
+namespace PartKeepr\Scripts;
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager,
- de\RaumZeitLabor\PartKeepr\Util\Configuration,
- de\RaumZeitLabor\PartKeepr\FootprintCategory\FootprintCategoryManager;
+use PartKeepr\PartKeepr,
+ PartKeepr\PartCategory\PartCategoryManager,
+ PartKeepr\Util\Configuration,
+ PartKeepr\FootprintCategory\FootprintCategoryManager;
-include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("../src/backend/PartKeepr/PartKeepr.php");
PartKeepr::initialize();
diff --git a/src/backend/PartKeepr/Auth/AuthService.php b/src/backend/PartKeepr/Auth/AuthService.php
@@ -0,0 +1,52 @@
+<?php
+namespace PartKeepr\Auth;
+
+use PartKeepr\Service\AnonService,
+ PartKeepr\User\User,
+ PartKeepr\User\UserManager,
+ PartKeepr\User\Exceptions\InvalidLoginDataException,
+ PartKeepr\Session\SessionManager;
+
+class AuthService extends AnonService {
+ /**
+ * Logs in the given user. If the login was successful,
+ * a session is automatically started.
+ *
+ * @throws InvalidLoginDataException
+ */
+ public function login () {
+ $this->requireParameter("username");
+ $this->requireParameter("password");
+
+ /* Build a temporary user */
+ $user = new User;
+ $user->setRawUsername($this->getParameter("username"));
+ $user->setHashedPassword($this->getParameter("password"));
+
+ $authenticatedUser = UserManager::getInstance()->authenticate($user);
+
+ if ($authenticatedUser !== false) {
+ /* Start Session */
+ $session = SessionManager::getInstance()->startSession($authenticatedUser);
+
+ $aPreferences = array();
+
+ foreach ($session->getUser()->getPreferences() as $result) {
+ $aPreferences[] = $result->serialize();
+ }
+
+ return array(
+ "sessionid" => $session->getSessionID(),
+ "username" => $this->getParameter("username"),
+ "admin" => $session->getUser()->isAdmin(),
+ "userPreferences" => array(
+ "response" => array(
+ "data" => $aPreferences
+ )));
+ } else {
+ throw new InvalidLoginDataException();
+ }
+
+
+ }
+}
diff --git a/src/backend/PartKeepr/Category/AbstractCategory.php b/src/backend/PartKeepr/Category/AbstractCategory.php
@@ -0,0 +1,202 @@
+<?php
+namespace PartKeepr\Category;
+
+use PartKeepr\Util\BaseEntity;
+use PartKeepr\Util\Serializable;
+use DoctrineExtensions\NestedSet\Node;
+
+/**
+ * @MappedSuperclass
+ * @Table(indexes={@index(columns={"lft"}),@index(columns={"rgt"})})
+ *
+ * Represents an abstract category. This class isn't directly usable; you need to inherit it to take advantage of
+ * the AbstractCategoryManager.
+ *
+ * If you are interested on how NestedSets work, please read http://en.wikipedia.org/wiki/Nested_set_model
+ */
+class AbstractCategory extends BaseEntity implements Node, Serializable {
+ /**
+ * The "left" property of the nested set
+ * @Column(type="integer")
+ * @var integer
+ */
+ private $lft;
+
+ /**
+ * The "right" property of the nested set
+ * @Column(type="integer")
+ * @var integer
+ */
+ private $rgt;
+
+ /**
+ * The name of the category
+ * @Column(length=128)
+ * @var string
+ */
+ private $name;
+
+ /**
+ * The description of the category
+ * @Column(type="text",nullable=true)
+ * @var string
+ */
+ private $description;
+
+ /**
+ * Holds the parent node ID. Note that this
+ * is not a persistant value, but rather calculated
+ * or set on the fly.
+ * @var int
+ */
+ private $parent;
+
+ /**
+ * Holds the category path.
+ *
+ * @Column(type="text",nullable=true)
+ *
+ * @var string
+ */
+ private $categoryPath;
+
+ /**
+ * Sets the name of this category
+ * @param string $name The name to set
+ */
+ public function setName ($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the name of this category
+ * @return string The category name
+ */
+ public function getName () {
+ return $this->name;
+ }
+
+ /**
+ * Sets the parent for this category.
+ *
+ * @param int $id The parent node
+ */
+ public function setParent ($id) {
+ $this->parent = $id;
+ }
+
+ /**
+ * Returns the parent node for this node.
+ * @return int The parent node
+ */
+ public function getParent () {
+ return $this->parent;
+ }
+
+ /**
+ * Sets the description for this category
+ * @param string $description The description of this category
+ */
+ public function setDescription ($description) {
+ $this->description = $description;
+ }
+
+ /**
+ * Returns the description of this category
+ * @return string The description
+ */
+ public function getDescription () {
+ return $this->description;
+ }
+
+ /**
+ * Returns the "left" value of the nested set.
+ *
+ * @return int The left value
+ *
+ * (non-PHPdoc)
+ * @see DoctrineExtensions\NestedSet.Node::getLeftValue()
+ */
+ public function getLeftValue() {
+ return $this->lft;
+ }
+
+ /**
+ * Sets the "left" value.
+ *
+ * @param $lft integer The left value
+ * (non-PHPdoc)
+ * @see DoctrineExtensions\NestedSet.Node::setLeftValue()
+ */
+ public function setLeftValue($lft) {
+ $this->lft = $lft;
+ }
+
+ /**
+ * Returns the "right" value of the nested set.
+ *
+ * @return int The right value
+ *
+ * (non-PHPdoc)
+ * @see DoctrineExtensions\NestedSet.Node::getRightValue()
+ */
+ public function getRightValue() {
+ return $this->rgt;
+ }
+
+ /**
+ * Sets the "right" value of the nested set
+ *
+ * @param $rgt int The right value
+ *
+ * (non-PHPdoc)
+ * @see DoctrineExtensions\NestedSet.Node::setRightValue()
+ */
+ public function setRightValue($rgt) {
+ $this->rgt = $rgt;
+ }
+
+ /**
+ * Serializes the entity.
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "name" => $this->getName(),
+ "description" => $this->getDescription()
+ );
+ }
+
+ /**
+ * Returns a string representation of the current node.
+ *
+ * @return string The node name
+ *
+ * (non-PHPdoc)
+ * @see DoctrineExtensions\NestedSet.Node::__toString()
+ */
+ public function __toString () {
+ return $this->getName();
+ }
+
+ /**
+ * Retrieves the category path
+ *
+ * @return string The category path
+ */
+ public function getCategoryPath () {
+ return $this->categoryPath;
+ }
+
+ /**
+ * Sets the category path.
+ *
+ * THIS IS ONLY TO BE CALLED FROM THE CATEGORYMANAGER! DON'T MESS WITH IT!
+ *
+ * @param string $categoryPath
+ */
+ public function setCategoryPath ($categoryPath) {
+ $this->categoryPath = $categoryPath;
+ }
+
+}
diff --git a/src/backend/PartKeepr/Category/AbstractCategoryManager.php b/src/backend/PartKeepr/Category/AbstractCategoryManager.php
@@ -0,0 +1,222 @@
+<?php
+namespace PartKeepr\Category;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\Category\Category,
+ PartKeepr\Util\SerializableException,
+ PartKeepr\Category\Exceptions\CategoryNotFoundException,
+ PartKeepr\PartKeepr,
+ PartKeepr\Util\Configuration,
+ DoctrineExtensions\NestedSet\Manager,
+ DoctrineExtensions\NestedSet\Config,
+ DoctrineExtensions\NestedSet\NodeWrapper;
+
+abstract class AbstractCategoryManager extends Singleton {
+ /**
+ * Holds the node manager
+ * @var object The node manager
+ */
+ private $nodeManager;
+
+ /**
+ * Holds the FQCN of the target entity
+ * @var PartKeepr\Category\AbstractCategory
+ */
+ protected $categoryClass = "PartKeepr\Category\AbstractCategory";
+
+ /**
+ * Returns the node manager. Creates it if it doesn't exist.
+ * @todo Can this method be made private?
+ * @return Manager The node manager
+ */
+ public function getNodeManager () {
+ if (!$this->nodeManager) {
+ $config = new Config(PartKeepr::getEM(), $this->categoryClass);
+
+ $this->nodeManager = new Manager($config);
+ }
+
+ return $this->nodeManager;
+ }
+
+ /**
+ * Returns the child node id's for a given node id.
+ * @param integer $id The ID for which to retrieve the child nodes
+ * @return array An array of the children id's
+ * @todo Refactor this method name to indicate that it operates on IDs only.
+ */
+ public function getChildNodes ($id) {
+ $category = $this->getCategory($id);
+
+ $aData = array();
+
+ foreach ($category->getDescendants() as $cat) {
+ $aData[] = $cat->getNode()->getId();
+ }
+ return $aData;
+ }
+
+ /**
+ * Returns all categories.
+ * @return The category tree
+ */
+ public function getAllCategories () {
+ return $this->getNodeManager()->fetchTree(1);
+ }
+
+ /**
+ * Ensures that the root node exists. If not, this method creates it.
+ */
+ public function ensureRootExists () {
+ /* Check if the root node exists */
+ $rootNode = $this->getNodeManager()->fetchTree(1);
+
+ if ($rootNode === null) {
+ $this->createRootNode();
+ }
+ }
+
+ /**
+ * Returns the root node for the category tree.
+ * @return The category root node
+ */
+ public function getRootNode () {
+ return $this->getNodeManager()->fetchTree(1);
+ }
+
+ /**
+ * Create the root node for the category tree.
+ */
+ public function createRootNode () {
+ $rootNode = new $this->categoryClass();
+ $rootNode->setName("Root Category");
+ $rootNode->setDescription("");
+
+ $this->getNodeManager()->createRoot($rootNode);
+ }
+
+ /**
+ * Adds a given category.
+ * @param Category $category The category to add to the tree
+ * @return Category the added category
+ */
+ public function addCategory (AbstractCategory $category) {
+ $parent = $category->getParent();
+
+ if ($parent == 0) {
+ $parent = $this->getRootNode();
+ } else {
+ $parent = PartKeepr::getEM()->find($this->categoryClass, $parent);
+ $parent = new NodeWrapper($parent, $this->getNodeManager());
+ }
+
+ $node = $parent->addChild($category);
+
+ // Force category path update
+ $this->updateCategoryPaths($node);
+
+ // Flush the category path changes
+ PartKeepr::getEM()->flush();
+
+ return $node;
+ }
+
+ /**
+ * Deletes the given category ID.
+ * @param $id int The category id to delete
+ * @throws CategoryNotFoundException If the category wasn't found
+ */
+ public function deleteCategory ($id) {
+ $this->getCategory($id)->delete();
+ }
+
+ /**
+ * Returns the category with the given ID.
+ * @param int $id The category id
+ * @throws CategoryNotFoundException If the category wasn't found
+ */
+ public function getCategory ($id) {
+ $category = $this->loadCategoryById($id);
+
+ return new NodeWrapper($category, $this->getNodeManager());
+ }
+
+ /**
+ * Returns the overall category count currently existing.
+ * @return int The amount of categories in the database
+ */
+ public function getCategoryCount () {
+ $dql = "SELECT COUNT(c.id) FROM ".$this->categoryClass." c";
+
+ return PartKeepr::getEM()->createQuery($dql)->getSingleScalarResult();
+ }
+
+ /**
+ * Updates the category paths for a given node and all children.
+ *
+ * This method is usually called whenever a category is moved.
+ *
+ * @param NodeWrapper $startNode The node to start updating at
+ */
+ public function updateCategoryPaths (NodeWrapper $startNode) {
+ $pathSeparator = Configuration::getOption("partkeepr.category.path_separator", " ➤ ");
+
+ $startNode->getNode()->setCategoryPath($startNode->getPath($pathSeparator, true));
+
+ foreach ($startNode->getChildren() as $child) {
+ $this->updateCategoryPaths($child);
+ }
+ }
+
+ /**
+ * 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;
+
+ return $class::loadById($id);
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Category/AbstractCategoryService.php b/src/backend/PartKeepr/Category/AbstractCategoryService.php
@@ -0,0 +1,145 @@
+<?php
+namespace PartKeepr\Category;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\Service\Service,
+ PartKeepr\Category\CategoryManager,
+ DoctrineExtensions\NestedSet\NodeWrapper;
+
+
+abstract class AbstractCategoryService extends Service {
+ protected $categoryManagerClass = "PartKeepr\Category\AbstractCategoryManager";
+ protected $categoryClass = "PartKeepr\Category\AbstractCategory";
+
+ /**
+ * Returns all categories found in the system.
+ * @return array A serialized tree
+ */
+ public function getCategories () {
+ $categories = $this->getCategoryManager()->getAllCategories(
+ $this->getParameter("parent", 0));
+
+ return $this->serializeTree($categories);
+ }
+
+ /**
+ * Moves the given category from one to another category.
+ */
+ public function moveCategory () {
+ $this->requireParameter("category");
+ $this->requireParameter("target");
+
+ $category = $this->getCategoryManager()->getCategory($this->getParameter("category"));
+
+ if (intval($this->getParameter("target", 0)) !== 0) {
+
+ $parent = $this->getCategoryManager()->getCategory($this->getParameter("target"));
+
+ $category->moveAsLastChildOf($parent);
+ $this->getCategoryManager()->updateCategoryPaths($category);
+
+ }
+ }
+
+ /**
+ * Deletes the given category.
+ */
+ public function deleteCategory () {
+ $this->requireParameter("id");
+
+ $this->getCategoryManager()->deleteCategory($this->getParameter("id"));
+
+ return array("id" => $this->getParameter("id"));
+ }
+
+ /**
+ * Updates the given category.
+ */
+ public function update () {
+ $this->requireParameter("id");
+ $this->requireParameter("name");
+
+ $category = $this->getCategoryManager()->getCategory($this->getParameter("id"));
+
+ $category->getNode()->setName($this->getParameter("name"));
+ $category->getNode()->setDescription($this->getParameter("description", ""));
+
+ PartKeepr::getEM()->persist($category->getNode());
+
+ $this->getCategoryManager()->updateCategoryPaths($category);
+
+ return array("data" => $this->serializeCategory($category));
+ }
+
+ public function create () {
+ $this->requireParameter("name");
+ $this->requireParameter("parent");
+
+ $category = new $this->categoryClass;
+ $category->setName($this->getParameter("name"));
+ $category->setDescription($this->getParameter("description", ""));
+ $category->setParent($this->getParameter("parent"));
+
+ $category = $this->getCategoryManager()->addCategory($category);
+
+ $this->getCategoryManager()->updateCategoryPaths($category);
+
+ return array("data" => $this->serializeCategory($category));
+ }
+
+ public function destroy () {
+ return $this->deleteCategory();
+ }
+
+ private function serializeCategory ($category) {
+ $data = $category->getNode()->serialize();
+
+ if ($category->getParent() !== null) {
+ $data["parent"] = $category->getParent()->getNode()->getId();
+ $data["parentName"] = $category->getParent()->getNode()->getName();
+ }
+
+ return $data;
+ }
+
+ /**
+ * Returns all categories
+ */
+ public function getAllCategories () {
+ return $this->serializeTree($this->getCategoryManager()->getAllCategories());
+ }
+
+ /**
+ * Serializes the given NodeWrapper as array including all children.
+ * @param NodeWrapper $node The category nodewrapper to serialize
+ * @throws \Exception
+ */
+ public function serializeTree (NodeWrapper $node = null) {
+ if ($node == null) {
+ throw new \Exception("Node must not be null!");
+ }
+
+ $aData = $node->getNode()->serialize();
+
+ $aData["children"] = array();
+
+ if (count($node->getChildren()) == 0) {
+ $aData["leaf"] = true;
+ } else {
+ $aData["expanded"] = true;
+ }
+
+ foreach ($node->getChildren() as $child) {
+ $aData["children"][] = $this->serializeTree($child);
+
+ }
+
+ return $aData;
+ }
+
+ public function getCategoryManager () {
+ $categoryManager = $this->categoryManagerClass;
+
+ return $categoryManager::getInstance();
+ }
+}
diff --git a/src/backend/PartKeepr/Category/Exceptions/CategoryNotFoundException.php b/src/backend/PartKeepr/Category/Exceptions/CategoryNotFoundException.php
@@ -0,0 +1,15 @@
+<?php
+namespace PartKeepr\Category\Exceptions;
+
+use PartKeepr\Util\SerializableException,
+ PartKeepr\PartKeepr;
+
+/**
+ * Thrown when the requested category was not found.
+ */
+class CategoryNotFoundException extends SerializableException {
+ public function __construct ($id) {
+ parent::__construct(sprintf(PartKeepr::i18n("Category %d not found."), $id));
+ }
+}
+?>+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/CronLogger/CronLogger.php b/src/backend/PartKeepr/CronLogger/CronLogger.php
@@ -0,0 +1,58 @@
+<?php
+namespace PartKeepr\CronLogger;
+
+use PartKeepr\UploadedFile\UploadedFile,
+ PartKeepr\Util\BaseEntity,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Util\Deserializable;
+
+/**
+ * Holds a project attachment
+ * @Entity
+ **/
+class CronLogger extends BaseEntity {
+ /**
+ * @Column(type="datetime")
+ * @var \DateTime
+ */
+ private $lastRunDate;
+
+ /**
+ * @Column(type="string")
+ * @var string
+ */
+ private $cronjob;
+
+ /**
+ * Sets the last run date and time for this entry
+ * @param \DateTime $date The date and time
+ */
+ public function setLastRunDate (\DateTime $date) {
+ $this->lastRunDate = $date;
+ }
+
+ /**
+ * Returns the date and time for this entry
+ *
+ * @return \DateTime the date and time for this entry
+ */
+ public function getLastRunDate () {
+ return $this->lastRunDate;
+ }
+
+ /**
+ * Sets the cronjob for this entry
+ * @param string $cronjob the title for this entry
+ */
+ public function setCronjob ($cronjob) {
+ $this->cronjob = $cronjob;
+ }
+
+ /**
+ * Returns the cronjob for this entry
+ * @return string the title
+ */
+ public function getCronjob () {
+ return $this->cronjob;
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/CronLogger/CronLoggerManager.php b/src/backend/PartKeepr/CronLogger/CronLoggerManager.php
@@ -0,0 +1,86 @@
+<?php
+namespace PartKeepr\CronLogger;
+
+use PartKeepr\Manager\AbstractManager,
+ PartKeepr\PartKeepr;
+
+class CronLoggerManager extends AbstractManager {
+ /**
+ * Returns the FQCN for the target entity to operate on.
+ * @return string The FQCN, e.g. PartKeepr\Part
+ */
+ public function getEntityName () {
+ return 'PartKeepr\CronLogger\CronLogger';
+ }
+
+ /**
+ * Returns all fields which need to appear in the getList ResultSet.
+ * @return array An array of all fields which should be returned
+ */
+ public function getQueryFields () {
+ return array("id", "title", "date");
+ }
+
+ /**
+ * Returns the default sort field
+ *
+ * @return string The default sort field
+ */
+ public function getDefaultSortField () {
+ return "date";
+ }
+
+ /**
+ * Marks a specific cronjob as ran
+ * @param string $cronjob The name of the cronjob
+ */
+ public function markCronRun ($cronjob) {
+ $dql = "SELECT c FROM PartKeepr\CronLogger\CronLogger c WHERE c.cronjob = :cronjob";
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("cronjob", $cronjob);
+
+ try {
+ $result = $query->getSingleResult();
+ } catch (\Exception $e) {
+ $result = new CronLogger();
+ $result->setCronjob($cronjob);
+ PartKeepr::getEM()->persist($result);
+ }
+
+ $result->setLastRunDate(new \DateTime());
+
+ PartKeepr::getEM()->flush();
+ }
+
+ /**
+ * Returns a list of all inactive cronjobs
+ *
+ * @param none
+ * @return array A string of cronjob names which aren't running
+ */
+ public function getInactiveCronjobs () {
+ $dql = "SELECT c.cronjob FROM PartKeepr\CronLogger\CronLogger c WHERE c.cronjob = :cronjob";
+ $dql .= " AND c.lastRunDate > :date";
+
+ $query = PartKeepr::getEM()->createQuery($dql);
+
+ $date = new \DateTime();
+ $date->sub(new \DateInterval('P1D'));
+ $query->setParameter("date", $date);
+
+ $failedCronjobs = array();
+
+ foreach (PartKeepr::getRequiredCronjobs() as $cronjob) {
+ $query->setParameter("cronjob", $cronjob);
+
+ try {
+ $query->getSingleResult();
+ } catch (\Exception $e) {
+ $failedCronjobs[] = $cronjob;
+ }
+
+ }
+
+ return $failedCronjobs;
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Distributor/Distributor.php b/src/backend/PartKeepr/Distributor/Distributor.php
@@ -0,0 +1,231 @@
+<?php
+namespace PartKeepr\Distributor;
+
+use PartKeepr\Util\Deserializable,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Util\BaseEntity,
+ PartKeepr\PartKeepr;
+
+/**
+ * Represents a distributor
+ * @Entity **/
+class Distributor extends BaseEntity implements Serializable, Deserializable {
+ /**
+ * Holds the name of the distributor
+ * @Column(type="string",unique=true)
+ * @var string
+ */
+ private $name;
+
+ /**
+ * Holds the address of the distributor
+ * @Column(type="text",nullable=true)
+ * @var string
+ */
+ private $address;
+
+ /**
+ * Holds the URL of the distributor
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $url;
+
+ /**
+ * Holds the phone number of the distributor
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $phone;
+
+ /**
+ * Holds the fax number of the distributor
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $fax;
+
+ /**
+ * Holds the email of the distributor
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $email;
+
+ /**
+ * Holds a comment for the distributor
+ * @Column(type="text",nullable=true)
+ * @var string
+ */
+ private $comment;
+
+ /**
+ * Sets the name for the distributor
+ *
+ * @param string $name The distributor's name
+ */
+ public function setName ($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the name of the distributor
+ * @return string The distributor's name
+ */
+ public function getName () {
+ return $this->name;
+ }
+
+ /**
+ * Sets the address of this distributor
+ *
+ * @param string $address The address of the distributor
+ */
+ public function setAddress ($address) {
+ $this->address = $address;
+ }
+
+ /**
+ * Returns the address of this distributor
+ * @return string The address of this distributor
+ */
+ public function getAddress () {
+ return $this->address;
+ }
+
+ /**
+ * Sets the phone number for this distributor
+ *
+ * @param string $phone The phone number of this distributor
+ */
+ public function setPhone ($phone) {
+ $this->phone = $phone;
+ }
+
+ /**
+ * Returns the phone number of this distributor
+ * @return string The phone number
+ */
+ public function getPhone () {
+ return $this->phone;
+ }
+
+ /**
+ * Sets the fax number for this distributor
+ *
+ * @param string $fax The fax number
+ */
+ public function setFax ($fax) {
+ $this->fax = $fax;
+ }
+
+ /**
+ * Returns the fax number for this distributor
+ *
+ * @return string $fax The fax number
+ */
+ public function getFax () {
+ return $this->fax;
+ }
+
+ /**
+ * Sets the comment for this distributor
+ *
+ * @param string $comment The comment for this distributor
+ */
+ public function setComment ($comment) {
+ $this->comment = $comment;
+ }
+
+ /**
+ * Returns the comment for this distributor
+ *
+ * @return string The comment
+ */
+ public function getComment () {
+ return $this->comment;
+ }
+
+ /**
+ * Sets the email for this distributor
+ *
+ * @param string $email The email for this distributor
+ */
+ public function setEmail ($email) {
+ $this->email = $email;
+ }
+
+ /**
+ * Returns the email for this distributor
+ * @return string The email
+ */
+ public function getEmail () {
+ return $this->email;
+ }
+
+ /**
+ * Sets the URL for this distributor
+ *
+ * @param string $url The URL for this distributor
+ */
+ public function setURL ($url) {
+ $this->url = $url;
+ }
+
+ /**
+ * Returns the URL for this distributor
+ * @return string The URL
+ */
+ public function getURL () {
+ return $this->url;
+ }
+
+ /**
+ * Returns the distributor in serialized form.
+ * @return array The serialized distributor
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "name" => $this->getName(),
+ "url" => $this->getURL(),
+ "address" => $this->getAddress(),
+ "email" => $this->getEmail(),
+ "comment" => $this->getComment(),
+ "phone" => $this->getPhone(),
+ "fax" => $this->getFax()
+ );
+ }
+
+ /**
+ * Deserializes the distributor
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "name":
+ $this->setName($value);
+ break;
+ case "url":
+ $this->setURL($value);
+ break;
+ case "comment":
+ $this->setComment($value);
+ break;
+ case "fax":
+ $this->setFax($value);
+ break;
+ case "phone":
+ $this->setPhone($value);
+ break;
+ case "email":
+ $this->setEmail($value);
+ break;
+ case "address":
+ $this->setAddress($value);
+ break;
+ }
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Distributor/DistributorManager.php b/src/backend/PartKeepr/Distributor/DistributorManager.php
@@ -0,0 +1,107 @@
+<?php
+namespace PartKeepr\Distributor;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\Distributor\Distributor,
+ PartKeepr\PartKeepr,
+ PartKeepr\Category\CategoryManager,
+ PartKeepr\Distributor\Exceptions\DistributorNotFoundException;
+
+class DistributorManager extends Singleton {
+ /**
+ * Returns a list of distributors.
+ *
+ * @param int $start Start of the list, default 0
+ * @param int $limit Number of users to list, default 10
+ * @param string $sort The field to sort by, default "name"
+ * @param string $dir The direction to sort (ASC or DESC), default ASC
+ * @param string $filter A string to filter the distributor's name by, default empty
+ */
+ public function getDistributors ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
+
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+ $qb->select("st.id, st.name, st.url, st.email, st.comment, st.address")->from("PartKeepr\Distributor\Distributor","st");
+
+ if ($filter != "") {
+ $qb = $qb->where("LOWER(st.name) LIKE :filter");
+ $qb->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ if ($limit > -1) {
+ $qb->setMaxResults($limit);
+ $qb->setFirstResult($start);
+ }
+
+ $qb->orderBy("st.".$sort, $dir);
+
+ $query = $qb->getQuery();
+
+ $result = $query->getResult();
+
+ $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
+ $totalQueryBuilder->select("COUNT(st.id)")->from("PartKeepr\Distributor\Distributor","st");
+
+
+
+ if ($filter != "") {
+ $totalQueryBuilder = $totalQueryBuilder->where("LOWER(st.name) LIKE :filter");
+ $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ $totalQuery = $totalQueryBuilder->getQuery();
+
+ return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
+ }
+
+ /**
+ * Returns a distributor by ID.
+ *
+ * @param int $id The distributor id
+ * @return Distributor The distributor
+ * @throws EntityNotFoundException If no distributor with the ID was found
+ */
+ public function getDistributor ($id) {
+ return Distributor::loadById($id);
+ }
+
+ /**
+ * Creates a new distributor with the given name.
+ * @param string $name The name of the distributor
+ * @return Distributor The new distributor object
+ */
+ public function addDistributor ($name) {
+ $distributor = new Distributor();
+ $distributor->setName($name);
+
+ PartKeepr::getEM()->persist($distributor);
+ PartKeepr::getEM()->flush();
+
+ return $distributor;
+ }
+
+ /**
+ * Deletes a distributor by id
+ *
+ * @param int $id The ID of the distributor to delete
+ */
+ public function deleteDistributor ($id) {
+ $distributor = $this->getDistributor($id);
+
+ 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 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/PartKeepr/Distributor/DistributorService.php b/src/backend/PartKeepr/Distributor/DistributorService.php
@@ -0,0 +1,82 @@
+<?php
+namespace PartKeepr\Distributor;
+use PartKeepr\Service\RestfulService;
+
+use PartKeepr\Service\Service,
+ PartKeepr\Part\PartManager,
+ PartKeepr\Stock\StockEntry,
+ PartKeepr\PartKeepr,
+ PartKeepr\Session\SessionManager;
+
+class DistributorService extends Service implements RestfulService {
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return array("data" => DistributorManager::getInstance()->getDistributor($this->getParameter("id"))->serialize());
+ } else {
+ if ($this->hasParameter("sort")) {
+ $tmp = json_decode($this->getParameter("sort"), true);
+
+ $aSortParams = $tmp[0];
+ } else {
+ $aSortParams = array(
+ "property" => "name",
+ "direction" => "ASC");
+ }
+ return DistributorManager::getInstance()->getDistributors(
+ $this->getParameter("start", $this->getParameter("start", 0)),
+ $this->getParameter("limit", $this->getParameter("limit", 25)),
+ $this->getParameter("sortby", $aSortParams["property"]),
+ $this->getParameter("dir", $aSortParams["direction"]),
+ $this->getParameter("query", ""));
+ }
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::create()
+ */
+ public function create () {
+ $this->requireParameter("name");
+
+ $distributor = new Distributor;
+ $distributor->deserialize($this->getParameters());
+
+ PartKeepr::getEM()->persist($distributor);
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $distributor->serialize());
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::update()
+ */
+ public function update () {
+ $this->requireParameter("id");
+ $this->requireParameter("name");
+
+ $distributor = Distributor::loadById($this->getParameter("id"));
+ $distributor->deserialize($this->getParameters());
+
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $distributor->serialize());
+
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::destroy()
+ */
+ public function destroy () {
+ $this->requireParameter("id");
+
+ DistributorManager::getInstance()->deleteDistributor($this->getParameter("id"));
+
+ return array("data" => null);
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Footprint/Footprint.php b/src/backend/PartKeepr/Footprint/Footprint.php
@@ -0,0 +1,192 @@
+<?php
+namespace PartKeepr\Footprint;
+use PartKeepr\Util\Deserializable;
+
+use PartKeepr\Util\Serializable;
+use PartKeepr\FootprintCategory\FootprintCategory;
+use PartKeepr\Util\BaseEntity;
+
+/** @Entity */
+
+class Footprint extends BaseEntity implements Serializable, Deserializable {
+ /**
+ * Holds the footprint name
+ * @Column(length=64,unique=true)
+ * @var string
+ */
+ private $name;
+
+ /**
+ * Holds the footprint description
+ * @Column(type="text",nullable=true)
+ * @var string
+ */
+ private $description;
+
+ /**
+ * The category of the footprint
+ * @ManyToOne(targetEntity="PartKeepr\FootprintCategory\FootprintCategory")
+ * @var Category
+ */
+ private $category;
+
+ /**
+ * Holds the footprint image
+ * @OneToOne(targetEntity="PartKeepr\Footprint\FootprintImage",mappedBy="footprint",cascade={"persist", "remove"})
+ * @var FootprintImage
+ */
+ private $image;
+
+ /**
+ * Holds the footprint attachments
+ * @OneToMany(targetEntity="PartKeepr\Footprint\FootprintAttachment",mappedBy="footprint",cascade={"persist", "remove"})
+ * @var FootprintAttachment
+ */
+ private $attachments;
+
+ /**
+ * Constructs a new Footprint entity
+ */
+ public function __construct () {
+ $this->attachments = new \Doctrine\Common\Collections\ArrayCollection();
+ }
+
+ /**
+ * Sets the name of this footprint
+ *
+ * @param string $name The footprint name
+ */
+ public function setName ($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the name of this footprint
+ * @return string The name of this footprint
+ */
+ public function getName () {
+ return $this->name;
+ }
+
+ /**
+ * Sets the description of this footprint
+ * @param string $description The description
+ */
+ public function setDescription ($description) {
+ $this->description = $description;
+ }
+
+ /**
+ * Returns the description of this footprint
+ * @return string The description
+ */
+ public function getDescription () {
+ return $this->description;
+ }
+
+ /**
+ * Sets the category for this footprint
+ * @param \PartKeepr\FootprintCategory\FootprintCategory $category The category
+ */
+ public function setCategory (FootprintCategory $category) {
+ $this->category = $category;
+ }
+
+ /**
+ * Returns the category of this footprint
+ * @return FootprintCategory The footprint category
+ */
+ public function getCategory () {
+ return $this->category;
+ }
+
+ /**
+ * Sets the footprint image
+ * @param FootprintImage $image The footprint image
+ */
+ public function setImage (FootprintImage $image) {
+ $this->image = $image;
+ $image->setFootprint($this);
+ }
+
+ /**
+ * Returns the footprint image
+ * @return FootprintImage The footprint image
+ */
+ public function getImage () {
+ return $this->image;
+ }
+
+ /**
+ * Returns the attachments for this footprint
+ * @return ArrayCollection The attachments
+ */
+ public function getAttachments () {
+ return $this->attachments;
+ }
+
+ /**
+ * Serializes the footprint
+ * @return array the serialized footprint
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "name" => $this->getName(),
+ "description" => $this->getDescription(),
+ "image_id" => is_object($this->getImage()) ? $this->getImage()->getId() : null,
+ "category" => is_object($this->getCategory()) ? $this->getCategory()->getId() : null,
+ "attachments" => $this->serializeChildren($this->getAttachments())
+ );
+ }
+
+ /**
+ * Deserializes the footprint
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "name":
+ $this->setName($value);
+ break;
+ case "description":
+ $this->setDescription($value);
+ break;
+ case "image_id":
+ if ($value == "") {
+ echo "/** Breaking because of empty value */";
+ break; }
+
+ try {
+ $image = FootprintImage::loadById($value);
+ $this->setImage($image);
+ } catch (\Exception $e) {
+ if ($this->getImage()) {
+ // Image was not found, maybe a temporary image?
+ $this->getImage()->replaceFromTemporaryFile($value);
+ } else {
+ $image = FootprintImage::createFromTemporaryFile($value);
+ $this->setImage($image);
+ }
+ }
+
+ break;
+ case "category":
+ try {
+ $category = FootprintCategory::loadById($value);
+ $this->setCategory($category);
+ } catch (\Exception $e) {
+ // Category was not found, do not change category.
+ }
+ break;
+ case "attachments":
+ $this->deserializeChildren($value, $this->getAttachments(), "PartKeepr\Footprint\FootprintAttachment");
+ foreach ($this->getAttachments() as $attachment) {
+ $attachment->setFootprint($this);
+ }
+ break;
+ }
+ }
+ }
+}
diff --git a/src/backend/PartKeepr/Footprint/FootprintAttachment.php b/src/backend/PartKeepr/Footprint/FootprintAttachment.php
@@ -0,0 +1,101 @@
+<?php
+namespace PartKeepr\Footprint;
+
+use PartKeepr\Util\Deserializable,
+ PartKeepr\Util\Serializable,
+ PartKeepr\UploadedFile\UploadedFile;
+
+/**
+ * Holds a footprint attachment
+ * @Entity
+ **/
+class FootprintAttachment extends UploadedFile implements Serializable, Deserializable {
+ /**
+ * The description of this attachment
+ * @Column(type="text")
+ * @var string
+ */
+ private $description;
+
+ /**
+ * Creates a new footprint attachment
+ */
+ public function __construct () {
+ parent::__construct();
+ $this->setType("FootprintAttachment");
+ }
+ /**
+ * The footprint object
+ * @ManyToOne(targetEntity="PartKeepr\Footprint\Footprint")
+ * @var Footprint
+ */
+ private $footprint = null;
+
+ /**
+ * Sets the footprint
+ * @param Footprint $footprint The footprint to set
+ */
+ public function setFootprint (Footprint $footprint) {
+ $this->footprint = $footprint;
+ }
+
+ /**
+ * Returns the footprint
+ * @return Footprint the footprint
+ */
+ public function getFootprint () {
+ return $this->footprint;
+ }
+
+ /**
+ * Sets the description for this attachment
+ * @param string $description The attachment description
+ */
+ public function setDescription ($description) {
+ $this->description = $description;
+ }
+
+ /**
+ * Returns the description for this attachment
+ * @return string The description
+ */
+ public function getDescription () {
+ return $this->description;
+ }
+
+ /**
+ *
+ * Serializes this footprint attachment
+ * @return array The serialized footprint attachment
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "footprint_id" => $this->getFootprint()->getId(),
+ "originalFilename" => $this->getOriginalFilename(),
+ "mimetype" => $this->getMimetype(),
+ "extension" => $this->getExtension(),
+ "size" => $this->getSize(),
+ "description" => $this->getDescription());
+ }
+
+ /**
+ * Deserializes the footprint attachment
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ if (array_key_exists("id", $parameters)) {
+ if (substr($parameters["id"], 0, 4) === "TMP:") {
+ $this->replaceFromTemporaryFile($parameters["id"]);
+ }
+ }
+
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "description":
+ $this->setDescription($value);
+ break;
+ }
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Footprint/FootprintImage.php b/src/backend/PartKeepr/Footprint/FootprintImage.php
@@ -0,0 +1,50 @@
+<?php
+namespace PartKeepr\Footprint;
+
+use PartKeepr\Util\Serializable,
+ PartKeepr\Image\Image;
+
+/**
+ * Holds a footprint image
+ * @Entity
+ **/
+class FootprintImage extends Image implements Serializable {
+ /**
+ * The footprint object
+ * @OneToOne(targetEntity="PartKeepr\Footprint\Footprint",inversedBy="image")
+ * @var Footprint
+ */
+ private $footprint = null;
+
+ /**
+ * Creates a new IC logo instance
+ */
+ public function __construct () {
+ parent::__construct(Image::IMAGE_FOOTPRINT);
+ }
+
+ /**
+ * Sets the footprint
+ * @param Footprint $footprint The footprint to set
+ */
+ public function setFootprint (Footprint $footprint) {
+ $this->footprint = $footprint;
+ }
+
+ /**
+ * Returns the footprint
+ * @return Footprint the footprint
+ */
+ public function getFootprint () {
+ return $this->footprint;
+ }
+
+ /**
+ *
+ * Serializes this ic logo
+ * @return array The serialized ic logo
+ */
+ public function serialize () {
+ return array("id" => $this->getId(), "footprint_id" => $this->getFootprint()->getId());
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Footprint/FootprintManager.php b/src/backend/PartKeepr/Footprint/FootprintManager.php
@@ -0,0 +1,158 @@
+<?php
+namespace PartKeepr\Footprint;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\Util\SerializableException,
+ PartKeepr\Footprint\Footprint,
+ PartKeepr\PartKeepr,
+ PartKeepr\Util\Exceptions\EntityNotFoundException;
+
+class FootprintManager extends Singleton {
+ /**
+ * Returns a list of footprints.
+ *
+ * @param int $start Start of the list, default 0
+ * @param int $limit Number of users to list, default 10
+ * @param string $sort The field to sort by, default "name"
+ * @param string $dir The direction to sort (ASC or DESC), default ASC
+ * @param string $filter A string to filter the footprint's name by, default empty
+ */
+ public function getFootprints ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
+
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+ $qb->select("f.id, f.name, f.description, im.id AS image_id, ca.id AS category")->from("PartKeepr\Footprint\Footprint","f")
+ ->leftJoin("f.image", "im")
+ ->leftJoin("f.category", "ca");
+
+ if ($filter != "") {
+ $qb = $qb->where("LOWER(f.name) LIKE :filter");
+ $qb->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ if ($limit > -1) {
+ $qb->setMaxResults($limit);
+ $qb->setFirstResult($start);
+ }
+
+ $qb->orderBy("f.".$sort, $dir);
+
+ $query = $qb->getQuery();
+
+ $result = $query->getResult();
+
+ $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
+ $totalQueryBuilder->select("COUNT(f.id)")->from("PartKeepr\Footprint\Footprint","f")->leftJoin("f.image", "im");
+
+
+
+ if ($filter != "") {
+ $totalQueryBuilder = $totalQueryBuilder->where("LOWER(f.name) LIKE :filter");
+ $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ $totalQuery = $totalQueryBuilder->getQuery();
+
+ return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
+ }
+
+ /**
+ * Creates a new footprint
+ *
+ * @param string $footprint The footprint's name
+ * @throws \PartKeepr\Util\SerializableException
+ * @throws PDOException
+ */
+ public function addFootprint ($name) {
+ $fp = new Footprint();
+ $fp->setName($name);
+
+ // @todo Port the UniqueEntityValidator from Symfony2 to here.
+ try {
+ PartKeepr::getEM()->persist($fp);
+ PartKeepr::getEM()->flush();
+ } catch (\PDOException $e) {
+ if ($e->getCode() == "23000") {
+ $exception = new SerializableException(sprintf(PartKeepr::i18n("Footprint %s already exists!"), $name));
+ $exception->setDetail(sprintf(PartKeepr::i18n("You tried to add the footprint %s, but a footprint with the same name already exists."), $name));
+
+ throw $exception;
+ } else {
+ throw $e;
+ }
+ }
+
+ return $fp;
+ }
+
+ /**
+ * Deletes the footprint with the given id.
+ *
+ * @param int $id The footprint id to delete
+ * @throws \PartKeepr\Util\SerializableException
+ */
+ public function deleteFootprint ($id) {
+ $footprint = Footprint::loadById($id);
+
+ try {
+ PartKeepr::getEM()->remove($footprint);
+ PartKeepr::getEM()->flush();
+ } catch (\PDOException $e) {
+ if ($e->getCode() == "23000") {
+ $exception = new SerializableException(sprintf(PartKeepr::i18n("Footprint %s is in use by some parts!"), $footprint->getName()));
+ $exception->setDetail(sprintf(PartKeepr::i18n("You tried to delete the footprint %s, but there are parts which use this footprint."), $footprint->getName()));
+
+ throw $exception;
+ }
+ }
+ }
+
+ /**
+ * Loads a footprint by id
+ * @param int $id The footprint id
+ */
+ public function getFootprint ($id) {
+ return Footprint::loadById($id);
+ }
+
+ /**
+ * Finds or creates a footprint by name.
+ *
+ * @param mixed $footprint Either the ID or the footprint's name to find
+ */
+ public function getOrCreateFootprint ($footprint) {
+ try {
+ $footprint = Footprint::loadById($footprint);
+ return $footprint;
+ } catch (EntityNotFoundException $e) {}
+
+ $dql = "SELECT f FROM PartKeepr\Footprint\Footprint f WHERE f.name = :name";
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("name", $footprint);
+
+ try {
+ $footprint = $query->getSingleResult();
+ return $footprint;
+ } catch (\Exception $e) {}
+
+ $fp = new Footprint();
+ $fp->setName($footprint);
+
+ PartKeepr::getEM()->persist($fp);
+
+ 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 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/PartKeepr/Footprint/FootprintService.php b/src/backend/PartKeepr/Footprint/FootprintService.php
@@ -0,0 +1,96 @@
+<?php
+namespace PartKeepr\Footprint;
+
+use PartKeepr\TempImage\TempImage,
+ PartKeepr\FootprintCategory\FootprintCategory,
+ PartKeepr\Service\Service,
+ PartKeepr\Service\RestfulService,
+ PartKeepr\PartKeepr,
+ PartKeepr\Footprint\FootprintManager;
+
+class FootprintService extends Service implements RestfulService {
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return array("data" => FootprintManager::getInstance()->getFootprint($this->getParameter("id"))->serialize());
+ } else {
+ if ($this->hasParameter("sort")) {
+ $tmp = json_decode($this->getParameter("sort"), true);
+
+ $aSortParams = $tmp[0];
+ } else {
+ $aSortParams = array(
+ "property" => "name",
+ "direction" => "ASC");
+ }
+ return FootprintManager::getInstance()->getFootprints(
+ $this->getParameter("start", $this->getParameter("start", 0)),
+ $this->getParameter("limit", $this->getParameter("limit", 25)),
+ $this->getParameter("sortby", $aSortParams["property"]),
+ $this->getParameter("dir", $aSortParams["direction"]),
+ $this->getParameter("query", ""));
+ }
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::create()
+ */
+ public function create () {
+ $this->requireParameter("name");
+
+ $footprint = new Footprint();
+ $footprint->deserialize($this->getParameters());
+
+ PartKeepr::getEM()->persist($footprint);
+
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $footprint->serialize());
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::update()
+ */
+ public function update () {
+ $this->requireParameter("id");
+ $this->requireParameter("name");
+ $footprint = Footprint::loadById($this->getParameter("id"));
+
+ $footprint->deserialize($this->getParameters());
+
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $footprint->serialize());
+
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::destroy()
+ */
+ public function destroy () {
+ $this->requireParameter("id");
+
+ FootprintManager::getInstance()->deleteFootprint($this->getParameter("id"));
+
+ return array("data" => null);
+ }
+
+ public function moveFootprint () {
+ $this->requireParameter("targetCategory");
+ $this->requireParameter("id");
+
+ $footprint = Footprint::loadById($this->getParameter("id"));
+ $category = FootprintCategory::loadById($this->getParameter("targetCategory"));
+
+ $footprint->setCategory($category);
+
+ PartKeepr::getEM()->flush();
+ }
+
+}
diff --git a/src/backend/PartKeepr/FootprintAttachment/FootprintAttachmentManager.php b/src/backend/PartKeepr/FootprintAttachment/FootprintAttachmentManager.php
@@ -0,0 +1,68 @@
+<?php
+namespace PartKeepr\FootprintAttachment;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\Footprint\Footprint,
+ PartKeepr\PartKeepr;
+
+class FootprintAttachmentManager extends Singleton {
+ /**
+ * Returns a list of footprint attachments
+ *
+ * @param int $start Start of the list, default 0
+ * @param int $limit Number of users to list, default 10
+ * @param string $sort The field to sort by, default "name"
+ * @param string $dir The direction to sort (ASC or DESC), default ASC
+ * @param string $filter The footprint id
+ */
+ public function getFootprintAttachments ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
+
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+ $qb->select("st")->from("PartKeepr\Footprint\FootprintAttachment","st")
+ ->leftJoin('st.footprint', "fp");
+
+ if ($filter != "") {
+ $footprint = Footprint::loadById($filter);
+ $qb = $qb->where("st.footprint = :footprint");
+ $qb->setParameter("footprint", $footprint);
+ }
+
+ if ($limit > -1) {
+ $qb->setMaxResults($limit);
+ $qb->setFirstResult($start);
+ }
+
+ $qb->orderBy("st.".$sort, $dir);
+
+ $query = $qb->getQuery();
+
+ $result = $query->getResult();
+
+ $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
+ $totalQueryBuilder->select("COUNT(st.id)")->from("PartKeepr\Footprint\FootprintAttachment","st");
+
+
+
+ if ($filter != "") {
+ $totalQueryBuilder = $totalQueryBuilder->where("st.footprint = :footprint");
+ $totalQueryBuilder->setParameter("footprint", $footprint);
+ }
+
+ $totalQuery = $totalQueryBuilder->getQuery();
+
+ $aData = array();
+ foreach ($result as $item) {
+ $aData[] = $item->serialize();
+ }
+ return array("data" => $aData, "totalCount" => $totalQuery->getSingleScalarResult());
+ }
+
+ /**
+ * Returns a footprint attachment by id
+ * @param int $id The footprint attachment id
+ */
+ public function getFootprintAttachment ($id) {
+ return FootprintAttachment::loadById($id);
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/FootprintAttachment/FootprintAttachmentService.php b/src/backend/PartKeepr/FootprintAttachment/FootprintAttachmentService.php
@@ -0,0 +1,102 @@
+<?php
+namespace PartKeepr\FootprintAttachment;
+
+use PartKeepr\Footprint\FootprintAttachment,
+ PartKeepr\UploadedFile\TempUploadedFile,
+ PartKeepr\Service\RestfulService,
+ PartKeepr\Service\Service,
+ PartKeepr\PartKeepr,
+ PartKeepr\Footprint\Footprint,
+ PartKeepr\Session\SessionManager;
+
+class FootprintAttachmentService extends Service implements RestfulService {
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return FootprintAttachmentManager::getInstance()->getFootprintAttachment($this->getParameter("id"))->serialize();
+ } else {
+ if ($this->hasParameter("sort")) {
+ $tmp = json_decode($this->getParameter("sort"), true);
+
+ $aSortParams = $tmp[0];
+ } else {
+ $aSortParams = array(
+ "property" => "id",
+ "direction" => "ASC");
+ }
+
+ $filter = "";
+
+ if ($this->hasParameter("filter")) {
+ $tmp = json_decode($this->getParameter("filter"), true);
+
+ foreach ($tmp as $item) {
+ if (array_key_exists("property", $item)) {
+ if ($item["property"] == "footprint_id") {
+ if (array_key_exists("value", $item)) {
+ $filter = $item["value"];
+ }
+ }
+ }
+ }
+ }
+ return FootprintAttachmentManager::getInstance()->getFootprintAttachments(
+ $this->getParameter("start", $this->getParameter("start", 0)),
+ $this->getParameter("limit", $this->getParameter("limit", 25)),
+ $this->getParameter("sortby", $aSortParams["property"]),
+ $this->getParameter("dir", $aSortParams["direction"]),
+ $filter);
+ }
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::create()
+ */
+ public function create () {
+ $this->requireParameter("tmp_id");
+ $this->requireParameter("footprint_id");
+
+ $tmpImage = TempUploadedFile::loadById($this->getParameter("tmp_id"));
+
+ $file = new FootprintAttachment();
+
+ $footprint = Footprint::loadById($this->getParameter("footprint_id"));
+
+ $file->setFootprint($footprint);
+ $file->replace($tmpImage->getFilename());
+ $file->setOriginalFilename($tmpImage->getOriginalFilename());
+ $file->setDescription($this->getParameter("description"));
+ PartKeepr::getEM()->persist($file);
+ PartKeepr::getEM()->flush();
+
+ return $file->serialize();
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::update()
+ */
+ public function update () {
+
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::destroy()
+ */
+ public function destroy () {
+ $this->requireParameter("id");
+
+ $file = FootprintAttachment::loadById($this->getParameter("id"));
+
+ PartKeepr::getEM()->remove($file);
+ PartKeepr::getEM()->flush();
+
+ return array("data" => null);
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/FootprintCategory/FootprintCategory.php b/src/backend/PartKeepr/FootprintCategory/FootprintCategory.php
@@ -0,0 +1,14 @@
+<?php
+namespace PartKeepr\FootprintCategory;
+
+use PartKeepr\Category\AbstractCategory;
+
+/**
+ * @Entity
+ * @Table(indexes={@index(columns={"lft"}),@index(columns={"rgt"})})
+ * The entity for our footprint categories
+ *
+ */
+class FootprintCategory extends AbstractCategory {
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/FootprintCategory/FootprintCategoryManager.php b/src/backend/PartKeepr/FootprintCategory/FootprintCategoryManager.php
@@ -0,0 +1,42 @@
+<?php
+namespace PartKeepr\FootprintCategory;
+
+use PartKeepr\Category\AbstractCategoryManager;
+use DoctrineExtensions\NestedSet\NodeWrapper;
+use PartKeepr\Util\SerializableException;
+use PartKeepr\PartKeepr;
+
+class FootprintCategoryManager extends AbstractCategoryManager {
+ protected $categoryClass = "PartKeepr\FootprintCategory\FootprintCategory";
+
+ /**
+ * Deletes the given category ID.
+ * @param $id int The category id to delete
+ * @throws CategoryNotFoundException If the category wasn't found
+ */
+ public function deleteCategory ($id) {
+ $category = $this->getCategory($id);
+
+ try {
+
+ if ($category->hasChildren()) {
+ $exception = new SerializableException(sprintf(PartKeepr::i18n("Category '%s' contains other categories."), $category->getNode()->getName()));
+ $exception->setDetail(sprintf(PartKeepr::i18n("You tried to delete the category '%s', but it still contains other categories. Please move the categories or delete them first."), $category->getNode()->getName()));
+
+ throw $exception;
+ }
+
+ parent::deleteCategory($id);
+ } catch (\PDOException $e) {
+ if ($e->getCode() == "23000") {
+ $exception = new SerializableException(sprintf(PartKeepr::i18n("Category '%s' contains footprints."), $category->getNode()->getName()));
+ $exception->setDetail(sprintf(PartKeepr::i18n("You tried to delete the category '%s', but it still contains footprints. Please move the footprints to another category."), $category->getNode()->getName()));
+
+ throw $exception;
+ } else {
+ throw $e;
+ }
+ }
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/FootprintCategory/FootprintCategoryService.php b/src/backend/PartKeepr/FootprintCategory/FootprintCategoryService.php
@@ -0,0 +1,9 @@
+<?php
+namespace PartKeepr\FootprintCategory;
+
+use PartKeepr\Category\AbstractCategoryService;
+
+class FootprintCategoryService extends AbstractCategoryService {
+ protected $categoryManagerClass = "PartKeepr\FootprintCategory\FootprintCategoryManager";
+ protected $categoryClass = "PartKeepr\FootprintCategory\FootprintCategory";
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/FulltextSearch/FulltextSearch.php b/src/backend/PartKeepr/FulltextSearch/FulltextSearch.php
@@ -0,0 +1,94 @@
+<?php
+namespace PartKeepr\FulltextSearch;
+
+use PartKeepr\PartKeepr;
+
+abstract class FulltextSearch {
+
+ /**
+ * Creates a new fulltext search based on the given query.
+ *
+ * The query can contain different query strings, separated by space. The query returns only results which contain
+ * all query strings in any fields.
+ *
+ * If the query is "100 ohm", it would only consider entities which have both "100" and "ohm", no matter which field
+ * the value is in.
+ *
+ * @param string $query The query to search for
+ */
+ public function __construct ($query) {
+ $this->query = explode(" ", $query);
+ }
+
+ /**
+ * Fires the query and returns the results.
+ *
+ * @param none
+ * @return array An array with all IDs which match the query
+ */
+ public function query () {
+ return $this->fallbackSearch();
+ }
+
+ /**
+ * A fallback search in case no fulltext search engine is available. This directly queries the database, which is
+ * slow.
+ */
+ protected function fallbackSearch () {
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+
+ $qb ->select("q.id")
+ ->from($this->getEntityName(), "q")
+ ->where("1=1");
+
+ $dqlChunks = array();
+
+ foreach ($this->query as $id => $queryString) {
+ $partDqlChunks = array();
+ foreach ($this->getFields() as $field) {
+ $partDqlChunks[] = "LOWER(q." . $field.") LIKE :filter".$id;
+ }
+
+ $dqlChunks[] = "(".implode(" OR ", $partDqlChunks).")";
+
+ $qb->setParameter("filter".$id, "%".str_replace("%", "\\%", strtolower($queryString))."%");
+ }
+
+ $qb->andWhere(implode(" AND " ,$dqlChunks));
+
+ $query = $qb->getQuery();
+
+
+
+ $result = $query->getArrayResult();
+
+ if (count($result) > 0) {
+ $results = array();
+
+ foreach ($result as $value) {
+ $results[] = $value["id"];
+ }
+
+ return $results;
+ } else {
+ return array(0);
+ }
+ }
+
+ /**
+ * Returns the FQDN name of the entity. This needs to be overridden in child classes.
+ *
+ * @param none
+ * @return string the FQDN of the entity to query, e.g. PartKeepr\Part\Part
+ */
+ abstract protected function getEntityName ();
+
+ /**
+ * Returns the fields in which the fulltext search should search in.
+ *
+ * @param none
+ * @return array An array of field names, e.g. array("name", "description")
+ */
+ abstract protected function getFields ();
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Image/CachedImage.php b/src/backend/PartKeepr/Image/CachedImage.php
@@ -0,0 +1,99 @@
+<?php
+namespace PartKeepr\Image;
+
+use PartKeepr\PartKeepr;
+
+/**
+ * Represtends a cached image. Cached images are used for scale/resize
+ * operations, so that the resize/scale operation doesn't need to be done
+ * every time a scaled/resized image is requested.
+ *
+ * @Entity
+ */
+class CachedImage {
+ /**
+ * Specifies the ID of the cached image.
+ *
+ * @var integer
+ * @Id
+ * @Column(type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ **/
+ private $id;
+
+ /**
+ * Specifies the ID of the original image
+ *
+ * @var integer
+ * @Column(type="integer")
+ */
+ private $originalId;
+
+ /**
+ * Specifies the type of the original image.
+ *
+ * @var string
+ * @Column(type="string")
+ **/
+ private $originalType;
+
+ /**
+ * The cache filename of the image
+ *
+ * @var string
+ * @Column(type="string")
+ */
+ private $cacheFile;
+
+ /**
+ * Creates a new cache entry for a specific image.
+ *
+ * @param Image $image The image to cache
+ * @param string $cacheFile The file which holds the cached image
+ */
+ public function __construct (Image $image, $cacheFile) {
+ $this->originalId = (int)$image->getId();
+ $this->originalType = $image->getType();
+ $this->cacheFile = $cacheFile;
+ }
+
+ /**
+ * Returns the cache file
+ * @return string The cache file including path
+ */
+ public function getCacheFile () {
+ return $this->cacheFile;
+ }
+
+ /**
+ * Removes all caches for a specific image. This is usually called
+ * when a new version of an image is uploaded.
+ *
+ * Automatically calls "flush" on the entity manager.
+ *
+ * @param Image $image The image to invalidate
+ */
+ public static function invalidate (Image $image) {
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+ $qb->select(array("c"))
+ ->from('PartKeepr\Image\CachedImage', 'c')
+ ->where("c.originalId = :id")
+ ->andWhere("c.originalType = :type")
+ ->setParameter("id", $image->getId())
+ ->setParameter("type", $image->getType());
+
+ $query = $qb->getQuery();
+
+ $bImagesRemoved = false;
+
+ foreach ($query->getResult() as $file) {
+ unlink($file->getCacheFile());
+ PartKeepr::getEM()->remove($file);
+ $bImagesRemoved = true;
+ }
+
+ if ($bImagesRemoved) {
+ PartKeepr::getEM()->flush();
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Image/Exceptions/InvalidImageTypeException.php b/src/backend/PartKeepr/Image/Exceptions/InvalidImageTypeException.php
@@ -0,0 +1,11 @@
+<?php
+namespace PartKeepr\Image\Exceptions;
+
+/**
+ * Thrown if an invalid type was passed
+ */
+class InvalidImageTypeException extends \Exception {
+ public function __construct ($type) {
+ parent::__construct("The image type $type is unknown.");
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Image/Image.php b/src/backend/PartKeepr/Image/Image.php
@@ -0,0 +1,227 @@
+<?php
+namespace PartKeepr\Image;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\UploadedFile\UploadedFile,
+ PartKeepr\Util\Configuration,
+ PartKeepr\TempImage\TempImage,
+ PartKeepr\Image\Exceptions\InvalidImageTypeException;
+
+/**
+ * This is only a storage class; actual image rendering is done by the ImageRenderer.
+ *
+ * @MappedSuperclass
+ */
+abstract class Image extends UploadedFile implements RenderableImage {
+ const IMAGE_ICLOGO = "iclogo";
+ const IMAGE_TEMP = "temp";
+ const IMAGE_PART = "part";
+ const IMAGE_STORAGELOCATION = "storagelocation";
+ const IMAGE_FOOTPRINT = "footprint";
+
+ /**
+ * Holds the image renderer
+ * @var object
+ */
+ private $renderer;
+
+ /**
+ * Constructs a new image object.
+ *
+ * @param string $type The type for the image, one of the IMAGE_ constants.
+ */
+ public function __construct ($type) {
+ parent::__construct();
+ $this->setType($type);
+ }
+
+ /**
+ * Sets the type of the image. Once the type is set,
+ * it may not be changed later.
+ *
+ * @param string $type The type for the image, one of the IMAGE_ constants.
+ * @throws InvalidImageTypeException
+ */
+ protected function setType ($type) {
+ switch ($type) {
+ case Image::IMAGE_ICLOGO:
+ case Image::IMAGE_TEMP:
+ case Image::IMAGE_PART:
+ case Image::IMAGE_FOOTPRINT:
+ case Image::IMAGE_STORAGELOCATION:
+ parent::setType($type);
+ break;
+ default:
+ throw new InvalidImageTypeException($type);
+ }
+ }
+
+ /**
+ * Returns the renderer for image manipulations
+ * @return object
+ */
+ public function getRenderer () {
+ if (!$this->renderer instanceof ImageRenderer) {
+ $this->renderer = new ImageRenderer($this);
+ }
+
+ return $this->renderer;
+ }
+ /**
+ * Replaces the current image with a new image.
+ *
+ * Automatically converts from one format to PNG,
+ * which is the default when dealing with images
+ * on the platform.
+ *
+ * @param string $path The path to the original image
+ */
+ public function replace ($path) {
+ parent::replace($path);
+
+ CachedImage::invalidate($this);
+ }
+
+ /**
+ * Returns the full image filename including path.
+ * This is the image where all scale operations take place on.
+ *
+ * @param none
+ * @return string The full image filename including path.
+ */
+ public function getFilename () {
+ return $this->getFilePath().$this->getPlainFilename().".png";
+ }
+
+ /**
+ * Returns the path to the image. May be overridden by
+ * subclasses.
+ *
+ * @param none
+ * @return string The path to the image
+ */
+ public function getFilePath () {
+ return Configuration::getOption(
+ "partkeepr.images.path",
+ PartKeepr::getRootDirectory() . "/data/images/") . $this->getType() . "/";
+ }
+
+ /**
+ * Ensures that the image cache dir exists.
+ */
+ public function ensureCachedirExists () {
+ if (!is_dir(Configuration::getOption("partkeepr.images.cache"))) {
+ mkdir(Configuration::getOption("partkeepr.images.cache"), 0777, true);
+ }
+ }
+
+ /**
+ * Scales the image to fit within the given size.
+ *
+ * @param int $w The width
+ * @param int $h The height
+ * @param boolean $padding If true, pad the output image to the given size (transparent background).
+ * @return string The path to the scaled file
+ */
+ public function fitWithin ($w, $h, $padding = false) {
+ $this->ensureCachedirExists();
+
+ if ($padding) {
+ $pd = "p";
+ } else {
+ $pd = "";
+ }
+
+ $outputFile = Configuration::getOption("partkeepr.images.cache").md5($this->getFilename().$w."x".$h."fw".$pd).".png";
+
+ if (file_exists($outputFile)) {
+ return $outputFile;
+ }
+
+ $this->getRenderer()->fitWithin($outputFile, $w, $h, $padding);
+
+ $cachedImage = new CachedImage($this, $outputFile);
+ PartKeepr::getEM()->persist($cachedImage);
+
+ return $outputFile;
+ }
+
+ /**
+ * Convinience method for fitWithin. Automatically pads the image.
+ *
+ * @param int $w The width
+ * @param int $h The height
+ * @return string The path to the scaled file
+ */
+ public function fitWithinPadding ($w, $h) {
+ return $this->fitWithin($w, $h);
+ }
+
+ /**
+ * Scales the image to fit exactly within the given size.
+ *
+ * This method ensures that no blank space is in the output image,
+ * and that the output image is exactly the width and height specified.
+ *
+ * @param string $outputFile The output file
+ * @param int $w The width
+ * @param int $h The height
+ * @return string The path to the scaled file
+ */
+ public function fitWithinExact ($w, $h) {
+ $this->ensureCachedirExists();
+
+ $outputFile = Configuration::getOption("partkeepr.images.cache").md5($this->getFilename().$w."x".$h."fwe").".png";
+
+ if (file_exists($outputFile)) {
+ return $outputFile;
+ }
+
+ $this->getRenderer()->fitWithinExact($outputFile, $w, $h);
+
+ $cachedImage = new CachedImage($this, $outputFile);
+ PartKeepr::getEM()->persist($cachedImage);
+
+ return $outputFile;
+ }
+
+ /**
+ * Scales the image to a specific width and height
+ *
+ * @param int $w The width
+ * @param int $h The height
+ * @return string The path to the scaled file
+ */
+ public function scaleTo ($w, $h) {
+ $this->ensureCachedirExists();
+
+ $outputFile = Configuration::getOption("partkeepr.images.cache").md5($this->getFilename().$w."x".$h).".png";
+
+ if (file_exists($outputFile)) {
+ return $outputFile;
+ }
+
+ $this->getRenderer()->scaleTo($outputFile, $w, $h);
+
+ $cachedImage = new CachedImage($this, $outputFile);
+ PartKeepr::getEM()->persist($cachedImage);
+
+ return $outputFile;
+ }
+
+ /**
+ * Replaces the file with a given temporary file.
+ * @param string $id The temporary id (prefixed with TMP:)
+ */
+ public function replaceFromTemporaryFile ($id) {
+ if (substr($id, 0, 4) === "TMP:") {
+ $tmpFileId = str_replace("TMP:", "", $id);
+ $tmpFile = TempImage::loadById($tmpFileId);
+
+ $this->replace($tmpFile->getFilename());
+ $this->setOriginalFilename($tmpFile->getOriginalFilename());
+
+ }
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Image/ImageRenderer.php b/src/backend/PartKeepr/Image/ImageRenderer.php
@@ -0,0 +1,133 @@
+<?php
+namespace PartKeepr\Image;
+
+use PartKeepr\Util\Configuration;
+
+class ImageRenderer {
+ private $image = null;
+
+ public function __construct (RenderableImage $image) {
+ $this->image = $image;
+ }
+
+ /**
+ * Renders and outputs the "image not found" image.
+ *
+ * Sends the header and immediately outputs the image.
+ *
+ * @param int $w Width of the image
+ * @param int $h Height of the image
+ */
+ public static function outputRenderNotFoundImage ($w, $h) {
+ $image = imagecreate($w, $h);
+ $white = imagecolorallocate($image, 255,255,255);
+ $black = imagecolorallocate($image, 0,0,0);
+
+ header("Content-Type: image/png");
+
+ $w = $_REQUEST["w"]-1;
+ $h = $_REQUEST["h"]-1;
+ imagefill($image, 0,0, $white);
+
+ /* Draw the X */
+ imageline($image, 0,0,$w,$h, $black);
+ imageline($image, $w,0,0,$h, $black);
+ imagepng($image);
+ }
+
+ /**
+ * Scales the image to fit within the given size.
+ *
+ * @param string $outputFile The target file
+ * @param int $w The width
+ * @param int $h The height
+ * @param boolean $padding If true, pad the output image to the given size (transparent background).
+ * @return string The path to the scaled file
+ */
+ public function fitWithin ($outputFile, $w, $h, $padding = false) {
+ $image = new \Imagick();
+ $image->readImage($this->image->getFilename());
+
+ $sourceAspectRatio = $image->getImageWidth() / $image->getImageHeight();
+ $targetAspectRatio = $w / $h;
+
+ $filter = \Imagick::FILTER_UNDEFINED;
+ $blur = 1;
+
+ $targetHeight = $h;
+ $targetWidth = $w;
+
+ if ($sourceAspectRatio < $targetAspectRatio) {
+ $targetWidth = $h * $sourceAspectRatio;
+ $image->resizeImage($h * $sourceAspectRatio, $h, $filter, $blur);
+ } else {
+ $targetHeight = $w / $sourceAspectRatio;
+ $image->resizeImage($w, $w / $sourceAspectRatio, $filter, $blur);
+ }
+
+ if ($padding) {
+ $posX = intval(($w - $targetWidth) / 2);
+ $posY = intval(($h - $targetHeight) / 2);
+
+ $image->extentImage($w, $h,-$posX, -$posY);
+ }
+
+ $image->writeImage($outputFile);
+
+ return $outputFile;
+ }
+
+ /**
+ * Scales the image to fit exactly within the given size.
+ *
+ * This method ensures that no blank space is in the output image,
+ * and that the output image is exactly the width and height specified.
+ *
+ * @param string $outputFile The output file
+ * @param int $w The width
+ * @param int $h The height
+ * @return string The path to the scaled file
+ */
+ public function fitWithinExact ($outputFile, $w, $h) {
+ $image = new \Imagick();
+ $image->readImage($this->image->getFilename());
+
+ $sourceAspectRatio = $image->getImageWidth() / $image->getImageHeight();
+ $targetAspectRatio = $w / $h;
+
+ $filter = \Imagick::FILTER_UNDEFINED;
+ $blur = 1;
+
+ if ($sourceAspectRatio < $targetAspectRatio) {
+ $image->resizeImage($w, $w / $sourceAspectRatio, $filter, $blur);
+ } else {
+ $image->resizeImage($h * $sourceAspectRatio, $h, $filter, $blur);
+ }
+
+ $offsetX = intval(($image->getImageWidth() - $w)/2);
+ $offsetY = intval(($image->getImageHeight() - $h)/2);
+
+ $image = $image->getImageRegion($w, $h, $offsetX, $offsetY);
+
+ $image->writeImage($outputFile);
+
+ return $outputFile;
+ }
+
+ /**
+ * Scales the image to a specific width and height
+ *
+ * @param string $outputFile The output file
+ * @param int $w The width
+ * @param int $h The height
+ * @return string The path to the scaled file
+ */
+ public function scaleTo ($outputFile, $w, $h) {
+ $image = new \Imagick();
+ $image->readImage($this->image->getFilename());
+ $image->adaptiveResizeImage($w, $h);
+ $image->writeImage($outputFile);
+
+ return $outputFile;
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Image/RenderableImage.php b/src/backend/PartKeepr/Image/RenderableImage.php
@@ -0,0 +1,16 @@
+<?php
+namespace PartKeepr\Image;
+
+/**
+ * Interface for any image which needs to be rendered.
+ */
+interface RenderableImage {
+ /**
+ * Returns the full image filename including path.
+ * This is the image where all scale operations take place on.
+ *
+ * @param none
+ * @return string The full image filename including path.
+ */
+ public function getFilename ();
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Logger/Logger.php b/src/backend/PartKeepr/Logger/Logger.php
@@ -0,0 +1,121 @@
+<?php
+namespace PartKeepr\Logger;
+
+/**
+ * This class implements a simple logging mechanism.
+ *
+ * Might be replaced with some more advanced logging framework, but it serves its purpose for now.
+ */
+use PartKeepr\Util\Configuration;
+
+class Logger {
+ /**
+ * Loglevel "debug"
+ *
+ * You want to use this loglevel for debugging messages.
+ * @var string
+ */
+ const LOGLEVEL_DEBUG = "debug";
+
+ /**
+ * Loglevel "info"
+ *
+ * You want to use this loglevel for informational messages where the program flow can continue normally and no
+ * impacts occur.
+ *
+ * @var string
+ */
+ const LOGLEVEL_INFO = "info";
+
+ /**
+ * Loglevel "warning"
+ *
+ * You want to use this loglevel for messages where program flow can continue normally, but a minor
+ * impact can occur.
+ *
+ * @var string
+ */
+ const LOGLEVEL_WARNING = "warning";
+
+ /**
+ * Loglevel "error"
+ *
+ * You want to use this loglevel for messages where program flow could be interrupted and major impacts occur.
+ *
+ * @var string
+ */
+ const LOGLEVEL_ERROR = "error";
+
+ /**
+ * Loglevel "critical"
+ *
+ * You want to use this loglevel for messages where program flow could be interrupted and major impacts occur.
+ *
+ * @var string
+ */
+ const LOGLEVEL_CRITICAL = "critical";
+
+ /**
+ * Logs a message.
+ *
+ * @param string $message The message to log
+ * @param string $severity One of the Logger::LOGLEVEL_* constants
+ */
+ public static function log ($message, $severity = Logger::LOGLEVEL_INFO) {
+ if (Configuration::getOption("partkeepr.logger.enable", false) === false) {
+ // No logging wanted
+ return;
+ }
+
+ $logFormat = "[%-19s] [%-8s] %s";
+
+ $outputFile = Configuration::getOption("partkeepr.logger.outputfile", sys_get_temp_dir() . "/partkeepr.log");
+ $fp = fopen($outputFile, "a");
+
+ $date = date("Y-m-d H:i:s");
+
+ fputs($fp, sprintf($logFormat, $date, $severity, $message)."\n");
+
+ fclose($fp);
+ }
+
+ /**
+ * Logs a message with the Logger::LOGLEVEL_DEBUG severity.
+ * @param string $message
+ */
+ public static function logDebug ($message) {
+ self::log($message, Logger::LOGLEVEL_DEBUG);
+ }
+
+ /**
+ * Logs a message with the Logger::LOGLEVEL_INFO severity.
+ * @param string $message
+ */
+ public static function logInfo ($message) {
+ self::log($message, Logger::LOGLEVEL_INFO);
+ }
+
+ /**
+ * Logs a message with the Logger::LOGLEVEL_WARNING severity.
+ * @param string $message
+ */
+ public static function logWarning ($message) {
+ self::log($message, Logger::LOGLEVEL_WARNING);
+ }
+
+ /**
+ * Logs a message with the Logger::LOGLEVEL_ERROR severity.
+ * @param string $message
+ */
+ public static function logError ($message) {
+ self::log($message, Logger::LOGLEVEL_ERROR);
+ }
+
+ /**
+ * Logs a message with the Logger::LOGLEVEL_CRITICAL severity.
+ * @param string $message
+ */
+ public static function logCritical ($message) {
+ self::log($message, Logger::LOGLEVEL_CRITICAL);
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Manager/AbstractManager.php b/src/backend/PartKeepr/Manager/AbstractManager.php
@@ -0,0 +1,230 @@
+<?php
+namespace PartKeepr\Manager;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\PartKeepr,
+ Doctrine\ORM\QueryBuilder,
+ Doctrine\ORM\Query,
+ PartKeepr\Manager\Exceptions\EntityInUseException;
+
+/**
+ * The AbstractManager is a very basic helper which
+ * implements the mostly used operations on entities:
+ *
+ * - Create
+ * - Delete
+ * - List
+ *
+ */
+abstract class AbstractManager extends Singleton {
+ /**
+ * Returns the FQCN for the target entity to operate on.
+ *
+ * Needs to be implemented by the parent class.
+ *
+ * @return string The FQCN, e.g. PartKeepr\Part
+ */
+ abstract public function getEntityName ();
+
+ /**
+ * Returns all fields which need to appear in the getList ResultSet.
+ *
+ * This should include all fields required by the frontend.
+ *
+ * @return array An array of all fields which should be returned
+ */
+ abstract public function getQueryFields ();
+
+ /**
+ * Returns the default sort field
+ *
+ * @return string The default sort field
+ */
+ abstract public function getDefaultSortField ();
+
+ /**
+ * Loads an entity by id
+ *
+ * @param int $id The entity id
+ */
+ public function getEntity ($id) {
+ return call_user_func($this->getEntityName()."::loadById", $id);
+ }
+
+ /**
+ * Removes a specific entity from the system
+ * @param int $id
+ * @throws EntityInUseException Is thrown when the entity is in use
+ */
+ public function deleteEntity ($id) {
+ $entity = $this->getEntity($id);
+
+ try {
+ PartKeepr::getEM()->remove($entity);
+ PartKeepr::getEM()->flush();
+ } catch (\PDOException $e) {
+ if ($e->getCode() == "23000") {
+ throw new EntityInUseException($entity);
+ }
+ }
+ }
+
+ /**
+ * Creates a new entity from an array of parameters
+ * @param array $parameters An array which gets passed to the deserialize method
+ */
+ public function createEntity ($parameters) {
+ $class = $this->getEntityName();
+ $entity = new $class;
+ $entity->deserialize($parameters);
+
+ PartKeepr::getEM()->persist($entity);
+ PartKeepr::getEM()->flush();
+
+ return $entity;
+ }
+
+ /**
+ * Returns a list of entities.
+ *
+ * @param ManagerFilter $filter The filter settings for this query
+ */
+ public function getList (ManagerFilter $filter) {
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+
+ $qb->select("COUNT(q.id)")->from($this->getEntityName(),"q");
+
+ $this->applyFiltering($qb, $filter);
+ $this->applyCustomQuery($qb, $filter);
+
+ $totalQuery = $qb->getQuery();
+
+ $this->applyResultFields($qb, $filter);
+ $this->applyPagination($qb, $filter);
+ $this->applySorting($qb, $filter);
+
+ $query = $qb->getQuery();
+
+ return array("data" => $this->getResult($query), "totalCount" => $totalQuery->getSingleScalarResult());
+ }
+
+ /**
+ * Processes the result after it was retrieved. In the default configuration, it returns an array result, or
+ * if no query fields are specified, it tries to serialize all objects.
+ */
+ protected function getResult (Query $query) {
+ if (count($this->getQueryFields()) == 0) {
+ $aSerializedResult = array();
+ foreach ($query->getResult() as $result) {
+ $aSerializedResult[] = $result->serialize();
+ }
+
+ return $aSerializedResult;
+ } else {
+ return $query->getArrayResult();
+ }
+ }
+
+ /**
+ * Applies the result fields to the query.
+ *
+ * The result fields can be prefixed with the table alias or not; if not prefixed, it is assumed that we'll be
+ * using the specified entity FQCN.
+ *
+ * Note that the base name will be always "q", so avoid "q" as alias for joined tables.
+ *
+ * @param QueryBuilder $qb The query builder
+ * @param ManagerFilter $filter The query filter
+ */
+ protected function applyResultFields (QueryBuilder $qb, ManagerFilter $filter) {
+ if (count($this->getQueryFields()) == 0) {
+ $qb->select("q");
+ } else {
+ // Prepend a prefix to each field
+ $aQueryFields = array();
+ foreach ($this->getQueryFields() as $field) {
+
+ if (strpos($field, ".") === false) {
+ // The field is not prefixed, prepend the q. prefix
+ $aQueryFields[] = "q.".$field;
+ } else {
+ // Use as-is
+ $aQueryFields[] = $field;
+ }
+ }
+
+ $qb->select($aQueryFields);
+ }
+ }
+
+ /**
+ * Applies filtering to the query and calls back the custom filtering function, if required.
+ *
+ * @param QueryBuilder $qb The query builder
+ * @param ManagerFilter $filter The query filter
+ */
+ protected function applyFiltering (QueryBuilder $qb, ManagerFilter $filter) {
+ if ($filter->getFilter() !== null && $filter->getFilterField() !== null) {
+ $aOrWhereFields = array();
+
+ if (is_array($filter->getFilterField())) {
+ foreach ($filter->getFilterField() as $field) {
+ $aOrWhereFields[] = "LOWER(q.".$field.") LIKE :filter";
+ }
+ } else {
+ $aOrWhereFields[] = "LOWER(q.".$filter->getFilterField().") LIKE :filter";
+ }
+
+ foreach ($aOrWhereFields as $or) {
+ $qb->orWhere($or);
+ }
+
+ $qb->setParameter("filter", "%".strtolower($filter->getFilter())."%");
+ }
+
+ if ($filter->getFilterCallback() !== null) {
+ call_user_func($filter->getFilterCallback(), $qb);
+ }
+ }
+
+
+ /**
+ * Applies a custom query to the QueryBuilder
+ *
+ * @param QueryBuilder $qb The query builder
+ * @param ManagerFilter $filter The query filter
+ */
+ protected function applyCustomQuery (QueryBuilder $qb, ManagerFilter $filter) {
+
+ }
+
+ /**
+ * Applies pagination to the query
+ *
+ * @param QueryBuilder $qb The query builder
+ * @param ManagerFilter $filter The query filter
+ */
+ protected function applyPagination (QueryBuilder $qb, ManagerFilter $filter) {
+ if ($filter->getStart() !== null && $filter->getLimit() !== null) {
+ $qb->setFirstResult($filter->getStart());
+ }
+
+ if ($filter->getLimit() !== null) {
+ $qb->setMaxResults($filter->getLimit());
+ }
+ }
+
+ /**
+ * Applies record sorting
+ *
+ * @param QueryBuilder $qb The query builder
+ * @param ManagerFilter $filter The query filter
+ */
+ protected function applySorting (QueryBuilder $qb, ManagerFilter $filter) {
+ foreach ($filter->getSorters() as $sorter) {
+ if ($sorter->getSortField() !== null && $sorter->getSortField() != "q.") {
+ $qb->addOrderBy($sorter->getSortField(), $sorter->getSortDirection());
+ }
+ }
+ }
+} +
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Manager/Exceptions/EntityInUseException.php b/src/backend/PartKeepr/Manager/Exceptions/EntityInUseException.php
@@ -0,0 +1,31 @@
+<?php
+namespace PartKeepr\Manager\Exceptions;
+
+/**
+ * This exception is thrown when an entity should be deleted, but is in use by other entities.
+ * @author felicitus
+ */
+class EntityInUseException extends \Exception {
+
+ /**
+ * The entity
+ * @var BaseEntity
+ */
+ private $entity;
+
+ /**
+ * Constructs the exception
+ * @param BaseEntity $entity
+ */
+ public function __construct (\PartKeepr\Util\BaseEntity $entity) {
+ parent::__construct(sprintf("Entity %s is referenced by other entities, can't delete", get_class($entity)));
+ $this->entity = $entity;
+ }
+
+ /**
+ * Returns the entity which caused the error
+ */
+ public function getEntity () {
+ return $this->entity;
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Manager/ManagerFilter.php b/src/backend/PartKeepr/Manager/ManagerFilter.php
@@ -0,0 +1,196 @@
+<?php
+namespace PartKeepr\Manager;
+
+use PartKeepr\Service\Service;
+
+class ManagerFilter {
+ /**
+ * Specifies the record index at which to start
+ * @var integer
+ */
+ protected $start = 0;
+
+ /**
+ * Specifies the number of records to retrieve
+ * @var integer
+ */
+ protected $limit = null;
+
+ /**
+ * Specifies a string to filter for. Can either be a string
+ * or null if no filter is wanted
+ * @var string
+ */
+ protected $filter = null;
+
+ /**
+ * Specifies the field (or a list of fields) to apply the filter on
+ * @var mixed null if disabled, a string for a single field or an array of fields
+ */
+ protected $filterField = null;
+
+ /**
+ * Specifies the fields to sort by
+ * @var array
+ */
+ protected $sorters = array();
+
+ /**
+ * A callback which is called when creating the filter
+ * @var function The callback
+ */
+ protected $callback = null;
+
+ /**
+ * Sets the start position
+ * @param int $start
+ */
+ public function setStart ($start) {
+ $this->start = intval($start);
+ }
+
+ /**
+ * Returns the start position
+ * @return int
+ */
+ public function getStart () {
+ if ($this->start === null) {
+ return 0;
+ } else {
+ return $this->start;
+ }
+ }
+
+ /**
+ * Sets the number of records to retrieve
+ * @param mixed $limit Either a positive integer, or null/-1 for no limit
+ */
+ public function setLimit ($limit) {
+ if ($limit === null || $limit == -1) {
+ $this->limit = null;
+ } else {
+ $this->limit = intval($limit);
+ }
+ }
+
+ /**
+ * Returns the number of records to retrieve
+ * @return int
+ */
+ public function getLimit () {
+ return $this->limit;
+ }
+
+ /**
+ * Sets the sorters for this filter.
+ *
+ * @param array $sorters An array of Sorter instances
+ */
+ public function setSorters (array $sorters) {
+ // Make sure that each sorter is an instance of the Sorter class.
+ foreach ($sorters as $sorter) {
+ if (!($sorter instanceof Sorter)) {
+ throw new InvalidArgumentException("The passed sorters needs to be an array of Sorter instances");
+ }
+ }
+
+ $this->sorters = $sorters;
+ }
+
+ /**
+ * Returns the sorters for this filter.
+ * @return array An array of Sorter instances
+ */
+ public function getSorters () {
+ return $this->sorters;
+ }
+
+ /**
+ * Sets the filter. Specify null if no filter is wanted.
+ * @param mixed $filter A string to filter for, or null to disable
+ */
+ public function setFilter ($filter) {
+ $this->filter = $filter;
+ }
+
+ /**
+ * Returns the filter.
+ * @return mixed Either a string to filter for, or null if disabled
+ */
+ public function getFilter () {
+ return $this->filter;
+ }
+
+ /**
+ * Sets the field(s) to filter for.
+ *
+ * If multiple fields are specified, they will be combined using an "OR" clause.
+ *
+ * @param mixed $field Either null to disable, a single string to specify a field, or an array of string fields
+ */
+ public function setFilterField ($field) {
+ $this->filterField = $field;
+ }
+
+ /**
+ * Returns the field(s) to filter for
+ * @return mixed See setFilterField
+ */
+ public function getFilterField () {
+ return $this->filterField;
+ }
+
+ /**
+ * Sets the filter callback
+ * @param function $callback A function which is called when creating a filter. The callback function receives the
+ * query builder as first argument.
+ */
+ public function setFilterCallback ($callback) {
+ $this->callback = $callback;
+ }
+
+ /**
+ * Returns the filter callback
+ * @return function The callback function
+ */
+ public function getFilterCallback () {
+ return $this->callback;
+ }
+
+ /**
+ * Constructs a new filter set.
+ *
+ * If a service is passed, the constructor automatically extracts the parameters from the service
+ *
+ * @todo Document which parameters we have
+ *
+ * @param Service $service A service to extract the information from, or null
+ */
+ public function __construct (Service $service = null) {
+ if (is_object($service)) {
+ if ($service->hasParameter("start")) {
+ $this->setStart($service->getParameter("start", null));
+ }
+
+ if ($service->hasParameter("limit")) {
+ $this->setLimit($service->getParameter("limit", null));
+ }
+
+ if ($service->hasParameter("sort")) {
+ $tmp = json_decode($service->getParameter("sort"), true);
+
+ $aSorters = array();
+
+ foreach ($tmp as $key => $sortParam) {
+ $aSorters[] = new Sorter("q.".$sortParam["property"], $sortParam["direction"]);
+ }
+
+ $this->setSorters($aSorters);
+ }
+
+ if ($service->hasParameter("query")) {
+ $this->setFilter($service->getParameter("query"));
+ }
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Manager/Sorter.php b/src/backend/PartKeepr/Manager/Sorter.php
@@ -0,0 +1,79 @@
+<?php
+namespace PartKeepr\Manager;
+
+/**
+ * Represents a sorter, which is used with the ManagerFilter class.
+ *
+ * This allows the developer to specify multiple sorters. One sorter contains a sort field and a sort direction.
+ */
+class Sorter {
+ /**
+ * The field to sort by
+ * @var string
+ */
+ private $sortField = null;
+
+ /**
+ * The direction to sort by
+ * @var string
+ */
+ private $sortDirection = null;
+
+ /**
+ * Constructs a new sorter.
+ *
+ * @param string $field The field to sort by
+ * @param string $direction The direction, either "asc" or "desc"
+ */
+ public function __construct ($field = null, $direction = null) {
+ if ($field !== null) {
+ $this->setSortField($field);
+ }
+
+ if ($direction !== null) {
+ $this->setSortDirection($direction);
+ }
+ }
+
+ /**
+ * Sets the sort field for this sorter
+ * @param string $field The field to sort by
+ */
+ public function setSortField ($field) {
+ $this->sortField = $field;
+ }
+
+ /**
+ * Sets the sort direction for this sorter
+ * @param string $direction Either "asc" or "desc"
+ */
+ public function setSortDirection ($direction) {
+ switch (strtolower($direction)) {
+ case "desc":
+ case "d":
+ $this->sortDirection = "desc";
+ break;
+ case "asc":
+ case "a":
+ default:
+ $this->sortDirection = "asc";
+ break;
+ }
+ }
+
+ /**
+ * Returns the sort field for this sorter
+ * @return string The field name
+ */
+ public function getSortField () {
+ return $this->sortField;
+ }
+
+ /**
+ * Returns the sort order for this sorter
+ * @return string Either "asc" or "desc"
+ */
+ public function getSortDirection () {
+ return $this->sortDirection;
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Manufacturer/Manufacturer.php b/src/backend/PartKeepr/Manufacturer/Manufacturer.php
@@ -0,0 +1,250 @@
+<?php
+namespace PartKeepr\Manufacturer;
+
+use PartKeepr\Util\Deserializable,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Util\BaseEntity,
+ PartKeepr\PartKeepr;
+
+/**
+ * Represents a manufacturer
+ * @Entity **/
+class Manufacturer extends BaseEntity implements Serializable, Deserializable {
+ /**
+ * The name of the manufacturer
+ * @Column(type="string",unique=true)
+ * @var string
+ */
+ private $name;
+
+ /**
+ * The address of the manufacturer
+ * @Column(type="text",nullable=true)
+ * @var string
+ */
+ private $address;
+
+ /**
+ * The URL
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $url;
+
+ /**
+ * The email
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $email;
+
+ /**
+ * The comment
+ * @Column(type="text",nullable=true)
+ * @var string
+ */
+ private $comment;
+
+ /**
+ * The phone number
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $phone;
+
+ /**
+ * The fax number
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $fax;
+
+ /**
+ * All ic logos of this manufacturer
+ * @OneToMany(targetEntity="PartKeepr\Manufacturer\ManufacturerICLogo",mappedBy="manufacturer",cascade={"persist", "remove"})
+ */
+ private $icLogos;
+
+ /**
+ * Creates a new manufacturer instance
+ */
+ public function __construct () {
+ $this->icLogos = new \Doctrine\Common\Collections\ArrayCollection();
+ }
+
+ /**
+ * Sets the name
+ * @param string $name The name
+ */
+ public function setName ($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the name
+ * @return string The name
+ */
+ public function getName () {
+ return $this->name;
+ }
+
+ /**
+ * Sets the phone number
+ * @param string $phone The phone number
+ */
+ public function setPhone ($phone) {
+ $this->phone = $phone;
+ }
+
+ /**
+ * Returns the phone number
+ * @return string The phone number
+ */
+ public function getPhone () {
+ return $this->phone;
+ }
+
+ /**
+ * Sets the fax number
+ * @param string $fax The fax number
+ */
+ public function setFax ($fax) {
+ $this->fax = $fax;
+ }
+
+ /**
+ * Returns the fax number
+ * @return string The fax number
+ */
+ public function getFax () {
+ return $this->fax;
+ }
+
+ /**
+ * Sets the address
+ * @param string $address The address
+ */
+ public function setAddress ($address) {
+ $this->address = $address;
+ }
+
+ /**
+ * Returns the address
+ * @return string The address
+ */
+ public function getAddress () {
+ return $this->address;
+ }
+
+ /**
+ * Sets the comment
+ * @param string $comment The comment
+ */
+ public function setComment ($comment) {
+ $this->comment = $comment;
+ }
+
+ /**
+ * Returns the comment
+ * @return string The comment
+ */
+ public function getComment () {
+ return $this->comment;
+ }
+
+ /**
+ * Sets the email
+ * @param string $email The email
+ */
+ public function setEmail ($email) {
+ $this->email = $email;
+ }
+
+ /**
+ * Returns the email
+ * @return string The email
+ */
+ public function getEmail () {
+ return $this->email;
+ }
+
+ /**
+ * Sets the URL
+ * @param string $url The URL
+ */
+ public function setURL ($url) {
+ $this->url = $url;
+ }
+
+ /**
+ * Returns the URL
+ * @return string The url
+ */
+ public function getURL () {
+ return $this->url;
+ }
+
+ /**
+ * Returns the ic logos
+ * @return ArrayCollection The array with all ic logos
+ */
+ public function getICLogos () {
+ return $this->icLogos;
+ }
+
+ /**
+ * Returns this manufacturer in serialized form
+ * @return array The serialized manufacturer
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "name" => $this->getName(),
+ "url" => $this->getURL(),
+ "address" => $this->getAddress(),
+ "email" => $this->getEmail(),
+ "comment" => $this->getComment(),
+ "phone" => $this->getPhone(),
+ "fax" => $this->getFax(),
+ "iclogos" => $this->serializeChildren($this->getICLogos())
+ );
+ }
+
+ /**
+ * Deserializes the manufacturer
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "name":
+ $this->setName($value);
+ break;
+ case "url":
+ $this->setURL($value);
+ break;
+ case "comment":
+ $this->setComment($value);
+ break;
+ case "email":
+ $this->setEmail($value);
+ break;
+ case "fax":
+ $this->setFax($value);
+ break;
+ case "phone":
+ $this->setPhone($value);
+ break;
+ case "address":
+ $this->setAddress($value);
+ break;
+ case "iclogos":
+ $this->deserializeChildren($value, $this->getICLogos(), "PartKeepr\Manufacturer\ManufacturerICLogo");
+ foreach ($this->getICLogos() as $iclogo) {
+ $iclogo->setManufacturer($this);
+ }
+ break;
+ }
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Manufacturer/ManufacturerICLogo.php b/src/backend/PartKeepr/Manufacturer/ManufacturerICLogo.php
@@ -0,0 +1,63 @@
+<?php
+namespace PartKeepr\Manufacturer;
+
+use PartKeepr\Util\Deserializable,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Image\Image;
+
+/**
+ * Holds a manufacturer IC logo
+ * @Entity
+ **/
+class ManufacturerICLogo extends Image implements Serializable, Deserializable {
+ /**
+ * The manufacturer object
+ * @ManyToOne(targetEntity="PartKeepr\Manufacturer\Manufacturer")
+ * @var Manufacturer
+ */
+ private $manufacturer = null;
+
+ /**
+ * Creates a new IC logo instance
+ */
+ public function __construct () {
+ parent::__construct(Image::IMAGE_ICLOGO);
+ }
+
+ /**
+ * Sets the manufacturer
+ * @param Manufacturer $manufacturer The manufacturer to set
+ */
+ public function setManufacturer (Manufacturer $manufacturer) {
+ $this->manufacturer = $manufacturer;
+ }
+
+ /**
+ * Returns the manufacturer
+ * @return Manufacturer the manufacturer
+ */
+ public function getManufacturer () {
+ return $this->manufacturer;
+ }
+
+ /**
+ *
+ * Serializes this ic logo
+ * @return array The serialized ic logo
+ */
+ public function serialize () {
+ return array("id" => $this->getId(), "manufacturer_id" => $this->getManufacturer()->getId());
+ }
+
+ /**
+ * Deserializes the iclogo
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ if (array_key_exists("id", $parameters)) {
+ if (substr($parameters["id"], 0, 4) === "TMP:") {
+ $this->replaceFromTemporaryFile($parameters["id"]);
+ }
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Manufacturer/ManufacturerManager.php b/src/backend/PartKeepr/Manufacturer/ManufacturerManager.php
@@ -0,0 +1,104 @@
+<?php
+namespace PartKeepr\Manufacturer;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\Manufacturer\Manufacturer,
+ PartKeepr\PartKeepr,
+ PartKeepr\Category\CategoryManager,
+ PartKeepr\Manufacturer\Exceptions\ManufacturerNotFoundException;
+
+class ManufacturerManager extends Singleton {
+ /**
+ * Returns a list of manufacturers.
+ *
+ * @param int $start Start of the list, default 0
+ * @param int $limit Number of users to list, default 10
+ * @param string $sort The field to sort by, default "name"
+ * @param string $dir The direction to sort (ASC or DESC), default ASC
+ * @param string $filter A string to filter the manufacturer's name by, default empty
+ */
+ public function getManufacturers ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
+
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+ $qb->select("st.id, st.name, st.url, st.email, st.comment, st.address")->from("PartKeepr\Manufacturer\Manufacturer","st");
+
+ if ($filter != "") {
+ $qb = $qb->where("LOWER(st.name) LIKE :filter");
+ $qb->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ if ($limit > -1) {
+ $qb->setMaxResults($limit);
+ $qb->setFirstResult($start);
+ }
+
+ $qb->orderBy("st.".$sort, $dir);
+
+ $query = $qb->getQuery();
+
+ $result = $query->getResult();
+
+ $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
+ $totalQueryBuilder->select("COUNT(st.id)")->from("PartKeepr\Manufacturer\Manufacturer","st");
+
+
+
+ if ($filter != "") {
+ $totalQueryBuilder = $totalQueryBuilder->where("LOWER(st.name) LIKE :filter");
+ $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ $totalQuery = $totalQueryBuilder->getQuery();
+
+ return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
+ }
+
+ /**
+ * Adds a new manufacturer by name
+ *
+ * @param string $name The manufacturer name
+ */
+ public function addManufacturer ($name) {
+ $manufacturer = new Manufacturer();
+ $manufacturer->setName($name);
+
+ PartKeepr::getEM()->persist($manufacturer);
+ PartKeepr::getEM()->flush();
+
+ return $manufacturer;
+ }
+
+ /**
+ * 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
+ */
+ public function deleteManufacturer ($id) {
+ $manufacturer = Manufacturer::loadById($id);
+
+ 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 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/PartKeepr/Manufacturer/ManufacturerService.php b/src/backend/PartKeepr/Manufacturer/ManufacturerService.php
@@ -0,0 +1,82 @@
+<?php
+namespace PartKeepr\Manufacturer;
+
+use PartKeepr\Service\RestfulService;
+
+use PartKeepr\Service\Service,
+ PartKeepr\Part\PartManager,
+ PartKeepr\Stock\StockEntry,
+ PartKeepr\PartKeepr,
+ PartKeepr\Session\SessionManager;
+
+class ManufacturerService extends Service implements RestfulService {
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return array("data" => ManufacturerManager::getInstance()->getManufacturer($this->getParameter("id"))->serialize());
+ } else {
+ if ($this->hasParameter("sort")) {
+ $tmp = json_decode($this->getParameter("sort"), true);
+
+ $aSortParams = $tmp[0];
+ } else {
+ $aSortParams = array(
+ "property" => "name",
+ "direction" => "ASC");
+ }
+ return ManufacturerManager::getInstance()->getManufacturers(
+ $this->getParameter("start", $this->getParameter("start", 0)),
+ $this->getParameter("limit", $this->getParameter("limit", 25)),
+ $this->getParameter("sortby", $aSortParams["property"]),
+ $this->getParameter("dir", $aSortParams["direction"]),
+ $this->getParameter("query", ""));
+ }
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::create()
+ */
+ public function create () {
+ $this->requireParameter("name");
+
+ $manufacturer = new Manufacturer;
+ $manufacturer->deserialize($this->getParameters());
+
+ PartKeepr::getEM()->persist($manufacturer);
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $manufacturer->serialize());
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::update()
+ */
+ public function update () {
+ $this->requireParameter("id");
+ $this->requireParameter("name");
+ $manufacturer = ManufacturerManager::getInstance()->getManufacturer($this->getParameter("id"));
+ $manufacturer->deserialize($this->getParameters());
+
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $manufacturer->serialize());
+
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::destroy()
+ */
+ public function destroy () {
+ $this->requireParameter("id");
+
+ ManufacturerManager::getInstance()->deleteManufacturer($this->getParameter("id"));
+
+ return array("data" => null);
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/ManufacturerICLogo/ManufacturerICLogoManager.php b/src/backend/PartKeepr/ManufacturerICLogo/ManufacturerICLogoManager.php
@@ -0,0 +1,65 @@
+<?php
+namespace PartKeepr\ManufacturerICLogo;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\Manufacturer\Manufacturer,
+ PartKeepr\PartKeepr,
+ PartKeepr\Manufacturer\Exceptions\ManufacturerNotFoundException;
+
+class ManufacturerICLogoManager extends Singleton {
+ /**
+ * Returns a list of manufacturer ic logos.
+ *
+ * @param int $start Start of the list, default 0
+ * @param int $limit Number of users to list, default 10
+ * @param string $sort The field to sort by, default "name"
+ * @param string $dir The direction to sort (ASC or DESC), default ASC
+ * @param string $filter The manufacturer id
+ */
+ public function getManufacturerICLogos ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
+
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+ $qb->select("st.id, maf.id AS manufacturer_id")->from("PartKeepr\Manufacturer\ManufacturerICLogo","st")
+ ->leftJoin('st.manufacturer', "maf");
+
+ if ($filter != "") {
+ $manufacturer = Manufacturer::loadById($filter);
+ $qb = $qb->where("st.manufacturer = :manufacturer");
+ $qb->setParameter("manufacturer", $manufacturer);
+ }
+
+ if ($limit > -1) {
+ $qb->setMaxResults($limit);
+ $qb->setFirstResult($start);
+ }
+
+ $qb->orderBy("st.".$sort, $dir);
+
+ $query = $qb->getQuery();
+
+ $result = $query->getResult();
+
+ $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
+ $totalQueryBuilder->select("COUNT(st.id)")->from("PartKeepr\Manufacturer\ManufacturerICLogo","st");
+
+
+
+ if ($filter != "") {
+ $totalQueryBuilder = $totalQueryBuilder->where("st.manufacturer = :manufacturer");
+ $totalQueryBuilder->setParameter("manufacturer", $manufacturer);
+ }
+
+ $totalQuery = $totalQueryBuilder->getQuery();
+
+ return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
+ }
+
+ /**
+ * Returns a manufacturer ic logo by id
+ * @param int $id The manufacturer ic logo id
+ */
+ public function getManufacturerICLogo ($id) {
+ return ManufacturerICLogo::loadById($id);
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/ManufacturerICLogo/ManufacturerICLogoService.php b/src/backend/PartKeepr/ManufacturerICLogo/ManufacturerICLogoService.php
@@ -0,0 +1,101 @@
+<?php
+namespace PartKeepr\ManufacturerICLogo;
+
+use PartKeepr\Manufacturer\ManufacturerICLogo,
+ PartKeepr\TempImage\TempImage,
+ PartKeepr\Service\RestfulService,
+ PartKeepr\Service\Service,
+ PartKeepr\PartKeepr,
+ PartKeepr\Manufacturer\Manufacturer,
+ PartKeepr\Session\SessionManager;
+
+class ManufacturerICLogoService extends Service implements RestfulService {
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return ManufacturerICLogoManager::getInstance()->getManufacturerICLogo($this->getParameter("id"))->serialize();
+ } else {
+ if ($this->hasParameter("sort")) {
+ $tmp = json_decode($this->getParameter("sort"), true);
+
+ $aSortParams = $tmp[0];
+ } else {
+ $aSortParams = array(
+ "property" => "id",
+ "direction" => "ASC");
+ }
+
+ $filter = "";
+
+ if ($this->hasParameter("filter")) {
+ $tmp = json_decode($this->getParameter("filter"), true);
+
+ foreach ($tmp as $item) {
+ if (array_key_exists("property", $item)) {
+ if ($item["property"] == "manufacturer_id") {
+ if (array_key_exists("value", $item)) {
+ $filter = $item["value"];
+ }
+ }
+ }
+ }
+ }
+ return ManufacturerICLogoManager::getInstance()->getManufacturerICLogos(
+ $this->getParameter("start", $this->getParameter("start", 0)),
+ $this->getParameter("limit", $this->getParameter("limit", 25)),
+ $this->getParameter("sortby", $aSortParams["property"]),
+ $this->getParameter("dir", $aSortParams["direction"]),
+ $filter);
+ }
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::create()
+ */
+ public function create () {
+ $this->requireParameter("tmp_id");
+ $this->requireParameter("manufacturer_id");
+
+ $tmpImage = TempImage::loadById($this->getParameter("tmp_id"));
+
+ $image = new ManufacturerICLogo();
+
+ $manufacturer = Manufacturer::loadById($this->getParameter("manufacturer_id"));
+
+ $image->setManufacturer($manufacturer);
+ $image->replace($tmpImage->getFilename());
+ $image->setOriginalFilename($tmpImage->getOriginalFilename());
+ PartKeepr::getEM()->persist($image);
+ PartKeepr::getEM()->flush();
+
+ return $image->serialize();
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::update()
+ */
+ public function update () {
+
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::destroy()
+ */
+ public function destroy () {
+ $this->requireParameter("id");
+
+ $logo = ManufacturerICLogo::loadById($this->getParameter("id"));
+
+ PartKeepr::getEM()->remove($logo);
+ PartKeepr::getEM()->flush();
+
+ return array("data" => null);
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Part/Exceptions/CategoryNotAssignedException.php b/src/backend/PartKeepr/Part/Exceptions/CategoryNotAssignedException.php
@@ -0,0 +1,20 @@
+<?php
+namespace PartKeepr\Part\Exceptions;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\Util\SerializableException,
+ PartKeepr\Part\Part;
+
+/**
+ * This exception is thrown when a part hasn't got a category assigned
+ */
+class CategoryNotAssignedException extends SerializableException {
+
+ /**
+ * Constructs the exception
+ * @param BaseEntity $entity
+ */
+ public function __construct (Part $part) {
+ parent::__construct(PartKeepr::i18n("Part %s has no category assigned", $part));
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Part/Exceptions/StorageLocationNotAssignedException.php b/src/backend/PartKeepr/Part/Exceptions/StorageLocationNotAssignedException.php
@@ -0,0 +1,19 @@
+<?php
+namespace PartKeepr\Part\Exceptions;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\Util\SerializableException;
+
+/**
+ * This exception is thrown when a part hasn't got a storage location assigned
+ */
+class StorageLocationNotAssignedException extends SerializableException {
+
+ /**
+ * Constructs the exception
+ * @param BaseEntity $entity
+ */
+ public function __construct () {
+ parent::__construct(PartKeepr::i18n("No storage location assigned"));
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Part/Part.php b/src/backend/PartKeepr/Part/Part.php
@@ -0,0 +1,640 @@
+<?php
+namespace PartKeepr\Part;
+
+use PartKeepr\StorageLocation\StorageLocation,
+ PartKeepr\Footprint\Footprint,
+ PartKeepr\PartCategory\PartCategoryManager,
+ PartKeepr\Util\Deserializable,
+ PartKeepr\PartCategory\PartCategory,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Util\BaseEntity,
+ PartKeepr\PartKeepr,
+ PartKeepr\Part\Exceptions\CategoryNotAssignedException,
+ PartKeepr\Util\Exceptions\OutOfRangeException,
+ PartKeepr\Part\Exceptions\StorageLocationNotAssignedException;
+
+
+/**
+ * Represents a part in the database. The heart of our project. Handle with care!
+ *
+ * @Entity @HasLifecycleCallbacks
+ */
+class Part extends BaseEntity implements Serializable, Deserializable {
+ /**
+ * The category of the part
+ * @ManyToOne(targetEntity="PartKeepr\PartCategory\PartCategory")
+ * @var Category
+ */
+ private $category;
+
+ /**
+ * The part's name
+ * @Column
+ * @var string
+ */
+ private $name;
+
+ /**
+ * The part's short description
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $description;
+
+ /**
+ * The footprint of this part
+ * @ManyToOne(targetEntity="PartKeepr\Footprint\Footprint")
+ * @var Footprint
+ */
+ private $footprint;
+
+ /**
+ * The unit in which the part's "amount" is calculated. This is necessary to count parts
+ * in "pieces", "meters" or "grams".
+ * @ManyToOne(targetEntity="PartKeepr\Part\PartUnit")
+ * @var PartUnit
+ */
+ private $partUnit;
+
+ /**
+ * Defines the storage location of this part
+ * @ManyToOne(targetEntity="PartKeepr\StorageLocation\StorageLocation")
+ * @var StorageLocation
+ */
+ private $storageLocation;
+
+ /**
+ * Holds the manufacturers which can manufacture this part
+ * @OneToMany(targetEntity="PartKeepr\Part\PartManufacturer",mappedBy="part",cascade={"persist", "remove"})
+ * @var ArrayCollection
+ */
+ private $manufacturers;
+
+ /**
+ * Holds the distributors from where we can buy the part
+ * @OneToMany(targetEntity="PartKeepr\Part\PartDistributor",mappedBy="part",cascade={"persist", "remove"})
+ * @var ArrayCollection
+ */
+ private $distributors;
+
+ /**
+ * Holds the part images
+ * @OneToMany(targetEntity="PartKeepr\Part\PartImage",mappedBy="part",cascade={"persist", "remove"})
+ * @var PartImage
+ */
+ private $images;
+
+ /**
+ * Holds the part attachments
+ * @OneToMany(targetEntity="PartKeepr\Part\PartAttachment",mappedBy="part",cascade={"persist", "remove"})
+ * @var PartAttachment
+ */
+ private $attachments;
+
+ /**
+ * The comment for this part
+ * @Column(type="text")
+ */
+ private $comment = "";
+
+ /**
+ * The stock level. Note that this is a cached value, because it makes our summary queries easier.
+ * @todo It would be nice if we could get rid of that.
+ * @Column(type="integer")
+ * @var integer
+ */
+ private $stockLevel = 0;
+
+ /**
+ * The minimum stock level for this part. If we run out of this part (e.g. stockLevel < minStockLevel),
+ * we can see that in the system and re-order parts.
+ *
+ * @Column(type="integer")
+ * @var integer
+ */
+ private $minStockLevel = 0;
+
+ /**
+ * The average price for the part. Note that this is a cached value.
+ *
+ * @todo It would be nice if we could get rid of that
+ * @Column(type="decimal",precision=13,scale=4,nullable=true)
+ * @var float
+ */
+ private $averagePrice = null;
+
+ /**
+ * The stock level history
+ * @OneToMany(targetEntity="PartKeepr\Stock\StockEntry",mappedBy="part",cascade={"persist", "remove"})
+ * @var ArrayCollection
+ */
+ private $stockLevels;
+
+ /**
+ * The parameters for this part
+ * @OneToMany(targetEntity="PartKeepr\PartParameter\PartParameter",mappedBy="part",cascade={"persist", "remove"})
+ * @var ArrayCollection
+ */
+ private $parameters;
+
+ /**
+ * The part status for this part
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $status;
+
+ /**
+ * Defines if the part needs review
+ * @Column(type="boolean")
+ * @var boolean
+ */
+ private $needsReview;
+
+ /**
+ * The create date+time for this part
+ * @Column(type="datetime",nullable=true)
+ * @var \DateTime
+ */
+ private $createDate;
+
+ /**
+ * @OneToMany(targetEntity="PartKeepr\Project\Project", mappedBy="part")
+ **/
+ private $projects;
+
+ /**
+ * The internal part number
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $internalPartNumber;
+
+ public function __construct () {
+ $this->distributors = new \Doctrine\Common\Collections\ArrayCollection();
+ $this->manufacturers = new \Doctrine\Common\Collections\ArrayCollection();
+ $this->parameters = new \Doctrine\Common\Collections\ArrayCollection();
+ $this->images = new \Doctrine\Common\Collections\ArrayCollection();
+ $this->attachments = new \Doctrine\Common\Collections\ArrayCollection();
+ $this->setCreateDate(new \DateTime());
+ $this->setReviewFlag(false);
+ }
+
+ /**
+ * Sets the name for this part
+ * @param string $name The part's name
+ */
+ public function setName ($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the name of this part
+ * @return string The part name
+ */
+ public function getName () {
+ return $this->name;
+ }
+
+ /**
+ * Sets the internal part number for this part
+ * @param string $partnumber
+ */
+ public function setInternalPartNumber ($partNumber) {
+ $this->internalPartNumber = $partNumber;
+ }
+
+ /**
+ * Returns the internal part number for this part
+ * @return string the internal part number
+ */
+ public function getInternalPartNumber () {
+ return $this->internalPartNumber;
+ }
+
+ /**
+ * Sets the description for this part
+ * @param string $description The part's short description
+ */
+ public function setDescription ($description) {
+ $this->description = $description;
+ }
+
+ /**
+ * Returns the short description of this part
+ * @return string The part description
+ */
+ public function getDescription () {
+ return $this->description;
+ }
+
+ /**
+ * Sets the part unit
+ *
+ * @param PartUnit $partUnit The part unit object to set
+ * @return nothing
+ */
+ public function setPartUnit (PartUnit $partUnit) {
+ $this->partUnit = $partUnit;
+ }
+
+ /**
+ * Returns the part unit
+ *
+ * @param none
+ * @return PartUnit The part unit object
+ */
+ public function getPartUnit () {
+ return $this->partUnit;
+ }
+
+ /**
+ * Sets the average price for this unit
+ * @todo Is this actually used?
+ * @param float $price The price to set
+ */
+ public function setAveragePrice ($price) {
+ $this->averagePrice = $price;
+ }
+
+ /**
+ * Updates the internal stock level from the stock history
+ */
+ public function updateStockLevel () {
+ $this->stockLevel = $this->getStockLevel();
+ }
+
+ /**
+ * Sets the review flag
+ * @param boolean $bReview True if the part needs review, false otherwise
+ */
+ public function setReviewFlag ($bReview) {
+ $this->needsReview = $bReview;
+ }
+
+ /**
+ * Returns the review flag
+ * @return boolean True if the part needs review, false otherwise
+ */
+ public function getReviewFlag () {
+ return $this->needsReview;
+ }
+
+ /**
+ * Set the minimum stock level for this part
+ *
+ * Only positive values are allowed.
+ *
+ * @param int $minStockLevel A minimum stock level, only values >= 0 are allowed.
+ * @throws \PartKeepr\Util\Exceptions\OutOfRangeException If the passed stock level is not in range (>=0)
+ */
+ public function setMinStockLevel ($minStockLevel) {
+ $minStockLevel = intval($minStockLevel);
+
+ if ($minStockLevel < 0) {
+ $exception = new OutOfRangeException(PartKeepr::i18n("Minimum Stock Level is out of range"));
+ $exception->setDetail(PartKeepr::i18n("The minimum stock level must be 0 or higher"));
+ throw $exception;
+ }
+ $this->minStockLevel = $minStockLevel;
+ }
+
+ /**
+ * Sets the category for this part
+ * @param \PartKeepr\PartCategory\PartCategory $category The category
+ */
+ public function setCategory (PartCategory $category) {
+ $this->category = $category;
+ }
+
+ /**
+ * Returns the assigned category
+ * @return \PartKeepr\PartCategory\PartCategory
+ */
+ public function getCategory () {
+ return $this->category;
+ }
+
+ /**
+ * Returns all projects this part is used
+ * @return ArrayCollection the projects
+ */
+ public function getProjects () {
+ return $this->projects;
+ }
+
+ /**
+ * Sets the storage location for this part
+ * @param \PartKeepr\StorageLocation\StorageLocation $storageLocation The storage location
+ */
+ public function setStorageLocation (StorageLocation $storageLocation) {
+ $this->storageLocation = $storageLocation;
+ }
+
+ /**
+ * Returns the storage location for this part
+ * @return \PartKeepr\StorageLocation\StorageLocation $storageLocation The storage location
+ */
+ public function getStorageLocation () {
+ return $this->storageLocation;
+ }
+
+ /**
+ * Sets the footprint for this part
+ * @param \PartKeepr\Footprint\Footprint $footprint The footprint to set
+ */
+ public function setFootprint (Footprint $footprint = null) {
+ $this->footprint = $footprint;
+ }
+
+ /**
+ * Sets the comment for this part
+ * @param string $comment The comment for this part
+ */
+ public function setComment ($comment) {
+ $this->comment = $comment;
+ }
+
+ /**
+ * Returns the comment for this part
+ * @return string The comment
+ */
+ public function getComment () {
+ return $this->comment;
+ }
+
+ /**
+ * Returns the distributors array
+ * @return ArrayCollection the distributors
+ */
+ public function getDistributors () {
+ return $this->distributors;
+ }
+
+ /**
+ * Returns the part images array
+ * @return ArrayCollection the part images
+ */
+ public function getImages () {
+ return $this->images;
+ }
+
+ /**
+ * Returns the part attachments array
+ * @return ArrayCollection the part attachments
+ */
+ public function getAttachments () {
+ return $this->attachments;
+ }
+
+ /**
+ * Returns the manufacturers array
+ * @return ArrayCollection the manufactuers
+ */
+ public function getManufacturers () {
+ return $this->manufacturers;
+ }
+
+ /**
+ * Returns the parameters assigned to this part
+ * @return array An array of PartParameter objects
+ */
+ public function getParameters () {
+ return $this->parameters;
+ }
+
+ /**
+ * Returns the stock level of this part. This is a realtime function which
+ * actually creates a query over the StockEntry table.
+ * @return int The stock level
+ */
+ public function getStockLevel () {
+ $query = PartKeepr::getEM()->createQuery("SELECT SUM(s.stockLevel) FROM PartKeepr\Stock\StockEntry s WHERE s.part = :part");
+ $query->setParameter("part", $this);
+
+ return $query->getSingleScalarResult();
+ }
+
+ /**
+ * Sets the create date for this part
+ * @param \DateTime $dateTime The create date+time
+ */
+ private function setCreateDate (\DateTime $dateTime) {
+ $this->createDate = $dateTime;
+ }
+
+ /**
+ * Returns the create date
+ * @return \DateTime The create date+time
+ */
+ public function getCreateDate () {
+ return $this->createDate;
+ }
+
+ /**
+ * Sets the status for this part. A status is any string describing the status,
+ * e.g. "new", "used", "broken" etc.
+ * @param string $status The status
+ */
+ public function setStatus ($status) {
+ $this->status = $status;
+ }
+
+ /**
+ * Returns the status for this part.
+ * @return string The status
+ */
+ public function getStatus () {
+ return $this->status;
+ }
+
+ public function updateCacheData () {
+ $this->updateStockLevel();
+ $this->updatePrice();
+ }
+
+ /**
+ * Updates the average price for a part
+ */
+ public function updatePrice () {
+ $query = PartKeepr::getEM()->createQuery("SELECT SUM(se.price*se.stockLevel) / SUM(se.stockLevel) FROM PartKeepr\Stock\StockEntry se WHERE se.part = :part AND se.stockLevel > 0");
+ $query->setParameter("part", $this);
+ $val = $query->getSingleScalarResult();
+
+ $query = PartKeepr::getEM()->createQuery('UPDATE PartKeepr\Part\Part p SET p.averagePrice = :val WHERE p = :part');
+ $query->setParameter("val", $val);
+ $query->setParameter("part", $this);
+ $query->execute();
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Util.Serializable::serialize()
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "name" => $this->getName(),
+ "description" => $this->getDescription(),
+ "comment" => $this->getComment(),
+ "stockLevel" => $this->getStockLevel(),
+ "footprint" => is_object($this->footprint) ? $this->footprint->getId() : null,
+ "minStockLevel" => $this->minStockLevel,
+ "status" => $this->getStatus(),
+ "storageLocation" => is_object($this->storageLocation) ? $this->storageLocation->getId() : null,
+ "category" => is_object($this->category) ? $this->category->getId() : null,
+ "partUnit" => is_object($this->partUnit) ? $this->getPartUnit()->getId() : null,
+ "manufacturers" => $this->serializeChildren($this->getManufacturers()),
+ "distributors" => $this->serializeChildren($this->getDistributors()),
+ "images" => $this->serializeChildren($this->getImages()),
+ "attachments" => $this->serializeChildren($this->getAttachments()),
+ "parameters" => $this->serializeChildren($this->getParameters()),
+ "createDate" => $this->getCreateDate()->format("Y-m-d H:i:s"),
+ "needsReview" => $this->getReviewFlag(),
+ "internalPartNumber" => $this->getInternalPartNumber(),
+ // Additional things we serialize to make displaying stuff in the frontend easier
+ "categoryName" => is_object($this->category) ? $this->category->getName() : null,
+ "footprintName" => is_object($this->footprint) ? $this->footprint->getName() : null,
+ "storageLocationName" => is_object($this->storageLocation) ? $this->storageLocation->getName() : null
+ );
+ }
+
+ /**
+ * Deserializes the part
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "name":
+ $this->setName($value);
+ break;
+ case "description":
+ $this->setDescription($value);
+ break;
+ case "comment":
+ $this->setComment($value);
+ break;
+ case "internalPartNumber":
+ $this->setInternalPartNumber($value);
+ break;
+ case "footprint":
+ if ($value === 0) {
+ $this->setFootprint(null);
+ } else {
+ try {
+ $footprint = Footprint::loadById($value);
+ $this->setFootprint($footprint);
+ } catch (\Exception $e) {
+ // No footprint was found. Ignore it.
+ }
+ }
+ break;
+ case "minStockLevel":
+ $this->setMinStockLevel($value);
+ break;
+ case "partUnit":
+ $partUnit = PartUnit::loadById($value);
+ $this->setPartUnit($partUnit);
+ break;
+ case "category":
+ $category = PartCategory::loadById($value);
+ $this->setCategory($category);
+ break;
+ case "status":
+ $this->setStatus($value);
+ break;
+ case "storageLocation":
+ $storageLocation = StorageLocation::loadById($value);
+ $this->setStorageLocation($storageLocation);
+ break;
+ case "manufacturers":
+ $this->deserializeChildren($value, $this->getManufacturers(), "PartKeepr\Part\PartManufacturer");
+ foreach ($this->getManufacturers() as $manufacturer) {
+ $manufacturer->setPart($this);
+ }
+ break;
+ case "distributors":
+ $this->deserializeChildren($value, $this->getDistributors(), "PartKeepr\Part\PartDistributor");
+ foreach ($this->getDistributors() as $distributor) {
+ $distributor->setPart($this);
+ }
+ break;
+ case "parameters":
+ $this->deserializeChildren($value, $this->getParameters(), "PartKeepr\PartParameter\PartParameter");
+ foreach ($this->getParameters() as $parameter) {
+ $parameter->setPart($this);
+ }
+ break;
+ case "needsReview":
+ $this->setReviewFlag($value);
+ break;
+ case "attachments":
+ $this->deserializeChildren($value, $this->getAttachments(), "PartKeepr\Part\PartAttachment");
+ foreach ($this->getAttachments() as $attachment) {
+ $attachment->setPart($this);
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * Checks if the part category is set.
+ *
+ * @throws CategoryNotAssignedException
+ */
+ private function checkCategoryConsistency () {
+ if ($this->getCategory() === null) {
+ throw new CategoryNotAssignedException($this);
+ }
+ }
+
+ /**
+ * Checks if the part storage location is set.
+ *
+ * @throws StorageLocationNotAssignedException
+ */
+ private function checkStorageLocationConsistency () {
+ if ($this->getStorageLocation() === null) {
+ throw new StorageLocationNotAssignedException();
+ }
+ }
+
+ /**
+ * Checks if the requirements for database persisting are given.
+ *
+ * @throws CategoryNotAssignedException Thrown if no category is set
+ * @throws StorageLocationNotAssignedException Thrown if no storage location is set
+ *
+ * @PrePersist
+ */
+ public function onPrePersist () {
+ $this->checkCategoryConsistency();
+ $this->checkStorageLocationConsistency();
+ }
+
+ /**
+ *
+ * Checks if the requirements for database persisting are given.
+ *
+ * For a list of exceptions, see
+ * @see PartKeepr\Part.Part::onPrePersist()
+ *
+ * @PreUpdate */
+ public function onPreUpdate () {
+ $this->checkCategoryConsistency();
+ $this->checkStorageLocationConsistency();
+ }
+
+ /**
+ * Returns a string representation of the part
+ *
+ * @param none
+ * @return string The name and the ID of the part
+ */
+ public function __toString () {
+ return $this->getName() . " (".$this->getId().")";
+ }
+
+}
diff --git a/src/backend/PartKeepr/Part/PartAttachment.php b/src/backend/PartKeepr/Part/PartAttachment.php
@@ -0,0 +1,129 @@
+<?php
+namespace PartKeepr\Part;
+
+use PartKeepr\Util\Deserializable,
+ PartKeepr\Util\Serializable,
+ PartKeepr\UploadedFile\UploadedFile;
+
+/**
+ * Holds a part attachment
+ * @Entity
+ **/
+class PartAttachment extends UploadedFile implements Serializable, Deserializable {
+ /**
+ * The description of this attachment
+ * @Column(type="text")
+ * @var string
+ */
+ private $description;
+
+ /**
+ * Creates a new part attachment
+ */
+ public function __construct () {
+ parent::__construct();
+ $this->setType("PartAttachment");
+ }
+
+ /**
+ * The part object
+ * @ManyToOne(targetEntity="PartKeepr\Part\Part")
+ * @var Part
+ */
+ private $part = null;
+
+ /**
+ * Sets the part
+ * @param Part $part The part to set
+ */
+ public function setPart (Part $part) {
+ $this->part = $part;
+ }
+
+ /**
+ * Returns the part
+ * @return Part the part
+ */
+ public function getPart () {
+ return $this->part;
+ }
+
+ /**
+ * Sets the description for this attachment
+ * @param string $description The attachment description
+ */
+ public function setDescription ($description) {
+ $this->description = $description;
+ }
+
+ /**
+ * Returns the description for this attachment
+ * @return string The description
+ */
+ public function getDescription () {
+ return $this->description;
+ }
+
+ /**
+ *
+ * Serializes this part attachment
+ * @return array The serialized part attachment
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "part_id" => $this->getPart()->getId(),
+ "originalFilename" => $this->getOriginalFilename(),
+ "mimetype" => $this->getMimetype(),
+ "extension" => $this->getExtension(),
+ "size" => $this->getSize(),
+ "description" => $this->getDescription(),
+ "image" => $this->isImage());
+ }
+
+ /**
+ * Deserializes the part attachment
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ if (array_key_exists("id", $parameters)) {
+ if (substr($parameters["id"], 0, 4) === "TMP:") {
+ $this->replaceFromTemporaryFile($parameters["id"]);
+ }
+ }
+
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "description":
+ $this->setDescription($value);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Returns if the attachment is an image or not.
+ *
+ * Ths method uses ImageMagick to find out if this is an image. Limitations apply; if ImageMagick doesn't support
+ * the image format, this method would return false, even if it is an image.
+ *
+ * @return True if the attachment is an image, false otherwise
+ */
+ public function isImage () {
+ /**
+ * Special case: Check if it's a PDF. If yes, return immediately.
+ * This is because ImageMagick outputs warning messages for malformed PDF files, and halts the execution
+ * of the script for several seconds. DO NOT REMOVE!
+ */
+ if ($this->getMimeType() == "application/pdf") {
+ return false;
+ }
+
+ try {
+ $im = new \Imagick($this->getFilename());
+ return true;
+ } catch (\ImagickException $e) {
+ return false;
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Part/PartDistributor.php b/src/backend/PartKeepr/Part/PartDistributor.php
@@ -0,0 +1,220 @@
+<?php
+namespace PartKeepr\Part;
+
+use PartKeepr\Util\Deserializable,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Util\BaseEntity,
+ PartKeepr\PartKeepr,
+ PartKeepr\Distributor\Distributor;
+
+/**
+ * This class represents the link between a part and a distributor.
+ * @Entity **/
+class PartDistributor extends BaseEntity implements Serializable, Deserializable {
+ /**
+ * @ManyToOne(targetEntity="PartKeepr\Part\Part")
+ */
+ private $part;
+
+ /**
+ * @ManyToOne(targetEntity="PartKeepr\Distributor\Distributor")
+ */
+ private $distributor;
+
+ /**
+ * The order number for the part and distributor
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $orderNumber;
+
+ /**
+ * Defines the packaging unit when ordering a part. Some items can't be ordered in a quantity of just one at
+ * certain manufacturers.
+ *
+ * @Column(type="integer")
+ * @var integer
+ */
+ private $packagingUnit;
+
+ /**
+ * Specifies the price of the part. Note that the price
+ * needs to be per item, not per packaging unit.
+ *
+ * @Column(type="decimal",precision=13,scale=4,nullable=true)
+ * @var float
+ */
+ private $price;
+
+ /**
+ * The distributor's SKU (stock keeping unit) for the part. Used with barcodes.
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $sku;
+
+ /**
+ * Cretes a new part->distributor link. Initializes the packaging unit with a quantity of "1".
+ *
+ * @param Part $part The part
+ * @param Distributor $distributor The distributor
+ */
+ public function __construct () {
+ $this->setPackagingUnit(1);
+ }
+
+ /**
+ * Sets the packaging unit for a specific distributor.
+ *
+ * For example, some distributors only sell resistors in packs of 100, so you can't order just one. We use the
+ * packagingUnit to calculate how many pieces will be delivered once ordered. So if your stock level falls below
+ * the minimum (example: you would need to order 10 resistors), we suggest that you only order one resistor pack
+ * instead of 10.
+ *
+ * @param int $packagingUnit The amount of items in one package
+ * @throws \PartKeepr\Part\OutOfRangeException When the packaging unit is less than 1
+ */
+ public function setPackagingUnit ($packagingUnit) {
+ $packagingUnit = intval($packagingUnit);
+
+ if ($packagingUnit < 1) {
+ $exception = new OutOfRangeException(PartKeepr::i18n("Packaging Unit is out of range"));
+ $exception->setDetail(PartKeepr::i18n("The packaging unit must be 1 or higher"));
+ throw $exception;
+ }
+
+ $this->packagingUnit = $packagingUnit;
+ }
+
+ /**
+ * Returns the packaging unit
+ * @return int The packaging unit
+ */
+ public function getPackagingUnit () {
+ return $this->packagingUnit;
+ }
+
+ /**
+ * Sets the part
+ * @param Part $part The part
+ */
+ public function setPart (Part $part) {
+ $this->part = $part;
+ }
+
+ /**
+ * Returns the part
+ * @return Part The part
+ */
+ public function getPart () {
+ return $this->part;
+ }
+
+ /**
+ * Sets the distributor
+ * @param Distributor $distributor The distributor
+ */
+ public function setDistributor (Distributor $distributor) {
+ $this->distributor = $distributor;
+ }
+
+ /**
+ * Returns the distributor
+ * @return Distributor The distributor
+ */
+ public function getDistributor () {
+ return $this->distributor;
+ }
+
+ /**
+ * Sets the order number
+ * @param string $orderNumber The order number
+ */
+ public function setOrderNumber ($orderNumber) {
+ $this->orderNumber = $orderNumber;
+ }
+
+ /**
+ * Returns the order number
+ * @return string The order number
+ */
+ public function getOrderNumber () {
+ return $this->orderNumber;
+ }
+
+ /**
+ * Sets the price
+ * @param float $price
+ */
+ public function setPrice ($price) {
+ echo "/** price set to ".$price." **/";
+ $this->price = $price;
+ }
+
+ /**
+ * Returns the price
+ */
+ public function getPrice () {
+ return $this->price;
+ }
+
+ /**
+ * Sets the SKU (stock keeping unit)
+ * @param string $sku The SKU
+ */
+ public function setSKU ($sku) {
+ $this->sku = $sku;
+ }
+
+ /**
+ * Returns the SKU (stock keeping unit)
+ * @return string The SKU
+ */
+ public function getSKU () {
+ return $this->sku;
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Util.Serializable::serialize()
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "orderNumber" => $this->getOrderNumber(),
+ "distributor_id" => $this->getDistributor()->getId(),
+ "distributor_name" => $this->getDistributor()->getName(),
+ "part_id" => $this->getPart()->getId(),
+ "part_name" => $this->getPart()->getName(),
+ "packagingUnit" => $this->getPackagingUnit(),
+ "price" => $this->getPrice(),
+ "sku" => $this->getSKU());
+ }
+
+ /**
+ * Deserializes the part manufacturer
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "distributor_id":
+ $distributor = Distributor::loadById($value);
+ $this->setDistributor($distributor);
+ break;
+ case "orderNumber":
+ $this->setOrderNumber($value);
+ break;
+ case "packagingUnit":
+ $this->setPackagingUnit($value);
+ break;
+ case "price":
+ $this->setPrice($value);
+ break;
+ case "sku":
+ $this->setSKU($value);
+ break;
+ }
+ }
+ }
+}
diff --git a/src/backend/PartKeepr/Part/PartFulltextSearch.php b/src/backend/PartKeepr/Part/PartFulltextSearch.php
@@ -0,0 +1,29 @@
+<?php
+namespace PartKeepr\Part;
+
+use PartKeepr\FulltextSearch\FulltextSearch;
+
+/**
+ * Implements the part fulltext search
+ */
+class PartFulltextSearch extends FulltextSearch {
+ /**
+ * Returns the FQDN of the part entity
+ *
+ * (non-PHPdoc)
+ * @see PartKeepr\FulltextSearch.FulltextSearch::getEntityName()
+ */
+ protected function getEntityName () {
+ return 'PartKeepr\Part\Part';
+ }
+
+ /**
+ * Returns the fields to be searched in
+ *
+ * (non-PHPdoc)
+ * @see PartKeepr\FulltextSearch.FulltextSearch::getFields()
+ */
+ protected function getFields () {
+ return array("comment", "name", "description", "internalPartNumber");
+ }
+}
diff --git a/src/backend/PartKeepr/Part/PartImage.php b/src/backend/PartKeepr/Part/PartImage.php
@@ -0,0 +1,50 @@
+<?php
+namespace PartKeepr\Part;
+
+use PartKeepr\Util\Serializable,
+ PartKeepr\Image\Image;
+
+/**
+ * Holds a part image
+ * @Entity
+ **/
+class PartImage extends Image implements Serializable {
+ /**
+ * The part object
+ * @ManyToOne(targetEntity="PartKeepr\Part\Part")
+ * @var Part
+ */
+ private $part = null;
+
+ /**
+ * Creates a new part image instance
+ */
+ public function __construct () {
+ parent::__construct(Image::IMAGE_PART);
+ }
+
+ /**
+ * Sets the part
+ * @param Part $part The part to set
+ */
+ public function setPart (Part $part) {
+ $this->part = $part;
+ }
+
+ /**
+ * Returns the part
+ * @return Part the part
+ */
+ public function getPart () {
+ return $this->part;
+ }
+
+ /**
+ *
+ * Serializes this part image
+ * @return array The serialized part imaage
+ */
+ public function serialize () {
+ return array("id" => $this->getId(), "part_id" => $this->getPart()->getId());
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Part/PartManager.php b/src/backend/PartKeepr/Part/PartManager.php
@@ -0,0 +1,441 @@
+<?php
+namespace PartKeepr\Part;
+
+use PartKeepr\Logger\Logger;
+
+use PartKeepr\UploadedFile\TempUploadedFile,
+ PartKeepr\Manager\ManagerFilter,
+ Doctrine\ORM\QueryBuilder,
+ PartKeepr\PartParameter\PartParameter,
+ PartKeepr\Manager\AbstractManager,
+ PartKeepr\Unit\Unit,
+ PartKeepr\SiPrefix\SiPrefix,
+ PartKeepr\Part\PartDistributor,
+ PartKeepr\Part\PartManufacturer,
+ PartKeepr\StorageLocation\StorageLocation,
+ PartKeepr\StorageLocation\StorageLocationManager,
+ PartKeepr\Part\Part,
+ Doctrine\ORM\Query,
+ PartKeepr\PartUnit\PartUnitManager,
+ PartKeepr\Distributor\Distributor,
+ PartKeepr\Manufacturer\Manufacturer,
+ PartKeepr\Footprint\FootprintManager,
+ PartKeepr\Session\SessionManager,
+ PartKeepr\Stock\StockEntry,
+ PartKeepr\Util\Singleton,
+ PartKeepr\Footprint\Footprint,
+ PartKeepr\PartKeepr,
+ PartKeepr\PartCategory\PartCategoryManager,
+ PartKeepr\Manufacturer\ManufacturerManager;
+
+class PartManager extends AbstractManager {
+
+ /**
+ * Returns the FQCN for the target entity to operate on.
+ * @return string The FQCN, e.g. PartKeepr\Part
+ */
+ public function getEntityName () {
+ return 'PartKeepr\Part\Part';
+ }
+
+ /**
+ * Returns all fields which need to appear in the getList ResultSet.
+ * @return array An array of all fields which should be returned
+ */
+ public function getQueryFields () {
+ return array("name", "description", "averagePrice", "status", "needsReview", "createDate", "id", "stockLevel",
+ "minStockLevel", "comment", "st.id AS storageLocation_id", "c.categoryPath AS categoryPath",
+ "st.name as storageLocationName", "f.id AS footprint_id", "f.name AS footprintName",
+ "c.id AS category", "c.name AS categoryName", "pu.id AS partUnit", "pu.name AS partUnitName",
+ "pu.is_default AS partUnitDefault"
+ );
+ }
+
+ /**
+ * Returns the default sort field
+ *
+ * @return string The default sort field
+ */
+ public function getDefaultSortField () {
+ return "dateTime";
+ }
+
+ /**
+ * Appends various join tables to the result set
+ *
+ * (non-PHPdoc)
+ * @see PartKeepr\Manager.AbstractManager::applyCustomQuery()
+ */
+ protected function applyCustomQuery (QueryBuilder $qb, ManagerFilter $filter) {
+ /**
+ * Pull in additional tables
+ */
+ $qb ->join("q.storageLocation", "st")
+ ->leftJoin("q.footprint", "f")
+ ->join("q.category", "c")
+ ->leftJoin("q.partUnit", "pu");
+
+ // Apply special handling for non-direct fields in relations, where the frontend has no idea about.
+ foreach ($filter->getSorters() as $sorter) {
+ switch ($sorter->getSortField()) {
+ case "q.categoryPath":
+ $sorter->setSortField("c.categoryPath");
+ break;
+ case "q.storageLocationName":
+ $sorter->setSortField("st.name");
+ break;
+ case "q.footprintName":
+ $sorter->setSortField("f.name");
+ break;
+ default:
+ break;
+ }
+ }
+
+ }
+
+ /**
+ * Processes the result after it was retrieved. In the default configuration, it returns an array result, or
+ * if no query fields are specified, it tries to serialize all objects.
+ */
+ protected function getResult (Query $query) {
+ $result = parent::getResult($query);
+
+ /* Add attachment counts to the result set and re-format the date */
+ foreach ($result as $key => $item) {
+ $dql = "SELECT COUNT(pa) FROM PartKeepr\Part\PartAttachment pa WHERE pa.part = :part";
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("part", $item["id"]);
+
+ $result[$key]["attachmentCount"] = $query->getSingleScalarResult();
+
+ $result[$key]["createDate"] = $result[$key]["createDate"]->format("Y-m-d H:i:s");
+ }
+
+ foreach ($result as $key => $item) {
+ $dql = "SELECT pr.name FROM PartKeepr\Project\Project pr JOIN pr.parts ppart WHERE ppart.part = :part";
+
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("part", $item["id"]);
+
+ $projectNames = array();
+ foreach ($query->getArrayResult() as $project) {
+ $projectNames[] = $project["name"];
+ }
+
+ $result[$key]["projects"] = implode(", ", $projectNames);
+
+ }
+
+ foreach ($result as $key => $item) {
+ $part = Part::loadById($item["id"]);
+ $result[$key]["attachments"] = $part->serializeChildren($part->getAttachments());
+ }
+
+ return $result;
+ }
+
+ public function addOrUpdatePart ($aParameters) {
+
+ if (!array_key_exists("quantity", $aParameters)) {
+ $aParameters["quantity"] = 0;
+ }
+
+ if ($aParameters["part"] !== null) {
+ try {
+ $part = $this->getPart($aParameters["part"]);
+ } catch (\Exception $e) {
+ $part = new Part();
+ $user = SessionManager::getCurrentSession()->getUser();
+
+ $stock = new StockEntry($part, $aParameters["quantity"], $user);
+ PartKeepr::getEM()->persist($stock);
+ }
+ } else {
+ $part = new Part();
+
+ $user = SessionManager::getCurrentSession()->getUser();
+
+ $stock = new StockEntry($part, $aParameters["quantity"], $user);
+ PartKeepr::getEM()->persist($stock);
+ }
+
+ if (array_key_exists("name", $aParameters)) {
+ $part->setName($aParameters["name"]);
+ }
+
+ if (array_key_exists("description", $aParameters)) {
+ $part->setDescription($aParameters["description"]);
+ }
+
+ if (array_key_exists("minstock", $aParameters)) {
+ $part->setMinStockLevel($aParameters["minstock"]);
+ }
+
+ if (array_key_exists("comment", $aParameters)) {
+ $part->setComment($aParameters["comment"]);
+ }
+
+ if (array_key_exists("footprint", $aParameters)) {
+
+ if ($aParameters["footprint"] === null) {
+ $part->setFootprint(null);
+ } else {
+ $footprint = FootprintManager::getInstance()->getOrCreateFootprint($aParameters["footprint"]);
+ $part->setFootprint($footprint);
+ }
+ }
+
+ if (array_key_exists("storagelocation", $aParameters)) {
+ $storageLocation = StorageLocationManager::getInstance()->getOrCreateStorageLocation($aParameters["storagelocation"]);
+ $part->setStorageLocation($storageLocation);
+ }
+
+ if (array_key_exists("category", $aParameters)) {
+ $category = PartCategoryManager::getInstance()->getCategory($aParameters["category"]);
+ $part->setCategory($category->getNode());
+ }
+
+ /* Process linked changes */
+ if (array_key_exists("distributorChanges", $aParameters)) {
+ if (is_array($aParameters["distributorChanges"])) {
+ $this->processDistributorChanges($part, $aParameters["distributorChanges"]);
+ }
+ }
+
+ if (array_key_exists("manufacturerChanges", $aParameters)) {
+ if (is_array($aParameters["manufacturerChanges"])) {
+ $this->processManufacturerChanges($part, $aParameters["manufacturerChanges"]);
+ }
+ }
+
+ if (array_key_exists("parameterChanges", $aParameters)) {
+ if (is_array($aParameters["parameterChanges"])) {
+ $this->processParameterChanges($part, $aParameters["parameterChanges"]);
+ }
+ }
+
+ if (array_key_exists("attachmentChanges", $aParameters)) {
+ if (is_array($aParameters["attachmentChanges"])) {
+ $this->processAttachmentChanges($part, $aParameters["attachmentChanges"]);
+ }
+ }
+
+ if (array_key_exists("partUnit", $aParameters)) {
+ if ($aParameters["partUnit"] === null || $aParameters["partUnit"] === 0) {
+ $part->setPartUnit(null);
+ } else {
+ $part->setPartUnit(PartUnitManager::getInstance()->getPartUnit($aParameters["partUnit"]));
+ }
+ }
+
+
+ PartKeepr::getEM()->persist($part);
+ PartKeepr::getEM()->flush();
+
+ }
+
+ private function processParameterChanges (Part $part, Array $data) {
+ if (array_key_exists("updates", $data)) {
+ foreach ($data["updates"] as $record) {
+ foreach ($part->getParameters() as $partParameter) {
+ if ($partParameter->getId() == $record["id"]) {
+ $partParameter->setName($record["name"]);
+ $partParameter->setDescription($record["description"]);
+ $partParameter->setValue($record["value"]);
+ $partParameter->setSiPrefix(SiPrefix::loadById($record["siprefix_id"]));
+ $partParameter->setUnit(Unit::loadById($record["unit_id"]));
+ break;
+ }
+ }
+ }
+ }
+
+ if (array_key_exists("removals", $data)) {
+ foreach ($data["removals"] as $record) {
+ foreach ($part->getParameters() as $partParameter) {
+ if ($partParameter->getId() == $record["id"]) {
+ PartKeepr::getEM()->remove($partParameter);
+ $part->getParameters()->removeElement($partParameter);
+ break;
+ }
+ }
+ }
+ }
+
+ if (array_key_exists("inserts", $data)) {
+ foreach ($data["inserts"] as $record) {
+ $partParameter = new PartParameter();
+ $partParameter->setPart($part);
+
+ $partParameter->setName($record["name"]);
+ $partParameter->setDescription($record["description"]);
+ $partParameter->setValue($record["value"]);
+ $partParameter->setSiPrefix(SiPrefix::loadById($record["siprefix_id"]));
+ $partParameter->setUnit(Unit::loadById($record["unit_id"]));
+
+ $part->getParameters()->add($partParameter);
+ }
+ }
+ }
+
+ private function processDistributorChanges (Part $part, Array $data) {
+ if (array_key_exists("updates", $data)) {
+ foreach ($data["updates"] as $record) {
+ foreach ($part->getDistributors() as $partDistributor) {
+ if ($partDistributor->getId() == $record["id"]) {
+ $partDistributor->setOrderNumber($record["orderNumber"]);
+ $partDistributor->setDistributor(Distributor::loadById($record["distributor_id"]));
+ $partDistributor->setPackagingUnit($record["packagingUnit"]);
+ break;
+ }
+ }
+ }
+ }
+
+ if (array_key_exists("removals", $data)) {
+ foreach ($data["removals"] as $record) {
+ foreach ($part->getDistributors() as $partDistributor) {
+ if ($partDistributor->getId() == $record["id"]) {
+ PartKeepr::getEM()->remove($partDistributor);
+ $part->getDistributors()->removeElement($partDistributor);
+ break;
+ }
+ }
+ }
+ }
+
+ if (array_key_exists("inserts", $data)) {
+ foreach ($data["inserts"] as $record) {
+ $distributor = new PartDistributor($part, Distributor::loadById($record["distributor_id"]));
+ $distributor->setOrderNumber($record["orderNumber"]);
+ $distributor->setPackagingUnit($record["packagingUnit"]);
+
+ $part->getDistributors()->add($distributor);
+ }
+ }
+ }
+
+ private function processManufacturerChanges (Part $part, Array $data) {
+ if (array_key_exists("updates", $data)) {
+ foreach ($data["updates"] as $record) {
+ foreach ($part->getManufacturers() as $partManufacturer) {
+ if ($partManufacturer->getId() == $record["id"]) {
+ $partManufacturer->setPartNumber($record["partNumber"]);
+ $partManufacturer->setManufacturer(Manufacturer::loadById($record["manufacturer_id"]));
+ break;
+ }
+ }
+ }
+ }
+
+ if (array_key_exists("removals", $data)) {
+ foreach ($data["removals"] as $record) {
+ foreach ($part->getManufacturers() as $partManufacturer) {
+ if ($partManufacturer->getId() == $record["id"]) {
+ PartKeepr::getEM()->remove($partManufacturer);
+ $part->getManufacturers()->removeElement($partManufacturer);
+ break;
+ }
+ }
+ }
+ }
+
+ if (array_key_exists("inserts", $data)) {
+ foreach ($data["inserts"] as $record) {
+ $manufacturer = new PartManufacturer($part, Manufacturer::loadById($record["manufacturer_id"]));
+ $manufacturer->setPartNumber($record["partNumber"]);
+
+ $part->getManufacturers()->add($manufacturer);
+ }
+ }
+ }
+
+ private function processAttachmentChanges (Part $part, Array $data) {
+ if (array_key_exists("updates", $data)) {
+ foreach ($data["updates"] as $record) {
+ foreach ($part->getAttachments() as $partAttachment) {
+ if ($partAttachment->getId() == $record["id"]) {
+ $partAttachment->setDescription($record["description"]);
+ break;
+ }
+ }
+ }
+ }
+
+ if (array_key_exists("removals", $data)) {
+ foreach ($data["removals"] as $record) {
+ foreach ($part->getAttachments() as $partAttachment) {
+ if ($partAttachment->getId() == $record["id"]) {
+ PartKeepr::getEM()->remove($partAttachment);
+ $part->getAttachments()->removeElement($partAttachment);
+ break;
+ }
+ }
+ }
+ }
+
+ if (array_key_exists("inserts", $data)) {
+ foreach ($data["inserts"] as $record) {
+ $attachment = new PartAttachment();
+ $attachment->setPart($part);
+ $attachment->setDescription($record["description"]);
+
+ $file = TempUploadedFile::loadById($record["tmp_id"]);
+
+ $attachment->replace($file->getFilename());
+ $attachment->setOriginalFilename($file->getOriginalFilename());
+
+ $part->getAttachments()->add($attachment);
+ }
+ }
+ }
+
+ public function deletePart ($id) {
+ $part = PartManager::getInstance()->getPart($id);
+
+ PartKeepr::getEM()->remove($part);
+ PartKeepr::getEM()->flush();
+ }
+
+ public function getPart ($id) {
+ $part = PartKeepr::getEM()->find("PartKeepr\Part\Part", $id);
+
+ return $part;
+ }
+
+ /**
+ * Returns the overall part count currently existing.
+ * @param boolean $withPrice Only consider parts with a price
+ * @return int The amount of parts in the database
+ */
+ public function getPartCount ($withPrice = false) {
+ $dql = "SELECT COUNT(p.id) FROM PartKeepr\Part\Part p";
+
+ if ($withPrice === true) {
+ $dql .= " WHERE p.averagePrice IS NOT NULL";
+ }
+
+ return PartKeepr::getEM()->createQuery($dql)->getSingleScalarResult();
+ }
+
+ /**
+ * Returns the total price for all parts. Only parts with a price are calculated.
+ * @return float The total price
+ */
+ public function getTotalPrice () {
+ $dql = "SELECT SUM(p.averagePrice * p.stockLevel) FROM PartKeepr\Part\Part p";
+
+ return PartKeepr::getEM()->createQuery($dql)->getSingleScalarResult();
+ }
+
+ /**
+ * Returns the average price for all parts. Only parts with a price are calculated.
+ * @return float The average price
+ */
+ public function getAveragePrice () {
+ $dql = "SELECT AVG(p.averagePrice) FROM PartKeepr\Part\Part p";
+
+ return PartKeepr::getEM()->createQuery($dql)->getSingleScalarResult();
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Part/PartManufacturer.php b/src/backend/PartKeepr/Part/PartManufacturer.php
@@ -0,0 +1,106 @@
+<?php
+namespace PartKeepr\Part;
+
+use PartKeepr\Util\Deserializable,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Util\BaseEntity,
+ PartKeepr\PartKeepr,
+ PartKeepr\Manufacturer\Manufacturer;
+
+/** @Entity **/
+class PartManufacturer extends BaseEntity implements Serializable, Deserializable {
+ /**
+ * @ManyToOne(targetEntity="PartKeepr\Part\Part")
+ */
+ private $part;
+
+ /**
+ * @ManyToOne(targetEntity="PartKeepr\Manufacturer\Manufacturer")
+ */
+ private $manufacturer;
+
+ /**
+ * @Column(type="string",nullable=true)
+ * Enter description here ...
+ * @var unknown_type
+ */
+ private $partNumber;
+
+ /**
+ * Sets the part which belongs to this manufacturer entry
+ * @param Part $part
+ */
+ public function setPart (Part $part) {
+ $this->part = $part;
+ }
+
+ /**
+ * Returns the part which belongs to this manufacturer entry
+ */
+ public function getPart () {
+ return $this->part;
+ }
+
+ /**
+ * Sets the manufacturer which belongs to this entry
+ * @param Manufacturer $manufacturer
+ */
+ public function setManufacturer (Manufacturer $manufacturer) {
+ $this->manufacturer = $manufacturer;
+ }
+
+ /**
+ * Returns the manufacturer which belongs to this part
+ */
+ public function getManufacturer () {
+ return $this->manufacturer;
+ }
+
+ /**
+ * Sets the manufacturer-specific part number
+ * @param string $partNumber
+ */
+ public function setPartNumber ($partNumber) {
+ $this->partNumber = $partNumber;
+ }
+
+ /**
+ * Returns the manufacturer-specific part number
+ * @return string The part number
+ */
+ public function getPartNumber () {
+ return $this->partNumber;
+ }
+
+ /**
+ * Returns the data of this object in a serialized form.
+ * @return array The result array
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "partNumber" => $this->getPartNumber(),
+ "manufacturer_id" => $this->getManufacturer()->getId(),
+ "manufacturer_name" => $this->getManufacturer()->getName(),
+ "part_id" => $this->getPart()->getId(),
+ "part_name" => $this->getPart()->getName());
+ }
+
+ /**
+ * Deserializes the part manufacturer
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "manufacturer_id":
+ $manufacturer = Manufacturer::loadById($value);
+ $this->setManufacturer($manufacturer);
+ break;
+ case "partNumber":
+ $this->setPartNumber($value);
+ break;
+ }
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Part/PartService.php b/src/backend/PartKeepr/Part/PartService.php
@@ -0,0 +1,262 @@
+<?php
+namespace PartKeepr\Part;
+
+use PartKeepr\User\User,
+ PartKeepr\Service\RestfulService,
+ PartKeepr\Service\Service,
+ PartKeepr\Manager\ManagerFilter,
+ PartKeepr\Part\PartManager,
+ PartKeepr\Stock\StockEntry,
+ PartKeepr\PartKeepr,
+ PartKeepr\PartCategory\PartCategory,
+ PartKeepr\PartCategory\PartCategoryManager,
+ PartKeepr\Session\SessionManager;
+
+class PartService extends Service implements RestfulService {
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return array("data" => PartManager::getInstance()->getPart($this->getParameter("id"))->serialize());
+ } else {
+
+ $filter = new ManagerFilter($this);
+ $filter->setFilterCallback(array($this, "filterCallback"));
+
+ return PartManager::getInstance()->getList($filter);
+ }
+ }
+
+ /**
+ * Advanced filtering for the list
+ * @param QueryBuilder The $queryBuilder
+ */
+ public function filterCallback ($queryBuilder) {
+
+ /**
+ * Applies text-based filtering
+ */
+ if ($this->hasParameter("query") && $this->getParameter("query") != "") {
+
+ $fulltextSearch = new PartFulltextSearch($this->getParameter("query"));
+ $fulltextSearchResults = $fulltextSearch->query();
+
+ $queryBuilder->andWhere("q.id IN (".implode(",", $fulltextSearchResults).")");
+
+ }
+
+ /**
+ * Applies filtering by the storage location name
+ */
+ if ($this->getParameter("storageLocation") !== null) {
+ $queryBuilder->andWhere("st.name = :storageLocation");
+ $queryBuilder->setParameter("storageLocation", $this->getParameter("storageLocation"));
+ }
+
+ /**
+ * Filter by the category id and set the category mode
+ *
+ */
+ $category = intval($this->getParameter("category", 0));
+
+ if ($category !== 0) {
+ /* Fetch all children */
+ if ($this->getParameter("categoryScope") == "selected") {
+ $queryBuilder->andWhere("q.category = :category");
+ $queryBuilder->setParameter("category", $category);
+ } else {
+ $childs = PartCategoryManager::getInstance()->getChildNodes($category);
+ $childs[] = $category;
+ $queryBuilder->andWhere("q.category IN (".implode(",", $childs).")");
+ }
+ }
+
+ /**
+ * Filter by the stock mode
+ */
+ switch ($this->getParameter("stockMode")) {
+ case "all":
+ break;
+ case "zero":
+ $queryBuilder->andWhere("q.stockLevel = 0");
+ break;
+ case "nonzero":
+ $queryBuilder->andWhere("q.stockLevel > 0");
+ break;
+ case "below":
+ $queryBuilder->andWhere("q.stockLevel < q.minStockLevel");
+ break;
+ }
+
+ /**
+ * Query by the distributor's order number
+ */
+ if ($this->getParameter("distributorOrderNumber")) {
+ $queryBuilder->leftJoin("q.distributors", "di");
+ $queryBuilder->andWhere("LOWER(di.orderNumber) LIKE :orderNumber");
+ $queryBuilder->setParameter("orderNumber", "%".strtolower($this->getParameter("distributorOrderNumber"))."%");
+ }
+
+ /**
+ * Filter by the price
+ */
+ if ($this->getParameter("withoutPrice") === true || $this->getParameter("withoutPrice") === "true") {
+ $queryBuilder->andWhere("q.averagePrice IS NULL");
+ }
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::create()
+ */
+ public function create () {
+ $entity = PartManager::getInstance()->createEntity($this->getParameters());
+
+ if ($this->getParameter("initialStockLevel") > 0) {
+ try {
+ $user = User::loadById($this->getParameter("initialStockLevelUser"));
+ } catch (\Exception $e) {
+ $user = SessionManager::getCurrentSession()->getUser();
+ }
+
+ $stock = new StockEntry($entity, intval($this->getParameter("initialStockLevel")), $user);
+
+ if ($this->getParameter("initialStockLevelPricePerItem") == true) {
+ $price = floatval($this->getParameter("initialStockLevelPrice"));
+ } else {
+ $price = floatval($this->getParameter("initialStockLevelPrice")) / $this->getParameter("initialStockLevel");
+ }
+
+ if ($price != 0) {
+ $stock->setPrice($price);
+ }
+
+ PartKeepr::getEM()->persist($stock);
+ PartKeepr::getEM()->flush();
+
+ $entity->updateStockLevel();
+ PartKeepr::getEM()->flush();
+ }
+
+ return array("data" => $entity->serialize());
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::update()
+ */
+ public function update () {
+ $entity = PartManager::getInstance()->getEntity($this->getParameter("id"));
+ $entity->deserialize($this->getParameters());
+
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $entity->serialize());
+ }
+
+
+ public function destroy () {
+ throw new \Exception("Not yet implemented");
+ }
+
+ public function getPartParameterNames () {
+ $dql = "SELECT pp.name FROM PartKeepr\PartParameter\PartParameter pp GROUP BY pp.name";
+ $query = PartKeepr::getEM()->createQuery($dql);
+
+ return array("data" => $query->getArrayResult());
+ }
+
+ public function movePart () {
+ $this->requireParameter("targetCategory");
+
+ if ($this->getParameter("parts", false) !== false) {
+ /* We are moving multiple parts */
+ foreach ($this->getParameter("parts") as $part) {
+ $part = Part::loadById($part);
+ $category = PartCategory::loadById($this->getParameter("targetCategory"));
+
+ $part->setCategory($category);
+ }
+ } else {
+ $part = Part::loadById($this->getParameter("part"));
+ $category = PartCategory::loadById($this->getParameter("targetCategory"));
+
+ $part->setCategory($category);
+
+ }
+
+ PartKeepr::getEM()->flush();
+ }
+
+ public function addStock () {
+ $part = PartManager::getInstance()->getPart($this->getParameter("part"));
+
+ $user = SessionManager::getCurrentSession()->getUser();
+
+ $stock = new StockEntry($part, intval($this->getParameter("stock")), $user);
+
+ $price = floatval($this->getParameter("price"));
+
+ if ($price != 0) {
+ $stock->setPrice($price);
+ }
+
+ if ($this->hasParameter("comment")) {
+ $stock->setComment($this->getParameter("comment"));
+ }
+
+ PartKeepr::getEM()->persist($stock);
+ PartKeepr::getEM()->flush();
+
+ $part->updateStockLevel();
+
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $part->serialize());
+ }
+
+ public function deleteStock () {
+ $part = PartManager::getInstance()->getPart($this->getParameter("part"));
+
+ $user = SessionManager::getCurrentSession()->getUser();
+
+ $stock = new StockEntry($part, 0-intval($this->getParameter("stock")), $user);
+
+ PartKeepr::getEM()->persist($stock);
+ PartKeepr::getEM()->flush();
+
+ $part->updateStockLevel();
+
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $part->serialize());
+ }
+
+ public function massDeleteStock () {
+ $data = $this->getParameter("removals");
+
+ $updateStockLevels = array();
+
+ foreach ($data as $item) {
+ $part = PartManager::getInstance()->getPart($item["part"]);
+ $user = SessionManager::getCurrentSession()->getUser();
+
+ $stock = new StockEntry($part, 0-intval($item["amount"]), $user);
+ $stock->setComment($item["comment"]);
+ PartKeepr::getEM()->persist($stock);
+
+ $updateStockLevels[$item["part"]] = $part;
+ }
+
+ PartKeepr::getEM()->flush();
+
+ foreach ($updateStockLevels as $part) {
+ $part->updateStockLevel();
+ }
+
+ PartKeepr::getEM()->flush();
+ return array();
+ }
+
+ public function deletePart () {
+ PartManager::getInstance()->deletePart($this->getParameter("part"));
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Part/PartUnit.php b/src/backend/PartKeepr/Part/PartUnit.php
@@ -0,0 +1,137 @@
+<?php
+namespace PartKeepr\Part;
+
+use PartKeepr\Util\Deserializable,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Util\BaseEntity,
+ PartKeepr\PartKeepr,
+ PartKeepr\Util\Exceptions\OutOfRangeException;
+
+
+/** @Entity **/
+class PartUnit extends BaseEntity implements Serializable, Deserializable {
+ /**
+ * Defines the name of the unit
+ * @Column
+ * @var string
+ */
+ private $name;
+
+ /**
+ * Defines the short name of the unit
+ * @Column
+ * @var string
+ */
+ private $shortName;
+
+ /**
+ * Defines if the unit is default or not.
+ *
+ * @Column(type="boolean")
+ * @var boolean
+ */
+ private $is_default;
+
+ /**
+ * @OneToMany(targetEntity="PartKeepr\Part\Part",mappedBy="partUnit")
+ */
+ private $parts;
+
+
+ /**
+ * Creates a new part unit.
+ *
+ * Sets the default to false.
+ */
+ public function __construct () {
+ $this->setDefault(false);
+ }
+
+ /**
+ * Sets the name for this unit
+ * @param string $name The name for this unit
+ * @return nothing
+ */
+ public function setName ($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the name for this unit
+ * @param none
+ * @return string The name for this unit
+ */
+ public function getName () {
+ return $this->name;
+ }
+
+ /**
+ * Sets the short name for this unit.
+ *
+ * Short names are used for list views (e.g. if your unit name is "metres", your short name could be "m")
+ * @param string $shortName The short name
+ * @return nothing
+ */
+ public function setShortName ($shortName) {
+ $this->shortName = $shortName;
+ }
+
+ /**
+ * Returns the short name for this unit
+ * @param none
+ * @return string The short name for this unit
+ */
+ public function getShortName () {
+ return $this->shortName;
+ }
+
+ /**
+ * Defines if the unit is default or not.
+ * @param boolean $default True if the unit is default, false otherwise
+ */
+ public function setDefault ($default) {
+ $this->is_default = (bool)$default;
+ }
+
+ /**
+ * Returns if the unit is default or not
+ * @param none
+ * @return boolean True if the unit is default, false for not
+ */
+ public function getDefault () {
+ return $this->is_default;
+ }
+
+ /**
+ * Serializes the object and returns it as array, suitable
+ * to process via json_encode.
+ * @param none
+ * @return array An array containing the object information
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "name" => $this->getName(),
+ "shortName" => $this->getShortName(),
+ "default" => $this->getDefault()
+ );
+ }
+
+ /**
+ * Deserializes the manufacturer
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "name":
+ $this->setName($value);
+ break;
+ case "shortName":
+ $this->setShortName($value);
+ break;
+ }
+ }
+ }
+}
+ +
\ No newline at end of file
diff --git a/src/backend/PartKeepr/PartCategory/PartCategory.php b/src/backend/PartKeepr/PartCategory/PartCategory.php
@@ -0,0 +1,14 @@
+<?php
+namespace PartKeepr\PartCategory;
+
+use PartKeepr\Category\AbstractCategory;
+
+/**
+ * @Entity
+ * @Table(indexes={@index(columns={"lft"}),@index(columns={"rgt"})})
+ * The entity for our part categories
+ *
+ */
+class PartCategory extends AbstractCategory {
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/PartCategory/PartCategoryManager.php b/src/backend/PartKeepr/PartCategory/PartCategoryManager.php
@@ -0,0 +1,42 @@
+<?php
+namespace PartKeepr\PartCategory;
+
+use PartKeepr\Category\AbstractCategoryManager;
+use DoctrineExtensions\NestedSet\NodeWrapper;
+use PartKeepr\Util\SerializableException;
+use PartKeepr\PartKeepr;
+
+class PartCategoryManager extends AbstractCategoryManager {
+ protected $categoryClass = "PartKeepr\PartCategory\PartCategory";
+
+ /**
+ * Deletes the given category ID.
+ * @param $id int The category id to delete
+ * @throws CategoryNotFoundException If the category wasn't found
+ */
+ public function deleteCategory ($id) {
+ $category = $this->getCategory($id);
+
+ try {
+
+ if ($category->hasChildren()) {
+ $exception = new SerializableException(sprintf(PartKeepr::i18n("Category '%s' contains other categories."), $category->getNode()->getName()));
+ $exception->setDetail(sprintf(PartKeepr::i18n("You tried to delete the category '%s', but it still contains other categories. Please move the categories or delete them first."), $category->getNode()->getName()));
+
+ throw $exception;
+ }
+
+ parent::deleteCategory($id);
+ } catch (\PDOException $e) {
+ if ($e->getCode() == "23000") {
+ $exception = new SerializableException(sprintf(PartKeepr::i18n("Category '%s' contains parts."), $category->getNode()->getName()));
+ $exception->setDetail(sprintf(PartKeepr::i18n("You tried to delete the category '%s', but it still contains parts. Please move the parts to another category."), $category->getNode()->getName()));
+
+ throw $exception;
+ } else {
+ throw $e;
+ }
+ }
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/PartCategory/PartCategoryService.php b/src/backend/PartKeepr/PartCategory/PartCategoryService.php
@@ -0,0 +1,9 @@
+<?php
+namespace PartKeepr\PartCategory;
+
+use PartKeepr\Category\AbstractCategoryService;
+
+class PartCategoryService extends AbstractCategoryService {
+ protected $categoryManagerClass = "PartKeepr\PartCategory\PartCategoryManager";
+ protected $categoryClass = "PartKeepr\PartCategory\PartCategory";
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/PartDistributor/PartDistributorManager.php b/src/backend/PartKeepr/PartDistributor/PartDistributorManager.php
@@ -0,0 +1,74 @@
+<?php
+namespace PartKeepr\PartDistributor;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\Manufacturer\Manufacturer,
+ PartKeepr\PartKeepr,
+ PartKeepr\Manufacturer\Exceptions\ManufacturerNotFoundException;
+
+class PartDistributorManager extends Singleton {
+ public function getPartDistributors ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
+
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+ $qb->select("pd.orderNumber, part.id AS part_id, dist.id AS distributor_id")->from("PartKeepr\Part\PartDistributor","pd")
+ ->leftJoin('pd.distributor', "dist")
+ ->leftJoin("pd.part", "part");
+
+ /*if ($filter != "") {
+ $manufacturer = Manufacturer::loadById($filter);
+ $qb = $qb->where("st.manufacturer = :manufacturer");
+ $qb->setParameter("manufacturer", $manufacturer);
+ }*/
+
+ if ($limit > -1) {
+ $qb->setMaxResults($limit);
+ $qb->setFirstResult($start);
+ }
+
+ $qb->orderBy("pd.".$sort, $dir);
+
+ $query = $qb->getQuery();
+
+ $result = $query->getResult();
+
+ $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
+ $totalQueryBuilder->select("COUNT(pd.id)")->from("PartKeepr\Part\PartDistributor","pd");
+
+
+ /*
+ if ($filter != "") {
+ $totalQueryBuilder = $totalQueryBuilder->where("st.manufacturer = :manufacturer");
+ $totalQueryBuilder->setParameter("manufacturer", $manufacturer);
+ }*/
+
+ $totalQuery = $totalQueryBuilder->getQuery();
+
+ return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
+ }
+
+ public function getPartDistributor ($id) {
+ $partDistributor = PartKeepr::getEM()->find("PartKeepr\Part\PartDistributor", $id);
+
+ if ($partDistributor) {
+ return $partDistributor;
+ } else {
+ throw new PartDistributorNotFoundException();
+ }
+ }
+
+ public function addPartDistributor ($orderNumber) {
+ $partDistributor = new PartDistributor();
+ $partDistributor->setName($orderNumber);
+
+ PartKeepr::getEM()->persist($partDistributor);
+ PartKeepr::getEM()->flush();
+
+ return $partDistributor;
+ }
+ public function deletePartDistributor ($id) {
+ $manufacturer = $this->getManufacturer($id);
+
+ PartKeepr::getEM()->remove($manufacturer);
+ PartKeepr::getEM()->flush();
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/PartDistributor/PartDistributorService.php b/src/backend/PartKeepr/PartDistributor/PartDistributorService.php
@@ -0,0 +1,84 @@
+<?php
+namespace PartKeepr\ManufacturerICLogo;
+
+use PartKeepr\Manufacturer\ManufacturerICLogo,
+ PartKeepr\Service\RestfulService,
+ PartKeepr\Service\Service,
+ PartKeepr\PartKeepr,
+ PartKeepr\Manufacturer\Manufacturer,
+ PartKeepr\Session\SessionManager;
+
+class PartDistributorService extends Service implements RestfulService {
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return PartDistributorManager::getInstance()->getManufacturerICLogo($this->getParameter("id"))->serialize();
+ } else {
+ if ($this->hasParameter("sort")) {
+ $tmp = json_decode($this->getParameter("sort"), true);
+
+ $aSortParams = $tmp[0];
+ } else {
+ $aSortParams = array(
+ "property" => "id",
+ "direction" => "ASC");
+ }
+
+ $filter = "";
+
+ if ($this->hasParameter("filter")) {
+ $tmp = json_decode($this->getParameter("filter"), true);
+
+ foreach ($tmp as $item) {
+ if (array_key_exists("property", $item)) {
+ if ($item["property"] == "manufacturer_id") {
+ if (array_key_exists("value", $item)) {
+ $filter = $item["value"];
+ }
+ }
+ }
+ }
+ }
+ // @todo This seems wrong?!?
+ return ManufacturerICLogoManager::getInstance()->getManufacturerICLogos(
+ $this->getParameter("start", $this->getParameter("start", 0)),
+ $this->getParameter("limit", $this->getParameter("limit", 25)),
+ $this->getParameter("sortby", $aSortParams["property"]),
+ $this->getParameter("dir", $aSortParams["direction"]),
+ $filter);
+ }
+ }
+
+ public function create () {
+ $this->requireParameter("tmp_id");
+ $this->requireParameter("manufacturer_id");
+
+ $tmpImage = TempImage::loadById($this->getParameter("tmp_id"));
+
+ $image = new ManufacturerICLogo();
+
+ $manufacturer = Manufacturer::loadById($this->getParameter("manufacturer_id"));
+
+ $image->setManufacturer($manufacturer);
+ $image->replace($tmpImage->getFilename());
+ PartKeepr::getEM()->persist($image);
+ PartKeepr::getEM()->flush();
+
+ return $image->serialize();
+ }
+
+ public function update () {
+
+ }
+
+ public function destroy () {
+ $this->requireParameter("id");
+
+ $logo = ManufacturerICLogo::loadById($this->getParameter("id"));
+
+ PartKeepr::getEM()->remove($logo);
+ PartKeepr::getEM()->flush();
+
+ return array("data" => null);
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/PartKeepr.php b/src/backend/PartKeepr/PartKeepr.php
@@ -0,0 +1,434 @@
+<?php
+namespace PartKeepr;
+
+use Doctrine\Common\ClassLoader,
+ PartKeepr\SystemNotice\SystemNoticeManager,
+ Doctrine\ORM\Configuration,
+ Doctrine\ORM\EntityManager,
+ PartKeepr\Util\Configuration as PartKeeprConfiguration;
+
+
+
+class PartKeepr {
+ /**
+ *
+ * Contains the doctrine entity manager.
+ * @var Doctrine\ORM\EntityManager
+ */
+ private static $entityManager = null;
+
+ /**
+ * Initializes the PartKeepr system
+ *
+ * You *need* to call this method before doing anything else.
+ *
+ * An environment is used to load a different configuration file.
+ * Usually, you don't need to pass anything here.
+ *
+ * @param $environment string The environment to use, null otherwise.
+ * @return nothing
+ */
+ public static function initialize ($environment = null) {
+ self::initializeClassLoaders();
+ self::initializeConfig($environment);
+ self::initializeDoctrine();
+ }
+
+ /**
+ * Initializes the doctrine class loader and sets up the
+ * directories.
+ *
+ * @param none
+ * @return nothing
+ */
+ public static function initializeClassLoaders() {
+ require_once 'Doctrine/Common/ClassLoader.php';
+
+
+ $classLoader = new ClassLoader('PartKeepr', self::getRootDirectory() . "/src/backend");
+ $classLoader->register();
+
+ $classLoader = new ClassLoader('Doctrine\ORM');
+ $classLoader->register();
+
+ $classLoader = new ClassLoader("Doctrine\DBAL\Migrations", self::getRootDirectory() ."/3rdparty/doctrine-migrations/lib");
+ $classLoader->register();
+
+ $classLoader = new ClassLoader('Doctrine\DBAL');
+ $classLoader->register();
+
+ $classLoader = new ClassLoader('Doctrine\Common');
+ $classLoader->register();
+
+ $classLoader = new ClassLoader('Symfony', 'Doctrine');
+ $classLoader->register();
+
+ $classLoader = new ClassLoader("DoctrineExtensions\NestedSet", self::getRootDirectory() ."/3rdparty/doctrine2-nestedset/lib");
+ $classLoader->register();
+
+
+ }
+
+ /**
+ * Returns an array of all cronjobs which are required for proper execution of PartKeepr.
+ *
+ * @return Array The filenames of each cronjob which is required
+ */
+ public static function getRequiredCronjobs () {
+ return array(
+ "CreateStatisticSnapshot.php",
+ "UpdatePartCacheData.php",
+ "UpdateTipsOfTheDay.php",
+ "CheckForUpdates.php"
+ );
+ }
+
+ /**
+ * Initializes the configuration for a given environment.
+ *
+ * An environment is used to load a different configuration file.
+ *
+ * Usually, you don't need to pass anything here.
+ *
+ *
+ * @param $environment string The environment to use, null otherwise.
+ * @return nothing
+ */
+ public static function initializeConfig ($environment = null) {
+ if ($environment != null) {
+ include(self::getRootDirectory()."/config-$environment.php");
+ } else {
+ include(self::getRootDirectory()."/config.php");
+ }
+
+ // Check if the files path is set. If not, fall back to <partkeepr-root>/data/
+ if (PartKeeprConfiguration::getOption("partkeepr.files.path", null) === null) {
+
+ PartKeeprConfiguration::setOption("partkeepr.files.path",
+ PartKeepr::getRootDirectory() . "/data/");
+ }
+
+ // Check if the image path is set. If not, fall back to <configured-files-directory>/images/
+ if (PartKeeprConfiguration::getOption("partkeepr.images.path", null) === null) {
+
+ PartKeeprConfiguration::setOption("partkeepr.images.path",
+ PartKeeprConfiguration::getOption("partkeepr.files.path") . "images/");
+ }
+
+ // Check if the image cache path is set. If not, fall back to <configured-images-directory>/images/
+ if (PartKeeprConfiguration::getOption("partkeepr.images.cache", null) === null) {
+
+ PartKeeprConfiguration::setOption("partkeepr.images.cache",
+ PartKeeprConfiguration::getOption("partkeepr.images.path") . "cache/");
+
+ }
+
+ }
+
+ /**
+ * Checks against the versions at partkeepr.org.
+ *
+ * If a newer version was found, create a system notice entry.
+ */
+ public static function doVersionCheck () {
+
+ $data = file_get_contents("http://www.partkeepr.org/versions.json");
+ $versions = json_decode($data, true);
+
+ if (PartKeeprVersion::PARTKEEPR_VERSION == "{V_GIT}") { return; }
+
+ if (version_compare(PartKeepr::getVersion(), $versions[0]["version"], '<')) {
+
+ SystemNoticeManager::getInstance()->createUniqueSystemNotice(
+ "PARTKEEPR_VERSION_".$versions[0]["version"],
+ sprintf(PartKeepr::i18n("New PartKeepr Version %s available"), $versions[0]["version"]),
+ sprintf(PartKeepr::i18n("PartKeepr Version %s changelog:"), $versions[0]["version"]) . "\n\n".
+ $versions[0]["changelog"]
+ );
+
+ }
+ }
+
+ /**
+ * Initializes the doctrine framework and
+ * sets all required configuration options.
+ *
+ * @param none
+ * @return nothing
+ */
+ public static function initializeDoctrine () {
+ $config = new Configuration;
+
+ $driverImpl = $config->newDefaultAnnotationDriver(
+ array(__DIR__)
+ );
+ $config->setMetadataDriverImpl($driverImpl);
+
+ $connectionOptions = PartKeepr::createConnectionOptionsFromConfig();
+
+ if (extension_loaded("apc")) {
+ $cache = new \Doctrine\Common\Cache\ApcCache();
+ } else {
+ $cache = new \Doctrine\Common\Cache\ArrayCache();
+ }
+
+ $config->setMetadataCacheImpl($cache);
+
+ $config->setQueryCacheImpl($cache);
+
+ $config->setProxyDir(self::getRootDirectory() . '/data/proxies');
+ $config->setProxyNamespace('Proxies');
+ $config->setEntityNamespaces(self::getEntityClasses());
+ $config->setAutoGenerateProxyClasses(false);
+
+ if (PartKeeprConfiguration::getOption("partkeepr.database.echo_sql_log", false) === true) {
+ $logger = new \Doctrine\DBAL\Logging\EchoSQLLogger();
+ $config->setSQLLogger($logger);
+ }
+
+ self::$entityManager = EntityManager::create($connectionOptions, $config);
+ }
+
+ public static function createConnectionOptionsFromConfig () {
+ $connectionOptions = array();
+
+ $driver = PartKeeprConfiguration::getOption("partkeepr.database.driver");
+
+ switch ($driver) {
+ case "pdo_mysql":
+ case "pdo_pgsql":
+ case "pdo_oci":
+ case "oci8":
+ case "pdo_sqlsrv":
+ $connectionOptions["driver"] = $driver;
+ $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["charset"] = "utf8";
+ /**
+ * Compatibility with older configuration files. We check for the key "hostname" as well as "host".
+ */
+ if (PartKeeprConfiguration::getOption("partkeepr.database.hostname", null) !== null) {
+ $connectionOptions["host"] = PartKeeprConfiguration::getOption("partkeepr.database.hostname");
+ } else {
+ $connectionOptions["host"] = PartKeeprConfiguration::getOption("partkeepr.database.host", "localhost");
+ }
+
+
+ if (PartKeeprConfiguration::getOption("partkeepr.database.port") !== null) {
+ $connectionOptions["port"] = PartKeeprConfiguration::getOption("partkeepr.database.port");
+ }
+
+ if (PartKeeprConfiguration::getOption("partkeepr.database.mysql_socket", null) !== null) {
+ $connectionOptions["unix_socket"] = PartKeeprConfiguration::getOption("partkeepr.database.mysql_socket");
+ }
+ break;
+ case "pdo_sqlite":
+ $connectionOptions["driver"] = $driver;
+ $connectionOptions["user"] = PartKeeprConfiguration::getOption("partkeepr.database.username", "partkeepr");
+ $connectionOptions["password"] = PartKeeprConfiguration::getOption("partkeepr.database.password", "partkeepr");
+ $connectionOptions["path"] = PartKeeprConfiguration::getOption("partkeepr.database.sqlite_path", PartKeepr::getRootDirectory() . "/data/partkeepr.sqlite");
+ break;
+ default:
+ throw new \Exception(sprintf("Unknown driver %s", $driver));
+ }
+
+ return $connectionOptions;
+ }
+
+ /**
+ * Returns the EntityManager. Shortcut for getEntityManager().
+ * @return \Doctrine\ORM\EntityManager The EntityManager
+ */
+ public static function getEM () {
+ return self::getEntityManager();
+ }
+
+ public static function getRootDirectory () {
+ return dirname(dirname(dirname(__DIR__)));
+ }
+
+ /**
+ * Returns the EntityManager.
+ * @return Doctrine\ORM\EntityManager The EntityManager
+ */
+ public static function getEntityManager () {
+ if (!self::$entityManager instanceof EntityManager) {
+ throw new Exception("No EntityManager found. Make sure you called initializeDoctrine() or initialize().");
+ }
+ return self::$entityManager;
+ }
+
+ /**
+ * Returns the class metadata for all entity classes
+ * @return array an array of class metadata objects
+ */
+ public static function getClassMetaData () {
+ $classes = self::getEntityClasses();
+
+ $aClasses = array();
+
+ foreach ($classes as $class) {
+ $aClasses[] = PartKeepr::getEM()->getClassMetadata($class);
+ }
+
+ return $aClasses;
+ }
+
+ /**
+ * Returns a list of all classes we use for entities.
+ * @return array An array of strings with all class names
+ */
+ public static function getEntityClasses () {
+ return array(
+ 'PartKeepr\User\User',
+ 'PartKeepr\Session\Session',
+
+ 'PartKeepr\Footprint\Footprint',
+ 'PartKeepr\Footprint\FootprintImage',
+ 'PartKeepr\Footprint\FootprintAttachment',
+ 'PartKeepr\FootprintCategory\FootprintCategory',
+
+ 'PartKeepr\Part\Part',
+ 'PartKeepr\Part\PartUnit',
+ 'PartKeepr\Part\PartManufacturer',
+ 'PartKeepr\Part\PartDistributor',
+ 'PartKeepr\Part\PartImage',
+ 'PartKeepr\Part\PartAttachment',
+ 'PartKeepr\PartCategory\PartCategory',
+
+ 'PartKeepr\Project\Project',
+ 'PartKeepr\Project\ProjectPart',
+ 'PartKeepr\Project\ProjectAttachment',
+
+ 'PartKeepr\StorageLocation\StorageLocation',
+ 'PartKeepr\StorageLocation\StorageLocationImage',
+
+ 'PartKeepr\Stock\StockEntry',
+
+ 'PartKeepr\Manufacturer\Manufacturer',
+ 'PartKeepr\Manufacturer\ManufacturerICLogo',
+
+ 'PartKeepr\Distributor\Distributor',
+
+ 'PartKeepr\Image\Image',
+ 'PartKeepr\Image\CachedImage',
+ 'PartKeepr\TempImage\TempImage',
+
+ 'PartKeepr\UploadedFile\TempUploadedFile',
+
+ 'PartKeepr\Statistic\StatisticSnapshot',
+ 'PartKeepr\Statistic\StatisticSnapshotUnit',
+ 'PartKeepr\SiPrefix\SiPrefix',
+ 'PartKeepr\Unit\Unit',
+ 'PartKeepr\PartParameter\PartParameter',
+
+ 'PartKeepr\TipOfTheDay\TipOfTheDay',
+ 'PartKeepr\TipOfTheDay\TipOfTheDayHistory',
+ 'PartKeepr\UserPreference\UserPreference',
+ 'PartKeepr\SystemNotice\SystemNotice',
+ 'PartKeepr\CronLogger\CronLogger'
+
+ );
+ }
+
+ /**
+ * Formats a message and applies internationalization.
+ *
+ * This method accepts sprintf-like parameters, which are appended after the $string parameter.
+ *
+ * @param $string string The string to internationalize
+ * @todo stub
+ */
+ public static function i18n ($string) {
+ if (func_num_args() > 1) {
+ $args = func_get_args();
+ array_shift($args);
+
+ return vsprintf($string, $args);
+ } else {
+ return $string;
+ }
+ }
+
+ /**
+ * Returns a new GUID.
+ * @return string The new GUID
+ */
+ public static function createGUIDv4() {
+ return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
+
+ // 32 bits for "time_low"
+ mt_rand(0, 0xffff), mt_rand(0, 0xffff),
+
+ // 16 bits for "time_mid"
+ mt_rand(0, 0xffff),
+
+ // 16 bits for "time_hi_and_version",
+ // four most significant bits holds version number 4
+ mt_rand(0, 0x0fff) | 0x4000,
+
+ // 16 bits, 8 bits for "clk_seq_hi_res",
+ // 8 bits for "clk_seq_low",
+ // two most significant bits holds zero and one for variant DCE1.1
+ mt_rand(0, 0x3fff) | 0x8000,
+
+ // 48 bits for "node"
+ mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
+ );
+ }
+
+ /**
+ * Returns the current PartKeepr version.
+ * @return string The PartKeepr Version
+ */
+ public static function getVersion () {
+ if (PartKeeprVersion::PARTKEEPR_VERSION == "{V_GIT}") {
+ return "GIT development version";
+ }
+ return PartKeeprVersion::PARTKEEPR_VERSION;
+ }
+
+ /**
+ * This is a re-implementation of gettype().
+ *
+ * The PHP documentation states that the "gettype" return values will change in the future, so we need
+ * to make sure we don't get bitten by the change.
+ *
+ * @param mixed $var
+ * @return string The type
+ */
+ public static function getType($var)
+ {
+ if (is_array($var)) return "array";
+ if (is_bool($var)) return "boolean";
+ if (is_float($var)) return "float";
+ if (is_int($var)) return "integer";
+ if (is_null($var)) return "NULL";
+ if (is_numeric($var)) return "numeric";
+ if (is_object($var)) return "object";
+ if (is_resource($var)) return "resource";
+ if (is_string($var)) return "string";
+ return "unknown type";
+ }
+
+ /**
+ * Returns the effective size from a human-readable byte format.
+ *
+ * Example:
+ * getBytesFromHumanReadable("1M") will return 1048576.
+ *
+ * @param string $size_str The byte
+ * @return int The bytes
+ */
+ public static function getBytesFromHumanReadable ($size_str)
+ {
+ switch (substr ($size_str, -1))
+ {
+ case 'M': case 'm': return (int)$size_str * 1048576;
+ case 'K': case 'k': return (int)$size_str * 1024;
+ case 'G': case 'g': return (int)$size_str * 1073741824;
+ default: return $size_str;
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/PartKeeprVersion.php b/src/backend/PartKeepr/PartKeeprVersion.php
@@ -0,0 +1,15 @@
+<?php
+namespace PartKeepr;
+
+class PartKeeprVersion {
+ /**
+ * Holds the PartKeepr Version.
+ *
+ * If {V_GIT}, then the function will return 'GIT Development Version'.
+ * {V_GIT} will be replaced by the build script with the actual version.
+ *
+ * The reason why we have a separate class for the version constant is that
+ * we can easily replace it from scripts.
+ */
+ const PARTKEEPR_VERSION = '{V_GIT}';
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/PartParameter/PartParameter.php b/src/backend/PartKeepr/PartParameter/PartParameter.php
@@ -0,0 +1,247 @@
+<?php
+namespace PartKeepr\PartParameter;
+
+use PartKeepr\PartKeepr,
+PartKeepr\Util\Exceptions\OutOfRangeException,
+PartKeepr\Unit\Unit,
+PartKeepr\Part\Part,
+PartKeepr\SiPrefix\SiPrefix;
+
+
+/**
+ * This object represents a parameter. Each parameter can have an unit (defined by the class "Unit") associated with
+ * a numeric value.
+ *
+ * @Entity @HasLifecycleCallbacks
+ **/
+class PartParameter {
+ /**
+ * @Id @Column(type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ * @var integer
+ */
+ private $id;
+
+ /**
+ * @ManyToOne(targetEntity="PartKeepr\Part\Part")
+ * The part this parameter is bound to
+ * @var Part
+ */
+ private $part;
+
+ /**
+ * The name of the parameter (e.g. Resistance, Voltage)
+ * @Column(type="string")
+ * @var string
+ */
+ private $name;
+
+ /**
+ * A description for this parameter
+ * @Column(type="string")
+ * @var string
+ */
+ private $description;
+
+ /**
+ * The unit for this type. May be null.
+ *
+ * @ManyToOne(targetEntity="PartKeepr\Unit\Unit")
+ * @var Unit
+ */
+ private $unit;
+
+ /**
+ * The value of the unit. Together with the prefix, it becomes the actual value.
+ *
+ * Example: If you have 10µ, the value field will contain "10", the prefix object is linked to the SiPrefix
+ * representing "µ" and the rawValue field will contain 0.000001
+ * @Column(type="float")
+ * @var float
+ */
+ private $value;
+
+ /**
+ * The SiPrefix of the unit
+ * @ManyToOne(targetEntity="PartKeepr\SiPrefix\SiPrefix")
+ * @var object
+ */
+ private $siPrefix;
+
+ /**
+ * The raw value of the unit.
+ * @Column(type="float")
+ * @var float
+ */
+ private $rawValue;
+
+ /**
+ * Sets the name for this parameter
+ * @param string $name The name
+ */
+ public function setName ($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the name for this parameter
+ * @return string The name for this parameter
+ */
+ public function getName () {
+ return $this->name;
+ }
+
+ /**
+ * Sets the description for this parameter
+ * @param string $description The description
+ */
+ public function setDescription ($description) {
+ $this->description = $description;
+ }
+
+ /**
+ * Returns the description
+ * @return string The description
+ */
+ public function getDescription () {
+ return $this->description;
+ }
+
+ /**
+ * Sets the unit
+ * @param Unit $unit The unit to set
+ */
+ public function setUnit (Unit $unit = null) {
+ $this->unit = $unit;
+ }
+
+ /**
+ * Returns the unit
+ * @return Unit the unit
+ */
+ public function getUnit () {
+ return $this->unit;
+ }
+
+ /**
+ * Sets the part
+ * @param Part $part The part to set
+ */
+ public function setPart (Part $part) {
+ $this->part = $part;
+ }
+
+ /**
+ * Returns the part
+ * @return Part the part
+ */
+ public function getPart () {
+ return $this->part;
+ }
+
+ /**
+ * Sets the value
+ * @param float $value The value to set
+ */
+ public function setValue ($value) {
+ $this->value = $value;
+
+ $this->recalculateRawValue();
+ }
+
+ /**
+ * Returns the value
+ * @return float The value
+ */
+ public function getValue () {
+ return $this->value;
+ }
+
+ /**
+ * Sets the si prefix for this parameter
+ * @param SiPrefix $prefix The prefix to set, or null
+ */
+ public function setSiPrefix (SiPrefix $prefix = null) {
+ $this->siPrefix = $prefix;
+
+ $this->recalculateRawValue();
+ }
+
+ /**
+ * Returns the si prefix for this parameter
+ * @return SiPrefix the si prefix or null
+ */
+ public function getSiPrefix () {
+ return $this->siPrefix;
+ }
+
+ /**
+ * Returns the ID for this object.
+ * @param none
+ * @return int The ID for this object
+ */
+ public function getId () {
+ return $this->id;
+ }
+
+ private function recalculateRawValue () {
+ if (is_object($this->getSiPrefix())) {
+ $power = $this->getSiPrefix()->getPower();
+ } else {
+ $power = 0;
+ }
+
+ $this->rawValue = $this->getValue() * pow(10, $power);
+ }
+
+ /**
+ * Returns the data of this object in a serialized form.
+ * @return array The result array
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "name" => $this->getName(),
+ "description" => $this->getDescription(),
+ "value" => $this->getValue(),
+ "part_id" => $this->getPart()->getId(),
+ "siprefix_id" => is_object($this->getSiPrefix()) ? $this->getSiPrefix()->getId() : null,
+ "prefixedValue" => array(
+ /* We duplicate most data because of strange ExtJS stuff... */
+ "value" => $this->getValue(),
+ "power" => is_object($this->getSiPrefix()) ? $this->getSiPrefix()->getPower() : 0,
+ "symbol" => is_object($this->getSiPrefix()) ? $this->getSiPrefix()->getSymbol() : "",
+ "siprefix_id" => is_object($this->getSiPrefix()) ? $this->getSiPrefix()->getId() : null
+ ),
+ "unit_id" => is_object($this->getUnit()) ? $this->getUnit()->getId() : null
+ );
+ }
+
+ /**
+ * Deserializes the part parameter
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "name":
+ $this->setName($value);
+ break;
+ case "description":
+ $this->setDescription($value);
+ break;
+ case "value":
+ $this->setValue($value);
+ break;
+ case "siprefix_id":
+ $prefix = SiPrefix::loadById($value);
+ $this->setSiPrefix($prefix);
+ break;
+ case "unit_id":
+ $unit = Unit::loadById($value);
+ $this->setUnit($unit);
+ break;
+ }
+ }
+ }
+}
diff --git a/src/backend/PartKeepr/PartUnit/PartUnitManager.php b/src/backend/PartKeepr/PartUnit/PartUnitManager.php
@@ -0,0 +1,106 @@
+<?php
+namespace PartKeepr\PartUnit;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\Part\PartUnit,
+ PartKeepr\PartKeepr,
+ PartKeepr\Category\CategoryManager,
+ PartKeepr\PartUnit\Exceptions\PartUnitNotFoundException;
+
+class PartUnitManager extends Singleton {
+ public function getPartUnits ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
+
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+ $qb->select("st.id, st.name, st.shortName, st.is_default AS default")->from("PartKeepr\Part\PartUnit","st");
+
+ if ($filter != "") {
+ $qb = $qb->where("LOWER(st.name) LIKE :filter");
+ $qb->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ if ($limit > -1) {
+ $qb->setMaxResults($limit);
+ $qb->setFirstResult($start);
+ }
+
+ $qb->orderBy("st.".$sort, $dir);
+
+ $query = $qb->getQuery();
+
+ $result = $query->getResult();
+
+ foreach ($result as $key => $row) {
+ foreach ($row as $rowkey => $column) {
+ if ($rowkey == "default") {
+ if ($column == 0) {
+ $result[$key][$rowkey] = false;
+ } else {
+ $result[$key][$rowkey] = true;
+ }
+ }
+ }
+ }
+
+ $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
+ $totalQueryBuilder->select("COUNT(st.id)")->from("PartKeepr\Part\PartUnit","st");
+
+
+
+ if ($filter != "") {
+ $totalQueryBuilder = $totalQueryBuilder->where("LOWER(st.name) LIKE :filter");
+ $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ $totalQuery = $totalQueryBuilder->getQuery();
+
+ return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
+ }
+
+ public function getPartUnit ($id) {
+ $partUnit = PartKeepr::getEM()->find("PartKeepr\Part\PartUnit", $id);
+
+ if ($partUnit) {
+ return $partUnit;
+ } else {
+ throw new PartUnitNotFoundException();
+ }
+ }
+
+ public function deletePartUnit ($id) {
+ $partUnit = $this->getPartUnit($id);
+
+ PartKeepr::getEM()->remove($partUnit);
+ 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 PartKeepr\Part\PartUnit pu WHERE pu.is_default = :default';
+ return PartKeepr::getEM()->createQuery($dql)->setParameter("default", true)->getSingleResult();
+ }
+
+ public function setDefaultPartUnit ($id) {
+ PartKeepr::getEM()->beginTransaction();
+
+ $dql = 'UPDATE PartKeepr\Part\PartUnit pu SET pu.is_default = :default WHERE pu.id = :id';
+ PartKeepr::getEM()->createQuery($dql)->setParameter("id", $id)->setParameter("default", true, \PDO::PARAM_BOOL)->execute();
+
+ $dql = 'UPDATE PartKeepr\Part\PartUnit pu SET pu.is_default = :default WHERE pu.id != :id';
+ PartKeepr::getEM()->createQuery($dql)->setParameter("id", $id)->setParameter("default", false, \PDO::PARAM_BOOL)->execute();
+
+ PartKeepr::getEM()->commit();
+ }
+
+ public function getUnitCounts () {
+ $dql = 'SELECT SUM(p.stockLevel) AS stockLevel, pu.id AS puid FROM PartKeepr\Part\PartUnit pu LEFT JOIN pu.parts p GROUP BY pu.id';
+
+ $result = PartKeepr::getEM()->createQuery($dql)->getResult();
+
+ return $result;
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/PartUnit/PartUnitService.php b/src/backend/PartKeepr/PartUnit/PartUnitService.php
@@ -0,0 +1,72 @@
+<?php
+namespace PartKeepr\PartUnit;
+use PartKeepr\Service\RestfulService;
+
+use PartKeepr\Service\Service,
+ PartKeepr\PartKeepr,
+ PartKeepr\Part\PartUnit,
+ PartKeepr\Session\SessionManager;
+
+class PartUnitService extends Service implements RestfulService {
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return array("data" => PartUnitManager::getInstance()->getPartUnit($this->getParameter("id"))->serialize());
+ } else {
+ if ($this->hasParameter("sort")) {
+ $tmp = json_decode($this->getParameter("sort"), true);
+
+ $aSortParams = $tmp[0];
+ } else {
+ $aSortParams = array(
+ "property" => "name",
+ "direction" => "ASC");
+ }
+ return PartUnitManager::getInstance()->getPartUnits(
+ $this->getParameter("start", $this->getParameter("start", 0)),
+ $this->getParameter("limit", $this->getParameter("limit", 25)),
+ $this->getParameter("sortby", $aSortParams["property"]),
+ $this->getParameter("dir", $aSortParams["direction"]),
+ $this->getParameter("query", ""));
+ }
+ }
+
+ public function create () {
+ $this->requireParameter("name");
+
+ $partUnit = new PartUnit;
+ $partUnit->deserialize($this->getParameters());
+
+ PartKeepr::getEM()->persist($partUnit);
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $partUnit->serialize());
+ }
+
+ public function update () {
+ $this->requireParameter("id");
+ $this->requireParameter("name");
+
+ $partUnit = PartUnitManager::getInstance()->getPartUnit($this->getParameter("id"));
+ $partUnit->deserialize($this->getParameters());
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $partUnit->serialize());
+
+ }
+
+ public function destroy () {
+ $this->requireParameter("id");
+
+ PartUnitManager::getInstance()->deletePartUnit($this->getParameter("id"));
+
+ return array("data" => null);
+ }
+
+ public function setDefault () {
+ $this->requireParameter("id");
+
+ $partUnit = PartUnitManager::getInstance()->setDefaultPartUnit($this->getParameter("id"));
+
+ return array("data" => null);
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Ping/PingService.php b/src/backend/PartKeepr/Ping/PingService.php
@@ -0,0 +1,19 @@
+<?php
+namespace PartKeepr\Ping;
+use PartKeepr\Service\AnonService;
+
+use PartKeepr\Service\Service,
+ PartKeepr\PartKeepr;
+
+class PingService extends AnonService {
+ /**
+ * Simple test call to verify if the service layer is reachable.
+ *
+ * This is used for the PartKeeprMobile client to verify if the URL
+ * is entered correctly.
+ */
+ public function ping () {
+ return "pong";
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Project/Project.php b/src/backend/PartKeepr/Project/Project.php
@@ -0,0 +1,161 @@
+<?php
+namespace PartKeepr\Project;
+
+use PartKeepr\User\User,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Util\Deserializable,
+ PartKeepr\Util\BaseEntity;
+
+/**
+ * Represents a part in the database. The heart of our project. Handle with care!
+ * @Entity **/
+class Project extends BaseEntity implements Serializable, Deserializable {
+ /**
+ * Specifies the name of the project
+ * @Column(type="string")
+ */
+ private $name;
+
+ /**
+ * Specifies the user this project belongs to
+ * @ManyToOne(targetEntity="PartKeepr\User\User")
+ */
+ private $user;
+
+ /**
+ * Holds the parts needed for this project
+ * @OneToMany(targetEntity="PartKeepr\Project\ProjectPart",mappedBy="project",cascade={"persist", "remove"})
+ * @var ArrayCollection
+ */
+ private $parts;
+
+ /**
+ * Holds the description of this project
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $description;
+
+ /**
+ * Holds the project attachments
+ * @OneToMany(targetEntity="PartKeepr\Project\ProjectAttachment",mappedBy="project",cascade={"persist", "remove"})
+ * @var ProjectAttachment
+ */
+ private $attachments;
+
+
+ /**
+ * Constructs a new project
+ */
+ public function __construct () {
+ $this->parts = new \Doctrine\Common\Collections\ArrayCollection();
+ $this->attachments = new \Doctrine\Common\Collections\ArrayCollection();
+ }
+
+ /**
+ * Sets the user for this project
+ * @param User $user
+ */
+ public function setUser (User $user) {
+ $this->user = $user;
+ }
+
+ /**
+ * Gets the user for this project
+ * @return User
+ */
+ public function getUser () {
+ return $this->user;
+ }
+
+ /**
+ * Sets the name for this project
+ * @param string $name
+ */
+ public function setName ($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the name of this project
+ */
+ public function getName () {
+ return $this->name;
+ }
+
+ /**
+ * Sets the description of this project
+ * @param string $description The description to set
+ */
+ public function setDescription ($description) {
+ $this->description = $description;
+ }
+
+ /**
+ * Returns the description of this project
+ * @return string The description
+ */
+ public function getDescription () {
+ return $this->description;
+ }
+
+ /**
+ * Returns the parts array
+ * @return ArrayCollection An array of ProjectPart objects
+ */
+ public function getParts () {
+ return $this->parts;
+ }
+
+ /**
+ * Returns the attachments for this project
+ * @return ArrayCollection The attachments
+ */
+ public function getAttachments () {
+ return $this->attachments;
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Util.Serializable::serialize()
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "name" => $this->getName(),
+ "description" => $this->getDescription(),
+ "parts" => $this->serializeChildren($this->getParts()),
+ "attachments" => $this->serializeChildren($this->getAttachments())
+ );
+ }
+
+ /**
+ * Deserializes the project
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "name":
+ $this->setName($value);
+ break;
+ case "description":
+ $this->setDescription($value);
+ break;
+ case "parts":
+ $this->deserializeChildren($value, $this->getParts(), "PartKeepr\Project\ProjectPart");
+ foreach ($this->getParts() as $part) {
+ $part->setProject($this);
+ }
+ break;
+ case "attachments":
+ $this->deserializeChildren($value, $this->getAttachments(), "PartKeepr\Project\ProjectAttachment");
+ foreach ($this->getAttachments() as $attachment) {
+ $attachment->setProject($this);
+ }
+ break;
+ }
+ }
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Project/ProjectAttachment.php b/src/backend/PartKeepr/Project/ProjectAttachment.php
@@ -0,0 +1,101 @@
+<?php
+namespace PartKeepr\Project;
+
+use PartKeepr\Util\Deserializable,
+ PartKeepr\Util\Serializable,
+ PartKeepr\UploadedFile\UploadedFile;
+
+/**
+ * Holds a project attachment
+ * @Entity
+ **/
+class ProjectAttachment extends UploadedFile implements Serializable, Deserializable {
+ /**
+ * The description of this attachment
+ * @Column(type="text")
+ * @var string
+ */
+ private $description;
+
+ /**
+ * Creates a new project attachment
+ */
+ public function __construct () {
+ parent::__construct();
+ $this->setType("ProjectAttachment");
+ }
+ /**
+ * The project object
+ * @ManyToOne(targetEntity="PartKeepr\Project\Project")
+ * @var Project
+ */
+ private $project = null;
+
+ /**
+ * Sets the project
+ * @param Project $project The project to set
+ */
+ public function setProject (Project $project) {
+ $this->project = $project;
+ }
+
+ /**
+ * Returns the roject
+ * @return Project the project
+ */
+ public function getProject () {
+ return $this->project;
+ }
+
+ /**
+ * Sets the description for this attachment
+ * @param string $description The attachment description
+ */
+ public function setDescription ($description) {
+ $this->description = $description;
+ }
+
+ /**
+ * Returns the description for this attachment
+ * @return string The description
+ */
+ public function getDescription () {
+ return $this->description;
+ }
+
+ /**
+ *
+ * Serializes this project attachment
+ * @return array The serialized project attachment
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "project_id" => $this->getProject()->getId(),
+ "originalFilename" => $this->getOriginalFilename(),
+ "mimetype" => $this->getMimetype(),
+ "extension" => $this->getExtension(),
+ "size" => $this->getSize(),
+ "description" => $this->getDescription());
+ }
+
+ /**
+ * Deserializes the project attachment
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ if (array_key_exists("id", $parameters)) {
+ if (substr($parameters["id"], 0, 4) === "TMP:") {
+ $this->replaceFromTemporaryFile($parameters["id"]);
+ }
+ }
+
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "description":
+ $this->setDescription($value);
+ break;
+ }
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Project/ProjectManager.php b/src/backend/PartKeepr/Project/ProjectManager.php
@@ -0,0 +1,33 @@
+<?php
+namespace PartKeepr\Project;
+
+use PartKeepr\Manager\AbstractManager,
+ PartKeepr\Project\Project,
+ PartKeepr\PartKeepr;
+
+class ProjectManager extends AbstractManager {
+ /**
+ * Returns the FQCN for the target entity to operate on.
+ * @return string The FQCN, e.g. PartKeepr\Part
+ */
+ public function getEntityName () {
+ return 'PartKeepr\Project\Project';
+ }
+
+ /**
+ * Returns all fields which need to appear in the getList ResultSet.
+ * @return array An array of all fields which should be returned
+ */
+ public function getQueryFields () {
+ return array("id", "name", "description");
+ }
+
+ /**
+ * Returns the default sort field
+ *
+ * @return string The default sort field
+ */
+ public function getDefaultSortField () {
+ return "name";
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Project/ProjectPart.php b/src/backend/PartKeepr/Project/ProjectPart.php
@@ -0,0 +1,136 @@
+<?php
+namespace PartKeepr\Project;
+
+use PartKeepr\Part\Part,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Util\Deserializable,
+ PartKeepr\Util\BaseEntity;
+
+/**
+ * Represents a part in the database. The heart of our project. Handle with care!
+ * @Entity **/
+class ProjectPart extends BaseEntity implements Serializable, Deserializable {
+ /**
+ * @ManyToOne(targetEntity="PartKeepr\Part\Part")
+ */
+ private $part;
+
+ /**
+ * Specifies the amount of parts
+ * @Column(type="integer")
+ */
+ private $quantity;
+
+ /**
+ * Specifies the project which belongs to this project part
+ * @ManyToOne(targetEntity="PartKeepr\Project\Project")
+ */
+ private $project;
+
+ /**
+ * Specifies the remarks for this entry
+ * @Column(type="string",nullable=true)
+ */
+ private $remarks;
+
+ /**
+ * Sets the part which belongs to this entry
+ * @param Part $part
+ */
+ public function setPart (Part $part) {
+ $this->part = $part;
+ }
+
+ /**
+ * Returns the part which belongs to this entry
+ * @return Part
+ */
+ public function getPart () {
+ return $this->part;
+ }
+
+ /**
+ * Sets the quantity for this entry
+ * @param int $quantity
+ */
+ public function setQuantity ($quantity) {
+ $this->quantity = intval($quantity);
+ }
+
+ /**
+ * Returns the quantity for this project
+ * @return int the amount of parts needed
+ */
+ public function getQuantity () {
+ return $this->quantity;
+ }
+
+ /**
+ * Sets the project assigned to this entry
+ * @param Project $project
+ */
+ public function setProject (Project $project) {
+ $this->project = $project;
+ }
+
+ /**
+ * Returns the project assigned to this entry
+ * @return Project
+ */
+ public function getProject () {
+ return $this->project;
+ }
+
+ /**
+ * Sets the remarks for this entry
+ * @param string $remarks
+ */
+ public function setRemarks ($remarks) {
+ $this->remarks = $remarks;
+ }
+
+ /**
+ * Returns the remarks for this entry
+ * @return string
+ */
+ public function getRemarks () {
+ return $this->remarks;
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Util.Serializable::serialize()
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "quantity" => $this->getQuantity(),
+ "part_id" => is_object($this->getPart()) ? $this->getPart()->getId() : 0,
+ "part_name" => is_object($this->getPart()) ? $this->getPart()->getName() : 0,
+ "project_id" => $this->getProject()->getId(),
+ "remarks" => $this->getRemarks()
+ );
+ }
+
+ /**
+ * Deserializes the project
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "remarks":
+ $this->setRemarks($value);
+ break;
+ case "quantity":
+ $this->setQuantity($value);
+ break;
+ case "part_id":
+ $part = Part::loadById($value);
+ $this->setPart($part);
+ break;
+ }
+ }
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Project/ProjectService.php b/src/backend/PartKeepr/Project/ProjectService.php
@@ -0,0 +1,64 @@
+<?php
+namespace PartKeepr\Project;
+
+use PartKeepr\Service\RestfulService,
+ PartKeepr\Service\Service,
+ PartKeepr\Project\ProjectManager,
+ PartKeepr\PartKeepr,
+ PartKeepr\Manager\ManagerFilter;
+
+class ProjectService extends Service implements RestfulService {
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return array("data" => ProjectManager::getInstance()->getEntity($this->getParameter("id"))->serialize());
+ } else {
+ $parameters = new ManagerFilter($this);
+ $parameters->setFilterField("name");
+ return ProjectManager::getInstance()->getList($parameters);
+ }
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::create()
+ */
+ public function create () {
+ $this->requireParameter("name");
+
+ $entity = ProjectManager::getInstance()->createEntity($this->getParameters());
+
+ return array("data" => $entity->serialize());
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::update()
+ */
+ public function update () {
+ $this->requireParameter("id");
+ $this->requireParameter("name");
+ $entity = ProjectManager::getInstance()->getEntity($this->getParameter("id"));
+ $entity->deserialize($this->getParameters());
+
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $entity->serialize());
+
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::destroy()
+ */
+ public function destroy () {
+ $this->requireParameter("id");
+
+ ProjectManager::getInstance()->deleteEntity($this->getParameter("id"));
+
+ return array("data" => null);
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/ProjectAttachment/ProjectAttachmentManager.php b/src/backend/PartKeepr/ProjectAttachment/ProjectAttachmentManager.php
@@ -0,0 +1,68 @@
+<?php
+namespace PartKeepr\ProjectAttachment;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\Project\Project,
+ PartKeepr\PartKeepr;
+
+class ProjectAttachmentManager extends Singleton {
+ /**
+ * Returns a list of project attachments
+ *
+ * @param int $start Start of the list, default 0
+ * @param int $limit Number of users to list, default 10
+ * @param string $sort The field to sort by, default "name"
+ * @param string $dir The direction to sort (ASC or DESC), default ASC
+ * @param string $filter The project id
+ */
+ public function getProjectAttachments ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
+
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+ $qb->select("st")->from("PartKeepr\Project\ProjectAttachment","st")
+ ->leftJoin('st.project', "fp");
+
+ if ($filter != "") {
+ $project = Project::loadById($filter);
+ $qb = $qb->where("st.project = :project");
+ $qb->setParameter("project", $project);
+ }
+
+ if ($limit > -1) {
+ $qb->setMaxResults($limit);
+ $qb->setFirstResult($start);
+ }
+
+ $qb->orderBy("st.".$sort, $dir);
+
+ $query = $qb->getQuery();
+
+ $result = $query->getResult();
+
+ $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
+ $totalQueryBuilder->select("COUNT(st.id)")->from("PartKeepr\Project\ProjectAttachment","st");
+
+
+
+ if ($filter != "") {
+ $totalQueryBuilder = $totalQueryBuilder->where("st.project = :project");
+ $totalQueryBuilder->setParameter("project", $project);
+ }
+
+ $totalQuery = $totalQueryBuilder->getQuery();
+
+ $aData = array();
+ foreach ($result as $item) {
+ $aData[] = $item->serialize();
+ }
+ return array("data" => $aData, "totalCount" => $totalQuery->getSingleScalarResult());
+ }
+
+ /**
+ * Returns a project attachment by id
+ * @param int $id The project attachment id
+ */
+ public function getProjectAttachment ($id) {
+ return ProjectAttachment::loadById($id);
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/ProjectAttachment/ProjectAttachmentService.php b/src/backend/PartKeepr/ProjectAttachment/ProjectAttachmentService.php
@@ -0,0 +1,102 @@
+<?php
+namespace PartKeepr\ProjectAttachment;
+
+use PartKeepr\Project\ProjectAttachment,
+ PartKeepr\UploadedFile\TempUploadedFile,
+ PartKeepr\Service\RestfulService,
+ PartKeepr\Service\Service,
+ PartKeepr\PartKeepr,
+ PartKeepr\Project\Project,
+ PartKeepr\Session\SessionManager;
+
+class ProjectAttachmentService extends Service implements RestfulService {
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return ProjectAttachmentManager::getInstance()->getProjectAttachment($this->getParameter("id"))->serialize();
+ } else {
+ if ($this->hasParameter("sort")) {
+ $tmp = json_decode($this->getParameter("sort"), true);
+
+ $aSortParams = $tmp[0];
+ } else {
+ $aSortParams = array(
+ "property" => "id",
+ "direction" => "ASC");
+ }
+
+ $filter = "";
+
+ if ($this->hasParameter("filter")) {
+ $tmp = json_decode($this->getParameter("filter"), true);
+
+ foreach ($tmp as $item) {
+ if (array_key_exists("property", $item)) {
+ if ($item["property"] == "project_id") {
+ if (array_key_exists("value", $item)) {
+ $filter = $item["value"];
+ }
+ }
+ }
+ }
+ }
+ return ProjectAttachmentManager::getInstance()->getProjectAttachments(
+ $this->getParameter("start", $this->getParameter("start", 0)),
+ $this->getParameter("limit", $this->getParameter("limit", 25)),
+ $this->getParameter("sortby", $aSortParams["property"]),
+ $this->getParameter("dir", $aSortParams["direction"]),
+ $filter);
+ }
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::create()
+ */
+ public function create () {
+ $this->requireParameter("tmp_id");
+ $this->requireParameter("project_id");
+
+ $tmpImage = TempUploadedFile::loadById($this->getParameter("tmp_id"));
+
+ $file = new ProjectAttachment();
+
+ $project = Project::loadById($this->getParameter("project_id"));
+
+ $file->setProject($project);
+ $file->replace($tmpImage->getFilename());
+ $file->setOriginalFilename($tmpImage->getOriginalFilename());
+ $file->setDescription($this->getParameter("description"));
+ PartKeepr::getEM()->persist($file);
+ PartKeepr::getEM()->flush();
+
+ return $file->serialize();
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::update()
+ */
+ public function update () {
+
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::destroy()
+ */
+ public function destroy () {
+ $this->requireParameter("id");
+
+ $file = ProjectAttachment::loadById($this->getParameter("id"));
+
+ PartKeepr::getEM()->remove($file);
+ PartKeepr::getEM()->flush();
+
+ return array("data" => null);
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/ProjectReport/ProjectReportService.php b/src/backend/PartKeepr/ProjectReport/ProjectReportService.php
@@ -0,0 +1,97 @@
+<?php
+namespace PartKeepr\ProjectReport;
+
+use PartKeepr\Service\RestfulService,
+ PartKeepr\Service\Service,
+ PartKeepr\Project\ProjectManager,
+ PartKeepr\PartKeepr,
+ PartKeepr\Part\Part,
+ PartKeepr\Manager\ManagerFilter;
+
+class ProjectReportService extends Service implements RestfulService {
+ /**
+ * Returns a project report.
+ *
+ * The input format is an array with the following keys per entry:
+ * - project: The project ID
+ * - amount: Specifies how many copies of the project need to be reported
+ *
+ * The output format is an array which contains the following keys:
+ * - quantity: The overall quantity of parts needed (for a specific part)
+ * - part: The serialized part entity
+ * - storageLocation_name: The storage location name
+ * - available: The overall amount of available parts
+ * - sum_order: Always set to 0 because calculation happens in the frontend
+ *
+ * @see PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ $reports = json_decode($this->getParameter("reports"), true);
+
+ $aPartResults = array();
+
+ // Loop over all reports and calculate the overall quantities
+ foreach ($reports as $report) {
+ $dql = "SELECT pp.quantity, pro.name AS projectname, pp.remarks, p.id FROM ";
+ $dql .= "PartKeepr\Project\ProjectPart pp JOIN pp.part p ";
+ $dql .= "JOIN pp.project pro WHERE pp.project = :project";
+
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("project", $report["project"]);
+
+ foreach ($query->getArrayResult() as $result) {
+ $part = Part::loadById($result["id"]);
+
+ if (array_key_exists($result["id"], $aPartResults)) {
+ // Only update the quantity of the part
+ $aPartResults[$result["id"]]["quantity"] += $result["quantity"] * $report["amount"];
+ $aPartResults[$result["id"]]["projects"][] = $result["projectname"];
+
+ if ($result["remarks"] != "") {
+ $aPartResults[$result["id"]]["remarks"][] = $result["projectname"]. ": " .$result["remarks"];
+ }
+ } else {
+ // Create a full resultset
+ $aPartResults[$result["id"]] = array(
+ "quantity" => $result["quantity"] * $report["amount"],
+ "part" => array("response" => array("totalCount" => 1, "data" => $part->serialize())),
+ "storageLocation_name" => $part->getStorageLocation()->getName(),
+ "available" => $part->getStockLevel(),
+ "sum_order" => 0,
+ "projects" => array($result["projectname"]),
+ "remarks" => array()
+ );
+
+ if ($result["remarks"] != "") {
+ $aPartResults[$result["id"]]["remarks"] = array($result["projectname"]. ": " .$result["remarks"]);
+ }
+ }
+ }
+ }
+
+ $aFinalResult = array();
+
+ // Iterate over all results and calculate how many parts are missing
+ foreach ($aPartResults as $key => $partResult) {
+ $missing = $partResult["quantity"] - $partResult["available"];
+
+ if ($missing < 0) {
+ $missing = 0;
+ }
+
+ $partResult["missing"] = $missing;
+ $partResult["remarks"] = implode(", ", $partResult["remarks"]);
+ $partResult["projects"] = implode(", ", $partResult["projects"]);
+
+ $aFinalResult[] = $partResult;
+ }
+
+ return array("data" => $aFinalResult);
+ }
+
+ public function create () {}
+
+ public function update () {}
+
+ public function destroy () {}
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/REST/ApplicationController.php b/src/backend/PartKeepr/REST/ApplicationController.php
@@ -0,0 +1,42 @@
+<?php
+namespace PartKeepr\REST;
+
+// Class taken over from the Sencha example
+class ApplicationController {
+ public $request, $id, $params;
+
+ /**
+ * dispatch
+ * Dispatch request to appropriate controller-action by convention according to the HTTP method.
+ */
+ public function dispatch($request) {
+ $this->request = $request;
+ $this->id = $request->id;
+ $this->params = $request->params;
+
+ if ($request->isRestful()) {
+ return $this->dispatchRestful();
+ }
+ if ($request->action) {
+ return $this->{$request->action}();
+ }
+ }
+
+ protected function dispatchRestful() {
+ switch ($this->request->method) {
+ case 'GET':
+ return $this->view();
+ break;
+ case 'POST':
+ return $this->create();
+ break;
+ case 'PUT':
+ return $this->update();
+ break;
+ case 'DELETE':
+ return $this->destroy();
+ break;
+ }
+ }
+}
+
diff --git a/src/backend/PartKeepr/REST/Model.php b/src/backend/PartKeepr/REST/Model.php
@@ -0,0 +1,71 @@
+<?php
+namespace PartKeepr\REST;
+
+// Class taken over from the Sencha example
+class Model {
+ public $id, $attributes;
+ static function create($params) {
+ $obj = new self(get_object_vars($params));
+ $obj->save();
+ return $obj;
+ }
+ static function find($id) {
+ global $dbh;
+ $found = null;
+ foreach ($dbh->rs() as $rec) {
+ if ($rec['id'] == $id) {
+ $found = new self($rec);
+ break;
+ }
+ }
+ return $found;
+ }
+ static function update($id, $params) {
+ global $dbh;
+ $rec = self::find($id);
+
+ if ($rec == null) {
+ return $rec;
+ }
+ $rs = $dbh->rs();
+
+ foreach ($rs as $idx => $row) {
+ if ($row['id'] == $id) {
+ $rec->attributes = array_merge($rec->attributes, get_object_vars($params));
+ $dbh->update($idx, $rec->attributes);
+ break;
+ }
+ }
+ return $rec;
+ }
+ static function destroy($id) {
+ global $dbh;
+ $rec = null;
+ $rs = $dbh->rs();
+ foreach ($rs as $idx => $row) {
+ if ($row['id'] == $id) {
+ $rec = new self($dbh->destroy($idx));
+ break;
+ }
+ }
+ return $rec;
+ }
+ static function all() {
+ global $dbh;
+ return $dbh->rs();
+ }
+
+ public function __construct($params) {
+ $this->id = isset($params['id']) ? $params['id'] : null;
+ $this->attributes = $params;
+ }
+ public function save() {
+ global $dbh;
+ $this->attributes['id'] = $dbh->pk();
+ $dbh->insert($this->attributes);
+ }
+ public function to_hash() {
+ return $this->attributes;
+ }
+}
+
diff --git a/src/backend/PartKeepr/REST/Request.php b/src/backend/PartKeepr/REST/Request.php
@@ -0,0 +1,115 @@
+<?php
+namespace PartKeepr\REST;
+
+// Class taken over from the Sencha example
+class Request {
+ public $restful, $method, $controller, $action, $id, $params;
+
+ public function __construct($params) {
+ $this->restful = (isset($params["restful"])) ? $params["restful"] : false;
+ $this->method = $_SERVER["REQUEST_METHOD"];
+ $this->parseRequest();
+ }
+ public function isRestful() {
+ return $this->restful;
+ }
+
+ public function getMethod () {
+ return $this->method;
+ }
+
+ public function getParams () {
+ if ($this->params === null) {
+ $this->params = array();
+ }
+
+ if ($this->id !== null) {
+ $this->params["id"] = $this->id;
+ }
+
+ $this->params = array_merge($_REQUEST, $this->params);
+ return $this->params;
+ }
+
+ public function getService () {
+ if ($this->controller == "") {
+ $this->controller = $_REQUEST["service"];
+ }
+
+ $serviceName = $this->controller."Service";
+ $namespace = 'PartKeepr\\';
+ $cat = $this->controller . "\\";
+ $fullName= $namespace . $cat . $serviceName;
+
+ $class = new $fullName($this->getParams());
+
+ return $class;
+ }
+
+ public function getAction () {
+ return $this->action;
+ }
+
+ protected function parseRequest() {
+ if ($this->method == 'PUT') { // <-- Have to jump through hoops to get PUT data
+ $raw = '';
+ $httpContent = fopen('php://input', 'r');
+ while ($kb = fread($httpContent, 1024)) {
+ $raw .= $kb;
+ }
+ fclose($httpContent);
+ $params = array();
+ parse_str($raw, $params);
+
+ if (isset($params['data'])) {
+ $this->params = json_decode($params['data'], true);
+ } else {
+ $params = json_decode($raw, true);
+ $this->params = $params;
+ }
+ } else {
+ // grab JSON data if there...
+ $this->params = (isset($_REQUEST['data'])) ? json_decode($_REQUEST['data'], true) : null;
+
+ if (isset($_REQUEST['data'])) {
+ $this->params = json_decode($_REQUEST['data'], true);
+ } else {
+ $raw = '';
+ $httpContent = fopen('php://input', 'r');
+ while ($kb = fread($httpContent, 1024)) {
+ $raw .= $kb;
+ }
+ $params = json_decode($raw, true);
+ if ($params) {
+ $this->params = $params;
+ }
+ }
+
+ }
+ // Quickndirty PATH_INFO parser
+ if (isset($_SERVER["PATH_INFO"])){
+ $cai = '/^\/([A-Za-z]+\w)\/([A-Za-z]+\w)\/([0-9]+)$/'; // /controller/action/id
+ $ca = '/^\/([A-Za-z]+\w)\/([A-Za-z]+)$/'; // /controller/action
+ $ci = '/^\/([A-Za-z]+\w)\/([0-9]+)$/'; // /controller/id
+ $c = '/^\/([A-Za-z]+\w)$/'; // /controller
+ $i = '/^\/([0-9]+)$/'; // /id
+ $matches = array();
+ if (preg_match($cai, $_SERVER["PATH_INFO"], $matches)) {
+ $this->controller = $matches[1];
+ $this->action = $matches[2];
+ $this->id = $matches[3];
+ } else if (preg_match($ca, $_SERVER["PATH_INFO"], $matches)) {
+ $this->controller = $matches[1];
+ $this->action = $matches[2];
+ } else if (preg_match($ci, $_SERVER["PATH_INFO"], $matches)) {
+ $this->controller = $matches[1];
+ $this->id = $matches[2];
+ } else if (preg_match($c, $_SERVER["PATH_INFO"], $matches)) {
+ $this->controller = $matches[1];
+ } else if (preg_match($i, $_SERVER["PATH_INFO"], $matches)) {
+ $this->id = $matches[1];
+ }
+ }
+ }
+}
+
diff --git a/src/backend/PartKeepr/REST/Response.php b/src/backend/PartKeepr/REST/Response.php
@@ -0,0 +1,21 @@
+<?php
+namespace PartKeepr\REST;
+
+// Class taken over from the Sencha example
+class Response {
+ public $success, $data, $message, $errors, $tid, $trace;
+
+ public function __construct($params = array()) {
+ $this->success = isset($params["success"]) ? $params["success"] : false;
+ $this->message = isset($params["message"]) ? $params["message"] : '';
+ $this->data = isset($params["data"]) ? $params["data"] : array();
+ }
+
+ public function to_json() {
+ return json_encode(array(
+ 'success' => $this->success,
+ 'message' => $this->message,
+ 'data' => $this->data
+ ));
+ }
+}
diff --git a/src/backend/PartKeepr/Service/AdminService.php b/src/backend/PartKeepr/Service/AdminService.php
@@ -0,0 +1,14 @@
+<?php
+namespace PartKeepr\Service;
+
+use PartKeepr\Session\SessionManager;
+
+class AdminService extends Service {
+ public function mayCall ($call) {
+ if (SessionManager::getCurrentSession()->getUser()->isAdmin()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/src/backend/PartKeepr/Service/AnonService.php b/src/backend/PartKeepr/Service/AnonService.php
@@ -0,0 +1,6 @@
+<?php
+namespace PartKeepr\Service;
+
+class AnonService extends Service {
+
+}
diff --git a/src/backend/PartKeepr/Service/Exceptions/ServiceException.php b/src/backend/PartKeepr/Service/Exceptions/ServiceException.php
@@ -0,0 +1,6 @@
+<?php
+namespace PartKeepr\Service\Exceptions;
+
+use PartKeepr\Util\SerializableException;
+
+class ServiceException extends SerializableException {}
diff --git a/src/backend/PartKeepr/Service/RestfulService.php b/src/backend/PartKeepr/Service/RestfulService.php
@@ -0,0 +1,9 @@
+<?php
+namespace PartKeepr\Service;
+
+interface RestfulService {
+ public function get ();
+ public function create ();
+ public function update ();
+ public function destroy ();
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Service/Service.php b/src/backend/PartKeepr/Service/Service.php
@@ -0,0 +1,110 @@
+<?php
+namespace PartKeepr\Service;
+
+use PartKeepr\User\User,
+ PartKeepr\Session\Session,
+ PartKeepr\Session\SessionManager,
+ PartKeepr\Service\Exceptions\ServiceException;
+
+class Service {
+ private $params;
+
+ public function __construct (Array $params) {
+ $this->params = $params;
+ }
+
+ public function mayCall ($call) {
+ if (SessionManager::getCurrentSession()->getUser() === null) {
+ return false;
+ } else {
+ /* @todo: Implement permission checking */
+ return true;
+ }
+
+
+ }
+
+ protected function requireParameter ($name) {
+ if (!$this->hasParameter($name)) {
+ throw new ServiceException(sprintf("Parameter %s is required.", $name));
+ }
+ }
+
+ public function getParameter ($name, $default = null) {
+ if (!$this->hasParameter($name)) {
+ return $default;
+ } else {
+ return $this->params[$name];
+ }
+ }
+
+ /**
+ * Returns all parameters passed to the service
+ * @return array An array with all parameters (key=>value format)
+ */
+ public function getParameters () {
+ return $this->params;
+ }
+
+ /**
+ * Returns the current user for this session
+ *
+ * @return User The user
+ */
+ public function getUser () {
+ return SessionManager::getCurrentSession()->getUser();
+ }
+
+ /**
+ * Checks if the environment has an active, logged in user.
+ *
+ * @param none
+ * @return boolean True if a logged in user exists, false otherwise
+ */
+ public function hasUser () {
+ if (!$this->hasSession()) {
+ return false;
+ }
+
+ var_dump($this->getUser());
+ if ($this->getUser() !== null) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Checks if there is an active session.
+ *
+ * @param none
+ * @return boolean true if an active session exists, false otherwise
+ */
+ public function hasSession () {
+ return SessionManager::hasSession();
+ }
+
+ public function hasParameter ($name) {
+ if (array_key_exists($name, $this->params)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function hasHeader ($name) {
+ $targetName = "HTTP_".strtoupper($name);
+
+ return array_key_exists($targetName, $_SERVER);
+ }
+
+ public function getHeader ($name) {
+ $targetName = "HTTP_".strtoupper($name);
+
+ if (array_key_exists($targetName, $_SERVER)) {
+ return $_SERVER[$targetName];
+ } else {
+ throw new \Exception("Header ".$targetName." not found");
+ }
+ }
+}
diff --git a/src/backend/PartKeepr/Service/ServiceManager.php b/src/backend/PartKeepr/Service/ServiceManager.php
@@ -0,0 +1,126 @@
+<?php
+namespace PartKeepr\Service;
+
+use PartKeepr\Session\SessionManager,
+ PartKeepr\Service\Exceptions\ServiceException,
+ PartKeepr\PartKeepr,
+ PartKeepr\User\User,
+ PartKeepr\User\UserManager,
+ PartKeepr\REST\Request;
+
+class ServiceManager {
+
+ public static function sendHeaders () {
+ header("Content-Type: text/html; charset=UTF-8");
+ header("Cache-Control: no-cache, must-revalidate");
+ header("Access-Control-Allow-Origin: *");
+ header("Access-Control-Allow-Headers: lang,call,service,X-Requested-With,X-PartKeepr-Locale,X-PartKeepr-Name,X-PartKeepr-Call");
+ }
+
+ public static function call () {
+
+ $request = new Request(array('restful' => true));
+ $service = $request->getService();
+
+ if ($service->hasHeader("call")) {
+ $call = $service->getHeader("call");
+ } elseif (array_key_exists("call", $_REQUEST) && $_REQUEST["call"] != "") {
+ $call = $_REQUEST["call"];
+ } elseif ($request->action != "") {
+ $call = $request->action;
+ } else {
+ switch (strtoupper($request->getMethod())) {
+ case "POST":
+ $call = "create";
+ break;
+ case "GET":
+ $call = "get";
+ break;
+ case "PUT":
+ $call = "update";
+ break;
+ case "DELETE":
+ $call = "destroy";
+ break;
+ default:
+ $call = $request->getMethod();
+ break;
+ }
+ }
+
+ $allowCall = true;
+
+ if (!is_subclass_of($service, "PartKeepr\\Service\\AnonService")) {
+ $session = null;
+ $sessionid = false;
+
+ $sessionid = self::getSession($service);
+
+
+ if ($sessionid === null)
+ {
+ $session = SessionManager::getInstance()->startSession();
+ throw new ServiceException("You called a non-anonymous service, but did not pass the 'session' parameter.");
+ } else {
+ $session = SessionManager::getInstance()->resumeSession($sessionid);
+ }
+
+ if (!$service->mayCall($call)) {
+ $allowCall = false;
+ }
+ }
+
+ if (!$allowCall) {
+ throw new ServiceException("Permission denied");
+ }
+
+ if (!method_exists($service, $call)) {
+ throw new \Exception(sprintf("The service %s doesn't implement %s", get_class($service), $call));
+ }
+ $result = $service->$call();
+
+ PartKeepr::getEM()->flush();
+
+ return $result;
+
+ }
+
+ private static function getSession ($service) {
+ if ($service->hasHeader("username") && $service->hasHeader("password") && !$service->hasHeader("session")) {
+ return self::authenticateByUsername($service->getHeader("username"), $service->getHeader("password"));
+ }
+
+ if (array_key_exists("username", $_REQUEST) && array_key_exists("password", $_REQUEST) && !array_key_exists("session", $_REQUEST)) {
+ return self::authenticateByUsername($_REQUEST["username"], $_REQUEST["password"]);
+ }
+
+ if ($service->hasHeader("session")) {
+ return $service->getHeader("session");
+ }
+
+ if (array_key_exists("session", $_REQUEST)) {
+ return $_REQUEST["session"];
+ }
+ }
+
+ private static function authenticateByUsername ($username, $password) {
+ /* Build a temporary user */
+ $user = new User;
+ $user->setRawUsername($username);
+ $user->setHashedPassword($password);
+
+ $authenticatedUser = UserManager::getInstance()->authenticate($user);
+
+ if ($authenticatedUser !== false) {
+ /* Start Session */
+ $session = SessionManager::getInstance()->startSession($authenticatedUser);
+
+ return $session->getSessionID();
+ } else {
+ throw new InvalidLoginDataException();
+ }
+ }
+
+}
+
+?>+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Session/Exceptions/SessionNotFoundException.php b/src/backend/PartKeepr/Session/Exceptions/SessionNotFoundException.php
@@ -0,0 +1,10 @@
+<?php
+namespace PartKeepr\Session\Exceptions;
+
+use PartKeepr\Util\SerializableException;
+
+class SessionNotFoundException extends SerializableException {
+ public function __construct ($id) {
+ parent::__construct("The session with the id $id could not be found");
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Session/Session.php b/src/backend/PartKeepr/Session/Session.php
@@ -0,0 +1,59 @@
+<?php
+namespace PartKeepr\Session;
+
+use PartKeepr\User\User,
+ PartKeepr\PartKeepr;
+
+/** @Entity */
+class Session {
+
+ /** @Id @Column(type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ */
+ private $id;
+
+ /** @Column(length=50) */
+ private $sessionid;
+
+ /**
+ * @ManyToOne(targetEntity="PartKeepr\User\User")
+ */
+ private $user;
+
+ public function __construct () {
+
+ }
+
+ public function start () {
+ session_start();
+ session_regenerate_id();
+ session_destroy();
+ unset($_SESSION);
+ session_start();
+
+ $query = PartKeepr::getEM()->createQuery("DELETE FROM PartKeepr\\Session\\Session s WHERE s.sessionid = :session");
+ $query->setParameter("session", session_id());
+ $query->execute();
+
+ $this->sessionid = session_id();
+ }
+
+ public function getSessionID () {
+ return $this->sessionid;
+ }
+
+ public function resume () {
+ session_id($this->sessionid);
+ session_start();
+ }
+
+ public function getUser () {
+ return $this->user;
+ }
+
+ public function setUser (User $user = null) {
+ $this->user = $user;
+ }
+
+}
+?>+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Session/SessionManager.php b/src/backend/PartKeepr/Session/SessionManager.php
@@ -0,0 +1,68 @@
+<?php
+namespace PartKeepr\Session;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\User\User,
+ PartKeepr\Session\Exceptions\SessionNotFoundException,
+ PartKeepr\PartKeepr;
+
+class SessionManager extends Singleton {
+ public static $currentSession = null;
+
+ public static function getCurrentSession () {
+ return self::$currentSession;
+ }
+
+ public static function hasSession () {
+ if (self::$currentSession !== null) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function startSession (User $user = null) {
+ if (is_object($user)) {
+ try {
+ $query = PartKeepr::getEM()->createQuery("SELECT s FROM PartKeepr\\Session\\Session s WHERE s.user = :user");
+ $query->setParameter("user", $user);
+ $query->execute();
+
+ $session = $query->getSingleResult();
+ $session->resume();
+ } catch (\Exception $e) {
+ $session = new Session;
+ $session->setUser($user);
+ $session->start();
+ PartKeepr::getEM()->persist($session);
+ }
+ } else {
+ $session = new Session;
+ $session->setUser(null);
+ $session->start();
+ PartKeepr::getEM()->persist($session);
+ }
+
+ PartKeepr::getEM()->flush();
+
+ self::$currentSession = $session;
+
+ return $session;
+ }
+
+ public function resumeSession ($session) {
+ $query = PartKeepr::getEM()->createQuery("SELECT s FROM PartKeepr\\Session\\Session s WHERE s.sessionid = :session");
+ $query->setParameter("session", $session);
+ $query->execute();
+ try {
+ self::$currentSession = $query->getSingleResult();
+ return self::$currentSession;
+ } catch (\Doctrine\ORM\NonUniqueResultException $e) {
+ throw new \Exception("Fatal error: Multiple sessions with id $session found.");
+ } catch (\Doctrine\ORM\NoResultException $e) {
+ throw new SessionNotFoundException($session);
+ }
+
+ }
+}
+?>+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Setup/AbstractSetup.php b/src/backend/PartKeepr/Setup/AbstractSetup.php
@@ -0,0 +1,44 @@
+<?php
+namespace PartKeepr\Setup;
+
+use Doctrine\ORM\EntityManager;
+
+/**
+ * Represents a basic setup step
+ */
+abstract class AbstractSetup {
+ private $console;
+
+ /**
+ * 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 setConsole ($console) {
+ $this->console = $console;
+ }
+
+ public function logMessage ($message) {
+ if ($this->console) {
+ echo "- ".$message."\n";
+ }
+ $this->messages[] = $message;
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Setup/ConfigFileSetup.php b/src/backend/PartKeepr/Setup/ConfigFileSetup.php
@@ -0,0 +1,65 @@
+<?php
+namespace PartKeepr\Setup;
+
+use PartKeepr\Util\Configuration,
+ PartKeepr\PartKeepr,
+ PartKeepr\Util\SerializableException;
+
+/**
+ * Creates or returns a new config file
+ */
+class ConfigFileSetup extends AbstractSetup {
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Setup.AbstractSetup::run()
+ */
+ public function run () {
+ switch ($_REQUEST["mode"]) {
+ case "save":
+ $this->saveConfig();
+ break;
+ case "display":
+ return $this->displayConfig();
+ break;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the configuration file as string, so that it can be displayed
+ * during setup.
+ *
+ * @param none
+ * @return array An array, where the "config" key contains the configuration.
+ */
+ private function displayConfig () {
+ return array("config" => Configuration::dumpConfig());
+ }
+
+ /**
+ * Saves the configuration file.
+ *
+ * @throws SerializableException An exception which describes what has been going wrong
+ */
+ private function saveConfig () {
+ $configFile = PartKeepr::getRootDirectory()."/config.php";
+
+ if (file_exists($configFile)) {
+ if (!is_writable($configFile)) {
+ $message = "The config.php file could not be written, because it already exists and the webserver has ";
+ $message .= "no write access to it.";
+
+ throw new SerializableException($message, 10000);
+ }
+ } else {
+ if (!is_writable(PartKeepr::getRootDirectory())) {
+ $message = "The config.php file could not be written, because the webserver has no write access to it.";
+
+ throw new SerializableException($message, 10001);
+ }
+ }
+ file_put_contents($configFile, Configuration::dumpConfig());
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Setup/FootprintSetup.php b/src/backend/PartKeepr/Setup/FootprintSetup.php
@@ -0,0 +1,156 @@
+<?php
+namespace PartKeepr\Setup;
+
+use PartKeepr\Footprint\FootprintManager,
+ PartKeepr\FootprintCategory\FootprintCategoryManager,
+ PartKeepr\FootprintCategory\FootprintCategory,
+ PartKeepr\Footprint\Footprint,
+ PartKeepr\Footprint\FootprintImage,
+ PartKeepr\Footprint\FootprintAttachment,
+ PartKeepr\PartKeepr,
+ PartKeepr\Setup\Setup;
+
+class FootprintSetup extends AbstractSetup {
+ /**
+ * Holds the migrated footprints
+ * @var array
+ */
+ private static $migratedFootprints = array();
+
+ const FOOTPRINT_PATH = "../setup-data/footprints/";
+ const FOOTPRINT_FILE = "../setup-data/footprints/footprints.yaml";
+
+ /**
+ * Creates the root node for the footprints
+ */
+ 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
+ */
+ public static function getFootprintForOldId ($id) {
+ return FootprintSetup::$migratedFootprints[$id];
+ }
+
+ /**
+ * Creates a node structure for the given path
+ *
+ * @param $path array The components of the path
+ * @param $node Node The parent node
+ */
+ public function addFootprintPath (Array $path, $node) {
+ if (count($path) == 0) {
+ return $node;
+ }
+ $name = array_shift($path);
+
+ $childNode = null;
+
+ foreach ($node->getChildren() as $child) {
+ if ($child->getNode()->getName() == $name) {
+ $childNode = $child;
+ }
+ }
+
+ if ($childNode === null) {
+ $category = new FootprintCategory();
+ $category->setParent($node->getNode()->getId());
+ $category->setName($name);
+ $childNode = FootprintCategoryManager::getInstance()->addCategory($category);
+ }
+
+ return $this->addFootprintPath($path, $childNode);
+ }
+
+ /**
+ * Checks if the specified footprint exists
+ * @param string $name The footprint name
+ */
+ public function footprintExists ($name) {
+ $dql = "SELECT COUNT(fp) FROM 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 function importFootprintData () {
+ $count = 0;
+ $skipped = 0;
+
+ /* Import pre-defined footprints */
+ $data = Setup::loadYAML(self::FOOTPRINT_FILE);
+
+ foreach ($data as $footprintName => $footprintData) {
+ /* 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);
+
+ if (array_key_exists("description", $footprintData)) {
+ $footprint->setDescription($footprintData["description"]);
+ }
+
+ if (array_key_exists("category", $footprintData)) {
+ $footprintCategory = $this->addFootprintPath(explode("/", $footprintData["category"]), FootprintCategoryManager::getInstance()->getRootNode());
+ $footprint->setCategory($footprintCategory->getNode());
+ }
+
+ if (array_key_exists("image", $footprintData)) {
+ $footprintImage = new FootprintImage();
+ $footprintImage->setFootprint($footprint);
+ $footprintImage->replace(self::FOOTPRINT_PATH . $footprintData["image"]);
+
+ $footprint->setImage($footprintImage);
+ }
+
+ if (array_key_exists("attachments", $footprintData) && is_array($footprintData["attachments"])) {
+ foreach ($footprintData["attachments"] as $attachment) {
+ if (!is_array($attachment)) {
+ throw new \Exception("Error: The property 'attachments' of $footprintName is not an array!");
+ }
+ if (array_key_exists("url", $attachment)) {
+ try {
+ $footprintAttachment = new FootprintAttachment();
+ $footprintAttachment->setFootprint($footprint);
+ $footprintAttachment->replaceFromURL($attachment["url"]);
+ if (array_key_exists("description", $attachment)) {
+ $footprintAttachment->setDescription($attachment["description"]);
+ }
+
+ $footprint->getAttachments()->add($footprintAttachment);
+ } catch (\Exception $e) {
+ //echo "error with url ".$attachment["url"]."\n";
+ }
+ }
+
+ }
+ }
+
+ $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/PartKeepr/Setup/ManufacturerSetup.php b/src/backend/PartKeepr/Setup/ManufacturerSetup.php
@@ -0,0 +1,56 @@
+<?php
+namespace PartKeepr\Setup;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\Manufacturer\Manufacturer,
+ PartKeepr\Manufacturer\ManufacturerManager,
+ PartKeepr\Manufacturer\ManufacturerICLogo,
+ PartKeepr\Setup\SiPrefixSetup;
+
+/**
+ * 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 function setupManufacturers () {
+ $count=0;
+ $skipped=0;
+ $data = Setup::loadYAML(self::MANUFACTURER_FILE);
+
+ foreach ($data as $mfgname => $logos) {
+ 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/PartKeepr/Setup/Migration/PartDB/DistributorMigration.php b/src/backend/PartKeepr/Setup/Migration/PartDB/DistributorMigration.php
@@ -0,0 +1,34 @@
+<?php
+namespace PartKeepr\Setup\Migration\PartDB;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\Distributor\Distributor,
+ PartKeepr\Distributor\DistributorManager,
+ 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/PartKeepr/Setup/Migration/PartDB/FootprintMigration.php b/src/backend/PartKeepr/Setup/Migration/PartDB/FootprintMigration.php
@@ -0,0 +1,43 @@
+<?php
+namespace PartKeepr\Setup\Migration\PartDB;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\Footprint\Footprint,
+ PartKeepr\Footprint\FootprintManager,
+ PartKeepr\FootprintCategory\FootprintCategoryManager,
+ 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/PartKeepr/Setup/Migration/PartDB/PartCategoryMigration.php b/src/backend/PartKeepr/Setup/Migration/PartDB/PartCategoryMigration.php
@@ -0,0 +1,50 @@
+<?php
+namespace PartKeepr\Setup\Migration\PartDB;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\PartCategory\PartCategory,
+ PartKeepr\PartCategory\PartCategoryManager,
+ 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/PartKeepr/Setup/Migration/PartDB/PartDBMigration.php b/src/backend/PartKeepr/Setup/Migration/PartDB/PartDBMigration.php
@@ -0,0 +1,71 @@
+<?php
+namespace PartKeepr\Setup\Migration\PartDB;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\Util\Configuration as PartKeeprConfiguration;
+
+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("Ω", "Ω", $string);
+ return $string;
+ }
+}
diff --git a/src/backend/PartKeepr/Setup/Migration/PartDB/PartMigration.php b/src/backend/PartKeepr/Setup/Migration/PartDB/PartMigration.php
@@ -0,0 +1,131 @@
+<?php
+namespace PartKeepr\Setup\Migration\PartDB;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\Part\Part,
+ PartKeepr\Part\PartAttachment,
+ PartKeepr\Part\PartDistributor,
+ PartKeepr\Part\PartManager,
+ PartKeepr\Stock\StockEntry,
+ PartKeepr\Distributor\DistributorManager,
+ PartKeepr\PartCategory\PartCategoryManager,
+ PartKeepr\Footprint\FootprintManager,
+ PartKeepr\PartUnit\PartUnitManager,
+ PartKeepr\StorageLocation\StorageLocationManager,
+ 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/PartKeepr/Setup/Migration/PartDB/StorageLocationMigration.php b/src/backend/PartKeepr/Setup/Migration/PartDB/StorageLocationMigration.php
@@ -0,0 +1,51 @@
+<?php
+namespace PartKeepr\Setup\Migration\PartDB;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\StorageLocation\StorageLocation,
+ PartKeepr\StorageLocation\StorageLocationManager,
+ 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/PartKeepr/Setup/MiscSettingsSetup.php b/src/backend/PartKeepr/Setup/MiscSettingsSetup.php
@@ -0,0 +1,69 @@
+<?php
+namespace PartKeepr\Setup;
+
+use PartKeepr\CronLogger\CronLoggerManager,
+ PartKeepr\PartKeepr;
+
+/**
+ * Sets up misc stuff, which doesn't fit into other steps
+ */
+class MiscSettingsSetup extends AbstractSetup {
+ public function run () {
+ $this->markCronjobsAsRun();
+ $this->clearAPCCache();
+ $this->regenerateProxies();
+ }
+
+ /**
+ * Marks the cronjobs as run, so that the user doesn't get an error during the first day.
+ *
+ * This is necessary because if the user sets up the system and enters the cronjobs, there is a chance
+ * that no cronjob has been ran when he logs in the first time and thus gets confused.
+ */
+ public function markCronjobsAsRun () {
+ foreach (PartKeepr::getRequiredCronjobs() as $cronjob) {
+ CronLoggerManager::getInstance()->markCronRun($cronjob);
+ }
+ }
+
+ /**
+ * Clears the APC cache to push out old entries
+ */
+ public function clearAPCCache () {
+ if (function_exists("apc_clear_cache")) {
+ apc_clear_cache();
+ apc_clear_cache("user");
+ }
+ }
+
+ /**
+ * Re-generates all proxies. This is analog to doctrine orm:generate-proxies
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function regenerateProxies () {
+ $em = $this->entityManager;
+
+ $metadatas = $em->getMetadataFactory()->getAllMetadata();
+ $destPath = $em->getConfiguration()->getProxyDir();
+
+ if ( ! is_dir($destPath)) {
+ mkdir($destPath, 0777, true);
+ }
+
+ $destPath = realpath($destPath);
+
+ if ( ! file_exists($destPath)) {
+ throw new \InvalidArgumentException(
+ sprintf("Proxies destination directory '<info>%s</info>' does not exist.", $em->getConfiguration()->getProxyDir())
+ );
+ } else if ( ! is_writable($destPath)) {
+ throw new \InvalidArgumentException(
+ sprintf("Proxies destination directory '<info>%s</info>' does not have write permissions.", $destPath)
+ );
+ }
+
+ $em->getProxyFactory()->generateProxyClasses($metadatas, $destPath);
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Setup/PartCategorySetup.php b/src/backend/PartKeepr/Setup/PartCategorySetup.php
@@ -0,0 +1,28 @@
+<?php
+namespace PartKeepr\Setup;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\PartCategory\PartCategoryManager,
+ PartKeepr\PartCategory\PartCategory;
+
+class PartCategorySetup extends AbstractSetup {
+ /**
+ * Sets up the root category node
+ */
+ public function setupRootCategory () {
+ PartCategoryManager::getInstance()->ensureRootExists();
+ }
+
+ public function updateCategoryPathCache () {
+ PartCategoryManager::getInstance()->updateCategoryPaths(
+ PartCategoryManager::getInstance()->getRootNode()
+ );
+
+ PartKeepr::getEM()->flush();
+ }
+
+ public function run () {
+ $this->setupRootCategory();
+ $this->updateCategoryPathCache();
+ }
+}
diff --git a/src/backend/PartKeepr/Setup/PartUnitSetup.php b/src/backend/PartKeepr/Setup/PartUnitSetup.php
@@ -0,0 +1,36 @@
+<?php
+namespace PartKeepr\Setup;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\Part\PartUnit;
+
+class PartUnitSetup extends AbstractSetup {
+ /**
+ * Holds the default unit
+ * @var object
+ */
+ private static $defaultUnit;
+
+ /**
+ * Sets up the default part unit if none exists
+ */
+ public function run () {
+ $dql = "SELECT COUNT(p) FROM PartKeepr\Part\PartUnit p WHERE p.is_default = :default";
+ $query = $this->entityManager->createQuery($dql);
+ $query->setParameter("default", true);
+
+ 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/PartKeepr/Setup/SchemaSetup.php b/src/backend/PartKeepr/Setup/SchemaSetup.php
@@ -0,0 +1,34 @@
+<?php
+namespace PartKeepr\Setup;
+
+use 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, true);
+ $this->logMessage("Database Schema created/updated");
+ }
+
+ /**
+ * Checks if the specified database has UTF-8 encoding
+ * @param $connection The DBAL connection
+ * @param string $dbname
+ */
+ public static function mysqlHasUTF8Encoding ($connection, $dbname) {
+ $statement = $connection->prepare("SELECT default_character_set_name FROM information_schema.SCHEMATA S WHERE schema_name = :schema");
+ $statement->bindValue("schema", $dbname);
+ $statement->execute();
+
+ $encoding = $statement->fetchColumn(0);
+
+ if ($encoding != "utf8") {
+ return false;
+ } else {
+ return true;
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Setup/Setup.php b/src/backend/PartKeepr/Setup/Setup.php
@@ -0,0 +1,176 @@
+<?php
+namespace PartKeepr\Setup;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\Util\Configuration as PartKeeprConfiguration;
+
+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 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.
+ *
+ * @param string $step The step to execute
+ * @throws \Exception
+ */
+ 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),
+ "miscsettings" => new MiscSettingsSetup($entityManager)
+ );
+
+ $aActions = array(
+ "configfile" => new ConfigFileSetup($entityManager)
+ );
+ if ($step == "all") {
+ foreach ($aSteps as $step) {
+ $step->setConsole($this->console);
+ $step->run();
+ }
+ } else {
+ if (array_key_exists($step, $aSteps)) {
+ return $aSteps[$step]->run();
+ }
+
+ if (array_key_exists($step, $aActions)) {
+ return $aActions[$step]->run();
+ }
+
+ throw new \Exception(sprintf("Setup step %s doesn't exist", $step));
+ }
+ }
+
+ /**
+ * Tests for APC. Throws an exception if APC is missing or not active.
+ * @throws \Exception
+ */
+ public function testAPC () {
+ if (!extension_loaded("apc")) {
+ throw new \Exception(PartKeepr::i18n("The extension 'apc' is not loaded. Make sure that it is installed (see http://php.net/manual/en/apc.installation.php) and that it is enabled (set apc.enabled=1 in your php.ini)."));
+ }
+ }
+
+ /**
+ * Tests for suitable memory_limit settings
+ * @todo stub
+ */
+ public function testMemoryLimit () {
+ //echo ini_get("memory_limit");
+ }
+
+ /**
+ * Sets the verbose flag
+ * @param boolean $verbose True if verbose output is wanted, false otherwise
+ */
+ public static function setVerbose ($verbose) {
+ Setup::$verbose = $verbose;
+ }
+
+ /**
+ * Outputs a progress message.
+ *
+ * @param string $string The string to output
+ * @param boolean $verbose True if the string should only be printed if verbosity is turned on
+ */
+ public static function progress ($string, $verbose = false) {
+ if (!$verbose || ($verbose && Setup::$verbose)) {
+ echo $string."\n";
+ }
+
+ }
+
+ /**
+ * Loads the given YAML file. Due to an API brach between Doctrine 2.0.5 and Doctrine 2.0.6,
+ * we need to work it around.
+ * @param string $file The path of the file to load
+ * @return array The parsed YAML file
+ */
+ public static function loadYAML ($file) {
+ return \Symfony\Component\Yaml\Yaml::parse($file);
+ }
+
+ /**
+ * Sets the database configuration array from $_REQUEST
+ */
+ public static function setDatabaseConfigurationFromRequest () {
+ if (isset($_REQUEST["dbname"])) {
+ PartKeeprConfiguration::setOption("partkeepr.database.dbname", $_REQUEST["dbname"]);
+ }
+
+ if (isset($_REQUEST["user"])) {
+ PartKeeprConfiguration::setOption("partkeepr.database.username", $_REQUEST["user"]);
+ }
+ if (isset($_REQUEST["password"])) {
+ PartKeeprConfiguration::setOption("partkeepr.database.password", $_REQUEST["password"]);
+ }
+ if (isset($_REQUEST["host"])) {
+ PartKeeprConfiguration::setOption("partkeepr.database.host", $_REQUEST["host"]);
+ }
+
+ if (isset($_REQUEST['port'])) {
+ PartKeeprConfiguration::setOption("partkeepr.database.port", $_REQUEST["port"]);
+ }
+
+ switch ($_REQUEST["driver"]) {
+ case "mysql":
+ PartKeeprConfiguration::setOption("partkeepr.database.driver","pdo_mysql");
+ break;
+ case "pgsql":
+ PartKeeprConfiguration::setOption("partkeepr.database.driver","pdo_pgsql");
+ break;
+ default:
+ throw new \Exception(sprintf("Invalid driver %s specified.", $_REQUEST["driver"]));
+ break;
+ }
+ }
+
+ /**
+ * Runs some checks for the CLI setup
+ */
+ public function runCLIChecks () {
+
+ if (PartKeeprConfiguration::getOption("partkeepr.database.driver") == "pdo_mysql") {
+ $dbname = PartKeeprConfiguration::getOption("partkeepr.database.dbname");
+ if (!SchemaSetup::mysqlHasUTF8Encoding(PartKeepr::getEM()->getConnection(), $dbname )) {
+ echo "Error: The database $dbname hasn't got the UTF-8 encoding. You need to set the database encoding to UTF-8. Aborting.\n";
+ die;
+ }
+ }
+
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Setup/SiPrefixSetup.php b/src/backend/PartKeepr/Setup/SiPrefixSetup.php
@@ -0,0 +1,47 @@
+<?php
+namespace PartKeepr\Setup;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\SiPrefix\SiPrefix,
+ PartKeepr\SiPrefix\SiPrefixManager;
+
+class SiPrefixSetup extends AbstractSetup {
+
+ const SIPREFIX_DATA_FILE = "../setup-data/siprefixes.yaml";
+
+ /**
+ * Stores the migrated si prefixes
+ * @var array
+ */
+ private static $siPrefixes = array();
+
+ public function run () {
+ $this->setupSiPrefixes();
+ }
+
+ /**
+ * Sets up the SI prefixes
+ */
+ public function setupSiPrefixes () {
+ $count = 0;
+ $skipped = 0;
+
+ $data = Setup::loadYAML(self::SIPREFIX_DATA_FILE);
+
+ foreach ($data as $prefixName => $prefixData) {
+ if (!SiPrefixManager::getInstance()->siPrefixExists($prefixName)) {
+ $prefix = new SiPrefix();
+ $prefix->setPrefix($prefixName);
+ $prefix->setPower($prefixData["power"]);
+ $prefix->setSymbol($prefixData["symbol"]);
+ $this->entityManager->persist($prefix);
+ $count++;
+ } else {
+ $skipped++;
+ }
+ }
+
+ $this->entityManager->flush();
+ $this->logMessage(sprintf("Imported %d Si Prefixes, skipped %d", $count, $skipped));
+ }
+}
diff --git a/src/backend/PartKeepr/Setup/UnitSetup.php b/src/backend/PartKeepr/Setup/UnitSetup.php
@@ -0,0 +1,62 @@
+<?php
+namespace PartKeepr\Setup;
+
+use PartKeepr\PartKeepr,
+ PartKeepr\Unit\Unit,
+ PartKeepr\SiPrefix\SiPrefixManager,
+ PartKeepr\Unit\UnitManager,
+ PartKeepr\Setup\SiPrefixSetup;
+
+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 function setupUnits () {
+ $count = 0;
+ $skipped = 0;
+ $data = Setup::loadYAML(self::UNIT_DATA_FILE);
+
+ $aUnits = array();
+
+ foreach ($data as $unitName => $unitData) {
+ if (UnitManager::getInstance()->unitExists($unitName)) {
+ $skipped++;
+ continue;
+ }
+ $unit = new Unit();
+ $unit->setName($unitName);
+ $unit->setSymbol($unitData["symbol"]);
+
+ if (array_key_exists("prefixes", $unitData)) {
+ if (!is_array($unitData["prefixes"])) {
+ throw new \Exception($unitName." doesn't contain a prefix list, or the prefix list is not an array.");
+ }
+
+ foreach ($unitData["prefixes"] as $prefix) {
+
+ $siPrefix = SiPrefixManager::getInstance()->getSiPrefixBySymbol($prefix);
+ if ($siPrefix === false) {
+ throw new \Exception("Unable to find prefix ".$prefix);
+ }
+ $unit->getPrefixes()->add($siPrefix);
+ }
+ }
+
+ 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/PartKeepr/Setup/UserSetup.php b/src/backend/PartKeepr/Setup/UserSetup.php
@@ -0,0 +1,31 @@
+<?php
+namespace PartKeepr\Setup;
+
+use 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 PartKeepr\User\User u WHERE u.username = :username OR u.admin = :admin";
+ $query = $this->entityManager->createQuery($dql);
+ $query->setParameter("username", "admin");
+ $query->setParameter("admin", true);
+
+ 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/PartKeepr/SiPrefix/SiPrefix.php b/src/backend/PartKeepr/SiPrefix/SiPrefix.php
@@ -0,0 +1,91 @@
+<?php
+namespace PartKeepr\SiPrefix;
+
+use PartKeepr\Util\BaseEntity,
+ PartKeepr\PartKeepr,
+ PartKeepr\Util\Exceptions\OutOfRangeException;
+
+
+/** @Entity **/
+class SiPrefix extends BaseEntity {
+ /**
+ * The prefix of the Si-Prefix (e.g. yotta, deca, deci, centi)
+ * @Column(type="string")
+ * @var string
+ */
+ private $prefix;
+
+ /**
+ * The symbol of the Si-Prefix (e.g. m, M, G)
+ * @Column(type="string",length=2)
+ * @var string
+ */
+ private $symbol;
+
+ /**
+ * The power of the Si-Prefix (e.g. milli = 10^-3)
+ * @Column(type="integer")
+ * @var int
+ */
+ private $power;
+
+ /**
+ * Sets the prefix name.
+ * @param string $prefix
+ */
+ public function setPrefix ($prefix) {
+ $this->prefix = $prefix;
+ }
+
+ /**
+ * Returns the prefix name
+ * @return string The prefix name
+ */
+ public function getPrefix () {
+ return $this->prefix;
+ }
+
+ /**
+ * Sets the symbol for the prefix
+ * @param string $symbol The symbol
+ */
+ public function setSymbol ($symbol) {
+ $this->symbol = $symbol;
+ }
+
+ /**
+ * Returns the symbol for the prefix
+ * @return string The symbol
+ */
+ public function getSymbol () {
+ return $this->symbol;
+ }
+
+ /**
+ * Sets the power in a 10^n power (n=power)
+ * @param int $power The 10^power
+ */
+ public function setPower ($power) {
+ $this->power = $power;
+ }
+
+ /**
+ * Returns the power (10^n)
+ * @return int The power
+ */
+ public function getPower () {
+ return $this->power;
+ }
+
+ /**
+ * Serializes the object into an array format.
+ * @return array the object in serialized format.
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "symbol" => $this->getSymbol(),
+ "prefix" => $this->getPrefix(),
+ "power" => $this->getPower());
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/SiPrefix/SiPrefixManager.php b/src/backend/PartKeepr/SiPrefix/SiPrefixManager.php
@@ -0,0 +1,42 @@
+<?php
+namespace PartKeepr\SiPrefix;
+
+use PartKeepr\Util\Singleton,
+ 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 PartKeepr\SiPrefix\SiPrefix sip";
+ $query = PartKeepr::getEM()->createQuery($dql);
+
+ $this->siPrefixSymbolCache = $query->getResult();
+ }
+
+ public function siPrefixExists ($prefix) {
+ $dql = "SELECT COUNT(sip) FROM 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/PartKeepr/SiPrefix/SiPrefixService.php b/src/backend/PartKeepr/SiPrefix/SiPrefixService.php
@@ -0,0 +1,27 @@
+<?php
+namespace PartKeepr\SiPrefix;
+
+use PartKeepr\Service\RestfulService,
+ PartKeepr\Service\Service,
+ PartKeepr\PartKeepr,
+ PartKeepr\Session\SessionManager;
+
+class SiPrefixService extends Service implements RestfulService {
+ public function get () {
+ $query = PartKeepr::getEM()->createQuery("SELECT si.id, si.prefix, si.symbol, si.power FROM PartKeepr\SiPrefix\SiPrefix si");
+
+ return array("data" => $query->getArrayResult());
+ }
+
+ public function create () {
+ throw new \Exception("Not yet implemented");
+ }
+
+ public function update () {
+ throw new \Exception("Not yet implemented");
+ }
+
+ public function destroy () {
+ throw new \Exception("Not yet implemented");
+ }
+}
diff --git a/src/backend/PartKeepr/Statistic/StatisticService.php b/src/backend/PartKeepr/Statistic/StatisticService.php
@@ -0,0 +1,148 @@
+<?php
+namespace PartKeepr\Statistic;
+
+use PartKeepr\Part\PartUnit,
+ PartKeepr\Service\Service,
+ PartKeepr\PartKeepr,
+ PartKeepr\Part\PartManager,
+ PartKeepr\PartCategory\PartCategoryManager,
+ PartKeepr\PartUnit\PartUnitManager;
+
+class StatisticService extends Service {
+ public function getCurrentStats () {
+
+ $aData = array();
+ $aData["partCount"] = PartManager::getInstance()->getPartCount();
+ $aData["categoryCount"] = PartCategoryManager::getInstance()->getCategoryCount();
+ $aData["totalPrice"] = PartManager::getInstance()->getTotalPrice();
+ $aData["averagePrice"] = PartManager::getInstance()->getAveragePrice();
+ $aData["partsWithPrice"] = PartManager::getInstance()->getPartCount(true);
+ $aData["partsWithoutPrice"] = $aData["partCount"] - $aData["partsWithPrice"];
+
+ $result = PartUnitManager::getInstance()->getUnitCounts();
+
+ $aUnits = array();
+
+ foreach ($result as $row) {
+ $aUnits[] = array(
+ "name" => PartUnit::loadById($row["puid"])->getName(),
+ "stockLevel" => $row["stockLevel"]);
+ }
+
+ $aData["units"] = $aUnits;
+
+ return $aData;
+ }
+
+ /**
+ * Returns the range of all recorded statistic snapshots.
+ */
+ public function getStatisticRange () {
+ $dql = "SELECT MIN(sts.dateTime), MAX(sts.dateTime) FROM PartKeepr\Statistic\StatisticSnapshot sts";
+ $query = PartKeepr::getEM()->createQuery($dql);
+
+ $data = $query->getArrayResult();
+
+ return array("data" => array("start" => $data[0][1], "end" => $data[0][2]));
+
+ }
+ /**
+ * Returns sampled statistics from the database.
+ *
+ * This call takes a start and an end time, and calculates a set of statistics
+ * for each interval.
+ *
+ * The sampleSize, which has a default of 50, specifies how many single statistic
+ * points in the given date interval will be returned.
+ *
+ * This function interpolates the statistics if there are not enough statistic samples available.
+ */
+ public function getSampledStatistics () {
+ $fooStart = microtime(true);
+
+ $this->requireParameter("startDateTime");
+ $this->requireParameter("endDateTime");
+
+
+ $start = \DateTime::createFromFormat("Y-m-d H:i:s", $this->getParameter("startDateTime"));
+ $end = \DateTime::createFromFormat("Y-m-d H:i:s", $this->getParameter("endDateTime"));
+
+ if ($start->getTimestamp() > $end->getTimestamp()) {
+ // Swap both times
+ list($start, $end) = array($end, $start);
+ }
+
+ if ($this->hasParameter("sampleSize")) {
+ $sampleSize = $this->getParameter("sampleSize");
+ } else {
+ $sampleSize = 25;
+ }
+
+ $intervalSize = intval(($end->getTimestamp() - $start->getTimestamp()) / $sampleSize);
+
+ $queryStartTime = clone $start;
+ $queryEndTime = clone $start;
+ $queryEndTime->add(new \DateInterval("PT".$intervalSize."S"));
+
+ $partUnitQuery = "SELECT pu FROM PartKeepr\Part\PartUnit pu";
+ $query = PartKeepr::getEM()->createQuery($partUnitQuery);
+
+ $aPartUnits = $query->getResult();
+
+ $aRecords = array();
+
+ $dql = "SELECT AVG(sts.parts) AS parts, AVG(sts.categories) AS categories FROM PartKeepr\Statistic\StatisticSnapshot sts WHERE sts.dateTime >= :start AND sts.dateTime <= :end";
+ $mainQuery = PartKeepr::getEM()->createQuery($dql);
+
+ $dql = "SELECT AVG(stsu.stockLevel) AS stockLevel FROM PartKeepr\Statistic\StatisticSnapshotUnit stsu JOIN stsu.statisticSnapshot sts WHERE sts.dateTime >= :start AND sts.dateTime <= :end AND stsu.partUnit = :partUnit";
+ $subQuery = PartKeepr::getEM()->createQuery($dql);
+
+ for ($i=0;$i<$sampleSize;$i++) {
+
+
+ $mainQuery->setParameter("start", $queryStartTime);
+ $mainQuery->setParameter("end", $queryEndTime);
+
+ $result = $mainQuery->getResult();
+
+ $record = $result[0];
+
+ if ($record["parts"] !== null) {
+ $record["parts"] = floatval($record["parts"]);
+ }
+
+ if ($record["categories"] !== null) {
+ $record["categories"] = floatval($record["categories"]);
+ }
+
+ foreach ($aPartUnits as $partUnit) {
+ $subQuery->setParameter("start", $queryStartTime);
+ $subQuery->setParameter("end", $queryEndTime);
+ $subQuery->setParameter("partUnit", $partUnit);
+
+ $aResult = $subQuery->getResult();
+
+ if ($aResult[0]["stockLevel"] !== null) {
+ $record["units"][$partUnit->getName()] = floatval($aResult[0]["stockLevel"]);
+ } else {
+ $record["units"][$partUnit->getName()] = null;
+ }
+
+ }
+
+ $record["start"] = $queryStartTime->format("Y-m-d H:i:s");
+
+ if ($record["parts"] !== null) {
+ $aRecords[] = $record;
+ }
+
+
+ $queryStartTime->add(new \DateInterval("PT".$intervalSize."S"));
+ $queryEndTime->add(new \DateInterval("PT".$intervalSize."S"));
+ }
+
+
+ return array("status" => "ok", "data" => $aRecords);
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Statistic/StatisticSnapshot.php b/src/backend/PartKeepr/Statistic/StatisticSnapshot.php
@@ -0,0 +1,109 @@
+<?php
+namespace PartKeepr\Statistic;
+
+use PartKeepr\PartKeepr;
+
+/** @Entity **/
+class StatisticSnapshot {
+ /**
+ * @Id @Column(type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ * @var integer
+ */
+ private $id;
+
+ /**
+ * Defines the date when this snapshot has been taken
+ * @Column(type="datetime")
+ * @var DateTime
+ */
+ private $dateTime;
+
+ /**
+ * Defines the amount of different parts in the database
+ * @Column(type="integer")
+ * @var int
+ */
+ private $parts;
+
+ /**
+ * Defines the amount of categories
+ * @Column(type="integer")
+ * @var int
+ */
+ private $categories;
+
+ /**
+ * Holds all defined units in the database
+ * @OneToMany(targetEntity="PartKeepr\Statistic\StatisticSnapshotUnit",mappedBy="statisticSnapshot",cascade={"persist", "remove"})
+ */
+ private $units;
+
+ /**
+ * Creates a new statistic snapshot
+ */
+ public function __construct () {
+ $this->units = new \Doctrine\Common\Collections\ArrayCollection();
+ $this->setDateTime(new \DateTime());
+ }
+
+ /**
+ * Sets the date+time for the snapshot
+ * @param \DateTime $dateTime The date+time for the snapshot
+ */
+ public function setDateTime (\DateTime $dateTime) {
+ $this->dateTime = $dateTime;
+ }
+
+ /**
+ * Returns the date+time for the snapshot
+ * @return DateTime The date+time for the snapshot
+ */
+ public function getDateTime () {
+ return $this->dateTime;
+ }
+
+ /**
+ * Sets the amount of overall parts for the snapshot
+ * @param int $parts The amount of parts
+ */
+ public function setParts ($parts) {
+ $this->parts = $parts;
+ }
+
+ /**
+ * Returns the amount of overall parts for the snapshot
+ * @return int The amount of parts
+ */
+ public function getParts () {
+ return $this->parts;
+ }
+
+ /**
+ * Sets the amount of categories for the snapshot
+ * @param int $categories The amount of categories
+ */
+ public function setCategories ($categories) {
+ $this->categories = $categories;
+ }
+
+ /**
+ * Returns the amount of categories
+ * @return int The amount of categories
+ */
+ public function getCategories () {
+ return $this->categories;
+ }
+
+ /**
+ * Returns the ID of this snapshot
+ * @return int The ID of this snapshot
+ */
+ public function getId () {
+ return $this->id;
+ }
+
+ public function getUnits () {
+ return $this->units;
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Statistic/StatisticSnapshotManager.php b/src/backend/PartKeepr/Statistic/StatisticSnapshotManager.php
@@ -0,0 +1,38 @@
+<?php
+namespace PartKeepr\Statistic;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\Part\PartUnit,
+ PartKeepr\Part\PartManager,
+ PartKeepr\PartUnit\PartUnitManager,
+ PartKeepr\PartKeepr,
+ PartKeepr\PartCategory\PartCategoryManager,
+ PartKeepr\PartUnit\Exceptions\PartUnitNotFoundException;
+
+class StatisticSnapshotManager extends Singleton {
+ public function createSnapshot () {
+
+ $snapshot = new StatisticSnapshot();
+ $snapshot->setParts(PartManager::getInstance()->getPartCount());
+ $snapshot->setCategories(PartCategoryManager::getInstance()->getCategoryCount());
+
+ $result = PartUnitManager::getInstance()->getUnitCounts();
+
+ foreach ($result as $row) {
+ $snapshotUnit = new StatisticSnapshotUnit();
+ $snapshotUnit->setPartUnit(PartUnit::loadById($row["puid"]));
+ $snapshotUnit->setStatisticSnapshot($snapshot);
+
+ if ($row["stockLevel"] !== null) {
+ $snapshotUnit->setStockLevel($row["stockLevel"]);
+ } else {
+ $snapshotUnit->setStockLevel(0);
+ }
+
+ $snapshot->getUnits()->add($snapshotUnit);
+ }
+
+ PartKeepr::getEM()->persist($snapshot);
+ PartKeepr::getEM()->flush();
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Statistic/StatisticSnapshotUnit.php b/src/backend/PartKeepr/Statistic/StatisticSnapshotUnit.php
@@ -0,0 +1,95 @@
+<?php
+namespace PartKeepr\Statistic;
+
+use PartKeepr\Statistic\StatisticSnapshot,
+ PartKeepr\Part\PartUnit,
+ PartKeepr\PartKeepr;
+
+
+/** @Entity **/
+class StatisticSnapshotUnit {
+ /**
+ * @Id @Column(type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ * @var integer
+ */
+ private $id;
+
+ /**
+ * @ManyToOne(targetEntity="PartKeepr\Statistic\StatisticSnapshot")
+ * The statistic snapshot this entity belongs to
+ * @var StatisticSnapshot
+ */
+ private $statisticSnapshot;
+
+ /**
+ * @ManyToOne(targetEntity="PartKeepr\Part\PartUnit")
+ * The statistic snapshot this entity belongs to
+ * @var StatisticSnapshot
+ */
+ private $partUnit;
+
+ /**
+ * The stockLevel for the unit
+ * @Column(type="integer")
+ * @var int
+ */
+ private $stockLevel;
+
+ /**
+ * Sets the statistic snapshot this entity belongs to
+ * @param StatisticSnapshot $snapshot The snapshot
+ */
+ public function setStatisticSnapshot (StatisticSnapshot $snapshot) {
+ $this->statisticSnapshot = $snapshot;
+ }
+
+ /**
+ * Returns the snapshot this entity belongs to
+ * @return StatisticSnapshot The snapshot
+ */
+ public function getStatisticSnapshot () {
+ return $this->statisticSnapshot;
+ }
+
+ /**
+ *
+ * Sets the part unit for this entity
+ * @param PartUnit $unit The part unit
+ */
+ public function setPartUnit (PartUnit $unit) {
+ $this->partUnit = $unit;
+ }
+
+ /**
+ * Returns the part unit for this entity
+ * @return PartUnit The part unit
+ */
+ public function getPartUnit () {
+ return $this->partUnit;
+ }
+
+ /**
+ * Returns the ID of this statistic snapshot unit
+ * @return int The ID
+ */
+ public function getId () {
+ return $this->id;
+ }
+
+ /**
+ * Sets the stock level for this unit snapshot
+ * @param int $stockLevel
+ */
+ public function setStockLevel ($stockLevel) {
+ $this->stockLevel = $stockLevel;
+ }
+
+ /**
+ * Returns the stock level for this unit snapshot
+ * @return int The stock level
+ */
+ public function getStockLevel () {
+ return $this->stockLevel;
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Stock/StockEntry.php b/src/backend/PartKeepr/Stock/StockEntry.php
@@ -0,0 +1,239 @@
+<?php
+namespace PartKeepr\Stock;
+
+use PartKeepr\Part\Part,
+ PartKeepr\User\User,
+ PartKeepr\PartKeepr,
+ PartKeepr\Util\BaseEntity,
+ PartKeepr\Util\Serializable;
+
+/** @Entity @HasLifecycleCallbacks **/
+class StockEntry extends BaseEntity implements Serializable {
+ /**
+ * @Column(type="integer")
+ */
+ private $stockLevel;
+
+ /**
+ * @ManyToOne(targetEntity="PartKeepr\Part\Part")
+ */
+ private $part;
+
+ /**
+ * @ManyToOne(targetEntity="PartKeepr\User\User")
+ */
+ private $user;
+
+ /**
+ * @Column(type="decimal",precision=13,scale=4,nullable=true)
+ * @var float
+ */
+ private $price;
+
+ /**
+ * @Column(type="datetime")
+ * @var DateTime
+ */
+ private $dateTime;
+
+ /**
+ * Indicates if the stock level is a correction entry.
+ *
+ * @Column(type="boolean")
+ * @var boolean
+ */
+ private $correction;
+
+ /**
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $comment;
+
+
+ /**
+ * Creates a new stock entry. A stock entry tracks how many parts
+ * were the stockLevel is the amount of items added/removed,
+ * by which user and how much the user paid for it (for adding parts only!)
+ *
+ * @param Part $part The part which was added/removed
+ * @param int $stockLevel The stock level. Positive value means added parts, negative values means removed parts.
+ * @param User $user The user who removed/added parts
+ */
+ public function __construct (Part $part, $stockLevel, User $user = null) {
+ $this->setPart($part);
+ $this->setStockLevel($stockLevel);
+ $this->setUser($user);
+ $this->setDateTime(new \DateTime());
+ $this->setCorrection(false);
+ }
+
+
+ /**
+ * Sets the date+time
+ * @param \DateTime $dateTime The date+time
+ */
+ private function setDateTime (\DateTime $dateTime) {
+ $this->dateTime = $dateTime;
+ }
+
+ /**
+ * Returns the date+time when the record was created.
+ * @return \DateTime The date+time when the record was created
+ */
+ public function getDateTime () {
+ return $this->dateTime;
+ }
+
+ /**
+ * Sets if the stock entry is a correction record.
+ * @param $bCorrection boolean True if the record is a correction record, false otherwise
+ */
+ public function setCorrection ($bCorrection) {
+ $this->correction = $bCorrection;
+ }
+
+ /**
+ * Returns if the entry is a correction entry.
+ * @return boolean True if the entry is a correction entry, false otherwise
+ */
+ public function getCorrection () {
+ return $this->correction;
+ }
+
+ /**
+ * Sets the price for the item stored.
+ *
+ * Please note that the price is for a single item only, and can be null.
+ * @param float $price The price to set
+ */
+ public function setPrice ($price) {
+ $this->price = $price;
+ }
+
+ /**
+ * Returns the price for this entry. The price is for a single item only.
+ *
+ * @return float The price for this entry.
+ */
+ public function getPrice () {
+ return $this->price;
+ }
+
+ /**
+ * Sets the stock level for this entry.
+ *
+ * Negative values means part removal, positive values means part adding.
+ * @param int $stockLevel The stock level
+ */
+ public function setStockLevel($stockLevel) {
+ $this->stockLevel = $stockLevel;
+ }
+
+ /**
+ * Returns the stock level for this entry.
+ * @return int The stock level
+ */
+ public function getStockLevel () {
+ return $this->stockLevel;
+ }
+
+ /**
+ * Sets the part assigned to this entry.
+ * @param Part $part The part to set
+ */
+ public function setPart (Part $part) {
+ $this->part = $part;
+ }
+
+ /**
+ * Returns the part assigned to this entry.
+ * @return Part $part The part
+ */
+ public function getPart () {
+ return $this->part;
+ }
+
+ /**
+ * Sets the user assigned to this entry.
+ * @param User $user The user The user to set
+ */
+ public function setUser (User $user = null) {
+ $this->user = $user;
+ }
+
+ /**
+ * Returns the user for this entry
+ * @return User the user
+ */
+ public function getUser () {
+ return $this->user;
+ }
+
+ /**
+ * If the stock level is negative, we can't have a price.
+ * @PrePersist
+ */
+ public function checkPrice () {
+ if ($this->getStockLevel() < 0 && $this->getPrice() !== null) {
+ $this->setPrice(null);
+ }
+ }
+
+ /**
+ * Updates the stock leve for a part
+ * @PostPersist
+ */
+ public function postPersist () {
+ $this->part->updateStockLevel();
+ $this->part->updatePrice();
+ }
+
+ /**
+ * Returns if the current stock entry is a removal.
+ * @return boolean True if the entry is a removal, false otherwise
+ */
+ public function isRemoval () {
+ if ($this->getStockLevel() < 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Sets a comment
+ * @param string $comment
+ */
+ public function setComment ($comment) {
+ $this->comment = $comment;
+ }
+
+ /**
+ * Returns the comment
+ * @return string The comment
+ */
+ public function getComment () {
+ return $this->comment;
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Util.Serializable::serialize()
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "part_name" => $this->getPart()->getName(),
+ "part_id" => $this->getPart()->getId(),
+ "storageLocation_name" => $this->getPart()->getStorageLocation()->getName(),
+ "username" => is_object($this->getUser()) ? $this->getUser()->getUsername() : PartKeepr::i18n("Unknown User"),
+ "user_id" => is_object($this->getUser()) ? $this->getUser()->getId() : null,
+ "stockLevel" => abs($this->getStockLevel()),
+ "comment" => $this->getComment(),
+ "dateTime" => $this->getDateTime()->format("Y-m-d H:i:s"),
+ "direction" => ($this->getStockLevel() < 0) ? "out" : "in",
+ "price" => $this->getPrice()
+ );
+ }
+}
diff --git a/src/backend/PartKeepr/Stock/StockManager.php b/src/backend/PartKeepr/Stock/StockManager.php
@@ -0,0 +1,66 @@
+<?php
+namespace PartKeepr\Stock;
+
+use PartKeepr\Manager\AbstractManager,
+ Doctrine\ORM\QueryBuilder,
+ PartKeepr\Manager\ManagerFilter,
+ PartKeepr\PartKeepr;
+
+class StockManager extends AbstractManager {
+ /**
+ * Returns the FQCN for the target entity to operate on.
+ * @return string The FQCN, e.g. PartKeepr\Part
+ */
+ public function getEntityName () {
+ return 'PartKeepr\Stock\StockEntry';
+ }
+
+ /**
+ * Returns all fields which need to appear in the getList ResultSet.
+ * @return array An array of all fields which should be returned
+ */
+ public function getQueryFields () {
+ return array();
+ }
+
+ /**
+ * Returns the default sort field
+ *
+ * @return string The default sort field
+ */
+ public function getDefaultSortField () {
+ return "dateTime";
+ }
+
+ /**
+ * Applies a custom query to the QueryBuilder
+ *
+ * @param QueryBuilder $qb The query builder
+ * @param ManagerFilter $filter The query filter
+ */
+ protected function applyCustomQuery (QueryBuilder $qb, ManagerFilter $filter) {
+
+ // Apply special handling for non-direct fields in relations, where the frontend has no idea about.
+ foreach ($filter->getSorters() as $sorter) {
+ switch ($sorter->getSortField()) {
+ case "q.part_name":
+ $qb->join("q.part", "p");
+ $sorter->setSortField("p.name");
+ break;
+ case "q.user_id":
+ $qb->leftJoin("q.user", "u");
+ $sorter->setSortField("u.username");
+ break;
+ case "q.direction":
+ $sorter->setSortField("q.dateTime");
+ break;
+ case "q.storageLocation_name":
+ $qb->join("q.part", "p")->join("p.storageLocation", "st");
+ $sorter->setSortField("st.name");
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Stock/StockService.php b/src/backend/PartKeepr/Stock/StockService.php
@@ -0,0 +1,93 @@
+<?php
+namespace PartKeepr\Stock;
+
+use PartKeepr\Stock\StockEntry,
+ PartKeepr\PartKeepr,
+ PartKeepr\User\User,
+ PartKeepr\Manager\ManagerFilter,
+ PartKeepr\Session\SessionManager,
+ PartKeepr\Service\RestfulService,
+ PartKeepr\Service\Service;
+
+class StockService extends Service implements RestfulService {
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return array("data" => StockManager::getInstance()->getEntity($this->getParameter("id"))->serialize());
+ } else {
+ $parameters = new ManagerFilter($this);
+ $parameters->setFilterField("name");
+
+ if ($this->hasParameter("part")) {
+ $parameters->setFilterCallback(array($this, "filterCallback"));
+ }
+ return StockManager::getInstance()->getList($parameters);
+ }
+ }
+
+ /**
+ * If the "part" parameter is set, join the part into the result and filter on that
+ * @param QueryBuilder The $queryBuilder
+ */
+ public function filterCallback ($queryBuilder) {
+ $queryBuilder->andWhere("q.part = :part");
+ $queryBuilder->setParameter("part", $this->getParameter("part"));
+ }
+
+ public function create () {
+ throw new \Exception("Not yet implemented");
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::update()
+ */
+ public function update () {
+ $this->requireParameter("id");
+
+ $stockEntry = StockEntry::loadById($this->getParameter("id"));
+
+ if (!SessionManager::getCurrentSession()->getUser()->isAdmin() &&
+ !(SessionManager::getCurrentSession()->getUser() && $stockEntry->getUser() && SessionManager::getCurrentSession()->getUser()->getId() == $stockEntry->getUser()->getId() )) {
+ throw new \Exception("Permission denied");
+ }
+
+ /* It's not allowed to edit a price for a removal */
+ if (!$stockEntry->isRemoval()) {
+ $stockEntry->setPrice(abs($this->getParameter("price")));
+ }
+
+ /**
+ * Only an admin user may correct the in&out stock levels
+ */
+ if (SessionManager::getCurrentSession()->getUser()->isAdmin()) {
+ if ($this->getParameter("direction") == "out") {
+ $stockEntry->setStockLevel(-(abs($this->getParameter("stockLevel"))));
+ } else {
+ $stockEntry->setStockLevel($this->getParameter("stockLevel"));
+ }
+
+ }
+
+ if (SessionManager::getCurrentSession()->getUser()->isAdmin()) {
+ try {
+ $stockEntry->setUser(User::loadById($this->getParameter("user_id")));
+ } catch (\Exception $e) {
+ $stockEntry->setUser(null);
+ }
+
+ }
+
+ $stockEntry->setComment($this->getParameter("comment"));
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $stockEntry->serialize());
+ }
+
+ public function destroy () {
+ throw new \Exception("Not yet implemented");
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/StorageLocation/Exceptions/StorageLocationNotFoundException.php b/src/backend/PartKeepr/StorageLocation/Exceptions/StorageLocationNotFoundException.php
@@ -0,0 +1,12 @@
+<?php
+namespace PartKeepr\StorageLocation\Exceptions;
+
+use PartKeepr\Util\SerializableException,
+ PartKeepr\PartKeepr;
+
+class StorageLocationNotFoundException extends SerializableException {
+ public function __construct () {
+ parent::__construct(PartKeepr::i18n("Storage Location not found."));
+ }
+}
+?>+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/StorageLocation/StorageLocation.php b/src/backend/PartKeepr/StorageLocation/StorageLocation.php
@@ -0,0 +1,105 @@
+<?php
+namespace PartKeepr\StorageLocation;
+
+use PartKeepr\Util\Deserializable,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Util\BaseEntity;
+
+/** @Entity **/
+class StorageLocation extends BaseEntity implements Serializable, Deserializable {
+ /**
+ * Holds the name for our storage location
+ * @Column(type="string",unique=true)
+ * @var string
+ */
+ private $name;
+
+ /**
+ * Holds the storage location image
+ * @OneToOne(targetEntity="PartKeepr\StorageLocation\StorageLocationImage",mappedBy="storageLocation",cascade={"persist", "remove"})
+ * @var StorageLocationImage
+ */
+ private $image;
+
+ /**
+ * Sets the name for the storage location
+ * @param string $name the name to set
+ */
+ public function setName ($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the name of the storage location
+ * @return string The name
+ */
+ public function getName () {
+ return $this->name;
+ }
+
+ /**
+ * Sets the storage location image
+ * @param StorageLocationImage $image The storage location image
+ */
+ public function setImage (StorageLocationImage $image) {
+ $this->image = $image;
+ $image->setStorageLocation($this);
+ }
+
+ /**
+ * Returns the storage location image
+ * @return StorageLocationImage The storage location image
+ */
+ public function getImage () {
+ return $this->image;
+ }
+
+ /**
+ * Returns this storage location in serialized form
+ * @return array The serialized storage location
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "name" => $this->getName(),
+ "image_id" => is_object($this->getImage()) ? $this->getImage()->getId() : null);
+ }
+
+ /**
+ * Deserializes the storage location
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "name":
+ $this->setName($value);
+ break;
+ case "image_id":
+ if ($value == "") {
+ echo "/** Breaking because of empty value */";
+ break;
+ }
+
+ try {
+ $image = StorageLocationImage::loadById($value);
+ $this->setImage($image);
+ } catch (\Exception $e) {
+ if ($this->getImage()) {
+ // Image was not found, maybe a temporary image?
+ $this->getImage()->replaceFromTemporaryFile($value);
+ } else {
+ $image = StorageLocationImage::createFromTemporaryFile($value);
+ $this->setImage($image);
+ echo "/**";
+ echo $image->getId();
+ echo "*/";
+ echo "/** FOO */";
+ }
+ }
+
+ break;
+ }
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/StorageLocation/StorageLocationImage.php b/src/backend/PartKeepr/StorageLocation/StorageLocationImage.php
@@ -0,0 +1,50 @@
+<?php
+namespace PartKeepr\StorageLocation;
+
+use PartKeepr\Util\Serializable,
+ PartKeepr\Image\Image;
+
+/**
+ * Holds a storage location image
+ * @Entity
+ **/
+class StorageLocationImage extends Image implements Serializable {
+ /**
+ * The storage location object
+ * @OneToOne(targetEntity="PartKeepr\StorageLocation\StorageLocation",inversedBy="image")
+ * @var StorageLocation
+ */
+ private $storageLocation = null;
+
+ /**
+ * Creates a new storage location image instance
+ */
+ public function __construct () {
+ parent::__construct(Image::IMAGE_STORAGELOCATION);
+ }
+
+ /**
+ * Sets the storage location
+ * @param StorageLocation $storageLocation The storage location to set
+ */
+ public function setStorageLocation (StorageLocation $storageLocation) {
+ $this->storageLocation = $storageLocation;
+ }
+
+ /**
+ * Returns the storage location
+ * @return StorageLocation the storage location
+ */
+ public function getStorageLocation () {
+ return $this->storageLocation;
+ }
+
+ /**
+ *
+ * Serializes this storage location image
+ * @return array The serialized storage location image
+ */
+ public function serialize () {
+ return array("id" => $this->getId(), "storageLocation_id" => $this->getStorageLocation()->getId());
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/StorageLocation/StorageLocationManager.php b/src/backend/PartKeepr/StorageLocation/StorageLocationManager.php
@@ -0,0 +1,94 @@
+<?php
+namespace PartKeepr\StorageLocation;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\StorageLocation\StorageLocation,
+ PartKeepr\PartKeepr,
+ PartKeepr\Category\CategoryManager,
+ PartKeepr\StorageLocation\Exceptions\StorageLocationNotFoundException;
+
+class StorageLocationManager extends Singleton {
+ public function getStorageLocations ($start = 0, $limit = 10, $sort = "footprint", $dir = "asc", $filter = "") {
+
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+ $qb->select("st.id, st.name")->from("PartKeepr\StorageLocation\StorageLocation","st");
+
+ if ($filter != "") {
+ $qb = $qb->where("LOWER(st.name) LIKE :filter");
+ $qb->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ if ($limit > -1) {
+ $qb->setMaxResults($limit);
+ $qb->setFirstResult($start);
+ }
+
+ $qb->orderBy("st.".$sort, $dir);
+
+ $query = $qb->getQuery();
+
+ $result = $query->getResult();
+
+ $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
+ $totalQueryBuilder->select("COUNT(st.id)")->from("PartKeepr\StorageLocation\StorageLocation","st");
+
+
+
+ if ($filter != "") {
+ $totalQueryBuilder = $totalQueryBuilder->where("LOWER(st.name) LIKE :filter");
+ $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ $totalQuery = $totalQueryBuilder->getQuery();
+
+ return array("data" => $result, "start" => $start, "totalCount" => $totalQuery->getSingleScalarResult());
+ }
+
+ public function getStorageLocation ($id) {
+ $storageLocation = PartKeepr::getEM()->find("PartKeepr\StorageLocation\StorageLocation", $id);
+
+ if ($storageLocation) {
+ return $storageLocation;
+ } else {
+ throw new StorageLocationNotFoundException();
+ }
+ }
+
+ public function getStorageLocationByName ($name) {
+ $query = PartKeepr::getEM()->createQuery("SELECT s FROM PartKeepr\StorageLocation\StorageLocation s WHERE s.name = :name");
+ $query->setParameter("name", $name);
+
+ return $query->getSingleResult();
+ }
+
+ public function addStorageLocation ($name) {
+ $storageLocation = new StorageLocation();
+ $storageLocation->setName($name);
+
+ PartKeepr::getEM()->persist($storageLocation);
+ PartKeepr::getEM()->flush();
+
+ return $storageLocation;
+ }
+ public function deleteStorageLocation ($id) {
+ $storageLocation = $this->getStorageLocation($id);
+
+ PartKeepr::getEM()->remove($storageLocation);
+ PartKeepr::getEM()->flush();
+ }
+
+ public function getOrCreateStorageLocation ($storageLocation) {
+ if (is_int($storageLocation)) {
+ try {
+ return $this->getStorageLocation($storageLocation);
+ } catch (StorageLocationNotFoundException $e) {}
+ }
+
+ $sl = new StorageLocation();
+ $sl->setName($storageLocation);
+
+ PartKeepr::getEM()->persist($sl);
+
+ return $sl;
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/StorageLocation/StorageLocationService.php b/src/backend/PartKeepr/StorageLocation/StorageLocationService.php
@@ -0,0 +1,108 @@
+<?php
+namespace PartKeepr\StorageLocation;
+
+use PartKeepr\Service\RestfulService,
+ PartKeepr\Service\Service,
+ PartKeepr\Part\PartManager,
+ PartKeepr\Util\SerializableException,
+ PartKeepr\Stock\StockEntry,
+ PartKeepr\PartKeepr,
+ PartKeepr\Session\SessionManager;
+
+class StorageLocationService extends Service implements RestfulService {
+
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return array("data" => StorageLocationManager::getInstance()->getStorageLocation($this->getParameter("id"))->serialize());
+ } else {
+ if ($this->hasParameter("sort")) {
+ $tmp = json_decode($this->getParameter("sort"), true);
+
+ $aSortParams = $tmp[0];
+ } else {
+ $aSortParams = array(
+ "property" => "name",
+ "direction" => "ASC");
+ }
+ return StorageLocationManager::getInstance()->getStorageLocations(
+ $this->getParameter("start", $this->getParameter("start", 0)),
+ $this->getParameter("limit", $this->getParameter("limit", 25)),
+ $this->getParameter("sortby", $aSortParams["property"]),
+ $this->getParameter("dir", $aSortParams["direction"]),
+ $this->getParameter("query", ""));
+ }
+ }
+
+ public function create () {
+ $this->requireParameter("name");
+
+ $storageLocation = new StorageLocation();
+ $storageLocation->deserialize($this->getParameters());
+
+ PartKeepr::getEM()->persist($storageLocation);
+
+ try {
+ PartKeepr::getEM()->flush();
+ } catch (\PDOException $e) {
+ if ($e->getCode() == "23505") {
+ $exception = new SerializableException(sprintf(PartKeepr::i18n("Storage Location %s already exists!"), $storageLocation->getName()));
+ $exception->setDetail(sprintf(PartKeepr::i18n("You tried to add the storage location %s, but a storage location with the same name already exists."), $storageLocation->getName()));
+
+ throw $exception;
+ } else {
+ throw $e;
+ }
+ }
+
+
+ return array("data" => $storageLocation->serialize());
+ }
+
+ public function update () {
+ $this->requireParameter("id");
+ $this->requireParameter("name");
+ $storageLocation = StorageLocationManager::getInstance()->getStorageLocation($this->getParameter("id"));
+ $storageLocation->deserialize($this->getParameters());
+
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $storageLocation->serialize());
+
+ }
+
+ public function destroy () {
+ $this->requireParameter("id");
+
+ StorageLocationManager::getInstance()->deleteStorageLocation($this->getParameter("id"));
+
+ return array("data" => null);
+ }
+
+ /**
+ * Creates multiple storage locations at once.
+ *
+ * Requires that the parameter "storageLocations" is set to an array with the names of the storage locations.
+ * Returns all error messages as "data" index in the result array.
+ */
+ public function massCreate () {
+ $this->requireParameter("storageLocations");
+
+ $aMessages = array();
+
+ foreach ($this->getParameter("storageLocations") as $storageLocation) {
+ try {
+ $obj = StorageLocationManager::getInstance()->getStorageLocationByName($storageLocation);
+ $aMessages[] = sprintf(PartKeepr::i18n("Storage Location %s already exists"), $storageLocation);
+ } catch (\Exception $e) {
+ $obj = new StorageLocation();
+ $obj->setName($storageLocation);
+ PartKeepr::getEM()->persist($obj);
+ }
+
+ }
+
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $aMessages);
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/System/SystemInformationRecord.php b/src/backend/PartKeepr/System/SystemInformationRecord.php
@@ -0,0 +1,55 @@
+<?php
+namespace PartKeepr\System;
+
+/**
+ * This class represents a system information record.
+ *
+ * This is basically a category, a name and a value. No logic included within
+ * the class.
+ *
+ * For example, records could hold:
+ *
+ * Name Value Category
+ * =====================================================================================
+ * Doctrine ORM 2.1.0 Libraries
+ * Doctrine DBAL 2.1.0 Libraries
+ * Doctrine Migrations git-f87afe9223dbfecaaddb Libraries
+ *
+ * PHP Version 5.3.2 Server Software
+ * Operating System Linux (Funtoo Linux - baselayout 2.1.8) Server Software
+
+ * @author felicitus
+ *
+ */
+class SystemInformationRecord {
+ /**
+ * Holds the category name
+ * @var string
+ */
+ public $category;
+
+ /**
+ * Holds the name
+ * @var string
+ */
+ public $name;
+
+ /**
+ * Holds the value
+ * @var mixed
+ */
+ public $value;
+
+ /**
+ * Creates a new system information record.
+ *
+ * @param string $name
+ * @param mixed $value
+ * @param string $category
+ */
+ public function __construct ($name, $value, $category) {
+ $this->name = $name;
+ $this->value = $value;
+ $this->category = $category;
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/System/SystemService.php b/src/backend/PartKeepr/System/SystemService.php
@@ -0,0 +1,99 @@
+<?php
+namespace PartKeepr\System;
+
+use PartKeepr\Util\Configuration,
+ PartKeepr\Service\Service,
+ PartKeepr\PartKeepr,
+ PartKeepr\CronLogger\CronLoggerManager,
+ PartKeepr\Util\OS\OperatingSystem;
+
+class SystemService extends Service {
+ /**
+ * Returns a list of system information records.
+ *
+ * Please note that it is not defined which information is returned; the result
+ * should be seen as "informational" to the system operator, not for automated purposes.
+ */
+ public function getSystemInformation () {
+ $aData = array();
+
+ $aData[] = new SystemInformationRecord("Doctrine ORM", \Doctrine\ORM\Version::VERSION, "Libraries");
+ $aData[] = new SystemInformationRecord("Doctrine DBAL", \Doctrine\DBAL\Version::VERSION, "Libraries");
+
+ $aData[] = new SystemInformationRecord("PHP Version", phpversion(), "System");
+
+ $os = new OperatingSystem();
+
+ $aData[] = new SystemInformationRecord("Operating System Type", $os->getPlatform(), "System");
+ $aData[] = new SystemInformationRecord("Operating System Release", $os->getRelease(), "System");
+
+ $aData[] = new SystemInformationRecord("memory_limit", ini_get("memory_limit"), "PHP");
+ $aData[] = new SystemInformationRecord("post_max_size", ini_get("post_max_size"), "PHP");
+ $aData[] = new SystemInformationRecord("upload_max_filesize", ini_get("upload_max_filesize"), "PHP");
+ $aData[] = new SystemInformationRecord("post_max_size", ini_get("post_max_size"), "PHP");
+ $aData[] = new SystemInformationRecord("allow_url_fopen", ini_get("allow_url_fopen"), "PHP");
+ $aData[] = new SystemInformationRecord("max_execution_time", ini_get("max_execution_time"), "PHP");
+ $aData[] = new SystemInformationRecord("APC enabled", (extension_loaded("apc") ? PartKeepr::i18n("Yes") : PartKeepr::i18n("No")), "PHP");
+
+ $aData[] = new SystemInformationRecord("PartKeepr Version", PartKeepr::getVersion(), "PartKeepr");
+
+
+ foreach (Configuration::getOptions() as $key => $value) {
+
+ // Hide passwords
+ if ($key == "partkeepr.database.password" || $key == "partkeepr.migration.partdb.password") {
+ $value = "<hidden>";
+ }
+
+ $aData[] = new SystemInformationRecord($key, $value, "PartKeepr Configuration Information");
+ }
+
+ return array("data" => $aData);
+ }
+
+ /**
+ * Returns the database schema status.
+ *
+ * This method is usuall called once the user logs in, and alerts him if the schema is not up-to-date.
+ *
+ * Returns either status incomplete if the schema is not up-to-date, or complete if everything is OK.
+ */
+ public function getSystemStatus () {
+
+ if (Configuration::getOption("partkeepr.cronjobs.disablecheck", false) === true) {
+ // Skip cronjob tests
+ $inactiveCronjobs = array();
+ } else {
+ $inactiveCronjobs = CronLoggerManager::getInstance()->getInactiveCronjobs();
+ }
+
+
+ return array("data" =>
+ array(
+ "inactiveCronjobCount" => count($inactiveCronjobs),
+ "inactiveCronjobs" => $inactiveCronjobs,
+ "schemaStatus" => $this->getSchemaStatus()));
+ }
+
+ /**
+ * Checks if the schema is up-to-date. If yes, it returns "complete", if not, it returns "incomplete".
+ *
+ * @param none
+ * @return string Either "complete" or "incomplete"
+ */
+ protected function getSchemaStatus () {
+ $metadatas = PartKeepr::getEM()->getMetadataFactory()->getAllMetadata();
+
+ $schemaTool = new \Doctrine\ORM\Tools\SchemaTool(PartKeepr::getEM());
+
+ $queries = $schemaTool->getUpdateSchemaSql($metadatas, true);
+
+ if (count($queries) > 0) {
+ return "incomplete";
+ } else {
+ return "complete";
+ }
+ }
+
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/SystemNotice/SystemNotice.php b/src/backend/PartKeepr/SystemNotice/SystemNotice.php
@@ -0,0 +1,141 @@
+<?php
+namespace PartKeepr\SystemNotice;
+
+use PartKeepr\UploadedFile\UploadedFile,
+ PartKeepr\Util\BaseEntity,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Util\Deserializable;
+
+/**
+ * Holds a system notice
+ * @Entity
+ **/
+class SystemNotice extends BaseEntity implements Serializable {
+ /**
+ * @Column(type="datetime")
+ * @var \DateTime
+ */
+ private $date;
+
+ /**
+ * @Column(type="string")
+ * @var string
+ */
+ private $title;
+
+ /**
+ * The description of this attachment
+ * @Column(type="text")
+ * @var string
+ */
+ private $description;
+
+ /**
+ * Defines if the system notice has been acknowledged
+ * @Column(type="boolean")
+ * @var boolean
+ */
+ private $acknowledged = false;
+
+ /**
+ * Specifies the type. This is required for unique notices which shouldn't pop up every time we create them.
+ * @Column(type="string")
+ * @var string
+ */
+ private $type;
+
+ /**
+ * Sets the date and time for this entry
+ * @param \DateTime $date The date and time
+ */
+ public function setDate (\DateTime $date) {
+ $this->date = $date;
+ }
+
+ /**
+ * Returns the date and time for this entry
+ *
+ * @return \DateTime the date and time for this entry
+ */
+ public function getDate () {
+ return $this->date;
+ }
+
+ /**
+ * Sets the title for this entry
+ * @param string $title the title for this entry
+ */
+ public function setTitle ($title) {
+ $this->title = $title;
+ }
+
+ /**
+ * Returns the title for this entry
+ * @return string the title
+ */
+ public function getTitle () {
+ return $this->title;
+ }
+
+ /**
+ * Sets the description
+ * @param string $description
+ */
+ public function setDescription ($description) {
+ $this->description = $description;
+ }
+
+ /**
+ * Returns the description
+ * @return string The description
+ */
+ public function getDescription () {
+ return $this->description;
+ }
+
+ /**
+ * Sets the value of the acknowledged flag
+ * @param boolean $bAck True if the notice should be acknowledged (default), false otherwise
+ */
+ public function setAcknowledgedFlag ($bAck = true) {
+ $this->acknowledged = $bAck;
+ }
+
+ /**
+ * Returns the value of the acknowledged flag
+ *
+ * @return boolean true if this notice has been acknowledged, false otherwise
+ */
+ public function getAcknowledgedFlag () {
+ return $this->acknowledged;
+ }
+
+ /**
+ * Sets the type of this entry
+ * @param string $type
+ */
+ public function setType ($type) {
+ $this->type = $type;
+ }
+
+ /**
+ * Returns the type of this entry
+ * @return string The type
+ */
+ public function getType () {
+ return $this->type;
+ }
+
+ /**
+ * Serializes this system notice attachment
+ * @return array The serialized system notice
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "date" => $this->getDate()->format("Y-m-d H:i:s"),
+ "title" => $this->getTitle(),
+ "description" => $this->getDescription(),
+ "acknowledged" => $this->getAcknowledgedFlag());
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/SystemNotice/SystemNoticeManager.php b/src/backend/PartKeepr/SystemNotice/SystemNoticeManager.php
@@ -0,0 +1,55 @@
+<?php
+namespace PartKeepr\SystemNotice;
+
+use PartKeepr\Manager\AbstractManager,
+ PartKeepr\Project\Project,
+ PartKeepr\PartKeepr;
+
+class SystemNoticeManager extends AbstractManager {
+ /**
+ * Returns the FQCN for the target entity to operate on.
+ * @return string The FQCN, e.g. PartKeepr\Part
+ */
+ public function getEntityName () {
+ return 'PartKeepr\SystemNotice\SystemNotice';
+ }
+
+ /**
+ * Returns all fields which need to appear in the getList ResultSet.
+ * @return array An array of all fields which should be returned
+ */
+ public function getQueryFields () {
+ return array("id", "title", "date");
+ }
+
+ /**
+ * Returns the default sort field
+ *
+ * @return string The default sort field
+ */
+ public function getDefaultSortField () {
+ return "date";
+ }
+
+ public function createUniqueSystemNotice ($type, $title, $description) {
+ $dql = "SELECT sn FROM PartKeepr\SystemNotice\SystemNotice sn WHERE sn.type = :type";
+ $query = PartKeepr::getEM()->createQuery($dql);
+
+ $query->setParameter("type", $type, \PDO::PARAM_BOOL);
+
+ try {
+ $notice = $query->getSingleResult();
+ } catch (\Exception $e) {
+ $notice = new SystemNotice();
+ PartKeepr::getEM()->persist($notice);
+ }
+
+ $notice->setDate(new \DateTime());
+ $notice->setTitle($title);
+ $notice->setDescription($description);
+ $notice->setType($type);
+
+ PartKeepr::getEM()->flush();
+
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/SystemNotice/SystemNoticeService.php b/src/backend/PartKeepr/SystemNotice/SystemNoticeService.php
@@ -0,0 +1,83 @@
+<?php
+namespace PartKeepr\SystemNotice;
+
+use PartKeepr\Service\RestfulService,
+ PartKeepr\Service\Service,
+ PartKeepr\PartKeepr,
+ PartKeepr\Manager\ManagerFilter;
+
+class SystemNoticeService extends Service implements RestfulService {
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return array("data" => SystemNoticeManager::getInstance()->getEntity($this->getParameter("id"))->serialize());
+ } else {
+ $parameters = new ManagerFilter($this);
+ $parameters->setFilterCallback(array($this, "filterCallback"));
+
+ return SystemNoticeManager::getInstance()->getList($parameters);
+ }
+ }
+
+ public function filterCallback ($queryBuilder) {
+ $queryBuilder->andWhere("q.acknowledged = :acknowledged");
+ $queryBuilder->setParameter("acknowledged", false, \PDO::PARAM_BOOL);
+ }
+ /**
+ * Stub method to fulfill the RestfulService. We don't want to have SystemNotices created by the user, so
+ * we bail out with an exception.
+ *
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::create()
+ */
+ public function create () {
+ throw new \Exception("Not implemented");
+ }
+
+ /**
+ * Stub method to fulfill the RestfulService. We don't want to have SystemNotices updated by the user, so
+ * we bail out with an exception.
+ *
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::update()
+ */
+ public function update () {
+ throw new \Exception("Not implemented");
+
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::destroy()
+ */
+ public function destroy () {
+ $this->requireParameter("id");
+
+ SystemNoticeManager::getInstance()->deleteEntity($this->getParameter("id"));
+
+ return array("data" => null);
+ }
+
+ public function acknowledge () {
+ $this->requireParameter("id");
+
+ $entity = SystemNoticeManager::getInstance()->getEntity($this->getParameter("id"));
+ $entity->setAcknowledgedFlag();
+ }
+
+ public function hasUnacknowledgedNotices () {
+ $dql = "SELECT COUNT(c) FROM PartKeepr\SystemNotice\SystemNotice c WHERE c.acknowledged = :a";
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("a", false, \PDO::PARAM_BOOL);
+
+ $bRetval = false;
+
+ if ($query->getSingleScalarResult() > 0) {
+ $bRetval = true;
+ }
+ return array("data" => array("unacknowledgedNotices" => $bRetval));
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/TempFile/TempFileService.php b/src/backend/PartKeepr/TempFile/TempFileService.php
@@ -0,0 +1,72 @@
+<?php
+namespace PartKeepr\TempFile;
+
+use PartKeepr\Service\Service;
+use PartKeepr\UploadedFile\TempUploadedFile;
+use PartKeepr\PartKeepr;
+
+class TempFileService extends Service {
+
+ public function upload () {
+ $tmpFile = new TempUploadedFile();
+
+ if (array_key_exists("userfile", $_FILES) && file_exists($_FILES["userfile"]["tmp_name"])) {
+ $file = $_FILES['userfile']['tmp_name'];
+ $filename = $_FILES['userfile']['name'];
+
+ $tmpFile->replace($file);
+ $tmpFile->setOriginalFilename(basename($filename));
+ } elseif (array_key_exists("url", $_REQUEST)) {
+ $tmpFile->replaceFromURL($_REQUEST["url"]);
+ } else {
+ throw new \Exception("Error: No valid file given");
+ }
+
+ PartKeepr::getEM()->persist($tmpFile);
+ PartKeepr::getEM()->flush();
+
+ return array("id" => $tmpFile->getId(), "extension" => $tmpFile->getExtension(), "size" => $tmpFile->getSize(), "originalFilename" => $tmpFile->getOriginalFilename());
+ }
+
+ /**
+ * Receives a file via the service call.
+ *
+ * Parameters:
+ * - filedata: needs to be base64-encoded.
+ * - filename: The filename
+ */
+ public function jsonUpload () {
+ $data = base64_decode($this->getParameter("filedata"));
+ $filename = $this->getParameter("filename");
+
+ $tempFile = tempnam("/tmp", "PWC");
+ file_put_contents($tempFile, $data);
+
+ $tmpFile = new TempUploadedFile();
+ $tmpFile->replace($tempFile);
+ $tmpFile->setOriginalFilename($filename);
+
+ PartKeepr::getEM()->persist($tmpFile);
+ PartKeepr::getEM()->flush();
+
+ return $tmpFile->serialize();
+ }
+
+ /**
+ * Processes data via HTTP POST. Reads php://input and creates a temporary image out of it.
+ */
+ public function uploadCam () {
+ $tempFile = tempnam("/tmp", "PWC") . ".jpg";
+ $result = file_put_contents( $tempFile, file_get_contents('php://input') );
+
+ $image = new TempUploadedFile();
+ $image->replace($tempFile);
+ $image->setOriginalFilename(sprintf(PartKeepr::i18n("Cam photo of %s"), date("Y-m-d H:i:s")).".jpg");
+
+ PartKeepr::getEM()->persist($image);
+ PartKeepr::getEM()->flush();
+
+ return array("id" => $image->getId(), "extension" => $image->getExtension(), "size" => $image->getSize(), "originalFilename" => $image->getOriginalFilename());
+ }
+}
+ +
\ No newline at end of file
diff --git a/src/backend/PartKeepr/TempImage/TempImage.php b/src/backend/PartKeepr/TempImage/TempImage.php
@@ -0,0 +1,19 @@
+<?php
+namespace PartKeepr\TempImage;
+
+use PartKeepr\Image\Exceptions\InvalidImageTypeException,
+ PartKeepr\Util\Configuration,
+ PartKeepr\Image\Image,
+ PartKeepr\PartKeepr;
+
+/**
+ * Represents a temporary image. Temporary images are used when
+ * a user uploaded an image, but not attached it to an entity.
+ *
+ * @Entity
+ */
+class TempImage extends Image {
+ public function __construct () {
+ parent::__construct(Image::IMAGE_TEMP);
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/TempImage/TempImageService.php b/src/backend/PartKeepr/TempImage/TempImageService.php
@@ -0,0 +1,30 @@
+<?php
+namespace PartKeepr\TempImage;
+
+use PartKeepr\Service\Service;
+use PartKeepr\TempImage\TempImage;
+use PartKeepr\PartKeepr;
+
+class TempImageService extends Service {
+ public function upload () {
+ $image = new TempImage();
+
+ if (array_key_exists("userfile", $_FILES) && file_exists($_FILES["userfile"]["tmp_name"])) {
+ $file = $_FILES['userfile']['tmp_name'];
+ $filename = $_FILES['userfile']['name'];
+
+ $image->replace($file);
+ $image->setOriginalFilename(basename($filename));
+ } elseif (array_key_exists("url", $_REQUEST)) {
+ $image->replaceFromURL($_REQUEST["url"]);
+ } else {
+ throw new \Exception("Error: No valid file given");
+ }
+
+ PartKeepr::getEM()->persist($image);
+ PartKeepr::getEM()->flush();
+
+ return array("id" => $image->getId(), "extension" => $image->getExtension(), "size" => $image->getSize(), "originalFilename" => $image->getOriginalFilename());
+ }
+}
+ +
\ No newline at end of file
diff --git a/src/backend/PartKeepr/TipOfTheDay/TipOfTheDay.php b/src/backend/PartKeepr/TipOfTheDay/TipOfTheDay.php
@@ -0,0 +1,114 @@
+<?php
+namespace PartKeepr\TipOfTheDay;
+
+use PartKeepr\Util\Serializable;
+
+use PartKeepr\PartKeepr;
+
+use PartKeepr\Util\Configuration;
+
+use PartKeepr\Util\BaseEntity;
+
+/**
+ * Represents a tip of the day.
+ *
+ * Tips are stored on the central PartKeepr server in a wiki. However, we need to know a list of all tip pages
+ * because the API has a limit per day. So basically, we sync the tip names from the wiki to the local system several
+ * times a day and not each time an user logs in.
+ *
+ * Note: If you wish to link against a tip of the day, do it by name and not by id!
+ *
+ * @Entity
+ **/
+class TipOfTheDay extends BaseEntity implements Serializable {
+ /**
+ * @Column(type="string")
+ * @var string
+ */
+ private $name;
+
+ /**
+ * Sets the name for this tip
+ * @param string $name The name
+ */
+ public function setName ($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the name for this tip
+ * @return string The name
+ */
+ public function getName () {
+ return $this->name;
+ }
+
+ /**
+ * Syncronizes the tip database against the master wiki.
+ * @throws \Exception
+ */
+ public static function syncTips () {
+ if (ini_get("allow_url_fopen") == 0) {
+ throw new \Exception("allow_url_fopen is disabled, but required to query the TipOfTheDay database.");
+ }
+
+ $url = Configuration::getOption("partkeepr.tipoftheday.api", "http://partkeepr.org/wiki/api.php?action=query&list=categorymembers&cmtitle=Category:TipOfTheDay&format=json");
+
+ $tipsString = file_get_contents($url);
+
+
+ $aPageNames = self::extractPageNames($tipsString);
+
+ self::updateTipDatabase($aPageNames);
+ }
+
+ /**
+ * Updates the tip database. Expects an array of page names.
+ *
+ * This method clears all page names and re-creates them. This saves
+ * alot of engineering, because we don't need to match contents
+ * within the database against contents in an array.
+ *
+ * @param array $aPageNames The page names as array. Page names are stored as string.
+ */
+ private static function updateTipDatabase (array $aPageNames) {
+ $dql = "DELETE FROM PartKeepr\TipOfTheDay\TipOfTheDay";
+ $query = PartKeepr::getEM()->createQuery($dql);
+
+ $query->execute();
+
+ foreach ($aPageNames as $pageName) {
+ $tip = new TipOfTheDay();
+ $tip->setName($pageName);
+ PartKeepr::getEM()->persist($tip);
+ }
+
+ PartKeepr::getEM()->flush();
+ }
+
+ /**
+ * Extracts the page names from the mediawiki JSON returned.
+ * @param string $response The encoded json string
+ * @return array An array with the titles of each page
+ */
+ private static function extractPageNames ($response) {
+ $aTipsStructure = json_decode($response, true);
+ $aTips = $aTipsStructure["query"]["categorymembers"];
+
+ $aPageNames = array();
+
+ foreach ($aTips as $tip) {
+ $aPageNames[] = $tip["title"];
+ }
+
+ return $aPageNames;
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Util.Serializable::serialize()
+ */
+ public function serialize () {
+ return array( "name" => $this->getName() );
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/TipOfTheDay/TipOfTheDayHistory.php b/src/backend/PartKeepr/TipOfTheDay/TipOfTheDayHistory.php
@@ -0,0 +1,51 @@
+<?php
+namespace PartKeepr\TipOfTheDay;
+
+use PartKeepr\User\User;
+
+use PartKeepr\Util\Serializable;
+
+use PartKeepr\PartKeepr;
+
+use PartKeepr\Util\Configuration;
+
+use PartKeepr\Util\BaseEntity;
+
+/**
+ * Represents a tip of the day history entry.
+ *
+ * This entity stores each tip of the day the user has already seen.
+ *
+ * @Entity
+ **/
+class TipOfTheDayHistory extends BaseEntity {
+ /**
+ * @Column(type="string")
+ * @var string
+ */
+ private $name;
+
+ /**
+ * Defines the user
+ * @ManyToOne(targetEntity="PartKeepr\User\User")
+ * @var StorageLocation
+ */
+ private $user;
+
+ /**
+ * Sets the user for this entry
+ * @param User $user
+ */
+ public function setUser (User $user) {
+ $this->user = $user;
+ }
+
+ /**
+ * Sets the tip of the day name the user already has seen
+ * @param string $name The tip name
+ */
+ public function setName ($name) {
+ $this->name = $name;
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/TipOfTheDay/TipOfTheDayService.php b/src/backend/PartKeepr/TipOfTheDay/TipOfTheDayService.php
@@ -0,0 +1,86 @@
+<?php
+namespace PartKeepr\TipOfTheDay;
+
+use PartKeepr\Util\Configuration,
+ PartKeepr\User\User,
+ PartKeepr\Service\RestfulService,
+ PartKeepr\Session\SessionManager,
+ PartKeepr\Service\Service,
+ PartKeepr\PartKeepr;
+
+class TipOfTheDayService extends Service implements RestfulService {
+ /**
+ * Returns all tips along with the information wether they are read or not.
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ $aTips = array();
+ $url = Configuration::getOption("partkeepr.tipoftheday.wiki", "http://partkeepr.org/wiki/index.php/");
+
+ /* Extract all tips which aren't read */
+ $dql = "SELECT d FROM PartKeepr\TipOfTheDay\TipOfTheDay d WHERE d.name NOT IN ";
+ $dql .= "(SELECT dh.name FROM PartKeepr\TipOfTheDay\TipOfTheDayHistory dh WHERE dh.user = :user)";
+
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("user", SessionManager::getCurrentSession()->getUser());
+
+ foreach ($query->getResult() as $result) {
+ $aTips[] = array (
+ "name" => $result->getName(),
+ "read" => false,
+ "url" => $url.$result->getName() . "?useskin=monobookplain");
+ }
+
+ /* Extract all tips which are read */
+ $dql = "SELECT d FROM PartKeepr\TipOfTheDay\TipOfTheDay d WHERE d.name IN ";
+ $dql .= "(SELECT dh.name FROM PartKeepr\TipOfTheDay\TipOfTheDayHistory dh WHERE dh.user = :user)";
+
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("user", SessionManager::getCurrentSession()->getUser());
+
+ foreach ($query->getResult() as $result) {
+ $aTips[] = array (
+ "name" => $result->getName(),
+ "read" => true,
+ "url" => $url.$result->getName() . "?useskin=monobookplain");
+ }
+
+ return array("data" => $aTips);
+ }
+
+ public function create() {}
+ public function update () {}
+ public function destroy () {}
+
+ /**
+ * Marks a specific tip as read.
+ *
+ * Uses the parameter "name" to identify the tip.
+ */
+ public function markTipAsRead () {
+ $this->requireParameter("name");
+
+ try {
+ $th = new TipOfTheDayHistory;
+ $th->setUser($this->getUser());
+ $th->setName($this->getParameter("name"));
+
+ PartKeepr::getEM()->persist($th);
+ PartKeepr::getEM()->flush();
+ } catch (\Exception $e) {
+ /* Do nothing */
+ }
+
+ }
+
+ /**
+ * Marks all tips as unread for the current user
+ */
+ public function markAllTipsAsUnread () {
+ $dql = "DELETE FROM PartKeepr\TipOfTheDay\TipOfTheDayHistory th WHERE th.user = :user";
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("user", $this->getUser());
+ $query->execute();
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Unit/Unit.php b/src/backend/PartKeepr/Unit/Unit.php
@@ -0,0 +1,130 @@
+<?php
+namespace PartKeepr\Unit;
+
+use PartKeepr\Util\Deserializable,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Util\BaseEntity,
+ PartKeepr\PartKeepr,
+ PartKeepr\Util\Exceptions\OutOfRangeException,
+ PartKeepr\SiPrefix\SiPrefix;
+
+
+/**
+ * This object represents an unit. Units can be: Volt, Hertz etc.
+ *
+ * @Entity
+ **/
+class Unit extends BaseEntity implements Serializable, Deserializable {
+ /**
+ * The name of the unit (e.g. Volts, Ampere, Farad, Metres)
+ * @Column(type="string")
+ * @var string
+ */
+ private $name;
+
+ /**
+ * The symbol of the unit (e.g. V, A, F, m)
+ * @Column(type="string")
+ * @var string
+ */
+ private $symbol;
+
+ /**
+ * Defines the allowed SiPrefixes for this parameter unit
+ * @ManyToMany(targetEntity="PartKeepr\SiPrefix\SiPrefix")
+ * @JoinTable(name="UnitSiPrefixes",
+ * joinColumns={@JoinColumn(name="unit_id", referencedColumnName="id")},
+ * inverseJoinColumns={@JoinColumn(name="siprefix_id", referencedColumnName="id")}
+ * )
+ * @var ArrayCollection
+ */
+ private $prefixes;
+
+ /**
+ * Creates a new Unit.
+ */
+ public function __construct () {
+ $this->prefixes = new \Doctrine\Common\Collections\ArrayCollection();
+ }
+
+ /**
+ * Sets the name for this unit
+ * @param string $name the name for this unit
+ */
+ public function setName ($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the name for this unit
+ * @return string The unit name
+ */
+ public function getName () {
+ return $this->name;
+ }
+
+ /**
+ * Sets the symbol for this unit
+ * @param string $symbol The symbol
+ */
+ public function setSymbol ($symbol) {
+ $this->symbol = $symbol;
+ }
+
+ /**
+ * Returns the symbol for this unit
+ * @return string The symbol
+ */
+ public function getSymbol () {
+ return $this->symbol;
+ }
+
+ /**
+ * Returns the si-prefix list for this unit
+ * @return array An array of SiPrefix objects
+ */
+ public function getPrefixes () {
+ return $this->prefixes;
+ }
+
+ /**
+ * Serializes the user object and returns it as array, suitable
+ * to process via json_encode.
+ * @param none
+ * @return array An array containing the object information
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "name" => $this->getName(),
+ "symbol" => $this->getSymbol(),
+ "prefixes" => $this->serializeChildren($this->getPrefixes())
+ );
+ }
+
+ /**
+ * Deserializes the unit
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "name":
+ $this->setName($value);
+ break;
+ case "symbol":
+ $this->setSymbol($value);
+ break;
+ case "prefixes":
+ $prefixes = $this->getPrefixes();
+ $prefixes->clear();
+
+ foreach ($value as $prefix) {
+ $prefix = SiPrefix::loadById($prefix["id"]);
+ $prefixes->add($prefix);
+ }
+ break;
+ }
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Unit/UnitManager.php b/src/backend/PartKeepr/Unit/UnitManager.php
@@ -0,0 +1,99 @@
+<?php
+namespace PartKeepr\Unit;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\PartKeepr,
+ PartKeepr\Unit\Exceptions\UnitNotFoundException;
+
+class UnitManager extends Singleton {
+ public function getUnits ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
+
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+ $qb->select("u.id, u.name, u.symbol")->from("PartKeepr\Unit\Unit","u");
+
+ if ($filter != "") {
+ $qb = $qb->where("LOWER(u.name) LIKE :filter");
+ $qb->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ if ($limit > -1) {
+ $qb->setMaxResults($limit);
+ $qb->setFirstResult($start);
+ }
+
+ $qb->orderBy("u.".$sort, $dir);
+
+ $query = $qb->getQuery();
+
+ $result = $query->getResult();
+
+ $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
+ $totalQueryBuilder->select("COUNT(u.id)")->from("PartKeepr\Unit\Unit","u");
+
+
+
+ if ($filter != "") {
+ $totalQueryBuilder = $totalQueryBuilder->where("LOWER(u.name) LIKE :filter");
+ $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ $totalQuery = $totalQueryBuilder->getQuery();
+
+ foreach ($result as $key => $value) {
+ $result[$key]["prefixes"] = $this->getSiPrefixes($value["id"]);
+ }
+
+ return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
+ }
+
+ public function getSiPrefixes ($id) {
+ $unit = UnitManager::getInstance()->getUnit($id);
+
+ $aData = array();
+
+ foreach ($unit->getPrefixes() as $prefix) {
+ $aData[] = $prefix->serialize();
+ }
+
+ return array("response" => array("totalCount" => count($aData), "data" => $aData));
+ }
+
+ public function getUnitByName ($name) {
+ $dql = "SELECT u FROM 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 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("PartKeepr\Unit\Unit", $id);
+
+ if ($unit) {
+ return $unit;
+ } else {
+ throw new UnitNotFoundException();
+ }
+ }
+
+ public function deleteUnit ($id) {
+ $unit = $this->getUnit($id);
+
+ PartKeepr::getEM()->remove($unit);
+ PartKeepr::getEM()->flush();
+ }
+
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Unit/UnitService.php b/src/backend/PartKeepr/Unit/UnitService.php
@@ -0,0 +1,67 @@
+<?php
+namespace PartKeepr\Unit;
+
+use PartKeepr\Service\RestfulService,
+ PartKeepr\Service\Service,
+ PartKeepr\PartKeepr,
+ PartKeepr\Part\PartUnit,
+ PartKeepr\SiPrefix\SiPrefix,
+ PartKeepr\Session\SessionManager;
+
+class UnitService extends Service implements RestfulService {
+ public function get () {
+ if ($this->hasParameter("id")) {
+ return array("data" => UnitManager::getInstance()->getUnit($this->getParameter("id"))->serialize());
+ } else {
+ if ($this->hasParameter("sort")) {
+ $tmp = json_decode($this->getParameter("sort"), true);
+
+ $aSortParams = $tmp[0];
+ } else {
+ $aSortParams = array(
+ "property" => "name",
+ "direction" => "ASC");
+ }
+ return UnitManager::getInstance()->getUnits(
+ $this->getParameter("start", $this->getParameter("start", 0)),
+ $this->getParameter("limit", $this->getParameter("limit", 25)),
+ $this->getParameter("sortby", $aSortParams["property"]),
+ $this->getParameter("dir", $aSortParams["direction"]),
+ $this->getParameter("query", ""));
+ }
+ }
+
+ public function create () {
+ $this->requireParameter("name");
+
+ $unit = new Unit;
+ $unit->deserialize($this->getParameters());
+
+ PartKeepr::getEM()->persist($unit);
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $unit->serialize());
+ }
+
+ public function update () {
+ $this->requireParameter("id");
+ $this->requireParameter("name");
+
+ $unit = UnitManager::getInstance()->getUnit($this->getParameter("id"));
+ $unit->deserialize($this->getParameters());
+
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $unit->serialize());
+
+ }
+
+ public function destroy () {
+ $this->requireParameter("id");
+
+ UnitManager::getInstance()->deleteUnit($this->getParameter("id"));
+
+ return array("data" => null);
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/UploadedFile/TempUploadedFile.php b/src/backend/PartKeepr/UploadedFile/TempUploadedFile.php
@@ -0,0 +1,15 @@
+<?php
+namespace PartKeepr\UploadedFile;
+
+/**
+ * Represents a temporary file. Temporary files are used when
+ * a user uploaded a file, but not attached it to an entity.
+ *
+ * @Entity
+ */
+class TempUploadedFile extends UploadedFile {
+ public function __construct () {
+ parent::__construct();
+ $this->setType("Temporary");
+ }
+}
diff --git a/src/backend/PartKeepr/UploadedFile/UploadedFile.php b/src/backend/PartKeepr/UploadedFile/UploadedFile.php
@@ -0,0 +1,301 @@
+<?php
+namespace PartKeepr\UploadedFile;
+
+use PartKeepr\Util\SerializableException,
+ PartKeepr\Util\BaseEntity,
+ PartKeepr\Util\Serializable,
+ PartKeepr\PartKeepr,
+ PartKeepr\UploadedFile\TempUploadedFile,
+ PartKeepr\Util\Configuration;
+
+/**
+ * @MappedSuperclass
+ */
+abstract class UploadedFile extends BaseEntity implements Serializable {
+ /**
+ * Specifies the type of the file.
+ *
+ * @var string
+ * @Column(type="string")
+ **/
+ private $type;
+
+ /**
+ * The unique filename of the file
+ *
+ * @var string
+ * @Column(type="string")
+ */
+ private $filename;
+
+ /**
+ * The original name of the file
+ * @Column(type="string",nullable=true)
+ * @var string
+ */
+ private $originalname;
+
+ /**
+ * The mimetype for the file
+ * @var string
+ * @Column(type="string")
+ */
+ private $mimetype;
+
+ /**
+ * The size of the uploaded file
+ * @Column(type="integer")
+ * @var integer
+ */
+ private $size;
+
+ /**
+ * Constructs a new file object.
+ *
+ */
+ public function __construct () {
+ $this->filename = PartKeepr::createGUIDv4();
+ }
+
+ /**
+ * Sets the type of the file. Once the type is set,
+ * it may not be changed later.
+ */
+ protected function setType ($type) {
+ $this->type = $type;
+ }
+
+ /**
+ * Returns the original filename
+ * @return string The original filename
+ */
+ public function getOriginalFilename () {
+ return $this->originalname;
+ }
+
+ /**
+ * Sets the original filename
+ * @param string $filename The original filename
+ */
+ public function setOriginalFilename ($filename) {
+ $this->originalname = $filename;
+ }
+
+ /**
+ * Replaces the current file with a new file.
+ *
+ * @param string $path The path to the original file
+ */
+ public function replace ($path) {
+ // Parse the file's mimetype
+ $finfo = new \finfo(FILEINFO_MIME);
+ $this->mimetype = $finfo->file($path, FILEINFO_MIME_TYPE);
+
+ // Get the file size
+ $this->size = filesize($path);
+
+ $this->ensureFilePathExists();
+ $this->checkPermissions();
+
+ copy($path, $this->getFilename());
+
+ $this->setOriginalFilename(basename($path));
+ }
+
+ /**
+ * Replaces the file from an URL. Does some tricks to avoid 403 forbidden on some sites.
+ * @param string $url
+ */
+ public function replaceFromURL ($url) {
+
+ /* Some sites don't like automated requests. But the internet is meant to be open for anybody,
+ * even for scripts. So we are evil and fake the headers.
+ *
+ * Credit goes to Ryan Rampersad from whom I copied most code.
+ * http://blog.ryanrampersad.com/2008/11/07/get-remote-html-with-curl-and-php/
+ */
+ $curl = curl_init();
+
+ $header[0] = "Accept: text/xml,application/xml,application/xhtml+xml,";
+ $header[0] .= "text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
+ $header[] = "Cache-Control: max-age=0";
+ $header[] = "Connection: keep-alive";
+ $header[] = "Keep-Alive: 300";
+ $header[] = "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7";
+ $header[] = "Accept-Language: en-us,en;q=0.5";
+ $header[] = "Pragma: ";
+
+ $browser = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092510 Ubuntu/8.04 (hardy) Firefox/3.0.3";
+
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_USERAGENT, $browser);
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
+ curl_setopt($curl, CURLOPT_AUTOREFERER, true);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_TIMEOUT, 30);
+ curl_setopt($curl, CURLOPT_MAXREDIRS, 7);
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
+
+ $data = curl_exec($curl);
+
+ if ($data === false) {
+ throw new \Exception("replaceFromURL error: ".curl_error($curl));
+ }
+
+ curl_close($curl);
+
+ $tempName = tempnam("/tmp", "PARTKEEPR");
+
+ file_put_contents($tempName, $data);
+
+ $this->replace($tempName);
+
+ $this->setOriginalFilename(basename($url));
+ }
+
+ /**
+ * Returns the size of this file
+ * @return integer The size in bytes
+ */
+ public function getSize () {
+ return $this->size;
+ }
+
+ /**
+ * Returns the type of the file
+ * @param none
+ * @return string The type of the file
+ */
+ public function getType () {
+ return $this->type;
+ }
+
+ /**
+ * Returns the full filename including path and suffix.
+ * @return string The full filename
+ */
+ public function getFilename () {
+ return $this->getFilePath().$this->filename.".".$this->getExtension();
+ }
+
+ /**
+ * Returns the plain filename without path and suffix.
+ * @return string the plain filename
+ */
+ public function getPlainFilename () {
+ return $this->filename;
+ }
+
+ /**
+ * Returns the mime type for this file
+ * @return string The mimetype for this file, e.g. text/plain
+ */
+ public function getMimeType () {
+ return $this->mimetype;
+ }
+
+ /**
+ * Returns the extension for the given mime type.
+ *
+ * This function simply extracts that information from the mime type;
+ * special cases are not handled. e.g. if you have image/foobar, it would
+ * return "foobar" as extension.
+ *
+ * @return string The extension
+ */
+ public function getExtension () {
+ list($category, $type) = explode("/", $this->getMimeType());
+ return $type;
+ }
+
+ /**
+ * Returns the path to the file. May be overridden by
+ * subclasses.
+ *
+ * @param none
+ * @return string The path to the file
+ */
+ public function getFilePath () {
+ return Configuration::getOption(
+ "partkeepr.files.path",
+ PartKeepr::getRootDirectory() . "/data/") . $this->getType() . "/";
+ }
+
+ /**
+ * Ensures that the file path exists. This function
+ * is called every time a file is processed.
+ * It is maybe a bit overhead, but saves headaches later when
+ * introducing new types.
+ *
+ * @param none
+ * @return nothing
+ */
+ public function ensureFilePathExists () {
+ if (!is_dir($this->getFilePath())) {
+ try {
+ mkdir($this->getFilePath(), 0777, true);
+ } catch (\Exception $e) {
+ throw new \Exception("Unable to create directory ".$this->getFilePath());
+ }
+ }
+ }
+
+ /**
+ * Creates a new entity from the given temporary id.
+ *
+ * @param string $id The temporary id (prefixed with TMP:)
+ * @return object a new instance of the file.
+ * @throws \Exception If the ID does not begin with TMP:
+ */
+ public static function createFromTemporaryFile ($id) {
+ if (substr($id, 0, 4) === "TMP:") {
+ // It's a temporary file
+ $className = get_called_class();
+
+ $file = new $className();
+ $file->replaceFromTemporaryFile($id);
+ return $file;
+ } else {
+ throw new \Exception("Given id $id is not a temporary file");
+ }
+ }
+
+ /**
+ * Replaces the file with a given temporary file.
+ * @param string $id The temporary id (prefixed with TMP:)
+ */
+ public function replaceFromTemporaryFile ($id) {
+ if (substr($id, 0, 4) === "TMP:") {
+ $tmpFileId = str_replace("TMP:", "", $id);
+ $tmpFile = TempUploadedFile::loadById($tmpFileId);
+
+ $this->replace($tmpFile->getFilename());
+ $this->setOriginalFilename($tmpFile->getOriginalFilename());
+ }
+ }
+
+ /**
+ * Checks if the path where the file should be stored has sufficient permissions to do so.
+ *
+ * @throws SerializableException
+ */
+ public function checkPermissions () {
+ if (!is_writable($this->getFilePath())) {
+ throw new SerializableException(
+ sprintf(PartKeepr::i18n("Unable to write to directory %s"), $this->getFilePath()));
+ }
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Util.Serializable::serialize()
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "extension" => $this->getExtension(),
+ "size" => $this->getSize(),
+ "originalFilename" => $this->getOriginalFilename()
+ );
+ }
+}
diff --git a/src/backend/PartKeepr/User/Exceptions/InvalidLoginDataException.php b/src/backend/PartKeepr/User/Exceptions/InvalidLoginDataException.php
@@ -0,0 +1,14 @@
+<?php
+namespace PartKeepr\User\Exceptions;
+
+use PartKeepr\Util\SerializableException,
+ PartKeepr\PartKeepr;
+
+/**
+ * Is thrown when the user has given wrong credentials.
+ */
+class InvalidLoginDataException extends SerializableException {
+ public function __construct () {
+ parent::__construct(PartKeepr::i18n("Username or Password wrong."));
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/User/Exceptions/UserAlreadyExistsException.php b/src/backend/PartKeepr/User/Exceptions/UserAlreadyExistsException.php
@@ -0,0 +1,19 @@
+<?php
+namespace PartKeepr\User\Exceptions;
+
+use PartKeepr\Util\SerializableException,
+ PartKeepr\PartKeepr;
+
+/**
+* Is thrown when the user already exists. This usually happens
+* if someone tries to create a user with the same name of an existing
+* user.
+*/
+class UserAlreadyExistsException extends SerializableException {
+ public function __construct ($username) {
+ parent::__construct(
+ sprintf(
+ PartKeepr::i18n("User %s already exists."),
+ $username));
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/User/Exceptions/UserDoesNotExistException.php b/src/backend/PartKeepr/User/Exceptions/UserDoesNotExistException.php
@@ -0,0 +1,17 @@
+<?php
+namespace PartKeepr\User\Exceptions;
+
+use PartKeepr\Util\SerializableException,
+ PartKeepr\PartKeepr;
+
+/**
+* Is thrown when the user doesn't exist.
+*/
+class UserDoesNotExistException extends SerializableException {
+ public function __construct ($username) {
+ parent::__construct(
+ sprintf(
+ PartKeepr::i18n("The user %s doesn't exist. Maybe the user was already deleted."),
+ $username));
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/User/User.php b/src/backend/PartKeepr/User/User.php
@@ -0,0 +1,259 @@
+<?php
+namespace PartKeepr\User;
+
+use PartKeepr\UserPreference\UserPreference;
+
+use PartKeepr\Util\Deserializable,
+ PartKeepr\Util\Serializable,
+ PartKeepr\Util\BaseEntity,
+ PartKeepr\PartKeepr;
+
+/** @Entity @Table(name="PartKeeprUser") */
+class User extends BaseEntity implements Serializable, Deserializable {
+ /** @Column(length=50,unique=true) */
+ private $username;
+
+ /** @Column(length=32) */
+ private $password;
+
+ /** @Column(type="boolean") */
+ private $admin;
+
+ /**
+ * Creates a new user object.
+ *
+ * @param string $username The username to set (optional)
+ * @param string $password The password to set (optional)
+ */
+ public function __construct ($username = null, $password = null) {
+ if ($username !== null) {
+ $this->setUsername($username);
+ }
+
+ if ($password !== null) {
+ $this->setPassword($password);
+ }
+
+ $this->setAdmin(false);
+ }
+
+ /**
+ * Sets the username.
+ *
+ * Forces the username to have
+ * lowercase a-z characters.
+ *
+ * Replaces space with an underscore.
+ * Replaces dot with nothing.
+ *
+ * @param string $username The username to set. Applies automatic username modification.
+ * @return nothing
+ */
+ public function setUsername ($username) {
+ $username = strtolower($username);
+ $username = str_replace(" ", "_", $username);
+ $username = str_replace(".", "", $username);
+
+ $this->username = $username;
+
+ }
+
+ /**
+ * Sets the raw username, without replacing any special chars.
+ *
+ * This method should only be used for building a temporary user
+ * for login checks.
+ *
+ * @param string $username The raw username
+ * @return nothing
+ */
+ public function setRawUsername ($username) {
+ $this->username = $username;
+ }
+
+ /**
+ * Returns the username.
+ * @param none
+ * @return string The username
+ */
+ public function getUsername () {
+ return $this->username;
+ }
+
+ /**
+ * Sets the admin flag
+ * @param boolean $bAdmin True if the user is an admin, false otherwise
+ */
+ public function setAdmin ($bAdmin) {
+ $this->admin = (boolean)$bAdmin;
+ }
+
+ /**
+ * Returns the admin flag
+ * @return boolean True if the user is an admin
+ */
+ public function isAdmin () {
+ return $this->admin;
+ }
+
+ /**
+ * Sets the user's password. Automatically
+ * applies md5 hashing.
+ *
+ * @param string $password
+ */
+ public function setPassword ($password) {
+ $this->setHashedPassword(md5($password));
+ }
+
+ /**
+ * Returns the user's md5-hashed password.
+ * @param none
+ * @return string The md5-hashed password
+ */
+ public function getHashedPassword () {
+ return $this->password;
+ }
+
+ /**
+ * Sets the user's password. Expects a hash
+ * and does not apply md5 hasing.
+ *
+ * @param string $hashedPassword
+ */
+ public function setHashedPassword ($hashedPassword) {
+ $this->password = $hashedPassword;
+ }
+
+ /**
+ * Compares the given un-hashed password with the
+ * object's hashed password.
+ *
+ *
+ * @param string $password The unhashed password
+ * @return boolean true if the passwords match, false otherwise
+ */
+ public function comparePassword ($password) {
+ return $this->compareHashedPassword(md5($password));
+ }
+
+ /**
+ * Compares the given hashed password with the object's
+ * hashed password.
+ *
+ * @param string $hashedPassword The md5-hashed password
+ * @return boolean true if the passwords match, false otherwise
+ */
+ public function compareHashedPassword ($hashedPassword) {
+ if ($hashedPassword == $this->password) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Serializes the user object and returns it as array, suitable
+ * to process via json_encode.
+ * @param none
+ * @return array An array containing the object information
+ */
+ public function serialize () {
+ return array(
+ "id" => $this->getId(),
+ "username" => $this->getUsername()
+ );
+ }
+
+ /**
+ * Deserializes the user
+ * @param array $parameters The array with the parameters to set
+ */
+ public function deserialize (array $parameters) {
+ foreach ($parameters as $key => $value) {
+ switch ($key) {
+ case "username":
+ $this->setUsername($value);
+ break;
+ case "password":
+ if ($value !== "") {
+ $this->setPassword($value);
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * Sets a user preference
+ *
+ * @param string $preferenceKey The preference key
+ * @param string $preferenceValue The preference value
+ * @throws EntityNotPersistantException Thrown if the entity is not persistant
+ */
+ public function setPreference ($preferenceKey, $preferenceValue) {
+ return UserPreference::setPreference($this, $preferenceKey, $preferenceValue);
+ }
+
+ /**
+ * Returns a given preference object
+ *
+ * @param string $preferenceKey The preference key
+ * @return UserPreference The user preference object
+ * @throws UserPreferenceNotFoundException If the preference key was not found
+ * @throws EntityNotPersistantException Thrown if the entity is not persistant
+ */
+ public function getPreference ($preferenceKey) {
+ return UserPreference::getPreference($this, $preferenceKey);
+ }
+
+ /**
+ * Returns a given preference value
+ *
+ * @param string $preferenceKey The preference key
+ * @return UserPreference The user preference object
+ * @throws UserPreferenceNotFoundException If the preference key was not found
+ * @throws EntityNotPersistantException Thrown if the entity is not persistant
+ */
+ public function getPreferenceValue ($preferenceKey) {
+ return UserPreference::getPreferenceValue($this, $preferenceKey);
+ }
+
+ /**
+ * Deletes the given preference
+ *
+ * @param string $preferenceKey The preference key
+ * @return UserPreference The user preference object
+ * @throws UserPreferenceNotFoundException If the preference key was not found
+ * @throws EntityNotPersistantException Thrown if the entity is not persistant
+ */
+ public function deletePreference ($preferenceKey) {
+ UserPreference::deletePreference($this, $preferenceKey);
+ }
+
+ /**
+ * Returns all user preferences for this user
+ *
+ * @param none
+ * @return Array An array of UserPreference objects
+ * @throws EntityNotPersistantException Thrown if the entity is not persistant
+ */
+ public function getPreferences () {
+ return UserPreference::getPreferences($this);
+ }
+ /**
+ * Loads a user by name.
+ *
+ * @param $username string The username to query
+ * @return User A user object
+ * @throws Doctrine\ORM\NoResultException If no user was found
+ */
+ public static function loadByName ($username) {
+ $dql = "SELECT u FROM PartKeepr\User\User u WHERE u.username = :username";
+
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("username", $username);
+
+ return $query->getSingleResult();
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/User/UserManager.php b/src/backend/PartKeepr/User/UserManager.php
@@ -0,0 +1,135 @@
+<?php
+namespace PartKeepr\User;
+
+use PartKeepr\Util\Singleton,
+ PartKeepr\User\User,
+ PartKeepr\PartKeepr,
+ PartKeepr\User\Exceptions\InvalidLoginDataException,
+ PartKeepr\Category\CategoryManager,
+ PartKeepr\User\Exceptions\UserAlreadyExistsException,
+ PartKeepr\User\Exceptions\UserNotFoundException;
+
+class UserManager extends Singleton {
+ /**
+ * Returns a list of users.
+ *
+ * @param int $start Start of the list, default 0
+ * @param int $limit Number of users to list, default 10
+ * @param string $sort The field to sort by, default "name"
+ * @param string $dir The direction to sort (ASC or DESC), default ASC
+ * @param string $filter A string to filter the user's name by, default empty
+ */
+ public function getUsers ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
+
+ $qb = PartKeepr::getEM()->createQueryBuilder();
+ $qb->select("st.id, st.username")->from("PartKeepr\User\User","st");
+
+ if ($filter != "") {
+ $qb = $qb->where("LOWER(st.username) LIKE :filter");
+ $qb->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ if ($limit > -1) {
+ $qb->setMaxResults($limit);
+ $qb->setFirstResult($start);
+ }
+
+ $qb->orderBy("st.".$sort, $dir);
+
+ $query = $qb->getQuery();
+
+ $result = $query->getResult();
+
+ $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
+ $totalQueryBuilder->select("COUNT(st.id)")->from("PartKeepr\User\User","st");
+
+
+
+ if ($filter != "") {
+ $totalQueryBuilder = $totalQueryBuilder->where("LOWER(st.username) LIKE :filter");
+ $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
+ }
+
+ $totalQuery = $totalQueryBuilder->getQuery();
+
+ return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
+ }
+
+ /**
+ * Checks if the passed user already exists.
+ *
+ * @param $username string The username to check
+ */
+ public function userExists ($username) {
+ $dql = "SELECT COUNT(u) FROM PartKeepr\User\User u WHERE u.username = :name";
+
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("name", $username);
+
+ $count = $query->getSingleScalarResult();
+
+ if ($count == 0) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Creates the given user. Checks if the user already exists
+ *
+ * @param User $user The user to create
+ * @throws UserAlreadyExistsException
+ */
+ public function createUser (User $user) {
+ if ($this->userExists($user->getUsername())) {
+ throw new UserAlreadyExistsException($user->getUsername());
+ }
+
+ PartKeepr::getEM()->persist($user);
+ PartKeepr::getEM()->flush();
+ }
+
+ /**
+ * Returns the user for a given user id
+ * @param integer $id The user id
+ */
+ public function getUser ($id) {
+ return User::loadById($id);
+ }
+
+ /**
+ * Deletes an user by id
+ * @param int $id The user's id
+ */
+ public function deleteUser ($id) {
+ $user = User::loadById($id);
+
+ PartKeepr::getEM()->remove($user);
+ PartKeepr::getEM()->flush();
+ }
+
+ /**
+ * Authenticates the given user. If successful, an instance
+ * of the user is returned.
+ *
+ * @param User $user The user to authenticate
+ * @throws InvalidLoginDataException Thrown if the user's credentials are not valid
+ */
+ public function authenticate (User $user) {
+ $result = PartKeepr::getEM()
+ ->getRepository("PartKeepr\User\User")
+ ->findOneBy(
+ array(
+ "username" => $user->getUsername(),
+ "password" => $user->getHashedPassword()
+ )
+ );
+
+ if ($result == null) {
+ throw new InvalidLoginDataException();
+ } else {
+ return $result;
+ }
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/User/UserService.php b/src/backend/PartKeepr/User/UserService.php
@@ -0,0 +1,101 @@
+<?php
+namespace PartKeepr\User;
+
+use PartKeepr\Service\RestfulService,
+ PartKeepr\Service\Service,
+ PartKeepr\PartKeepr,
+ PartKeepr\User\User,
+ PartKeepr\Session\SessionManager;
+
+class UserService extends Service implements RestfulService {
+
+ /**
+ * Implements the get() call for the RestfulService.
+ *
+ * If the "id" parameter is passed, try to return the user by id. If not,
+ * return a list.
+ *
+ * @see PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ if ($this->hasParameter("id")) {
+ if (!SessionManager::getCurrentSession()->getUser()->isAdmin()) {
+ throw new \Exception("Permission denied");
+ }
+
+ return array("data" => UserManager::getInstance()->getUser($this->getParameter("id"))->serialize());
+ } else {
+ if ($this->hasParameter("sort")) {
+ $tmp = json_decode($this->getParameter("sort"), true);
+
+ $aSortParams = $tmp[0];
+ } else {
+ $aSortParams = array(
+ "property" => "username",
+ "direction" => "ASC");
+ }
+ return UserManager::getInstance()->getUsers(
+ $this->getParameter("start", $this->getParameter("start", 0)),
+ $this->getParameter("limit", $this->getParameter("limit", 25)),
+ $this->getParameter("sortby", $aSortParams["property"]),
+ $this->getParameter("dir", $aSortParams["direction"]),
+ $this->getParameter("query", ""));
+ }
+ }
+
+ /**
+ * Creates a new user.
+ *
+ * @see PartKeepr\Service.RestfulService::create()
+ */
+ public function create () {
+ if (!SessionManager::getCurrentSession()->getUser()->isAdmin()) {
+ throw new \Exception("Permission denied");
+ }
+
+ $this->requireParameter("username");
+
+ $user = new User;
+ $user->deserialize($this->getParameters());
+
+ UserManager::getInstance()->createUser($user);
+
+ return array("data" => $user->serialize());
+ }
+
+ /**
+ * Updates the user informations.
+ * @see PartKeepr\Service.RestfulService::update()
+ */
+ public function update () {
+ if (!SessionManager::getCurrentSession()->getUser()->isAdmin()) {
+ throw new \Exception("Permission denied");
+ }
+
+ $this->requireParameter("id");
+ $this->requireParameter("username");
+ $user = UserManager::getInstance()->getUser($this->getParameter("id"));
+
+ $user->deserialize($this->getParameters());
+ PartKeepr::getEM()->flush();
+
+ return array("data" => $user->serialize());
+
+ }
+
+ /**
+ * Deletes the user from the database.
+ * @see PartKeepr\Service.RestfulService::destroy()
+ */
+ public function destroy () {
+ if (!SessionManager::getCurrentSession()->getUser()->isAdmin()) {
+ throw new \Exception("Permission denied");
+ }
+
+ $this->requireParameter("id");
+
+ UserManager::getInstance()->deleteUser($this->getParameter("id"));
+
+ return array("data" => null);
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/UserPreference/Exceptions/UserPreferenceNotFoundException.php b/src/backend/PartKeepr/UserPreference/Exceptions/UserPreferenceNotFoundException.php
@@ -0,0 +1,20 @@
+<?php
+namespace PartKeepr\UserPreference\Exceptions;
+
+use PartKeepr\User\User,
+ PartKeepr\Util\SerializableException,
+ PartKeepr\PartKeepr;
+
+/**
+ * Is thrown when the user has given wrong credentials.
+ */
+class UserPreferenceNotFoundException extends SerializableException {
+ public function __construct (User $user, $preferenceKey) {
+ $message = sprintf( PartKeepr::i18n("User preference %s not found for user %s (%s)"),
+ $preferenceKey,
+ $user->getUsername(),
+ $user->getId());
+
+ parent::__construct($message);
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/UserPreference/UserPreference.php b/src/backend/PartKeepr/UserPreference/UserPreference.php
@@ -0,0 +1,229 @@
+<?php
+namespace PartKeepr\UserPreference;
+
+use PartKeepr\Util\Serializable,
+ PartKeepr\PartKeepr,
+ PartKeepr\User\User,
+ PartKeepr\Util\Configuration,
+ PartKeepr\Util\BaseEntity,
+ PartKeepr\UserPreference\Exceptions\UserPreferenceNotFoundException,
+ PartKeepr\Util\Exceptions\EntityNotPersistantException,
+ Doctrine\ORM\NoResultException;
+
+/**
+ * Represents a user preference entry.
+ *
+ * User preferences are a simple key => value mechanism, where the developer can
+ * specify the key and value himself.
+ *
+ * Note that values are stored internally as serialized PHP values to keep their type.
+ *
+ * @Entity
+ **/
+class UserPreference implements Serializable {
+ /**
+ * Defines the key of the user preference
+ * @Column(type="string",length=255)
+ * @Id
+ * @var string
+ */
+ private $preferenceKey;
+
+ /**
+ * Defines the value. Note that the value is internally stored as a serialized string.
+ * @Column(type="text")
+ * @var mixed
+ */
+ private $preferenceValue;
+
+ /**
+ * Defines the user
+ * @ManyToOne(targetEntity="PartKeepr\User\User")
+ * @Id
+ * @var User
+ */
+ private $user;
+
+
+ /**
+ * Sets the user for this entry
+ * @param User $user
+ */
+ public function setUser (User $user) {
+ $this->user = $user;
+ }
+
+ /**
+ * Returns the user associated with this entry
+ * @return \PartKeepr\User\User
+ */
+ public function getUser () {
+ return $this->user;
+ }
+
+ /**
+ * Sets the key for this user preference
+ * @param string $key The key name
+ */
+ public function setKey ($key) {
+ $this->preferenceKey = $key;
+ }
+
+ /**
+ * Returns the key of this entry
+ * @return string
+ */
+ public function getKey () {
+ return $this->preferenceKey;
+ }
+
+ /**
+ * Sets the value for this entry
+ * @param mixed $value
+ */
+ public function setValue ($value) {
+ $this->preferenceValue = serialize($value);
+ }
+
+ /**
+ * Returns the value for this entry
+ * @return mixed The value
+ */
+ public function getValue () {
+ return unserialize($this->preferenceValue);
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see PartKeepr\Util.Serializable::serialize()
+ */
+ public function serialize () {
+ return array(
+ "key" => $this->getKey(),
+ "value" => $this->getValue(),
+ "user_id" => $this->getUser()->getId()
+ );
+ }
+
+ /**
+ * Creates or updates a preference for a given user.
+ *
+ * @param User $user The user to set the preference for
+ * @param string $key The key to set
+ * @param string $value The value to set
+ * @throws EntityNotPersistantException Thrown if the entity is not persistant
+ */
+ public static function setPreference (User $user, $key, $value) {
+ if (!PartKeepr::getEM()->contains($user)) {
+ throw new EntityNotPersistantException();
+ }
+
+ $dql = "SELECT up FROM PartKeepr\UserPreference\UserPreference up WHERE up.user = :user AND ";
+ $dql .= "up.preferenceKey = :key";
+
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("user", $user);
+ $query->setParameter("key", $key);
+
+ try {
+ $userPreference = $query->getSingleResult();
+ } catch (\Exception $e) {
+ $userPreference = new UserPreference();
+ $userPreference->setUser($user);
+ $userPreference->setKey($key);
+
+ PartKeepr::getEM()->persist($userPreference);
+ }
+
+ $userPreference->setValue($value);
+
+ PartKeepr::getEM()->flush();
+
+ return $userPreference;
+ }
+
+ /**
+ * Returns a specific preference value for the given user
+ *
+ * @param User $user The user to retrieve the preference for
+ * @param string $key The preference key to retrieve
+ * @return string The preference string
+ * @throws UserPreferenceNotFoundException Thrown if the preference key was not found
+ * @throws EntityNotPersistantException Thrown if the entity is not persistant
+ */
+ public static function getPreferenceValue (User $user, $key) {
+ $userPreference = self::getPreference($user, $key);
+
+ return $userPreference->getValue();
+ }
+
+ /**
+ * Returns all preferences for the given user
+ * @param User $user The user
+ * @throws EntityNotPersistantException Thrown if the user entity is not persistent
+ */
+ public static function getPreferences (User $user) {
+ if (!PartKeepr::getEM()->contains($user)) {
+ throw new EntityNotPersistantException();
+ }
+
+ $dql = "SELECT up FROM PartKeepr\UserPreference\UserPreference up WHERE up.user = :user";
+
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("user", $user);
+
+ return $query->getResult();
+ }
+
+ /**
+ * Returns a specific preference object for the given user
+ *
+ * @param User $user The user to retrieve the preference for
+ * @param string $key The preference key to retrieve
+ * @return UserPreference The preference object
+ * @throws UserPreferenceNotFoundException Thrown if the preference key was not found
+ * @throws EntityNotPersistantException Thrown if the entity is not persistant
+ */
+ public static function getPreference (User $user, $key) {
+ if (!PartKeepr::getEM()->contains($user)) {
+ throw new EntityNotPersistantException();
+ }
+
+ $dql = "SELECT up FROM PartKeepr\UserPreference\UserPreference up WHERE up.user = :user AND ";
+ $dql .= "up.preferenceKey = :key";
+
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("user", $user);
+ $query->setParameter("key", $key);
+
+ try {
+ $up = $query->getSingleResult();
+ return $up;
+ } catch (NoResultException $e) {
+ throw new UserPreferenceNotFoundException($user, $key);
+ }
+ }
+
+ /**
+ * Removes a specific setting for a specific user.
+ *
+ * @param User $user The user to delete the preference for
+ * @param string $key The key to delete
+ * @throws EntityNotPersistantException Thrown if the entity is not persistant
+ */
+ public static function deletePreference (User $user, $key) {
+ if (!PartKeepr::getEM()->contains($user)) {
+ throw new EntityNotPersistantException();
+ }
+
+ $dql = "DELETE FROM PartKeepr\UserPreference\UserPreference up WHERE up.user = :user AND ";
+ $dql .= "up.preferenceKey = :key";
+
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("user", $user);
+ $query->setParameter("key", $key);
+
+ $query->execute();
+ }
+
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/UserPreference/UserPreferenceService.php b/src/backend/PartKeepr/UserPreference/UserPreferenceService.php
@@ -0,0 +1,96 @@
+<?php
+namespace PartKeepr\UserPreference;
+
+use PartKeepr\User\User,
+ PartKeepr\Util\Configuration,
+ PartKeepr\Service\RestfulService,
+ PartKeepr\Session\SessionManager,
+ PartKeepr\Service\Service,
+ PartKeepr\PartKeepr;
+
+/**
+ * Represents the user preference service. This service is implemented as a RestfulService, however,
+ * only setting and deleting properties is supported, as we don't want to have duplicate values per key.
+ *
+ * For convinience, create() and update() perform the exact same function.
+ * @author felicitus
+ *
+ */
+class UserPreferenceService extends Service implements RestfulService {
+ /**
+ * Returns the preferences for the current user, or a user specified by user_id (admin only).
+ *
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ $user = null;
+
+ if ($this->hasParameter("user_id") && SessionManager::getCurrentSession()->getUser()->isAdmin()) {
+ if ($this->getParameter("user_id") != 0) {
+ $user = User::loadById($this->getParameter("user_id"));
+ }
+ } else {
+ $user = SessionManager::getCurrentSession()->getUser();
+ }
+
+ $aPreferences = array();
+
+ foreach ($user->getPreferences() as $result) {
+ $aPreferences[] = $result->serialize();
+ }
+
+ return array("data" => $aPreferences);
+ }
+
+ /**
+ * Creates or updates a value for a specific key.
+ *
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::create()
+ */
+ public function create() {
+ $userPreference = UserPreference::setPreference($this->getUser(), $this->getParameter("key"), $this->getParameter("value"));
+
+ return array("data" => $userPreference->serialize());
+ }
+
+ /**
+ * Creates or updates a value for a specific key.
+ *
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::update()
+ */
+ public function update () {
+ return $this->create();
+ }
+
+ /**
+ * Deletes a key-value combination from the database.
+ *
+ * (non-PHPdoc)
+ * @see PartKeepr\Service.RestfulService::destroy()
+ */
+ public function destroy () {
+ if ($this->hasParameter("user_id") && SessionManager::getCurrentSession()->getUser()->isAdmin()) {
+ UserPreference::deletePreference(User::loadById($this->getParameter("user_id")), $this->getParameter("key"));
+ } else {
+ UserPreference::deletePreference($this->getUser(), $this->getParameter("key"));
+ }
+ }
+
+ public function changePassword () {
+ if (Configuration::getOption("partkeepr.frontend.allow_password_change", true) === false) {
+ throw new \Exception("Password changing has been disabled on this server");
+ }
+
+ if (!$this->getUser()->compareHashedPassword($this->getParameter("oldpassword"))) {
+ throw new \Exception("Invalid Password");
+ } else {
+ $this->getUser()->setHashedPassword($this->getParameter("newpassword"));
+ }
+
+ return array("data" => PartKeepr::i18n("Password changed successfully"));
+
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Util/BaseEntity.php b/src/backend/PartKeepr/Util/BaseEntity.php
@@ -0,0 +1,116 @@
+<?php
+namespace PartKeepr\Util;
+
+use PartKeepr\Util\Exceptions\EntityNotFoundException,
+ PartKeepr\PartKeepr;
+
+/** @MappedSuperclass */
+class BaseEntity {
+ /**
+ * @Id @Column(type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ * @var unknown_type
+ */
+ private $id;
+
+ /**
+ * Returns the ID of this object.
+ * @param none
+ * @return int The ID of this object
+ */
+ public function getId () {
+ return $this->id;
+ }
+
+ /**
+ * Syncs a given collection with the entity's collection.
+ *
+ * This is used for 1:n or m:n relations, where we need to process inserts, updates and deletes for the records.
+ *
+ * @param array $sourceArray The array with all records which should be deserialized
+ * @param \Doctrine\Common\Collections\Collection $collection The collection which contains the existing records
+ * @param string $entityClass The class name which is used when a new entity needs to be created
+ */
+ public function deserializeChildren (array $sourceArray, \Doctrine\Common\Collections\Collection $collection, $entityClass) {
+ $deletes = array();
+ $inserts = array();
+
+ /* Round 1: Check if we've got a matching id in both lists. If yes, we know that the record
+ * should be updated. If no, the record should be appended */
+ foreach ($sourceArray as $sourceItem) {
+ $bFound = false;
+ foreach ($collection as $item) {
+ if ($item->getId() == $sourceItem["id"]) {
+ // Directly update
+ $item->deserialize($sourceItem);
+ $bFound = true;
+ break;
+ }
+ }
+
+ if (!$bFound) {
+ $inserts[] = $sourceItem;
+ }
+ }
+
+ /* Round 2: Check for items which are in the collection but not in the sourceArray. */
+ foreach ($collection as $targetItem) {
+ $bFound = false;
+ foreach ($sourceArray as $item) {
+ if ($targetItem->getId() == $item["id"]) {
+ $bFound = true;
+ break;
+ }
+ }
+
+ if (!$bFound) {
+ $deletes[] = $targetItem;
+ }
+ }
+
+ foreach ($inserts as $item) {
+ $class = new $entityClass;
+ $class->deserialize($item);
+
+ $collection->add($class);
+ PartKeepr::getEM()->persist($class);
+ }
+
+ /* Remove the to-be-deleted items from the collection. Note that we store the instance of the item,
+ * so we can simply use removeElement.
+ */
+ foreach ($deletes as $item) {
+ $collection->removeElement($item);
+ PartKeepr::getEM()->remove($item);
+ }
+ }
+
+ /**
+ * Serializes the children of a specific collection
+ * @param \Doctrine\Common\Collections\Collection $array The array holding BaseEntities to serialize
+ */
+ public function serializeChildren (\Doctrine\Common\Collections\Collection $array) {
+ $aData = array();
+ $aData["totalCount"] = $array->count();
+ $aData["data"] = array();
+
+ foreach ($array as $item) {
+ $aData["data"][] = $item->serialize();
+ }
+
+ return array("response" => $aData);
+ }
+
+ /**
+ * Loads the entity from the database.
+ * @param integer $id The entity's id
+ */
+ public static function loadById ($id) {
+ $entity = PartKeepr::getEM()->find(get_called_class(), $id);
+
+ if (!is_object($entity)) {
+ throw new EntityNotFoundException(get_called_class(), $id);
+ }
+ return $entity;
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Util/Configuration.php b/src/backend/PartKeepr/Util/Configuration.php
@@ -0,0 +1,92 @@
+<?php
+namespace PartKeepr\Util;
+
+use PartKeepr\PartKeepr;
+
+/**
+ * This class manages simple key -> value configurations within the system.
+ *
+ * This allows the user to configure certain aspects of the system in a central place.
+ *
+ * The convention is to use a dotted format, for example:
+ *
+ * flipbeat.cms.layoutrenderer
+ *
+ * @author felicitus
+ */
+class Configuration {
+ private static $options = array();
+
+ /**
+ * Sets the option to value.
+ *
+ * @param string $option The option to set
+ * @param string $value The value to set
+ */
+ public static function setOption ($option, $value) {
+ Configuration::$options[$option] = $value;
+ }
+
+ /**
+ * Returns the value of an option. The developer
+ * may additionally specify a default value, which
+ * is returned when no option was found.
+ *
+ * @param string $option The option to return
+ * @param string $default The default value if the option was not found
+ */
+ public static function getOption ($option, $default = false) {
+ if (!array_key_exists($option, Configuration::$options)) {
+ return $default;
+ }
+ return Configuration::$options[$option];
+ }
+
+ /**
+ * Returns all configuration options
+ *
+ * @return array An array with key=>value assignments
+ */
+ public static function getOptions () {
+ return Configuration::$options;
+ }
+
+ /**
+ * Returns a configuration file, based on all configurations.
+ *
+ * @param none
+ * @return string A complete configuration file including namespace and use directives
+ */
+ public static function dumpConfig () {
+ $config = <<<EOD
+<?php
+namespace PartKeepr;
+use PartKeepr\Util\Configuration;
+
+
+EOD;
+ foreach (Configuration::$options as $option => $value) {
+ switch (PartKeepr::getType($value)) {
+ case "string":
+ $config .= 'Configuration::setOption("'.$option.'", "'.$value.'");'."\n";
+ break;
+ case "boolean":
+ $config .= 'Configuration::setOption("'.$option.'", '.($value === true ? 'true' : 'false').');'."\n";
+ break;
+ case "integer":
+ case "numeric":
+ $config .= 'Configuration::setOption("'.$option.'", '.intval($value).');'."\n";
+ break;
+ case "float":
+ $config .= 'Configuration::setOption("'.$option.'", '.floatval($value).');'."\n";
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ return $config;
+ }
+}
+?>+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Util/Deserializable.php b/src/backend/PartKeepr/Util/Deserializable.php
@@ -0,0 +1,10 @@
+<?php
+namespace PartKeepr\Util;
+
+interface Deserializable {
+ /**
+ * Deserializes the entity from an array format
+ * @param $parameters array The serialized form of the entity to deserialize
+ */
+ public function deserialize (array $parameters);
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Util/Exceptions/EntityNotFoundException.php b/src/backend/PartKeepr/Util/Exceptions/EntityNotFoundException.php
@@ -0,0 +1,17 @@
+<?php
+namespace PartKeepr\Util\Exceptions;
+
+use PartKeepr\Util\SerializableException,
+ PartKeepr\PartKeepr;
+
+/**
+ * Thrown when an entity via loadById() was not found.
+ */
+class EntityNotFoundException extends SerializableException {
+ public function __construct ($class, $id) {
+ parent::__construct(
+ sprintf(
+ PartKeepr::i18n("The entity %s with the id %d could not be found"),
+ $class, $id));
+ }
+}
diff --git a/src/backend/PartKeepr/Util/Exceptions/EntityNotPersistantException.php b/src/backend/PartKeepr/Util/Exceptions/EntityNotPersistantException.php
@@ -0,0 +1,14 @@
+<?php
+namespace PartKeepr\Util\Exceptions;
+
+use PartKeepr\Util\SerializableException,
+ PartKeepr\PartKeepr;
+
+/**
+ * Thrown when an entity via loadById() was not found.
+ */
+class EntityNotPersistantException extends SerializableException {
+ public function __construct () {
+ parent::__construct("The entity is not persistant.");
+ }
+}
diff --git a/src/backend/PartKeepr/Util/Exceptions/OutOfRangeException.php b/src/backend/PartKeepr/Util/Exceptions/OutOfRangeException.php
@@ -0,0 +1,6 @@
+<?php
+namespace PartKeepr\Util\Exceptions;
+
+use PartKeepr\Util\SerializableException;
+
+class OutOfRangeException extends SerializableException {}
diff --git a/src/backend/PartKeepr/Util/OS/OperatingSystem.php b/src/backend/PartKeepr/Util/OS/OperatingSystem.php
@@ -0,0 +1,94 @@
+<?php
+namespace PartKeepr\Util\OS;
+
+class OperatingSystem {
+ /**
+ * Returns the platform name the system is running on.
+ *
+ * Typical return values are: "Linux", "FreeBSD", "Darwin" (Mac OSX),
+ * "Windows".
+ */
+ public function getPlatform () {
+ if (function_exists("posix_uname")) {
+ $data = posix_uname();
+
+ if (array_key_exists("sysname", $data)) {
+ return $data["sysname"];
+ }
+ }
+
+ if (\PHP_OS == "WINNT") {
+ return "Windows";
+ }
+
+ return "unknown";
+ }
+
+ /**
+ * Returns the distribution
+ * @return string string
+ */
+ public function getRelease () {
+ switch (strtolower($this->getPlatform())) {
+ case "freebsd":
+ /**
+ * Unfortunately, there's no text file on FreeBSD which tells us the release
+ * number. Thus, we hope that "release" within posix_uname() is defined.
+ */
+ if (function_exists("posix_uname")) {
+ $data = posix_uname();
+
+ if (array_key_exists("release", $data)) {
+ return $data["release"];
+ }
+ }
+ break;
+ case "darwin":
+ /**
+ * Mac stores its version number in a public readable plist file, which
+ * is in XML format.
+ */
+ $document = new \DomDocument();
+ $document->load("/System/Library/CoreServices/SystemVersion.plist");
+ $xpath = new \DOMXPath($document);
+ $entries = $xpath->query("/plist/dict/*");
+
+ $previous = "";
+ foreach ($entries as $entry) {
+ if (strpos($previous, "ProductVersion") !== false) {
+ return $entry->textContent;
+ }
+ $previous = $entry->textContent;
+ }
+ break;
+ case "linux":
+ return $this->getLinuxDistribution();
+ break;
+ default:
+ break;
+ }
+
+ return "unknown";
+ }
+
+ /**
+ * Tries to detect the distribution.
+ *
+ * Currently, we only execute lsb_release to find out the version number.
+ * As I don't have any other distributions at hand to test with, I rely
+ * on user feedback which distributions don't have lsb_release.
+ */
+ public function getLinuxDistribution () {
+ /* Try executing lsb_release */
+ $release = @exec('lsb_release -d -s', $void, $retval);
+
+ if ($retval === 0 && $release !== "")
+ {
+ return $release;
+ }
+
+ //@todo we need better handling here
+ return "unknown";
+ }
+
+}
diff --git a/src/backend/PartKeepr/Util/Serializable.php b/src/backend/PartKeepr/Util/Serializable.php
@@ -0,0 +1,11 @@
+<?php
+namespace PartKeepr\Util;
+
+interface Serializable {
+ /**
+ * Serializes the entity into an array format, which in turn can
+ * be used by json_encode.
+ * @return array The serialized form of the entity
+ */
+ public function serialize ();
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Util/SerializableException.php b/src/backend/PartKeepr/Util/SerializableException.php
@@ -0,0 +1,60 @@
+<?php
+namespace PartKeepr\Util;
+
+class SerializableException extends \Exception {
+ protected $detailMessage = "No detail message has been entered.";
+
+ /* @todo: stub */
+ public function getDetail () {
+ return $this->detailMessage;
+ }
+
+ public function setDetail ($message) {
+ $this->detailMessage = $message;
+ }
+
+ public function serialize () {
+ return array(
+ "message" => $this->getMessage(),
+ "detail" => $this->getDetail(),
+ "exception" => get_class($this),
+ "code" => $this->getCode()
+ //"backtrace" => $this->getFormattedTrace()
+ );
+ }
+
+ public function getFormattedTrace () {
+ $items = $this->getTrace();
+
+ $message = "";
+
+ $args = array();
+
+ foreach ($items as $id => $item) {
+ foreach ($item["args"] as $itemData) {
+ switch (gettype($itemData)) {
+ case "object":
+ if (method_exists($itemData, "__toString")) {
+ $args[] = get_class($itemData) . "(".$itemData->__toString().")";
+ } else {
+ $args[] = get_class($itemData);
+ }
+ break;
+ case "array":
+ $args[] = "array";
+ break;
+ default:
+ $args[] = $itemData;
+ break;
+ }
+ }
+
+ $message .= $item["file"].":".$item["line"]."\n";
+ $message .= $item["function"] ."(".implode(",", $args).")"."\n\n";
+ }
+
+ return $message;
+ }
+
+}
+?>+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Util/Singleton.php b/src/backend/PartKeepr/Util/Singleton.php
@@ -0,0 +1,22 @@
+<?php
+namespace PartKeepr\Util;
+
+abstract class Singleton {
+ static $instance = null;
+
+ private function __construct () {
+
+ }
+
+ /**
+ * Returns an instance of the current singleton
+ * @return $this
+ */
+ public static function getInstance () {
+ if (!static::$instance instanceof static) {
+ static::$instance = new static;
+ }
+
+ return static::$instance;
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/PartKeepr/Util/UtilService.php b/src/backend/PartKeepr/Util/UtilService.php
@@ -0,0 +1,13 @@
+<?php
+namespace PartKeepr\Util;
+
+use PartKeepr\Service\AnonService;
+
+class UtilService extends AnonService {
+ public function clearCache () {
+ apc_clear_cache();
+ apc_clear_cache("user");
+
+ return array("status" => "ok");
+ }
+}+
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Auth/AuthService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Auth/AuthService.php
@@ -1,52 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Auth;
-
-use de\RaumZeitLabor\PartKeepr\Service\AnonService,
- de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\User\UserManager,
- de\RaumZeitLabor\PartKeepr\User\Exceptions\InvalidLoginDataException,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class AuthService extends AnonService {
- /**
- * Logs in the given user. If the login was successful,
- * a session is automatically started.
- *
- * @throws InvalidLoginDataException
- */
- public function login () {
- $this->requireParameter("username");
- $this->requireParameter("password");
-
- /* Build a temporary user */
- $user = new User;
- $user->setRawUsername($this->getParameter("username"));
- $user->setHashedPassword($this->getParameter("password"));
-
- $authenticatedUser = UserManager::getInstance()->authenticate($user);
-
- if ($authenticatedUser !== false) {
- /* Start Session */
- $session = SessionManager::getInstance()->startSession($authenticatedUser);
-
- $aPreferences = array();
-
- foreach ($session->getUser()->getPreferences() as $result) {
- $aPreferences[] = $result->serialize();
- }
-
- return array(
- "sessionid" => $session->getSessionID(),
- "username" => $this->getParameter("username"),
- "admin" => $session->getUser()->isAdmin(),
- "userPreferences" => array(
- "response" => array(
- "data" => $aPreferences
- )));
- } else {
- throw new InvalidLoginDataException();
- }
-
-
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Category/AbstractCategory.php b/src/backend/de/RaumZeitLabor/PartKeepr/Category/AbstractCategory.php
@@ -1,202 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Category;
-
-use de\RaumZeitLabor\PartKeepr\Util\BaseEntity;
-use de\RaumZeitLabor\PartKeepr\Util\Serializable;
-use DoctrineExtensions\NestedSet\Node;
-
-/**
- * @MappedSuperclass
- * @Table(indexes={@index(columns={"lft"}),@index(columns={"rgt"})})
- *
- * Represents an abstract category. This class isn't directly usable; you need to inherit it to take advantage of
- * the AbstractCategoryManager.
- *
- * If you are interested on how NestedSets work, please read http://en.wikipedia.org/wiki/Nested_set_model
- */
-class AbstractCategory extends BaseEntity implements Node, Serializable {
- /**
- * The "left" property of the nested set
- * @Column(type="integer")
- * @var integer
- */
- private $lft;
-
- /**
- * The "right" property of the nested set
- * @Column(type="integer")
- * @var integer
- */
- private $rgt;
-
- /**
- * The name of the category
- * @Column(length=128)
- * @var string
- */
- private $name;
-
- /**
- * The description of the category
- * @Column(type="text",nullable=true)
- * @var string
- */
- private $description;
-
- /**
- * Holds the parent node ID. Note that this
- * is not a persistant value, but rather calculated
- * or set on the fly.
- * @var int
- */
- private $parent;
-
- /**
- * Holds the category path.
- *
- * @Column(type="text",nullable=true)
- *
- * @var string
- */
- private $categoryPath;
-
- /**
- * Sets the name of this category
- * @param string $name The name to set
- */
- public function setName ($name) {
- $this->name = $name;
- }
-
- /**
- * Returns the name of this category
- * @return string The category name
- */
- public function getName () {
- return $this->name;
- }
-
- /**
- * Sets the parent for this category.
- *
- * @param int $id The parent node
- */
- public function setParent ($id) {
- $this->parent = $id;
- }
-
- /**
- * Returns the parent node for this node.
- * @return int The parent node
- */
- public function getParent () {
- return $this->parent;
- }
-
- /**
- * Sets the description for this category
- * @param string $description The description of this category
- */
- public function setDescription ($description) {
- $this->description = $description;
- }
-
- /**
- * Returns the description of this category
- * @return string The description
- */
- public function getDescription () {
- return $this->description;
- }
-
- /**
- * Returns the "left" value of the nested set.
- *
- * @return int The left value
- *
- * (non-PHPdoc)
- * @see DoctrineExtensions\NestedSet.Node::getLeftValue()
- */
- public function getLeftValue() {
- return $this->lft;
- }
-
- /**
- * Sets the "left" value.
- *
- * @param $lft integer The left value
- * (non-PHPdoc)
- * @see DoctrineExtensions\NestedSet.Node::setLeftValue()
- */
- public function setLeftValue($lft) {
- $this->lft = $lft;
- }
-
- /**
- * Returns the "right" value of the nested set.
- *
- * @return int The right value
- *
- * (non-PHPdoc)
- * @see DoctrineExtensions\NestedSet.Node::getRightValue()
- */
- public function getRightValue() {
- return $this->rgt;
- }
-
- /**
- * Sets the "right" value of the nested set
- *
- * @param $rgt int The right value
- *
- * (non-PHPdoc)
- * @see DoctrineExtensions\NestedSet.Node::setRightValue()
- */
- public function setRightValue($rgt) {
- $this->rgt = $rgt;
- }
-
- /**
- * Serializes the entity.
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "name" => $this->getName(),
- "description" => $this->getDescription()
- );
- }
-
- /**
- * Returns a string representation of the current node.
- *
- * @return string The node name
- *
- * (non-PHPdoc)
- * @see DoctrineExtensions\NestedSet.Node::__toString()
- */
- public function __toString () {
- return $this->getName();
- }
-
- /**
- * Retrieves the category path
- *
- * @return string The category path
- */
- public function getCategoryPath () {
- return $this->categoryPath;
- }
-
- /**
- * Sets the category path.
- *
- * THIS IS ONLY TO BE CALLED FROM THE CATEGORYMANAGER! DON'T MESS WITH IT!
- *
- * @param string $categoryPath
- */
- public function setCategoryPath ($categoryPath) {
- $this->categoryPath = $categoryPath;
- }
-
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Category/AbstractCategoryManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Category/AbstractCategoryManager.php
@@ -1,222 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Category;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\Category\Category,
- de\RaumZeitLabor\PartKeepr\Util\SerializableException,
- de\RaumZeitLabor\PartKeepr\Category\Exceptions\CategoryNotFoundException,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Util\Configuration,
- DoctrineExtensions\NestedSet\Manager,
- DoctrineExtensions\NestedSet\Config,
- DoctrineExtensions\NestedSet\NodeWrapper;
-
-abstract class AbstractCategoryManager extends Singleton {
- /**
- * Holds the node manager
- * @var object The node manager
- */
- private $nodeManager;
-
- /**
- * Holds the FQCN of the target entity
- * @var de\RaumZeitLabor\PartKeepr\Category\AbstractCategory
- */
- protected $categoryClass = "de\RaumZeitLabor\PartKeepr\Category\AbstractCategory";
-
- /**
- * Returns the node manager. Creates it if it doesn't exist.
- * @todo Can this method be made private?
- * @return Manager The node manager
- */
- public function getNodeManager () {
- if (!$this->nodeManager) {
- $config = new Config(PartKeepr::getEM(), $this->categoryClass);
-
- $this->nodeManager = new Manager($config);
- }
-
- return $this->nodeManager;
- }
-
- /**
- * Returns the child node id's for a given node id.
- * @param integer $id The ID for which to retrieve the child nodes
- * @return array An array of the children id's
- * @todo Refactor this method name to indicate that it operates on IDs only.
- */
- public function getChildNodes ($id) {
- $category = $this->getCategory($id);
-
- $aData = array();
-
- foreach ($category->getDescendants() as $cat) {
- $aData[] = $cat->getNode()->getId();
- }
- return $aData;
- }
-
- /**
- * Returns all categories.
- * @return The category tree
- */
- public function getAllCategories () {
- return $this->getNodeManager()->fetchTree(1);
- }
-
- /**
- * Ensures that the root node exists. If not, this method creates it.
- */
- public function ensureRootExists () {
- /* Check if the root node exists */
- $rootNode = $this->getNodeManager()->fetchTree(1);
-
- if ($rootNode === null) {
- $this->createRootNode();
- }
- }
-
- /**
- * Returns the root node for the category tree.
- * @return The category root node
- */
- public function getRootNode () {
- return $this->getNodeManager()->fetchTree(1);
- }
-
- /**
- * Create the root node for the category tree.
- */
- public function createRootNode () {
- $rootNode = new $this->categoryClass();
- $rootNode->setName("Root Category");
- $rootNode->setDescription("");
-
- $this->getNodeManager()->createRoot($rootNode);
- }
-
- /**
- * Adds a given category.
- * @param Category $category The category to add to the tree
- * @return Category the added category
- */
- public function addCategory (AbstractCategory $category) {
- $parent = $category->getParent();
-
- if ($parent == 0) {
- $parent = $this->getRootNode();
- } else {
- $parent = PartKeepr::getEM()->find($this->categoryClass, $parent);
- $parent = new NodeWrapper($parent, $this->getNodeManager());
- }
-
- $node = $parent->addChild($category);
-
- // Force category path update
- $this->updateCategoryPaths($node);
-
- // Flush the category path changes
- PartKeepr::getEM()->flush();
-
- return $node;
- }
-
- /**
- * Deletes the given category ID.
- * @param $id int The category id to delete
- * @throws CategoryNotFoundException If the category wasn't found
- */
- public function deleteCategory ($id) {
- $this->getCategory($id)->delete();
- }
-
- /**
- * Returns the category with the given ID.
- * @param int $id The category id
- * @throws CategoryNotFoundException If the category wasn't found
- */
- public function getCategory ($id) {
- $category = $this->loadCategoryById($id);
-
- return new NodeWrapper($category, $this->getNodeManager());
- }
-
- /**
- * Returns the overall category count currently existing.
- * @return int The amount of categories in the database
- */
- public function getCategoryCount () {
- $dql = "SELECT COUNT(c.id) FROM ".$this->categoryClass." c";
-
- return PartKeepr::getEM()->createQuery($dql)->getSingleScalarResult();
- }
-
- /**
- * Updates the category paths for a given node and all children.
- *
- * This method is usually called whenever a category is moved.
- *
- * @param NodeWrapper $startNode The node to start updating at
- */
- public function updateCategoryPaths (NodeWrapper $startNode) {
- $pathSeparator = Configuration::getOption("partkeepr.category.path_separator", " ➤ ");
-
- $startNode->getNode()->setCategoryPath($startNode->getPath($pathSeparator, true));
-
- foreach ($startNode->getChildren() as $child) {
- $this->updateCategoryPaths($child);
- }
- }
-
- /**
- * 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;
-
- return $class::loadById($id);
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Category/AbstractCategoryService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Category/AbstractCategoryService.php
@@ -1,145 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Category;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\Category\CategoryManager,
- DoctrineExtensions\NestedSet\NodeWrapper;
-
-
-abstract class AbstractCategoryService extends Service {
- protected $categoryManagerClass = "de\RaumZeitLabor\PartKeepr\Category\AbstractCategoryManager";
- protected $categoryClass = "de\RaumZeitLabor\PartKeepr\Category\AbstractCategory";
-
- /**
- * Returns all categories found in the system.
- * @return array A serialized tree
- */
- public function getCategories () {
- $categories = $this->getCategoryManager()->getAllCategories(
- $this->getParameter("parent", 0));
-
- return $this->serializeTree($categories);
- }
-
- /**
- * Moves the given category from one to another category.
- */
- public function moveCategory () {
- $this->requireParameter("category");
- $this->requireParameter("target");
-
- $category = $this->getCategoryManager()->getCategory($this->getParameter("category"));
-
- if (intval($this->getParameter("target", 0)) !== 0) {
-
- $parent = $this->getCategoryManager()->getCategory($this->getParameter("target"));
-
- $category->moveAsLastChildOf($parent);
- $this->getCategoryManager()->updateCategoryPaths($category);
-
- }
- }
-
- /**
- * Deletes the given category.
- */
- public function deleteCategory () {
- $this->requireParameter("id");
-
- $this->getCategoryManager()->deleteCategory($this->getParameter("id"));
-
- return array("id" => $this->getParameter("id"));
- }
-
- /**
- * Updates the given category.
- */
- public function update () {
- $this->requireParameter("id");
- $this->requireParameter("name");
-
- $category = $this->getCategoryManager()->getCategory($this->getParameter("id"));
-
- $category->getNode()->setName($this->getParameter("name"));
- $category->getNode()->setDescription($this->getParameter("description", ""));
-
- PartKeepr::getEM()->persist($category->getNode());
-
- $this->getCategoryManager()->updateCategoryPaths($category);
-
- return array("data" => $this->serializeCategory($category));
- }
-
- public function create () {
- $this->requireParameter("name");
- $this->requireParameter("parent");
-
- $category = new $this->categoryClass;
- $category->setName($this->getParameter("name"));
- $category->setDescription($this->getParameter("description", ""));
- $category->setParent($this->getParameter("parent"));
-
- $category = $this->getCategoryManager()->addCategory($category);
-
- $this->getCategoryManager()->updateCategoryPaths($category);
-
- return array("data" => $this->serializeCategory($category));
- }
-
- public function destroy () {
- return $this->deleteCategory();
- }
-
- private function serializeCategory ($category) {
- $data = $category->getNode()->serialize();
-
- if ($category->getParent() !== null) {
- $data["parent"] = $category->getParent()->getNode()->getId();
- $data["parentName"] = $category->getParent()->getNode()->getName();
- }
-
- return $data;
- }
-
- /**
- * Returns all categories
- */
- public function getAllCategories () {
- return $this->serializeTree($this->getCategoryManager()->getAllCategories());
- }
-
- /**
- * Serializes the given NodeWrapper as array including all children.
- * @param NodeWrapper $node The category nodewrapper to serialize
- * @throws \Exception
- */
- public function serializeTree (NodeWrapper $node = null) {
- if ($node == null) {
- throw new \Exception("Node must not be null!");
- }
-
- $aData = $node->getNode()->serialize();
-
- $aData["children"] = array();
-
- if (count($node->getChildren()) == 0) {
- $aData["leaf"] = true;
- } else {
- $aData["expanded"] = true;
- }
-
- foreach ($node->getChildren() as $child) {
- $aData["children"][] = $this->serializeTree($child);
-
- }
-
- return $aData;
- }
-
- public function getCategoryManager () {
- $categoryManager = $this->categoryManagerClass;
-
- return $categoryManager::getInstance();
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Category/Exceptions/CategoryNotFoundException.php b/src/backend/de/RaumZeitLabor/PartKeepr/Category/Exceptions/CategoryNotFoundException.php
@@ -1,15 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Category\Exceptions;
-
-use de\RaumZeitLabor\PartKeepr\Util\SerializableException,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
- * Thrown when the requested category was not found.
- */
-class CategoryNotFoundException extends SerializableException {
- public function __construct ($id) {
- parent::__construct(sprintf(PartKeepr::i18n("Category %d not found."), $id));
- }
-}
-?>-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/CronLogger/CronLogger.php b/src/backend/de/RaumZeitLabor/PartKeepr/CronLogger/CronLogger.php
@@ -1,58 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\CronLogger;
-
-use de\RaumZeitLabor\PartKeepr\UploadedFile\UploadedFile,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Util\Deserializable;
-
-/**
- * Holds a project attachment
- * @Entity
- **/
-class CronLogger extends BaseEntity {
- /**
- * @Column(type="datetime")
- * @var \DateTime
- */
- private $lastRunDate;
-
- /**
- * @Column(type="string")
- * @var string
- */
- private $cronjob;
-
- /**
- * Sets the last run date and time for this entry
- * @param \DateTime $date The date and time
- */
- public function setLastRunDate (\DateTime $date) {
- $this->lastRunDate = $date;
- }
-
- /**
- * Returns the date and time for this entry
- *
- * @return \DateTime the date and time for this entry
- */
- public function getLastRunDate () {
- return $this->lastRunDate;
- }
-
- /**
- * Sets the cronjob for this entry
- * @param string $cronjob the title for this entry
- */
- public function setCronjob ($cronjob) {
- $this->cronjob = $cronjob;
- }
-
- /**
- * Returns the cronjob for this entry
- * @return string the title
- */
- public function getCronjob () {
- return $this->cronjob;
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/CronLogger/CronLoggerManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/CronLogger/CronLoggerManager.php
@@ -1,86 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\CronLogger;
-
-use de\RaumZeitLabor\PartKeepr\Manager\AbstractManager,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class CronLoggerManager extends AbstractManager {
- /**
- * Returns the FQCN for the target entity to operate on.
- * @return string The FQCN, e.g. de\RaumZeitLabor\PartKeepr\Part
- */
- public function getEntityName () {
- return 'de\RaumZeitLabor\PartKeepr\CronLogger\CronLogger';
- }
-
- /**
- * Returns all fields which need to appear in the getList ResultSet.
- * @return array An array of all fields which should be returned
- */
- public function getQueryFields () {
- return array("id", "title", "date");
- }
-
- /**
- * Returns the default sort field
- *
- * @return string The default sort field
- */
- public function getDefaultSortField () {
- return "date";
- }
-
- /**
- * Marks a specific cronjob as ran
- * @param string $cronjob The name of the cronjob
- */
- public function markCronRun ($cronjob) {
- $dql = "SELECT c FROM de\RaumZeitLabor\PartKeepr\CronLogger\CronLogger c WHERE c.cronjob = :cronjob";
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("cronjob", $cronjob);
-
- try {
- $result = $query->getSingleResult();
- } catch (\Exception $e) {
- $result = new CronLogger();
- $result->setCronjob($cronjob);
- PartKeepr::getEM()->persist($result);
- }
-
- $result->setLastRunDate(new \DateTime());
-
- PartKeepr::getEM()->flush();
- }
-
- /**
- * Returns a list of all inactive cronjobs
- *
- * @param none
- * @return array A string of cronjob names which aren't running
- */
- public function getInactiveCronjobs () {
- $dql = "SELECT c.cronjob FROM de\RaumZeitLabor\PartKeepr\CronLogger\CronLogger c WHERE c.cronjob = :cronjob";
- $dql .= " AND c.lastRunDate > :date";
-
- $query = PartKeepr::getEM()->createQuery($dql);
-
- $date = new \DateTime();
- $date->sub(new \DateInterval('P1D'));
- $query->setParameter("date", $date);
-
- $failedCronjobs = array();
-
- foreach (PartKeepr::getRequiredCronjobs() as $cronjob) {
- $query->setParameter("cronjob", $cronjob);
-
- try {
- $query->getSingleResult();
- } catch (\Exception $e) {
- $failedCronjobs[] = $cronjob;
- }
-
- }
-
- return $failedCronjobs;
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Distributor/Distributor.php b/src/backend/de/RaumZeitLabor/PartKeepr/Distributor/Distributor.php
@@ -1,231 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Distributor;
-
-use de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
- * Represents a distributor
- * @Entity **/
-class Distributor extends BaseEntity implements Serializable, Deserializable {
- /**
- * Holds the name of the distributor
- * @Column(type="string",unique=true)
- * @var string
- */
- private $name;
-
- /**
- * Holds the address of the distributor
- * @Column(type="text",nullable=true)
- * @var string
- */
- private $address;
-
- /**
- * Holds the URL of the distributor
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $url;
-
- /**
- * Holds the phone number of the distributor
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $phone;
-
- /**
- * Holds the fax number of the distributor
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $fax;
-
- /**
- * Holds the email of the distributor
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $email;
-
- /**
- * Holds a comment for the distributor
- * @Column(type="text",nullable=true)
- * @var string
- */
- private $comment;
-
- /**
- * Sets the name for the distributor
- *
- * @param string $name The distributor's name
- */
- public function setName ($name) {
- $this->name = $name;
- }
-
- /**
- * Returns the name of the distributor
- * @return string The distributor's name
- */
- public function getName () {
- return $this->name;
- }
-
- /**
- * Sets the address of this distributor
- *
- * @param string $address The address of the distributor
- */
- public function setAddress ($address) {
- $this->address = $address;
- }
-
- /**
- * Returns the address of this distributor
- * @return string The address of this distributor
- */
- public function getAddress () {
- return $this->address;
- }
-
- /**
- * Sets the phone number for this distributor
- *
- * @param string $phone The phone number of this distributor
- */
- public function setPhone ($phone) {
- $this->phone = $phone;
- }
-
- /**
- * Returns the phone number of this distributor
- * @return string The phone number
- */
- public function getPhone () {
- return $this->phone;
- }
-
- /**
- * Sets the fax number for this distributor
- *
- * @param string $fax The fax number
- */
- public function setFax ($fax) {
- $this->fax = $fax;
- }
-
- /**
- * Returns the fax number for this distributor
- *
- * @return string $fax The fax number
- */
- public function getFax () {
- return $this->fax;
- }
-
- /**
- * Sets the comment for this distributor
- *
- * @param string $comment The comment for this distributor
- */
- public function setComment ($comment) {
- $this->comment = $comment;
- }
-
- /**
- * Returns the comment for this distributor
- *
- * @return string The comment
- */
- public function getComment () {
- return $this->comment;
- }
-
- /**
- * Sets the email for this distributor
- *
- * @param string $email The email for this distributor
- */
- public function setEmail ($email) {
- $this->email = $email;
- }
-
- /**
- * Returns the email for this distributor
- * @return string The email
- */
- public function getEmail () {
- return $this->email;
- }
-
- /**
- * Sets the URL for this distributor
- *
- * @param string $url The URL for this distributor
- */
- public function setURL ($url) {
- $this->url = $url;
- }
-
- /**
- * Returns the URL for this distributor
- * @return string The URL
- */
- public function getURL () {
- return $this->url;
- }
-
- /**
- * Returns the distributor in serialized form.
- * @return array The serialized distributor
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "name" => $this->getName(),
- "url" => $this->getURL(),
- "address" => $this->getAddress(),
- "email" => $this->getEmail(),
- "comment" => $this->getComment(),
- "phone" => $this->getPhone(),
- "fax" => $this->getFax()
- );
- }
-
- /**
- * Deserializes the distributor
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "name":
- $this->setName($value);
- break;
- case "url":
- $this->setURL($value);
- break;
- case "comment":
- $this->setComment($value);
- break;
- case "fax":
- $this->setFax($value);
- break;
- case "phone":
- $this->setPhone($value);
- break;
- case "email":
- $this->setEmail($value);
- break;
- case "address":
- $this->setAddress($value);
- break;
- }
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Distributor/DistributorManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Distributor/DistributorManager.php
@@ -1,107 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Distributor;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\Distributor\Distributor,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Category\CategoryManager,
- de\RaumZeitLabor\PartKeepr\Distributor\Exceptions\DistributorNotFoundException;
-
-class DistributorManager extends Singleton {
- /**
- * Returns a list of distributors.
- *
- * @param int $start Start of the list, default 0
- * @param int $limit Number of users to list, default 10
- * @param string $sort The field to sort by, default "name"
- * @param string $dir The direction to sort (ASC or DESC), default ASC
- * @param string $filter A string to filter the distributor's name by, default empty
- */
- public function getDistributors ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
-
- $qb = PartKeepr::getEM()->createQueryBuilder();
- $qb->select("st.id, st.name, st.url, st.email, st.comment, st.address")->from("de\RaumZeitLabor\PartKeepr\Distributor\Distributor","st");
-
- if ($filter != "") {
- $qb = $qb->where("LOWER(st.name) LIKE :filter");
- $qb->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- if ($limit > -1) {
- $qb->setMaxResults($limit);
- $qb->setFirstResult($start);
- }
-
- $qb->orderBy("st.".$sort, $dir);
-
- $query = $qb->getQuery();
-
- $result = $query->getResult();
-
- $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
- $totalQueryBuilder->select("COUNT(st.id)")->from("de\RaumZeitLabor\PartKeepr\Distributor\Distributor","st");
-
-
-
- if ($filter != "") {
- $totalQueryBuilder = $totalQueryBuilder->where("LOWER(st.name) LIKE :filter");
- $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- $totalQuery = $totalQueryBuilder->getQuery();
-
- return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
- }
-
- /**
- * Returns a distributor by ID.
- *
- * @param int $id The distributor id
- * @return Distributor The distributor
- * @throws EntityNotFoundException If no distributor with the ID was found
- */
- public function getDistributor ($id) {
- return Distributor::loadById($id);
- }
-
- /**
- * Creates a new distributor with the given name.
- * @param string $name The name of the distributor
- * @return Distributor The new distributor object
- */
- public function addDistributor ($name) {
- $distributor = new Distributor();
- $distributor->setName($name);
-
- PartKeepr::getEM()->persist($distributor);
- PartKeepr::getEM()->flush();
-
- return $distributor;
- }
-
- /**
- * Deletes a distributor by id
- *
- * @param int $id The ID of the distributor to delete
- */
- public function deleteDistributor ($id) {
- $distributor = $this->getDistributor($id);
-
- 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/Distributor/DistributorService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Distributor/DistributorService.php
@@ -1,82 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Distributor;
-use de\RaumZeitLabor\PartKeepr\Service\RestfulService;
-
-use de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\Part\PartManager,
- de\RaumZeitLabor\PartKeepr\Stock\StockEntry,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class DistributorService extends Service implements RestfulService {
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
- */
- public function get () {
- if ($this->hasParameter("id")) {
- return array("data" => DistributorManager::getInstance()->getDistributor($this->getParameter("id"))->serialize());
- } else {
- if ($this->hasParameter("sort")) {
- $tmp = json_decode($this->getParameter("sort"), true);
-
- $aSortParams = $tmp[0];
- } else {
- $aSortParams = array(
- "property" => "name",
- "direction" => "ASC");
- }
- return DistributorManager::getInstance()->getDistributors(
- $this->getParameter("start", $this->getParameter("start", 0)),
- $this->getParameter("limit", $this->getParameter("limit", 25)),
- $this->getParameter("sortby", $aSortParams["property"]),
- $this->getParameter("dir", $aSortParams["direction"]),
- $this->getParameter("query", ""));
- }
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::create()
- */
- public function create () {
- $this->requireParameter("name");
-
- $distributor = new Distributor;
- $distributor->deserialize($this->getParameters());
-
- PartKeepr::getEM()->persist($distributor);
- PartKeepr::getEM()->flush();
-
- return array("data" => $distributor->serialize());
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update()
- */
- public function update () {
- $this->requireParameter("id");
- $this->requireParameter("name");
-
- $distributor = Distributor::loadById($this->getParameter("id"));
- $distributor->deserialize($this->getParameters());
-
- PartKeepr::getEM()->flush();
-
- return array("data" => $distributor->serialize());
-
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::destroy()
- */
- public function destroy () {
- $this->requireParameter("id");
-
- DistributorManager::getInstance()->deleteDistributor($this->getParameter("id"));
-
- return array("data" => null);
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Footprint/Footprint.php b/src/backend/de/RaumZeitLabor/PartKeepr/Footprint/Footprint.php
@@ -1,192 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Footprint;
-use de\RaumZeitLabor\PartKeepr\Util\Deserializable;
-
-use de\RaumZeitLabor\PartKeepr\Util\Serializable;
-use de\RaumZeitLabor\PartKeepr\FootprintCategory\FootprintCategory;
-use de\RaumZeitLabor\PartKeepr\Util\BaseEntity;
-
-/** @Entity */
-
-class Footprint extends BaseEntity implements Serializable, Deserializable {
- /**
- * Holds the footprint name
- * @Column(length=64,unique=true)
- * @var string
- */
- private $name;
-
- /**
- * Holds the footprint description
- * @Column(type="text",nullable=true)
- * @var string
- */
- private $description;
-
- /**
- * The category of the footprint
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\FootprintCategory\FootprintCategory")
- * @var Category
- */
- private $category;
-
- /**
- * Holds the footprint image
- * @OneToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Footprint\FootprintImage",mappedBy="footprint",cascade={"persist", "remove"})
- * @var FootprintImage
- */
- private $image;
-
- /**
- * Holds the footprint attachments
- * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment",mappedBy="footprint",cascade={"persist", "remove"})
- * @var FootprintAttachment
- */
- private $attachments;
-
- /**
- * Constructs a new Footprint entity
- */
- public function __construct () {
- $this->attachments = new \Doctrine\Common\Collections\ArrayCollection();
- }
-
- /**
- * Sets the name of this footprint
- *
- * @param string $name The footprint name
- */
- public function setName ($name) {
- $this->name = $name;
- }
-
- /**
- * Returns the name of this footprint
- * @return string The name of this footprint
- */
- public function getName () {
- return $this->name;
- }
-
- /**
- * Sets the description of this footprint
- * @param string $description The description
- */
- public function setDescription ($description) {
- $this->description = $description;
- }
-
- /**
- * Returns the description of this footprint
- * @return string The description
- */
- public function getDescription () {
- return $this->description;
- }
-
- /**
- * Sets the category for this footprint
- * @param \de\RaumZeitLabor\PartKeepr\FootprintCategory\FootprintCategory $category The category
- */
- public function setCategory (FootprintCategory $category) {
- $this->category = $category;
- }
-
- /**
- * Returns the category of this footprint
- * @return FootprintCategory The footprint category
- */
- public function getCategory () {
- return $this->category;
- }
-
- /**
- * Sets the footprint image
- * @param FootprintImage $image The footprint image
- */
- public function setImage (FootprintImage $image) {
- $this->image = $image;
- $image->setFootprint($this);
- }
-
- /**
- * Returns the footprint image
- * @return FootprintImage The footprint image
- */
- public function getImage () {
- return $this->image;
- }
-
- /**
- * Returns the attachments for this footprint
- * @return ArrayCollection The attachments
- */
- public function getAttachments () {
- return $this->attachments;
- }
-
- /**
- * Serializes the footprint
- * @return array the serialized footprint
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "name" => $this->getName(),
- "description" => $this->getDescription(),
- "image_id" => is_object($this->getImage()) ? $this->getImage()->getId() : null,
- "category" => is_object($this->getCategory()) ? $this->getCategory()->getId() : null,
- "attachments" => $this->serializeChildren($this->getAttachments())
- );
- }
-
- /**
- * Deserializes the footprint
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "name":
- $this->setName($value);
- break;
- case "description":
- $this->setDescription($value);
- break;
- case "image_id":
- if ($value == "") {
- echo "/** Breaking because of empty value */";
- break; }
-
- try {
- $image = FootprintImage::loadById($value);
- $this->setImage($image);
- } catch (\Exception $e) {
- if ($this->getImage()) {
- // Image was not found, maybe a temporary image?
- $this->getImage()->replaceFromTemporaryFile($value);
- } else {
- $image = FootprintImage::createFromTemporaryFile($value);
- $this->setImage($image);
- }
- }
-
- break;
- case "category":
- try {
- $category = FootprintCategory::loadById($value);
- $this->setCategory($category);
- } catch (\Exception $e) {
- // Category was not found, do not change category.
- }
- break;
- case "attachments":
- $this->deserializeChildren($value, $this->getAttachments(), "de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment");
- foreach ($this->getAttachments() as $attachment) {
- $attachment->setFootprint($this);
- }
- break;
- }
- }
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Footprint/FootprintAttachment.php b/src/backend/de/RaumZeitLabor/PartKeepr/Footprint/FootprintAttachment.php
@@ -1,101 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Footprint;
-
-use de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\UploadedFile\UploadedFile;
-
-/**
- * Holds a footprint attachment
- * @Entity
- **/
-class FootprintAttachment extends UploadedFile implements Serializable, Deserializable {
- /**
- * The description of this attachment
- * @Column(type="text")
- * @var string
- */
- private $description;
-
- /**
- * Creates a new footprint attachment
- */
- public function __construct () {
- parent::__construct();
- $this->setType("FootprintAttachment");
- }
- /**
- * The footprint object
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Footprint\Footprint")
- * @var Footprint
- */
- private $footprint = null;
-
- /**
- * Sets the footprint
- * @param Footprint $footprint The footprint to set
- */
- public function setFootprint (Footprint $footprint) {
- $this->footprint = $footprint;
- }
-
- /**
- * Returns the footprint
- * @return Footprint the footprint
- */
- public function getFootprint () {
- return $this->footprint;
- }
-
- /**
- * Sets the description for this attachment
- * @param string $description The attachment description
- */
- public function setDescription ($description) {
- $this->description = $description;
- }
-
- /**
- * Returns the description for this attachment
- * @return string The description
- */
- public function getDescription () {
- return $this->description;
- }
-
- /**
- *
- * Serializes this footprint attachment
- * @return array The serialized footprint attachment
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "footprint_id" => $this->getFootprint()->getId(),
- "originalFilename" => $this->getOriginalFilename(),
- "mimetype" => $this->getMimetype(),
- "extension" => $this->getExtension(),
- "size" => $this->getSize(),
- "description" => $this->getDescription());
- }
-
- /**
- * Deserializes the footprint attachment
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- if (array_key_exists("id", $parameters)) {
- if (substr($parameters["id"], 0, 4) === "TMP:") {
- $this->replaceFromTemporaryFile($parameters["id"]);
- }
- }
-
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "description":
- $this->setDescription($value);
- break;
- }
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Footprint/FootprintImage.php b/src/backend/de/RaumZeitLabor/PartKeepr/Footprint/FootprintImage.php
@@ -1,50 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Footprint;
-
-use de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Image\Image;
-
-/**
- * Holds a footprint image
- * @Entity
- **/
-class FootprintImage extends Image implements Serializable {
- /**
- * The footprint object
- * @OneToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Footprint\Footprint",inversedBy="image")
- * @var Footprint
- */
- private $footprint = null;
-
- /**
- * Creates a new IC logo instance
- */
- public function __construct () {
- parent::__construct(Image::IMAGE_FOOTPRINT);
- }
-
- /**
- * Sets the footprint
- * @param Footprint $footprint The footprint to set
- */
- public function setFootprint (Footprint $footprint) {
- $this->footprint = $footprint;
- }
-
- /**
- * Returns the footprint
- * @return Footprint the footprint
- */
- public function getFootprint () {
- return $this->footprint;
- }
-
- /**
- *
- * Serializes this ic logo
- * @return array The serialized ic logo
- */
- public function serialize () {
- return array("id" => $this->getId(), "footprint_id" => $this->getFootprint()->getId());
- }
-}-
\ 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
@@ -1,158 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Footprint;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\Util\SerializableException,
- de\RaumZeitLabor\PartKeepr\Footprint\Footprint,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Util\Exceptions\EntityNotFoundException;
-
-class FootprintManager extends Singleton {
- /**
- * Returns a list of footprints.
- *
- * @param int $start Start of the list, default 0
- * @param int $limit Number of users to list, default 10
- * @param string $sort The field to sort by, default "name"
- * @param string $dir The direction to sort (ASC or DESC), default ASC
- * @param string $filter A string to filter the footprint's name by, default empty
- */
- public function getFootprints ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
-
- $qb = PartKeepr::getEM()->createQueryBuilder();
- $qb->select("f.id, f.name, f.description, im.id AS image_id, ca.id AS category")->from("de\RaumZeitLabor\PartKeepr\Footprint\Footprint","f")
- ->leftJoin("f.image", "im")
- ->leftJoin("f.category", "ca");
-
- if ($filter != "") {
- $qb = $qb->where("LOWER(f.name) LIKE :filter");
- $qb->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- if ($limit > -1) {
- $qb->setMaxResults($limit);
- $qb->setFirstResult($start);
- }
-
- $qb->orderBy("f.".$sort, $dir);
-
- $query = $qb->getQuery();
-
- $result = $query->getResult();
-
- $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
- $totalQueryBuilder->select("COUNT(f.id)")->from("de\RaumZeitLabor\PartKeepr\Footprint\Footprint","f")->leftJoin("f.image", "im");
-
-
-
- if ($filter != "") {
- $totalQueryBuilder = $totalQueryBuilder->where("LOWER(f.name) LIKE :filter");
- $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- $totalQuery = $totalQueryBuilder->getQuery();
-
- return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
- }
-
- /**
- * Creates a new footprint
- *
- * @param string $footprint The footprint's name
- * @throws \de\RaumZeitLabor\PartKeepr\Util\SerializableException
- * @throws PDOException
- */
- public function addFootprint ($name) {
- $fp = new Footprint();
- $fp->setName($name);
-
- // @todo Port the UniqueEntityValidator from Symfony2 to here.
- try {
- PartKeepr::getEM()->persist($fp);
- PartKeepr::getEM()->flush();
- } catch (\PDOException $e) {
- if ($e->getCode() == "23000") {
- $exception = new SerializableException(sprintf(PartKeepr::i18n("Footprint %s already exists!"), $name));
- $exception->setDetail(sprintf(PartKeepr::i18n("You tried to add the footprint %s, but a footprint with the same name already exists."), $name));
-
- throw $exception;
- } else {
- throw $e;
- }
- }
-
- return $fp;
- }
-
- /**
- * Deletes the footprint with the given id.
- *
- * @param int $id The footprint id to delete
- * @throws \de\RaumZeitLabor\PartKeepr\Util\SerializableException
- */
- public function deleteFootprint ($id) {
- $footprint = Footprint::loadById($id);
-
- try {
- PartKeepr::getEM()->remove($footprint);
- PartKeepr::getEM()->flush();
- } catch (\PDOException $e) {
- if ($e->getCode() == "23000") {
- $exception = new SerializableException(sprintf(PartKeepr::i18n("Footprint %s is in use by some parts!"), $footprint->getName()));
- $exception->setDetail(sprintf(PartKeepr::i18n("You tried to delete the footprint %s, but there are parts which use this footprint."), $footprint->getName()));
-
- throw $exception;
- }
- }
- }
-
- /**
- * Loads a footprint by id
- * @param int $id The footprint id
- */
- public function getFootprint ($id) {
- return Footprint::loadById($id);
- }
-
- /**
- * Finds or creates a footprint by name.
- *
- * @param mixed $footprint Either the ID or the footprint's name to find
- */
- public function getOrCreateFootprint ($footprint) {
- try {
- $footprint = Footprint::loadById($footprint);
- return $footprint;
- } catch (EntityNotFoundException $e) {}
-
- $dql = "SELECT f FROM de\RaumZeitLabor\PartKeepr\Footprint\Footprint f WHERE f.name = :name";
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("name", $footprint);
-
- try {
- $footprint = $query->getSingleResult();
- return $footprint;
- } catch (\Exception $e) {}
-
- $fp = new Footprint();
- $fp->setName($footprint);
-
- PartKeepr::getEM()->persist($fp);
-
- 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/Footprint/FootprintService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Footprint/FootprintService.php
@@ -1,96 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Footprint;
-
-use de\RaumZeitLabor\PartKeepr\TempImage\TempImage,
- de\RaumZeitLabor\PartKeepr\FootprintCategory\FootprintCategory,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Footprint\FootprintManager;
-
-class FootprintService extends Service implements RestfulService {
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
- */
- public function get () {
- if ($this->hasParameter("id")) {
- return array("data" => FootprintManager::getInstance()->getFootprint($this->getParameter("id"))->serialize());
- } else {
- if ($this->hasParameter("sort")) {
- $tmp = json_decode($this->getParameter("sort"), true);
-
- $aSortParams = $tmp[0];
- } else {
- $aSortParams = array(
- "property" => "name",
- "direction" => "ASC");
- }
- return FootprintManager::getInstance()->getFootprints(
- $this->getParameter("start", $this->getParameter("start", 0)),
- $this->getParameter("limit", $this->getParameter("limit", 25)),
- $this->getParameter("sortby", $aSortParams["property"]),
- $this->getParameter("dir", $aSortParams["direction"]),
- $this->getParameter("query", ""));
- }
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::create()
- */
- public function create () {
- $this->requireParameter("name");
-
- $footprint = new Footprint();
- $footprint->deserialize($this->getParameters());
-
- PartKeepr::getEM()->persist($footprint);
-
- PartKeepr::getEM()->flush();
-
- return array("data" => $footprint->serialize());
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update()
- */
- public function update () {
- $this->requireParameter("id");
- $this->requireParameter("name");
- $footprint = Footprint::loadById($this->getParameter("id"));
-
- $footprint->deserialize($this->getParameters());
-
- PartKeepr::getEM()->flush();
-
- return array("data" => $footprint->serialize());
-
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::destroy()
- */
- public function destroy () {
- $this->requireParameter("id");
-
- FootprintManager::getInstance()->deleteFootprint($this->getParameter("id"));
-
- return array("data" => null);
- }
-
- public function moveFootprint () {
- $this->requireParameter("targetCategory");
- $this->requireParameter("id");
-
- $footprint = Footprint::loadById($this->getParameter("id"));
- $category = FootprintCategory::loadById($this->getParameter("targetCategory"));
-
- $footprint->setCategory($category);
-
- PartKeepr::getEM()->flush();
- }
-
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/FootprintAttachment/FootprintAttachmentManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/FootprintAttachment/FootprintAttachmentManager.php
@@ -1,68 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\FootprintAttachment;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\Footprint\Footprint,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class FootprintAttachmentManager extends Singleton {
- /**
- * Returns a list of footprint attachments
- *
- * @param int $start Start of the list, default 0
- * @param int $limit Number of users to list, default 10
- * @param string $sort The field to sort by, default "name"
- * @param string $dir The direction to sort (ASC or DESC), default ASC
- * @param string $filter The footprint id
- */
- public function getFootprintAttachments ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
-
- $qb = PartKeepr::getEM()->createQueryBuilder();
- $qb->select("st")->from("de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment","st")
- ->leftJoin('st.footprint', "fp");
-
- if ($filter != "") {
- $footprint = Footprint::loadById($filter);
- $qb = $qb->where("st.footprint = :footprint");
- $qb->setParameter("footprint", $footprint);
- }
-
- if ($limit > -1) {
- $qb->setMaxResults($limit);
- $qb->setFirstResult($start);
- }
-
- $qb->orderBy("st.".$sort, $dir);
-
- $query = $qb->getQuery();
-
- $result = $query->getResult();
-
- $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
- $totalQueryBuilder->select("COUNT(st.id)")->from("de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment","st");
-
-
-
- if ($filter != "") {
- $totalQueryBuilder = $totalQueryBuilder->where("st.footprint = :footprint");
- $totalQueryBuilder->setParameter("footprint", $footprint);
- }
-
- $totalQuery = $totalQueryBuilder->getQuery();
-
- $aData = array();
- foreach ($result as $item) {
- $aData[] = $item->serialize();
- }
- return array("data" => $aData, "totalCount" => $totalQuery->getSingleScalarResult());
- }
-
- /**
- * Returns a footprint attachment by id
- * @param int $id The footprint attachment id
- */
- public function getFootprintAttachment ($id) {
- return FootprintAttachment::loadById($id);
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/FootprintAttachment/FootprintAttachmentService.php b/src/backend/de/RaumZeitLabor/PartKeepr/FootprintAttachment/FootprintAttachmentService.php
@@ -1,102 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\FootprintAttachment;
-
-use de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment,
- de\RaumZeitLabor\PartKeepr\UploadedFile\TempUploadedFile,
- de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Footprint\Footprint,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class FootprintAttachmentService extends Service implements RestfulService {
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
- */
- public function get () {
- if ($this->hasParameter("id")) {
- return FootprintAttachmentManager::getInstance()->getFootprintAttachment($this->getParameter("id"))->serialize();
- } else {
- if ($this->hasParameter("sort")) {
- $tmp = json_decode($this->getParameter("sort"), true);
-
- $aSortParams = $tmp[0];
- } else {
- $aSortParams = array(
- "property" => "id",
- "direction" => "ASC");
- }
-
- $filter = "";
-
- if ($this->hasParameter("filter")) {
- $tmp = json_decode($this->getParameter("filter"), true);
-
- foreach ($tmp as $item) {
- if (array_key_exists("property", $item)) {
- if ($item["property"] == "footprint_id") {
- if (array_key_exists("value", $item)) {
- $filter = $item["value"];
- }
- }
- }
- }
- }
- return FootprintAttachmentManager::getInstance()->getFootprintAttachments(
- $this->getParameter("start", $this->getParameter("start", 0)),
- $this->getParameter("limit", $this->getParameter("limit", 25)),
- $this->getParameter("sortby", $aSortParams["property"]),
- $this->getParameter("dir", $aSortParams["direction"]),
- $filter);
- }
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::create()
- */
- public function create () {
- $this->requireParameter("tmp_id");
- $this->requireParameter("footprint_id");
-
- $tmpImage = TempUploadedFile::loadById($this->getParameter("tmp_id"));
-
- $file = new FootprintAttachment();
-
- $footprint = Footprint::loadById($this->getParameter("footprint_id"));
-
- $file->setFootprint($footprint);
- $file->replace($tmpImage->getFilename());
- $file->setOriginalFilename($tmpImage->getOriginalFilename());
- $file->setDescription($this->getParameter("description"));
- PartKeepr::getEM()->persist($file);
- PartKeepr::getEM()->flush();
-
- return $file->serialize();
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update()
- */
- public function update () {
-
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::destroy()
- */
- public function destroy () {
- $this->requireParameter("id");
-
- $file = FootprintAttachment::loadById($this->getParameter("id"));
-
- PartKeepr::getEM()->remove($file);
- PartKeepr::getEM()->flush();
-
- return array("data" => null);
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/FootprintCategory/FootprintCategory.php b/src/backend/de/RaumZeitLabor/PartKeepr/FootprintCategory/FootprintCategory.php
@@ -1,14 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\FootprintCategory;
-
-use de\RaumZeitLabor\PartKeepr\Category\AbstractCategory;
-
-/**
- * @Entity
- * @Table(indexes={@index(columns={"lft"}),@index(columns={"rgt"})})
- * The entity for our footprint categories
- *
- */
-class FootprintCategory extends AbstractCategory {
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/FootprintCategory/FootprintCategoryManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/FootprintCategory/FootprintCategoryManager.php
@@ -1,42 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\FootprintCategory;
-
-use de\RaumZeitLabor\PartKeepr\Category\AbstractCategoryManager;
-use DoctrineExtensions\NestedSet\NodeWrapper;
-use de\RaumZeitLabor\PartKeepr\Util\SerializableException;
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class FootprintCategoryManager extends AbstractCategoryManager {
- protected $categoryClass = "de\RaumZeitLabor\PartKeepr\FootprintCategory\FootprintCategory";
-
- /**
- * Deletes the given category ID.
- * @param $id int The category id to delete
- * @throws CategoryNotFoundException If the category wasn't found
- */
- public function deleteCategory ($id) {
- $category = $this->getCategory($id);
-
- try {
-
- if ($category->hasChildren()) {
- $exception = new SerializableException(sprintf(PartKeepr::i18n("Category '%s' contains other categories."), $category->getNode()->getName()));
- $exception->setDetail(sprintf(PartKeepr::i18n("You tried to delete the category '%s', but it still contains other categories. Please move the categories or delete them first."), $category->getNode()->getName()));
-
- throw $exception;
- }
-
- parent::deleteCategory($id);
- } catch (\PDOException $e) {
- if ($e->getCode() == "23000") {
- $exception = new SerializableException(sprintf(PartKeepr::i18n("Category '%s' contains footprints."), $category->getNode()->getName()));
- $exception->setDetail(sprintf(PartKeepr::i18n("You tried to delete the category '%s', but it still contains footprints. Please move the footprints to another category."), $category->getNode()->getName()));
-
- throw $exception;
- } else {
- throw $e;
- }
- }
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/FootprintCategory/FootprintCategoryService.php b/src/backend/de/RaumZeitLabor/PartKeepr/FootprintCategory/FootprintCategoryService.php
@@ -1,9 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\FootprintCategory;
-
-use de\RaumZeitLabor\PartKeepr\Category\AbstractCategoryService;
-
-class FootprintCategoryService extends AbstractCategoryService {
- protected $categoryManagerClass = "de\RaumZeitLabor\PartKeepr\FootprintCategory\FootprintCategoryManager";
- protected $categoryClass = "de\RaumZeitLabor\PartKeepr\FootprintCategory\FootprintCategory";
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/FulltextSearch/FulltextSearch.php b/src/backend/de/RaumZeitLabor/PartKeepr/FulltextSearch/FulltextSearch.php
@@ -1,94 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\FulltextSearch;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-abstract class FulltextSearch {
-
- /**
- * Creates a new fulltext search based on the given query.
- *
- * The query can contain different query strings, separated by space. The query returns only results which contain
- * all query strings in any fields.
- *
- * If the query is "100 ohm", it would only consider entities which have both "100" and "ohm", no matter which field
- * the value is in.
- *
- * @param string $query The query to search for
- */
- public function __construct ($query) {
- $this->query = explode(" ", $query);
- }
-
- /**
- * Fires the query and returns the results.
- *
- * @param none
- * @return array An array with all IDs which match the query
- */
- public function query () {
- return $this->fallbackSearch();
- }
-
- /**
- * A fallback search in case no fulltext search engine is available. This directly queries the database, which is
- * slow.
- */
- protected function fallbackSearch () {
- $qb = PartKeepr::getEM()->createQueryBuilder();
-
- $qb ->select("q.id")
- ->from($this->getEntityName(), "q")
- ->where("1=1");
-
- $dqlChunks = array();
-
- foreach ($this->query as $id => $queryString) {
- $partDqlChunks = array();
- foreach ($this->getFields() as $field) {
- $partDqlChunks[] = "LOWER(q." . $field.") LIKE :filter".$id;
- }
-
- $dqlChunks[] = "(".implode(" OR ", $partDqlChunks).")";
-
- $qb->setParameter("filter".$id, "%".str_replace("%", "\\%", strtolower($queryString))."%");
- }
-
- $qb->andWhere(implode(" AND " ,$dqlChunks));
-
- $query = $qb->getQuery();
-
-
-
- $result = $query->getArrayResult();
-
- if (count($result) > 0) {
- $results = array();
-
- foreach ($result as $value) {
- $results[] = $value["id"];
- }
-
- return $results;
- } else {
- return array(0);
- }
- }
-
- /**
- * Returns the FQDN name of the entity. This needs to be overridden in child classes.
- *
- * @param none
- * @return string the FQDN of the entity to query, e.g. de\RaumZeitLabor\PartKeepr\Part\Part
- */
- abstract protected function getEntityName ();
-
- /**
- * Returns the fields in which the fulltext search should search in.
- *
- * @param none
- * @return array An array of field names, e.g. array("name", "description")
- */
- abstract protected function getFields ();
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Image/CachedImage.php b/src/backend/de/RaumZeitLabor/PartKeepr/Image/CachedImage.php
@@ -1,99 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Image;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
- * Represtends a cached image. Cached images are used for scale/resize
- * operations, so that the resize/scale operation doesn't need to be done
- * every time a scaled/resized image is requested.
- *
- * @Entity
- */
-class CachedImage {
- /**
- * Specifies the ID of the cached image.
- *
- * @var integer
- * @Id
- * @Column(type="integer")
- * @GeneratedValue(strategy="AUTO")
- **/
- private $id;
-
- /**
- * Specifies the ID of the original image
- *
- * @var integer
- * @Column(type="integer")
- */
- private $originalId;
-
- /**
- * Specifies the type of the original image.
- *
- * @var string
- * @Column(type="string")
- **/
- private $originalType;
-
- /**
- * The cache filename of the image
- *
- * @var string
- * @Column(type="string")
- */
- private $cacheFile;
-
- /**
- * Creates a new cache entry for a specific image.
- *
- * @param Image $image The image to cache
- * @param string $cacheFile The file which holds the cached image
- */
- public function __construct (Image $image, $cacheFile) {
- $this->originalId = (int)$image->getId();
- $this->originalType = $image->getType();
- $this->cacheFile = $cacheFile;
- }
-
- /**
- * Returns the cache file
- * @return string The cache file including path
- */
- public function getCacheFile () {
- return $this->cacheFile;
- }
-
- /**
- * Removes all caches for a specific image. This is usually called
- * when a new version of an image is uploaded.
- *
- * Automatically calls "flush" on the entity manager.
- *
- * @param Image $image The image to invalidate
- */
- public static function invalidate (Image $image) {
- $qb = PartKeepr::getEM()->createQueryBuilder();
- $qb->select(array("c"))
- ->from('de\RaumZeitLabor\PartKeepr\Image\CachedImage', 'c')
- ->where("c.originalId = :id")
- ->andWhere("c.originalType = :type")
- ->setParameter("id", $image->getId())
- ->setParameter("type", $image->getType());
-
- $query = $qb->getQuery();
-
- $bImagesRemoved = false;
-
- foreach ($query->getResult() as $file) {
- unlink($file->getCacheFile());
- PartKeepr::getEM()->remove($file);
- $bImagesRemoved = true;
- }
-
- if ($bImagesRemoved) {
- PartKeepr::getEM()->flush();
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Image/Exceptions/InvalidImageTypeException.php b/src/backend/de/RaumZeitLabor/PartKeepr/Image/Exceptions/InvalidImageTypeException.php
@@ -1,11 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Image\Exceptions;
-
-/**
- * Thrown if an invalid type was passed
- */
-class InvalidImageTypeException extends \Exception {
- public function __construct ($type) {
- parent::__construct("The image type $type is unknown.");
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Image/Image.php b/src/backend/de/RaumZeitLabor/PartKeepr/Image/Image.php
@@ -1,254 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Image;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\UploadedFile\UploadedFile,
- de\RaumZeitLabor\PartKeepr\Util\Configuration,
- de\RaumZeitLabor\PartKeepr\TempImage\TempImage,
- de\RaumZeitLabor\PartKeepr\Image\Exceptions\InvalidImageTypeException;
-
-/**
- * @MappedSuperclass
- */
-abstract class Image extends UploadedFile {
- const IMAGE_ICLOGO = "iclogo";
- const IMAGE_TEMP = "temp";
- const IMAGE_PART = "part";
- const IMAGE_STORAGELOCATION = "storagelocation";
- const IMAGE_FOOTPRINT = "footprint";
-
- /**
- * Constructs a new image object.
- *
- * @param string $type The type for the image, one of the IMAGE_ constants.
- */
- public function __construct ($type) {
- parent::__construct();
- $this->setType($type);
- }
-
- /**
- * Sets the type of the image. Once the type is set,
- * it may not be changed later.
- *
- * @param string $type The type for the image, one of the IMAGE_ constants.
- * @throws InvalidImageTypeException
- */
- protected function setType ($type) {
- switch ($type) {
- case Image::IMAGE_ICLOGO:
- case Image::IMAGE_TEMP:
- case Image::IMAGE_PART:
- case Image::IMAGE_FOOTPRINT:
- case Image::IMAGE_STORAGELOCATION:
- parent::setType($type);
- break;
- default:
- throw new InvalidImageTypeException($type);
- }
- }
-
- /**
- * Replaces the current image with a new image.
- *
- * Automatically converts from one format to PNG,
- * which is the default when dealing with images
- * on the platform.
- *
- * @param string $path The path to the original image
- */
- public function replace ($path) {
- parent::replace($path);
-
- CachedImage::invalidate($this);
- }
-
- /**
- * Returns the full image filename including path.
- * This is the image where all scale operations take place on.
- *
- * @param none
- * @return string The full image filename including path.
- */
- public function getFilename () {
- return $this->getFilePath().$this->getPlainFilename().".png";
- }
-
- /**
- * Returns the path to the image. May be overridden by
- * subclasses.
- *
- * @param none
- * @return string The path to the image
- */
- public function getFilePath () {
- return Configuration::getOption(
- "partkeepr.images.path",
- PartKeepr::getRootDirectory() . "/data/images/") . $this->getType() . "/";
- }
-
- /**
- * Scales the image to a specific width and height
- *
- * @param int $w The width
- * @param int $h The height
- * @return string The path to the scaled file
- */
- public function scaleTo ($w, $h) {
- $this->ensureCachedirExists();
-
- $outputFile = Configuration::getOption("partkeepr.images.cache").md5($this->getFilename().$w."x".$h).".png";
-
- if (file_exists($outputFile)) {
- return $outputFile;
- }
- $image = new \Imagick();
- $image->readImage($this->getFilename());
- $image->adaptiveResizeImage($w, $h);
- $image->writeImage($outputFile);
-
- $cachedImage = new CachedImage($this, $outputFile);
- PartKeepr::getEM()->persist($cachedImage);
-
- return $outputFile;
- }
-
- /**
- * Scales the image to fit exactly within the given size.
- *
- * This method ensures that no blank space is in the output image,
- * and that the output image is exactly the width and height specified.
- *
- * @param int $w The width
- * @param int $h The height
- * @return string The path to the scaled file
- */
- public function fitWithinExact ($w, $h) {
- $this->ensureCachedirExists();
-
- $outputFile = Configuration::getOption("partkeepr.images.cache").md5($this->getFilename().$w."x".$h."fwe").".png";
-
- if (file_exists($outputFile)) {
- return $outputFile;
- }
- $image = new \Imagick();
- $image->readImage($this->getFilename());
-
- $sourceAspectRatio = $image->getImageWidth() / $image->getImageHeight();
- $targetAspectRatio = $w / $h;
-
- $filter = \Imagick::FILTER_UNDEFINED;
- $blur = 1;
-
- if ($sourceAspectRatio < $targetAspectRatio) {
- $image->resizeImage($w, $w / $sourceAspectRatio, $filter, $blur);
- } else {
- $image->resizeImage($h * $sourceAspectRatio, $h, $filter, $blur);
- }
-
- $offsetX = intval(($image->getImageWidth() - $w)/2);
- $offsetY = intval(($image->getImageHeight() - $h)/2);
-
- $image = $image->getImageRegion($w, $h, $offsetX, $offsetY);
-
- $image->writeImage($outputFile);
-
- $cachedImage = new CachedImage($this, $outputFile);
- PartKeepr::getEM()->persist($cachedImage);
-
- return $outputFile;
- }
-
- /**
- * Scales the image to fit within the given size.
- *
- * @param int $w The width
- * @param int $h The height
- * @param boolean $padding If true, pad the output image to the given size (transparent background).
- * @return string The path to the scaled file
- */
- public function fitWithin ($w, $h, $padding = false) {
- $this->ensureCachedirExists();
-
- if ($padding) {
- $pd = "p";
- } else {
- $pd = "";
- }
-
- $outputFile = Configuration::getOption("partkeepr.images.cache").md5($this->getFilename().$w."x".$h."fw".$pd).".png";
-
- if (file_exists($outputFile)) {
- return $outputFile;
- }
- $image = new \Imagick();
- $image->readImage($this->getFilename());
-
- $sourceAspectRatio = $image->getImageWidth() / $image->getImageHeight();
- $targetAspectRatio = $w / $h;
-
- $filter = \Imagick::FILTER_UNDEFINED;
- $blur = 1;
-
- $targetHeight = $h;
- $targetWidth = $w;
-
- if ($sourceAspectRatio < $targetAspectRatio) {
- $targetWidth = $h * $sourceAspectRatio;
- $image->resizeImage($h * $sourceAspectRatio, $h, $filter, $blur);
- } else {
- $targetHeight = $w / $sourceAspectRatio;
- $image->resizeImage($w, $w / $sourceAspectRatio, $filter, $blur);
- }
-
- if ($padding) {
- $posX = intval(($w - $targetWidth) / 2);
- $posY = intval(($h - $targetHeight) / 2);
-
- $image->extentImage($w, $h,-$posX, -$posY);
- }
-
- $image->writeImage($outputFile);
-
- $cachedImage = new CachedImage($this, $outputFile);
- PartKeepr::getEM()->persist($cachedImage);
-
- return $outputFile;
- }
-
- /**
- * Convinience method for fitWithin. Automatically pads the image.
- *
- * @param int $w The width
- * @param int $h The height
- * @return string The path to the scaled file
- */
- public function fitWithinPadding ($w, $h) {
- return $this->fitWithin($w, $h, true);
- }
-
- /**
- * Ensures that the image cache dir exists.
- */
- public function ensureCachedirExists () {
- if (!is_dir(Configuration::getOption("partkeepr.images.cache"))) {
- mkdir(Configuration::getOption("partkeepr.images.cache"), 0777, true);
- }
- }
-
- /**
- * Replaces the file with a given temporary file.
- * @param string $id The temporary id (prefixed with TMP:)
- */
- public function replaceFromTemporaryFile ($id) {
- if (substr($id, 0, 4) === "TMP:") {
- $tmpFileId = str_replace("TMP:", "", $id);
- $tmpFile = TempImage::loadById($tmpFileId);
-
- $this->replace($tmpFile->getFilename());
- $this->setOriginalFilename($tmpFile->getOriginalFilename());
-
- }
- }
-
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Logger/Logger.php b/src/backend/de/RaumZeitLabor/PartKeepr/Logger/Logger.php
@@ -1,121 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Logger;
-
-/**
- * This class implements a simple logging mechanism.
- *
- * Might be replaced with some more advanced logging framework, but it serves its purpose for now.
- */
-use de\RaumZeitLabor\PartKeepr\Util\Configuration;
-
-class Logger {
- /**
- * Loglevel "debug"
- *
- * You want to use this loglevel for debugging messages.
- * @var string
- */
- const LOGLEVEL_DEBUG = "debug";
-
- /**
- * Loglevel "info"
- *
- * You want to use this loglevel for informational messages where the program flow can continue normally and no
- * impacts occur.
- *
- * @var string
- */
- const LOGLEVEL_INFO = "info";
-
- /**
- * Loglevel "warning"
- *
- * You want to use this loglevel for messages where program flow can continue normally, but a minor
- * impact can occur.
- *
- * @var string
- */
- const LOGLEVEL_WARNING = "warning";
-
- /**
- * Loglevel "error"
- *
- * You want to use this loglevel for messages where program flow could be interrupted and major impacts occur.
- *
- * @var string
- */
- const LOGLEVEL_ERROR = "error";
-
- /**
- * Loglevel "critical"
- *
- * You want to use this loglevel for messages where program flow could be interrupted and major impacts occur.
- *
- * @var string
- */
- const LOGLEVEL_CRITICAL = "critical";
-
- /**
- * Logs a message.
- *
- * @param string $message The message to log
- * @param string $severity One of the Logger::LOGLEVEL_* constants
- */
- public static function log ($message, $severity = Logger::LOGLEVEL_INFO) {
- if (Configuration::getOption("partkeepr.logger.enable", false) === false) {
- // No logging wanted
- return;
- }
-
- $logFormat = "[%-19s] [%-8s] %s";
-
- $outputFile = Configuration::getOption("partkeepr.logger.outputfile", sys_get_temp_dir() . "/partkeepr.log");
- $fp = fopen($outputFile, "a");
-
- $date = date("Y-m-d H:i:s");
-
- fputs($fp, sprintf($logFormat, $date, $severity, $message)."\n");
-
- fclose($fp);
- }
-
- /**
- * Logs a message with the Logger::LOGLEVEL_DEBUG severity.
- * @param string $message
- */
- public static function logDebug ($message) {
- self::log($message, Logger::LOGLEVEL_DEBUG);
- }
-
- /**
- * Logs a message with the Logger::LOGLEVEL_INFO severity.
- * @param string $message
- */
- public static function logInfo ($message) {
- self::log($message, Logger::LOGLEVEL_INFO);
- }
-
- /**
- * Logs a message with the Logger::LOGLEVEL_WARNING severity.
- * @param string $message
- */
- public static function logWarning ($message) {
- self::log($message, Logger::LOGLEVEL_WARNING);
- }
-
- /**
- * Logs a message with the Logger::LOGLEVEL_ERROR severity.
- * @param string $message
- */
- public static function logError ($message) {
- self::log($message, Logger::LOGLEVEL_ERROR);
- }
-
- /**
- * Logs a message with the Logger::LOGLEVEL_CRITICAL severity.
- * @param string $message
- */
- public static function logCritical ($message) {
- self::log($message, Logger::LOGLEVEL_CRITICAL);
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Manager/AbstractManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Manager/AbstractManager.php
@@ -1,230 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Manager;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- Doctrine\ORM\QueryBuilder,
- Doctrine\ORM\Query,
- de\RaumZeitLabor\PartKeepr\Manager\Exceptions\EntityInUseException;
-
-/**
- * The AbstractManager is a very basic helper which
- * implements the mostly used operations on entities:
- *
- * - Create
- * - Delete
- * - List
- *
- */
-abstract class AbstractManager extends Singleton {
- /**
- * Returns the FQCN for the target entity to operate on.
- *
- * Needs to be implemented by the parent class.
- *
- * @return string The FQCN, e.g. de\RaumZeitLabor\PartKeepr\Part
- */
- abstract public function getEntityName ();
-
- /**
- * Returns all fields which need to appear in the getList ResultSet.
- *
- * This should include all fields required by the frontend.
- *
- * @return array An array of all fields which should be returned
- */
- abstract public function getQueryFields ();
-
- /**
- * Returns the default sort field
- *
- * @return string The default sort field
- */
- abstract public function getDefaultSortField ();
-
- /**
- * Loads an entity by id
- *
- * @param int $id The entity id
- */
- public function getEntity ($id) {
- return call_user_func($this->getEntityName()."::loadById", $id);
- }
-
- /**
- * Removes a specific entity from the system
- * @param int $id
- * @throws EntityInUseException Is thrown when the entity is in use
- */
- public function deleteEntity ($id) {
- $entity = $this->getEntity($id);
-
- try {
- PartKeepr::getEM()->remove($entity);
- PartKeepr::getEM()->flush();
- } catch (\PDOException $e) {
- if ($e->getCode() == "23000") {
- throw new EntityInUseException($entity);
- }
- }
- }
-
- /**
- * Creates a new entity from an array of parameters
- * @param array $parameters An array which gets passed to the deserialize method
- */
- public function createEntity ($parameters) {
- $class = $this->getEntityName();
- $entity = new $class;
- $entity->deserialize($parameters);
-
- PartKeepr::getEM()->persist($entity);
- PartKeepr::getEM()->flush();
-
- return $entity;
- }
-
- /**
- * Returns a list of entities.
- *
- * @param ManagerFilter $filter The filter settings for this query
- */
- public function getList (ManagerFilter $filter) {
- $qb = PartKeepr::getEM()->createQueryBuilder();
-
- $qb->select("COUNT(q.id)")->from($this->getEntityName(),"q");
-
- $this->applyFiltering($qb, $filter);
- $this->applyCustomQuery($qb, $filter);
-
- $totalQuery = $qb->getQuery();
-
- $this->applyResultFields($qb, $filter);
- $this->applyPagination($qb, $filter);
- $this->applySorting($qb, $filter);
-
- $query = $qb->getQuery();
-
- return array("data" => $this->getResult($query), "totalCount" => $totalQuery->getSingleScalarResult());
- }
-
- /**
- * Processes the result after it was retrieved. In the default configuration, it returns an array result, or
- * if no query fields are specified, it tries to serialize all objects.
- */
- protected function getResult (Query $query) {
- if (count($this->getQueryFields()) == 0) {
- $aSerializedResult = array();
- foreach ($query->getResult() as $result) {
- $aSerializedResult[] = $result->serialize();
- }
-
- return $aSerializedResult;
- } else {
- return $query->getArrayResult();
- }
- }
-
- /**
- * Applies the result fields to the query.
- *
- * The result fields can be prefixed with the table alias or not; if not prefixed, it is assumed that we'll be
- * using the specified entity FQCN.
- *
- * Note that the base name will be always "q", so avoid "q" as alias for joined tables.
- *
- * @param QueryBuilder $qb The query builder
- * @param ManagerFilter $filter The query filter
- */
- protected function applyResultFields (QueryBuilder $qb, ManagerFilter $filter) {
- if (count($this->getQueryFields()) == 0) {
- $qb->select("q");
- } else {
- // Prepend a prefix to each field
- $aQueryFields = array();
- foreach ($this->getQueryFields() as $field) {
-
- if (strpos($field, ".") === false) {
- // The field is not prefixed, prepend the q. prefix
- $aQueryFields[] = "q.".$field;
- } else {
- // Use as-is
- $aQueryFields[] = $field;
- }
- }
-
- $qb->select($aQueryFields);
- }
- }
-
- /**
- * Applies filtering to the query and calls back the custom filtering function, if required.
- *
- * @param QueryBuilder $qb The query builder
- * @param ManagerFilter $filter The query filter
- */
- protected function applyFiltering (QueryBuilder $qb, ManagerFilter $filter) {
- if ($filter->getFilter() !== null && $filter->getFilterField() !== null) {
- $aOrWhereFields = array();
-
- if (is_array($filter->getFilterField())) {
- foreach ($filter->getFilterField() as $field) {
- $aOrWhereFields[] = "LOWER(q.".$field.") LIKE :filter";
- }
- } else {
- $aOrWhereFields[] = "LOWER(q.".$filter->getFilterField().") LIKE :filter";
- }
-
- foreach ($aOrWhereFields as $or) {
- $qb->orWhere($or);
- }
-
- $qb->setParameter("filter", "%".strtolower($filter->getFilter())."%");
- }
-
- if ($filter->getFilterCallback() !== null) {
- call_user_func($filter->getFilterCallback(), $qb);
- }
- }
-
-
- /**
- * Applies a custom query to the QueryBuilder
- *
- * @param QueryBuilder $qb The query builder
- * @param ManagerFilter $filter The query filter
- */
- protected function applyCustomQuery (QueryBuilder $qb, ManagerFilter $filter) {
-
- }
-
- /**
- * Applies pagination to the query
- *
- * @param QueryBuilder $qb The query builder
- * @param ManagerFilter $filter The query filter
- */
- protected function applyPagination (QueryBuilder $qb, ManagerFilter $filter) {
- if ($filter->getStart() !== null && $filter->getLimit() !== null) {
- $qb->setFirstResult($filter->getStart());
- }
-
- if ($filter->getLimit() !== null) {
- $qb->setMaxResults($filter->getLimit());
- }
- }
-
- /**
- * Applies record sorting
- *
- * @param QueryBuilder $qb The query builder
- * @param ManagerFilter $filter The query filter
- */
- protected function applySorting (QueryBuilder $qb, ManagerFilter $filter) {
- foreach ($filter->getSorters() as $sorter) {
- if ($sorter->getSortField() !== null && $sorter->getSortField() != "q.") {
- $qb->addOrderBy($sorter->getSortField(), $sorter->getSortDirection());
- }
- }
- }
-} -
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Manager/Exceptions/EntityInUseException.php b/src/backend/de/RaumZeitLabor/PartKeepr/Manager/Exceptions/EntityInUseException.php
@@ -1,31 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Manager\Exceptions;
-
-/**
- * This exception is thrown when an entity should be deleted, but is in use by other entities.
- * @author felicitus
- */
-class EntityInUseException extends \Exception {
-
- /**
- * The entity
- * @var BaseEntity
- */
- private $entity;
-
- /**
- * Constructs the exception
- * @param BaseEntity $entity
- */
- public function __construct (\de\RaumZeitLabor\PartKeepr\Util\BaseEntity $entity) {
- parent::__construct(sprintf("Entity %s is referenced by other entities, can't delete", get_class($entity)));
- $this->entity = $entity;
- }
-
- /**
- * Returns the entity which caused the error
- */
- public function getEntity () {
- return $this->entity;
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Manager/ManagerFilter.php b/src/backend/de/RaumZeitLabor/PartKeepr/Manager/ManagerFilter.php
@@ -1,196 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Manager;
-
-use de\RaumZeitLabor\PartKeepr\Service\Service;
-
-class ManagerFilter {
- /**
- * Specifies the record index at which to start
- * @var integer
- */
- protected $start = 0;
-
- /**
- * Specifies the number of records to retrieve
- * @var integer
- */
- protected $limit = null;
-
- /**
- * Specifies a string to filter for. Can either be a string
- * or null if no filter is wanted
- * @var string
- */
- protected $filter = null;
-
- /**
- * Specifies the field (or a list of fields) to apply the filter on
- * @var mixed null if disabled, a string for a single field or an array of fields
- */
- protected $filterField = null;
-
- /**
- * Specifies the fields to sort by
- * @var array
- */
- protected $sorters = array();
-
- /**
- * A callback which is called when creating the filter
- * @var function The callback
- */
- protected $callback = null;
-
- /**
- * Sets the start position
- * @param int $start
- */
- public function setStart ($start) {
- $this->start = intval($start);
- }
-
- /**
- * Returns the start position
- * @return int
- */
- public function getStart () {
- if ($this->start === null) {
- return 0;
- } else {
- return $this->start;
- }
- }
-
- /**
- * Sets the number of records to retrieve
- * @param mixed $limit Either a positive integer, or null/-1 for no limit
- */
- public function setLimit ($limit) {
- if ($limit === null || $limit == -1) {
- $this->limit = null;
- } else {
- $this->limit = intval($limit);
- }
- }
-
- /**
- * Returns the number of records to retrieve
- * @return int
- */
- public function getLimit () {
- return $this->limit;
- }
-
- /**
- * Sets the sorters for this filter.
- *
- * @param array $sorters An array of Sorter instances
- */
- public function setSorters (array $sorters) {
- // Make sure that each sorter is an instance of the Sorter class.
- foreach ($sorters as $sorter) {
- if (!($sorter instanceof Sorter)) {
- throw new InvalidArgumentException("The passed sorters needs to be an array of Sorter instances");
- }
- }
-
- $this->sorters = $sorters;
- }
-
- /**
- * Returns the sorters for this filter.
- * @return array An array of Sorter instances
- */
- public function getSorters () {
- return $this->sorters;
- }
-
- /**
- * Sets the filter. Specify null if no filter is wanted.
- * @param mixed $filter A string to filter for, or null to disable
- */
- public function setFilter ($filter) {
- $this->filter = $filter;
- }
-
- /**
- * Returns the filter.
- * @return mixed Either a string to filter for, or null if disabled
- */
- public function getFilter () {
- return $this->filter;
- }
-
- /**
- * Sets the field(s) to filter for.
- *
- * If multiple fields are specified, they will be combined using an "OR" clause.
- *
- * @param mixed $field Either null to disable, a single string to specify a field, or an array of string fields
- */
- public function setFilterField ($field) {
- $this->filterField = $field;
- }
-
- /**
- * Returns the field(s) to filter for
- * @return mixed See setFilterField
- */
- public function getFilterField () {
- return $this->filterField;
- }
-
- /**
- * Sets the filter callback
- * @param function $callback A function which is called when creating a filter. The callback function receives the
- * query builder as first argument.
- */
- public function setFilterCallback ($callback) {
- $this->callback = $callback;
- }
-
- /**
- * Returns the filter callback
- * @return function The callback function
- */
- public function getFilterCallback () {
- return $this->callback;
- }
-
- /**
- * Constructs a new filter set.
- *
- * If a service is passed, the constructor automatically extracts the parameters from the service
- *
- * @todo Document which parameters we have
- *
- * @param Service $service A service to extract the information from, or null
- */
- public function __construct (Service $service = null) {
- if (is_object($service)) {
- if ($service->hasParameter("start")) {
- $this->setStart($service->getParameter("start", null));
- }
-
- if ($service->hasParameter("limit")) {
- $this->setLimit($service->getParameter("limit", null));
- }
-
- if ($service->hasParameter("sort")) {
- $tmp = json_decode($service->getParameter("sort"), true);
-
- $aSorters = array();
-
- foreach ($tmp as $key => $sortParam) {
- $aSorters[] = new Sorter("q.".$sortParam["property"], $sortParam["direction"]);
- }
-
- $this->setSorters($aSorters);
- }
-
- if ($service->hasParameter("query")) {
- $this->setFilter($service->getParameter("query"));
- }
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Manager/Sorter.php b/src/backend/de/RaumZeitLabor/PartKeepr/Manager/Sorter.php
@@ -1,79 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Manager;
-
-/**
- * Represents a sorter, which is used with the ManagerFilter class.
- *
- * This allows the developer to specify multiple sorters. One sorter contains a sort field and a sort direction.
- */
-class Sorter {
- /**
- * The field to sort by
- * @var string
- */
- private $sortField = null;
-
- /**
- * The direction to sort by
- * @var string
- */
- private $sortDirection = null;
-
- /**
- * Constructs a new sorter.
- *
- * @param string $field The field to sort by
- * @param string $direction The direction, either "asc" or "desc"
- */
- public function __construct ($field = null, $direction = null) {
- if ($field !== null) {
- $this->setSortField($field);
- }
-
- if ($direction !== null) {
- $this->setSortDirection($direction);
- }
- }
-
- /**
- * Sets the sort field for this sorter
- * @param string $field The field to sort by
- */
- public function setSortField ($field) {
- $this->sortField = $field;
- }
-
- /**
- * Sets the sort direction for this sorter
- * @param string $direction Either "asc" or "desc"
- */
- public function setSortDirection ($direction) {
- switch (strtolower($direction)) {
- case "desc":
- case "d":
- $this->sortDirection = "desc";
- break;
- case "asc":
- case "a":
- default:
- $this->sortDirection = "asc";
- break;
- }
- }
-
- /**
- * Returns the sort field for this sorter
- * @return string The field name
- */
- public function getSortField () {
- return $this->sortField;
- }
-
- /**
- * Returns the sort order for this sorter
- * @return string Either "asc" or "desc"
- */
- public function getSortDirection () {
- return $this->sortDirection;
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Manufacturer/Manufacturer.php b/src/backend/de/RaumZeitLabor/PartKeepr/Manufacturer/Manufacturer.php
@@ -1,250 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Manufacturer;
-
-use de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
- * Represents a manufacturer
- * @Entity **/
-class Manufacturer extends BaseEntity implements Serializable, Deserializable {
- /**
- * The name of the manufacturer
- * @Column(type="string",unique=true)
- * @var string
- */
- private $name;
-
- /**
- * The address of the manufacturer
- * @Column(type="text",nullable=true)
- * @var string
- */
- private $address;
-
- /**
- * The URL
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $url;
-
- /**
- * The email
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $email;
-
- /**
- * The comment
- * @Column(type="text",nullable=true)
- * @var string
- */
- private $comment;
-
- /**
- * The phone number
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $phone;
-
- /**
- * The fax number
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $fax;
-
- /**
- * All ic logos of this manufacturer
- * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerICLogo",mappedBy="manufacturer",cascade={"persist", "remove"})
- */
- private $icLogos;
-
- /**
- * Creates a new manufacturer instance
- */
- public function __construct () {
- $this->icLogos = new \Doctrine\Common\Collections\ArrayCollection();
- }
-
- /**
- * Sets the name
- * @param string $name The name
- */
- public function setName ($name) {
- $this->name = $name;
- }
-
- /**
- * Returns the name
- * @return string The name
- */
- public function getName () {
- return $this->name;
- }
-
- /**
- * Sets the phone number
- * @param string $phone The phone number
- */
- public function setPhone ($phone) {
- $this->phone = $phone;
- }
-
- /**
- * Returns the phone number
- * @return string The phone number
- */
- public function getPhone () {
- return $this->phone;
- }
-
- /**
- * Sets the fax number
- * @param string $fax The fax number
- */
- public function setFax ($fax) {
- $this->fax = $fax;
- }
-
- /**
- * Returns the fax number
- * @return string The fax number
- */
- public function getFax () {
- return $this->fax;
- }
-
- /**
- * Sets the address
- * @param string $address The address
- */
- public function setAddress ($address) {
- $this->address = $address;
- }
-
- /**
- * Returns the address
- * @return string The address
- */
- public function getAddress () {
- return $this->address;
- }
-
- /**
- * Sets the comment
- * @param string $comment The comment
- */
- public function setComment ($comment) {
- $this->comment = $comment;
- }
-
- /**
- * Returns the comment
- * @return string The comment
- */
- public function getComment () {
- return $this->comment;
- }
-
- /**
- * Sets the email
- * @param string $email The email
- */
- public function setEmail ($email) {
- $this->email = $email;
- }
-
- /**
- * Returns the email
- * @return string The email
- */
- public function getEmail () {
- return $this->email;
- }
-
- /**
- * Sets the URL
- * @param string $url The URL
- */
- public function setURL ($url) {
- $this->url = $url;
- }
-
- /**
- * Returns the URL
- * @return string The url
- */
- public function getURL () {
- return $this->url;
- }
-
- /**
- * Returns the ic logos
- * @return ArrayCollection The array with all ic logos
- */
- public function getICLogos () {
- return $this->icLogos;
- }
-
- /**
- * Returns this manufacturer in serialized form
- * @return array The serialized manufacturer
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "name" => $this->getName(),
- "url" => $this->getURL(),
- "address" => $this->getAddress(),
- "email" => $this->getEmail(),
- "comment" => $this->getComment(),
- "phone" => $this->getPhone(),
- "fax" => $this->getFax(),
- "iclogos" => $this->serializeChildren($this->getICLogos())
- );
- }
-
- /**
- * Deserializes the manufacturer
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "name":
- $this->setName($value);
- break;
- case "url":
- $this->setURL($value);
- break;
- case "comment":
- $this->setComment($value);
- break;
- case "email":
- $this->setEmail($value);
- break;
- case "fax":
- $this->setFax($value);
- break;
- case "phone":
- $this->setPhone($value);
- break;
- case "address":
- $this->setAddress($value);
- break;
- case "iclogos":
- $this->deserializeChildren($value, $this->getICLogos(), "de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerICLogo");
- foreach ($this->getICLogos() as $iclogo) {
- $iclogo->setManufacturer($this);
- }
- break;
- }
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Manufacturer/ManufacturerICLogo.php b/src/backend/de/RaumZeitLabor/PartKeepr/Manufacturer/ManufacturerICLogo.php
@@ -1,63 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Manufacturer;
-
-use de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Image\Image;
-
-/**
- * Holds a manufacturer IC logo
- * @Entity
- **/
-class ManufacturerICLogo extends Image implements Serializable, Deserializable {
- /**
- * The manufacturer object
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer")
- * @var Manufacturer
- */
- private $manufacturer = null;
-
- /**
- * Creates a new IC logo instance
- */
- public function __construct () {
- parent::__construct(Image::IMAGE_ICLOGO);
- }
-
- /**
- * Sets the manufacturer
- * @param Manufacturer $manufacturer The manufacturer to set
- */
- public function setManufacturer (Manufacturer $manufacturer) {
- $this->manufacturer = $manufacturer;
- }
-
- /**
- * Returns the manufacturer
- * @return Manufacturer the manufacturer
- */
- public function getManufacturer () {
- return $this->manufacturer;
- }
-
- /**
- *
- * Serializes this ic logo
- * @return array The serialized ic logo
- */
- public function serialize () {
- return array("id" => $this->getId(), "manufacturer_id" => $this->getManufacturer()->getId());
- }
-
- /**
- * Deserializes the iclogo
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- if (array_key_exists("id", $parameters)) {
- if (substr($parameters["id"], 0, 4) === "TMP:") {
- $this->replaceFromTemporaryFile($parameters["id"]);
- }
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Manufacturer/ManufacturerManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Manufacturer/ManufacturerManager.php
@@ -1,104 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Manufacturer;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Category\CategoryManager,
- de\RaumZeitLabor\PartKeepr\Manufacturer\Exceptions\ManufacturerNotFoundException;
-
-class ManufacturerManager extends Singleton {
- /**
- * Returns a list of manufacturers.
- *
- * @param int $start Start of the list, default 0
- * @param int $limit Number of users to list, default 10
- * @param string $sort The field to sort by, default "name"
- * @param string $dir The direction to sort (ASC or DESC), default ASC
- * @param string $filter A string to filter the manufacturer's name by, default empty
- */
- public function getManufacturers ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
-
- $qb = PartKeepr::getEM()->createQueryBuilder();
- $qb->select("st.id, st.name, st.url, st.email, st.comment, st.address")->from("de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer","st");
-
- if ($filter != "") {
- $qb = $qb->where("LOWER(st.name) LIKE :filter");
- $qb->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- if ($limit > -1) {
- $qb->setMaxResults($limit);
- $qb->setFirstResult($start);
- }
-
- $qb->orderBy("st.".$sort, $dir);
-
- $query = $qb->getQuery();
-
- $result = $query->getResult();
-
- $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
- $totalQueryBuilder->select("COUNT(st.id)")->from("de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer","st");
-
-
-
- if ($filter != "") {
- $totalQueryBuilder = $totalQueryBuilder->where("LOWER(st.name) LIKE :filter");
- $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- $totalQuery = $totalQueryBuilder->getQuery();
-
- return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
- }
-
- /**
- * Adds a new manufacturer by name
- *
- * @param string $name The manufacturer name
- */
- public function addManufacturer ($name) {
- $manufacturer = new Manufacturer();
- $manufacturer->setName($name);
-
- PartKeepr::getEM()->persist($manufacturer);
- PartKeepr::getEM()->flush();
-
- return $manufacturer;
- }
-
- /**
- * 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
- */
- public function deleteManufacturer ($id) {
- $manufacturer = Manufacturer::loadById($id);
-
- 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/Manufacturer/ManufacturerService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Manufacturer/ManufacturerService.php
@@ -1,82 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Manufacturer;
-
-use de\RaumZeitLabor\PartKeepr\Service\RestfulService;
-
-use de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\Part\PartManager,
- de\RaumZeitLabor\PartKeepr\Stock\StockEntry,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class ManufacturerService extends Service implements RestfulService {
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
- */
- public function get () {
- if ($this->hasParameter("id")) {
- return array("data" => ManufacturerManager::getInstance()->getManufacturer($this->getParameter("id"))->serialize());
- } else {
- if ($this->hasParameter("sort")) {
- $tmp = json_decode($this->getParameter("sort"), true);
-
- $aSortParams = $tmp[0];
- } else {
- $aSortParams = array(
- "property" => "name",
- "direction" => "ASC");
- }
- return ManufacturerManager::getInstance()->getManufacturers(
- $this->getParameter("start", $this->getParameter("start", 0)),
- $this->getParameter("limit", $this->getParameter("limit", 25)),
- $this->getParameter("sortby", $aSortParams["property"]),
- $this->getParameter("dir", $aSortParams["direction"]),
- $this->getParameter("query", ""));
- }
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::create()
- */
- public function create () {
- $this->requireParameter("name");
-
- $manufacturer = new Manufacturer;
- $manufacturer->deserialize($this->getParameters());
-
- PartKeepr::getEM()->persist($manufacturer);
- PartKeepr::getEM()->flush();
-
- return array("data" => $manufacturer->serialize());
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update()
- */
- public function update () {
- $this->requireParameter("id");
- $this->requireParameter("name");
- $manufacturer = ManufacturerManager::getInstance()->getManufacturer($this->getParameter("id"));
- $manufacturer->deserialize($this->getParameters());
-
- PartKeepr::getEM()->flush();
-
- return array("data" => $manufacturer->serialize());
-
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::destroy()
- */
- public function destroy () {
- $this->requireParameter("id");
-
- ManufacturerManager::getInstance()->deleteManufacturer($this->getParameter("id"));
-
- return array("data" => null);
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/ManufacturerICLogo/ManufacturerICLogoManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/ManufacturerICLogo/ManufacturerICLogoManager.php
@@ -1,65 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\ManufacturerICLogo;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Manufacturer\Exceptions\ManufacturerNotFoundException;
-
-class ManufacturerICLogoManager extends Singleton {
- /**
- * Returns a list of manufacturer ic logos.
- *
- * @param int $start Start of the list, default 0
- * @param int $limit Number of users to list, default 10
- * @param string $sort The field to sort by, default "name"
- * @param string $dir The direction to sort (ASC or DESC), default ASC
- * @param string $filter The manufacturer id
- */
- public function getManufacturerICLogos ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
-
- $qb = PartKeepr::getEM()->createQueryBuilder();
- $qb->select("st.id, maf.id AS manufacturer_id")->from("de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerICLogo","st")
- ->leftJoin('st.manufacturer', "maf");
-
- if ($filter != "") {
- $manufacturer = Manufacturer::loadById($filter);
- $qb = $qb->where("st.manufacturer = :manufacturer");
- $qb->setParameter("manufacturer", $manufacturer);
- }
-
- if ($limit > -1) {
- $qb->setMaxResults($limit);
- $qb->setFirstResult($start);
- }
-
- $qb->orderBy("st.".$sort, $dir);
-
- $query = $qb->getQuery();
-
- $result = $query->getResult();
-
- $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
- $totalQueryBuilder->select("COUNT(st.id)")->from("de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerICLogo","st");
-
-
-
- if ($filter != "") {
- $totalQueryBuilder = $totalQueryBuilder->where("st.manufacturer = :manufacturer");
- $totalQueryBuilder->setParameter("manufacturer", $manufacturer);
- }
-
- $totalQuery = $totalQueryBuilder->getQuery();
-
- return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
- }
-
- /**
- * Returns a manufacturer ic logo by id
- * @param int $id The manufacturer ic logo id
- */
- public function getManufacturerICLogo ($id) {
- return ManufacturerICLogo::loadById($id);
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/ManufacturerICLogo/ManufacturerICLogoService.php b/src/backend/de/RaumZeitLabor/PartKeepr/ManufacturerICLogo/ManufacturerICLogoService.php
@@ -1,101 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\ManufacturerICLogo;
-
-use de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerICLogo,
- de\RaumZeitLabor\PartKeepr\TempImage\TempImage,
- de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class ManufacturerICLogoService extends Service implements RestfulService {
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
- */
- public function get () {
- if ($this->hasParameter("id")) {
- return ManufacturerICLogoManager::getInstance()->getManufacturerICLogo($this->getParameter("id"))->serialize();
- } else {
- if ($this->hasParameter("sort")) {
- $tmp = json_decode($this->getParameter("sort"), true);
-
- $aSortParams = $tmp[0];
- } else {
- $aSortParams = array(
- "property" => "id",
- "direction" => "ASC");
- }
-
- $filter = "";
-
- if ($this->hasParameter("filter")) {
- $tmp = json_decode($this->getParameter("filter"), true);
-
- foreach ($tmp as $item) {
- if (array_key_exists("property", $item)) {
- if ($item["property"] == "manufacturer_id") {
- if (array_key_exists("value", $item)) {
- $filter = $item["value"];
- }
- }
- }
- }
- }
- return ManufacturerICLogoManager::getInstance()->getManufacturerICLogos(
- $this->getParameter("start", $this->getParameter("start", 0)),
- $this->getParameter("limit", $this->getParameter("limit", 25)),
- $this->getParameter("sortby", $aSortParams["property"]),
- $this->getParameter("dir", $aSortParams["direction"]),
- $filter);
- }
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::create()
- */
- public function create () {
- $this->requireParameter("tmp_id");
- $this->requireParameter("manufacturer_id");
-
- $tmpImage = TempImage::loadById($this->getParameter("tmp_id"));
-
- $image = new ManufacturerICLogo();
-
- $manufacturer = Manufacturer::loadById($this->getParameter("manufacturer_id"));
-
- $image->setManufacturer($manufacturer);
- $image->replace($tmpImage->getFilename());
- $image->setOriginalFilename($tmpImage->getOriginalFilename());
- PartKeepr::getEM()->persist($image);
- PartKeepr::getEM()->flush();
-
- return $image->serialize();
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update()
- */
- public function update () {
-
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::destroy()
- */
- public function destroy () {
- $this->requireParameter("id");
-
- $logo = ManufacturerICLogo::loadById($this->getParameter("id"));
-
- PartKeepr::getEM()->remove($logo);
- PartKeepr::getEM()->flush();
-
- return array("data" => null);
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Part/Exceptions/CategoryNotAssignedException.php b/src/backend/de/RaumZeitLabor/PartKeepr/Part/Exceptions/CategoryNotAssignedException.php
@@ -1,20 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Part\Exceptions;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Util\SerializableException,
- de\RaumZeitLabor\PartKeepr\Part\Part;
-
-/**
- * This exception is thrown when a part hasn't got a category assigned
- */
-class CategoryNotAssignedException extends SerializableException {
-
- /**
- * Constructs the exception
- * @param BaseEntity $entity
- */
- public function __construct (Part $part) {
- parent::__construct(PartKeepr::i18n("Part %s has no category assigned", $part));
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Part/Exceptions/StorageLocationNotAssignedException.php b/src/backend/de/RaumZeitLabor/PartKeepr/Part/Exceptions/StorageLocationNotAssignedException.php
@@ -1,19 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Part\Exceptions;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Util\SerializableException;
-
-/**
- * This exception is thrown when a part hasn't got a storage location assigned
- */
-class StorageLocationNotAssignedException extends SerializableException {
-
- /**
- * Constructs the exception
- * @param BaseEntity $entity
- */
- public function __construct () {
- parent::__construct(PartKeepr::i18n("No storage location assigned"));
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Part/Part.php b/src/backend/de/RaumZeitLabor/PartKeepr/Part/Part.php
@@ -1,640 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Part;
-
-use de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation,
- de\RaumZeitLabor\PartKeepr\Footprint\Footprint,
- de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager,
- de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\PartCategory\PartCategory,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Part\Exceptions\CategoryNotAssignedException,
- de\RaumZeitLabor\PartKeepr\Util\Exceptions\OutOfRangeException,
- de\RaumZeitLabor\PartKeepr\Part\Exceptions\StorageLocationNotAssignedException;
-
-
-/**
- * Represents a part in the database. The heart of our project. Handle with care!
- *
- * @Entity @HasLifecycleCallbacks
- */
-class Part extends BaseEntity implements Serializable, Deserializable {
- /**
- * The category of the part
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\PartCategory\PartCategory")
- * @var Category
- */
- private $category;
-
- /**
- * The part's name
- * @Column
- * @var string
- */
- private $name;
-
- /**
- * The part's short description
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $description;
-
- /**
- * The footprint of this part
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Footprint\Footprint")
- * @var Footprint
- */
- private $footprint;
-
- /**
- * The unit in which the part's "amount" is calculated. This is necessary to count parts
- * in "pieces", "meters" or "grams".
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Part\PartUnit")
- * @var PartUnit
- */
- private $partUnit;
-
- /**
- * Defines the storage location of this part
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation")
- * @var StorageLocation
- */
- private $storageLocation;
-
- /**
- * Holds the manufacturers which can manufacture this part
- * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\Part\PartManufacturer",mappedBy="part",cascade={"persist", "remove"})
- * @var ArrayCollection
- */
- private $manufacturers;
-
- /**
- * Holds the distributors from where we can buy the part
- * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\Part\PartDistributor",mappedBy="part",cascade={"persist", "remove"})
- * @var ArrayCollection
- */
- private $distributors;
-
- /**
- * Holds the part images
- * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\Part\PartImage",mappedBy="part",cascade={"persist", "remove"})
- * @var PartImage
- */
- private $images;
-
- /**
- * Holds the part attachments
- * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\Part\PartAttachment",mappedBy="part",cascade={"persist", "remove"})
- * @var PartAttachment
- */
- private $attachments;
-
- /**
- * The comment for this part
- * @Column(type="text")
- */
- private $comment = "";
-
- /**
- * The stock level. Note that this is a cached value, because it makes our summary queries easier.
- * @todo It would be nice if we could get rid of that.
- * @Column(type="integer")
- * @var integer
- */
- private $stockLevel = 0;
-
- /**
- * The minimum stock level for this part. If we run out of this part (e.g. stockLevel < minStockLevel),
- * we can see that in the system and re-order parts.
- *
- * @Column(type="integer")
- * @var integer
- */
- private $minStockLevel = 0;
-
- /**
- * The average price for the part. Note that this is a cached value.
- *
- * @todo It would be nice if we could get rid of that
- * @Column(type="decimal",precision=13,scale=4,nullable=true)
- * @var float
- */
- private $averagePrice = null;
-
- /**
- * The stock level history
- * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\Stock\StockEntry",mappedBy="part",cascade={"persist", "remove"})
- * @var ArrayCollection
- */
- private $stockLevels;
-
- /**
- * The parameters for this part
- * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\PartParameter\PartParameter",mappedBy="part",cascade={"persist", "remove"})
- * @var ArrayCollection
- */
- private $parameters;
-
- /**
- * The part status for this part
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $status;
-
- /**
- * Defines if the part needs review
- * @Column(type="boolean")
- * @var boolean
- */
- private $needsReview;
-
- /**
- * The create date+time for this part
- * @Column(type="datetime",nullable=true)
- * @var \DateTime
- */
- private $createDate;
-
- /**
- * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\Project\Project", mappedBy="part")
- **/
- private $projects;
-
- /**
- * The internal part number
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $internalPartNumber;
-
- public function __construct () {
- $this->distributors = new \Doctrine\Common\Collections\ArrayCollection();
- $this->manufacturers = new \Doctrine\Common\Collections\ArrayCollection();
- $this->parameters = new \Doctrine\Common\Collections\ArrayCollection();
- $this->images = new \Doctrine\Common\Collections\ArrayCollection();
- $this->attachments = new \Doctrine\Common\Collections\ArrayCollection();
- $this->setCreateDate(new \DateTime());
- $this->setReviewFlag(false);
- }
-
- /**
- * Sets the name for this part
- * @param string $name The part's name
- */
- public function setName ($name) {
- $this->name = $name;
- }
-
- /**
- * Returns the name of this part
- * @return string The part name
- */
- public function getName () {
- return $this->name;
- }
-
- /**
- * Sets the internal part number for this part
- * @param string $partnumber
- */
- public function setInternalPartNumber ($partNumber) {
- $this->internalPartNumber = $partNumber;
- }
-
- /**
- * Returns the internal part number for this part
- * @return string the internal part number
- */
- public function getInternalPartNumber () {
- return $this->internalPartNumber;
- }
-
- /**
- * Sets the description for this part
- * @param string $description The part's short description
- */
- public function setDescription ($description) {
- $this->description = $description;
- }
-
- /**
- * Returns the short description of this part
- * @return string The part description
- */
- public function getDescription () {
- return $this->description;
- }
-
- /**
- * Sets the part unit
- *
- * @param PartUnit $partUnit The part unit object to set
- * @return nothing
- */
- public function setPartUnit (PartUnit $partUnit) {
- $this->partUnit = $partUnit;
- }
-
- /**
- * Returns the part unit
- *
- * @param none
- * @return PartUnit The part unit object
- */
- public function getPartUnit () {
- return $this->partUnit;
- }
-
- /**
- * Sets the average price for this unit
- * @todo Is this actually used?
- * @param float $price The price to set
- */
- public function setAveragePrice ($price) {
- $this->averagePrice = $price;
- }
-
- /**
- * Updates the internal stock level from the stock history
- */
- public function updateStockLevel () {
- $this->stockLevel = $this->getStockLevel();
- }
-
- /**
- * Sets the review flag
- * @param boolean $bReview True if the part needs review, false otherwise
- */
- public function setReviewFlag ($bReview) {
- $this->needsReview = $bReview;
- }
-
- /**
- * Returns the review flag
- * @return boolean True if the part needs review, false otherwise
- */
- public function getReviewFlag () {
- return $this->needsReview;
- }
-
- /**
- * Set the minimum stock level for this part
- *
- * Only positive values are allowed.
- *
- * @param int $minStockLevel A minimum stock level, only values >= 0 are allowed.
- * @throws \de\RaumZeitLabor\PartKeepr\Util\Exceptions\OutOfRangeException If the passed stock level is not in range (>=0)
- */
- public function setMinStockLevel ($minStockLevel) {
- $minStockLevel = intval($minStockLevel);
-
- if ($minStockLevel < 0) {
- $exception = new OutOfRangeException(PartKeepr::i18n("Minimum Stock Level is out of range"));
- $exception->setDetail(PartKeepr::i18n("The minimum stock level must be 0 or higher"));
- throw $exception;
- }
- $this->minStockLevel = $minStockLevel;
- }
-
- /**
- * Sets the category for this part
- * @param \de\RaumZeitLabor\PartKeepr\PartCategory\PartCategory $category The category
- */
- public function setCategory (PartCategory $category) {
- $this->category = $category;
- }
-
- /**
- * Returns the assigned category
- * @return \de\RaumZeitLabor\PartKeepr\PartCategory\PartCategory
- */
- public function getCategory () {
- return $this->category;
- }
-
- /**
- * Returns all projects this part is used
- * @return ArrayCollection the projects
- */
- public function getProjects () {
- return $this->projects;
- }
-
- /**
- * Sets the storage location for this part
- * @param \de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation $storageLocation The storage location
- */
- public function setStorageLocation (StorageLocation $storageLocation) {
- $this->storageLocation = $storageLocation;
- }
-
- /**
- * Returns the storage location for this part
- * @return \de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation $storageLocation The storage location
- */
- public function getStorageLocation () {
- return $this->storageLocation;
- }
-
- /**
- * Sets the footprint for this part
- * @param \de\RaumZeitLabor\PartKeepr\Footprint\Footprint $footprint The footprint to set
- */
- public function setFootprint (Footprint $footprint = null) {
- $this->footprint = $footprint;
- }
-
- /**
- * Sets the comment for this part
- * @param string $comment The comment for this part
- */
- public function setComment ($comment) {
- $this->comment = $comment;
- }
-
- /**
- * Returns the comment for this part
- * @return string The comment
- */
- public function getComment () {
- return $this->comment;
- }
-
- /**
- * Returns the distributors array
- * @return ArrayCollection the distributors
- */
- public function getDistributors () {
- return $this->distributors;
- }
-
- /**
- * Returns the part images array
- * @return ArrayCollection the part images
- */
- public function getImages () {
- return $this->images;
- }
-
- /**
- * Returns the part attachments array
- * @return ArrayCollection the part attachments
- */
- public function getAttachments () {
- return $this->attachments;
- }
-
- /**
- * Returns the manufacturers array
- * @return ArrayCollection the manufactuers
- */
- public function getManufacturers () {
- return $this->manufacturers;
- }
-
- /**
- * Returns the parameters assigned to this part
- * @return array An array of PartParameter objects
- */
- public function getParameters () {
- return $this->parameters;
- }
-
- /**
- * Returns the stock level of this part. This is a realtime function which
- * actually creates a query over the StockEntry table.
- * @return int The stock level
- */
- public function getStockLevel () {
- $query = PartKeepr::getEM()->createQuery("SELECT SUM(s.stockLevel) FROM de\RaumZeitLabor\PartKeepr\Stock\StockEntry s WHERE s.part = :part");
- $query->setParameter("part", $this);
-
- return $query->getSingleScalarResult();
- }
-
- /**
- * Sets the create date for this part
- * @param \DateTime $dateTime The create date+time
- */
- private function setCreateDate (\DateTime $dateTime) {
- $this->createDate = $dateTime;
- }
-
- /**
- * Returns the create date
- * @return \DateTime The create date+time
- */
- public function getCreateDate () {
- return $this->createDate;
- }
-
- /**
- * Sets the status for this part. A status is any string describing the status,
- * e.g. "new", "used", "broken" etc.
- * @param string $status The status
- */
- public function setStatus ($status) {
- $this->status = $status;
- }
-
- /**
- * Returns the status for this part.
- * @return string The status
- */
- public function getStatus () {
- return $this->status;
- }
-
- public function updateCacheData () {
- $this->updateStockLevel();
- $this->updatePrice();
- }
-
- /**
- * Updates the average price for a part
- */
- public function updatePrice () {
- $query = PartKeepr::getEM()->createQuery("SELECT SUM(se.price*se.stockLevel) / SUM(se.stockLevel) FROM de\RaumZeitLabor\PartKeepr\Stock\StockEntry se WHERE se.part = :part AND se.stockLevel > 0");
- $query->setParameter("part", $this);
- $val = $query->getSingleScalarResult();
-
- $query = PartKeepr::getEM()->createQuery('UPDATE de\RaumZeitLabor\PartKeepr\Part\Part p SET p.averagePrice = :val WHERE p = :part');
- $query->setParameter("val", $val);
- $query->setParameter("part", $this);
- $query->execute();
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Util.Serializable::serialize()
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "name" => $this->getName(),
- "description" => $this->getDescription(),
- "comment" => $this->getComment(),
- "stockLevel" => $this->getStockLevel(),
- "footprint" => is_object($this->footprint) ? $this->footprint->getId() : null,
- "minStockLevel" => $this->minStockLevel,
- "status" => $this->getStatus(),
- "storageLocation" => is_object($this->storageLocation) ? $this->storageLocation->getId() : null,
- "category" => is_object($this->category) ? $this->category->getId() : null,
- "partUnit" => is_object($this->partUnit) ? $this->getPartUnit()->getId() : null,
- "manufacturers" => $this->serializeChildren($this->getManufacturers()),
- "distributors" => $this->serializeChildren($this->getDistributors()),
- "images" => $this->serializeChildren($this->getImages()),
- "attachments" => $this->serializeChildren($this->getAttachments()),
- "parameters" => $this->serializeChildren($this->getParameters()),
- "createDate" => $this->getCreateDate()->format("Y-m-d H:i:s"),
- "needsReview" => $this->getReviewFlag(),
- "internalPartNumber" => $this->getInternalPartNumber(),
- // Additional things we serialize to make displaying stuff in the frontend easier
- "categoryName" => is_object($this->category) ? $this->category->getName() : null,
- "footprintName" => is_object($this->footprint) ? $this->footprint->getName() : null,
- "storageLocationName" => is_object($this->storageLocation) ? $this->storageLocation->getName() : null
- );
- }
-
- /**
- * Deserializes the part
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "name":
- $this->setName($value);
- break;
- case "description":
- $this->setDescription($value);
- break;
- case "comment":
- $this->setComment($value);
- break;
- case "internalPartNumber":
- $this->setInternalPartNumber($value);
- break;
- case "footprint":
- if ($value === 0) {
- $this->setFootprint(null);
- } else {
- try {
- $footprint = Footprint::loadById($value);
- $this->setFootprint($footprint);
- } catch (\Exception $e) {
- // No footprint was found. Ignore it.
- }
- }
- break;
- case "minStockLevel":
- $this->setMinStockLevel($value);
- break;
- case "partUnit":
- $partUnit = PartUnit::loadById($value);
- $this->setPartUnit($partUnit);
- break;
- case "category":
- $category = PartCategory::loadById($value);
- $this->setCategory($category);
- break;
- case "status":
- $this->setStatus($value);
- break;
- case "storageLocation":
- $storageLocation = StorageLocation::loadById($value);
- $this->setStorageLocation($storageLocation);
- break;
- case "manufacturers":
- $this->deserializeChildren($value, $this->getManufacturers(), "de\RaumZeitLabor\PartKeepr\Part\PartManufacturer");
- foreach ($this->getManufacturers() as $manufacturer) {
- $manufacturer->setPart($this);
- }
- break;
- case "distributors":
- $this->deserializeChildren($value, $this->getDistributors(), "de\RaumZeitLabor\PartKeepr\Part\PartDistributor");
- foreach ($this->getDistributors() as $distributor) {
- $distributor->setPart($this);
- }
- break;
- case "parameters":
- $this->deserializeChildren($value, $this->getParameters(), "de\RaumZeitLabor\PartKeepr\PartParameter\PartParameter");
- foreach ($this->getParameters() as $parameter) {
- $parameter->setPart($this);
- }
- break;
- case "needsReview":
- $this->setReviewFlag($value);
- break;
- case "attachments":
- $this->deserializeChildren($value, $this->getAttachments(), "de\RaumZeitLabor\PartKeepr\Part\PartAttachment");
- foreach ($this->getAttachments() as $attachment) {
- $attachment->setPart($this);
- }
- break;
- }
- }
- }
-
- /**
- * Checks if the part category is set.
- *
- * @throws CategoryNotAssignedException
- */
- private function checkCategoryConsistency () {
- if ($this->getCategory() === null) {
- throw new CategoryNotAssignedException($this);
- }
- }
-
- /**
- * Checks if the part storage location is set.
- *
- * @throws StorageLocationNotAssignedException
- */
- private function checkStorageLocationConsistency () {
- if ($this->getStorageLocation() === null) {
- throw new StorageLocationNotAssignedException();
- }
- }
-
- /**
- * Checks if the requirements for database persisting are given.
- *
- * @throws CategoryNotAssignedException Thrown if no category is set
- * @throws StorageLocationNotAssignedException Thrown if no storage location is set
- *
- * @PrePersist
- */
- public function onPrePersist () {
- $this->checkCategoryConsistency();
- $this->checkStorageLocationConsistency();
- }
-
- /**
- *
- * Checks if the requirements for database persisting are given.
- *
- * For a list of exceptions, see
- * @see de\RaumZeitLabor\PartKeepr\Part.Part::onPrePersist()
- *
- * @PreUpdate */
- public function onPreUpdate () {
- $this->checkCategoryConsistency();
- $this->checkStorageLocationConsistency();
- }
-
- /**
- * Returns a string representation of the part
- *
- * @param none
- * @return string The name and the ID of the part
- */
- public function __toString () {
- return $this->getName() . " (".$this->getId().")";
- }
-
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartAttachment.php b/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartAttachment.php
@@ -1,128 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Part;
-
-use de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\UploadedFile\UploadedFile;
-
-/**
- * Holds a part attachment
- * @Entity
- **/
-class PartAttachment extends UploadedFile implements Serializable, Deserializable {
- /**
- * The description of this attachment
- * @Column(type="text")
- * @var string
- */
- private $description;
-
- /**
- * Creates a new part attachment
- */
- public function __construct () {
- parent::__construct();
- $this->setType("PartAttachment");
- }
- /**
- * The part object
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Part\Part")
- * @var Part
- */
- private $part = null;
-
- /**
- * Sets the part
- * @param Part $part The part to set
- */
- public function setPart (Part $part) {
- $this->part = $part;
- }
-
- /**
- * Returns the part
- * @return Part the part
- */
- public function getPart () {
- return $this->part;
- }
-
- /**
- * Sets the description for this attachment
- * @param string $description The attachment description
- */
- public function setDescription ($description) {
- $this->description = $description;
- }
-
- /**
- * Returns the description for this attachment
- * @return string The description
- */
- public function getDescription () {
- return $this->description;
- }
-
- /**
- *
- * Serializes this part attachment
- * @return array The serialized part attachment
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "part_id" => $this->getPart()->getId(),
- "originalFilename" => $this->getOriginalFilename(),
- "mimetype" => $this->getMimetype(),
- "extension" => $this->getExtension(),
- "size" => $this->getSize(),
- "description" => $this->getDescription(),
- "image" => $this->isImage());
- }
-
- /**
- * Deserializes the part attachment
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- if (array_key_exists("id", $parameters)) {
- if (substr($parameters["id"], 0, 4) === "TMP:") {
- $this->replaceFromTemporaryFile($parameters["id"]);
- }
- }
-
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "description":
- $this->setDescription($value);
- break;
- }
- }
- }
-
- /**
- * Returns if the attachment is an image or not.
- *
- * Ths method uses ImageMagick to find out if this is an image. Limitations apply; if ImageMagick doesn't support
- * the image format, this method would return false, even if it is an image.
- *
- * @return True if the attachment is an image, false otherwise
- */
- public function isImage () {
- /**
- * Special case: Check if it's a PDF. If yes, return immediately.
- * This is because ImageMagick outputs warning messages for malformed PDF files, and halts the execution
- * of the script for several seconds. DO NOT REMOVE!
- */
- if ($this->getMimeType() == "application/pdf") {
- return false;
- }
-
- try {
- $im = new \Imagick($this->getFilename());
- return true;
- } catch (\ImagickException $e) {
- return false;
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartDistributor.php b/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartDistributor.php
@@ -1,193 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Part;
-
-use de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Distributor\Distributor;
-
-/**
- * This class represents the link between a part and a distributor.
- * @Entity **/
-class PartDistributor extends BaseEntity implements Serializable, Deserializable {
- /**
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Part\Part")
- */
- private $part;
-
- /**
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Distributor\Distributor")
- */
- private $distributor;
-
- /**
- * The order number for the part and distributor
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $orderNumber;
-
- /**
- * Defines the packaging unit when ordering a part. Some items can't be ordered in a quantity of just one at
- * certain manufacturers.
- *
- * @Column(type="integer")
- * @var integer
- */
- private $packagingUnit;
-
- /**
- * Specifies the price of the part. Note that the price
- * needs to be per item, not per packaging unit.
- *
- * @Column(type="decimal",precision=13,scale=4,nullable=true)
- * @var float
- */
- private $price;
-
- /**
- * Cretes a new part->distributor link. Initializes the packaging unit with a quantity of "1".
- *
- * @param Part $part The part
- * @param Distributor $distributor The distributor
- */
- public function __construct () {
- $this->setPackagingUnit(1);
- }
-
- /**
- * Sets the packaging unit for a specific distributor.
- *
- * For example, some distributors only sell resistors in packs of 100, so you can't order just one. We use the
- * packagingUnit to calculate how many pieces will be delivered once ordered. So if your stock level falls below
- * the minimum (example: you would need to order 10 resistors), we suggest that you only order one resistor pack
- * instead of 10.
- *
- * @param int $packagingUnit The amount of items in one package
- * @throws \de\RaumZeitLabor\PartKeepr\Part\OutOfRangeException When the packaging unit is less than 1
- */
- public function setPackagingUnit ($packagingUnit) {
- $packagingUnit = intval($packagingUnit);
-
- if ($packagingUnit < 1) {
- $exception = new OutOfRangeException(PartKeepr::i18n("Packaging Unit is out of range"));
- $exception->setDetail(PartKeepr::i18n("The packaging unit must be 1 or higher"));
- throw $exception;
- }
-
- $this->packagingUnit = $packagingUnit;
- }
-
- /**
- * Returns the packaging unit
- * @return int The packaging unit
- */
- public function getPackagingUnit () {
- return $this->packagingUnit;
- }
-
- /**
- * Sets the part
- * @param Part $part The part
- */
- public function setPart (Part $part) {
- $this->part = $part;
- }
-
- /**
- * Returns the part
- * @return Part The part
- */
- public function getPart () {
- return $this->part;
- }
-
- /**
- * Sets the distributor
- * @param Distributor $distributor The distributor
- */
- public function setDistributor (Distributor $distributor) {
- $this->distributor = $distributor;
- }
-
- /**
- * Returns the distributor
- * @return Distributor The distributor
- */
- public function getDistributor () {
- return $this->distributor;
- }
-
- /**
- * Sets the order number
- * @param string $orderNumber The order number
- */
- public function setOrderNumber ($orderNumber) {
- $this->orderNumber = $orderNumber;
- }
-
- /**
- * Returns the order number
- * @return string The order number
- */
- public function getOrderNumber () {
- return $this->orderNumber;
- }
-
- /**
- * Sets the price
- * @param float $price
- */
- public function setPrice ($price) {
- echo "/** price set to ".$price." **/";
- $this->price = $price;
- }
-
- /**
- * Returns the price
- */
- public function getPrice () {
- return $this->price;
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Util.Serializable::serialize()
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "orderNumber" => $this->getOrderNumber(),
- "distributor_id" => $this->getDistributor()->getId(),
- "distributor_name" => $this->getDistributor()->getName(),
- "part_id" => $this->getPart()->getId(),
- "part_name" => $this->getPart()->getName(),
- "packagingUnit" => $this->getPackagingUnit(),
- "price" => $this->getPrice());
- }
-
- /**
- * Deserializes the part manufacturer
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "distributor_id":
- $distributor = Distributor::loadById($value);
- $this->setDistributor($distributor);
- break;
- case "orderNumber":
- $this->setOrderNumber($value);
- break;
- case "packagingUnit":
- $this->setPackagingUnit($value);
- break;
- case "price":
- $this->setPrice($value);
- break;
- }
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartFulltextSearch.php b/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartFulltextSearch.php
@@ -1,29 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Part;
-
-use de\RaumZeitLabor\PartKeepr\FulltextSearch\FulltextSearch;
-
-/**
- * Implements the part fulltext search
- */
-class PartFulltextSearch extends FulltextSearch {
- /**
- * Returns the FQDN of the part entity
- *
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\FulltextSearch.FulltextSearch::getEntityName()
- */
- protected function getEntityName () {
- return 'de\RaumZeitLabor\PartKeepr\Part\Part';
- }
-
- /**
- * Returns the fields to be searched in
- *
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\FulltextSearch.FulltextSearch::getFields()
- */
- protected function getFields () {
- return array("comment", "name", "internalPartNumber");
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartImage.php b/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartImage.php
@@ -1,50 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Part;
-
-use de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Image\Image;
-
-/**
- * Holds a part image
- * @Entity
- **/
-class PartImage extends Image implements Serializable {
- /**
- * The part object
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Part\Part")
- * @var Part
- */
- private $part = null;
-
- /**
- * Creates a new part image instance
- */
- public function __construct () {
- parent::__construct(Image::IMAGE_PART);
- }
-
- /**
- * Sets the part
- * @param Part $part The part to set
- */
- public function setPart (Part $part) {
- $this->part = $part;
- }
-
- /**
- * Returns the part
- * @return Part the part
- */
- public function getPart () {
- return $this->part;
- }
-
- /**
- *
- * Serializes this part image
- * @return array The serialized part imaage
- */
- public function serialize () {
- return array("id" => $this->getId(), "part_id" => $this->getPart()->getId());
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartManager.php
@@ -1,441 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Part;
-
-use de\RaumZeitLabor\PartKeepr\Logger\Logger;
-
-use de\RaumZeitLabor\PartKeepr\UploadedFile\TempUploadedFile,
- de\RaumZeitLabor\PartKeepr\Manager\ManagerFilter,
- Doctrine\ORM\QueryBuilder,
- de\RaumZeitLabor\PartKeepr\PartParameter\PartParameter,
- de\RaumZeitLabor\PartKeepr\Manager\AbstractManager,
- de\RaumZeitLabor\PartKeepr\Unit\Unit,
- de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefix,
- de\RaumZeitLabor\PartKeepr\Part\PartDistributor,
- de\RaumZeitLabor\PartKeepr\Part\PartManufacturer,
- de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation,
- de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocationManager,
- de\RaumZeitLabor\PartKeepr\Part\Part,
- Doctrine\ORM\Query,
- de\RaumZeitLabor\PartKeepr\PartUnit\PartUnitManager,
- de\RaumZeitLabor\PartKeepr\Distributor\Distributor,
- de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer,
- de\RaumZeitLabor\PartKeepr\Footprint\FootprintManager,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager,
- de\RaumZeitLabor\PartKeepr\Stock\StockEntry,
- de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\Footprint\Footprint,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager,
- de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerManager;
-
-class PartManager extends AbstractManager {
-
- /**
- * Returns the FQCN for the target entity to operate on.
- * @return string The FQCN, e.g. de\RaumZeitLabor\PartKeepr\Part
- */
- public function getEntityName () {
- return 'de\RaumZeitLabor\PartKeepr\Part\Part';
- }
-
- /**
- * Returns all fields which need to appear in the getList ResultSet.
- * @return array An array of all fields which should be returned
- */
- public function getQueryFields () {
- return array("name", "description", "averagePrice", "status", "needsReview", "createDate", "id", "stockLevel",
- "minStockLevel", "comment", "st.id AS storageLocation_id", "c.categoryPath AS categoryPath",
- "st.name as storageLocationName", "f.id AS footprint_id", "f.name AS footprintName",
- "c.id AS category", "c.name AS categoryName", "pu.id AS partUnit", "pu.name AS partUnitName",
- "pu.is_default AS partUnitDefault"
- );
- }
-
- /**
- * Returns the default sort field
- *
- * @return string The default sort field
- */
- public function getDefaultSortField () {
- return "dateTime";
- }
-
- /**
- * Appends various join tables to the result set
- *
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Manager.AbstractManager::applyCustomQuery()
- */
- protected function applyCustomQuery (QueryBuilder $qb, ManagerFilter $filter) {
- /**
- * Pull in additional tables
- */
- $qb ->join("q.storageLocation", "st")
- ->leftJoin("q.footprint", "f")
- ->join("q.category", "c")
- ->leftJoin("q.partUnit", "pu");
-
- // Apply special handling for non-direct fields in relations, where the frontend has no idea about.
- foreach ($filter->getSorters() as $sorter) {
- switch ($sorter->getSortField()) {
- case "q.categoryPath":
- $sorter->setSortField("c.categoryPath");
- break;
- case "q.storageLocationName":
- $sorter->setSortField("st.name");
- break;
- case "q.footprintName":
- $sorter->setSortField("f.name");
- break;
- default:
- break;
- }
- }
-
- }
-
- /**
- * Processes the result after it was retrieved. In the default configuration, it returns an array result, or
- * if no query fields are specified, it tries to serialize all objects.
- */
- protected function getResult (Query $query) {
- $result = parent::getResult($query);
-
- /* Add attachment counts to the result set and re-format the date */
- foreach ($result as $key => $item) {
- $dql = "SELECT COUNT(pa) FROM de\RaumZeitLabor\PartKeepr\Part\PartAttachment pa WHERE pa.part = :part";
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("part", $item["id"]);
-
- $result[$key]["attachmentCount"] = $query->getSingleScalarResult();
-
- $result[$key]["createDate"] = $result[$key]["createDate"]->format("Y-m-d H:i:s");
- }
-
- foreach ($result as $key => $item) {
- $dql = "SELECT pr.name FROM de\RaumZeitLabor\PartKeepr\Project\Project pr JOIN pr.parts ppart WHERE ppart.part = :part";
-
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("part", $item["id"]);
-
- $projectNames = array();
- foreach ($query->getArrayResult() as $project) {
- $projectNames[] = $project["name"];
- }
-
- $result[$key]["projects"] = implode(", ", $projectNames);
-
- }
-
- foreach ($result as $key => $item) {
- $part = Part::loadById($item["id"]);
- $result[$key]["attachments"] = $part->serializeChildren($part->getAttachments());
- }
-
- return $result;
- }
-
- public function addOrUpdatePart ($aParameters) {
-
- if (!array_key_exists("quantity", $aParameters)) {
- $aParameters["quantity"] = 0;
- }
-
- if ($aParameters["part"] !== null) {
- try {
- $part = $this->getPart($aParameters["part"]);
- } catch (\Exception $e) {
- $part = new Part();
- $user = SessionManager::getCurrentSession()->getUser();
-
- $stock = new StockEntry($part, $aParameters["quantity"], $user);
- PartKeepr::getEM()->persist($stock);
- }
- } else {
- $part = new Part();
-
- $user = SessionManager::getCurrentSession()->getUser();
-
- $stock = new StockEntry($part, $aParameters["quantity"], $user);
- PartKeepr::getEM()->persist($stock);
- }
-
- if (array_key_exists("name", $aParameters)) {
- $part->setName($aParameters["name"]);
- }
-
- if (array_key_exists("description", $aParameters)) {
- $part->setDescription($aParameters["description"]);
- }
-
- if (array_key_exists("minstock", $aParameters)) {
- $part->setMinStockLevel($aParameters["minstock"]);
- }
-
- if (array_key_exists("comment", $aParameters)) {
- $part->setComment($aParameters["comment"]);
- }
-
- if (array_key_exists("footprint", $aParameters)) {
-
- if ($aParameters["footprint"] === null) {
- $part->setFootprint(null);
- } else {
- $footprint = FootprintManager::getInstance()->getOrCreateFootprint($aParameters["footprint"]);
- $part->setFootprint($footprint);
- }
- }
-
- if (array_key_exists("storagelocation", $aParameters)) {
- $storageLocation = StorageLocationManager::getInstance()->getOrCreateStorageLocation($aParameters["storagelocation"]);
- $part->setStorageLocation($storageLocation);
- }
-
- if (array_key_exists("category", $aParameters)) {
- $category = PartCategoryManager::getInstance()->getCategory($aParameters["category"]);
- $part->setCategory($category->getNode());
- }
-
- /* Process linked changes */
- if (array_key_exists("distributorChanges", $aParameters)) {
- if (is_array($aParameters["distributorChanges"])) {
- $this->processDistributorChanges($part, $aParameters["distributorChanges"]);
- }
- }
-
- if (array_key_exists("manufacturerChanges", $aParameters)) {
- if (is_array($aParameters["manufacturerChanges"])) {
- $this->processManufacturerChanges($part, $aParameters["manufacturerChanges"]);
- }
- }
-
- if (array_key_exists("parameterChanges", $aParameters)) {
- if (is_array($aParameters["parameterChanges"])) {
- $this->processParameterChanges($part, $aParameters["parameterChanges"]);
- }
- }
-
- if (array_key_exists("attachmentChanges", $aParameters)) {
- if (is_array($aParameters["attachmentChanges"])) {
- $this->processAttachmentChanges($part, $aParameters["attachmentChanges"]);
- }
- }
-
- if (array_key_exists("partUnit", $aParameters)) {
- if ($aParameters["partUnit"] === null || $aParameters["partUnit"] === 0) {
- $part->setPartUnit(null);
- } else {
- $part->setPartUnit(PartUnitManager::getInstance()->getPartUnit($aParameters["partUnit"]));
- }
- }
-
-
- PartKeepr::getEM()->persist($part);
- PartKeepr::getEM()->flush();
-
- }
-
- private function processParameterChanges (Part $part, Array $data) {
- if (array_key_exists("updates", $data)) {
- foreach ($data["updates"] as $record) {
- foreach ($part->getParameters() as $partParameter) {
- if ($partParameter->getId() == $record["id"]) {
- $partParameter->setName($record["name"]);
- $partParameter->setDescription($record["description"]);
- $partParameter->setValue($record["value"]);
- $partParameter->setSiPrefix(SiPrefix::loadById($record["siprefix_id"]));
- $partParameter->setUnit(Unit::loadById($record["unit_id"]));
- break;
- }
- }
- }
- }
-
- if (array_key_exists("removals", $data)) {
- foreach ($data["removals"] as $record) {
- foreach ($part->getParameters() as $partParameter) {
- if ($partParameter->getId() == $record["id"]) {
- PartKeepr::getEM()->remove($partParameter);
- $part->getParameters()->removeElement($partParameter);
- break;
- }
- }
- }
- }
-
- if (array_key_exists("inserts", $data)) {
- foreach ($data["inserts"] as $record) {
- $partParameter = new PartParameter();
- $partParameter->setPart($part);
-
- $partParameter->setName($record["name"]);
- $partParameter->setDescription($record["description"]);
- $partParameter->setValue($record["value"]);
- $partParameter->setSiPrefix(SiPrefix::loadById($record["siprefix_id"]));
- $partParameter->setUnit(Unit::loadById($record["unit_id"]));
-
- $part->getParameters()->add($partParameter);
- }
- }
- }
-
- private function processDistributorChanges (Part $part, Array $data) {
- if (array_key_exists("updates", $data)) {
- foreach ($data["updates"] as $record) {
- foreach ($part->getDistributors() as $partDistributor) {
- if ($partDistributor->getId() == $record["id"]) {
- $partDistributor->setOrderNumber($record["orderNumber"]);
- $partDistributor->setDistributor(Distributor::loadById($record["distributor_id"]));
- $partDistributor->setPackagingUnit($record["packagingUnit"]);
- break;
- }
- }
- }
- }
-
- if (array_key_exists("removals", $data)) {
- foreach ($data["removals"] as $record) {
- foreach ($part->getDistributors() as $partDistributor) {
- if ($partDistributor->getId() == $record["id"]) {
- PartKeepr::getEM()->remove($partDistributor);
- $part->getDistributors()->removeElement($partDistributor);
- break;
- }
- }
- }
- }
-
- if (array_key_exists("inserts", $data)) {
- foreach ($data["inserts"] as $record) {
- $distributor = new PartDistributor($part, Distributor::loadById($record["distributor_id"]));
- $distributor->setOrderNumber($record["orderNumber"]);
- $distributor->setPackagingUnit($record["packagingUnit"]);
-
- $part->getDistributors()->add($distributor);
- }
- }
- }
-
- private function processManufacturerChanges (Part $part, Array $data) {
- if (array_key_exists("updates", $data)) {
- foreach ($data["updates"] as $record) {
- foreach ($part->getManufacturers() as $partManufacturer) {
- if ($partManufacturer->getId() == $record["id"]) {
- $partManufacturer->setPartNumber($record["partNumber"]);
- $partManufacturer->setManufacturer(Manufacturer::loadById($record["manufacturer_id"]));
- break;
- }
- }
- }
- }
-
- if (array_key_exists("removals", $data)) {
- foreach ($data["removals"] as $record) {
- foreach ($part->getManufacturers() as $partManufacturer) {
- if ($partManufacturer->getId() == $record["id"]) {
- PartKeepr::getEM()->remove($partManufacturer);
- $part->getManufacturers()->removeElement($partManufacturer);
- break;
- }
- }
- }
- }
-
- if (array_key_exists("inserts", $data)) {
- foreach ($data["inserts"] as $record) {
- $manufacturer = new PartManufacturer($part, Manufacturer::loadById($record["manufacturer_id"]));
- $manufacturer->setPartNumber($record["partNumber"]);
-
- $part->getManufacturers()->add($manufacturer);
- }
- }
- }
-
- private function processAttachmentChanges (Part $part, Array $data) {
- if (array_key_exists("updates", $data)) {
- foreach ($data["updates"] as $record) {
- foreach ($part->getAttachments() as $partAttachment) {
- if ($partAttachment->getId() == $record["id"]) {
- $partAttachment->setDescription($record["description"]);
- break;
- }
- }
- }
- }
-
- if (array_key_exists("removals", $data)) {
- foreach ($data["removals"] as $record) {
- foreach ($part->getAttachments() as $partAttachment) {
- if ($partAttachment->getId() == $record["id"]) {
- PartKeepr::getEM()->remove($partAttachment);
- $part->getAttachments()->removeElement($partAttachment);
- break;
- }
- }
- }
- }
-
- if (array_key_exists("inserts", $data)) {
- foreach ($data["inserts"] as $record) {
- $attachment = new PartAttachment();
- $attachment->setPart($part);
- $attachment->setDescription($record["description"]);
-
- $file = TempUploadedFile::loadById($record["tmp_id"]);
-
- $attachment->replace($file->getFilename());
- $attachment->setOriginalFilename($file->getOriginalFilename());
-
- $part->getAttachments()->add($attachment);
- }
- }
- }
-
- public function deletePart ($id) {
- $part = PartManager::getInstance()->getPart($id);
-
- PartKeepr::getEM()->remove($part);
- PartKeepr::getEM()->flush();
- }
-
- public function getPart ($id) {
- $part = PartKeepr::getEM()->find("de\RaumZeitLabor\PartKeepr\Part\Part", $id);
-
- return $part;
- }
-
- /**
- * Returns the overall part count currently existing.
- * @param boolean $withPrice Only consider parts with a price
- * @return int The amount of parts in the database
- */
- public function getPartCount ($withPrice = false) {
- $dql = "SELECT COUNT(p.id) FROM de\RaumZeitLabor\PartKeepr\Part\Part p";
-
- if ($withPrice === true) {
- $dql .= " WHERE p.averagePrice IS NOT NULL";
- }
-
- return PartKeepr::getEM()->createQuery($dql)->getSingleScalarResult();
- }
-
- /**
- * Returns the total price for all parts. Only parts with a price are calculated.
- * @return float The total price
- */
- public function getTotalPrice () {
- $dql = "SELECT SUM(p.averagePrice * p.stockLevel) FROM de\RaumZeitLabor\PartKeepr\Part\Part p";
-
- return PartKeepr::getEM()->createQuery($dql)->getSingleScalarResult();
- }
-
- /**
- * Returns the average price for all parts. Only parts with a price are calculated.
- * @return float The average price
- */
- public function getAveragePrice () {
- $dql = "SELECT AVG(p.averagePrice) FROM de\RaumZeitLabor\PartKeepr\Part\Part p";
-
- return PartKeepr::getEM()->createQuery($dql)->getSingleScalarResult();
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartManufacturer.php b/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartManufacturer.php
@@ -1,106 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Part;
-
-use de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer;
-
-/** @Entity **/
-class PartManufacturer extends BaseEntity implements Serializable, Deserializable {
- /**
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Part\Part")
- */
- private $part;
-
- /**
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer")
- */
- private $manufacturer;
-
- /**
- * @Column(type="string",nullable=true)
- * Enter description here ...
- * @var unknown_type
- */
- private $partNumber;
-
- /**
- * Sets the part which belongs to this manufacturer entry
- * @param Part $part
- */
- public function setPart (Part $part) {
- $this->part = $part;
- }
-
- /**
- * Returns the part which belongs to this manufacturer entry
- */
- public function getPart () {
- return $this->part;
- }
-
- /**
- * Sets the manufacturer which belongs to this entry
- * @param Manufacturer $manufacturer
- */
- public function setManufacturer (Manufacturer $manufacturer) {
- $this->manufacturer = $manufacturer;
- }
-
- /**
- * Returns the manufacturer which belongs to this part
- */
- public function getManufacturer () {
- return $this->manufacturer;
- }
-
- /**
- * Sets the manufacturer-specific part number
- * @param string $partNumber
- */
- public function setPartNumber ($partNumber) {
- $this->partNumber = $partNumber;
- }
-
- /**
- * Returns the manufacturer-specific part number
- * @return string The part number
- */
- public function getPartNumber () {
- return $this->partNumber;
- }
-
- /**
- * Returns the data of this object in a serialized form.
- * @return array The result array
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "partNumber" => $this->getPartNumber(),
- "manufacturer_id" => $this->getManufacturer()->getId(),
- "manufacturer_name" => $this->getManufacturer()->getName(),
- "part_id" => $this->getPart()->getId(),
- "part_name" => $this->getPart()->getName());
- }
-
- /**
- * Deserializes the part manufacturer
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "manufacturer_id":
- $manufacturer = Manufacturer::loadById($value);
- $this->setManufacturer($manufacturer);
- break;
- case "partNumber":
- $this->setPartNumber($value);
- break;
- }
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartService.php
@@ -1,258 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Part;
-
-use de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\Manager\ManagerFilter,
- de\RaumZeitLabor\PartKeepr\Part\PartManager,
- de\RaumZeitLabor\PartKeepr\Stock\StockEntry,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\PartCategory\PartCategory,
- de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class PartService extends Service implements RestfulService {
- public function get () {
- if ($this->hasParameter("id")) {
- return array("data" => PartManager::getInstance()->getPart($this->getParameter("id"))->serialize());
- } else {
-
- $filter = new ManagerFilter($this);
- $filter->setFilterCallback(array($this, "filterCallback"));
-
- return PartManager::getInstance()->getList($filter);
- }
- }
-
- /**
- * Advanced filtering for the list
- * @param QueryBuilder The $queryBuilder
- */
- public function filterCallback ($queryBuilder) {
-
- /**
- * Applies text-based filtering
- */
- if ($this->hasParameter("query") && $this->getParameter("query") != "") {
-
- $fulltextSearch = new PartFulltextSearch($this->getParameter("query"));
- $fulltextSearchResults = $fulltextSearch->query();
-
- $queryBuilder->andWhere("q.id IN (".implode(",", $fulltextSearchResults).")");
-
- }
-
- /**
- * Applies filtering by the storage location name
- */
- if ($this->getParameter("storageLocation") !== null) {
- $queryBuilder->andWhere("st.name = :storageLocation");
- $queryBuilder->setParameter("storageLocation", $this->getParameter("storageLocation"));
- }
-
- /**
- * Filter by the category id and set the category mode
- *
- */
- $category = intval($this->getParameter("category", 0));
-
- if ($category !== 0) {
- /* Fetch all children */
- if ($this->getParameter("categoryScope") == "selected") {
- $queryBuilder->andWhere("q.category = :category");
- $queryBuilder->setParameter("category", $category);
- } else {
- $childs = PartCategoryManager::getInstance()->getChildNodes($category);
- $childs[] = $category;
- $queryBuilder->andWhere("q.category IN (".implode(",", $childs).")");
- }
- }
-
- /**
- * Filter by the stock mode
- */
- switch ($this->getParameter("stockMode")) {
- case "all":
- break;
- case "zero":
- $queryBuilder->andWhere("q.stockLevel = 0");
- break;
- case "nonzero":
- $queryBuilder->andWhere("q.stockLevel > 0");
- break;
- case "below":
- $queryBuilder->andWhere("q.stockLevel < q.minStockLevel");
- break;
- }
-
- /**
- * Query by the distributor's order number
- */
- if ($this->getParameter("distributorOrderNumber")) {
- $queryBuilder->leftJoin("q.distributors", "di");
- $queryBuilder->andWhere("LOWER(di.orderNumber) LIKE :orderNumber");
- $queryBuilder->setParameter("orderNumber", "%".strtolower($this->getParameter("distributorOrderNumber"))."%");
- }
-
- /**
- * Filter by the price
- */
- if ($this->getParameter("withoutPrice") === true || $this->getParameter("withoutPrice") === "true") {
- $queryBuilder->andWhere("q.averagePrice IS NULL");
- }
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::create()
- */
- public function create () {
- $entity = PartManager::getInstance()->createEntity($this->getParameters());
-
- if ($this->getParameter("initialStockLevel") > 0) {
- try {
- $user = User::loadById($this->getParameter("initialStockLevelUser"));
- } catch (\Exception $e) {
- $user = SessionManager::getCurrentSession()->getUser();
- }
-
- $stock = new StockEntry($entity, intval($this->getParameter("initialStockLevel")), $user);
-
- if ($this->getParameter("initialStockLevelPricePerItem") == true) {
- $price = floatval($this->getParameter("initialStockLevelPrice"));
- } else {
- $price = floatval($this->getParameter("initialStockLevelPrice")) / $this->getParameter("initialStockLevel");
- }
-
- if ($price != 0) {
- $stock->setPrice($price);
- }
-
- PartKeepr::getEM()->persist($stock);
- PartKeepr::getEM()->flush();
-
- $entity->updateStockLevel();
- PartKeepr::getEM()->flush();
- }
-
- return array("data" => $entity->serialize());
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update()
- */
- public function update () {
- $entity = PartManager::getInstance()->getEntity($this->getParameter("id"));
- $entity->deserialize($this->getParameters());
-
- PartKeepr::getEM()->flush();
-
- return array("data" => $entity->serialize());
- }
-
-
- public function destroy () {
- throw new \Exception("Not yet implemented");
- }
-
- public function getPartParameterNames () {
- $dql = "SELECT pp.name FROM de\RaumZeitLabor\PartKeepr\PartParameter\PartParameter pp GROUP BY pp.name";
- $query = PartKeepr::getEM()->createQuery($dql);
-
- return array("data" => $query->getArrayResult());
- }
-
- public function movePart () {
- $this->requireParameter("targetCategory");
-
- if ($this->getParameter("parts", false) !== false) {
- /* We are moving multiple parts */
- foreach ($this->getParameter("parts") as $part) {
- $part = Part::loadById($part);
- $category = PartCategory::loadById($this->getParameter("targetCategory"));
-
- $part->setCategory($category);
- }
- } else {
- $part = Part::loadById($this->getParameter("part"));
- $category = PartCategory::loadById($this->getParameter("targetCategory"));
-
- $part->setCategory($category);
-
- }
-
- PartKeepr::getEM()->flush();
- }
-
- public function addStock () {
- $part = PartManager::getInstance()->getPart($this->getParameter("part"));
-
- $user = SessionManager::getCurrentSession()->getUser();
-
- $stock = new StockEntry($part, intval($this->getParameter("stock")), $user);
-
- $price = floatval($this->getParameter("price"));
-
- if ($price != 0) {
- $stock->setPrice($price);
- }
-
- PartKeepr::getEM()->persist($stock);
- PartKeepr::getEM()->flush();
-
- $part->updateStockLevel();
-
- PartKeepr::getEM()->flush();
-
- return array("data" => $part->serialize());
- }
-
- public function deleteStock () {
- $part = PartManager::getInstance()->getPart($this->getParameter("part"));
-
- $user = SessionManager::getCurrentSession()->getUser();
-
- $stock = new StockEntry($part, 0-intval($this->getParameter("stock")), $user);
-
- PartKeepr::getEM()->persist($stock);
- PartKeepr::getEM()->flush();
-
- $part->updateStockLevel();
-
- PartKeepr::getEM()->flush();
-
- return array("data" => $part->serialize());
- }
-
- public function massDeleteStock () {
- $data = $this->getParameter("removals");
-
- $updateStockLevels = array();
-
- foreach ($data as $item) {
- $part = PartManager::getInstance()->getPart($item["part"]);
- $user = SessionManager::getCurrentSession()->getUser();
-
- $stock = new StockEntry($part, 0-intval($item["amount"]), $user);
- $stock->setComment($item["comment"]);
- PartKeepr::getEM()->persist($stock);
-
- $updateStockLevels[$item["part"]] = $part;
- }
-
- PartKeepr::getEM()->flush();
-
- foreach ($updateStockLevels as $part) {
- $part->updateStockLevel();
- }
-
- PartKeepr::getEM()->flush();
- return array();
- }
-
- public function deletePart () {
- PartManager::getInstance()->deletePart($this->getParameter("part"));
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartUnit.php b/src/backend/de/RaumZeitLabor/PartKeepr/Part/PartUnit.php
@@ -1,137 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Part;
-
-use de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Util\Exceptions\OutOfRangeException;
-
-
-/** @Entity **/
-class PartUnit extends BaseEntity implements Serializable, Deserializable {
- /**
- * Defines the name of the unit
- * @Column
- * @var string
- */
- private $name;
-
- /**
- * Defines the short name of the unit
- * @Column
- * @var string
- */
- private $shortName;
-
- /**
- * Defines if the unit is default or not.
- *
- * @Column(type="boolean")
- * @var boolean
- */
- private $is_default;
-
- /**
- * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\Part\Part",mappedBy="partUnit")
- */
- private $parts;
-
-
- /**
- * Creates a new part unit.
- *
- * Sets the default to false.
- */
- public function __construct () {
- $this->setDefault(false);
- }
-
- /**
- * Sets the name for this unit
- * @param string $name The name for this unit
- * @return nothing
- */
- public function setName ($name) {
- $this->name = $name;
- }
-
- /**
- * Returns the name for this unit
- * @param none
- * @return string The name for this unit
- */
- public function getName () {
- return $this->name;
- }
-
- /**
- * Sets the short name for this unit.
- *
- * Short names are used for list views (e.g. if your unit name is "metres", your short name could be "m")
- * @param string $shortName The short name
- * @return nothing
- */
- public function setShortName ($shortName) {
- $this->shortName = $shortName;
- }
-
- /**
- * Returns the short name for this unit
- * @param none
- * @return string The short name for this unit
- */
- public function getShortName () {
- return $this->shortName;
- }
-
- /**
- * Defines if the unit is default or not.
- * @param boolean $default True if the unit is default, false otherwise
- */
- public function setDefault ($default) {
- $this->is_default = (bool)$default;
- }
-
- /**
- * Returns if the unit is default or not
- * @param none
- * @return boolean True if the unit is default, false for not
- */
- public function getDefault () {
- return $this->is_default;
- }
-
- /**
- * Serializes the object and returns it as array, suitable
- * to process via json_encode.
- * @param none
- * @return array An array containing the object information
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "name" => $this->getName(),
- "shortName" => $this->getShortName(),
- "default" => $this->getDefault()
- );
- }
-
- /**
- * Deserializes the manufacturer
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "name":
- $this->setName($value);
- break;
- case "shortName":
- $this->setShortName($value);
- break;
- }
- }
- }
-}
- -
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/PartCategory/PartCategory.php b/src/backend/de/RaumZeitLabor/PartKeepr/PartCategory/PartCategory.php
@@ -1,14 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\PartCategory;
-
-use de\RaumZeitLabor\PartKeepr\Category\AbstractCategory;
-
-/**
- * @Entity
- * @Table(indexes={@index(columns={"lft"}),@index(columns={"rgt"})})
- * The entity for our part categories
- *
- */
-class PartCategory extends AbstractCategory {
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/PartCategory/PartCategoryManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/PartCategory/PartCategoryManager.php
@@ -1,42 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\PartCategory;
-
-use de\RaumZeitLabor\PartKeepr\Category\AbstractCategoryManager;
-use DoctrineExtensions\NestedSet\NodeWrapper;
-use de\RaumZeitLabor\PartKeepr\Util\SerializableException;
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class PartCategoryManager extends AbstractCategoryManager {
- protected $categoryClass = "de\RaumZeitLabor\PartKeepr\PartCategory\PartCategory";
-
- /**
- * Deletes the given category ID.
- * @param $id int The category id to delete
- * @throws CategoryNotFoundException If the category wasn't found
- */
- public function deleteCategory ($id) {
- $category = $this->getCategory($id);
-
- try {
-
- if ($category->hasChildren()) {
- $exception = new SerializableException(sprintf(PartKeepr::i18n("Category '%s' contains other categories."), $category->getNode()->getName()));
- $exception->setDetail(sprintf(PartKeepr::i18n("You tried to delete the category '%s', but it still contains other categories. Please move the categories or delete them first."), $category->getNode()->getName()));
-
- throw $exception;
- }
-
- parent::deleteCategory($id);
- } catch (\PDOException $e) {
- if ($e->getCode() == "23000") {
- $exception = new SerializableException(sprintf(PartKeepr::i18n("Category '%s' contains parts."), $category->getNode()->getName()));
- $exception->setDetail(sprintf(PartKeepr::i18n("You tried to delete the category '%s', but it still contains parts. Please move the parts to another category."), $category->getNode()->getName()));
-
- throw $exception;
- } else {
- throw $e;
- }
- }
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/PartCategory/PartCategoryService.php b/src/backend/de/RaumZeitLabor/PartKeepr/PartCategory/PartCategoryService.php
@@ -1,9 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\PartCategory;
-
-use de\RaumZeitLabor\PartKeepr\Category\AbstractCategoryService;
-
-class PartCategoryService extends AbstractCategoryService {
- protected $categoryManagerClass = "de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager";
- protected $categoryClass = "de\RaumZeitLabor\PartKeepr\PartCategory\PartCategory";
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/PartDistributor/PartDistributorManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/PartDistributor/PartDistributorManager.php
@@ -1,74 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\PartDistributor;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Manufacturer\Exceptions\ManufacturerNotFoundException;
-
-class PartDistributorManager extends Singleton {
- public function getPartDistributors ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
-
- $qb = PartKeepr::getEM()->createQueryBuilder();
- $qb->select("pd.orderNumber, part.id AS part_id, dist.id AS distributor_id")->from("de\RaumZeitLabor\PartKeepr\Part\PartDistributor","pd")
- ->leftJoin('pd.distributor', "dist")
- ->leftJoin("pd.part", "part");
-
- /*if ($filter != "") {
- $manufacturer = Manufacturer::loadById($filter);
- $qb = $qb->where("st.manufacturer = :manufacturer");
- $qb->setParameter("manufacturer", $manufacturer);
- }*/
-
- if ($limit > -1) {
- $qb->setMaxResults($limit);
- $qb->setFirstResult($start);
- }
-
- $qb->orderBy("pd.".$sort, $dir);
-
- $query = $qb->getQuery();
-
- $result = $query->getResult();
-
- $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
- $totalQueryBuilder->select("COUNT(pd.id)")->from("de\RaumZeitLabor\PartKeepr\Part\PartDistributor","pd");
-
-
- /*
- if ($filter != "") {
- $totalQueryBuilder = $totalQueryBuilder->where("st.manufacturer = :manufacturer");
- $totalQueryBuilder->setParameter("manufacturer", $manufacturer);
- }*/
-
- $totalQuery = $totalQueryBuilder->getQuery();
-
- return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
- }
-
- public function getPartDistributor ($id) {
- $partDistributor = PartKeepr::getEM()->find("de\RaumZeitLabor\PartKeepr\Part\PartDistributor", $id);
-
- if ($partDistributor) {
- return $partDistributor;
- } else {
- throw new PartDistributorNotFoundException();
- }
- }
-
- public function addPartDistributor ($orderNumber) {
- $partDistributor = new PartDistributor();
- $partDistributor->setName($orderNumber);
-
- PartKeepr::getEM()->persist($partDistributor);
- PartKeepr::getEM()->flush();
-
- return $partDistributor;
- }
- public function deletePartDistributor ($id) {
- $manufacturer = $this->getManufacturer($id);
-
- PartKeepr::getEM()->remove($manufacturer);
- PartKeepr::getEM()->flush();
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/PartDistributor/PartDistributorService.php b/src/backend/de/RaumZeitLabor/PartKeepr/PartDistributor/PartDistributorService.php
@@ -1,84 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\ManufacturerICLogo;
-
-use de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerICLogo,
- de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class PartDistributorService extends Service implements RestfulService {
- public function get () {
- if ($this->hasParameter("id")) {
- return PartDistributorManager::getInstance()->getManufacturerICLogo($this->getParameter("id"))->serialize();
- } else {
- if ($this->hasParameter("sort")) {
- $tmp = json_decode($this->getParameter("sort"), true);
-
- $aSortParams = $tmp[0];
- } else {
- $aSortParams = array(
- "property" => "id",
- "direction" => "ASC");
- }
-
- $filter = "";
-
- if ($this->hasParameter("filter")) {
- $tmp = json_decode($this->getParameter("filter"), true);
-
- foreach ($tmp as $item) {
- if (array_key_exists("property", $item)) {
- if ($item["property"] == "manufacturer_id") {
- if (array_key_exists("value", $item)) {
- $filter = $item["value"];
- }
- }
- }
- }
- }
- // @todo This seems wrong?!?
- return ManufacturerICLogoManager::getInstance()->getManufacturerICLogos(
- $this->getParameter("start", $this->getParameter("start", 0)),
- $this->getParameter("limit", $this->getParameter("limit", 25)),
- $this->getParameter("sortby", $aSortParams["property"]),
- $this->getParameter("dir", $aSortParams["direction"]),
- $filter);
- }
- }
-
- public function create () {
- $this->requireParameter("tmp_id");
- $this->requireParameter("manufacturer_id");
-
- $tmpImage = TempImage::loadById($this->getParameter("tmp_id"));
-
- $image = new ManufacturerICLogo();
-
- $manufacturer = Manufacturer::loadById($this->getParameter("manufacturer_id"));
-
- $image->setManufacturer($manufacturer);
- $image->replace($tmpImage->getFilename());
- PartKeepr::getEM()->persist($image);
- PartKeepr::getEM()->flush();
-
- return $image->serialize();
- }
-
- public function update () {
-
- }
-
- public function destroy () {
- $this->requireParameter("id");
-
- $logo = ManufacturerICLogo::loadById($this->getParameter("id"));
-
- PartKeepr::getEM()->remove($logo);
- PartKeepr::getEM()->flush();
-
- return array("data" => null);
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php b/src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php
@@ -1,434 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr;
-
-use Doctrine\Common\ClassLoader,
- de\RaumZeitLabor\PartKeepr\SystemNotice\SystemNoticeManager,
- Doctrine\ORM\Configuration,
- Doctrine\ORM\EntityManager,
- de\RaumZeitLabor\PartKeepr\Util\Configuration as PartKeeprConfiguration;
-
-
-
-class PartKeepr {
- /**
- *
- * Contains the doctrine entity manager.
- * @var Doctrine\ORM\EntityManager
- */
- private static $entityManager = null;
-
- /**
- * Initializes the PartKeepr system
- *
- * You *need* to call this method before doing anything else.
- *
- * An environment is used to load a different configuration file.
- * Usually, you don't need to pass anything here.
- *
- * @param $environment string The environment to use, null otherwise.
- * @return nothing
- */
- public static function initialize ($environment = null) {
- self::initializeClassLoaders();
- self::initializeConfig($environment);
- self::initializeDoctrine();
- }
-
- /**
- * Initializes the doctrine class loader and sets up the
- * directories.
- *
- * @param none
- * @return nothing
- */
- public static function initializeClassLoaders() {
- require_once 'Doctrine/Common/ClassLoader.php';
-
-
- $classLoader = new ClassLoader('de\RaumZeitLabor\PartKeepr', dirname(dirname(dirname(__DIR__))));
- $classLoader->register();
-
- $classLoader = new ClassLoader('Doctrine\ORM');
- $classLoader->register();
-
- $classLoader = new ClassLoader("Doctrine\DBAL\Migrations", dirname(dirname(dirname(dirname(dirname(__DIR__))))) ."/3rdparty/doctrine-migrations/lib");
- $classLoader->register();
-
- $classLoader = new ClassLoader('Doctrine\DBAL');
- $classLoader->register();
-
- $classLoader = new ClassLoader('Doctrine\Common');
- $classLoader->register();
-
- $classLoader = new ClassLoader('Symfony', 'Doctrine');
- $classLoader->register();
-
- $classLoader = new ClassLoader("DoctrineExtensions\NestedSet", dirname(dirname(dirname(dirname(dirname(__DIR__))))) ."/3rdparty/doctrine2-nestedset/lib");
- $classLoader->register();
-
-
- }
-
- /**
- * Returns an array of all cronjobs which are required for proper execution of PartKeepr.
- *
- * @return Array The filenames of each cronjob which is required
- */
- public static function getRequiredCronjobs () {
- return array(
- "CreateStatisticSnapshot.php",
- "UpdatePartCacheData.php",
- "UpdateTipsOfTheDay.php",
- "CheckForUpdates.php"
- );
- }
-
- /**
- * Initializes the configuration for a given environment.
- *
- * An environment is used to load a different configuration file.
- *
- * Usually, you don't need to pass anything here.
- *
- *
- * @param $environment string The environment to use, null otherwise.
- * @return nothing
- */
- public static function initializeConfig ($environment = null) {
- if ($environment != null) {
- include(dirname(dirname(dirname(dirname(dirname(__DIR__)))))."/config-$environment.php");
- } else {
- include(dirname(dirname(dirname(dirname(dirname(__DIR__)))))."/config.php");
- }
-
- // Check if the files path is set. If not, fall back to <partkeepr-root>/data/
- if (PartKeeprConfiguration::getOption("partkeepr.files.path", null) === null) {
-
- PartKeeprConfiguration::setOption("partkeepr.files.path",
- PartKeepr::getRootDirectory() . "/data/");
- }
-
- // Check if the image path is set. If not, fall back to <configured-files-directory>/images/
- if (PartKeeprConfiguration::getOption("partkeepr.images.path", null) === null) {
-
- PartKeeprConfiguration::setOption("partkeepr.images.path",
- PartKeeprConfiguration::getOption("partkeepr.files.path") . "images/");
- }
-
- // Check if the image cache path is set. If not, fall back to <configured-images-directory>/images/
- if (PartKeeprConfiguration::getOption("partkeepr.images.cache", null) === null) {
-
- PartKeeprConfiguration::setOption("partkeepr.images.cache",
- PartKeeprConfiguration::getOption("partkeepr.images.path") . "cache/");
-
- }
-
- }
-
- /**
- * Checks against the versions at partkeepr.org.
- *
- * If a newer version was found, create a system notice entry.
- */
- public static function doVersionCheck () {
-
- $data = file_get_contents("http://www.partkeepr.org/versions.json");
- $versions = json_decode($data, true);
-
- if (PartKeeprVersion::PARTKEEPR_VERSION == "{V_GIT}") { return; }
-
- if (version_compare(PartKeepr::getVersion(), $versions[0]["version"], '<')) {
-
- SystemNoticeManager::getInstance()->createUniqueSystemNotice(
- "PARTKEEPR_VERSION_".$versions[0]["version"],
- sprintf(PartKeepr::i18n("New PartKeepr Version %s available"), $versions[0]["version"]),
- sprintf(PartKeepr::i18n("PartKeepr Version %s changelog:"), $versions[0]["version"]) . "\n\n".
- $versions[0]["changelog"]
- );
-
- }
- }
-
- /**
- * Initializes the doctrine framework and
- * sets all required configuration options.
- *
- * @param none
- * @return nothing
- */
- public static function initializeDoctrine () {
- $config = new Configuration;
-
- $driverImpl = $config->newDefaultAnnotationDriver(
- array(__DIR__)
- );
- $config->setMetadataDriverImpl($driverImpl);
-
- $connectionOptions = PartKeepr::createConnectionOptionsFromConfig();
-
- if (extension_loaded("apc")) {
- $cache = new \Doctrine\Common\Cache\ApcCache();
- } else {
- $cache = new \Doctrine\Common\Cache\ArrayCache();
- }
-
- $config->setMetadataCacheImpl($cache);
-
- $config->setQueryCacheImpl($cache);
-
- $config->setProxyDir(dirname(dirname(dirname(dirname(dirname(__DIR__))))) . '/data/proxies');
- $config->setProxyNamespace('Proxies');
- $config->setEntityNamespaces(self::getEntityClasses());
- $config->setAutoGenerateProxyClasses(false);
-
- if (PartKeeprConfiguration::getOption("partkeepr.database.echo_sql_log", false) === true) {
- $logger = new \Doctrine\DBAL\Logging\EchoSQLLogger();
- $config->setSQLLogger($logger);
- }
-
- self::$entityManager = EntityManager::create($connectionOptions, $config);
- }
-
- public static function createConnectionOptionsFromConfig () {
- $connectionOptions = array();
-
- $driver = PartKeeprConfiguration::getOption("partkeepr.database.driver");
-
- switch ($driver) {
- case "pdo_mysql":
- case "pdo_pgsql":
- case "pdo_oci":
- case "oci8":
- case "pdo_sqlsrv":
- $connectionOptions["driver"] = $driver;
- $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["charset"] = "utf8";
- /**
- * Compatibility with older configuration files. We check for the key "hostname" as well as "host".
- */
- if (PartKeeprConfiguration::getOption("partkeepr.database.hostname", null) !== null) {
- $connectionOptions["host"] = PartKeeprConfiguration::getOption("partkeepr.database.hostname");
- } else {
- $connectionOptions["host"] = PartKeeprConfiguration::getOption("partkeepr.database.host", "localhost");
- }
-
-
- if (PartKeeprConfiguration::getOption("partkeepr.database.port") !== null) {
- $connectionOptions["port"] = PartKeeprConfiguration::getOption("partkeepr.database.port");
- }
-
- if (PartKeeprConfiguration::getOption("partkeepr.database.mysql_socket", null) !== null) {
- $connectionOptions["unix_socket"] = PartKeeprConfiguration::getOption("partkeepr.database.mysql_socket");
- }
- break;
- case "pdo_sqlite":
- $connectionOptions["driver"] = $driver;
- $connectionOptions["user"] = PartKeeprConfiguration::getOption("partkeepr.database.username", "partkeepr");
- $connectionOptions["password"] = PartKeeprConfiguration::getOption("partkeepr.database.password", "partkeepr");
- $connectionOptions["path"] = PartKeeprConfiguration::getOption("partkeepr.database.sqlite_path", PartKeepr::getRootDirectory() . "/data/partkeepr.sqlite");
- break;
- default:
- throw new \Exception(sprintf("Unknown driver %s", $driver));
- }
-
- return $connectionOptions;
- }
-
- /**
- * Returns the EntityManager. Shortcut for getEntityManager().
- * @return \Doctrine\ORM\EntityManager The EntityManager
- */
- public static function getEM () {
- return self::getEntityManager();
- }
-
- public static function getRootDirectory () {
- return dirname(dirname(dirname(dirname(dirname(__DIR__)))));
- }
-
- /**
- * Returns the EntityManager.
- * @return Doctrine\ORM\EntityManager The EntityManager
- */
- public static function getEntityManager () {
- if (!self::$entityManager instanceof EntityManager) {
- throw new Exception("No EntityManager found. Make sure you called initializeDoctrine() or initialize().");
- }
- return self::$entityManager;
- }
-
- /**
- * Returns the class metadata for all entity classes
- * @return array an array of class metadata objects
- */
- public static function getClassMetaData () {
- $classes = self::getEntityClasses();
-
- $aClasses = array();
-
- foreach ($classes as $class) {
- $aClasses[] = PartKeepr::getEM()->getClassMetadata($class);
- }
-
- return $aClasses;
- }
-
- /**
- * Returns a list of all classes we use for entities.
- * @return array An array of strings with all class names
- */
- public static function getEntityClasses () {
- return array(
- 'de\RaumZeitLabor\PartKeepr\User\User',
- 'de\RaumZeitLabor\PartKeepr\Session\Session',
-
- 'de\RaumZeitLabor\PartKeepr\Footprint\Footprint',
- 'de\RaumZeitLabor\PartKeepr\Footprint\FootprintImage',
- 'de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment',
- 'de\RaumZeitLabor\PartKeepr\FootprintCategory\FootprintCategory',
-
- 'de\RaumZeitLabor\PartKeepr\Part\Part',
- 'de\RaumZeitLabor\PartKeepr\Part\PartUnit',
- 'de\RaumZeitLabor\PartKeepr\Part\PartManufacturer',
- 'de\RaumZeitLabor\PartKeepr\Part\PartDistributor',
- 'de\RaumZeitLabor\PartKeepr\Part\PartImage',
- 'de\RaumZeitLabor\PartKeepr\Part\PartAttachment',
- 'de\RaumZeitLabor\PartKeepr\PartCategory\PartCategory',
-
- 'de\RaumZeitLabor\PartKeepr\Project\Project',
- 'de\RaumZeitLabor\PartKeepr\Project\ProjectPart',
- 'de\RaumZeitLabor\PartKeepr\Project\ProjectAttachment',
-
- 'de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation',
- 'de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocationImage',
-
- 'de\RaumZeitLabor\PartKeepr\Stock\StockEntry',
-
- 'de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer',
- 'de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerICLogo',
-
- 'de\RaumZeitLabor\PartKeepr\Distributor\Distributor',
-
- 'de\RaumZeitLabor\PartKeepr\Image\Image',
- 'de\RaumZeitLabor\PartKeepr\Image\CachedImage',
- 'de\RaumZeitLabor\PartKeepr\TempImage\TempImage',
-
- 'de\RaumZeitLabor\PartKeepr\UploadedFile\TempUploadedFile',
-
- 'de\RaumZeitLabor\PartKeepr\Statistic\StatisticSnapshot',
- 'de\RaumZeitLabor\PartKeepr\Statistic\StatisticSnapshotUnit',
- 'de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefix',
- 'de\RaumZeitLabor\PartKeepr\Unit\Unit',
- 'de\RaumZeitLabor\PartKeepr\PartParameter\PartParameter',
-
- 'de\RaumZeitLabor\PartKeepr\TipOfTheDay\TipOfTheDay',
- 'de\RaumZeitLabor\PartKeepr\TipOfTheDay\TipOfTheDayHistory',
- 'de\RaumZeitLabor\PartKeepr\UserPreference\UserPreference',
- 'de\RaumZeitLabor\PartKeepr\SystemNotice\SystemNotice',
- 'de\RaumZeitLabor\PartKeepr\CronLogger\CronLogger'
-
- );
- }
-
- /**
- * Formats a message and applies internationalization.
- *
- * This method accepts sprintf-like parameters, which are appended after the $string parameter.
- *
- * @param $string string The string to internationalize
- * @todo stub
- */
- public static function i18n ($string) {
- if (func_num_args() > 1) {
- $args = func_get_args();
- array_shift($args);
-
- return vsprintf($string, $args);
- } else {
- return $string;
- }
- }
-
- /**
- * Returns a new GUID.
- * @return string The new GUID
- */
- public static function createGUIDv4() {
- return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
-
- // 32 bits for "time_low"
- mt_rand(0, 0xffff), mt_rand(0, 0xffff),
-
- // 16 bits for "time_mid"
- mt_rand(0, 0xffff),
-
- // 16 bits for "time_hi_and_version",
- // four most significant bits holds version number 4
- mt_rand(0, 0x0fff) | 0x4000,
-
- // 16 bits, 8 bits for "clk_seq_hi_res",
- // 8 bits for "clk_seq_low",
- // two most significant bits holds zero and one for variant DCE1.1
- mt_rand(0, 0x3fff) | 0x8000,
-
- // 48 bits for "node"
- mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
- );
- }
-
- /**
- * Returns the current PartKeepr version.
- * @return string The PartKeepr Version
- */
- public static function getVersion () {
- if (PartKeeprVersion::PARTKEEPR_VERSION == "{V_GIT}") {
- return "GIT development version";
- }
- return PartKeeprVersion::PARTKEEPR_VERSION;
- }
-
- /**
- * This is a re-implementation of gettype().
- *
- * The PHP documentation states that the "gettype" return values will change in the future, so we need
- * to make sure we don't get bitten by the change.
- *
- * @param mixed $var
- * @return string The type
- */
- public static function getType($var)
- {
- if (is_array($var)) return "array";
- if (is_bool($var)) return "boolean";
- if (is_float($var)) return "float";
- if (is_int($var)) return "integer";
- if (is_null($var)) return "NULL";
- if (is_numeric($var)) return "numeric";
- if (is_object($var)) return "object";
- if (is_resource($var)) return "resource";
- if (is_string($var)) return "string";
- return "unknown type";
- }
-
- /**
- * Returns the effective size from a human-readable byte format.
- *
- * Example:
- * getBytesFromHumanReadable("1M") will return 1048576.
- *
- * @param string $size_str The byte
- * @return int The bytes
- */
- public static function getBytesFromHumanReadable ($size_str)
- {
- switch (substr ($size_str, -1))
- {
- case 'M': case 'm': return (int)$size_str * 1048576;
- case 'K': case 'k': return (int)$size_str * 1024;
- case 'G': case 'g': return (int)$size_str * 1073741824;
- default: return $size_str;
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/PartKeeprVersion.php b/src/backend/de/RaumZeitLabor/PartKeepr/PartKeeprVersion.php
@@ -1,15 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr;
-
-class PartKeeprVersion {
- /**
- * Holds the PartKeepr Version.
- *
- * If {V_GIT}, then the function will return 'GIT Development Version'.
- * {V_GIT} will be replaced by the build script with the actual version.
- *
- * The reason why we have a separate class for the version constant is that
- * we can easily replace it from scripts.
- */
- const PARTKEEPR_VERSION = '{V_GIT}';
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/PartParameter/PartParameter.php b/src/backend/de/RaumZeitLabor/PartKeepr/PartParameter/PartParameter.php
@@ -1,247 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\PartParameter;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
-de\RaumZeitLabor\PartKeepr\Util\Exceptions\OutOfRangeException,
-de\RaumZeitLabor\PartKeepr\Unit\Unit,
-de\RaumZeitLabor\PartKeepr\Part\Part,
-de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefix;
-
-
-/**
- * This object represents a parameter. Each parameter can have an unit (defined by the class "Unit") associated with
- * a numeric value.
- *
- * @Entity @HasLifecycleCallbacks
- **/
-class PartParameter {
- /**
- * @Id @Column(type="integer")
- * @GeneratedValue(strategy="AUTO")
- * @var integer
- */
- private $id;
-
- /**
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Part\Part")
- * The part this parameter is bound to
- * @var Part
- */
- private $part;
-
- /**
- * The name of the parameter (e.g. Resistance, Voltage)
- * @Column(type="string")
- * @var string
- */
- private $name;
-
- /**
- * A description for this parameter
- * @Column(type="string")
- * @var string
- */
- private $description;
-
- /**
- * The unit for this type. May be null.
- *
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Unit\Unit")
- * @var Unit
- */
- private $unit;
-
- /**
- * The value of the unit. Together with the prefix, it becomes the actual value.
- *
- * Example: If you have 10µ, the value field will contain "10", the prefix object is linked to the SiPrefix
- * representing "µ" and the rawValue field will contain 0.000001
- * @Column(type="float")
- * @var float
- */
- private $value;
-
- /**
- * The SiPrefix of the unit
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefix")
- * @var object
- */
- private $siPrefix;
-
- /**
- * The raw value of the unit.
- * @Column(type="float")
- * @var float
- */
- private $rawValue;
-
- /**
- * Sets the name for this parameter
- * @param string $name The name
- */
- public function setName ($name) {
- $this->name = $name;
- }
-
- /**
- * Returns the name for this parameter
- * @return string The name for this parameter
- */
- public function getName () {
- return $this->name;
- }
-
- /**
- * Sets the description for this parameter
- * @param string $description The description
- */
- public function setDescription ($description) {
- $this->description = $description;
- }
-
- /**
- * Returns the description
- * @return string The description
- */
- public function getDescription () {
- return $this->description;
- }
-
- /**
- * Sets the unit
- * @param Unit $unit The unit to set
- */
- public function setUnit (Unit $unit = null) {
- $this->unit = $unit;
- }
-
- /**
- * Returns the unit
- * @return Unit the unit
- */
- public function getUnit () {
- return $this->unit;
- }
-
- /**
- * Sets the part
- * @param Part $part The part to set
- */
- public function setPart (Part $part) {
- $this->part = $part;
- }
-
- /**
- * Returns the part
- * @return Part the part
- */
- public function getPart () {
- return $this->part;
- }
-
- /**
- * Sets the value
- * @param float $value The value to set
- */
- public function setValue ($value) {
- $this->value = $value;
-
- $this->recalculateRawValue();
- }
-
- /**
- * Returns the value
- * @return float The value
- */
- public function getValue () {
- return $this->value;
- }
-
- /**
- * Sets the si prefix for this parameter
- * @param SiPrefix $prefix The prefix to set, or null
- */
- public function setSiPrefix (SiPrefix $prefix = null) {
- $this->siPrefix = $prefix;
-
- $this->recalculateRawValue();
- }
-
- /**
- * Returns the si prefix for this parameter
- * @return SiPrefix the si prefix or null
- */
- public function getSiPrefix () {
- return $this->siPrefix;
- }
-
- /**
- * Returns the ID for this object.
- * @param none
- * @return int The ID for this object
- */
- public function getId () {
- return $this->id;
- }
-
- private function recalculateRawValue () {
- if (is_object($this->getSiPrefix())) {
- $power = $this->getSiPrefix()->getPower();
- } else {
- $power = 0;
- }
-
- $this->rawValue = $this->getValue() * pow(10, $power);
- }
-
- /**
- * Returns the data of this object in a serialized form.
- * @return array The result array
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "name" => $this->getName(),
- "description" => $this->getDescription(),
- "value" => $this->getValue(),
- "part_id" => $this->getPart()->getId(),
- "siprefix_id" => is_object($this->getSiPrefix()) ? $this->getSiPrefix()->getId() : null,
- "prefixedValue" => array(
- /* We duplicate most data because of strange ExtJS stuff... */
- "value" => $this->getValue(),
- "power" => is_object($this->getSiPrefix()) ? $this->getSiPrefix()->getPower() : 0,
- "symbol" => is_object($this->getSiPrefix()) ? $this->getSiPrefix()->getSymbol() : "",
- "siprefix_id" => is_object($this->getSiPrefix()) ? $this->getSiPrefix()->getId() : null
- ),
- "unit_id" => is_object($this->getUnit()) ? $this->getUnit()->getId() : null
- );
- }
-
- /**
- * Deserializes the part parameter
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "name":
- $this->setName($value);
- break;
- case "description":
- $this->setDescription($value);
- break;
- case "value":
- $this->setValue($value);
- break;
- case "siprefix_id":
- $prefix = SiPrefix::loadById($value);
- $this->setSiPrefix($prefix);
- break;
- case "unit_id":
- $unit = Unit::loadById($value);
- $this->setUnit($unit);
- break;
- }
- }
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/PartUnit/PartUnitManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/PartUnit/PartUnitManager.php
@@ -1,106 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\PartUnit;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\Part\PartUnit,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Category\CategoryManager,
- de\RaumZeitLabor\PartKeepr\PartUnit\Exceptions\PartUnitNotFoundException;
-
-class PartUnitManager extends Singleton {
- public function getPartUnits ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
-
- $qb = PartKeepr::getEM()->createQueryBuilder();
- $qb->select("st.id, st.name, st.shortName, st.is_default AS default")->from("de\RaumZeitLabor\PartKeepr\Part\PartUnit","st");
-
- if ($filter != "") {
- $qb = $qb->where("LOWER(st.name) LIKE :filter");
- $qb->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- if ($limit > -1) {
- $qb->setMaxResults($limit);
- $qb->setFirstResult($start);
- }
-
- $qb->orderBy("st.".$sort, $dir);
-
- $query = $qb->getQuery();
-
- $result = $query->getResult();
-
- foreach ($result as $key => $row) {
- foreach ($row as $rowkey => $column) {
- if ($rowkey == "default") {
- if ($column == 0) {
- $result[$key][$rowkey] = false;
- } else {
- $result[$key][$rowkey] = true;
- }
- }
- }
- }
-
- $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
- $totalQueryBuilder->select("COUNT(st.id)")->from("de\RaumZeitLabor\PartKeepr\Part\PartUnit","st");
-
-
-
- if ($filter != "") {
- $totalQueryBuilder = $totalQueryBuilder->where("LOWER(st.name) LIKE :filter");
- $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- $totalQuery = $totalQueryBuilder->getQuery();
-
- return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
- }
-
- public function getPartUnit ($id) {
- $partUnit = PartKeepr::getEM()->find("de\RaumZeitLabor\PartKeepr\Part\PartUnit", $id);
-
- if ($partUnit) {
- return $partUnit;
- } else {
- throw new PartUnitNotFoundException();
- }
- }
-
- public function deletePartUnit ($id) {
- $partUnit = $this->getPartUnit($id);
-
- PartKeepr::getEM()->remove($partUnit);
- 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 = :default';
- return PartKeepr::getEM()->createQuery($dql)->setParameter("default", true)->getSingleResult();
- }
-
- public function setDefaultPartUnit ($id) {
- PartKeepr::getEM()->beginTransaction();
-
- $dql = 'UPDATE de\RaumZeitLabor\PartKeepr\Part\PartUnit pu SET pu.is_default = :default WHERE pu.id = :id';
- PartKeepr::getEM()->createQuery($dql)->setParameter("id", $id)->setParameter("default", true, \PDO::PARAM_BOOL)->execute();
-
- $dql = 'UPDATE de\RaumZeitLabor\PartKeepr\Part\PartUnit pu SET pu.is_default = :default WHERE pu.id != :id';
- PartKeepr::getEM()->createQuery($dql)->setParameter("id", $id)->setParameter("default", false, \PDO::PARAM_BOOL)->execute();
-
- PartKeepr::getEM()->commit();
- }
-
- public function getUnitCounts () {
- $dql = 'SELECT SUM(p.stockLevel) AS stockLevel, pu.id AS puid FROM de\RaumZeitLabor\PartKeepr\Part\PartUnit pu LEFT JOIN pu.parts p GROUP BY pu.id';
-
- $result = PartKeepr::getEM()->createQuery($dql)->getResult();
-
- return $result;
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/PartUnit/PartUnitService.php b/src/backend/de/RaumZeitLabor/PartKeepr/PartUnit/PartUnitService.php
@@ -1,72 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\PartUnit;
-use de\RaumZeitLabor\PartKeepr\Service\RestfulService;
-
-use de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Part\PartUnit,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class PartUnitService extends Service implements RestfulService {
- public function get () {
- if ($this->hasParameter("id")) {
- return array("data" => PartUnitManager::getInstance()->getPartUnit($this->getParameter("id"))->serialize());
- } else {
- if ($this->hasParameter("sort")) {
- $tmp = json_decode($this->getParameter("sort"), true);
-
- $aSortParams = $tmp[0];
- } else {
- $aSortParams = array(
- "property" => "name",
- "direction" => "ASC");
- }
- return PartUnitManager::getInstance()->getPartUnits(
- $this->getParameter("start", $this->getParameter("start", 0)),
- $this->getParameter("limit", $this->getParameter("limit", 25)),
- $this->getParameter("sortby", $aSortParams["property"]),
- $this->getParameter("dir", $aSortParams["direction"]),
- $this->getParameter("query", ""));
- }
- }
-
- public function create () {
- $this->requireParameter("name");
-
- $partUnit = new PartUnit;
- $partUnit->deserialize($this->getParameters());
-
- PartKeepr::getEM()->persist($partUnit);
- PartKeepr::getEM()->flush();
-
- return array("data" => $partUnit->serialize());
- }
-
- public function update () {
- $this->requireParameter("id");
- $this->requireParameter("name");
-
- $partUnit = PartUnitManager::getInstance()->getPartUnit($this->getParameter("id"));
- $partUnit->deserialize($this->getParameters());
- PartKeepr::getEM()->flush();
-
- return array("data" => $partUnit->serialize());
-
- }
-
- public function destroy () {
- $this->requireParameter("id");
-
- PartUnitManager::getInstance()->deletePartUnit($this->getParameter("id"));
-
- return array("data" => null);
- }
-
- public function setDefault () {
- $this->requireParameter("id");
-
- $partUnit = PartUnitManager::getInstance()->setDefaultPartUnit($this->getParameter("id"));
-
- return array("data" => null);
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Ping/PingService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Ping/PingService.php
@@ -1,19 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Ping;
-use de\RaumZeitLabor\PartKeepr\Service\AnonService;
-
-use de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class PingService extends AnonService {
- /**
- * Simple test call to verify if the service layer is reachable.
- *
- * This is used for the PartKeeprMobile client to verify if the URL
- * is entered correctly.
- */
- public function ping () {
- return "pong";
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Project/Project.php b/src/backend/de/RaumZeitLabor/PartKeepr/Project/Project.php
@@ -1,161 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Project;
-
-use de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity;
-
-/**
- * Represents a part in the database. The heart of our project. Handle with care!
- * @Entity **/
-class Project extends BaseEntity implements Serializable, Deserializable {
- /**
- * Specifies the name of the project
- * @Column(type="string")
- */
- private $name;
-
- /**
- * Specifies the user this project belongs to
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\User\User")
- */
- private $user;
-
- /**
- * Holds the parts needed for this project
- * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\Project\ProjectPart",mappedBy="project",cascade={"persist", "remove"})
- * @var ArrayCollection
- */
- private $parts;
-
- /**
- * Holds the description of this project
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $description;
-
- /**
- * Holds the project attachments
- * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\Project\ProjectAttachment",mappedBy="project",cascade={"persist", "remove"})
- * @var ProjectAttachment
- */
- private $attachments;
-
-
- /**
- * Constructs a new project
- */
- public function __construct () {
- $this->parts = new \Doctrine\Common\Collections\ArrayCollection();
- $this->attachments = new \Doctrine\Common\Collections\ArrayCollection();
- }
-
- /**
- * Sets the user for this project
- * @param User $user
- */
- public function setUser (User $user) {
- $this->user = $user;
- }
-
- /**
- * Gets the user for this project
- * @return User
- */
- public function getUser () {
- return $this->user;
- }
-
- /**
- * Sets the name for this project
- * @param string $name
- */
- public function setName ($name) {
- $this->name = $name;
- }
-
- /**
- * Returns the name of this project
- */
- public function getName () {
- return $this->name;
- }
-
- /**
- * Sets the description of this project
- * @param string $description The description to set
- */
- public function setDescription ($description) {
- $this->description = $description;
- }
-
- /**
- * Returns the description of this project
- * @return string The description
- */
- public function getDescription () {
- return $this->description;
- }
-
- /**
- * Returns the parts array
- * @return ArrayCollection An array of ProjectPart objects
- */
- public function getParts () {
- return $this->parts;
- }
-
- /**
- * Returns the attachments for this project
- * @return ArrayCollection The attachments
- */
- public function getAttachments () {
- return $this->attachments;
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Util.Serializable::serialize()
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "name" => $this->getName(),
- "description" => $this->getDescription(),
- "parts" => $this->serializeChildren($this->getParts()),
- "attachments" => $this->serializeChildren($this->getAttachments())
- );
- }
-
- /**
- * Deserializes the project
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "name":
- $this->setName($value);
- break;
- case "description":
- $this->setDescription($value);
- break;
- case "parts":
- $this->deserializeChildren($value, $this->getParts(), "de\RaumZeitLabor\PartKeepr\Project\ProjectPart");
- foreach ($this->getParts() as $part) {
- $part->setProject($this);
- }
- break;
- case "attachments":
- $this->deserializeChildren($value, $this->getAttachments(), "de\RaumZeitLabor\PartKeepr\Project\ProjectAttachment");
- foreach ($this->getAttachments() as $attachment) {
- $attachment->setProject($this);
- }
- break;
- }
- }
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Project/ProjectAttachment.php b/src/backend/de/RaumZeitLabor/PartKeepr/Project/ProjectAttachment.php
@@ -1,101 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Project;
-
-use de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\UploadedFile\UploadedFile;
-
-/**
- * Holds a project attachment
- * @Entity
- **/
-class ProjectAttachment extends UploadedFile implements Serializable, Deserializable {
- /**
- * The description of this attachment
- * @Column(type="text")
- * @var string
- */
- private $description;
-
- /**
- * Creates a new project attachment
- */
- public function __construct () {
- parent::__construct();
- $this->setType("ProjectAttachment");
- }
- /**
- * The project object
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Project\Project")
- * @var Project
- */
- private $project = null;
-
- /**
- * Sets the project
- * @param Project $project The project to set
- */
- public function setProject (Project $project) {
- $this->project = $project;
- }
-
- /**
- * Returns the roject
- * @return Project the project
- */
- public function getProject () {
- return $this->project;
- }
-
- /**
- * Sets the description for this attachment
- * @param string $description The attachment description
- */
- public function setDescription ($description) {
- $this->description = $description;
- }
-
- /**
- * Returns the description for this attachment
- * @return string The description
- */
- public function getDescription () {
- return $this->description;
- }
-
- /**
- *
- * Serializes this project attachment
- * @return array The serialized project attachment
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "project_id" => $this->getProject()->getId(),
- "originalFilename" => $this->getOriginalFilename(),
- "mimetype" => $this->getMimetype(),
- "extension" => $this->getExtension(),
- "size" => $this->getSize(),
- "description" => $this->getDescription());
- }
-
- /**
- * Deserializes the project attachment
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- if (array_key_exists("id", $parameters)) {
- if (substr($parameters["id"], 0, 4) === "TMP:") {
- $this->replaceFromTemporaryFile($parameters["id"]);
- }
- }
-
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "description":
- $this->setDescription($value);
- break;
- }
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Project/ProjectManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Project/ProjectManager.php
@@ -1,33 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Project;
-
-use de\RaumZeitLabor\PartKeepr\Manager\AbstractManager,
- de\RaumZeitLabor\PartKeepr\Project\Project,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class ProjectManager extends AbstractManager {
- /**
- * Returns the FQCN for the target entity to operate on.
- * @return string The FQCN, e.g. de\RaumZeitLabor\PartKeepr\Part
- */
- public function getEntityName () {
- return 'de\RaumZeitLabor\PartKeepr\Project\Project';
- }
-
- /**
- * Returns all fields which need to appear in the getList ResultSet.
- * @return array An array of all fields which should be returned
- */
- public function getQueryFields () {
- return array("id", "name", "description");
- }
-
- /**
- * Returns the default sort field
- *
- * @return string The default sort field
- */
- public function getDefaultSortField () {
- return "name";
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Project/ProjectPart.php b/src/backend/de/RaumZeitLabor/PartKeepr/Project/ProjectPart.php
@@ -1,136 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Project;
-
-use de\RaumZeitLabor\PartKeepr\Part\Part,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity;
-
-/**
- * Represents a part in the database. The heart of our project. Handle with care!
- * @Entity **/
-class ProjectPart extends BaseEntity implements Serializable, Deserializable {
- /**
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Part\Part")
- */
- private $part;
-
- /**
- * Specifies the amount of parts
- * @Column(type="integer")
- */
- private $quantity;
-
- /**
- * Specifies the project which belongs to this project part
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Project\Project")
- */
- private $project;
-
- /**
- * Specifies the remarks for this entry
- * @Column(type="string",nullable=true)
- */
- private $remarks;
-
- /**
- * Sets the part which belongs to this entry
- * @param Part $part
- */
- public function setPart (Part $part) {
- $this->part = $part;
- }
-
- /**
- * Returns the part which belongs to this entry
- * @return Part
- */
- public function getPart () {
- return $this->part;
- }
-
- /**
- * Sets the quantity for this entry
- * @param int $quantity
- */
- public function setQuantity ($quantity) {
- $this->quantity = intval($quantity);
- }
-
- /**
- * Returns the quantity for this project
- * @return int the amount of parts needed
- */
- public function getQuantity () {
- return $this->quantity;
- }
-
- /**
- * Sets the project assigned to this entry
- * @param Project $project
- */
- public function setProject (Project $project) {
- $this->project = $project;
- }
-
- /**
- * Returns the project assigned to this entry
- * @return Project
- */
- public function getProject () {
- return $this->project;
- }
-
- /**
- * Sets the remarks for this entry
- * @param string $remarks
- */
- public function setRemarks ($remarks) {
- $this->remarks = $remarks;
- }
-
- /**
- * Returns the remarks for this entry
- * @return string
- */
- public function getRemarks () {
- return $this->remarks;
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Util.Serializable::serialize()
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "quantity" => $this->getQuantity(),
- "part_id" => is_object($this->getPart()) ? $this->getPart()->getId() : 0,
- "part_name" => is_object($this->getPart()) ? $this->getPart()->getName() : 0,
- "project_id" => $this->getProject()->getId(),
- "remarks" => $this->getRemarks()
- );
- }
-
- /**
- * Deserializes the project
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "remarks":
- $this->setRemarks($value);
- break;
- case "quantity":
- $this->setQuantity($value);
- break;
- case "part_id":
- $part = Part::loadById($value);
- $this->setPart($part);
- break;
- }
- }
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Project/ProjectService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Project/ProjectService.php
@@ -1,64 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Project;
-
-use de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\Project\ProjectManager,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Manager\ManagerFilter;
-
-class ProjectService extends Service implements RestfulService {
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
- */
- public function get () {
- if ($this->hasParameter("id")) {
- return array("data" => ProjectManager::getInstance()->getEntity($this->getParameter("id"))->serialize());
- } else {
- $parameters = new ManagerFilter($this);
- $parameters->setFilterField("name");
- return ProjectManager::getInstance()->getList($parameters);
- }
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::create()
- */
- public function create () {
- $this->requireParameter("name");
-
- $entity = ProjectManager::getInstance()->createEntity($this->getParameters());
-
- return array("data" => $entity->serialize());
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update()
- */
- public function update () {
- $this->requireParameter("id");
- $this->requireParameter("name");
- $entity = ProjectManager::getInstance()->getEntity($this->getParameter("id"));
- $entity->deserialize($this->getParameters());
-
- PartKeepr::getEM()->flush();
-
- return array("data" => $entity->serialize());
-
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::destroy()
- */
- public function destroy () {
- $this->requireParameter("id");
-
- ProjectManager::getInstance()->deleteEntity($this->getParameter("id"));
-
- return array("data" => null);
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/ProjectAttachment/ProjectAttachmentManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/ProjectAttachment/ProjectAttachmentManager.php
@@ -1,68 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\ProjectAttachment;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\Project\Project,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class ProjectAttachmentManager extends Singleton {
- /**
- * Returns a list of project attachments
- *
- * @param int $start Start of the list, default 0
- * @param int $limit Number of users to list, default 10
- * @param string $sort The field to sort by, default "name"
- * @param string $dir The direction to sort (ASC or DESC), default ASC
- * @param string $filter The project id
- */
- public function getProjectAttachments ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
-
- $qb = PartKeepr::getEM()->createQueryBuilder();
- $qb->select("st")->from("de\RaumZeitLabor\PartKeepr\Project\ProjectAttachment","st")
- ->leftJoin('st.project', "fp");
-
- if ($filter != "") {
- $project = Project::loadById($filter);
- $qb = $qb->where("st.project = :project");
- $qb->setParameter("project", $project);
- }
-
- if ($limit > -1) {
- $qb->setMaxResults($limit);
- $qb->setFirstResult($start);
- }
-
- $qb->orderBy("st.".$sort, $dir);
-
- $query = $qb->getQuery();
-
- $result = $query->getResult();
-
- $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
- $totalQueryBuilder->select("COUNT(st.id)")->from("de\RaumZeitLabor\PartKeepr\Project\ProjectAttachment","st");
-
-
-
- if ($filter != "") {
- $totalQueryBuilder = $totalQueryBuilder->where("st.project = :project");
- $totalQueryBuilder->setParameter("project", $project);
- }
-
- $totalQuery = $totalQueryBuilder->getQuery();
-
- $aData = array();
- foreach ($result as $item) {
- $aData[] = $item->serialize();
- }
- return array("data" => $aData, "totalCount" => $totalQuery->getSingleScalarResult());
- }
-
- /**
- * Returns a project attachment by id
- * @param int $id The project attachment id
- */
- public function getProjectAttachment ($id) {
- return ProjectAttachment::loadById($id);
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/ProjectAttachment/ProjectAttachmentService.php b/src/backend/de/RaumZeitLabor/PartKeepr/ProjectAttachment/ProjectAttachmentService.php
@@ -1,102 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\ProjectAttachment;
-
-use de\RaumZeitLabor\PartKeepr\Project\ProjectAttachment,
- de\RaumZeitLabor\PartKeepr\UploadedFile\TempUploadedFile,
- de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Project\Project,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class ProjectAttachmentService extends Service implements RestfulService {
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
- */
- public function get () {
- if ($this->hasParameter("id")) {
- return ProjectAttachmentManager::getInstance()->getProjectAttachment($this->getParameter("id"))->serialize();
- } else {
- if ($this->hasParameter("sort")) {
- $tmp = json_decode($this->getParameter("sort"), true);
-
- $aSortParams = $tmp[0];
- } else {
- $aSortParams = array(
- "property" => "id",
- "direction" => "ASC");
- }
-
- $filter = "";
-
- if ($this->hasParameter("filter")) {
- $tmp = json_decode($this->getParameter("filter"), true);
-
- foreach ($tmp as $item) {
- if (array_key_exists("property", $item)) {
- if ($item["property"] == "project_id") {
- if (array_key_exists("value", $item)) {
- $filter = $item["value"];
- }
- }
- }
- }
- }
- return ProjectAttachmentManager::getInstance()->getProjectAttachments(
- $this->getParameter("start", $this->getParameter("start", 0)),
- $this->getParameter("limit", $this->getParameter("limit", 25)),
- $this->getParameter("sortby", $aSortParams["property"]),
- $this->getParameter("dir", $aSortParams["direction"]),
- $filter);
- }
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::create()
- */
- public function create () {
- $this->requireParameter("tmp_id");
- $this->requireParameter("project_id");
-
- $tmpImage = TempUploadedFile::loadById($this->getParameter("tmp_id"));
-
- $file = new ProjectAttachment();
-
- $project = Project::loadById($this->getParameter("project_id"));
-
- $file->setProject($project);
- $file->replace($tmpImage->getFilename());
- $file->setOriginalFilename($tmpImage->getOriginalFilename());
- $file->setDescription($this->getParameter("description"));
- PartKeepr::getEM()->persist($file);
- PartKeepr::getEM()->flush();
-
- return $file->serialize();
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update()
- */
- public function update () {
-
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::destroy()
- */
- public function destroy () {
- $this->requireParameter("id");
-
- $file = ProjectAttachment::loadById($this->getParameter("id"));
-
- PartKeepr::getEM()->remove($file);
- PartKeepr::getEM()->flush();
-
- return array("data" => null);
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/ProjectReport/ProjectReportService.php b/src/backend/de/RaumZeitLabor/PartKeepr/ProjectReport/ProjectReportService.php
@@ -1,97 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\ProjectReport;
-
-use de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\Project\ProjectManager,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Part\Part,
- de\RaumZeitLabor\PartKeepr\Manager\ManagerFilter;
-
-class ProjectReportService extends Service implements RestfulService {
- /**
- * Returns a project report.
- *
- * The input format is an array with the following keys per entry:
- * - project: The project ID
- * - amount: Specifies how many copies of the project need to be reported
- *
- * The output format is an array which contains the following keys:
- * - quantity: The overall quantity of parts needed (for a specific part)
- * - part: The serialized part entity
- * - storageLocation_name: The storage location name
- * - available: The overall amount of available parts
- * - sum_order: Always set to 0 because calculation happens in the frontend
- *
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
- */
- public function get () {
- $reports = json_decode($this->getParameter("reports"), true);
-
- $aPartResults = array();
-
- // Loop over all reports and calculate the overall quantities
- foreach ($reports as $report) {
- $dql = "SELECT pp.quantity, pro.name AS projectname, pp.remarks, p.id FROM ";
- $dql .= "de\RaumZeitLabor\PartKeepr\Project\ProjectPart pp JOIN pp.part p ";
- $dql .= "JOIN pp.project pro WHERE pp.project = :project";
-
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("project", $report["project"]);
-
- foreach ($query->getArrayResult() as $result) {
- $part = Part::loadById($result["id"]);
-
- if (array_key_exists($result["id"], $aPartResults)) {
- // Only update the quantity of the part
- $aPartResults[$result["id"]]["quantity"] += $result["quantity"] * $report["amount"];
- $aPartResults[$result["id"]]["projects"][] = $result["projectname"];
-
- if ($result["remarks"] != "") {
- $aPartResults[$result["id"]]["remarks"][] = $result["projectname"]. ": " .$result["remarks"];
- }
- } else {
- // Create a full resultset
- $aPartResults[$result["id"]] = array(
- "quantity" => $result["quantity"] * $report["amount"],
- "part" => array("response" => array("totalCount" => 1, "data" => $part->serialize())),
- "storageLocation_name" => $part->getStorageLocation()->getName(),
- "available" => $part->getStockLevel(),
- "sum_order" => 0,
- "projects" => array($result["projectname"]),
- "remarks" => array()
- );
-
- if ($result["remarks"] != "") {
- $aPartResults[$result["id"]]["remarks"] = array($result["projectname"]. ": " .$result["remarks"]);
- }
- }
- }
- }
-
- $aFinalResult = array();
-
- // Iterate over all results and calculate how many parts are missing
- foreach ($aPartResults as $key => $partResult) {
- $missing = $partResult["quantity"] - $partResult["available"];
-
- if ($missing < 0) {
- $missing = 0;
- }
-
- $partResult["missing"] = $missing;
- $partResult["remarks"] = implode(", ", $partResult["remarks"]);
- $partResult["projects"] = implode(", ", $partResult["projects"]);
-
- $aFinalResult[] = $partResult;
- }
-
- return array("data" => $aFinalResult);
- }
-
- public function create () {}
-
- public function update () {}
-
- public function destroy () {}
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/REST/ApplicationController.php b/src/backend/de/RaumZeitLabor/PartKeepr/REST/ApplicationController.php
@@ -1,42 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\REST;
-
-// Class taken over from the Sencha example
-class ApplicationController {
- public $request, $id, $params;
-
- /**
- * dispatch
- * Dispatch request to appropriate controller-action by convention according to the HTTP method.
- */
- public function dispatch($request) {
- $this->request = $request;
- $this->id = $request->id;
- $this->params = $request->params;
-
- if ($request->isRestful()) {
- return $this->dispatchRestful();
- }
- if ($request->action) {
- return $this->{$request->action}();
- }
- }
-
- protected function dispatchRestful() {
- switch ($this->request->method) {
- case 'GET':
- return $this->view();
- break;
- case 'POST':
- return $this->create();
- break;
- case 'PUT':
- return $this->update();
- break;
- case 'DELETE':
- return $this->destroy();
- break;
- }
- }
-}
-
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/REST/Model.php b/src/backend/de/RaumZeitLabor/PartKeepr/REST/Model.php
@@ -1,71 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\REST;
-
-// Class taken over from the Sencha example
-class Model {
- public $id, $attributes;
- static function create($params) {
- $obj = new self(get_object_vars($params));
- $obj->save();
- return $obj;
- }
- static function find($id) {
- global $dbh;
- $found = null;
- foreach ($dbh->rs() as $rec) {
- if ($rec['id'] == $id) {
- $found = new self($rec);
- break;
- }
- }
- return $found;
- }
- static function update($id, $params) {
- global $dbh;
- $rec = self::find($id);
-
- if ($rec == null) {
- return $rec;
- }
- $rs = $dbh->rs();
-
- foreach ($rs as $idx => $row) {
- if ($row['id'] == $id) {
- $rec->attributes = array_merge($rec->attributes, get_object_vars($params));
- $dbh->update($idx, $rec->attributes);
- break;
- }
- }
- return $rec;
- }
- static function destroy($id) {
- global $dbh;
- $rec = null;
- $rs = $dbh->rs();
- foreach ($rs as $idx => $row) {
- if ($row['id'] == $id) {
- $rec = new self($dbh->destroy($idx));
- break;
- }
- }
- return $rec;
- }
- static function all() {
- global $dbh;
- return $dbh->rs();
- }
-
- public function __construct($params) {
- $this->id = isset($params['id']) ? $params['id'] : null;
- $this->attributes = $params;
- }
- public function save() {
- global $dbh;
- $this->attributes['id'] = $dbh->pk();
- $dbh->insert($this->attributes);
- }
- public function to_hash() {
- return $this->attributes;
- }
-}
-
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/REST/Request.php b/src/backend/de/RaumZeitLabor/PartKeepr/REST/Request.php
@@ -1,115 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\REST;
-
-// Class taken over from the Sencha example
-class Request {
- public $restful, $method, $controller, $action, $id, $params;
-
- public function __construct($params) {
- $this->restful = (isset($params["restful"])) ? $params["restful"] : false;
- $this->method = $_SERVER["REQUEST_METHOD"];
- $this->parseRequest();
- }
- public function isRestful() {
- return $this->restful;
- }
-
- public function getMethod () {
- return $this->method;
- }
-
- public function getParams () {
- if ($this->params === null) {
- $this->params = array();
- }
-
- if ($this->id !== null) {
- $this->params["id"] = $this->id;
- }
-
- $this->params = array_merge($_REQUEST, $this->params);
- return $this->params;
- }
-
- public function getService () {
- if ($this->controller == "") {
- $this->controller = $_REQUEST["service"];
- }
-
- $serviceName = $this->controller."Service";
- $namespace = 'de\RaumZeitLabor\PartKeepr\\';
- $cat = $this->controller . "\\";
- $fullName= $namespace . $cat . $serviceName;
-
- $class = new $fullName($this->getParams());
-
- return $class;
- }
-
- public function getAction () {
- return $this->action;
- }
-
- protected function parseRequest() {
- if ($this->method == 'PUT') { // <-- Have to jump through hoops to get PUT data
- $raw = '';
- $httpContent = fopen('php://input', 'r');
- while ($kb = fread($httpContent, 1024)) {
- $raw .= $kb;
- }
- fclose($httpContent);
- $params = array();
- parse_str($raw, $params);
-
- if (isset($params['data'])) {
- $this->params = json_decode($params['data'], true);
- } else {
- $params = json_decode($raw, true);
- $this->params = $params;
- }
- } else {
- // grab JSON data if there...
- $this->params = (isset($_REQUEST['data'])) ? json_decode($_REQUEST['data'], true) : null;
-
- if (isset($_REQUEST['data'])) {
- $this->params = json_decode($_REQUEST['data'], true);
- } else {
- $raw = '';
- $httpContent = fopen('php://input', 'r');
- while ($kb = fread($httpContent, 1024)) {
- $raw .= $kb;
- }
- $params = json_decode($raw, true);
- if ($params) {
- $this->params = $params;
- }
- }
-
- }
- // Quickndirty PATH_INFO parser
- if (isset($_SERVER["PATH_INFO"])){
- $cai = '/^\/([A-Za-z]+\w)\/([A-Za-z]+\w)\/([0-9]+)$/'; // /controller/action/id
- $ca = '/^\/([A-Za-z]+\w)\/([A-Za-z]+)$/'; // /controller/action
- $ci = '/^\/([A-Za-z]+\w)\/([0-9]+)$/'; // /controller/id
- $c = '/^\/([A-Za-z]+\w)$/'; // /controller
- $i = '/^\/([0-9]+)$/'; // /id
- $matches = array();
- if (preg_match($cai, $_SERVER["PATH_INFO"], $matches)) {
- $this->controller = $matches[1];
- $this->action = $matches[2];
- $this->id = $matches[3];
- } else if (preg_match($ca, $_SERVER["PATH_INFO"], $matches)) {
- $this->controller = $matches[1];
- $this->action = $matches[2];
- } else if (preg_match($ci, $_SERVER["PATH_INFO"], $matches)) {
- $this->controller = $matches[1];
- $this->id = $matches[2];
- } else if (preg_match($c, $_SERVER["PATH_INFO"], $matches)) {
- $this->controller = $matches[1];
- } else if (preg_match($i, $_SERVER["PATH_INFO"], $matches)) {
- $this->id = $matches[1];
- }
- }
- }
-}
-
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/REST/Response.php b/src/backend/de/RaumZeitLabor/PartKeepr/REST/Response.php
@@ -1,21 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\REST;
-
-// Class taken over from the Sencha example
-class Response {
- public $success, $data, $message, $errors, $tid, $trace;
-
- public function __construct($params = array()) {
- $this->success = isset($params["success"]) ? $params["success"] : false;
- $this->message = isset($params["message"]) ? $params["message"] : '';
- $this->data = isset($params["data"]) ? $params["data"] : array();
- }
-
- public function to_json() {
- return json_encode(array(
- 'success' => $this->success,
- 'message' => $this->message,
- 'data' => $this->data
- ));
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Service/AdminService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Service/AdminService.php
@@ -1,14 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Service;
-
-use de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class AdminService extends Service {
- public function mayCall ($call) {
- if (SessionManager::getCurrentSession()->getUser()->isAdmin()) {
- return true;
- } else {
- return false;
- }
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Service/AnonService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Service/AnonService.php
@@ -1,6 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Service;
-
-class AnonService extends Service {
-
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Service/Exceptions/ServiceException.php b/src/backend/de/RaumZeitLabor/PartKeepr/Service/Exceptions/ServiceException.php
@@ -1,6 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Service\Exceptions;
-
-use de\RaumZeitLabor\PartKeepr\Util\SerializableException;
-
-class ServiceException extends SerializableException {}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Service/RestfulService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Service/RestfulService.php
@@ -1,9 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Service;
-
-interface RestfulService {
- public function get ();
- public function create ();
- public function update ();
- public function destroy ();
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Service/Service.php b/src/backend/de/RaumZeitLabor/PartKeepr/Service/Service.php
@@ -1,110 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Service;
-
-use de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\Session\Session,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager,
- de\RaumZeitLabor\PartKeepr\Service\Exceptions\ServiceException;
-
-class Service {
- private $params;
-
- public function __construct (Array $params) {
- $this->params = $params;
- }
-
- public function mayCall ($call) {
- if (SessionManager::getCurrentSession()->getUser() === null) {
- return false;
- } else {
- /* @todo: Implement permission checking */
- return true;
- }
-
-
- }
-
- protected function requireParameter ($name) {
- if (!$this->hasParameter($name)) {
- throw new ServiceException(sprintf("Parameter %s is required.", $name));
- }
- }
-
- public function getParameter ($name, $default = null) {
- if (!$this->hasParameter($name)) {
- return $default;
- } else {
- return $this->params[$name];
- }
- }
-
- /**
- * Returns all parameters passed to the service
- * @return array An array with all parameters (key=>value format)
- */
- public function getParameters () {
- return $this->params;
- }
-
- /**
- * Returns the current user for this session
- *
- * @return User The user
- */
- public function getUser () {
- return SessionManager::getCurrentSession()->getUser();
- }
-
- /**
- * Checks if the environment has an active, logged in user.
- *
- * @param none
- * @return boolean True if a logged in user exists, false otherwise
- */
- public function hasUser () {
- if (!$this->hasSession()) {
- return false;
- }
-
- var_dump($this->getUser());
- if ($this->getUser() !== null) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Checks if there is an active session.
- *
- * @param none
- * @return boolean true if an active session exists, false otherwise
- */
- public function hasSession () {
- return SessionManager::hasSession();
- }
-
- public function hasParameter ($name) {
- if (array_key_exists($name, $this->params)) {
- return true;
- } else {
- return false;
- }
- }
-
- public function hasHeader ($name) {
- $targetName = "HTTP_".strtoupper($name);
-
- return array_key_exists($targetName, $_SERVER);
- }
-
- public function getHeader ($name) {
- $targetName = "HTTP_".strtoupper($name);
-
- if (array_key_exists($targetName, $_SERVER)) {
- return $_SERVER[$targetName];
- } else {
- throw new \Exception("Header ".$targetName." not found");
- }
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Service/ServiceManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Service/ServiceManager.php
@@ -1,126 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Service;
-
-use de\RaumZeitLabor\PartKeepr\Session\SessionManager,
- de\RaumZeitLabor\PartKeepr\Service\Exceptions\ServiceException,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\User\UserManager,
- de\RaumZeitLabor\PartKeepr\REST\Request;
-
-class ServiceManager {
-
- public static function sendHeaders () {
- header("Content-Type: text/html; charset=UTF-8");
- header("Cache-Control: no-cache, must-revalidate");
- header("Access-Control-Allow-Origin: *");
- header("Access-Control-Allow-Headers: lang,call,service,X-Requested-With,X-PartKeepr-Locale,X-PartKeepr-Name,X-PartKeepr-Call");
- }
-
- public static function call () {
-
- $request = new Request(array('restful' => true));
- $service = $request->getService();
-
- if ($service->hasHeader("call")) {
- $call = $service->getHeader("call");
- } elseif (array_key_exists("call", $_REQUEST) && $_REQUEST["call"] != "") {
- $call = $_REQUEST["call"];
- } elseif ($request->action != "") {
- $call = $request->action;
- } else {
- switch (strtoupper($request->getMethod())) {
- case "POST":
- $call = "create";
- break;
- case "GET":
- $call = "get";
- break;
- case "PUT":
- $call = "update";
- break;
- case "DELETE":
- $call = "destroy";
- break;
- default:
- $call = $request->getMethod();
- break;
- }
- }
-
- $allowCall = true;
-
- if (!is_subclass_of($service, "de\\RaumZeitLabor\\PartKeepr\\Service\\AnonService")) {
- $session = null;
- $sessionid = false;
-
- $sessionid = self::getSession($service);
-
-
- if ($sessionid === null)
- {
- $session = SessionManager::getInstance()->startSession();
- throw new ServiceException("You called a non-anonymous service, but did not pass the 'session' parameter.");
- } else {
- $session = SessionManager::getInstance()->resumeSession($sessionid);
- }
-
- if (!$service->mayCall($call)) {
- $allowCall = false;
- }
- }
-
- if (!$allowCall) {
- throw new ServiceException("Permission denied");
- }
-
- if (!method_exists($service, $call)) {
- throw new \Exception(sprintf("The service %s doesn't implement %s", get_class($service), $call));
- }
- $result = $service->$call();
-
- PartKeepr::getEM()->flush();
-
- return $result;
-
- }
-
- private static function getSession ($service) {
- if ($service->hasHeader("username") && $service->hasHeader("password") && !$service->hasHeader("session")) {
- return self::authenticateByUsername($service->getHeader("username"), $service->getHeader("password"));
- }
-
- if (array_key_exists("username", $_REQUEST) && array_key_exists("password", $_REQUEST) && !array_key_exists("session", $_REQUEST)) {
- return self::authenticateByUsername($_REQUEST["username"], $_REQUEST["password"]);
- }
-
- if ($service->hasHeader("session")) {
- return $service->getHeader("session");
- }
-
- if (array_key_exists("session", $_REQUEST)) {
- return $_REQUEST["session"];
- }
- }
-
- private static function authenticateByUsername ($username, $password) {
- /* Build a temporary user */
- $user = new User;
- $user->setRawUsername($username);
- $user->setHashedPassword($password);
-
- $authenticatedUser = UserManager::getInstance()->authenticate($user);
-
- if ($authenticatedUser !== false) {
- /* Start Session */
- $session = SessionManager::getInstance()->startSession($authenticatedUser);
-
- return $session->getSessionID();
- } else {
- throw new InvalidLoginDataException();
- }
- }
-
-}
-
-?>-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Session/Exceptions/SessionNotFoundException.php b/src/backend/de/RaumZeitLabor/PartKeepr/Session/Exceptions/SessionNotFoundException.php
@@ -1,10 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Session\Exceptions;
-
-use de\RaumZeitLabor\PartKeepr\Util\SerializableException;
-
-class SessionNotFoundException extends SerializableException {
- public function __construct ($id) {
- parent::__construct("The session with the id $id could not be found");
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Session/Session.php b/src/backend/de/RaumZeitLabor/PartKeepr/Session/Session.php
@@ -1,59 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Session;
-
-use de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/** @Entity */
-class Session {
-
- /** @Id @Column(type="integer")
- * @GeneratedValue(strategy="AUTO")
- */
- private $id;
-
- /** @Column(length=50) */
- private $sessionid;
-
- /**
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\User\User")
- */
- private $user;
-
- public function __construct () {
-
- }
-
- public function start () {
- session_start();
- session_regenerate_id();
- session_destroy();
- unset($_SESSION);
- session_start();
-
- $query = PartKeepr::getEM()->createQuery("DELETE FROM de\\RaumZeitLabor\\PartKeepr\\Session\\Session s WHERE s.sessionid = :session");
- $query->setParameter("session", session_id());
- $query->execute();
-
- $this->sessionid = session_id();
- }
-
- public function getSessionID () {
- return $this->sessionid;
- }
-
- public function resume () {
- session_id($this->sessionid);
- session_start();
- }
-
- public function getUser () {
- return $this->user;
- }
-
- public function setUser (User $user = null) {
- $this->user = $user;
- }
-
-}
-?>-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Session/SessionManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Session/SessionManager.php
@@ -1,68 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Session;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\Session\Exceptions\SessionNotFoundException,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class SessionManager extends Singleton {
- public static $currentSession = null;
-
- public static function getCurrentSession () {
- return self::$currentSession;
- }
-
- public static function hasSession () {
- if (self::$currentSession !== null) {
- return true;
- } else {
- return false;
- }
- }
-
- public function startSession (User $user = null) {
- if (is_object($user)) {
- try {
- $query = PartKeepr::getEM()->createQuery("SELECT s FROM de\\RaumZeitLabor\\PartKeepr\\Session\\Session s WHERE s.user = :user");
- $query->setParameter("user", $user);
- $query->execute();
-
- $session = $query->getSingleResult();
- $session->resume();
- } catch (\Exception $e) {
- $session = new Session;
- $session->setUser($user);
- $session->start();
- PartKeepr::getEM()->persist($session);
- }
- } else {
- $session = new Session;
- $session->setUser(null);
- $session->start();
- PartKeepr::getEM()->persist($session);
- }
-
- PartKeepr::getEM()->flush();
-
- self::$currentSession = $session;
-
- return $session;
- }
-
- public function resumeSession ($session) {
- $query = PartKeepr::getEM()->createQuery("SELECT s FROM de\\RaumZeitLabor\\PartKeepr\\Session\\Session s WHERE s.sessionid = :session");
- $query->setParameter("session", $session);
- $query->execute();
- try {
- self::$currentSession = $query->getSingleResult();
- return self::$currentSession;
- } catch (\Doctrine\ORM\NonUniqueResultException $e) {
- throw new \Exception("Fatal error: Multiple sessions with id $session found.");
- } catch (\Doctrine\ORM\NoResultException $e) {
- throw new SessionNotFoundException($session);
- }
-
- }
-}
-?>-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/AbstractSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/AbstractSetup.php
@@ -1,44 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Setup;
-
-use Doctrine\ORM\EntityManager;
-
-/**
- * Represents a basic setup step
- */
-abstract class AbstractSetup {
- private $console;
-
- /**
- * 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 setConsole ($console) {
- $this->console = $console;
- }
-
- public function logMessage ($message) {
- if ($this->console) {
- echo "- ".$message."\n";
- }
- $this->messages[] = $message;
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/ConfigFileSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/ConfigFileSetup.php
@@ -1,65 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Setup;
-
-use de\RaumZeitLabor\PartKeepr\Util\Configuration,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Util\SerializableException;
-
-/**
- * Creates or returns a new config file
- */
-class ConfigFileSetup extends AbstractSetup {
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Setup.AbstractSetup::run()
- */
- public function run () {
- switch ($_REQUEST["mode"]) {
- case "save":
- $this->saveConfig();
- break;
- case "display":
- return $this->displayConfig();
- break;
- }
-
- return null;
- }
-
- /**
- * Returns the configuration file as string, so that it can be displayed
- * during setup.
- *
- * @param none
- * @return array An array, where the "config" key contains the configuration.
- */
- private function displayConfig () {
- return array("config" => Configuration::dumpConfig());
- }
-
- /**
- * Saves the configuration file.
- *
- * @throws SerializableException An exception which describes what has been going wrong
- */
- private function saveConfig () {
- $configFile = PartKeepr::getRootDirectory()."/config.php";
-
- if (file_exists($configFile)) {
- if (!is_writable($configFile)) {
- $message = "The config.php file could not be written, because it already exists and the webserver has ";
- $message .= "no write access to it.";
-
- throw new SerializableException($message, 10000);
- }
- } else {
- if (!is_writable(PartKeepr::getRootDirectory())) {
- $message = "The config.php file could not be written, because the webserver has no write access to it.";
-
- throw new SerializableException($message, 10001);
- }
- }
- file_put_contents($configFile, Configuration::dumpConfig());
- }
-}-
\ 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
@@ -1,156 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Setup;
-
-use de\RaumZeitLabor\PartKeepr\Footprint\FootprintManager,
- de\RaumZeitLabor\PartKeepr\FootprintCategory\FootprintCategoryManager,
- de\RaumZeitLabor\PartKeepr\FootprintCategory\FootprintCategory,
- de\RaumZeitLabor\PartKeepr\Footprint\Footprint,
- de\RaumZeitLabor\PartKeepr\Footprint\FootprintImage,
- de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Setup\Setup;
-
-class FootprintSetup extends AbstractSetup {
- /**
- * Holds the migrated footprints
- * @var array
- */
- private static $migratedFootprints = array();
-
- const FOOTPRINT_PATH = "../setup-data/footprints/";
- const FOOTPRINT_FILE = "../setup-data/footprints/footprints.yaml";
-
- /**
- * Creates the root node for the footprints
- */
- 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
- */
- public static function getFootprintForOldId ($id) {
- return FootprintSetup::$migratedFootprints[$id];
- }
-
- /**
- * Creates a node structure for the given path
- *
- * @param $path array The components of the path
- * @param $node Node The parent node
- */
- public function addFootprintPath (Array $path, $node) {
- if (count($path) == 0) {
- return $node;
- }
- $name = array_shift($path);
-
- $childNode = null;
-
- foreach ($node->getChildren() as $child) {
- if ($child->getNode()->getName() == $name) {
- $childNode = $child;
- }
- }
-
- if ($childNode === null) {
- $category = new FootprintCategory();
- $category->setParent($node->getNode()->getId());
- $category->setName($name);
- $childNode = FootprintCategoryManager::getInstance()->addCategory($category);
- }
-
- return $this->addFootprintPath($path, $childNode);
- }
-
- /**
- * 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 function importFootprintData () {
- $count = 0;
- $skipped = 0;
-
- /* Import pre-defined footprints */
- $data = Setup::loadYAML(self::FOOTPRINT_FILE);
-
- foreach ($data as $footprintName => $footprintData) {
- /* 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);
-
- if (array_key_exists("description", $footprintData)) {
- $footprint->setDescription($footprintData["description"]);
- }
-
- if (array_key_exists("category", $footprintData)) {
- $footprintCategory = $this->addFootprintPath(explode("/", $footprintData["category"]), FootprintCategoryManager::getInstance()->getRootNode());
- $footprint->setCategory($footprintCategory->getNode());
- }
-
- if (array_key_exists("image", $footprintData)) {
- $footprintImage = new FootprintImage();
- $footprintImage->setFootprint($footprint);
- $footprintImage->replace(self::FOOTPRINT_PATH . $footprintData["image"]);
-
- $footprint->setImage($footprintImage);
- }
-
- if (array_key_exists("attachments", $footprintData) && is_array($footprintData["attachments"])) {
- foreach ($footprintData["attachments"] as $attachment) {
- if (!is_array($attachment)) {
- throw new \Exception("Error: The property 'attachments' of $footprintName is not an array!");
- }
- if (array_key_exists("url", $attachment)) {
- try {
- $footprintAttachment = new FootprintAttachment();
- $footprintAttachment->setFootprint($footprint);
- $footprintAttachment->replaceFromURL($attachment["url"]);
- if (array_key_exists("description", $attachment)) {
- $footprintAttachment->setDescription($attachment["description"]);
- }
-
- $footprint->getAttachments()->add($footprintAttachment);
- } catch (\Exception $e) {
- //echo "error with url ".$attachment["url"]."\n";
- }
- }
-
- }
- }
-
- $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
@@ -1,56 +0,0 @@
-<?php
-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;
-
-/**
- * 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 function setupManufacturers () {
- $count=0;
- $skipped=0;
- $data = Setup::loadYAML(self::MANUFACTURER_FILE);
-
- foreach ($data as $mfgname => $logos) {
- 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/Migration/PartDB/DistributorMigration.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/DistributorMigration.php
@@ -1,34 +0,0 @@
-<?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
@@ -1,43 +0,0 @@
-<?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
@@ -1,50 +0,0 @@
-<?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
@@ -1,71 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Setup\Migration\PartDB;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Util\Configuration as PartKeeprConfiguration;
-
-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("Ω", "Ω", $string);
- return $string;
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/PartMigration.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/Migration/PartDB/PartMigration.php
@@ -1,131 +0,0 @@
-<?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
@@ -1,51 +0,0 @@
-<?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/MiscSettingsSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/MiscSettingsSetup.php
@@ -1,69 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Setup;
-
-use de\RaumZeitLabor\PartKeepr\CronLogger\CronLoggerManager,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
- * Sets up misc stuff, which doesn't fit into other steps
- */
-class MiscSettingsSetup extends AbstractSetup {
- public function run () {
- $this->markCronjobsAsRun();
- $this->clearAPCCache();
- $this->regenerateProxies();
- }
-
- /**
- * Marks the cronjobs as run, so that the user doesn't get an error during the first day.
- *
- * This is necessary because if the user sets up the system and enters the cronjobs, there is a chance
- * that no cronjob has been ran when he logs in the first time and thus gets confused.
- */
- public function markCronjobsAsRun () {
- foreach (PartKeepr::getRequiredCronjobs() as $cronjob) {
- CronLoggerManager::getInstance()->markCronRun($cronjob);
- }
- }
-
- /**
- * Clears the APC cache to push out old entries
- */
- public function clearAPCCache () {
- if (function_exists("apc_clear_cache")) {
- apc_clear_cache();
- apc_clear_cache("user");
- }
- }
-
- /**
- * Re-generates all proxies. This is analog to doctrine orm:generate-proxies
- *
- * @throws \InvalidArgumentException
- */
- public function regenerateProxies () {
- $em = $this->entityManager;
-
- $metadatas = $em->getMetadataFactory()->getAllMetadata();
- $destPath = $em->getConfiguration()->getProxyDir();
-
- if ( ! is_dir($destPath)) {
- mkdir($destPath, 0777, true);
- }
-
- $destPath = realpath($destPath);
-
- if ( ! file_exists($destPath)) {
- throw new \InvalidArgumentException(
- sprintf("Proxies destination directory '<info>%s</info>' does not exist.", $em->getConfiguration()->getProxyDir())
- );
- } else if ( ! is_writable($destPath)) {
- throw new \InvalidArgumentException(
- sprintf("Proxies destination directory '<info>%s</info>' does not have write permissions.", $destPath)
- );
- }
-
- $em->getProxyFactory()->generateProxyClasses($metadatas, $destPath);
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/PartCategorySetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/PartCategorySetup.php
@@ -1,28 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Setup;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager,
- de\RaumZeitLabor\PartKeepr\PartCategory\PartCategory;
-
-class PartCategorySetup extends AbstractSetup {
- /**
- * Sets up the root category node
- */
- public function setupRootCategory () {
- PartCategoryManager::getInstance()->ensureRootExists();
- }
-
- public function updateCategoryPathCache () {
- PartCategoryManager::getInstance()->updateCategoryPaths(
- PartCategoryManager::getInstance()->getRootNode()
- );
-
- PartKeepr::getEM()->flush();
- }
-
- public function run () {
- $this->setupRootCategory();
- $this->updateCategoryPathCache();
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Setup/PartUnitSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/PartUnitSetup.php
@@ -1,36 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Setup;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Part\PartUnit;
-
-class PartUnitSetup extends AbstractSetup {
- /**
- * Holds the default unit
- * @var object
- */
- private static $defaultUnit;
-
- /**
- * Sets up the default part unit if none exists
- */
- public function run () {
- $dql = "SELECT COUNT(p) FROM de\RaumZeitLabor\PartKeepr\Part\PartUnit p WHERE p.is_default = :default";
- $query = $this->entityManager->createQuery($dql);
- $query->setParameter("default", true);
-
- 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/SchemaSetup.php b/src/backend/de/RaumZeitLabor/PartKeepr/Setup/SchemaSetup.php
@@ -1,34 +0,0 @@
-<?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, true);
- $this->logMessage("Database Schema created/updated");
- }
-
- /**
- * Checks if the specified database has UTF-8 encoding
- * @param $connection The DBAL connection
- * @param string $dbname
- */
- public static function mysqlHasUTF8Encoding ($connection, $dbname) {
- $statement = $connection->prepare("SELECT default_character_set_name FROM information_schema.SCHEMATA S WHERE schema_name = :schema");
- $statement->bindValue("schema", $dbname);
- $statement->execute();
-
- $encoding = $statement->fetchColumn(0);
-
- if ($encoding != "utf8") {
- return false;
- } else {
- return true;
- }
- }
-}-
\ 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,176 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Setup;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Util\Configuration as PartKeeprConfiguration;
-
-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 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.
- *
- * @param string $step The step to execute
- * @throws \Exception
- */
- 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),
- "miscsettings" => new MiscSettingsSetup($entityManager)
- );
-
- $aActions = array(
- "configfile" => new ConfigFileSetup($entityManager)
- );
- if ($step == "all") {
- foreach ($aSteps as $step) {
- $step->setConsole($this->console);
- $step->run();
- }
- } else {
- if (array_key_exists($step, $aSteps)) {
- return $aSteps[$step]->run();
- }
-
- if (array_key_exists($step, $aActions)) {
- return $aActions[$step]->run();
- }
-
- throw new \Exception(sprintf("Setup step %s doesn't exist", $step));
- }
- }
-
- /**
- * Tests for APC. Throws an exception if APC is missing or not active.
- * @throws \Exception
- */
- public function testAPC () {
- if (!extension_loaded("apc")) {
- throw new \Exception(PartKeepr::i18n("The extension 'apc' is not loaded. Make sure that it is installed (see http://php.net/manual/en/apc.installation.php) and that it is enabled (set apc.enabled=1 in your php.ini)."));
- }
- }
-
- /**
- * Tests for suitable memory_limit settings
- * @todo stub
- */
- public function testMemoryLimit () {
- //echo ini_get("memory_limit");
- }
-
- /**
- * Sets the verbose flag
- * @param boolean $verbose True if verbose output is wanted, false otherwise
- */
- public static function setVerbose ($verbose) {
- Setup::$verbose = $verbose;
- }
-
- /**
- * Outputs a progress message.
- *
- * @param string $string The string to output
- * @param boolean $verbose True if the string should only be printed if verbosity is turned on
- */
- public static function progress ($string, $verbose = false) {
- if (!$verbose || ($verbose && Setup::$verbose)) {
- echo $string."\n";
- }
-
- }
-
- /**
- * Loads the given YAML file. Due to an API brach between Doctrine 2.0.5 and Doctrine 2.0.6,
- * we need to work it around.
- * @param string $file The path of the file to load
- * @return array The parsed YAML file
- */
- public static function loadYAML ($file) {
- return \Symfony\Component\Yaml\Yaml::parse($file);
- }
-
- /**
- * Sets the database configuration array from $_REQUEST
- */
- public static function setDatabaseConfigurationFromRequest () {
- if (isset($_REQUEST["dbname"])) {
- PartKeeprConfiguration::setOption("partkeepr.database.dbname", $_REQUEST["dbname"]);
- }
-
- if (isset($_REQUEST["user"])) {
- PartKeeprConfiguration::setOption("partkeepr.database.username", $_REQUEST["user"]);
- }
- if (isset($_REQUEST["password"])) {
- PartKeeprConfiguration::setOption("partkeepr.database.password", $_REQUEST["password"]);
- }
- if (isset($_REQUEST["host"])) {
- PartKeeprConfiguration::setOption("partkeepr.database.host", $_REQUEST["host"]);
- }
-
- if (isset($_REQUEST['port'])) {
- PartKeeprConfiguration::setOption("partkeepr.database.port", $_REQUEST["port"]);
- }
-
- switch ($_REQUEST["driver"]) {
- case "mysql":
- PartKeeprConfiguration::setOption("partkeepr.database.driver","pdo_mysql");
- break;
- case "pgsql":
- PartKeeprConfiguration::setOption("partkeepr.database.driver","pdo_pgsql");
- break;
- default:
- throw new \Exception(sprintf("Invalid driver %s specified.", $_REQUEST["driver"]));
- break;
- }
- }
-
- /**
- * Runs some checks for the CLI setup
- */
- public function runCLIChecks () {
-
- if (PartKeeprConfiguration::getOption("partkeepr.database.driver") == "pdo_mysql") {
- $dbname = PartKeeprConfiguration::getOption("partkeepr.database.dbname");
- if (!SchemaSetup::mysqlHasUTF8Encoding(PartKeepr::getEM()->getConnection(), $dbname )) {
- echo "Error: The database $dbname hasn't got the UTF-8 encoding. You need to set the database encoding to UTF-8. Aborting.\n";
- die;
- }
- }
-
- }
-}-
\ 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
@@ -1,47 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Setup;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefix,
- de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefixManager;
-
-class SiPrefixSetup extends AbstractSetup {
-
- const SIPREFIX_DATA_FILE = "../setup-data/siprefixes.yaml";
-
- /**
- * Stores the migrated si prefixes
- * @var array
- */
- private static $siPrefixes = array();
-
- public function run () {
- $this->setupSiPrefixes();
- }
-
- /**
- * Sets up the SI prefixes
- */
- public function setupSiPrefixes () {
- $count = 0;
- $skipped = 0;
-
- $data = Setup::loadYAML(self::SIPREFIX_DATA_FILE);
-
- foreach ($data as $prefixName => $data) {
- 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++;
- }
- }
-
- $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
@@ -1,62 +0,0 @@
-<?php
-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 extends AbstractSetup {
-
- const UNIT_DATA_FILE = "../setup-data/units.yaml";
-
-
- public function run () {
- $this->setupUnits();
- }
- /**
- * Sets up the default units
- * @throws \Exception
- */
- public function setupUnits () {
- $count = 0;
- $skipped = 0;
- $data = Setup::loadYAML(self::UNIT_DATA_FILE);
-
- $aUnits = array();
-
- foreach ($data as $unitName => $data) {
- if (UnitManager::getInstance()->unitExists($unitName)) {
- $skipped++;
- continue;
- }
- $unit = new Unit();
- $unit->setName($unitName);
- $unit->setSymbol($data["symbol"]);
-
- if (array_key_exists("prefixes", $data)) {
- if (!is_array($data["prefixes"])) {
- throw new \Exception($unitName." doesn't contain a prefix list, or the prefix list is not an array.");
- }
-
- foreach ($data["prefixes"] as $prefix) {
-
- $siPrefix = SiPrefixManager::getInstance()->getSiPrefixBySymbol($prefix);
- if ($siPrefix === false) {
- throw new \Exception("Unable to find prefix ".$prefix);
- }
- $unit->getPrefixes()->add($siPrefix);
- }
- }
-
- 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
@@ -1,31 +0,0 @@
-<?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 = :admin";
- $query = $this->entityManager->createQuery($dql);
- $query->setParameter("username", "admin");
- $query->setParameter("admin", true);
-
- 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/SiPrefix.php b/src/backend/de/RaumZeitLabor/PartKeepr/SiPrefix/SiPrefix.php
@@ -1,91 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\SiPrefix;
-
-use de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Util\Exceptions\OutOfRangeException;
-
-
-/** @Entity **/
-class SiPrefix extends BaseEntity {
- /**
- * The prefix of the Si-Prefix (e.g. yotta, deca, deci, centi)
- * @Column(type="string")
- * @var string
- */
- private $prefix;
-
- /**
- * The symbol of the Si-Prefix (e.g. m, M, G)
- * @Column(type="string",length=2)
- * @var string
- */
- private $symbol;
-
- /**
- * The power of the Si-Prefix (e.g. milli = 10^-3)
- * @Column(type="integer")
- * @var int
- */
- private $power;
-
- /**
- * Sets the prefix name.
- * @param string $prefix
- */
- public function setPrefix ($prefix) {
- $this->prefix = $prefix;
- }
-
- /**
- * Returns the prefix name
- * @return string The prefix name
- */
- public function getPrefix () {
- return $this->prefix;
- }
-
- /**
- * Sets the symbol for the prefix
- * @param string $symbol The symbol
- */
- public function setSymbol ($symbol) {
- $this->symbol = $symbol;
- }
-
- /**
- * Returns the symbol for the prefix
- * @return string The symbol
- */
- public function getSymbol () {
- return $this->symbol;
- }
-
- /**
- * Sets the power in a 10^n power (n=power)
- * @param int $power The 10^power
- */
- public function setPower ($power) {
- $this->power = $power;
- }
-
- /**
- * Returns the power (10^n)
- * @return int The power
- */
- public function getPower () {
- return $this->power;
- }
-
- /**
- * Serializes the object into an array format.
- * @return array the object in serialized format.
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "symbol" => $this->getSymbol(),
- "prefix" => $this->getPrefix(),
- "power" => $this->getPower());
- }
-}-
\ 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
@@ -1,42 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\SiPrefix;
-
-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/SiPrefix/SiPrefixService.php b/src/backend/de/RaumZeitLabor/PartKeepr/SiPrefix/SiPrefixService.php
@@ -1,27 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\SiPrefix;
-
-use de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class SiPrefixService extends Service implements RestfulService {
- public function get () {
- $query = PartKeepr::getEM()->createQuery("SELECT si.id, si.prefix, si.symbol, si.power FROM de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefix si");
-
- return array("data" => $query->getArrayResult());
- }
-
- public function create () {
- throw new \Exception("Not yet implemented");
- }
-
- public function update () {
- throw new \Exception("Not yet implemented");
- }
-
- public function destroy () {
- throw new \Exception("Not yet implemented");
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Statistic/StatisticService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Statistic/StatisticService.php
@@ -1,148 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Statistic;
-
-use de\RaumZeitLabor\PartKeepr\Part\PartUnit,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Part\PartManager,
- de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager,
- de\RaumZeitLabor\PartKeepr\PartUnit\PartUnitManager;
-
-class StatisticService extends Service {
- public function getCurrentStats () {
-
- $aData = array();
- $aData["partCount"] = PartManager::getInstance()->getPartCount();
- $aData["categoryCount"] = PartCategoryManager::getInstance()->getCategoryCount();
- $aData["totalPrice"] = PartManager::getInstance()->getTotalPrice();
- $aData["averagePrice"] = PartManager::getInstance()->getAveragePrice();
- $aData["partsWithPrice"] = PartManager::getInstance()->getPartCount(true);
- $aData["partsWithoutPrice"] = $aData["partCount"] - $aData["partsWithPrice"];
-
- $result = PartUnitManager::getInstance()->getUnitCounts();
-
- $aUnits = array();
-
- foreach ($result as $row) {
- $aUnits[] = array(
- "name" => PartUnit::loadById($row["puid"])->getName(),
- "stockLevel" => $row["stockLevel"]);
- }
-
- $aData["units"] = $aUnits;
-
- return $aData;
- }
-
- /**
- * Returns the range of all recorded statistic snapshots.
- */
- public function getStatisticRange () {
- $dql = "SELECT MIN(sts.dateTime), MAX(sts.dateTime) FROM de\RaumZeitLabor\PartKeepr\Statistic\StatisticSnapshot sts";
- $query = PartKeepr::getEM()->createQuery($dql);
-
- $data = $query->getArrayResult();
-
- return array("data" => array("start" => $data[0][1], "end" => $data[0][2]));
-
- }
- /**
- * Returns sampled statistics from the database.
- *
- * This call takes a start and an end time, and calculates a set of statistics
- * for each interval.
- *
- * The sampleSize, which has a default of 50, specifies how many single statistic
- * points in the given date interval will be returned.
- *
- * This function interpolates the statistics if there are not enough statistic samples available.
- */
- public function getSampledStatistics () {
- $fooStart = microtime(true);
-
- $this->requireParameter("startDateTime");
- $this->requireParameter("endDateTime");
-
-
- $start = \DateTime::createFromFormat("Y-m-d H:i:s", $this->getParameter("startDateTime"));
- $end = \DateTime::createFromFormat("Y-m-d H:i:s", $this->getParameter("endDateTime"));
-
- if ($start->getTimestamp() > $end->getTimestamp()) {
- // Swap both times
- list($start, $end) = array($end, $start);
- }
-
- if ($this->hasParameter("sampleSize")) {
- $sampleSize = $this->getParameter("sampleSize");
- } else {
- $sampleSize = 25;
- }
-
- $intervalSize = intval(($end->getTimestamp() - $start->getTimestamp()) / $sampleSize);
-
- $queryStartTime = clone $start;
- $queryEndTime = clone $start;
- $queryEndTime->add(new \DateInterval("PT".$intervalSize."S"));
-
- $partUnitQuery = "SELECT pu FROM de\RaumZeitLabor\PartKeepr\Part\PartUnit pu";
- $query = PartKeepr::getEM()->createQuery($partUnitQuery);
-
- $aPartUnits = $query->getResult();
-
- $aRecords = array();
-
- $dql = "SELECT AVG(sts.parts) AS parts, AVG(sts.categories) AS categories FROM de\RaumZeitLabor\PartKeepr\Statistic\StatisticSnapshot sts WHERE sts.dateTime >= :start AND sts.dateTime <= :end";
- $mainQuery = PartKeepr::getEM()->createQuery($dql);
-
- $dql = "SELECT AVG(stsu.stockLevel) AS stockLevel FROM de\RaumZeitLabor\PartKeepr\Statistic\StatisticSnapshotUnit stsu JOIN stsu.statisticSnapshot sts WHERE sts.dateTime >= :start AND sts.dateTime <= :end AND stsu.partUnit = :partUnit";
- $subQuery = PartKeepr::getEM()->createQuery($dql);
-
- for ($i=0;$i<$sampleSize;$i++) {
-
-
- $mainQuery->setParameter("start", $queryStartTime);
- $mainQuery->setParameter("end", $queryEndTime);
-
- $result = $mainQuery->getResult();
-
- $record = $result[0];
-
- if ($record["parts"] !== null) {
- $record["parts"] = floatval($record["parts"]);
- }
-
- if ($record["categories"] !== null) {
- $record["categories"] = floatval($record["categories"]);
- }
-
- foreach ($aPartUnits as $partUnit) {
- $subQuery->setParameter("start", $queryStartTime);
- $subQuery->setParameter("end", $queryEndTime);
- $subQuery->setParameter("partUnit", $partUnit);
-
- $aResult = $subQuery->getResult();
-
- if ($aResult[0]["stockLevel"] !== null) {
- $record["units"][$partUnit->getName()] = floatval($aResult[0]["stockLevel"]);
- } else {
- $record["units"][$partUnit->getName()] = null;
- }
-
- }
-
- $record["start"] = $queryStartTime->format("Y-m-d H:i:s");
-
- if ($record["parts"] !== null) {
- $aRecords[] = $record;
- }
-
-
- $queryStartTime->add(new \DateInterval("PT".$intervalSize."S"));
- $queryEndTime->add(new \DateInterval("PT".$intervalSize."S"));
- }
-
-
- return array("status" => "ok", "data" => $aRecords);
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Statistic/StatisticSnapshot.php b/src/backend/de/RaumZeitLabor/PartKeepr/Statistic/StatisticSnapshot.php
@@ -1,109 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Statistic;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/** @Entity **/
-class StatisticSnapshot {
- /**
- * @Id @Column(type="integer")
- * @GeneratedValue(strategy="AUTO")
- * @var integer
- */
- private $id;
-
- /**
- * Defines the date when this snapshot has been taken
- * @Column(type="datetime")
- * @var DateTime
- */
- private $dateTime;
-
- /**
- * Defines the amount of different parts in the database
- * @Column(type="integer")
- * @var int
- */
- private $parts;
-
- /**
- * Defines the amount of categories
- * @Column(type="integer")
- * @var int
- */
- private $categories;
-
- /**
- * Holds all defined units in the database
- * @OneToMany(targetEntity="de\RaumZeitLabor\PartKeepr\Statistic\StatisticSnapshotUnit",mappedBy="statisticSnapshot",cascade={"persist", "remove"})
- */
- private $units;
-
- /**
- * Creates a new statistic snapshot
- */
- public function __construct () {
- $this->units = new \Doctrine\Common\Collections\ArrayCollection();
- $this->setDateTime(new \DateTime());
- }
-
- /**
- * Sets the date+time for the snapshot
- * @param \DateTime $dateTime The date+time for the snapshot
- */
- public function setDateTime (\DateTime $dateTime) {
- $this->dateTime = $dateTime;
- }
-
- /**
- * Returns the date+time for the snapshot
- * @return DateTime The date+time for the snapshot
- */
- public function getDateTime () {
- return $this->dateTime;
- }
-
- /**
- * Sets the amount of overall parts for the snapshot
- * @param int $parts The amount of parts
- */
- public function setParts ($parts) {
- $this->parts = $parts;
- }
-
- /**
- * Returns the amount of overall parts for the snapshot
- * @return int The amount of parts
- */
- public function getParts () {
- return $this->parts;
- }
-
- /**
- * Sets the amount of categories for the snapshot
- * @param int $categories The amount of categories
- */
- public function setCategories ($categories) {
- $this->categories = $categories;
- }
-
- /**
- * Returns the amount of categories
- * @return int The amount of categories
- */
- public function getCategories () {
- return $this->categories;
- }
-
- /**
- * Returns the ID of this snapshot
- * @return int The ID of this snapshot
- */
- public function getId () {
- return $this->id;
- }
-
- public function getUnits () {
- return $this->units;
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Statistic/StatisticSnapshotManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Statistic/StatisticSnapshotManager.php
@@ -1,38 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Statistic;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\Part\PartUnit,
- de\RaumZeitLabor\PartKeepr\Part\PartManager,
- de\RaumZeitLabor\PartKeepr\PartUnit\PartUnitManager,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager,
- de\RaumZeitLabor\PartKeepr\PartUnit\Exceptions\PartUnitNotFoundException;
-
-class StatisticSnapshotManager extends Singleton {
- public function createSnapshot () {
-
- $snapshot = new StatisticSnapshot();
- $snapshot->setParts(PartManager::getInstance()->getPartCount());
- $snapshot->setCategories(PartCategoryManager::getInstance()->getCategoryCount());
-
- $result = PartUnitManager::getInstance()->getUnitCounts();
-
- foreach ($result as $row) {
- $snapshotUnit = new StatisticSnapshotUnit();
- $snapshotUnit->setPartUnit(PartUnit::loadById($row["puid"]));
- $snapshotUnit->setStatisticSnapshot($snapshot);
-
- if ($row["stockLevel"] !== null) {
- $snapshotUnit->setStockLevel($row["stockLevel"]);
- } else {
- $snapshotUnit->setStockLevel(0);
- }
-
- $snapshot->getUnits()->add($snapshotUnit);
- }
-
- PartKeepr::getEM()->persist($snapshot);
- PartKeepr::getEM()->flush();
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Statistic/StatisticSnapshotUnit.php b/src/backend/de/RaumZeitLabor/PartKeepr/Statistic/StatisticSnapshotUnit.php
@@ -1,95 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Statistic;
-
-use de\RaumZeitLabor\PartKeepr\Statistic\StatisticSnapshot,
- de\RaumZeitLabor\PartKeepr\Part\PartUnit,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-
-/** @Entity **/
-class StatisticSnapshotUnit {
- /**
- * @Id @Column(type="integer")
- * @GeneratedValue(strategy="AUTO")
- * @var integer
- */
- private $id;
-
- /**
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Statistic\StatisticSnapshot")
- * The statistic snapshot this entity belongs to
- * @var StatisticSnapshot
- */
- private $statisticSnapshot;
-
- /**
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Part\PartUnit")
- * The statistic snapshot this entity belongs to
- * @var StatisticSnapshot
- */
- private $partUnit;
-
- /**
- * The stockLevel for the unit
- * @Column(type="integer")
- * @var int
- */
- private $stockLevel;
-
- /**
- * Sets the statistic snapshot this entity belongs to
- * @param StatisticSnapshot $snapshot The snapshot
- */
- public function setStatisticSnapshot (StatisticSnapshot $snapshot) {
- $this->statisticSnapshot = $snapshot;
- }
-
- /**
- * Returns the snapshot this entity belongs to
- * @return StatisticSnapshot The snapshot
- */
- public function getStatisticSnapshot () {
- return $this->statisticSnapshot;
- }
-
- /**
- *
- * Sets the part unit for this entity
- * @param PartUnit $unit The part unit
- */
- public function setPartUnit (PartUnit $unit) {
- $this->partUnit = $unit;
- }
-
- /**
- * Returns the part unit for this entity
- * @return PartUnit The part unit
- */
- public function getPartUnit () {
- return $this->partUnit;
- }
-
- /**
- * Returns the ID of this statistic snapshot unit
- * @return int The ID
- */
- public function getId () {
- return $this->id;
- }
-
- /**
- * Sets the stock level for this unit snapshot
- * @param int $stockLevel
- */
- public function setStockLevel ($stockLevel) {
- $this->stockLevel = $stockLevel;
- }
-
- /**
- * Returns the stock level for this unit snapshot
- * @return int The stock level
- */
- public function getStockLevel () {
- return $this->stockLevel;
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Stock/StockEntry.php b/src/backend/de/RaumZeitLabor/PartKeepr/Stock/StockEntry.php
@@ -1,239 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Stock;
-
-use de\RaumZeitLabor\PartKeepr\Part\Part,
- de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\Util\Serializable;
-
-/** @Entity @HasLifecycleCallbacks **/
-class StockEntry extends BaseEntity implements Serializable {
- /**
- * @Column(type="integer")
- */
- private $stockLevel;
-
- /**
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\Part\Part")
- */
- private $part;
-
- /**
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\User\User")
- */
- private $user;
-
- /**
- * @Column(type="decimal",precision=13,scale=4,nullable=true)
- * @var float
- */
- private $price;
-
- /**
- * @Column(type="datetime")
- * @var DateTime
- */
- private $dateTime;
-
- /**
- * Indicates if the stock level is a correction entry.
- *
- * @Column(type="boolean")
- * @var boolean
- */
- private $correction;
-
- /**
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $comment;
-
-
- /**
- * Creates a new stock entry. A stock entry tracks how many parts
- * were the stockLevel is the amount of items added/removed,
- * by which user and how much the user paid for it (for adding parts only!)
- *
- * @param Part $part The part which was added/removed
- * @param int $stockLevel The stock level. Positive value means added parts, negative values means removed parts.
- * @param User $user The user who removed/added parts
- */
- public function __construct (Part $part, $stockLevel, User $user = null) {
- $this->setPart($part);
- $this->setStockLevel($stockLevel);
- $this->setUser($user);
- $this->setDateTime(new \DateTime());
- $this->setCorrection(false);
- }
-
-
- /**
- * Sets the date+time
- * @param \DateTime $dateTime The date+time
- */
- private function setDateTime (\DateTime $dateTime) {
- $this->dateTime = $dateTime;
- }
-
- /**
- * Returns the date+time when the record was created.
- * @return \DateTime The date+time when the record was created
- */
- public function getDateTime () {
- return $this->dateTime;
- }
-
- /**
- * Sets if the stock entry is a correction record.
- * @param $bCorrection boolean True if the record is a correction record, false otherwise
- */
- public function setCorrection ($bCorrection) {
- $this->correction = $bCorrection;
- }
-
- /**
- * Returns if the entry is a correction entry.
- * @return boolean True if the entry is a correction entry, false otherwise
- */
- public function getCorrection () {
- return $this->correction;
- }
-
- /**
- * Sets the price for the item stored.
- *
- * Please note that the price is for a single item only, and can be null.
- * @param float $price The price to set
- */
- public function setPrice ($price) {
- $this->price = $price;
- }
-
- /**
- * Returns the price for this entry. The price is for a single item only.
- *
- * @return float The price for this entry.
- */
- public function getPrice () {
- return $this->price;
- }
-
- /**
- * Sets the stock level for this entry.
- *
- * Negative values means part removal, positive values means part adding.
- * @param int $stockLevel The stock level
- */
- public function setStockLevel($stockLevel) {
- $this->stockLevel = $stockLevel;
- }
-
- /**
- * Returns the stock level for this entry.
- * @return int The stock level
- */
- public function getStockLevel () {
- return $this->stockLevel;
- }
-
- /**
- * Sets the part assigned to this entry.
- * @param Part $part The part to set
- */
- public function setPart (Part $part) {
- $this->part = $part;
- }
-
- /**
- * Returns the part assigned to this entry.
- * @return Part $part The part
- */
- public function getPart () {
- return $this->part;
- }
-
- /**
- * Sets the user assigned to this entry.
- * @param User $user The user The user to set
- */
- public function setUser (User $user = null) {
- $this->user = $user;
- }
-
- /**
- * Returns the user for this entry
- * @return User the user
- */
- public function getUser () {
- return $this->user;
- }
-
- /**
- * If the stock level is negative, we can't have a price.
- * @PrePersist
- */
- public function checkPrice () {
- if ($this->getStockLevel() < 0 && $this->getPrice() !== null) {
- $this->setPrice(null);
- }
- }
-
- /**
- * Updates the stock leve for a part
- * @PostPersist
- */
- public function postPersist () {
- $this->part->updateStockLevel();
- $this->part->updatePrice();
- }
-
- /**
- * Returns if the current stock entry is a removal.
- * @return boolean True if the entry is a removal, false otherwise
- */
- public function isRemoval () {
- if ($this->getStockLevel() < 0) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Sets a comment
- * @param string $comment
- */
- public function setComment ($comment) {
- $this->comment = $comment;
- }
-
- /**
- * Returns the comment
- * @return string The comment
- */
- public function getComment () {
- return $this->comment;
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Util.Serializable::serialize()
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "part_name" => $this->getPart()->getName(),
- "part_id" => $this->getPart()->getId(),
- "storageLocation_name" => $this->getPart()->getStorageLocation()->getName(),
- "username" => is_object($this->getUser()) ? $this->getUser()->getUsername() : PartKeepr::i18n("Unknown User"),
- "user_id" => is_object($this->getUser()) ? $this->getUser()->getId() : null,
- "stockLevel" => abs($this->getStockLevel()),
- "comment" => $this->getComment(),
- "dateTime" => $this->getDateTime()->format("Y-m-d H:i:s"),
- "direction" => ($this->getStockLevel() < 0) ? "out" : "in",
- "price" => $this->getPrice()
- );
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Stock/StockManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/Stock/StockManager.php
@@ -1,66 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Stock;
-
-use de\RaumZeitLabor\PartKeepr\Manager\AbstractManager,
- Doctrine\ORM\QueryBuilder,
- de\RaumZeitLabor\PartKeepr\Manager\ManagerFilter,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class StockManager extends AbstractManager {
- /**
- * Returns the FQCN for the target entity to operate on.
- * @return string The FQCN, e.g. de\RaumZeitLabor\PartKeepr\Part
- */
- public function getEntityName () {
- return 'de\RaumZeitLabor\PartKeepr\Stock\StockEntry';
- }
-
- /**
- * Returns all fields which need to appear in the getList ResultSet.
- * @return array An array of all fields which should be returned
- */
- public function getQueryFields () {
- return array();
- }
-
- /**
- * Returns the default sort field
- *
- * @return string The default sort field
- */
- public function getDefaultSortField () {
- return "dateTime";
- }
-
- /**
- * Applies a custom query to the QueryBuilder
- *
- * @param QueryBuilder $qb The query builder
- * @param ManagerFilter $filter The query filter
- */
- protected function applyCustomQuery (QueryBuilder $qb, ManagerFilter $filter) {
-
- // Apply special handling for non-direct fields in relations, where the frontend has no idea about.
- foreach ($filter->getSorters() as $sorter) {
- switch ($sorter->getSortField()) {
- case "q.part_name":
- $qb->join("q.part", "p");
- $sorter->setSortField("p.name");
- break;
- case "q.user_id":
- $qb->leftJoin("q.user", "u");
- $sorter->setSortField("u.username");
- break;
- case "q.direction":
- $sorter->setSortField("q.dateTime");
- break;
- case "q.storageLocation_name":
- $qb->join("q.part", "p")->join("p.storageLocation", "st");
- $sorter->setSortField("st.name");
- break;
- default:
- break;
- }
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Stock/StockService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Stock/StockService.php
@@ -1,93 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Stock;
-
-use de\RaumZeitLabor\PartKeepr\Stock\StockEntry,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\Manager\ManagerFilter,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager,
- de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Service\Service;
-
-class StockService extends Service implements RestfulService {
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
- */
- public function get () {
- if ($this->hasParameter("id")) {
- return array("data" => StockManager::getInstance()->getEntity($this->getParameter("id"))->serialize());
- } else {
- $parameters = new ManagerFilter($this);
- $parameters->setFilterField("name");
-
- if ($this->hasParameter("part")) {
- $parameters->setFilterCallback(array($this, "filterCallback"));
- }
- return StockManager::getInstance()->getList($parameters);
- }
- }
-
- /**
- * If the "part" parameter is set, join the part into the result and filter on that
- * @param QueryBuilder The $queryBuilder
- */
- public function filterCallback ($queryBuilder) {
- $queryBuilder->andWhere("q.part = :part");
- $queryBuilder->setParameter("part", $this->getParameter("part"));
- }
-
- public function create () {
- throw new \Exception("Not yet implemented");
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update()
- */
- public function update () {
- $this->requireParameter("id");
-
- $stockEntry = StockEntry::loadById($this->getParameter("id"));
-
- if (!SessionManager::getCurrentSession()->getUser()->isAdmin() &&
- !(SessionManager::getCurrentSession()->getUser() && $stockEntry->getUser() && SessionManager::getCurrentSession()->getUser()->getId() == $stockEntry->getUser()->getId() )) {
- throw new \Exception("Permission denied");
- }
-
- /* It's not allowed to edit a price for a removal */
- if (!$stockEntry->isRemoval()) {
- $stockEntry->setPrice(abs($this->getParameter("price")));
- }
-
- /**
- * Only an admin user may correct the in&out stock levels
- */
- if (SessionManager::getCurrentSession()->getUser()->isAdmin()) {
- if ($this->getParameter("direction") == "out") {
- $stockEntry->setStockLevel(-(abs($this->getParameter("stockLevel"))));
- } else {
- $stockEntry->setStockLevel($this->getParameter("stockLevel"));
- }
-
- }
-
- if (SessionManager::getCurrentSession()->getUser()->isAdmin()) {
- try {
- $stockEntry->setUser(User::loadById($this->getParameter("user_id")));
- } catch (\Exception $e) {
- $stockEntry->setUser(null);
- }
-
- }
-
- $stockEntry->setComment($this->getParameter("comment"));
- PartKeepr::getEM()->flush();
-
- return array("data" => $stockEntry->serialize());
- }
-
- public function destroy () {
- throw new \Exception("Not yet implemented");
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/StorageLocation/Exceptions/StorageLocationNotFoundException.php b/src/backend/de/RaumZeitLabor/PartKeepr/StorageLocation/Exceptions/StorageLocationNotFoundException.php
@@ -1,12 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\StorageLocation\Exceptions;
-
-use de\RaumZeitLabor\PartKeepr\Util\SerializableException,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class StorageLocationNotFoundException extends SerializableException {
- public function __construct () {
- parent::__construct(PartKeepr::i18n("Storage Location not found."));
- }
-}
-?>-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/StorageLocation/StorageLocation.php b/src/backend/de/RaumZeitLabor/PartKeepr/StorageLocation/StorageLocation.php
@@ -1,105 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\StorageLocation;
-
-use de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity;
-
-/** @Entity **/
-class StorageLocation extends BaseEntity implements Serializable, Deserializable {
- /**
- * Holds the name for our storage location
- * @Column(type="string",unique=true)
- * @var string
- */
- private $name;
-
- /**
- * Holds the storage location image
- * @OneToOne(targetEntity="de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocationImage",mappedBy="storageLocation",cascade={"persist", "remove"})
- * @var StorageLocationImage
- */
- private $image;
-
- /**
- * Sets the name for the storage location
- * @param string $name the name to set
- */
- public function setName ($name) {
- $this->name = $name;
- }
-
- /**
- * Returns the name of the storage location
- * @return string The name
- */
- public function getName () {
- return $this->name;
- }
-
- /**
- * Sets the storage location image
- * @param StorageLocationImage $image The storage location image
- */
- public function setImage (StorageLocationImage $image) {
- $this->image = $image;
- $image->setStorageLocation($this);
- }
-
- /**
- * Returns the storage location image
- * @return StorageLocationImage The storage location image
- */
- public function getImage () {
- return $this->image;
- }
-
- /**
- * Returns this storage location in serialized form
- * @return array The serialized storage location
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "name" => $this->getName(),
- "image_id" => is_object($this->getImage()) ? $this->getImage()->getId() : null);
- }
-
- /**
- * Deserializes the storage location
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "name":
- $this->setName($value);
- break;
- case "image_id":
- if ($value == "") {
- echo "/** Breaking because of empty value */";
- break;
- }
-
- try {
- $image = StorageLocationImage::loadById($value);
- $this->setImage($image);
- } catch (\Exception $e) {
- if ($this->getImage()) {
- // Image was not found, maybe a temporary image?
- $this->getImage()->replaceFromTemporaryFile($value);
- } else {
- $image = StorageLocationImage::createFromTemporaryFile($value);
- $this->setImage($image);
- echo "/**";
- echo $image->getId();
- echo "*/";
- echo "/** FOO */";
- }
- }
-
- break;
- }
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/StorageLocation/StorageLocationImage.php b/src/backend/de/RaumZeitLabor/PartKeepr/StorageLocation/StorageLocationImage.php
@@ -1,50 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\StorageLocation;
-
-use de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Image\Image;
-
-/**
- * Holds a storage location image
- * @Entity
- **/
-class StorageLocationImage extends Image implements Serializable {
- /**
- * The storage location object
- * @OneToOne(targetEntity="de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation",inversedBy="image")
- * @var StorageLocation
- */
- private $storageLocation = null;
-
- /**
- * Creates a new storage location image instance
- */
- public function __construct () {
- parent::__construct(Image::IMAGE_STORAGELOCATION);
- }
-
- /**
- * Sets the storage location
- * @param StorageLocation $storageLocation The storage location to set
- */
- public function setStorageLocation (StorageLocation $storageLocation) {
- $this->storageLocation = $storageLocation;
- }
-
- /**
- * Returns the storage location
- * @return StorageLocation the storage location
- */
- public function getStorageLocation () {
- return $this->storageLocation;
- }
-
- /**
- *
- * Serializes this storage location image
- * @return array The serialized storage location image
- */
- public function serialize () {
- return array("id" => $this->getId(), "storageLocation_id" => $this->getStorageLocation()->getId());
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/StorageLocation/StorageLocationManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/StorageLocation/StorageLocationManager.php
@@ -1,94 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\StorageLocation;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Category\CategoryManager,
- de\RaumZeitLabor\PartKeepr\StorageLocation\Exceptions\StorageLocationNotFoundException;
-
-class StorageLocationManager extends Singleton {
- public function getStorageLocations ($start = 0, $limit = 10, $sort = "footprint", $dir = "asc", $filter = "") {
-
- $qb = PartKeepr::getEM()->createQueryBuilder();
- $qb->select("st.id, st.name")->from("de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation","st");
-
- if ($filter != "") {
- $qb = $qb->where("LOWER(st.name) LIKE :filter");
- $qb->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- if ($limit > -1) {
- $qb->setMaxResults($limit);
- $qb->setFirstResult($start);
- }
-
- $qb->orderBy("st.".$sort, $dir);
-
- $query = $qb->getQuery();
-
- $result = $query->getResult();
-
- $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
- $totalQueryBuilder->select("COUNT(st.id)")->from("de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation","st");
-
-
-
- if ($filter != "") {
- $totalQueryBuilder = $totalQueryBuilder->where("LOWER(st.name) LIKE :filter");
- $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- $totalQuery = $totalQueryBuilder->getQuery();
-
- return array("data" => $result, "start" => $start, "totalCount" => $totalQuery->getSingleScalarResult());
- }
-
- public function getStorageLocation ($id) {
- $storageLocation = PartKeepr::getEM()->find("de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation", $id);
-
- if ($storageLocation) {
- return $storageLocation;
- } else {
- throw new StorageLocationNotFoundException();
- }
- }
-
- public function getStorageLocationByName ($name) {
- $query = PartKeepr::getEM()->createQuery("SELECT s FROM de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocation s WHERE s.name = :name");
- $query->setParameter("name", $name);
-
- return $query->getSingleResult();
- }
-
- public function addStorageLocation ($name) {
- $storageLocation = new StorageLocation();
- $storageLocation->setName($name);
-
- PartKeepr::getEM()->persist($storageLocation);
- PartKeepr::getEM()->flush();
-
- return $storageLocation;
- }
- public function deleteStorageLocation ($id) {
- $storageLocation = $this->getStorageLocation($id);
-
- PartKeepr::getEM()->remove($storageLocation);
- PartKeepr::getEM()->flush();
- }
-
- public function getOrCreateStorageLocation ($storageLocation) {
- if (is_int($storageLocation)) {
- try {
- return $this->getStorageLocation($storageLocation);
- } catch (StorageLocationNotFoundException $e) {}
- }
-
- $sl = new StorageLocation();
- $sl->setName($storageLocation);
-
- PartKeepr::getEM()->persist($sl);
-
- return $sl;
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/StorageLocation/StorageLocationService.php b/src/backend/de/RaumZeitLabor/PartKeepr/StorageLocation/StorageLocationService.php
@@ -1,108 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\StorageLocation;
-
-use de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\Part\PartManager,
- de\RaumZeitLabor\PartKeepr\Util\SerializableException,
- de\RaumZeitLabor\PartKeepr\Stock\StockEntry,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class StorageLocationService extends Service implements RestfulService {
-
- public function get () {
- if ($this->hasParameter("id")) {
- return array("data" => StorageLocationManager::getInstance()->getStorageLocation($this->getParameter("id"))->serialize());
- } else {
- if ($this->hasParameter("sort")) {
- $tmp = json_decode($this->getParameter("sort"), true);
-
- $aSortParams = $tmp[0];
- } else {
- $aSortParams = array(
- "property" => "name",
- "direction" => "ASC");
- }
- return StorageLocationManager::getInstance()->getStorageLocations(
- $this->getParameter("start", $this->getParameter("start", 0)),
- $this->getParameter("limit", $this->getParameter("limit", 25)),
- $this->getParameter("sortby", $aSortParams["property"]),
- $this->getParameter("dir", $aSortParams["direction"]),
- $this->getParameter("query", ""));
- }
- }
-
- public function create () {
- $this->requireParameter("name");
-
- $storageLocation = new StorageLocation();
- $storageLocation->deserialize($this->getParameters());
-
- PartKeepr::getEM()->persist($storageLocation);
-
- try {
- PartKeepr::getEM()->flush();
- } catch (\PDOException $e) {
- if ($e->getCode() == "23505") {
- $exception = new SerializableException(sprintf(PartKeepr::i18n("Storage Location %s already exists!"), $storageLocation->getName()));
- $exception->setDetail(sprintf(PartKeepr::i18n("You tried to add the storage location %s, but a storage location with the same name already exists."), $storageLocation->getName()));
-
- throw $exception;
- } else {
- throw $e;
- }
- }
-
-
- return array("data" => $storageLocation->serialize());
- }
-
- public function update () {
- $this->requireParameter("id");
- $this->requireParameter("name");
- $storageLocation = StorageLocationManager::getInstance()->getStorageLocation($this->getParameter("id"));
- $storageLocation->deserialize($this->getParameters());
-
- PartKeepr::getEM()->flush();
-
- return array("data" => $storageLocation->serialize());
-
- }
-
- public function destroy () {
- $this->requireParameter("id");
-
- StorageLocationManager::getInstance()->deleteStorageLocation($this->getParameter("id"));
-
- return array("data" => null);
- }
-
- /**
- * Creates multiple storage locations at once.
- *
- * Requires that the parameter "storageLocations" is set to an array with the names of the storage locations.
- * Returns all error messages as "data" index in the result array.
- */
- public function massCreate () {
- $this->requireParameter("storageLocations");
-
- $aMessages = array();
-
- foreach ($this->getParameter("storageLocations") as $storageLocation) {
- try {
- $obj = StorageLocationManager::getInstance()->getStorageLocationByName($storageLocation);
- $aMessages[] = sprintf(PartKeepr::i18n("Storage Location %s already exists"), $storageLocation);
- } catch (\Exception $e) {
- $obj = new StorageLocation();
- $obj->setName($storageLocation);
- PartKeepr::getEM()->persist($obj);
- }
-
- }
-
- PartKeepr::getEM()->flush();
-
- return array("data" => $aMessages);
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/System/SystemInformationRecord.php b/src/backend/de/RaumZeitLabor/PartKeepr/System/SystemInformationRecord.php
@@ -1,55 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\System;
-
-/**
- * This class represents a system information record.
- *
- * This is basically a category, a name and a value. No logic included within
- * the class.
- *
- * For example, records could hold:
- *
- * Name Value Category
- * =====================================================================================
- * Doctrine ORM 2.1.0 Libraries
- * Doctrine DBAL 2.1.0 Libraries
- * Doctrine Migrations git-f87afe9223dbfecaaddb Libraries
- *
- * PHP Version 5.3.2 Server Software
- * Operating System Linux (Funtoo Linux - baselayout 2.1.8) Server Software
-
- * @author felicitus
- *
- */
-class SystemInformationRecord {
- /**
- * Holds the category name
- * @var string
- */
- public $category;
-
- /**
- * Holds the name
- * @var string
- */
- public $name;
-
- /**
- * Holds the value
- * @var mixed
- */
- public $value;
-
- /**
- * Creates a new system information record.
- *
- * @param string $name
- * @param mixed $value
- * @param string $category
- */
- public function __construct ($name, $value, $category) {
- $this->name = $name;
- $this->value = $value;
- $this->category = $category;
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/System/SystemService.php b/src/backend/de/RaumZeitLabor/PartKeepr/System/SystemService.php
@@ -1,99 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\System;
-
-use de\RaumZeitLabor\PartKeepr\Util\Configuration,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\CronLogger\CronLoggerManager,
- de\RaumZeitLabor\PartKeepr\Util\OS\OperatingSystem;
-
-class SystemService extends Service {
- /**
- * Returns a list of system information records.
- *
- * Please note that it is not defined which information is returned; the result
- * should be seen as "informational" to the system operator, not for automated purposes.
- */
- public function getSystemInformation () {
- $aData = array();
-
- $aData[] = new SystemInformationRecord("Doctrine ORM", \Doctrine\ORM\Version::VERSION, "Libraries");
- $aData[] = new SystemInformationRecord("Doctrine DBAL", \Doctrine\DBAL\Version::VERSION, "Libraries");
-
- $aData[] = new SystemInformationRecord("PHP Version", phpversion(), "System");
-
- $os = new OperatingSystem();
-
- $aData[] = new SystemInformationRecord("Operating System Type", $os->getPlatform(), "System");
- $aData[] = new SystemInformationRecord("Operating System Release", $os->getRelease(), "System");
-
- $aData[] = new SystemInformationRecord("memory_limit", ini_get("memory_limit"), "PHP");
- $aData[] = new SystemInformationRecord("post_max_size", ini_get("post_max_size"), "PHP");
- $aData[] = new SystemInformationRecord("upload_max_filesize", ini_get("upload_max_filesize"), "PHP");
- $aData[] = new SystemInformationRecord("post_max_size", ini_get("post_max_size"), "PHP");
- $aData[] = new SystemInformationRecord("allow_url_fopen", ini_get("allow_url_fopen"), "PHP");
- $aData[] = new SystemInformationRecord("max_execution_time", ini_get("max_execution_time"), "PHP");
- $aData[] = new SystemInformationRecord("APC enabled", (extension_loaded("apc") ? PartKeepr::i18n("Yes") : PartKeepr::i18n("No")), "PHP");
-
- $aData[] = new SystemInformationRecord("PartKeepr Version", PartKeepr::getVersion(), "PartKeepr");
-
-
- foreach (Configuration::getOptions() as $key => $value) {
-
- // Hide passwords
- if ($key == "partkeepr.database.password" || $key == "partkeepr.migration.partdb.password") {
- $value = "<hidden>";
- }
-
- $aData[] = new SystemInformationRecord($key, $value, "PartKeepr Configuration Information");
- }
-
- return array("data" => $aData);
- }
-
- /**
- * Returns the database schema status.
- *
- * This method is usuall called once the user logs in, and alerts him if the schema is not up-to-date.
- *
- * Returns either status incomplete if the schema is not up-to-date, or complete if everything is OK.
- */
- public function getSystemStatus () {
-
- if (Configuration::getOption("partkeepr.cronjobs.disablecheck", false) === true) {
- // Skip cronjob tests
- $inactiveCronjobs = array();
- } else {
- $inactiveCronjobs = CronLoggerManager::getInstance()->getInactiveCronjobs();
- }
-
-
- return array("data" =>
- array(
- "inactiveCronjobCount" => count($inactiveCronjobs),
- "inactiveCronjobs" => $inactiveCronjobs,
- "schemaStatus" => $this->getSchemaStatus()));
- }
-
- /**
- * Checks if the schema is up-to-date. If yes, it returns "complete", if not, it returns "incomplete".
- *
- * @param none
- * @return string Either "complete" or "incomplete"
- */
- protected function getSchemaStatus () {
- $metadatas = PartKeepr::getEM()->getMetadataFactory()->getAllMetadata();
-
- $schemaTool = new \Doctrine\ORM\Tools\SchemaTool(PartKeepr::getEM());
-
- $queries = $schemaTool->getUpdateSchemaSql($metadatas, true);
-
- if (count($queries) > 0) {
- return "incomplete";
- } else {
- return "complete";
- }
- }
-
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/SystemNotice/SystemNotice.php b/src/backend/de/RaumZeitLabor/PartKeepr/SystemNotice/SystemNotice.php
@@ -1,141 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\SystemNotice;
-
-use de\RaumZeitLabor\PartKeepr\UploadedFile\UploadedFile,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Util\Deserializable;
-
-/**
- * Holds a system notice
- * @Entity
- **/
-class SystemNotice extends BaseEntity implements Serializable {
- /**
- * @Column(type="datetime")
- * @var \DateTime
- */
- private $date;
-
- /**
- * @Column(type="string")
- * @var string
- */
- private $title;
-
- /**
- * The description of this attachment
- * @Column(type="text")
- * @var string
- */
- private $description;
-
- /**
- * Defines if the system notice has been acknowledged
- * @Column(type="boolean")
- * @var boolean
- */
- private $acknowledged = false;
-
- /**
- * Specifies the type. This is required for unique notices which shouldn't pop up every time we create them.
- * @Column(type="string")
- * @var string
- */
- private $type;
-
- /**
- * Sets the date and time for this entry
- * @param \DateTime $date The date and time
- */
- public function setDate (\DateTime $date) {
- $this->date = $date;
- }
-
- /**
- * Returns the date and time for this entry
- *
- * @return \DateTime the date and time for this entry
- */
- public function getDate () {
- return $this->date;
- }
-
- /**
- * Sets the title for this entry
- * @param string $title the title for this entry
- */
- public function setTitle ($title) {
- $this->title = $title;
- }
-
- /**
- * Returns the title for this entry
- * @return string the title
- */
- public function getTitle () {
- return $this->title;
- }
-
- /**
- * Sets the description
- * @param string $description
- */
- public function setDescription ($description) {
- $this->description = $description;
- }
-
- /**
- * Returns the description
- * @return string The description
- */
- public function getDescription () {
- return $this->description;
- }
-
- /**
- * Sets the value of the acknowledged flag
- * @param boolean $bAck True if the notice should be acknowledged (default), false otherwise
- */
- public function setAcknowledgedFlag ($bAck = true) {
- $this->acknowledged = $bAck;
- }
-
- /**
- * Returns the value of the acknowledged flag
- *
- * @return boolean true if this notice has been acknowledged, false otherwise
- */
- public function getAcknowledgedFlag () {
- return $this->acknowledged;
- }
-
- /**
- * Sets the type of this entry
- * @param string $type
- */
- public function setType ($type) {
- $this->type = $type;
- }
-
- /**
- * Returns the type of this entry
- * @return string The type
- */
- public function getType () {
- return $this->type;
- }
-
- /**
- * Serializes this system notice attachment
- * @return array The serialized system notice
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "date" => $this->getDate()->format("Y-m-d H:i:s"),
- "title" => $this->getTitle(),
- "description" => $this->getDescription(),
- "acknowledged" => $this->getAcknowledgedFlag());
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/SystemNotice/SystemNoticeManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/SystemNotice/SystemNoticeManager.php
@@ -1,55 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\SystemNotice;
-
-use de\RaumZeitLabor\PartKeepr\Manager\AbstractManager,
- de\RaumZeitLabor\PartKeepr\Project\Project,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class SystemNoticeManager extends AbstractManager {
- /**
- * Returns the FQCN for the target entity to operate on.
- * @return string The FQCN, e.g. de\RaumZeitLabor\PartKeepr\Part
- */
- public function getEntityName () {
- return 'de\RaumZeitLabor\PartKeepr\SystemNotice\SystemNotice';
- }
-
- /**
- * Returns all fields which need to appear in the getList ResultSet.
- * @return array An array of all fields which should be returned
- */
- public function getQueryFields () {
- return array("id", "title", "date");
- }
-
- /**
- * Returns the default sort field
- *
- * @return string The default sort field
- */
- public function getDefaultSortField () {
- return "date";
- }
-
- public function createUniqueSystemNotice ($type, $title, $description) {
- $dql = "SELECT sn FROM de\RaumZeitLabor\PartKeepr\SystemNotice\SystemNotice sn WHERE sn.type = :type";
- $query = PartKeepr::getEM()->createQuery($dql);
-
- $query->setParameter("type", $type, \PDO::PARAM_BOOL);
-
- try {
- $notice = $query->getSingleResult();
- } catch (\Exception $e) {
- $notice = new SystemNotice();
- PartKeepr::getEM()->persist($notice);
- }
-
- $notice->setDate(new \DateTime());
- $notice->setTitle($title);
- $notice->setDescription($description);
- $notice->setType($type);
-
- PartKeepr::getEM()->flush();
-
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/SystemNotice/SystemNoticeService.php b/src/backend/de/RaumZeitLabor/PartKeepr/SystemNotice/SystemNoticeService.php
@@ -1,83 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\SystemNotice;
-
-use de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Manager\ManagerFilter;
-
-class SystemNoticeService extends Service implements RestfulService {
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
- */
- public function get () {
- if ($this->hasParameter("id")) {
- return array("data" => SystemNoticeManager::getInstance()->getEntity($this->getParameter("id"))->serialize());
- } else {
- $parameters = new ManagerFilter($this);
- $parameters->setFilterCallback(array($this, "filterCallback"));
-
- return SystemNoticeManager::getInstance()->getList($parameters);
- }
- }
-
- public function filterCallback ($queryBuilder) {
- $queryBuilder->andWhere("q.acknowledged = :acknowledged");
- $queryBuilder->setParameter("acknowledged", false, \PDO::PARAM_BOOL);
- }
- /**
- * Stub method to fulfill the RestfulService. We don't want to have SystemNotices created by the user, so
- * we bail out with an exception.
- *
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::create()
- */
- public function create () {
- throw new \Exception("Not implemented");
- }
-
- /**
- * Stub method to fulfill the RestfulService. We don't want to have SystemNotices updated by the user, so
- * we bail out with an exception.
- *
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update()
- */
- public function update () {
- throw new \Exception("Not implemented");
-
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::destroy()
- */
- public function destroy () {
- $this->requireParameter("id");
-
- SystemNoticeManager::getInstance()->deleteEntity($this->getParameter("id"));
-
- return array("data" => null);
- }
-
- public function acknowledge () {
- $this->requireParameter("id");
-
- $entity = SystemNoticeManager::getInstance()->getEntity($this->getParameter("id"));
- $entity->setAcknowledgedFlag();
- }
-
- public function hasUnacknowledgedNotices () {
- $dql = "SELECT COUNT(c) FROM de\RaumZeitLabor\PartKeepr\SystemNotice\SystemNotice c WHERE c.acknowledged = :a";
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("a", false, \PDO::PARAM_BOOL);
-
- $bRetval = false;
-
- if ($query->getSingleScalarResult() > 0) {
- $bRetval = true;
- }
- return array("data" => array("unacknowledgedNotices" => $bRetval));
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/TempFile/TempFileService.php b/src/backend/de/RaumZeitLabor/PartKeepr/TempFile/TempFileService.php
@@ -1,72 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\TempFile;
-
-use de\RaumZeitLabor\PartKeepr\Service\Service;
-use de\RaumZeitLabor\PartKeepr\UploadedFile\TempUploadedFile;
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class TempFileService extends Service {
-
- public function upload () {
- $tmpFile = new TempUploadedFile();
-
- if (array_key_exists("userfile", $_FILES) && file_exists($_FILES["userfile"]["tmp_name"])) {
- $file = $_FILES['userfile']['tmp_name'];
- $filename = $_FILES['userfile']['name'];
-
- $tmpFile->replace($file);
- $tmpFile->setOriginalFilename(basename($filename));
- } elseif (array_key_exists("url", $_REQUEST)) {
- $tmpFile->replaceFromURL($_REQUEST["url"]);
- } else {
- throw new \Exception("Error: No valid file given");
- }
-
- PartKeepr::getEM()->persist($tmpFile);
- PartKeepr::getEM()->flush();
-
- return array("id" => $tmpFile->getId(), "extension" => $tmpFile->getExtension(), "size" => $tmpFile->getSize(), "originalFilename" => $tmpFile->getOriginalFilename());
- }
-
- /**
- * Receives a file via the service call.
- *
- * Parameters:
- * - filedata: needs to be base64-encoded.
- * - filename: The filename
- */
- public function jsonUpload () {
- $data = base64_decode($this->getParameter("filedata"));
- $filename = $this->getParameter("filename");
-
- $tempFile = tempnam("/tmp", "PWC");
- file_put_contents($tempFile, $data);
-
- $tmpFile = new TempUploadedFile();
- $tmpFile->replace($tempFile);
- $tmpFile->setOriginalFilename($filename);
-
- PartKeepr::getEM()->persist($tmpFile);
- PartKeepr::getEM()->flush();
-
- return $tmpFile->serialize();
- }
-
- /**
- * Processes data via HTTP POST. Reads php://input and creates a temporary image out of it.
- */
- public function uploadCam () {
- $tempFile = tempnam("/tmp", "PWC") . ".jpg";
- $result = file_put_contents( $tempFile, file_get_contents('php://input') );
-
- $image = new TempUploadedFile();
- $image->replace($tempFile);
- $image->setOriginalFilename(sprintf(PartKeepr::i18n("Cam photo of %s"), date("Y-m-d H:i:s")).".jpg");
-
- PartKeepr::getEM()->persist($image);
- PartKeepr::getEM()->flush();
-
- return array("id" => $image->getId(), "extension" => $image->getExtension(), "size" => $image->getSize(), "originalFilename" => $image->getOriginalFilename());
- }
-}
- -
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/TempImage/TempImage.php b/src/backend/de/RaumZeitLabor/PartKeepr/TempImage/TempImage.php
@@ -1,19 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\TempImage;
-
-use de\RaumZeitLabor\PartKeepr\Image\Exceptions\InvalidImageTypeException,
- de\RaumZeitLabor\PartKeepr\Util\Configuration,
- de\RaumZeitLabor\PartKeepr\Image\Image,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
- * Represents a temporary image. Temporary images are used when
- * a user uploaded an image, but not attached it to an entity.
- *
- * @Entity
- */
-class TempImage extends Image {
- public function __construct () {
- parent::__construct(Image::IMAGE_TEMP);
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/TempImage/TempImageService.php b/src/backend/de/RaumZeitLabor/PartKeepr/TempImage/TempImageService.php
@@ -1,30 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\TempImage;
-
-use de\RaumZeitLabor\PartKeepr\Service\Service;
-use de\RaumZeitLabor\PartKeepr\TempImage\TempImage;
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class TempImageService extends Service {
- public function upload () {
- $image = new TempImage();
-
- if (array_key_exists("userfile", $_FILES) && file_exists($_FILES["userfile"]["tmp_name"])) {
- $file = $_FILES['userfile']['tmp_name'];
- $filename = $_FILES['userfile']['name'];
-
- $image->replace($file);
- $image->setOriginalFilename(basename($filename));
- } elseif (array_key_exists("url", $_REQUEST)) {
- $image->replaceFromURL($_REQUEST["url"]);
- } else {
- throw new \Exception("Error: No valid file given");
- }
-
- PartKeepr::getEM()->persist($image);
- PartKeepr::getEM()->flush();
-
- return array("id" => $image->getId(), "extension" => $image->getExtension(), "size" => $image->getSize(), "originalFilename" => $image->getOriginalFilename());
- }
-}
- -
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/TipOfTheDay/TipOfTheDay.php b/src/backend/de/RaumZeitLabor/PartKeepr/TipOfTheDay/TipOfTheDay.php
@@ -1,114 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\TipOfTheDay;
-
-use de\RaumZeitLabor\PartKeepr\Util\Serializable;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-use de\RaumZeitLabor\PartKeepr\Util\Configuration;
-
-use de\RaumZeitLabor\PartKeepr\Util\BaseEntity;
-
-/**
- * Represents a tip of the day.
- *
- * Tips are stored on the central PartKeepr server in a wiki. However, we need to know a list of all tip pages
- * because the API has a limit per day. So basically, we sync the tip names from the wiki to the local system several
- * times a day and not each time an user logs in.
- *
- * Note: If you wish to link against a tip of the day, do it by name and not by id!
- *
- * @Entity
- **/
-class TipOfTheDay extends BaseEntity implements Serializable {
- /**
- * @Column(type="string")
- * @var string
- */
- private $name;
-
- /**
- * Sets the name for this tip
- * @param string $name The name
- */
- public function setName ($name) {
- $this->name = $name;
- }
-
- /**
- * Returns the name for this tip
- * @return string The name
- */
- public function getName () {
- return $this->name;
- }
-
- /**
- * Syncronizes the tip database against the master wiki.
- * @throws \Exception
- */
- public static function syncTips () {
- if (ini_get("allow_url_fopen") == 0) {
- throw new \Exception("allow_url_fopen is disabled, but required to query the TipOfTheDay database.");
- }
-
- $url = Configuration::getOption("partkeepr.tipoftheday.api", "http://partkeepr.org/wiki/api.php?action=query&list=categorymembers&cmtitle=Category:TipOfTheDay&format=json");
-
- $tipsString = file_get_contents($url);
-
-
- $aPageNames = self::extractPageNames($tipsString);
-
- self::updateTipDatabase($aPageNames);
- }
-
- /**
- * Updates the tip database. Expects an array of page names.
- *
- * This method clears all page names and re-creates them. This saves
- * alot of engineering, because we don't need to match contents
- * within the database against contents in an array.
- *
- * @param array $aPageNames The page names as array. Page names are stored as string.
- */
- private static function updateTipDatabase (array $aPageNames) {
- $dql = "DELETE FROM de\RaumZeitLabor\PartKeepr\TipOfTheDay\TipOfTheDay";
- $query = PartKeepr::getEM()->createQuery($dql);
-
- $query->execute();
-
- foreach ($aPageNames as $pageName) {
- $tip = new TipOfTheDay();
- $tip->setName($pageName);
- PartKeepr::getEM()->persist($tip);
- }
-
- PartKeepr::getEM()->flush();
- }
-
- /**
- * Extracts the page names from the mediawiki JSON returned.
- * @param string $response The encoded json string
- * @return array An array with the titles of each page
- */
- private static function extractPageNames ($response) {
- $aTipsStructure = json_decode($response, true);
- $aTips = $aTipsStructure["query"]["categorymembers"];
-
- $aPageNames = array();
-
- foreach ($aTips as $tip) {
- $aPageNames[] = $tip["title"];
- }
-
- return $aPageNames;
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Util.Serializable::serialize()
- */
- public function serialize () {
- return array( "name" => $this->getName() );
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/TipOfTheDay/TipOfTheDayHistory.php b/src/backend/de/RaumZeitLabor/PartKeepr/TipOfTheDay/TipOfTheDayHistory.php
@@ -1,51 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\TipOfTheDay;
-
-use de\RaumZeitLabor\PartKeepr\User\User;
-
-use de\RaumZeitLabor\PartKeepr\Util\Serializable;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-use de\RaumZeitLabor\PartKeepr\Util\Configuration;
-
-use de\RaumZeitLabor\PartKeepr\Util\BaseEntity;
-
-/**
- * Represents a tip of the day history entry.
- *
- * This entity stores each tip of the day the user has already seen.
- *
- * @Entity
- **/
-class TipOfTheDayHistory extends BaseEntity {
- /**
- * @Column(type="string")
- * @var string
- */
- private $name;
-
- /**
- * Defines the user
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\User\User")
- * @var StorageLocation
- */
- private $user;
-
- /**
- * Sets the user for this entry
- * @param User $user
- */
- public function setUser (User $user) {
- $this->user = $user;
- }
-
- /**
- * Sets the tip of the day name the user already has seen
- * @param string $name The tip name
- */
- public function setName ($name) {
- $this->name = $name;
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/TipOfTheDay/TipOfTheDayService.php b/src/backend/de/RaumZeitLabor/PartKeepr/TipOfTheDay/TipOfTheDayService.php
@@ -1,86 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\TipOfTheDay;
-
-use de\RaumZeitLabor\PartKeepr\Util\Configuration,
- de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-class TipOfTheDayService extends Service implements RestfulService {
- /**
- * Returns all tips along with the information wether they are read or not.
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
- */
- public function get () {
- $aTips = array();
- $url = Configuration::getOption("partkeepr.tipoftheday.wiki", "http://partkeepr.org/wiki/index.php/");
-
- /* Extract all tips which aren't read */
- $dql = "SELECT d FROM de\RaumZeitLabor\PartKeepr\TipOfTheDay\TipOfTheDay d WHERE d.name NOT IN ";
- $dql .= "(SELECT dh.name FROM de\RaumZeitLabor\PartKeepr\TipOfTheDay\TipOfTheDayHistory dh WHERE dh.user = :user)";
-
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("user", SessionManager::getCurrentSession()->getUser());
-
- foreach ($query->getResult() as $result) {
- $aTips[] = array (
- "name" => $result->getName(),
- "read" => false,
- "url" => $url.$result->getName() . "?useskin=monobookplain");
- }
-
- /* Extract all tips which are read */
- $dql = "SELECT d FROM de\RaumZeitLabor\PartKeepr\TipOfTheDay\TipOfTheDay d WHERE d.name IN ";
- $dql .= "(SELECT dh.name FROM de\RaumZeitLabor\PartKeepr\TipOfTheDay\TipOfTheDayHistory dh WHERE dh.user = :user)";
-
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("user", SessionManager::getCurrentSession()->getUser());
-
- foreach ($query->getResult() as $result) {
- $aTips[] = array (
- "name" => $result->getName(),
- "read" => true,
- "url" => $url.$result->getName() . "?useskin=monobookplain");
- }
-
- return array("data" => $aTips);
- }
-
- public function create() {}
- public function update () {}
- public function destroy () {}
-
- /**
- * Marks a specific tip as read.
- *
- * Uses the parameter "name" to identify the tip.
- */
- public function markTipAsRead () {
- $this->requireParameter("name");
-
- try {
- $th = new TipOfTheDayHistory;
- $th->setUser($this->getUser());
- $th->setName($this->getParameter("name"));
-
- PartKeepr::getEM()->persist($th);
- PartKeepr::getEM()->flush();
- } catch (\Exception $e) {
- /* Do nothing */
- }
-
- }
-
- /**
- * Marks all tips as unread for the current user
- */
- public function markAllTipsAsUnread () {
- $dql = "DELETE FROM de\RaumZeitLabor\PartKeepr\TipOfTheDay\TipOfTheDayHistory th WHERE th.user = :user";
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("user", $this->getUser());
- $query->execute();
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Unit/Unit.php b/src/backend/de/RaumZeitLabor/PartKeepr/Unit/Unit.php
@@ -1,130 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Unit;
-
-use de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Util\Exceptions\OutOfRangeException,
- de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefix;
-
-
-/**
- * This object represents an unit. Units can be: Volt, Hertz etc.
- *
- * @Entity
- **/
-class Unit extends BaseEntity implements Serializable, Deserializable {
- /**
- * The name of the unit (e.g. Volts, Ampere, Farad, Metres)
- * @Column(type="string")
- * @var string
- */
- private $name;
-
- /**
- * The symbol of the unit (e.g. V, A, F, m)
- * @Column(type="string")
- * @var string
- */
- private $symbol;
-
- /**
- * Defines the allowed SiPrefixes for this parameter unit
- * @ManyToMany(targetEntity="de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefix")
- * @JoinTable(name="UnitSiPrefixes",
- * joinColumns={@JoinColumn(name="unit_id", referencedColumnName="id")},
- * inverseJoinColumns={@JoinColumn(name="siprefix_id", referencedColumnName="id")}
- * )
- * @var ArrayCollection
- */
- private $prefixes;
-
- /**
- * Creates a new Unit.
- */
- public function __construct () {
- $this->prefixes = new \Doctrine\Common\Collections\ArrayCollection();
- }
-
- /**
- * Sets the name for this unit
- * @param string $name the name for this unit
- */
- public function setName ($name) {
- $this->name = $name;
- }
-
- /**
- * Returns the name for this unit
- * @return string The unit name
- */
- public function getName () {
- return $this->name;
- }
-
- /**
- * Sets the symbol for this unit
- * @param string $symbol The symbol
- */
- public function setSymbol ($symbol) {
- $this->symbol = $symbol;
- }
-
- /**
- * Returns the symbol for this unit
- * @return string The symbol
- */
- public function getSymbol () {
- return $this->symbol;
- }
-
- /**
- * Returns the si-prefix list for this unit
- * @return array An array of SiPrefix objects
- */
- public function getPrefixes () {
- return $this->prefixes;
- }
-
- /**
- * Serializes the user object and returns it as array, suitable
- * to process via json_encode.
- * @param none
- * @return array An array containing the object information
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "name" => $this->getName(),
- "symbol" => $this->getSymbol(),
- "prefixes" => $this->serializeChildren($this->getPrefixes())
- );
- }
-
- /**
- * Deserializes the unit
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "name":
- $this->setName($value);
- break;
- case "symbol":
- $this->setSymbol($value);
- break;
- case "prefixes":
- $prefixes = $this->getPrefixes();
- $prefixes->clear();
-
- foreach ($value as $prefix) {
- $prefix = SiPrefix::loadById($prefix["id"]);
- $prefixes->add($prefix);
- }
- break;
- }
- }
- }
-}-
\ 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
@@ -1,99 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Unit;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Unit\Exceptions\UnitNotFoundException;
-
-class UnitManager extends Singleton {
- public function getUnits ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
-
- $qb = PartKeepr::getEM()->createQueryBuilder();
- $qb->select("u.id, u.name, u.symbol")->from("de\RaumZeitLabor\PartKeepr\Unit\Unit","u");
-
- if ($filter != "") {
- $qb = $qb->where("LOWER(u.name) LIKE :filter");
- $qb->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- if ($limit > -1) {
- $qb->setMaxResults($limit);
- $qb->setFirstResult($start);
- }
-
- $qb->orderBy("u.".$sort, $dir);
-
- $query = $qb->getQuery();
-
- $result = $query->getResult();
-
- $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
- $totalQueryBuilder->select("COUNT(u.id)")->from("de\RaumZeitLabor\PartKeepr\Unit\Unit","u");
-
-
-
- if ($filter != "") {
- $totalQueryBuilder = $totalQueryBuilder->where("LOWER(u.name) LIKE :filter");
- $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- $totalQuery = $totalQueryBuilder->getQuery();
-
- foreach ($result as $key => $value) {
- $result[$key]["prefixes"] = $this->getSiPrefixes($value["id"]);
- }
-
- return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
- }
-
- public function getSiPrefixes ($id) {
- $unit = UnitManager::getInstance()->getUnit($id);
-
- $aData = array();
-
- foreach ($unit->getPrefixes() as $prefix) {
- $aData[] = $prefix->serialize();
- }
-
- 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);
-
- if ($unit) {
- return $unit;
- } else {
- throw new UnitNotFoundException();
- }
- }
-
- public function deleteUnit ($id) {
- $unit = $this->getUnit($id);
-
- PartKeepr::getEM()->remove($unit);
- PartKeepr::getEM()->flush();
- }
-
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Unit/UnitService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Unit/UnitService.php
@@ -1,67 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Unit;
-
-use de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Part\PartUnit,
- de\RaumZeitLabor\PartKeepr\SiPrefix\SiPrefix,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class UnitService extends Service implements RestfulService {
- public function get () {
- if ($this->hasParameter("id")) {
- return array("data" => UnitManager::getInstance()->getUnit($this->getParameter("id"))->serialize());
- } else {
- if ($this->hasParameter("sort")) {
- $tmp = json_decode($this->getParameter("sort"), true);
-
- $aSortParams = $tmp[0];
- } else {
- $aSortParams = array(
- "property" => "name",
- "direction" => "ASC");
- }
- return UnitManager::getInstance()->getUnits(
- $this->getParameter("start", $this->getParameter("start", 0)),
- $this->getParameter("limit", $this->getParameter("limit", 25)),
- $this->getParameter("sortby", $aSortParams["property"]),
- $this->getParameter("dir", $aSortParams["direction"]),
- $this->getParameter("query", ""));
- }
- }
-
- public function create () {
- $this->requireParameter("name");
-
- $unit = new Unit;
- $unit->deserialize($this->getParameters());
-
- PartKeepr::getEM()->persist($unit);
- PartKeepr::getEM()->flush();
-
- return array("data" => $unit->serialize());
- }
-
- public function update () {
- $this->requireParameter("id");
- $this->requireParameter("name");
-
- $unit = UnitManager::getInstance()->getUnit($this->getParameter("id"));
- $unit->deserialize($this->getParameters());
-
- PartKeepr::getEM()->flush();
-
- return array("data" => $unit->serialize());
-
- }
-
- public function destroy () {
- $this->requireParameter("id");
-
- UnitManager::getInstance()->deleteUnit($this->getParameter("id"));
-
- return array("data" => null);
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/UploadedFile/TempUploadedFile.php b/src/backend/de/RaumZeitLabor/PartKeepr/UploadedFile/TempUploadedFile.php
@@ -1,15 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\UploadedFile;
-
-/**
- * Represents a temporary file. Temporary files are used when
- * a user uploaded a file, but not attached it to an entity.
- *
- * @Entity
- */
-class TempUploadedFile extends UploadedFile {
- public function __construct () {
- parent::__construct();
- $this->setType("Temporary");
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/UploadedFile/UploadedFile.php b/src/backend/de/RaumZeitLabor/PartKeepr/UploadedFile/UploadedFile.php
@@ -1,301 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\UploadedFile;
-
-use de\RaumZeitLabor\PartKeepr\Util\SerializableException,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\UploadedFile\TempUploadedFile,
- de\RaumZeitLabor\PartKeepr\Util\Configuration;
-
-/**
- * @MappedSuperclass
- */
-abstract class UploadedFile extends BaseEntity implements Serializable {
- /**
- * Specifies the type of the file.
- *
- * @var string
- * @Column(type="string")
- **/
- private $type;
-
- /**
- * The unique filename of the file
- *
- * @var string
- * @Column(type="string")
- */
- private $filename;
-
- /**
- * The original name of the file
- * @Column(type="string",nullable=true)
- * @var string
- */
- private $originalname;
-
- /**
- * The mimetype for the file
- * @var string
- * @Column(type="string")
- */
- private $mimetype;
-
- /**
- * The size of the uploaded file
- * @Column(type="integer")
- * @var integer
- */
- private $size;
-
- /**
- * Constructs a new file object.
- *
- */
- public function __construct () {
- $this->filename = PartKeepr::createGUIDv4();
- }
-
- /**
- * Sets the type of the file. Once the type is set,
- * it may not be changed later.
- */
- protected function setType ($type) {
- $this->type = $type;
- }
-
- /**
- * Returns the original filename
- * @return string The original filename
- */
- public function getOriginalFilename () {
- return $this->originalname;
- }
-
- /**
- * Sets the original filename
- * @param string $filename The original filename
- */
- public function setOriginalFilename ($filename) {
- $this->originalname = $filename;
- }
-
- /**
- * Replaces the current file with a new file.
- *
- * @param string $path The path to the original file
- */
- public function replace ($path) {
- // Parse the file's mimetype
- $finfo = new \finfo(FILEINFO_MIME);
- $this->mimetype = $finfo->file($path, FILEINFO_MIME_TYPE);
-
- // Get the file size
- $this->size = filesize($path);
-
- $this->ensureFilePathExists();
- $this->checkPermissions();
-
- copy($path, $this->getFilename());
-
- $this->setOriginalFilename(basename($path));
- }
-
- /**
- * Replaces the file from an URL. Does some tricks to avoid 403 forbidden on some sites.
- * @param string $url
- */
- public function replaceFromURL ($url) {
-
- /* Some sites don't like automated requests. But the internet is meant to be open for anybody,
- * even for scripts. So we are evil and fake the headers.
- *
- * Credit goes to Ryan Rampersad from whom I copied most code.
- * http://blog.ryanrampersad.com/2008/11/07/get-remote-html-with-curl-and-php/
- */
- $curl = curl_init();
-
- $header[0] = "Accept: text/xml,application/xml,application/xhtml+xml,";
- $header[0] .= "text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
- $header[] = "Cache-Control: max-age=0";
- $header[] = "Connection: keep-alive";
- $header[] = "Keep-Alive: 300";
- $header[] = "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7";
- $header[] = "Accept-Language: en-us,en;q=0.5";
- $header[] = "Pragma: ";
-
- $browser = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092510 Ubuntu/8.04 (hardy) Firefox/3.0.3";
-
- curl_setopt($curl, CURLOPT_URL, $url);
- curl_setopt($curl, CURLOPT_USERAGENT, $browser);
- curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
- curl_setopt($curl, CURLOPT_AUTOREFERER, true);
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($curl, CURLOPT_TIMEOUT, 30);
- curl_setopt($curl, CURLOPT_MAXREDIRS, 7);
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
-
- $data = curl_exec($curl);
-
- if ($data === false) {
- throw new \Exception("replaceFromURL error: ".curl_error($curl));
- }
-
- curl_close($curl);
-
- $tempName = tempnam("/tmp", "PARTKEEPR");
-
- file_put_contents($tempName, $data);
-
- $this->replace($tempName);
-
- $this->setOriginalFilename(basename($url));
- }
-
- /**
- * Returns the size of this file
- * @return integer The size in bytes
- */
- public function getSize () {
- return $this->size;
- }
-
- /**
- * Returns the type of the file
- * @param none
- * @return string The type of the file
- */
- public function getType () {
- return $this->type;
- }
-
- /**
- * Returns the full filename including path and suffix.
- * @return string The full filename
- */
- public function getFilename () {
- return $this->getFilePath().$this->filename.".".$this->getExtension();
- }
-
- /**
- * Returns the plain filename without path and suffix.
- * @return string the plain filename
- */
- public function getPlainFilename () {
- return $this->filename;
- }
-
- /**
- * Returns the mime type for this file
- * @return string The mimetype for this file, e.g. text/plain
- */
- public function getMimeType () {
- return $this->mimetype;
- }
-
- /**
- * Returns the extension for the given mime type.
- *
- * This function simply extracts that information from the mime type;
- * special cases are not handled. e.g. if you have image/foobar, it would
- * return "foobar" as extension.
- *
- * @return string The extension
- */
- public function getExtension () {
- list($category, $type) = explode("/", $this->getMimeType());
- return $type;
- }
-
- /**
- * Returns the path to the file. May be overridden by
- * subclasses.
- *
- * @param none
- * @return string The path to the file
- */
- public function getFilePath () {
- return Configuration::getOption(
- "partkeepr.files.path",
- PartKeepr::getRootDirectory() . "/data/") . $this->getType() . "/";
- }
-
- /**
- * Ensures that the file path exists. This function
- * is called every time a file is processed.
- * It is maybe a bit overhead, but saves headaches later when
- * introducing new types.
- *
- * @param none
- * @return nothing
- */
- public function ensureFilePathExists () {
- if (!is_dir($this->getFilePath())) {
- try {
- mkdir($this->getFilePath(), 0777, true);
- } catch (\Exception $e) {
- throw new \Exception("Unable to create directory ".$this->getFilePath());
- }
- }
- }
-
- /**
- * Creates a new entity from the given temporary id.
- *
- * @param string $id The temporary id (prefixed with TMP:)
- * @return object a new instance of the file.
- * @throws \Exception If the ID does not begin with TMP:
- */
- public static function createFromTemporaryFile ($id) {
- if (substr($id, 0, 4) === "TMP:") {
- // It's a temporary file
- $className = get_called_class();
-
- $file = new $className();
- $file->replaceFromTemporaryFile($id);
- return $file;
- } else {
- throw new \Exception("Given id $id is not a temporary file");
- }
- }
-
- /**
- * Replaces the file with a given temporary file.
- * @param string $id The temporary id (prefixed with TMP:)
- */
- public function replaceFromTemporaryFile ($id) {
- if (substr($id, 0, 4) === "TMP:") {
- $tmpFileId = str_replace("TMP:", "", $id);
- $tmpFile = TempUploadedFile::loadById($tmpFileId);
-
- $this->replace($tmpFile->getFilename());
- $this->setOriginalFilename($tmpFile->getOriginalFilename());
- }
- }
-
- /**
- * Checks if the path where the file should be stored has sufficient permissions to do so.
- *
- * @throws SerializableException
- */
- public function checkPermissions () {
- if (!is_writable($this->getFilePath())) {
- throw new SerializableException(
- sprintf(PartKeepr::i18n("Unable to write to directory %s"), $this->getFilePath()));
- }
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Util.Serializable::serialize()
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "extension" => $this->getExtension(),
- "size" => $this->getSize(),
- "originalFilename" => $this->getOriginalFilename()
- );
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/User/Exceptions/InvalidLoginDataException.php b/src/backend/de/RaumZeitLabor/PartKeepr/User/Exceptions/InvalidLoginDataException.php
@@ -1,14 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\User\Exceptions;
-
-use de\RaumZeitLabor\PartKeepr\Util\SerializableException,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
- * Is thrown when the user has given wrong credentials.
- */
-class InvalidLoginDataException extends SerializableException {
- public function __construct () {
- parent::__construct(PartKeepr::i18n("Username or Password wrong."));
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/User/Exceptions/UserAlreadyExistsException.php b/src/backend/de/RaumZeitLabor/PartKeepr/User/Exceptions/UserAlreadyExistsException.php
@@ -1,19 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\User\Exceptions;
-
-use de\RaumZeitLabor\PartKeepr\Util\SerializableException,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
-* Is thrown when the user already exists. This usually happens
-* if someone tries to create a user with the same name of an existing
-* user.
-*/
-class UserAlreadyExistsException extends SerializableException {
- public function __construct ($username) {
- parent::__construct(
- sprintf(
- PartKeepr::i18n("User %s already exists."),
- $username));
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/User/Exceptions/UserDoesNotExistException.php b/src/backend/de/RaumZeitLabor/PartKeepr/User/Exceptions/UserDoesNotExistException.php
@@ -1,17 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\User\Exceptions;
-
-use de\RaumZeitLabor\PartKeepr\Util\SerializableException,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
-* Is thrown when the user doesn't exist.
-*/
-class UserDoesNotExistException extends SerializableException {
- public function __construct ($username) {
- parent::__construct(
- sprintf(
- PartKeepr::i18n("The user %s doesn't exist. Maybe the user was already deleted."),
- $username));
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/User/User.php b/src/backend/de/RaumZeitLabor/PartKeepr/User/User.php
@@ -1,259 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\User;
-
-use de\RaumZeitLabor\PartKeepr\UserPreference\UserPreference;
-
-use de\RaumZeitLabor\PartKeepr\Util\Deserializable,
- de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/** @Entity @Table(name="PartKeeprUser") */
-class User extends BaseEntity implements Serializable, Deserializable {
- /** @Column(length=50,unique=true) */
- private $username;
-
- /** @Column(length=32) */
- private $password;
-
- /** @Column(type="boolean") */
- private $admin;
-
- /**
- * Creates a new user object.
- *
- * @param string $username The username to set (optional)
- * @param string $password The password to set (optional)
- */
- public function __construct ($username = null, $password = null) {
- if ($username !== null) {
- $this->setUsername($username);
- }
-
- if ($password !== null) {
- $this->setPassword($password);
- }
-
- $this->setAdmin(false);
- }
-
- /**
- * Sets the username.
- *
- * Forces the username to have
- * lowercase a-z characters.
- *
- * Replaces space with an underscore.
- * Replaces dot with nothing.
- *
- * @param string $username The username to set. Applies automatic username modification.
- * @return nothing
- */
- public function setUsername ($username) {
- $username = strtolower($username);
- $username = str_replace(" ", "_", $username);
- $username = str_replace(".", "", $username);
-
- $this->username = $username;
-
- }
-
- /**
- * Sets the raw username, without replacing any special chars.
- *
- * This method should only be used for building a temporary user
- * for login checks.
- *
- * @param string $username The raw username
- * @return nothing
- */
- public function setRawUsername ($username) {
- $this->username = $username;
- }
-
- /**
- * Returns the username.
- * @param none
- * @return string The username
- */
- public function getUsername () {
- return $this->username;
- }
-
- /**
- * Sets the admin flag
- * @param boolean $bAdmin True if the user is an admin, false otherwise
- */
- public function setAdmin ($bAdmin) {
- $this->admin = (boolean)$bAdmin;
- }
-
- /**
- * Returns the admin flag
- * @return boolean True if the user is an admin
- */
- public function isAdmin () {
- return $this->admin;
- }
-
- /**
- * Sets the user's password. Automatically
- * applies md5 hashing.
- *
- * @param string $password
- */
- public function setPassword ($password) {
- $this->setHashedPassword(md5($password));
- }
-
- /**
- * Returns the user's md5-hashed password.
- * @param none
- * @return string The md5-hashed password
- */
- public function getHashedPassword () {
- return $this->password;
- }
-
- /**
- * Sets the user's password. Expects a hash
- * and does not apply md5 hasing.
- *
- * @param string $hashedPassword
- */
- public function setHashedPassword ($hashedPassword) {
- $this->password = $hashedPassword;
- }
-
- /**
- * Compares the given un-hashed password with the
- * object's hashed password.
- *
- *
- * @param string $password The unhashed password
- * @return boolean true if the passwords match, false otherwise
- */
- public function comparePassword ($password) {
- return $this->compareHashedPassword(md5($password));
- }
-
- /**
- * Compares the given hashed password with the object's
- * hashed password.
- *
- * @param string $hashedPassword The md5-hashed password
- * @return boolean true if the passwords match, false otherwise
- */
- public function compareHashedPassword ($hashedPassword) {
- if ($hashedPassword == $this->password) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Serializes the user object and returns it as array, suitable
- * to process via json_encode.
- * @param none
- * @return array An array containing the object information
- */
- public function serialize () {
- return array(
- "id" => $this->getId(),
- "username" => $this->getUsername()
- );
- }
-
- /**
- * Deserializes the user
- * @param array $parameters The array with the parameters to set
- */
- public function deserialize (array $parameters) {
- foreach ($parameters as $key => $value) {
- switch ($key) {
- case "username":
- $this->setUsername($value);
- break;
- case "password":
- if ($value !== "") {
- $this->setPassword($value);
- }
- break;
- }
- }
- }
-
- /**
- * Sets a user preference
- *
- * @param string $preferenceKey The preference key
- * @param string $preferenceValue The preference value
- * @throws EntityNotPersistantException Thrown if the entity is not persistant
- */
- public function setPreference ($preferenceKey, $preferenceValue) {
- return UserPreference::setPreference($this, $preferenceKey, $preferenceValue);
- }
-
- /**
- * Returns a given preference object
- *
- * @param string $preferenceKey The preference key
- * @return UserPreference The user preference object
- * @throws UserPreferenceNotFoundException If the preference key was not found
- * @throws EntityNotPersistantException Thrown if the entity is not persistant
- */
- public function getPreference ($preferenceKey) {
- return UserPreference::getPreference($this, $preferenceKey);
- }
-
- /**
- * Returns a given preference value
- *
- * @param string $preferenceKey The preference key
- * @return UserPreference The user preference object
- * @throws UserPreferenceNotFoundException If the preference key was not found
- * @throws EntityNotPersistantException Thrown if the entity is not persistant
- */
- public function getPreferenceValue ($preferenceKey) {
- return UserPreference::getPreferenceValue($this, $preferenceKey);
- }
-
- /**
- * Deletes the given preference
- *
- * @param string $preferenceKey The preference key
- * @return UserPreference The user preference object
- * @throws UserPreferenceNotFoundException If the preference key was not found
- * @throws EntityNotPersistantException Thrown if the entity is not persistant
- */
- public function deletePreference ($preferenceKey) {
- return UserPreference::deletePreference($this, $preferenceKey);
- }
-
- /**
- * Returns all user preferences for this user
- *
- * @param none
- * @return Array An array of UserPreference objects
- * @throws EntityNotPersistantException Thrown if the entity is not persistant
- */
- public function getPreferences () {
- return UserPreference::getPreferences($this);
- }
- /**
- * Loads a user by name.
- *
- * @param $username string The username to query
- * @return User A user object
- * @throws Doctrine\ORM\NoResultException If no user was found
- */
- public static function loadByName ($username) {
- $dql = "SELECT u FROM de\RaumZeitLabor\PartKeepr\User\User u WHERE u.username = :username";
-
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("username", $username);
-
- return $query->getSingleResult();
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/User/UserManager.php b/src/backend/de/RaumZeitLabor/PartKeepr/User/UserManager.php
@@ -1,135 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\User;
-
-use de\RaumZeitLabor\PartKeepr\Util\Singleton,
- de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\User\Exceptions\InvalidLoginDataException,
- de\RaumZeitLabor\PartKeepr\Category\CategoryManager,
- de\RaumZeitLabor\PartKeepr\User\Exceptions\UserAlreadyExistsException,
- de\RaumZeitLabor\PartKeepr\User\Exceptions\UserNotFoundException;
-
-class UserManager extends Singleton {
- /**
- * Returns a list of users.
- *
- * @param int $start Start of the list, default 0
- * @param int $limit Number of users to list, default 10
- * @param string $sort The field to sort by, default "name"
- * @param string $dir The direction to sort (ASC or DESC), default ASC
- * @param string $filter A string to filter the user's name by, default empty
- */
- public function getUsers ($start = 0, $limit = 10, $sort = "name", $dir = "asc", $filter = "") {
-
- $qb = PartKeepr::getEM()->createQueryBuilder();
- $qb->select("st.id, st.username")->from("de\RaumZeitLabor\PartKeepr\User\User","st");
-
- if ($filter != "") {
- $qb = $qb->where("LOWER(st.username) LIKE :filter");
- $qb->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- if ($limit > -1) {
- $qb->setMaxResults($limit);
- $qb->setFirstResult($start);
- }
-
- $qb->orderBy("st.".$sort, $dir);
-
- $query = $qb->getQuery();
-
- $result = $query->getResult();
-
- $totalQueryBuilder = PartKeepr::getEM()->createQueryBuilder();
- $totalQueryBuilder->select("COUNT(st.id)")->from("de\RaumZeitLabor\PartKeepr\User\User","st");
-
-
-
- if ($filter != "") {
- $totalQueryBuilder = $totalQueryBuilder->where("LOWER(st.username) LIKE :filter");
- $totalQueryBuilder->setParameter("filter", "%".strtolower($filter)."%");
- }
-
- $totalQuery = $totalQueryBuilder->getQuery();
-
- return array("data" => $result, "totalCount" => $totalQuery->getSingleScalarResult());
- }
-
- /**
- * Checks if the passed user already exists.
- *
- * @param $username string The username to check
- */
- public function userExists ($username) {
- $dql = "SELECT COUNT(u) FROM de\RaumZeitLabor\PartKeepr\User\User u WHERE u.username = :name";
-
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("name", $username);
-
- $count = $query->getSingleScalarResult();
-
- if ($count == 0) {
- return false;
- } else {
- return true;
- }
- }
-
- /**
- * Creates the given user. Checks if the user already exists
- *
- * @param User $user The user to create
- * @throws UserAlreadyExistsException
- */
- public function createUser (User $user) {
- if ($this->userExists($user->getUsername())) {
- throw new UserAlreadyExistsException($user->getUsername());
- }
-
- PartKeepr::getEM()->persist($user);
- PartKeepr::getEM()->flush();
- }
-
- /**
- * Returns the user for a given user id
- * @param integer $id The user id
- */
- public function getUser ($id) {
- return User::loadById($id);
- }
-
- /**
- * Deletes an user by id
- * @param int $id The user's id
- */
- public function deleteUser ($id) {
- $user = User::loadById($id);
-
- PartKeepr::getEM()->remove($user);
- PartKeepr::getEM()->flush();
- }
-
- /**
- * Authenticates the given user. If successful, an instance
- * of the user is returned.
- *
- * @param User $user The user to authenticate
- * @throws InvalidLoginDataException Thrown if the user's credentials are not valid
- */
- public function authenticate (User $user) {
- $result = PartKeepr::getEM()
- ->getRepository("de\RaumZeitLabor\PartKeepr\User\User")
- ->findOneBy(
- array(
- "username" => $user->getUsername(),
- "password" => $user->getHashedPassword()
- )
- );
-
- if ($result == null) {
- throw new InvalidLoginDataException();
- } else {
- return $result;
- }
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/User/UserService.php b/src/backend/de/RaumZeitLabor/PartKeepr/User/UserService.php
@@ -1,101 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\User;
-
-use de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager;
-
-class UserService extends Service implements RestfulService {
-
- /**
- * Implements the get() call for the RestfulService.
- *
- * If the "id" parameter is passed, try to return the user by id. If not,
- * return a list.
- *
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
- */
- public function get () {
- if ($this->hasParameter("id")) {
- if (!SessionManager::getCurrentSession()->getUser()->isAdmin()) {
- throw new \Exception("Permission denied");
- }
-
- return array("data" => UserManager::getInstance()->getUser($this->getParameter("id"))->serialize());
- } else {
- if ($this->hasParameter("sort")) {
- $tmp = json_decode($this->getParameter("sort"), true);
-
- $aSortParams = $tmp[0];
- } else {
- $aSortParams = array(
- "property" => "username",
- "direction" => "ASC");
- }
- return UserManager::getInstance()->getUsers(
- $this->getParameter("start", $this->getParameter("start", 0)),
- $this->getParameter("limit", $this->getParameter("limit", 25)),
- $this->getParameter("sortby", $aSortParams["property"]),
- $this->getParameter("dir", $aSortParams["direction"]),
- $this->getParameter("query", ""));
- }
- }
-
- /**
- * Creates a new user.
- *
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::create()
- */
- public function create () {
- if (!SessionManager::getCurrentSession()->getUser()->isAdmin()) {
- throw new \Exception("Permission denied");
- }
-
- $this->requireParameter("username");
-
- $user = new User;
- $user->deserialize($this->getParameters());
-
- UserManager::getInstance()->createUser($user);
-
- return array("data" => $user->serialize());
- }
-
- /**
- * Updates the user informations.
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update()
- */
- public function update () {
- if (!SessionManager::getCurrentSession()->getUser()->isAdmin()) {
- throw new \Exception("Permission denied");
- }
-
- $this->requireParameter("id");
- $this->requireParameter("username");
- $user = UserManager::getInstance()->getUser($this->getParameter("id"));
-
- $user->deserialize($this->getParameters());
- PartKeepr::getEM()->flush();
-
- return array("data" => $user->serialize());
-
- }
-
- /**
- * Deletes the user from the database.
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::destroy()
- */
- public function destroy () {
- if (!SessionManager::getCurrentSession()->getUser()->isAdmin()) {
- throw new \Exception("Permission denied");
- }
-
- $this->requireParameter("id");
-
- UserManager::getInstance()->deleteUser($this->getParameter("id"));
-
- return array("data" => null);
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/UserPreference/Exceptions/UserPreferenceNotFoundException.php b/src/backend/de/RaumZeitLabor/PartKeepr/UserPreference/Exceptions/UserPreferenceNotFoundException.php
@@ -1,20 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\UserPreference\Exceptions;
-
-use de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\Util\SerializableException,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
- * Is thrown when the user has given wrong credentials.
- */
-class UserPreferenceNotFoundException extends SerializableException {
- public function __construct (User $user, $preferenceKey) {
- $message = sprintf( PartKeepr::i18n("User preference %s not found for user %s (%s)"),
- $preferenceKey,
- $user->getUsername(),
- $user->getId());
-
- parent::__construct($message);
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/UserPreference/UserPreference.php b/src/backend/de/RaumZeitLabor/PartKeepr/UserPreference/UserPreference.php
@@ -1,229 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\UserPreference;
-
-use de\RaumZeitLabor\PartKeepr\Util\Serializable,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\Util\Configuration,
- de\RaumZeitLabor\PartKeepr\Util\BaseEntity,
- de\RaumZeitLabor\PartKeepr\UserPreference\Exceptions\UserPreferenceNotFoundException,
- de\RaumZeitLabor\PartKeepr\Util\Exceptions\EntityNotPersistantException,
- Doctrine\ORM\NoResultException;
-
-/**
- * Represents a user preference entry.
- *
- * User preferences are a simple key => value mechanism, where the developer can
- * specify the key and value himself.
- *
- * Note that values are stored internally as serialized PHP values to keep their type.
- *
- * @Entity
- **/
-class UserPreference implements Serializable {
- /**
- * Defines the key of the user preference
- * @Column(type="string",length=255)
- * @Id
- * @var string
- */
- private $preferenceKey;
-
- /**
- * Defines the value. Note that the value is internally stored as a serialized string.
- * @Column(type="text")
- * @var mixed
- */
- private $preferenceValue;
-
- /**
- * Defines the user
- * @ManyToOne(targetEntity="de\RaumZeitLabor\PartKeepr\User\User")
- * @Id
- * @var User
- */
- private $user;
-
-
- /**
- * Sets the user for this entry
- * @param User $user
- */
- public function setUser (User $user) {
- $this->user = $user;
- }
-
- /**
- * Returns the user associated with this entry
- * @return \de\RaumZeitLabor\PartKeepr\User\User
- */
- public function getUser () {
- return $this->user;
- }
-
- /**
- * Sets the key for this user preference
- * @param string $key The key name
- */
- public function setKey ($key) {
- $this->preferenceKey = $key;
- }
-
- /**
- * Returns the key of this entry
- * @return string
- */
- public function getKey () {
- return $this->preferenceKey;
- }
-
- /**
- * Sets the value for this entry
- * @param mixed $value
- */
- public function setValue ($value) {
- $this->preferenceValue = serialize($value);
- }
-
- /**
- * Returns the value for this entry
- * @return mixed The value
- */
- public function getValue () {
- return unserialize($this->preferenceValue);
- }
-
- /**
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Util.Serializable::serialize()
- */
- public function serialize () {
- return array(
- "key" => $this->getKey(),
- "value" => $this->getValue(),
- "user_id" => $this->getUser()->getId()
- );
- }
-
- /**
- * Creates or updates a preference for a given user.
- *
- * @param User $user The user to set the preference for
- * @param string $key The key to set
- * @param string $value The value to set
- * @throws EntityNotPersistantException Thrown if the entity is not persistant
- */
- public static function setPreference (User $user, $key, $value) {
- if (!PartKeepr::getEM()->contains($user)) {
- throw new EntityNotPersistantException();
- }
-
- $dql = "SELECT up FROM de\RaumZeitLabor\PartKeepr\UserPreference\UserPreference up WHERE up.user = :user AND ";
- $dql .= "up.preferenceKey = :key";
-
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("user", $user);
- $query->setParameter("key", $key);
-
- try {
- $userPreference = $query->getSingleResult();
- } catch (\Exception $e) {
- $userPreference = new UserPreference();
- $userPreference->setUser($user);
- $userPreference->setKey($key);
-
- PartKeepr::getEM()->persist($userPreference);
- }
-
- $userPreference->setValue($value);
-
- PartKeepr::getEM()->flush();
-
- return $userPreference;
- }
-
- /**
- * Returns a specific preference value for the given user
- *
- * @param User $user The user to retrieve the preference for
- * @param string $key The preference key to retrieve
- * @return string The preference string
- * @throws UserPreferenceNotFoundException Thrown if the preference key was not found
- * @throws EntityNotPersistantException Thrown if the entity is not persistant
- */
- public static function getPreferenceValue (User $user, $key) {
- $userPreference = self::getPreference($user, $key);
-
- return $userPreference->getValue();
- }
-
- /**
- * Returns all preferences for the given user
- * @param User $user The user
- * @throws EntityNotPersistantException Thrown if the user entity is not persistent
- */
- public static function getPreferences (User $user) {
- if (!PartKeepr::getEM()->contains($user)) {
- throw new EntityNotPersistantException();
- }
-
- $dql = "SELECT up FROM de\RaumZeitLabor\PartKeepr\UserPreference\UserPreference up WHERE up.user = :user";
-
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("user", $user);
-
- return $query->getResult();
- }
-
- /**
- * Returns a specific preference object for the given user
- *
- * @param User $user The user to retrieve the preference for
- * @param string $key The preference key to retrieve
- * @return UserPreference The preference object
- * @throws UserPreferenceNotFoundException Thrown if the preference key was not found
- * @throws EntityNotPersistantException Thrown if the entity is not persistant
- */
- public static function getPreference (User $user, $key) {
- if (!PartKeepr::getEM()->contains($user)) {
- throw new EntityNotPersistantException();
- }
-
- $dql = "SELECT up FROM de\RaumZeitLabor\PartKeepr\UserPreference\UserPreference up WHERE up.user = :user AND ";
- $dql .= "up.preferenceKey = :key";
-
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("user", $user);
- $query->setParameter("key", $key);
-
- try {
- $up = $query->getSingleResult();
- return $up;
- } catch (NoResultException $e) {
- throw new UserPreferenceNotFoundException($user, $key);
- }
- }
-
- /**
- * Removes a specific setting for a specific user.
- *
- * @param User $user The user to delete the preference for
- * @param string $key The key to delete
- * @throws EntityNotPersistantException Thrown if the entity is not persistant
- */
- public static function deletePreference (User $user, $key) {
- if (!PartKeepr::getEM()->contains($user)) {
- throw new EntityNotPersistantException();
- }
-
- $dql = "DELETE FROM de\RaumZeitLabor\PartKeepr\UserPreference\UserPreference up WHERE up.user = :user AND ";
- $dql .= "up.preferenceKey = :key";
-
- $query = PartKeepr::getEM()->createQuery($dql);
- $query->setParameter("user", $user);
- $query->setParameter("key", $key);
-
- $query->execute();
- }
-
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/UserPreference/UserPreferenceService.php b/src/backend/de/RaumZeitLabor/PartKeepr/UserPreference/UserPreferenceService.php
@@ -1,96 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\UserPreference;
-
-use de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\Util\Configuration,
- de\RaumZeitLabor\PartKeepr\Service\RestfulService,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager,
- de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
- * Represents the user preference service. This service is implemented as a RestfulService, however,
- * only setting and deleting properties is supported, as we don't want to have duplicate values per key.
- *
- * For convinience, create() and update() perform the exact same function.
- * @author felicitus
- *
- */
-class UserPreferenceService extends Service implements RestfulService {
- /**
- * Returns the preferences for the current user, or a user specified by user_id (admin only).
- *
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
- */
- public function get () {
- $user = null;
-
- if ($this->hasParameter("user_id") && SessionManager::getCurrentSession()->getUser()->isAdmin()) {
- if ($this->getParameter("user_id") != 0) {
- $user = User::loadById($this->getParameter("user_id"));
- }
- } else {
- $user = SessionManager::getCurrentSession()->getUser();
- }
-
- $aPreferences = array();
-
- foreach ($user->getPreferences() as $result) {
- $aPreferences[] = $result->serialize();
- }
-
- return array("data" => $aPreferences);
- }
-
- /**
- * Creates or updates a value for a specific key.
- *
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::create()
- */
- public function create() {
- $userPreference = UserPreference::setPreference($this->getUser(), $this->getParameter("key"), $this->getParameter("value"));
-
- return array("data" => $userPreference->serialize());
- }
-
- /**
- * Creates or updates a value for a specific key.
- *
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update()
- */
- public function update () {
- return $this->create();
- }
-
- /**
- * Deletes a key-value combination from the database.
- *
- * (non-PHPdoc)
- * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::destroy()
- */
- public function destroy () {
- if ($this->hasParameter("user_id") && SessionManager::getCurrentSession()->getUser()->isAdmin()) {
- UserPreference::deletePreference(User::loadById($this->getParameter("user_id")), $this->getParameter("key"));
- } else {
- UserPreference::deletePreference($this->getUser(), $this->getParameter("key"));
- }
- }
-
- public function changePassword () {
- if (Configuration::getOption("partkeepr.frontend.allow_password_change", true) === false) {
- throw new \Exception("Password changing has been disabled on this server");
- }
-
- if (!$this->getUser()->compareHashedPassword($this->getParameter("oldpassword"))) {
- throw new \Exception("Invalid Password");
- } else {
- $this->getUser()->setHashedPassword($this->getParameter("newpassword"));
- }
-
- return array("data" => PartKeepr::i18n("Password changed successfully"));
-
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Util/BaseEntity.php b/src/backend/de/RaumZeitLabor/PartKeepr/Util/BaseEntity.php
@@ -1,116 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Util;
-
-use de\RaumZeitLabor\PartKeepr\Util\Exceptions\EntityNotFoundException,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/** @MappedSuperclass */
-class BaseEntity {
- /**
- * @Id @Column(type="integer")
- * @GeneratedValue(strategy="AUTO")
- * @var unknown_type
- */
- private $id;
-
- /**
- * Returns the ID of this object.
- * @param none
- * @return int The ID of this object
- */
- public function getId () {
- return $this->id;
- }
-
- /**
- * Syncs a given collection with the entity's collection.
- *
- * This is used for 1:n or m:n relations, where we need to process inserts, updates and deletes for the records.
- *
- * @param array $sourceArray The array with all records which should be deserialized
- * @param \Doctrine\Common\Collections\Collection $collection The collection which contains the existing records
- * @param string $entityClass The class name which is used when a new entity needs to be created
- */
- public function deserializeChildren (array $sourceArray, \Doctrine\Common\Collections\Collection $collection, $entityClass) {
- $deletes = array();
- $inserts = array();
-
- /* Round 1: Check if we've got a matching id in both lists. If yes, we know that the record
- * should be updated. If no, the record should be appended */
- foreach ($sourceArray as $sourceItem) {
- $bFound = false;
- foreach ($collection as $item) {
- if ($item->getId() == $sourceItem["id"]) {
- // Directly update
- $item->deserialize($sourceItem);
- $bFound = true;
- break;
- }
- }
-
- if (!$bFound) {
- $inserts[] = $sourceItem;
- }
- }
-
- /* Round 2: Check for items which are in the collection but not in the sourceArray. */
- foreach ($collection as $targetItem) {
- $bFound = false;
- foreach ($sourceArray as $item) {
- if ($targetItem->getId() == $item["id"]) {
- $bFound = true;
- break;
- }
- }
-
- if (!$bFound) {
- $deletes[] = $targetItem;
- }
- }
-
- foreach ($inserts as $item) {
- $class = new $entityClass;
- $class->deserialize($item);
-
- $collection->add($class);
- PartKeepr::getEM()->persist($class);
- }
-
- /* Remove the to-be-deleted items from the collection. Note that we store the instance of the item,
- * so we can simply use removeElement.
- */
- foreach ($deletes as $item) {
- $collection->removeElement($item);
- PartKeepr::getEM()->remove($item);
- }
- }
-
- /**
- * Serializes the children of a specific collection
- * @param \Doctrine\Common\Collections\Collection $array The array holding BaseEntities to serialize
- */
- public function serializeChildren (\Doctrine\Common\Collections\Collection $array) {
- $aData = array();
- $aData["totalCount"] = $array->count();
- $aData["data"] = array();
-
- foreach ($array as $item) {
- $aData["data"][] = $item->serialize();
- }
-
- return array("response" => $aData);
- }
-
- /**
- * Loads the entity from the database.
- * @param integer $id The entity's id
- */
- public static function loadById ($id) {
- $entity = PartKeepr::getEM()->find(get_called_class(), $id);
-
- if (!is_object($entity)) {
- throw new EntityNotFoundException(get_called_class(), $id);
- }
- return $entity;
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Util/Configuration.php b/src/backend/de/RaumZeitLabor/PartKeepr/Util/Configuration.php
@@ -1,92 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Util;
-
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
- * This class manages simple key -> value configurations within the system.
- *
- * This allows the user to configure certain aspects of the system in a central place.
- *
- * The convention is to use a dotted format, for example:
- *
- * flipbeat.cms.layoutrenderer
- *
- * @author felicitus
- */
-class Configuration {
- private static $options = array();
-
- /**
- * Sets the option to value.
- *
- * @param string $option The option to set
- * @param string $value The value to set
- */
- public static function setOption ($option, $value) {
- Configuration::$options[$option] = $value;
- }
-
- /**
- * Returns the value of an option. The developer
- * may additionally specify a default value, which
- * is returned when no option was found.
- *
- * @param string $option The option to return
- * @param string $default The default value if the option was not found
- */
- public static function getOption ($option, $default = false) {
- if (!array_key_exists($option, Configuration::$options)) {
- return $default;
- }
- return Configuration::$options[$option];
- }
-
- /**
- * Returns all configuration options
- *
- * @return array An array with key=>value assignments
- */
- public static function getOptions () {
- return Configuration::$options;
- }
-
- /**
- * Returns a configuration file, based on all configurations.
- *
- * @param none
- * @return string A complete configuration file including namespace and use directives
- */
- public static function dumpConfig () {
- $config = <<<EOD
-<?php
-namespace de\RaumZeitLabor\PartKeepr;
-use de\RaumZeitLabor\PartKeepr\Util\Configuration;
-
-
-EOD;
- foreach (Configuration::$options as $option => $value) {
- switch (PartKeepr::getType($value)) {
- case "string":
- $config .= 'Configuration::setOption("'.$option.'", "'.$value.'");'."\n";
- break;
- case "boolean":
- $config .= 'Configuration::setOption("'.$option.'", '.($value === true ? 'true' : 'false').');'."\n";
- break;
- case "integer":
- case "numeric":
- $config .= 'Configuration::setOption("'.$option.'", '.intval($value).');'."\n";
- break;
- case "float":
- $config .= 'Configuration::setOption("'.$option.'", '.floatval($value).');'."\n";
- break;
- default:
- break;
- }
-
- }
-
- return $config;
- }
-}
-?>-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Util/Deserializable.php b/src/backend/de/RaumZeitLabor/PartKeepr/Util/Deserializable.php
@@ -1,10 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Util;
-
-interface Deserializable {
- /**
- * Deserializes the entity from an array format
- * @param $parameters array The serialized form of the entity to deserialize
- */
- public function deserialize (array $parameters);
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Util/Exceptions/EntityNotFoundException.php b/src/backend/de/RaumZeitLabor/PartKeepr/Util/Exceptions/EntityNotFoundException.php
@@ -1,17 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Util\Exceptions;
-
-use de\RaumZeitLabor\PartKeepr\Util\SerializableException,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
- * Thrown when an entity via loadById() was not found.
- */
-class EntityNotFoundException extends SerializableException {
- public function __construct ($class, $id) {
- parent::__construct(
- sprintf(
- PartKeepr::i18n("The entity %s with the id %d could not be found"),
- $class, $id));
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Util/Exceptions/EntityNotPersistantException.php b/src/backend/de/RaumZeitLabor/PartKeepr/Util/Exceptions/EntityNotPersistantException.php
@@ -1,14 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Util\Exceptions;
-
-use de\RaumZeitLabor\PartKeepr\Util\SerializableException,
- de\RaumZeitLabor\PartKeepr\PartKeepr;
-
-/**
- * Thrown when an entity via loadById() was not found.
- */
-class EntityNotPersistantException extends SerializableException {
- public function __construct () {
- parent::__construct("The entity is not persistant.");
- }
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Util/Exceptions/OutOfRangeException.php b/src/backend/de/RaumZeitLabor/PartKeepr/Util/Exceptions/OutOfRangeException.php
@@ -1,6 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Util\Exceptions;
-
-use de\RaumZeitLabor\PartKeepr\Util\SerializableException;
-
-class OutOfRangeException extends SerializableException {}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Util/OS/OperatingSystem.php b/src/backend/de/RaumZeitLabor/PartKeepr/Util/OS/OperatingSystem.php
@@ -1,94 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Util\OS;
-
-class OperatingSystem {
- /**
- * Returns the platform name the system is running on.
- *
- * Typical return values are: "Linux", "FreeBSD", "Darwin" (Mac OSX),
- * "Windows".
- */
- public function getPlatform () {
- if (function_exists("posix_uname")) {
- $data = posix_uname();
-
- if (array_key_exists("sysname", $data)) {
- return $data["sysname"];
- }
- }
-
- if (\PHP_OS == "WINNT") {
- return "Windows";
- }
-
- return "unknown";
- }
-
- /**
- * Returns the distribution
- * @return string string
- */
- public function getRelease () {
- switch (strtolower($this->getPlatform())) {
- case "freebsd":
- /**
- * Unfortunately, there's no text file on FreeBSD which tells us the release
- * number. Thus, we hope that "release" within posix_uname() is defined.
- */
- if (function_exists("posix_uname")) {
- $data = posix_uname();
-
- if (array_key_exists("release", $data)) {
- return $data["release"];
- }
- }
- break;
- case "darwin":
- /**
- * Mac stores its version number in a public readable plist file, which
- * is in XML format.
- */
- $document = new \DomDocument();
- $document->load("/System/Library/CoreServices/SystemVersion.plist");
- $xpath = new \DOMXPath($document);
- $entries = $xpath->query("/plist/dict/*");
-
- $previous = "";
- foreach ($entries as $entry) {
- if (strpos($previous, "ProductVersion") !== false) {
- return $entry->textContent;
- }
- $previous = $entry->textContent;
- }
- break;
- case "linux":
- return $this->getLinuxDistribution();
- break;
- default:
- break;
- }
-
- return "unknown";
- }
-
- /**
- * Tries to detect the distribution.
- *
- * Currently, we only execute lsb_release to find out the version number.
- * As I don't have any other distributions at hand to test with, I rely
- * on user feedback which distributions don't have lsb_release.
- */
- public function getLinuxDistribution () {
- /* Try executing lsb_release */
- $release = @exec('lsb_release -d -s', $void, $retval);
-
- if ($retval === 0 && $release !== "")
- {
- return $release;
- }
-
- //@todo we need better handling here
- return "unknown";
- }
-
-}
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Util/Serializable.php b/src/backend/de/RaumZeitLabor/PartKeepr/Util/Serializable.php
@@ -1,11 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Util;
-
-interface Serializable {
- /**
- * Serializes the entity into an array format, which in turn can
- * be used by json_encode.
- * @return array The serialized form of the entity
- */
- public function serialize ();
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Util/SerializableException.php b/src/backend/de/RaumZeitLabor/PartKeepr/Util/SerializableException.php
@@ -1,59 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Util;
-
-class SerializableException extends \Exception {
- protected $detailMessage = "No detail message has been entered.";
-
- /* @todo: stub */
- public function getDetail () {
- return $this->detailMessage;
- }
-
- public function setDetail ($message) {
- $this->detailMessage = $message;
- }
-
- public function serialize () {
- return array(
- "message" => $this->getMessage(),
- "detail" => $this->getDetail(),
- "exception" => get_class($this),
- "code" => $this->getCode()
- //"backtrace" => $this->getFormattedTrace()
- );
- }
-
- public function getFormattedTrace () {
- $items = $this->getTrace();
-
- $message = "";
-
- $args = array();
-
- foreach ($items as $id => $item) {
- foreach ($item["args"] as $item) {
- switch (gettype($item)) {
- case "object":
- if (method_exists($item, "__toString")) {
- $args[] = get_class($item) . "(".$item->__toString().")";
- } else {
- $args[] = get_class($item);
- }
- case "array":
- $args[] = "array";
- break;
- default:
- $args[] = $item;
- break;
- }
- }
-
- $message .= $item["file"].":".$item["line"]."\n";
- $message .= $item["function"] ."(".implode(",", $args).")"."\n\n";
- }
-
- return $message;
- }
-
-}
-?>-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Util/Singleton.php b/src/backend/de/RaumZeitLabor/PartKeepr/Util/Singleton.php
@@ -1,22 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Util;
-
-abstract class Singleton {
- static $instance = null;
-
- private function __construct () {
-
- }
-
- /**
- * Returns an instance of the current singleton
- * @return $this
- */
- public static function getInstance () {
- if (!static::$instance instanceof static) {
- static::$instance = new static;
- }
-
- return static::$instance;
- }
-}-
\ No newline at end of file
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/Util/UtilService.php b/src/backend/de/RaumZeitLabor/PartKeepr/Util/UtilService.php
@@ -1,13 +0,0 @@
-<?php
-namespace de\RaumZeitLabor\PartKeepr\Util;
-
-use de\RaumZeitLabor\PartKeepr\Service\AnonService;
-
-class UtilService extends AnonService {
- public function clearCache () {
- apc_clear_cache();
- apc_clear_cache("user");
-
- return array("status" => "ok");
- }
-}-
\ No newline at end of file
diff --git a/src/frontend/file.php b/src/frontend/file.php
@@ -1,14 +1,14 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Frontend;
-use de\RaumZeitLabor\PartKeepr\Footprint\FootprintAttachment,
- de\RaumZeitLabor\PartKeepr\Project\ProjectAttachment,
- de\RaumZeitLabor\PartKeepr\Part\PartAttachment,
- de\RaumZeitLabor\PartKeepr\UploadedFile\TempUploadedFile,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Image\Image,
- de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerICLogo;
+namespace PartKeepr\Frontend;
+use PartKeepr\Footprint\FootprintAttachment,
+ PartKeepr\Project\ProjectAttachment,
+ PartKeepr\Part\PartAttachment,
+ PartKeepr\UploadedFile\TempUploadedFile,
+ PartKeepr\PartKeepr,
+ PartKeepr\Image\Image,
+ PartKeepr\Manufacturer\ManufacturerICLogo;
-include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("../src/backend/PartKeepr/PartKeepr.php");
PartKeepr::initialize("");
@@ -29,9 +29,9 @@ if (substr($id, 0, 4) === "TMP:") {
case "PartKeepr.FootprintAttachment":
$file = FootprintAttachment::loadById($id);
break;
- case "ProjectAttachment":
- case "PartKeepr.ProjectAttachment":
- $file = ProjectAttachment::loadById($id);
+ case "ProjectAttachment":
+ case "PartKeepr.ProjectAttachment":
+ $file = ProjectAttachment::loadById($id);
break;
default:
$file = null;
diff --git a/src/frontend/image.php b/src/frontend/image.php
@@ -1,16 +1,20 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Frontend;
+namespace PartKeepr\Frontend;
-use de\RaumZeitLabor\PartKeepr\Part\PartImage,
- de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocationImage,
- de\RaumZeitLabor\PartKeepr\Footprint\FootprintImage,
- de\RaumZeitLabor\PartKeepr\TempImage\TempImage,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Image\Image,
- de\RaumZeitLabor\PartKeepr\Image\CachedImage,
- de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerICLogo;
+use PartKeepr\Part\PartAttachment;
-include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+use PartKeepr\Image\ImageRenderer;
+
+use PartKeepr\Part\PartImage,
+ PartKeepr\StorageLocation\StorageLocationImage,
+ PartKeepr\Footprint\FootprintImage,
+ PartKeepr\TempImage\TempImage,
+ PartKeepr\PartKeepr,
+ PartKeepr\Image\Image,
+ PartKeepr\Image\CachedImage,
+ PartKeepr\Manufacturer\ManufacturerICLogo;
+
+include("../src/backend/PartKeepr/PartKeepr.php");
PartKeepr::initialize("");
@@ -30,10 +34,12 @@ if (substr($id, 0, 4) === "TMP:") {
$image = FootprintImage::loadById($id);
break;
case Image::IMAGE_STORAGELOCATION:
- $image = StorageLocationImage::loadById($id);
- break;
- case Image::IMAGE_PART:
- $image = PartImage::loadById($id);
+ $image = StorageLocationImage::loadById($id);
+ break;
+ case "partattachment":
+ $attachment = PartAttachment::loadById($id);
+ $image = new PartImage();
+ $image->replace($attachment->getFilename());
break;
default:
$image = null;
@@ -54,20 +60,7 @@ if ($image == null) {
if ($image === null) {
/* The image is still null - output an "image not found" image. */
- $image = imagecreate($_REQUEST["w"], $_REQUEST["h"]);
- $white = imagecolorallocate($image, 255,255,255);
- $black = imagecolorallocate($image, 0,0,0);
-
- header("Content-Type: image/png");
-
- $w = $_REQUEST["w"]-1;
- $h = $_REQUEST["h"]-1;
- imagefill($image, 0,0, $white);
-
- /* Draw the X */
- imageline($image, 0,0,$w,$h, $black);
- imageline($image, $w,0,0,$h, $black);
- imagepng($image);
+ ImageRenderer::outputRenderNotFoundImage($_REQUEST["w"], $_REQUEST["h"]);
exit();
}
@@ -98,8 +91,7 @@ switch ($mode) {
case "fit":
default:
$file = $image->fitWithin($_REQUEST["w"],$_REQUEST["h"]);
- break;
-
+ break;
}
diff --git a/src/frontend/index.php b/src/frontend/index.php
@@ -1,13 +1,13 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Frontend;
+namespace PartKeepr\Frontend;
-use de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\Service\ServiceManager,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Session\SessionManager,
- de\RaumZeitLabor\PartKeepr\Util\Configuration;
+use PartKeepr\User\User,
+ PartKeepr\Service\ServiceManager,
+ PartKeepr\PartKeepr,
+ PartKeepr\Session\SessionManager,
+ PartKeepr\Util\Configuration;
-include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("../src/backend/PartKeepr/PartKeepr.php");
include_once 'Twig/Autoloader.php';
PartKeepr::initialize("");
@@ -45,8 +45,8 @@ if (Configuration::getOption("partkeepr.auth.http", false) === true) {
$aPreferences = array();
- foreach ($user->getPreferences() as $result) {
- $aPreferences[] = $result->serialize();
+ foreach ($user->getPreferences() as $result) {
+ $aPreferences[] = $result->serialize();
}
$aParameters["userPreferences"] = array("response" => array("data" => $aPreferences));
diff --git a/src/frontend/js/Components/Part/Editor/PartDistributorGrid.js b/src/frontend/js/Components/Part/Editor/PartDistributorGrid.js
@@ -52,7 +52,7 @@ Ext.define('PartKeepr.PartDistributorGrid', {
}, {
header : i18n("Order Number"),
dataIndex : 'orderNumber',
- flex : 0.3,
+ flex : 0.2,
editor : {
xtype : 'textfield',
allowBlank : true
@@ -78,6 +78,14 @@ Ext.define('PartKeepr.PartDistributorGrid', {
xtype : 'CurrencyField',
allowBlank : false
}
+ }, {
+ header : i18n("SKU"),
+ dataIndex : 'sku',
+ flex : 0.1,
+ editor : {
+ xtype : 'textfield',
+ allowBlank : true
+ }
} ];
this.callParent();
@@ -116,4 +124,4 @@ Ext.define('PartKeepr.PartDistributorGrid', {
onSelectChange : function(selModel, selections) {
this.deleteButton.setDisabled(selections.length === 0);
}
-});-
\ No newline at end of file
+});
diff --git a/src/frontend/js/Components/Part/PartDisplay.js b/src/frontend/js/Components/Part/PartDisplay.js
@@ -6,6 +6,8 @@ Ext.define('PartKeepr.PartDisplay', {
extend: 'Ext.panel.Panel',
bodyCls: 'partdisplay',
+ autoScroll: true,
+
/**
* Initializes the component and adds a template as well as the add/remove stock and edit part buttons.
*/
@@ -55,7 +57,7 @@ Ext.define('PartKeepr.PartDisplay', {
'</tr>',
'<tr>',
'<td class="e">'+i18n("Used in projects")+':</td>',
- '<td class="e">{projects}</td>',
+ '<td class="e">{[ (values.projects == "") ? "'+i18n("none")+'" : values.projects ]}</td>',
'</tr>',
'</table>');
@@ -105,6 +107,10 @@ Ext.define('PartKeepr.PartDisplay', {
*/
this.addEvents("editPart");
+ this.imageDisplay = Ext.create("PartKeepr.PartImageDisplay");
+ this.infoContainer = Ext.create("Ext.container.Container");
+
+ this.items = [ this.infoContainer, this.imageDisplay ];
this.callParent();
},
/**
@@ -125,7 +131,13 @@ Ext.define('PartKeepr.PartDisplay', {
}
}
- this.tpl.overwrite(this.getTargetEl(), values);
+ this.tpl.overwrite(this.infoContainer.getEl(), values);
+ this.imageDisplay.setStore(this.record.attachments());
+
+ this.doLayout();
+ // Scroll the container to top in case the user scrolled the part, then switched to another part
+ this.getTargetEl().scrollTo("top", 0);
+
},
/**
* Prompt the user for the stock level he wishes to add.
@@ -137,12 +149,13 @@ Ext.define('PartKeepr.PartDisplay', {
/**
* Callback after the "add stock" dialog is complete.
*/
- addPartHandler: function (quantity, price) {
+ addPartHandler: function (quantity, price, comment) {
var call = new PartKeepr.ServiceCall(
"Part",
"addStock");
call.setParameter("stock", quantity);
call.setParameter("price", price);
+ call.setParameter("comment", comment);
call.setParameter("part", this.record.get("id"));
call.setHandler(Ext.bind(this.reloadPart, this));
call.doCall();
@@ -189,4 +202,4 @@ Ext.define('PartKeepr.PartDisplay', {
this.setValues(this.record);
this.record.commit();
}
-});-
\ No newline at end of file
+});
diff --git a/src/frontend/js/Components/Part/PartImageDisplay.js b/src/frontend/js/Components/Part/PartImageDisplay.js
@@ -0,0 +1,143 @@
+/**
+ * @class PartKeepr.PartImageDisplay
+ * Provides a display of all part images with scroll-through functionality.
+ */
+Ext.define('PartKeepr.PartImageDisplay', {
+ extend: 'Ext.panel.Panel',
+
+ displayedImageId: 0,
+ maxImageWidth: 200,
+ maxImageHeight: 150,
+
+ layout: 'hbox',
+ border: false,
+
+ /**
+ * Initializes the component and creates all widgets.
+ */
+ initComponent: function () {
+ this.prevButton = Ext.create("Ext.button.Button", {
+ text: '<',
+ width: 20,
+ height: this.maxImageHeight,
+ handler: this.onPreviousClick,
+ scope: this
+ });
+
+ this.nextButton = Ext.create("Ext.button.Button", {
+ text: '>',
+ width: 20,
+ height: this.maxImageHeight,
+ handler: this.onNextClick,
+ scope: this
+ });
+
+ this.imageDisplay = Ext.create("Ext.container.Container", {
+ height: this.maxImageHeight,
+ width: this.maxImageWidth,
+ style: 'align: center'
+ });
+
+ this.items = [ this.prevButton, this.imageDisplay, this.nextButton ];
+
+ this.tpl = new Ext.XTemplate('<img src="{image}"/>');
+
+ this.callParent();
+ },
+ /**
+ * Sets the stored when a new part is selected.
+ * @param store The store
+ */
+ setStore: function (store) {
+ var imageSet = false;
+
+ this.store = store;
+
+ this.displayedImageId = 0;
+
+ var id = this.getImageToDisplayForward(0);
+
+ if (id !== -1) {
+ this.setImage(id);
+ imageSet = true;
+
+ }
+
+ if (!imageSet) {
+ this.tpl.overwrite(this.imageDisplay.getEl(), { image: 'image.php?type=partattachment&id=0&w='+this.maxImageWidth+'&h='+this.maxImageHeight});
+ }
+ },
+ /**
+ * Sets the image
+ * @param id The attachment ID to set
+ */
+ setImage: function (id) {
+ this.tpl.overwrite(this.imageDisplay.getEl(), { image: 'image.php?type=partattachment&m=fitexact&w='+this.maxImageWidth+'&h='+this.maxImageHeight+'&id='+id});
+ this.displayedImageId = id;
+ },
+ /**
+ * Handler for the "next" button
+ */
+ onNextClick: function () {
+ var imgId = this.getImageToDisplayForward(this.displayedImageId);
+
+ if (imgId !== -1) {
+ this.setImage(imgId);
+ }
+ },
+ /**
+ * Handler for the "previous" button
+ */
+ onPreviousClick: function () {
+ var imgId = this.getImageToDisplayBackward(this.displayedImageId);
+
+ if (imgId !== -1) {
+ this.setImage(imgId);
+ }
+
+ },
+ /**
+ * Returns the next image in the attachment store
+ * @param startId The start ID
+ * @returns int An attachment id, or -1 of none was found
+ */
+ getImageToDisplayForward: function (startId) {
+ var startIdx = this.store.findExact("id", startId);
+
+ if (startIdx === -1) {
+ startIdx = 0;
+ } else {
+ startIdx++;
+ }
+
+ for (var i=startIdx;i<this.store.count();i++) {
+ if (this.store.getAt(i).get("image")) {
+ return this.store.getAt(i).get("id");
+ }
+ }
+
+ return -1;
+ },
+ /**
+ * Returns the previous image in the attachment store
+ * @param startId The start ID
+ * @returns int An attachment id, or -1 of none was found
+ */
+ getImageToDisplayBackward: function (startId) {
+ var startIdx = this.store.findExact("id", startId);
+
+ if (startIdx >= this.store.count()) {
+ startIdx = this.store.count()-1;
+ } else {
+ startIdx--;
+ }
+
+ for (var i=startIdx;i>-1;i--) {
+ if (this.store.getAt(i).get("image")) {
+ return this.store.getAt(i).get("id");
+ }
+ }
+
+ return -1;
+ }
+});+
\ No newline at end of file
diff --git a/src/frontend/js/Components/Part/PartStockWindow.js b/src/frontend/js/Components/Part/PartStockWindow.js
@@ -8,7 +8,7 @@ Ext.define('PartKeepr.PartStockWindow', {
// Configurations
constrainHeader : true,
width : 305,
- height : 155,
+ height : 180,
resizable : false,
@@ -68,6 +68,23 @@ Ext.define('PartKeepr.PartStockWindow', {
checked : true
});
+ this.commentField = Ext.create("Ext.form.field.Text", {
+ anchor : '100%',
+ fieldLabel : i18n("Comment"),
+ maxLength : 255,
+ enforceMaxLength : true,
+ listeners : {
+ specialkey : {
+ fn : function(field, e) {
+ if (e.getKey() == e.ENTER) {
+ this.onOKClick();
+ }
+ },
+ scope : this
+ }
+ }
+ });
+
this.form = Ext.create("Ext.form.Panel", {
bodyStyle : 'background:#DBDBDB;',
border : false,
@@ -81,7 +98,7 @@ Ext.define('PartKeepr.PartStockWindow', {
margin : "0 0 0 5",
value : this.partUnitName
} ]
- }, this.priceField, this.priceCheckbox ]
+ }, this.priceField, this.priceCheckbox, this.commentField ]
});
this.items = this.form;
@@ -126,13 +143,13 @@ Ext.define('PartKeepr.PartStockWindow', {
Ext.callback( this.callbackFn,
this.callbackScope,
- [ this.quantityField.getValue(), price ]);
+ [ this.quantityField.getValue(), price, this.commentField.getValue() ]);
this.close();
}
},
/**
- * Opens the window in "add stock" mode. The target callback receives two parameters: the value of the quantity
- * field and the value of the price field.
+ * Opens the window in "add stock" mode. The target callback receives three parameters: the value of the quantity
+ * field, the value of the price field and the value of the comment field.
*
* @param fn
* The callback
@@ -161,8 +178,9 @@ Ext.define('PartKeepr.PartStockWindow', {
this.setTitle(this.removePartText);
this.priceField.hide();
this.priceCheckbox.hide();
+ this.commentField.hide();
this.setHeight(105);
this.okButton.setIcon("resources/silkicons/brick_delete.png");
this.show();
}
-});-
\ No newline at end of file
+});
diff --git a/src/frontend/js/Models/PartAttachment.js b/src/frontend/js/Models/PartAttachment.js
@@ -5,6 +5,7 @@ Ext.define("PartKeepr.PartAttachment", {
{ name: 'originalFilename', type: 'string' },
{ name: 'footprint_id', type: 'int' },
{ name: 'mimetype', type: 'string' },
+ { name: 'image', type: 'boolean' },
{ name: 'extension', type: 'string' },
{ name: 'description', type: 'string' },
{ name: 'size', type: 'string' }
diff --git a/src/frontend/js/Models/PartDistributor.js b/src/frontend/js/Models/PartDistributor.js
@@ -1,16 +1,17 @@
Ext.define("PartKeepr.PartDistributor", {
extend: "Ext.data.Model",
fields: [
- { id: 'id', name: 'id', type: 'int' },
- { name: 'part_id', type: 'int' },
- { name: 'part_name', type: 'string' },
- { name: 'distributor_id', type: 'int' },
- { name: 'distributor_name', type: 'string' },
- { name: 'price', type: 'float' },
- { name: 'orderNumber', type: 'string' },
- { name: 'packagingUnit', type: 'int'}
+ { id: 'id', name: 'id', type: 'int' },
+ { name: 'part_id', type: 'int' },
+ { name: 'part_name', type: 'string' },
+ { name: 'distributor_id', type: 'int' },
+ { name: 'distributor_name', type: 'string' },
+ { name: 'price', type: 'float' },
+ { name: 'orderNumber', type: 'string' },
+ { name: 'packagingUnit', type: 'int'},
+ { name: 'sku', type: 'string' }
],
belongsTo: { type: 'belongsTo', model: 'PartKeepr.Part', primaryKey: 'id', foreignKey: 'part_id'},
belongsTo: { type: 'belongsTo', model: 'PartKeepr.Distributor', primaryKey: 'id', foreignKey: 'distributor_id'},
proxy: PartKeepr.getRESTProxy("PartDistributor")
-});-
\ No newline at end of file
+});
diff --git a/src/frontend/js/Util/i18n.js b/src/frontend/js/Util/i18n.js
@@ -1,3 +1,8 @@
+/**
+ * Returns an internationalized string.
+ * @param string
+ * @return {*}
+ */
function i18n (string) {
return string;
}
\ No newline at end of file
diff --git a/src/frontend/rest.php b/src/frontend/rest.php
@@ -1,10 +1,10 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Frontend;
+namespace PartKeepr\Frontend;
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Service\ServiceManager;
+use PartKeepr\PartKeepr,
+ PartKeepr\Service\ServiceManager;
-include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("../src/backend/PartKeepr/PartKeepr.php");
PartKeepr::initialize("");
@@ -39,7 +39,7 @@ $timingStart = microtime(true);
* rest.php/Part
*
* /Part specifies that you wish to call the Part service. The service manager automatically extends the short "Part"
- * name to the class de\RaumZeitLabor\PartKeepr\Part\PartService.
+ * name to the class PartKeepr\Part\PartService.
*
* REST
* ====
@@ -57,7 +57,7 @@ try {
echo json_encode($response);
-} catch (\de\RaumZeitLabor\PartKeepr\Util\SerializableException $e) {
+} catch (\PartKeepr\Util\SerializableException $e) {
header('HTTP/1.0 400 Exception', false, 400);
$response = array();
$response["status"] = "error";
diff --git a/src/frontend/rss.php b/src/frontend/rss.php
@@ -1,10 +1,10 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Frontend;
+namespace PartKeepr\Frontend;
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Util\Configuration;
+use PartKeepr\PartKeepr,
+ PartKeepr\Util\Configuration;
-include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("../src/backend/PartKeepr/PartKeepr.php");
header("Content-Type: text/xml; charset=UTF-8");
diff --git a/src/frontend/service.php b/src/frontend/service.php
@@ -1,10 +1,10 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Frontend;
+namespace PartKeepr\Frontend;
-use de\RaumZeitLabor\PartKeepr\Service\ServiceManager;
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
+use PartKeepr\Service\ServiceManager;
+use PartKeepr\PartKeepr;
-include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("../src/backend/PartKeepr/PartKeepr.php");
PartKeepr::initialize("");
@@ -27,7 +27,7 @@ try {
$response["response"] = ServiceManager::call($request);
$response["timing"] = microtime(true) - $timingStart;
-} catch (de\RaumZeitLabor\PartKeepr\Util\SerializableException $e) {
+} catch (PartKeepr\Util\SerializableException $e) {
$response = array();
$response["status"] = "error";
$response["exception"] = $e->serialize();
diff --git a/src/frontend/upload.php b/src/frontend/upload.php
@@ -1,12 +1,12 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Frontend;
+namespace PartKeepr\Frontend;
-use de\RaumZeitLabor\PartKeepr\PartKeepr;
-use de\RaumZeitLabor\PartKeepr\Image\Image;
-use de\RaumZeitLabor\PartKeepr\Manufacturer\ManufacturerICLogo;
-use de\RaumZeitLabor\PartKeepr\Manufacturer\Manufacturer;
+use PartKeepr\PartKeepr;
+use PartKeepr\Image\Image;
+use PartKeepr\Manufacturer\ManufacturerICLogo;
+use PartKeepr\Manufacturer\Manufacturer;
-include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("../src/backend/PartKeepr/PartKeepr.php");
PartKeepr::initialize("");
diff --git a/src/setup/setup.php b/src/setup/setup.php
@@ -1,26 +1,26 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Setup;
+namespace PartKeepr\Setup;
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Setup\Setup,
- de\RaumZeitLabor\PartKeepr\Util\SerializableException;
+use PartKeepr\PartKeepr,
+ PartKeepr\Setup\Setup,
+ PartKeepr\Util\SerializableException;
-set_error_handler(create_function('$a, $b, $c, $d', 'throw new ErrorException($b, 0, $a, $c, $d);'), E_ALL);
+set_error_handler(create_function('$a, $b, $c, $d', 'throw new ErrorException($b, 0, $a, $c, $d);'), E_ALL);
-include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("../src/backend/PartKeepr/PartKeepr.php");
PartKeepr::initializeClassLoaders();
-try {
- Setup::setDatabaseConfigurationFromRequest();
-} catch (\Exception $e) {
- echo json_encode(array("error" => true, "message" => $e->getMessage()));
- exit;
+try {
+ Setup::setDatabaseConfigurationFromRequest();
+} catch (\Exception $e) {
+ echo json_encode(array("error" => true, "message" => $e->getMessage()));
+ exit;
}
PartKeepr::initializeDoctrine();
-$setup = new Setup();
+$setup = new Setup();
try {
/**
diff --git a/src/setup/tests/check-database-connectivity.php b/src/setup/tests/check-database-connectivity.php
@@ -2,16 +2,16 @@
/**
* Tests the connection to the database.
*/
-include("../../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("../../src/backend/PartKeepr/PartKeepr.php");
use Doctrine\Common\ClassLoader;
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Setup\Setup,
- de\RaumZeitLabor\PartKeepr\Setup\SchemaSetup;
+use PartKeepr\PartKeepr,
+ PartKeepr\Setup\Setup,
+ PartKeepr\Setup\SchemaSetup;
PartKeepr::initializeClassLoaders();
-$config = new \Doctrine\DBAL\Configuration();
+$config = new \Doctrine\DBAL\Configuration();
/**
* Test if the requested driver is available
@@ -22,7 +22,7 @@ $drivers = PDO::getAvailableDrivers();
$bDriverAvailable = false;
if (!in_array($_REQUEST["driver"], $drivers)) {
- echo json_encode(array("error" => true, "message" => "The requested driver isn't installed as PHP pdo module. Please install the PDO driver for PHP."));
+ echo json_encode(array("error" => true, "message" => "The requested driver isn't installed as PHP pdo module. Please install the PDO driver for PHP."));
exit;
}
@@ -33,7 +33,7 @@ try {
$onnectionOptions = Setup::setDatabaseConfigurationFromRequest();
$connectionOptions = PartKeepr::createConnectionOptionsFromConfig();
} catch (\Exception $e) {
- echo json_encode(array("error" => true, "message" => $e->getMessage()));
+ echo json_encode(array("error" => true, "message" => $e->getMessage()));
exit;
}
@@ -60,12 +60,12 @@ switch ($_REQUEST["driver"]) {
function performAdditionalMySQLTests ($connection, $dbname) {
if (!SchemaSetup::mysqlHasUTF8Encoding($connection, $dbname)) {
- echo json_encode(array("error" => true, "message" => "Your database doesn't have the proper encoding. Please change it using the following SQL statement: <br/><br/><code>ALTER DATABASE ".$dbname." CHARACTER SET utf8;</code>"));
+ echo json_encode(array("error" => true, "message" => "Your database doesn't have the proper encoding. Please change it using the following SQL statement: <br/><br/><code>ALTER DATABASE ".$dbname." CHARACTER SET utf8;</code>"));
exit;
}
}
-echo json_encode(array("error" => false));
+echo json_encode(array("error" => false));
/**
* Returns error messages for a specific platform and PDOException code
@@ -89,15 +89,15 @@ function getPlatformSpecificErrorMessage($platform, $code) {
* @return An error message, or "" if no message is available.
*/
function getMySQLSpecificErrorMessage ($code) {
- switch ($code) {
- case 1044:
- return "<br/><br/>You need to grant permissions to the database, or you haven't created the database yet.";
- break;
- case 1045:
- return "<br/><br/>It seems that you have mistyped your username or password.";
- break;
- case 2013:
- return "<br/><br/>This error is an indication that the database host you have specified is not reachable, or that your database runs on a different port.";
+ switch ($code) {
+ case 1044:
+ return "<br/><br/>You need to grant permissions to the database, or you haven't created the database yet.";
+ break;
+ case 1045:
+ return "<br/><br/>It seems that you have mistyped your username or password.";
+ break;
+ case 2013:
+ return "<br/><br/>This error is an indication that the database host you have specified is not reachable, or that your database runs on a different port.";
break;
default:
return "";
diff --git a/testing/PartTest.php b/testing/PartTest.php
@@ -2,7 +2,7 @@
namespace de\RaumZeitLabor\PartKeepr\Tests;
declare(encoding = 'UTF-8');
-include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("../src/backend/PartKeepr/PartKeepr.php");
use de\RaumZeitLabor\PartKeepr\Auth\User;
use de\RaumZeitLabor\PartKeepr\Footprint\Footprint;
@@ -12,8 +12,33 @@ use de\RaumZeitLabor\PartKeepr\Category\CategoryManager;
use de\RaumZeitLabor\PartKeepr\PartKeepr;
use de\RaumZeitLabor\PartKeepr\Part\Part;
use de\RaumZeitLabor\PartKeepr\Part\PartAttachment;
+use de\RaumZeitLabor\PartKeepr\PartUnit\PartUnitManager;
+use Doctrine\DBAL\Migrations\Migration,
+ Doctrine\DBAL\Migrations\Configuration\YamlConfiguration;
PartKeepr::initialize();
-$test = new PartAttachment();
-$test->replaceFromURL("http://www.datasheetcatalog.org/datasheet/motorola/MCT7809BD2T.pdf");
+
+$aPartResults[] = array();
+
+$dql = "SELECT pp.quantity, p.id FROM ";
+$dql .= "de\RaumZeitLabor\PartKeepr\Project\ProjectPart pp JOIN pp.part p WHERE pp.project = :project";
+
+$query = PartKeepr::getEM()->createQuery($dql);
+$query->setParameter("project", 1);
+
+foreach ($query->getArrayResult() as $result) {
+ $part = Part::loadById($result["id"]);
+
+ if (array_key_exists($result["id"], $aPartResults)) {
+ $aPartResults[$result["id"]]["quantity"] += $result["quantity"];
+ } else {
+ $aPartResults[$result["id"]] = array(
+ "quantity" => $result["quantity"],
+ "part" => array("response" => array("totalCount" => 1, "data" => $part->serialize())),
+ "storageLocation_name" => $part->getStorageLocation()->getName()
+ );
+ }
+}
+
+print_r($aPartResults);+
\ No newline at end of file
diff --git a/testing/Service.php b/testing/Service.php
@@ -2,7 +2,7 @@
namespace de\RaumZeitLabor\PartKeepr\Tests;
declare(encoding = 'UTF-8');
-include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("../src/backend/PartKeepr/PartKeepr.php");
use de\RaumZeitLabor\PartKeepr\Auth\User;
use de\RaumZeitLabor\PartKeepr\PartKeepr;
diff --git a/testing/SetupDatabase.php b/testing/SetupDatabase.php
@@ -1,19 +1,19 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Tests;
+namespace PartKeepr\Testing;
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 PartKeepr\PartKeepr,
+ PartKeepr\Setup\Migration\PartDB\PartDBMigration,
+ PartKeepr\Util\Configuration,
+ PartKeepr\PartCategory\PartCategoryManager;
-use de\RaumZeitLabor\PartKeepr\Setup\Setup;
+use PartKeepr\Setup\Setup;
declare(encoding = 'UTF-8');
-include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("../src/backend/PartKeepr/PartKeepr.php");
PartKeepr::initialize();
@@ -76,15 +76,15 @@ $setup->run();
if ($migration) {
- 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";
+ 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;
+ 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");
diff --git a/testing/genman.php b/testing/genman.php
@@ -1,5 +1,5 @@
<?php
-include("../src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include("../src/backend/PartKeepr/PartKeepr.php");
use de\RaumZeitLabor\PartKeepr\PartKeepr;
diff --git a/tests/Auth/UserTest.php b/tests/Auth/UserTest.php
@@ -1,7 +1,7 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Tests\Auth;
+namespace PartKeepr\Tests\Auth;
-use de\RaumZeitLabor\PartKeepr\User\User;
+use PartKeepr\User\User;
class UserTest extends \PHPUnit_Framework_TestCase {
public function testBasics () {
diff --git a/tests/Logger/LoggerTest.php b/tests/Logger/LoggerTest.php
@@ -1,8 +1,8 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Tests\Logger;
+namespace PartKeepr\Tests\Logger;
-use de\RaumZeitLabor\PartKeepr\Logger\Logger,
- de\RaumZeitLabor\PartKeepr\Util\Configuration;
+use PartKeepr\Logger\Logger,
+ PartKeepr\Util\Configuration;
class LoggerTest extends \PHPUnit_Framework_TestCase {
diff --git a/tests/Part/PartServiceTest.php b/tests/Part/PartServiceTest.php
@@ -1,14 +1,14 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Tests\Part;
+namespace PartKeepr\Tests\Part;
-use de\RaumZeitLabor\PartKeepr\Distributor\DistributorService;
+use PartKeepr\Distributor\DistributorService;
-use de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager,
- de\RaumZeitLabor\PartKeepr\Part\PartService,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Part\Part,
- de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocationManager,
- de\RaumZeitLabor\PartKeepr\StorageLocation\StorageLocationService;
+use PartKeepr\PartCategory\PartCategoryManager,
+ PartKeepr\Part\PartService,
+ PartKeepr\PartKeepr,
+ PartKeepr\Part\Part,
+ PartKeepr\StorageLocation\StorageLocationManager,
+ PartKeepr\StorageLocation\StorageLocationService;
class PartServiceTest extends \PHPUnit_Framework_TestCase {
protected $backupGlobals = false;
@@ -26,7 +26,7 @@ class PartServiceTest extends \PHPUnit_Framework_TestCase {
}
/**
- * @expectedException de\RaumZeitLabor\PartKeepr\Part\Exceptions\CategoryNotAssignedException
+ * @expectedException PartKeepr\Part\Exceptions\CategoryNotAssignedException
*/
public function testCreatePartWithoutCategory () {
$partName = "testCreatePartWithoutCategory";
@@ -98,19 +98,19 @@ class PartServiceTest extends \PHPUnit_Framework_TestCase {
$service->create();
}
- /**
- * @expectedException de\RaumZeitLabor\PartKeepr\Part\Exceptions\StorageLocationNotAssignedException
- */
- public function testCreatePartWithoutStorageLocation () {
- $partName = "testCreatePartWithoutStorageLocation";
-
- $part = array(
+ /**
+ * @expectedException PartKeepr\Part\Exceptions\StorageLocationNotAssignedException
+ */
+ public function testCreatePartWithoutStorageLocation () {
+ $partName = "testCreatePartWithoutStorageLocation";
+
+ $part = array(
"name" => $partName,
- "category" => 1
- );
-
- $service = new PartService($part);
- $service->create();
+ "category" => 1
+ );
+
+ $service = new PartService($part);
+ $service->create();
}
/**
diff --git a/tests/Service/ServiceTest.php b/tests/Service/ServiceTest.php
@@ -1,9 +1,9 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Tests\Service;
+namespace PartKeepr\Tests\Service;
-use de\RaumZeitLabor\PartKeepr\Service\Service,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\Part\Part;
+use PartKeepr\Service\Service,
+ PartKeepr\PartKeepr,
+ PartKeepr\Part\Part;
class ServiceTest extends \PHPUnit_Framework_TestCase {
diff --git a/tests/User/UserTest.php b/tests/User/UserTest.php
@@ -1,9 +1,9 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Tests\User;
+namespace PartKeepr\Tests\User;
-use de\RaumZeitLabor\PartKeepr\User\UserManager,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\User\User;
+use PartKeepr\User\UserManager,
+ PartKeepr\PartKeepr,
+ PartKeepr\User\User;
class UserTest extends \PHPUnit_Framework_TestCase {
protected $backupGlobals = false;
@@ -99,7 +99,7 @@ class UserTest extends \PHPUnit_Framework_TestCase {
/**
* Makes sure that an exception is thrown when attempting to set a preference if the user is not persistant yet.
*
- * @expectedException de\RaumZeitLabor\PartKeepr\Util\Exceptions\EntityNotPersistantException
+ * @expectedException PartKeepr\Util\Exceptions\EntityNotPersistantException
*/
public function testSetNonPersistantUserPreference () {
$user = new User();
@@ -109,7 +109,7 @@ class UserTest extends \PHPUnit_Framework_TestCase {
/**
* Makes sure that an exception is thrown when attempting to get a preference if the user is not persistant yet.
*
- * @expectedException de\RaumZeitLabor\PartKeepr\Util\Exceptions\EntityNotPersistantException
+ * @expectedException PartKeepr\Util\Exceptions\EntityNotPersistantException
*/
public function testGetNonPersistantUserPreference () {
$user = new User();
@@ -119,7 +119,7 @@ class UserTest extends \PHPUnit_Framework_TestCase {
/**
* Makes sure that an exception is thrown when attempting to delete a preference if the user is not persistant yet.
*
- * @expectedException de\RaumZeitLabor\PartKeepr\Util\Exceptions\EntityNotPersistantException
+ * @expectedException PartKeepr\Util\Exceptions\EntityNotPersistantException
*/
public function testDeleteNonPersistantUserPreference () {
$user = new User();
diff --git a/tests/UserPreference/UserPreferenceTest.php b/tests/UserPreference/UserPreferenceTest.php
@@ -1,9 +1,9 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Tests\UserPreference;
+namespace PartKeepr\Tests\UserPreference;
-use de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\User\User,
- de\RaumZeitLabor\PartKeepr\UserPreference\UserPreference;
+use PartKeepr\PartKeepr,
+ PartKeepr\User\User,
+ PartKeepr\UserPreference\UserPreference;
class UserPreferenceTest extends \PHPUnit_Framework_TestCase {
protected $user;
@@ -35,7 +35,7 @@ class UserPreferenceTest extends \PHPUnit_Framework_TestCase {
* @return nothing
*/
protected function deleteUserPreferences () {
- $dql = "DELETE FROM de\RaumZeitLabor\PartKeepr\UserPreference\UserPreference up WHERE up.user = :user";
+ $dql = "DELETE FROM PartKeepr\UserPreference\UserPreference up WHERE up.user = :user";
$query = PartKeepr::getEM()->createQuery($dql);
$query->setParameter("user", $this->user);
@@ -63,7 +63,7 @@ class UserPreferenceTest extends \PHPUnit_Framework_TestCase {
// Make sure that we only get one result when we set the same preference twice
UserPreference::setPreference($this->user, $preferenceKey, $preferenceValue);
- $dql = "SELECT COUNT(up) FROM de\RaumZeitLabor\PartKeepr\UserPreference\UserPreference up WHERE ";
+ $dql = "SELECT COUNT(up) FROM PartKeepr\UserPreference\UserPreference up WHERE ";
$dql .= "up.user = :user AND up.preferenceKey = :key";
$query = PartKeepr::getEM()->createQuery($dql);
@@ -75,7 +75,7 @@ class UserPreferenceTest extends \PHPUnit_Framework_TestCase {
/**
* Tests if the correct exception is thrown when attempting to load a non-existing user preference
- * @expectedException de\RaumZeitLabor\PartKeepr\UserPreference\Exceptions\UserPreferenceNotFoundException
+ * @expectedException PartKeepr\UserPreference\Exceptions\UserPreferenceNotFoundException
*/
public function testGetNonExistingUserPreference () {
$preferenceKey = "test2";
@@ -89,7 +89,7 @@ class UserPreferenceTest extends \PHPUnit_Framework_TestCase {
* We're expecting the UserPreferenceNotFoundException because we are attempting to retrieve the value of the
* previously deleted value.
*
- * @expectedException de\RaumZeitLabor\PartKeepr\UserPreference\Exceptions\UserPreferenceNotFoundException
+ * @expectedException PartKeepr\UserPreference\Exceptions\UserPreferenceNotFoundException
*/
public function testDeleteUserPreference () {
$preferenceKey = "test3";
@@ -114,7 +114,7 @@ class UserPreferenceTest extends \PHPUnit_Framework_TestCase {
UserPreference::setPreference($this->user, $preferenceKey, $preferenceValue);
- $dql = "SELECT up.preferenceValue FROM de\RaumZeitLabor\PartKeepr\UserPreference\UserPreference up WHERE ";
+ $dql = "SELECT up.preferenceValue FROM PartKeepr\UserPreference\UserPreference up WHERE ";
$dql .= "up.user = :user AND up.preferenceKey = :key";
$query = PartKeepr::getEM()->createQuery($dql);
@@ -146,7 +146,7 @@ class UserPreferenceTest extends \PHPUnit_Framework_TestCase {
/**
* Makes sure that an exception is thrown when attempting to set a preference if the user is not persistant yet.
*
- * @expectedException de\RaumZeitLabor\PartKeepr\Util\Exceptions\EntityNotPersistantException
+ * @expectedException PartKeepr\Util\Exceptions\EntityNotPersistantException
*/
public function testSetNonPersistantUserPreference () {
$user = new User();
@@ -156,7 +156,7 @@ class UserPreferenceTest extends \PHPUnit_Framework_TestCase {
/**
* Makes sure that an exception is thrown when attempting to get a preference if the user is not persistant yet.
*
- * @expectedException de\RaumZeitLabor\PartKeepr\Util\Exceptions\EntityNotPersistantException
+ * @expectedException PartKeepr\Util\Exceptions\EntityNotPersistantException
*/
public function testGetNonPersistantUserPreference () {
$user = new User();
@@ -166,7 +166,7 @@ class UserPreferenceTest extends \PHPUnit_Framework_TestCase {
/**
* Makes sure that an exception is thrown when attempting to delete a preference if the user is not persistant yet.
*
- * @expectedException de\RaumZeitLabor\PartKeepr\Util\Exceptions\EntityNotPersistantException
+ * @expectedException PartKeepr\Util\Exceptions\EntityNotPersistantException
*/
public function testDeleteNonPersistantUserPreference () {
$user = new User();
diff --git a/tests/Util/ConfigurationTest.php b/tests/Util/ConfigurationTest.php
@@ -1,7 +1,7 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Tests\Util;
+namespace PartKeepr\Tests\Util;
-use de\RaumZeitLabor\PartKeepr\Util\Configuration;
+use PartKeepr\Util\Configuration;
class ConfigurationTest extends \PHPUnit_Framework_TestCase {
public function testConfiguration () {
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
@@ -1,11 +1,11 @@
<?php
-namespace de\RaumZeitLabor\PartKeepr\Tests;
+namespace PartKeepr\Tests;
-use de\RaumZeitLabor\PartKeepr\PartCategory\PartCategoryManager,
- de\RaumZeitLabor\PartKeepr\PartKeepr,
- de\RaumZeitLabor\PartKeepr\User\User;
+use PartKeepr\PartCategory\PartCategoryManager,
+ PartKeepr\PartKeepr,
+ PartKeepr\User\User;
-include(dirname(__DIR__). "/src/backend/de/RaumZeitLabor/PartKeepr/PartKeepr.php");
+include(dirname(__DIR__). "/src/backend/PartKeepr/PartKeepr.php");
/**
* Initializes a bootstrapped PartKeepr environment.
diff --git a/util/classes/ExtJSFile.php b/util/classes/ExtJSFile.php
@@ -37,6 +37,8 @@ class ExtJSFile {
* @param string $file The source file
*/
public function __construct ($file) {
+ $file = str_replace("//", "/", $file);
+
$this->source = file_get_contents($file);
if ($this->parseExtendDirective() != "") {