summaryrefslogtreecommitdiff
path: root/weave_storage.php
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2011-03-17 00:01:25 +0000
committerdakkar <dakkar@thenautilus.net>2011-03-17 00:01:25 +0000
commitabd38899f6f1fcf7c8f16eb83356c8ce1070cf71 (patch)
tree1374fd9507ef1d0a5bb77b82c6d3846b9170b79e /weave_storage.php
downloadweave-minimal-abd38899f6f1fcf7c8f16eb83356c8ce1070cf71.tar.gz
weave-minimal-abd38899f6f1fcf7c8f16eb83356c8ce1070cf71.tar.bz2
weave-minimal-abd38899f6f1fcf7c8f16eb83356c8ce1070cf71.zip
import from http://tobyelliott.wordpress.com/2009/09/11/weave-minimal-server/
Diffstat (limited to 'weave_storage.php')
-rw-r--r--weave_storage.php787
1 files changed, 787 insertions, 0 deletions
diff --git a/weave_storage.php b/weave_storage.php
new file mode 100644
index 0000000..c82873d
--- /dev/null
+++ b/weave_storage.php
@@ -0,0 +1,787 @@
+<?php
+
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Weave Basic Object Server
+#
+# The Initial Developer of the Original Code is
+# Mozilla Labs.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Toby Elliott (telliott@mozilla.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+require_once 'weave_basic_object.php';
+
+class WeaveStorage
+{
+ private $_username;
+ private $_dbh;
+
+ function __construct($username)
+ {
+ $this->_username = $username;
+ $path = explode('/', $_SERVER['SCRIPT_FILENAME']);
+ $db_name = 'weave_db';
+ array_pop($path);
+ array_push($path, $db_name);
+ $db_name = implode('/', $path);
+
+ $create_tables = !file_exists($db_name);
+
+ try
+ {
+ $this->_dbh = new PDO('sqlite:' . $db_name);
+ $this->_dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ }
+ catch( PDOException $exception )
+ {
+ throw new Exception("Database unavailable", 503);
+ }
+
+ if ($create_tables)
+ $this->setup_db();
+ }
+
+ function get_connection()
+ {
+ return $this->_dbh;
+ }
+
+ function begin_transaction()
+ {
+ try
+ {
+ $this->_dbh->beginTransaction();
+ }
+ catch( PDOException $exception )
+ {
+ error_log("begin_transaction: " . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+ return 1;
+ }
+
+ function commit_transaction()
+ {
+ $this->_dbh->commit();
+ return 1;
+ }
+
+ function get_max_timestamp($collection)
+ {
+ if (!$collection)
+ {
+ return 0;
+ }
+
+ try
+ {
+ $select_stmt = 'select max(modified) from wbo where username = :username and collection = :collection';
+ $sth = $this->_dbh->prepare($select_stmt);
+ $sth->bindParam(':username', $this->_username);
+ $sth->bindParam(':collection', $collection);
+ $sth->execute();
+ }
+ catch( PDOException $exception )
+ {
+ error_log("get_max_timestamp: " . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+
+ $result = $sth->fetchColumn();
+ return round((float)$result, 2);
+ }
+
+ function get_collection_list()
+ {
+ try
+ {
+ $select_stmt = 'select distinct(collection) from wbo where username = :username';
+ $sth = $this->_dbh->prepare($select_stmt);
+ $sth->bindParam(':username', $this->_username);
+ $sth->execute();
+ }
+ catch( PDOException $exception )
+ {
+ error_log("get_collection_list: " . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+
+
+ $collections = array();
+ while ($result = $sth->fetchColumn())
+ {
+ $collections[] = $result;
+ }
+
+ return $collections;
+ }
+
+
+ function get_collection_list_with_timestamps()
+ {
+ try
+ {
+ $select_stmt = 'select collection, max(modified) as timestamp from wbo where username = :username group by collection';
+ $sth = $this->_dbh->prepare($select_stmt);
+ $sth->bindParam(':username', $this->_username);
+ $sth->execute();
+ }
+ catch( PDOException $exception )
+ {
+ error_log("get_collection_list: " . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+
+ $collections = array();
+ while ($result = $sth->fetch(PDO::FETCH_NUM))
+ {
+ $collections[$result[0]] = (float)$result[1];
+ }
+
+ return $collections;
+ }
+
+ function get_collection_list_with_counts()
+ {
+ try
+ {
+ $select_stmt = 'select collection, count(*) as ct from wbo where username = :username group by collection';
+ $sth = $this->_dbh->prepare($select_stmt);
+ $sth->bindParam(':username', $this->_username);
+ $sth->execute();
+ }
+ catch( PDOException $exception )
+ {
+ error_log("get_collection_list_with_counts: " . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+
+
+ $collections = array();
+ while ($result = $sth->fetch(PDO::FETCH_NUM))
+ {
+ $collections[$result[0]] = (int)$result[1];
+ }
+
+ return $collections;
+ }
+
+ function store_object(&$wbo)
+ {
+
+ try
+ {
+ $insert_stmt = 'replace into wbo (username, id, collection, parentid, predecessorid, sortindex, modified, payload, payload_size, depth)
+ values (:username, :id, :collection, :parentid, :predecessorid, :sortindex, :modified, :payload, :payload_size, :depth)';
+ $sth = $this->_dbh->prepare($insert_stmt);
+ $sth->bindParam(':username', $this->_username);
+ $sth->bindParam(':id', $wbo->id());
+ $sth->bindParam(':collection', $wbo->collection());
+ $sth->bindParam(':parentid', $wbo->parentid());
+ $sth->bindParam(':predecessorid', $wbo->predecessorid());
+ $sth->bindParam(':depth', $wbo->depth());
+ $sth->bindParam(':sortindex', $wbo->sortindex());
+ $sth->bindParam(':modified', $wbo->modified());
+ $sth->bindParam(':payload', $wbo->payload());
+ $sth->bindParam(':payload_size', $wbo->payload_size());
+
+ $sth->execute();
+
+ }
+ catch( PDOException $exception )
+ {
+ error_log("store_object: " . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+ return 1;
+ }
+
+
+ function update_object(&$wbo)
+ {
+ $update = "update wbo set ";
+ $params = array();
+ $update_list = array();
+
+ #make sure we have an id and collection. No point in continuing otherwise
+ if (!$wbo->id() || !$wbo->collection())
+ {
+ error_log('Trying to update without a valid id or collection!');
+ return 0;
+ }
+
+ if ($wbo->parentid_exists())
+ {
+ $update_list[] = "parentid = ?";
+ $params[] = $wbo->parentid();
+ }
+
+ if ($wbo->parentid_exists())
+ {
+ $update_list[] = "predecessorid = ?";
+ $params[] = $wbo->predecessorid();
+ }
+
+ if ($wbo->depth_exists())
+ {
+ $update_list[] = "depth = ?";
+ $params[] = $wbo->depth();
+ }
+
+ if ($wbo->sortindex_exists())
+ {
+ $update_list[] = "sortindex = ?";
+ $params[] = $wbo->sortindex();
+ }
+
+ if ($wbo->payload_exists())
+ {
+ $update_list[] = "payload = ?";
+ $update_list[] = "payload_size = ?";
+ $params[] = $wbo->payload();
+ $params[] = $wbo->payload_size();
+ }
+
+ # Don't modify the timestamp on a depth-only change
+ if ($wbo->parentid_exists() || $wbo->payload_exists())
+ {
+ #better make sure we have a modified date. Should have been handled earlier
+ if (!$wbo->modified_exists())
+ {
+ error_log("Called update_object with no defined timestamp. Please check");
+ $wbo->modified(microtime(1));
+ }
+ $update_list[] = "modified = ?";
+ $params[] = $wbo->modified();
+
+ }
+
+
+ if (count($params) == 0)
+ {
+ return 0;
+ }
+
+ $update .= join($update_list, ",");
+
+ $update .= " where username = ? and collection = ? and id = ?";
+ $params[] = $this->_username;
+ $params[] = $wbo->collection();
+ $params[] = $wbo->id();
+
+ try
+ {
+ $sth = $this->_dbh->prepare($update);
+ $sth->execute($params);
+ }
+ catch( PDOException $exception )
+ {
+ error_log("update_object: " . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+ return 1;
+ }
+
+ function delete_object($collection, $id)
+ {
+ try
+ {
+ $delete_stmt = 'delete from wbo where username = :username and collection = :collection and id = :id';
+ $sth = $this->_dbh->prepare($delete_stmt);
+ $sth->bindParam(':username', $this->_username);
+ $sth->bindParam(':collection', $collection);
+ $sth->bindParam(':id', $id);
+ $sth->execute();
+ }
+ catch( PDOException $exception )
+ {
+ error_log("delete_object: " . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+ return 1;
+ }
+
+ function delete_objects($collection, $id = null, $parentid = null, $predecessorid = null, $newer = null,
+ $older = null, $sort = null, $limit = null, $offset = null, $ids = null,
+ $index_above = null, $index_below = null)
+ {
+ $params = array();
+ $select_stmt = '';
+
+ if ($limit || $offset || $sort)
+ {
+ #sqlite can't do sort or limit deletes without special compiled versions
+ #so, we need to grab the set, then delete it manually.
+
+ $params = $this->retrieve_objects($collection, $id, 0, 0, $parentid, $predecessorid, $newer, $older, $sort, $limit, $offset, $ids, $index_above, $index_below);
+ if (!count($params))
+ {
+ return 1; #nothing to delete
+ }
+ $paramqs = array();
+ $select_stmt = "delete from wbo where username = ? and collection = ? and id in (" . join(", ", array_pad($paramqs, count($params), '?')) . ")";
+ array_unshift($params, $collection);
+ array_unshift($params, $username);
+ }
+ else
+ {
+
+ $select_stmt = "delete from wbo where username = ? and collection = ?";
+ $params[] = $this->_username;
+ $params[] = $collection;
+
+
+ if ($id)
+ {
+ $select_stmt .= " and id = ?";
+ $params[] = $id;
+ }
+
+ if ($ids && count($ids) > 0)
+ {
+ $qmarks = array();
+ $select_stmt .= " and id in (";
+ foreach ($ids as $temp)
+ {
+ $params[] = $temp;
+ $qmarks[] = '?';
+ }
+ $select_stmt .= implode(",", $qmarks);
+ $select_stmt .= ')';
+ }
+
+ if ($parentid)
+ {
+ $select_stmt .= " and parentid = ?";
+ $params[] = $parentid;
+ }
+
+ if ($predecessorid)
+ {
+ $select_stmt .= " and predecessorid = ?";
+ $params[] = $parentid;
+ }
+
+ if ($index_above)
+ {
+ $select_stmt .= " and sortindex > ?";
+ $params[] = $parentid;
+ }
+
+ if ($index_below)
+ {
+ $select_stmt .= " and sortindex < ?";
+ $params[] = $parentid;
+ }
+
+ if ($newer)
+ {
+ $select_stmt .= " and modified > ?";
+ $params[] = $newer;
+ }
+
+ if ($older)
+ {
+ $select_stmt .= " and modified < ?";
+ $params[] = $older;
+ }
+
+ if ($sort == 'index')
+ {
+ $select_stmt .= " order by sortindex desc";
+ }
+ else if ($sort == 'newest')
+ {
+ $select_stmt .= " order by modified desc";
+ }
+ else if ($sort == 'oldest')
+ {
+ $select_stmt .= " order by modified";
+ }
+
+ if ($limit)
+ {
+ $select_stmt .= " limit " . intval($limit);
+ if ($offset)
+ {
+ $select_stmt .= " offset " . intval($offset);
+ }
+ }
+ }
+
+ try
+ {
+ $sth = $this->_dbh->prepare($select_stmt);
+ $sth->execute($params);
+ }
+ catch( PDOException $exception )
+ {
+ error_log("delete_objects: " . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+ return 1;
+ }
+
+ function retrieve_object($collection, $id)
+ {
+ try
+ {
+ $select_stmt = 'select * from wbo where username = :username and collection = :collection and id = :id';
+ $sth = $this->_dbh->prepare($select_stmt);
+ $sth->bindParam(':username', $this->_username);
+ $sth->bindParam(':collection', $collection);
+ $sth->bindParam(':id', $id);
+ $sth->execute();
+ }
+ catch( PDOException $exception )
+ {
+ error_log("retrieve_object: " . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+
+ $result = $sth->fetch(PDO::FETCH_ASSOC);
+
+ $wbo = new wbo();
+ $wbo->populate($result);
+ return $wbo;
+ }
+
+ function retrieve_objects($collection, $id = null, $full = null, $direct_output = null, $parentid = null,
+ $predecessorid = null, $newer = null, $older = null, $sort = null,
+ $limit = null, $offset = null, $ids = null,
+ $index_above = null, $index_below = null, $depth = null)
+ {
+ $full_list = $full ? '*' : 'id';
+
+
+ $select_stmt = "select $full_list from wbo where username = ? and collection = ?";
+ $params[] = $this->_username;
+ $params[] = $collection;
+
+
+ if ($id)
+ {
+ $select_stmt .= " and id = ?";
+ $params[] = $id;
+ }
+
+ if ($ids && count($ids) > 0)
+ {
+ $qmarks = array();
+ $select_stmt .= " and id in (";
+ foreach ($ids as $temp)
+ {
+ $params[] = $temp;
+ $qmarks[] = '?';
+ }
+ $select_stmt .= implode(",", $qmarks);
+ $select_stmt .= ')';
+ }
+
+ if ($ids && count($ids) > 0)
+ {
+ $qmarks = array();
+ $select_stmt .= " and id in (";
+ foreach ($ids as $temp)
+ {
+ $params[] = $temp;
+ $qmarks[] = '?';
+ }
+ $select_stmt .= implode(",", $qmarks);
+ $select_stmt .= ')';
+ }
+
+ if ($parentid)
+ {
+ $select_stmt .= " and parentid = ?";
+ $params[] = $parentid;
+ }
+
+
+ if ($predecessorid)
+ {
+ $select_stmt .= " and predecessorid = ?";
+ $params[] = $predecessorid;
+ }
+
+ if ($index_above)
+ {
+ $select_stmt .= " and sortindex > ?";
+ $params[] = $parentid;
+ }
+
+ if ($index_below)
+ {
+ $select_stmt .= " and sortindex < ?";
+ $params[] = $parentid;
+ }
+
+ if ($newer)
+ {
+ $select_stmt .= " and modified > ?";
+ $params[] = $newer;
+ }
+
+ if ($older)
+ {
+ $select_stmt .= " and modified < ?";
+ $params[] = $older;
+ }
+
+
+ if ($depth)
+ {
+ $select_stmt .= " and depth = ?";
+ $params[] = $depth;
+ }
+
+ if ($sort == 'index')
+ {
+ $select_stmt .= " order by sortindex desc";
+ }
+ else if ($sort == 'newest')
+ {
+ $select_stmt .= " order by modified desc";
+ }
+ else if ($sort == 'oldest')
+ {
+ $select_stmt .= " order by modified";
+ }
+
+ if ($limit)
+ {
+ $select_stmt .= " limit " . intval($limit);
+ if ($offset)
+ {
+ $select_stmt .= " offset " . intval($offset);
+ }
+ }
+
+ try
+ {
+ $sth = $this->_dbh->prepare($select_stmt);
+ $sth->execute($params);
+ }
+ catch( PDOException $exception )
+ {
+ error_log("retrieve_collection: " . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+
+ if ($direct_output)
+ return $direct_output->output($sth);
+
+ $ids = array();
+ while ($result = $sth->fetch(PDO::FETCH_ASSOC))
+ {
+ if ($full)
+ {
+ $wbo = new wbo();
+ $wbo->populate($result);
+ $ids[] = $wbo;
+ }
+ else
+ $ids[] = $result{'id'};
+ }
+ return $ids;
+ }
+
+ function get_storage_total()
+ {
+ try
+ {
+ $select_stmt = 'select round(sum(length(payload))/1024) from wbo where username = :username';
+ $sth = $this->_dbh->prepare($select_stmt);
+ $sth->bindParam(':username', $this->_username);
+ $sth->execute();
+ }
+ catch( PDOException $exception )
+ {
+ error_log("get_storage_total: " . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+
+ return (int)$sth->fetchColumn();
+ }
+
+ function get_user_quota()
+ {
+ return null;
+ }
+
+ function delete_user($username)
+ {
+ if (!$username)
+ {
+ throw new Exception("3", 404);
+ }
+
+ try
+ {
+ $delete_stmt = 'delete from users where username = :username';
+ $sth = $this->_dbh->prepare($delete_stmt);
+ $sth->bindParam(':username', $username);
+ $sth->execute();
+ $sth->closeCursor();
+
+ $delete_wbo_stmt = 'delete from wbo where username = :username';
+ $sth = $this->_dbh->prepare($delete_wbo_stmt);
+ $sth->bindParam(':username', $username);
+ $sth->execute();
+
+ }
+ catch( PDOException $exception )
+ {
+ error_log("delete_user: " . $exception->getMessage());
+ return 0;
+ }
+ return 1;
+ }
+
+ function create_user($username, $password)
+ {
+ try
+ {
+ $create_statement = "insert into users values (:username, :md5)";
+
+ $sth = $this->_dbh->prepare($create_statement);
+ $sth->bindParam(':username', $username);
+ $sth->bindParam(':md5', md5($password));
+ $sth->execute();
+ }
+ catch( PDOException $exception )
+ {
+ error_log("create_user:" . $exception->getMessage());
+ return 0;
+ }
+ return 1;
+ }
+
+ function change_password($username, $password)
+ {
+ try
+ {
+ $update_statement = "update users set md5 = :md5 where username = :username";
+
+ $sth = $this->_dbh->prepare($update_statement);
+ $sth->bindParam(':username', $username);
+ $sth->bindParam(':md5', md5($password));
+ $sth->execute();
+ }
+ catch( PDOException $exception )
+ {
+ error_log("change_password:" . $exception->getMessage());
+ return 0;
+ }
+ return 1;
+ }
+
+ function authenticate_user($password)
+ {
+ try
+ {
+ $select_stmt = 'select username from users where username = :username and md5 = :md5';
+ $sth = $this->_dbh->prepare($select_stmt);
+ $sth->bindParam(':username', $this->_username);
+ $sth->bindParam(':md5', md5($password));
+ $sth->execute();
+ }
+ catch( PDOException $exception )
+ {
+ error_log("authenticate_user: " . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+
+ if (!$result = $sth->fetch(PDO::FETCH_ASSOC))
+ {
+ return null;
+ }
+
+ return 1;
+ }
+
+ function setup_db()
+ {
+
+ try
+ {
+ $create_statement = <<< end
+create table wbo
+(
+ username text,
+ id text,
+ collection text,
+ parentid text,
+ predecessorid int,
+ modified real,
+ sortindex int,
+ depth int,
+ payload text,
+ payload_size int,
+ primary key (username,collection,id)
+)
+end;
+
+ $create_statement2 = <<< end
+create table users
+(
+ username text,
+ md5 text,
+ primary key (username)
+)
+end;
+
+ $index1 = 'create index parentindex on wbo (username, parentid)';
+ $index2 = 'create index predecessorindex on wbo (username, predecessorid)';
+ $index3 = 'create index modifiedindex on wbo (username, collection, modified)';
+
+
+ $sth = $this->_dbh->prepare($create_statement);
+ $sth->execute();
+ $sth = $this->_dbh->prepare($create_statement2);
+ $sth->execute();
+ $sth = $this->_dbh->prepare($index1);
+ $sth->execute();
+ $sth = $this->_dbh->prepare($index2);
+ $sth->execute();
+ $sth = $this->_dbh->prepare($index3);
+ $sth->execute();
+ }
+ catch( PDOException $exception )
+ {
+ error_log("initialize_user_db:" . $exception->getMessage());
+ throw new Exception("Database unavailable", 503);
+ }
+ }
+}
+
+
+ ?> \ No newline at end of file