code cleanup

added doctrine parts
This commit is contained in:
Steffen Vogel 2010-07-09 23:50:20 +02:00
parent 2c173faa4e
commit e205925b19
28 changed files with 390 additions and 217 deletions

View file

@ -0,0 +1,6 @@
<?php
$cliConfig = new Doctrine\Common\Cli\Configuration();
$cliConfig->setAttribute('em', $entityManager);
?>

1
backend/bin/doctrine Symbolic link
View file

@ -0,0 +1 @@
/home/steffen/workspace/doctrine2/bin/doctrine

1
backend/bin/doctrine.php Symbolic link
View file

@ -0,0 +1 @@
/home/steffen/workspace/doctrine2/bin/doctrine.php

View file

@ -20,11 +20,9 @@
*/
/*
* Bootstrap entrypoint, just calls Frontcontroller::run()
* Bootstrap entrypoint, just calls FrontController::run()
*/
include 'init.php'; // initialize environment (error handling, configuration, class autoloading)
$fc = new FrontController(); // spawn frontcontroller
$fc->run(); // execute controller and sends output

View file

@ -1,73 +0,0 @@
<?php
/*
* Copyright (c) 2010 by Justin Otherguy <justin@justinotherguy.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (either version 2 or
* version 3) as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* For more information on the GPL, please go to:
* http://www.gnu.org/copyleft/gpl.html
*/
define('VZ_VERSION', '0.2');
/*
* class autoloading
*/
function __autoload($className) {
$libs = __DIR__ . '/lib/';
// preg_replace pattern class name => inclulde path
$mapping = array(
// util classes
'/^Registry$/' => 'util/registry',
'/^Uuid$/' => 'util/uuid',
// model classes
'/^(Channel|User|Group|(Nested)?Database(Object)?)$/'=> 'model/$1',
'/^(MySql|PgSql|SqLite)$/i' => 'model/db/$1',
'/^(.+(Meter|Sensor))$/' => 'model/channel/$2/$1',
'/^(Meter|Sensor)$/' => 'model/channel/$1',
// view classes
'/^(Http.*)$/' => 'view/http/$1',
'/^(.*View)$/' => 'view/$1',
// controller classes
'/^(.*Controller)$/' => 'controller/$1'
);
$include = $libs . strtolower(preg_replace(array_keys($mapping), array_values($mapping), $className)) . '.php';
if (empty($include)) {
throw new Exception('Cannot load class ' . $className . '! Name not mapped.');
}
if (!file_exists($include)) {
throw new Exception('Cannot load class ' . $className . '! File does not exist: ' . $include);
}
require_once $include;
}
// enable strict error reporting
error_reporting(E_ALL);
// load configuration into registry
if (!file_exists(__DIR__ . '/volkszaehler.conf.php')) {
throw new Exception('No configuration available! Use volkszaehler.conf.default.php as an template');
}
include __DIR__ . '/volkszaehler.conf.php';
?>

View file

@ -21,8 +21,7 @@
class ChannelController extends Controller {
public function get() {
$user = User::getByUuid($this->view->request->get['uuid']);
$channels = $user->getChannels(false); // TODO recursive or not?
// TODO get channels from entity manager
foreach ($channels as $channel) {
$this->view->addChannel($channel);
@ -32,22 +31,29 @@ class ChannelController extends Controller {
public function add() {
$channel = new Channel();
/*if (substr($channel->uuid, 0, 19) == OneWireSensor::$uuidPrefix) { // TODO how do differ the 1-wire sensors?
// TODO how do differ the 1-wire sensors?
/*if (substr($channel->uuid, 0, 19) == OneWireSensor::$uuidPrefix) {
$channel->type = 'OneWireSensor';
$channel->description = OneWireSensor::getFamilyDescription($channel);
}
else {
$channel->type = 'Channel';
}*/
$channel->persist();
$channel->save();
$this->view->addChannel($channel);
}
public function delete() { // TODO authentification
// TODO check for valid user identity
public function delete() {
$channel = Channel::getByUuid($this->view->request->get['ucid']);
$channel->delete();
}
public function edit() {
// TODO implement ChannelController::edit();
}
}
?>

View file

@ -21,17 +21,16 @@
class ControllerException extends Exception {};
interface ControllerInterface {
public function __construct(View $view);
}
abstract class Controller implements ControllerInterface {
abstract class Controller {
protected $view;
public function __construct(View $view) {
$this->view = $view;
}
/*
* catches unknown actions
*/
public function __call($method, $param) {
throw new ControllerException('Undefined controller action!');
}

View file

@ -20,12 +20,6 @@
*/
class DataController extends Controller {
public function add() {
$ucid = $this->view->request->get['ucid'];
$channel = Channel::getByUuid($ucid);
$channel->addData($this->view->request->get); // array(timestamp, value, count)
}
public function get() {
$ids = explode(',', trim($this->view->request->get['ids']));
$channels = Channel::getByFilter(array('id' => $ids), true, false); // get all channels with id in $ids as an array
@ -35,7 +29,14 @@ class DataController extends Controller {
$groupBy = (isset($this->view->request->get['groupBy'])) ? $this->view->request->get['groupBy'] : NULL; // get all readings by default
foreach ($channels as $channel) {
// TODO change to Channel::getValues()
$this->view->addChannel($channel, $channel->getPulses($from, $to, $groupBy));
}
}
public function add() {
$ucid = $this->view->request->get['ucid'];
$channel = Channel::getByUuid($ucid);
$channel->addData($this->view->request->get); // array(timestamp, value, count)
}
}

View file

@ -0,0 +1,132 @@
<?php
/*
* Copyright (c) 2010 by Justin Otherguy <justin@justinotherguy.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (either version 2 or
* version 3) as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* For more information on the GPL, please go to:
* http://www.gnu.org/copyleft/gpl.html
*/
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Configuration;
final class FrontController {
// MVC
private $em = NULL; // Model (Doctrine Entitymanager)
private $view = NULL; // View
private $controller = NULL; // Controller
public function __construct() {
// create view instance
$view = $request->get['format'] . 'View';
if (!class_exists($view) || !is_subclass_of($view, 'View')) {
throw new InvalidArgumentException('\'' . $view . '\' is not a valid View');
}
$this->view = new $view;
// create entitymanager
require '/path/to/lib/Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine', 'lib/doctrine/lib');
$classLoader->register(); // register on SPL autoload stack
// Doctrine
$doctConfig = new Configuration;
//$cache = new \Doctrine\Common\Cache\ApcCache;
//$config->setMetadataCacheImpl($cache);
$driverImpl = $doctConfig->newDefaultAnnotationDriver('/path/to/lib/MyProject/Entities');
$doctConfig->setMetadataDriverImpl($driverImpl);
//$config->setQueryCacheImpl($cache);
$doctConfig->setProxyDir('/path/to/myproject/lib/MyProject/Proxies');
$doctConfig->setProxyNamespace('MyProject\Proxies');
$em = EntityManager::create($config['db'], $doctConfig);
}
public function run() {
// create controller instance
$controller = $request->get['controller'] . 'Controller';
if (!class_exists($controller) || !is_subclass_of($controller, 'Controller')) {
throw new ControllerException('\'' . $controller . '\' is not a valid controller');
}
$controller = new $controller($this->view);
$action = $this->view->request->get['action'];
$controller->$action(); // run controllers actions (usually CRUD: http://de.wikipedia.org/wiki/CRUD)
}
public function __destruct() {
$this->view->render(); // render view & send http response
}
public static function initialize() {
define('VERSION', '0.2');
// enable strict error reporting
error_reporting(E_ALL);
// load configuration into registry
if (!file_exists(__DIR__ . '/volkszaehler.conf.php')) {
throw new Exception('No configuration available! Use volkszaehler.conf.default.php as an template');
}
include __DIR__ . '/volkszaehler.conf.php';
spl_autoload_register(array($this, 'loadClass'));
$this->initializeDoctrine();
}
/*
* class autoloading
*/
private function loadClass($className) {
$libs = __DIR__ . '/lib/';
// preg_replace pattern class name => inclulde path
$mapping = array(
// util classes
'/^Registry$/' => 'util/registry',
'/^Uuid$/' => 'util/uuid',
// model classes
'/^(Channel|User|Group|(Nested)?Database(Object)?)$/'=> 'model/$1',
'/^(.+(Meter|Sensor))$/' => 'model/channel/$2/$1',
'/^(Meter|Sensor)$/' => 'model/channel/$1',
// view classes
'/^(Http.*)$/' => 'view/http/$1',
'/^(.*View)$/' => 'view/$1',
// controller classes
'/^(.*Controller)$/' => 'controller/$1'
);
$include = $libs . strtolower(preg_replace(array_keys($mapping), array_values($mapping), $className)) . '.php';
if (!file_exists($include)) {
return false;
}
require_once $include;
return true;
}
}
?>

View file

@ -20,29 +20,38 @@ chann<?php
*/
class GroupController extends Controller {
public function add() {
$group = new Group();
$group->name = $this->view->request->get['name'];
$group->description = $this->view->request->get['description'];
$group->save();
$this->view->addGroup($group);
}
public function delete() {
$group = Group::getByUuid($this->view->request->get['ugid']);
$group->delete();
}
public function get() {
$user = User::getByUuid($this->view->request->get['uuid']);
$groups = $user->getGroups(false); // TODO recursive or not?
// TODO get groups from entitymanager according to API specs
foreach ($groups as $group) {
$this->view->addGroup($group);
}
}
public function add() {
$group = new Group();
$group->name = $this->view->request->get['name'];
$group->description = $this->view->request->get['description'];
// TODO adapt to doctrine orm
$group->save();
$this->view->addGroup($group);
}
// TODO check for valid user identity
public function delete() {
$group = Group::getByUuid($this->view->request->get['ugid']);
// TODO adapt to doctrine orm
$group->delete();
}
public function edit() {
// TODO implement GroupController::edit();
}
}
?>

View file

@ -20,18 +20,26 @@
*/
class UserController extends Controller {
// TODO do we need this?
public function get() {
}
public function add() {
$user = new User();
$user->password = $this->view->request->get['password'];
// TODO generate uuid
// TODO adapt to doctrine orm
$user->save();
$this->view->addUser($user);
}
// TODO check for valid user identity
public function delete() {
$user = User::getByUuid($this->view->request->get['uuid']);
// TODO adapt to doctrine orm
$user->delete();
}

View file

@ -31,12 +31,36 @@ interface ChannelInterface {
public function getAverage($from = NULL, $to = NULL);
}
abstract class Channel extends DatabaseObject implements ChannelInterface {
/**
* Channel class
*
* @Entity
* @Table(name="channels")
*/
abstract class Channel extends Entity implements ChannelInterface {
/** @Column(type="string") */
protected $type;
/** @Column(type="integer") */
protected $resolution;
/** @Column(type="integer") */
protected $cost;
/** @Column(type="string") */
protected $name;
/** @Column(type="string") */
protected $description;
/*
* deletes all data from database
*/
public function reset($from = NULL, $to = NULL) {
$this->dbh->execute('DELETE FROM data WHERE channel_id = ' . (int) $this->id) . $this->buildTimeFilter($from, $to);
* prune all data from database
*/
public function reset($from = 0, $to = NULL) {
// TODO add timefilter
$sql = 'DELETE FROM data WHERE channel_id = ' . (int) $this->id . ' && from to';
// TODO delelte with doctrine dal
}
/*
@ -44,11 +68,13 @@ abstract class Channel extends DatabaseObject implements ChannelInterface {
*/
public function addData($data) {
$sql = 'INSERT INTO data (channel_id, timestamp, value) VALUES(' . $this->dbh->escape($this) . ', ' . $this->dbh->escape($data['timestamp']) . ', ' . $this->dbh->escape($data['value']) . ')';
$this->dbh->execute($sql);
// TODO insert with doctrine dal
}
/*
* This function retrieve data from the database. If desired it groups it into packages ($groupBy parameter)
* retrieve data from the database
*
* If desired it groups it into packages ($groupBy parameter)
*
* @return array() Array with timestamps => value (sorted by timestamp from newest to oldest)
* @param $groupBy determines how readings are grouped. Possible values are: year, month, day, hour, minute or an integer for the desired size of the returned array
@ -96,8 +122,10 @@ abstract class Channel extends DatabaseObject implements ChannelInterface {
}
$sql .= ' ORDER BY timestamp DESC';
$result = $this->dbh->query($sql);
$totalCount = $result->count();
// TODO query with doctrine dal
//$result = $this->dbh->query($sql);
//$totalCount = $result->count();
if (is_int($groupBy) && $groupBy < $totalCount) { // return $groupBy values
$packageSize = floor($totalCount / $groupBy);
@ -128,21 +156,4 @@ abstract class Channel extends DatabaseObject implements ChannelInterface {
return array_reverse($packages); // start with oldest ts and ends with newest ts (reverse array order due to descending order in sql statement)
}
/*
* build simple timeframe filter
*/
static protected function buildFilterTime($from = NULL, $to = NULL) {
$sql = '';
if (is_int($to) && $to <= time() * 1000) {
$sql .= ' && timestamp < ' . $to;
}
if (is_int($from) && $from > 0) {
$sql .= ' && timestamp > ' . $from;
}
return $sql;
}
}

View file

@ -20,7 +20,6 @@
*/
abstract class Sensor extends Channel {
public function getData($from = NULL, $to = NULL, $groupBy = NULL) {
$data = parent::getData($from, $to, $groupBy);

View file

@ -19,13 +19,19 @@
* http://www.gnu.org/copyleft/gpl.html
*/
/*
* Grouping class
/**
* Database Entity
*
* the group class groups users, channels and groups itself
* @todo doctrine abstract entity?
* @Entity
*/
class Group extends NestedDatabaseObject {
}
?>
abstract class Entity {
/**
* @Id
* @Column(type="integer")
*/
protected $id;
/** @Column(type="string", length=36) */
protected $uuid;
}

View file

@ -0,0 +1,49 @@
<?php
/*
* Copyright (c) 2010 by Justin Otherguy <justin@justinotherguy.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (either version 2 or
* version 3) as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* For more information on the GPL, please go to:
* http://www.gnu.org/copyleft/gpl.html
*/
use Doctrine\Common\Collections\ArrayCollection;
/**
* Grouping class
*
* @Entity
* @Table(name="groups")
*/
class Group extends Entity {
/** @Column(type="string") */
protected $name;
/** @Column(type="string") */
protected $description;
// TODO doctrine join
protected $channels = NULL;
// TODO doctrine nested selfjoin
protected $children = NULL;
public function __construct() {
$this->channels = new ArrayCollection();
$this->children = new ArrayCollection();
}
}
?>

View file

@ -19,11 +19,27 @@
* http://www.gnu.org/copyleft/gpl.html
*/
/*
* User class
*/
class User extends DatabaseObject {
use Doctrine\Common\Collections\ArrayCollection;
/**
* User class
*
* @Entity
* @Table(name="users")
*/
class User extends Entity {
/** @Column(type="string") */
protected $email;
/** @Column(type="string") */
protected $passwords;
// TODO doctrine join
protected $groups = NULL;
public function __construct() {
$this->groups = new ArrayCollection();
}
}
?>

View file

@ -0,0 +1,37 @@
<?php
/*
* Copyright (c) 2010 by Justin Otherguy <justin@justinotherguy.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (either version 2 or
* version 3) as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* For more information on the GPL, please go to:
* http://www.gnu.org/copyleft/gpl.html
*/
class Configuration extends Registry implements ArrayAccess {
public function offsetSet($offset, $value) {
$this->registry[$offset] = $value;
}
public function offsetExists($offset) {
return isset($this->registry[$offset]);
}
public function offsetUnset($offset) {
unset($this->registry[$offset]);
}
public function offsetGet($offset) {
return isset($this->registry[$offset]) ? $this->registry[$offset] : null;
}
}
?>

View file

@ -1,4 +1,23 @@
<?php
/*
* Copyright (c) 2010 by Justin Otherguy <justin@justinotherguy.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (either version 2 or
* version 3) as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* For more information on the GPL, please go to:
* http://www.gnu.org/copyleft/gpl.html
*/
/**
* Registry class to pass global variables between classes.
@ -9,7 +28,7 @@ abstract class Registry {
*
* @var array
*/
private static $registry = array();
protected static $registry = array();
/**
* Adds a new variable to the Registry.

View file

@ -1,53 +0,0 @@
<?php
/*
* Copyright (c) 2010 by Justin Otherguy <justin@justinotherguy.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (either version 2 or
* version 3) as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* For more information on the GPL, please go to:
* http://www.gnu.org/copyleft/gpl.html
*/
final class FrontController {
private $controller;
private $view;
public function __construct() {
$request = new HttpRequest();
$response = new HttpResponse();
// create view instance
$view = $request->get['format'] . 'View';
if (!class_exists($view) || !is_subclass_of($view, 'View')) {
throw new InvalidArgumentException('\'' . $view . '\' is not a valid View');
}
$this->view = new $view($request, $response);
// create controller instance
$controller = $request->get['controller'] . 'Controller';
if (!class_exists($controller) || !is_subclass_of($controller, 'Controller')) {
throw new InvalidArgumentException('\'' . $controller . '\' is not a valid controller');
}
$this->controller = new $controller($this->view);
}
public function run() {
$action = $this->view->request->get['action'];
$this->controller->$action(); // run controllers actions (usually CRUD: http://de.wikipedia.org/wiki/CRUD)
$this->view->render(); // render view & send http response
}
}
?>

1
backend/lib/vendor/doctrine vendored Symbolic link
View file

@ -0,0 +1 @@
/home/steffen/workspace/doctrine2/lib/Doctrine/

View file

@ -22,13 +22,13 @@
class JsonView extends View {
public $jsonData = array();
public function __construct(HttpRequest $request, HttpResponse $response) {
parent::__construct($request, $response);
public function __construct() {
parent::__construct();
$config = Registry::get('config');
$this->jsonData['source'] = 'volkszaehler.org';
$this->jsonData['version'] = VZ_VERSION;
$this->jsonData['version'] = VERSION;
$this->jsonData['storage'] = $config['db']['backend'];
$this->jsonData['controller'] = $request->get['controller'];
$this->jsonData['action'] = $request->get['action'];

View file

@ -20,7 +20,6 @@
*/
interface ViewInterface {
public function __construct(HttpRequest $request, HttpResponse $response);
public function render();
public function exceptionHandler(Exception $exception);
public function errorHandler($errno, $errstr, $errfile, $errline);
@ -35,9 +34,10 @@ abstract class View implements ViewInterface {
protected $response;
private $created; // holds timestamp of creation, used later to return time of execution
public function __construct(HttpRequest $request, HttpResponse $response) {
$this->request = $request;
$this->response = $response;
public function __construct() {
$this->request = new HttpRequest();
$this->response = new HttpResponse();
$this->created = microtime(true);
// error & exception handling by view

View file

@ -26,15 +26,15 @@ class XmlView extends View {
private $xmlUsers;
private $xmlGroups;
public function __construct(HttpRequest $request, HttpResponse $response) {
parent::__construct($request, $response);
public function __construct() {
parent::__construct();
$config = Registry::get('config');
$this->xmlDoc = new DOMDocument('1.0', 'UTF-8');
$this->xml = $this->xmlDoc->createElement('volkszaehler');
$this->xml->setAttribute('version', VZ_VERSION);
$this->xml->setAttribute('version', VERSION);
$this->xmlChannels = $this->xmlDoc->createElement('channels');
$this->xmlUsers = $this->xmlDoc->createElement('users');
$this->xmlGroups = $this->xmlDoc->createElement('groups');

View file

@ -19,11 +19,11 @@
* http://www.gnu.org/copyleft/gpl.html
*/
$config['db']['backend'] = 'mysql';
$config['db']['driver'] = 'pdo_mysql';
$config['db']['host'] = 'localhost';
$config['db']['user'] = 'volkszaehler';
$config['db']['password'] = '';
$config['db']['database'] = 'volkszaehler_nested';
$config['db']['dbname'] = 'volkszaehler';
$config['passthru']['enabled'] = false;
$config['passthru']['url'] = 'http://volkszaehler.org/httplog/httplog.php?&passthru=yes';