summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/akismet/tests/Akismet_Helper_Test.php43
-rw-r--r--modules/comment/controllers/comments.php57
-rw-r--r--modules/comment/helpers/comment.php40
-rw-r--r--modules/comment/models/comment.php90
-rw-r--r--modules/comment/tests/Comment_Event_Test.php15
-rw-r--r--modules/comment/tests/Comment_Helper_Test.php32
-rw-r--r--modules/comment/tests/Comment_Model_Test.php17
-rw-r--r--modules/digibug/tests/Digibug_Controller_Test.php36
-rw-r--r--modules/exif/tests/Exif_Test.php7
-rw-r--r--modules/gallery/controllers/albums.php93
-rw-r--r--modules/gallery/controllers/login.php4
-rw-r--r--modules/gallery/controllers/movies.php55
-rw-r--r--modules/gallery/controllers/photos.php55
-rw-r--r--modules/gallery/controllers/simple_uploader.php47
-rw-r--r--modules/gallery/helpers/album.php77
-rw-r--r--modules/gallery/helpers/gallery_event.php18
-rw-r--r--modules/gallery/helpers/gallery_installer.php33
-rw-r--r--modules/gallery/helpers/gallery_rest.php309
-rw-r--r--modules/gallery/helpers/identity.php4
-rw-r--r--modules/gallery/helpers/item.php34
-rw-r--r--modules/gallery/helpers/movie.php114
-rw-r--r--modules/gallery/helpers/photo.php123
-rw-r--r--modules/gallery/libraries/IdentityProvider.php4
-rw-r--r--modules/gallery/libraries/MY_Forge.php14
-rw-r--r--modules/gallery/libraries/MY_ORM.php4
-rw-r--r--modules/gallery/libraries/ORM_MPTT.php82
-rw-r--r--modules/gallery/libraries/drivers/IdentityProvider.php3
-rw-r--r--modules/gallery/models/item.php402
-rw-r--r--modules/gallery/tests/Access_Helper_Test.php110
-rw-r--r--modules/gallery/tests/Gallery_Rest_Helper_Test.php3
-rw-r--r--modules/gallery/tests/Item_Model_Test.php134
-rw-r--r--modules/gallery/tests/Kohana_Bug_Test.php38
-rw-r--r--modules/gallery_unit_test/controllers/gallery_unit_test.php6
-rw-r--r--modules/gallery_unit_test/helpers/test.php50
-rw-r--r--modules/gallery_unit_test/views/kohana_unit_test_cli.php6
-rw-r--r--modules/image_block/helpers/image_block_block.php24
-rw-r--r--modules/image_block/helpers/image_block_rest.php62
-rw-r--r--modules/kohana23_compat/libraries/MY_Database_Builder.php12
-rw-r--r--modules/rest/controllers/rest.php65
-rw-r--r--modules/rest/helpers/rest.php104
-rw-r--r--modules/rest/libraries/Rest_Exception.php17
-rw-r--r--modules/rest/tests/Rest_Controller_Test.php20
-rw-r--r--modules/tag/controllers/admin_tags.php4
-rw-r--r--modules/tag/controllers/tags.php4
-rw-r--r--modules/tag/helpers/tag.php2
-rw-r--r--modules/tag/helpers/tag_rest.php157
-rw-r--r--modules/tag/helpers/tags_rest.php48
-rw-r--r--modules/tag/tests/Tag_Rest_Helper_Test.php12
-rw-r--r--modules/user/controllers/admin_users.php168
-rw-r--r--modules/user/controllers/users.php58
-rw-r--r--modules/user/helpers/group.php17
-rw-r--r--modules/user/helpers/user.php26
-rw-r--r--modules/user/helpers/user_installer.php33
-rw-r--r--modules/user/libraries/drivers/IdentityProvider/Gallery.php13
-rw-r--r--modules/user/models/group.php41
-rw-r--r--modules/user/models/user.php83
-rw-r--r--modules/user/views/user_form.html.php2
-rw-r--r--modules/watermark/controllers/admin_watermarks.php12
58 files changed, 1504 insertions, 1639 deletions
diff --git a/modules/akismet/tests/Akismet_Helper_Test.php b/modules/akismet/tests/Akismet_Helper_Test.php
index d8605d5c..b32e9a02 100644
--- a/modules/akismet/tests/Akismet_Helper_Test.php
+++ b/modules/akismet/tests/Akismet_Helper_Test.php
@@ -23,19 +23,26 @@ class Akismet_Helper_Test extends Unit_Test_Case {
public function setup() {
Input::instance()->ip_address = "1.1.1.1";
request::set_user_agent("Akismet_Helper_Test");
+ module::set_var("akismet", "api_key", "TEST_KEY");
+ }
+
+ private function _make_comment() {
+ $comment = ORM::factory("comment");
+ $comment->item_id = item::root()->id;
+ $comment->author_id = identity::guest()->id;
+ $comment->text = "This is a comment";
+ $comment->guest_name = "John Doe";
+ $comment->guest_email = "john@gallery2.org";
+ $comment->guest_url = "http://gallery2.org";
+ $comment->save();
- $root = ORM::factory("item", 1);
- $this->_comment = comment::create(
- $root, identity::guest(), "This is a comment",
- "John Doe", "john@gallery2.org", "http://gallery2.org");
- foreach ($this->_comment->list_fields("comments") as $name => $field) {
+ // Set the server fields to a known placeholder
+ foreach ($comment->list_fields("comments") as $name => $field) {
if (strpos($name, "server_") === 0) {
- $this->_comment->$name = substr($name, strlen("server_"));
+ $comment->$name = substr($name, strlen("server_"));
}
}
- $this->_comment->save();
-
- module::set_var("akismet", "api_key", "TEST_KEY");
+ return $comment->save();
}
public function build_verify_request_test() {
@@ -51,8 +58,8 @@ class Akismet_Helper_Test extends Unit_Test_Case {
}
public function build_comment_check_request_test() {
- $request = akismet::_build_request("comment-check", $this->_comment);
- $id = $this->_comment->id;
+ $comment = $this->_make_comment();
+ $request = akismet::_build_request("comment-check", $comment);
$expected = "POST /1.1/comment-check HTTP/1.0\r\n" .
"Host: TEST_KEY.rest.akismet.com\r\n" .
"Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n" .
@@ -66,15 +73,15 @@ class Akismet_Helper_Test extends Unit_Test_Case {
"SERVER_HTTP_ACCEPT_CHARSET=http_accept_charset&" .
"blog=http%3A%2F%2F.%2F&comment_author=John+Doe&comment_author_email=john%40gallery2.org&" .
"comment_author_url=http%3A%2F%2Fgallery2.org&comment_content=This+is+a+comment&" .
- "comment_type=comment&permalink=http%3A%2F%2F.%2Findex.php%2Fcomments%2F{$id}&" .
+ "comment_type=comment&permalink=http%3A%2F%2F.%2Findex.php%2Fcomments%2F{$comment->id}&" .
"referrer=http_referer&user_agent=http_user_agent&user_ip=remote_addr";
$this->assert_equal($expected, $request);
}
public function build_submit_spam_request_test() {
- $request = akismet::_build_request("submit-spam", $this->_comment);
- $id = $this->_comment->id;
+ $comment = $this->_make_comment();
+ $request = akismet::_build_request("submit-spam", $comment);
$expected =
"POST /1.1/submit-spam HTTP/1.0\r\n" .
"Host: TEST_KEY.rest.akismet.com\r\n" .
@@ -89,15 +96,15 @@ class Akismet_Helper_Test extends Unit_Test_Case {
"SERVER_HTTP_ACCEPT_CHARSET=http_accept_charset&" .
"blog=http%3A%2F%2F.%2F&comment_author=John+Doe&comment_author_email=john%40gallery2.org&" .
"comment_author_url=http%3A%2F%2Fgallery2.org&comment_content=This+is+a+comment&" .
- "comment_type=comment&permalink=http%3A%2F%2F.%2Findex.php%2Fcomments%2F{$id}&" .
+ "comment_type=comment&permalink=http%3A%2F%2F.%2Findex.php%2Fcomments%2F{$comment->id}&" .
"referrer=http_referer&user_agent=http_user_agent&user_ip=remote_addr";
$this->assert_equal($expected, $request);
}
public function build_submit_ham_request_test() {
- $request = akismet::_build_request("submit-ham", $this->_comment);
- $id = $this->_comment->id;
+ $comment = $this->_make_comment();
+ $request = akismet::_build_request("submit-ham", $comment);
$expected =
"POST /1.1/submit-ham HTTP/1.0\r\n" .
"Host: TEST_KEY.rest.akismet.com\r\n" .
@@ -112,7 +119,7 @@ class Akismet_Helper_Test extends Unit_Test_Case {
"SERVER_HTTP_ACCEPT_CHARSET=http_accept_charset&blog=http%3A%2F%2F.%2F&" .
"comment_author=John+Doe&comment_author_email=john%40gallery2.org&" .
"comment_author_url=http%3A%2F%2Fgallery2.org&comment_content=This+is+a+comment&" .
- "comment_type=comment&permalink=http%3A%2F%2F.%2Findex.php%2Fcomments%2F{$id}&" .
+ "comment_type=comment&permalink=http%3A%2F%2F.%2Findex.php%2Fcomments%2F{$comment->id}&" .
"referrer=http_referer&user_agent=http_user_agent&user_ip=remote_addr";
$this->assert_equal($expected, $request);
diff --git a/modules/comment/controllers/comments.php b/modules/comment/controllers/comments.php
index 068152a2..6c546321 100644
--- a/modules/comment/controllers/comments.php
+++ b/modules/comment/controllers/comments.php
@@ -26,50 +26,39 @@ class Comments_Controller extends Controller {
access::required("view", $item);
$form = comment::get_add_form($item);
- $valid = $form->validate();
- if ($valid) {
- if (identity::active_user()->guest && !$form->add_comment->inputs["name"]->value) {
- $form->add_comment->inputs["name"]->add_error("missing", 1);
- $valid = false;
- }
-
- if (!$form->add_comment->text->value) {
- $form->add_comment->text->add_error("missing", 1);
- $valid = false;
+ try {
+ $valid = $form->validate();
+ $comment = ORM::factory("comment");
+ $comment->item_id = $id;
+ $comment->author_id = identity::active_user()->id;
+ $comment->text = $form->add_comment->text->value;
+ $comment->guest_name = $form->add_comment->inputs["name"]->value;
+ $comment->guest_email = $form->add_comment->email->value;
+ $comment->guest_url = $form->add_comment->url->value;
+ $comment->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ switch ($key) {
+ case "guest_name": $key = "name"; break;
+ case "guest_email": $key = "email"; break;
+ }
+ $form->add_comment->inputs[$key]->add_error($error, 1);
}
+ $valid = false;
}
if ($valid) {
- $comment = comment::create(
- $item, identity::active_user(),
- $form->add_comment->text->value,
- $form->add_comment->inputs["name"]->value,
- $form->add_comment->email->value,
- $form->add_comment->url->value);
-
- $active = identity::active_user();
- if ($active->guest) {
- $form->add_comment->inputs["name"]->value("");
- $form->add_comment->email->value("");
- $form->add_comment->url->value("");
- } else {
- $form->add_comment->inputs["name"]->value($active->full_name);
- $form->add_comment->email->value($active->email);
- $form->add_comment->url->value($active->url);
- }
-
- $form->add_comment->text->value("");
+ $comment->save();
$view = new Theme_View("comment.html", "other", "comment-fragment");
$view->comment = $comment;
print json_encode(
array("result" => "success",
- "view" => $view->__toString(),
- "form" => $form->__toString()));
+ "view" => (string) $view,
+ "form" => (string) comment::get_add_form($item)));
} else {
- print json_encode(
- array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
diff --git a/modules/comment/helpers/comment.php b/modules/comment/helpers/comment.php
index 1e1e7d2f..389c8922 100644
--- a/modules/comment/helpers/comment.php
+++ b/modules/comment/helpers/comment.php
@@ -24,46 +24,6 @@
* Note: by design, this class does not do any permission checking.
*/
class comment_Core {
- /**
- * Create a new comment.
- * @param Item_MOdel $item the parent item
- * @param User_Model $author the author User_Model
- * @param string $text comment body
- * @param string $guest_name guest's name (if the author is a guest user, default empty)
- * @param string $guest_email guest's email (if the author is a guest user, default empty)
- * @param string $guest_url guest's url (if the author is a guest user, default empty)
- * @return Comment_Model
- */
- static function create($item, $author, $text, $guest_name=null,
- $guest_email=null, $guest_url=null) {
- $comment = ORM::factory("comment");
- $comment->author_id = $author->id;
- $comment->guest_email = $guest_email;
- $comment->guest_name = $guest_name;
- $comment->guest_url = $guest_url;
- $comment->item_id = $item->id;
- $comment->text = $text;
- $comment->state = "published";
-
- // These values are useful for spam fighting, so save them with the comment.
- $input = Input::instance();
- $comment->server_http_accept = substr($input->server("HTTP_ACCEPT"), 0, 128);
- $comment->server_http_accept_charset = substr($input->server("HTTP_ACCEPT_CHARSET"), 0, 64);
- $comment->server_http_accept_encoding = substr($input->server("HTTP_ACCEPT_ENCODING"), 0, 64);
- $comment->server_http_accept_language = substr($input->server("HTTP_ACCEPT_LANGUAGE"), 0, 64);
- $comment->server_http_connection = substr($input->server("HTTP_CONNECTION"), 0, 64);
- $comment->server_http_host = substr($input->server("HTTP_HOST"), 0, 64);
- $comment->server_http_referer = substr($input->server("HTTP_REFERER"), 0, 255);
- $comment->server_http_user_agent = substr($input->server("HTTP_USER_AGENT"), 0, 128);
- $comment->server_query_string = substr($input->server("QUERY_STRING"), 0, 64);
- $comment->server_remote_addr = substr($input->server("REMOTE_ADDR"), 0, 32);
- $comment->server_remote_host = substr($input->server("REMOTE_HOST"), 0, 64);
- $comment->server_remote_port = substr($input->server("REMOTE_PORT"), 0, 16);
- $comment->save();
-
- return $comment;
- }
-
static function get_add_form($item) {
$form = new Forge("comments/create/{$item->id}", "", "post", array("id" => "g-comment-form"));
$group = $form->group("add_comment")->label(t("Add comment"));
diff --git a/modules/comment/models/comment.php b/modules/comment/models/comment.php
index e0b82039..69b8505e 100644
--- a/modules/comment/models/comment.php
+++ b/modules/comment/models/comment.php
@@ -54,24 +54,62 @@ class Comment_Model extends ORM {
}
/**
+ * Add some custom per-instance rules.
+ */
+ public function validate($array=null) {
+ // validate() is recursive, only modify the rules on the outermost call.
+ if (!$array) {
+ $this->rules = array(
+ "guest_name" => array("callbacks" => array(array($this, "valid_author"))),
+ "guest_email" => array("rules" => array("email")),
+ "guest_url" => array("rules" => array("url")),
+ "item_id" => array("callbacks" => array(array($this, "valid_item"))),
+ "state" => array("rules" => array("Comment_Model::valid_state")),
+ "text" => array("rules" => array("required")),
+ );
+ }
+
+ parent::validate($array);
+ }
+
+ /**
* @see ORM::save()
*/
public function save() {
- if (!empty($this->changed)) {
- $this->updated = time();
- if (!$this->loaded() && empty($this->created)) {
- $this->created = $this->updated;
- $created = true;
+ $this->updated = time();
+ if (!$this->loaded()) {
+ // New comment
+ $this->created = $this->updated;
+ if (empty($this->state)) {
+ $this->state = "published";
}
- }
- $visible_change = $this->original()->state == "published" || $this->state == "published";
-
- $original = clone $this->original();
- parent::save();
- if (isset($created)) {
+ // These values are useful for spam fighting, so save them with the comment. It's painful to
+ // check each one to see if it already exists before setting it, so just use server_http_host
+ // as a semaphore for now (we use that in g2_import.php)
+ if (empty($this->server_http_host)) {
+ $input = Input::instance();
+ $this->server_http_accept = substr($input->server("HTTP_ACCEPT"), 0, 128);
+ $this->server_http_accept_charset = substr($input->server("HTTP_ACCEPT_CHARSET"), 0, 64);
+ $this->server_http_accept_encoding = substr($input->server("HTTP_ACCEPT_ENCODING"), 0, 64);
+ $this->server_http_accept_language = substr($input->server("HTTP_ACCEPT_LANGUAGE"), 0, 64);
+ $this->server_http_connection = substr($input->server("HTTP_CONNECTION"), 0, 64);
+ $this->server_http_host = substr($input->server("HTTP_HOST"), 0, 64);
+ $this->server_http_referer = substr($input->server("HTTP_REFERER"), 0, 255);
+ $this->server_http_user_agent = substr($input->server("HTTP_USER_AGENT"), 0, 128);
+ $this->server_query_string = substr($input->server("QUERY_STRING"), 0, 64);
+ $this->server_remote_addr = substr($input->server("REMOTE_ADDR"), 0, 32);
+ $this->server_remote_host = substr($input->server("REMOTE_HOST"), 0, 64);
+ $this->server_remote_port = substr($input->server("REMOTE_PORT"), 0, 16);
+ }
+ $visible_change = $this->original()->state == "published" || $this->state == "published";
+ parent::save();
module::event("comment_created", $this);
} else {
+ // Updated comment
+ $visible_change = $this->original()->state == "published" || $this->state == "published";
+ $original = clone $this->original();
+ parent::save();
module::event("comment_updated", $original, $this);
}
@@ -92,4 +130,34 @@ class Comment_Model extends ORM {
$this->join("items", "items.id", "comments.item_id");
return item::viewable($this);
}
+
+ /**
+ * Make sure we have an appropriate author id set, or a guest name.
+ */
+ public function valid_author(Validation $v, $field) {
+ if (empty($this->author_id)) {
+ $v->add_error("author_id", "required");
+ } else if ($this->author_id == identity::guest()->id && empty($this->guest_name)) {
+ $v->add_error("guest_name", "required");
+ }
+ }
+
+ /**
+ * Make sure we have a valid associated item id.
+ */
+ public function valid_item(Validation $v, $field) {
+ if (db::build()
+ ->from("items")
+ ->where("id", "=", $this->item_id)
+ ->count_records() != 1) {
+ $v->add_error("item_id", "invalid");
+ }
+ }
+
+ /**
+ * Make sure that the state is legal.
+ */
+ static function valid_state($value) {
+ return in_array($value, array("published", "unpublished", "spam", "deleted"));
+ }
}
diff --git a/modules/comment/tests/Comment_Event_Test.php b/modules/comment/tests/Comment_Event_Test.php
index ff7f1c26..5b7daef4 100644
--- a/modules/comment/tests/Comment_Event_Test.php
+++ b/modules/comment/tests/Comment_Event_Test.php
@@ -19,14 +19,17 @@
*/
class Comment_Event_Test extends Unit_Test_Case {
public function deleting_an_item_deletes_its_comments_too_test() {
- $rand = rand();
- $album = album::create(ORM::factory("item", 1), "test_$rand", "test_$rand");
- $comment = comment::create(
- $album, identity::guest(), "text_$rand", "name_$rand", "email_$rand", "url_$rand");
+ $album = test::random_album();
+
+ $comment = ORM::factory("comment");
+ $comment->item_id = $album->id;
+ $comment->author_id = identity::guest()->id;
+ $comment->guest_name = "test";
+ $comment->text = "text";
+ $comment->save();
$album->delete();
- $deleted_comment = ORM::factory("comment", $comment->id);
- $this->assert_false($deleted_comment->loaded());
+ $this->assert_false(ORM::factory("comment")->where("id", "=", $comment->id)->find()->loaded());
}
}
diff --git a/modules/comment/tests/Comment_Helper_Test.php b/modules/comment/tests/Comment_Helper_Test.php
index 8e726869..d780aba6 100644
--- a/modules/comment/tests/Comment_Helper_Test.php
+++ b/modules/comment/tests/Comment_Helper_Test.php
@@ -48,15 +48,19 @@ class Comment_Helper_Test extends Unit_Test_Case {
}
public function create_comment_for_guest_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- $comment = comment::create(
- $root, identity::guest(), "text_$rand", "name_$rand", "email_$rand", "url_$rand");
+ $comment = ORM::factory("comment");
+ $comment->item_id = item::root()->id;
+ $comment->text = "text";
+ $comment->author_id = identity::guest()->id;
+ $comment->guest_name = "name";
+ $comment->guest_email = "email@email.com";
+ $comment->guest_url = "http://url.com";
+ $comment->save();
- $this->assert_equal("name_$rand", $comment->author_name());
- $this->assert_equal("email_$rand", $comment->author_email());
- $this->assert_equal("url_$rand", $comment->author_url());
- $this->assert_equal("text_$rand", $comment->text);
+ $this->assert_equal("name", $comment->author_name());
+ $this->assert_equal("email@email.com", $comment->author_email());
+ $this->assert_equal("http://url.com", $comment->author_url());
+ $this->assert_equal("text", $comment->text);
$this->assert_equal(1, $comment->item_id);
$this->assert_equal("REMOTE_ADDR", $comment->server_remote_addr);
@@ -78,16 +82,18 @@ class Comment_Helper_Test extends Unit_Test_Case {
}
public function create_comment_for_user_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
$admin = identity::admin_user();
- $comment = comment::create(
- $root, $admin, "text_$rand", "name_$rand", "email_$rand", "url_$rand");
+
+ $comment = ORM::factory("comment");
+ $comment->item_id = item::root()->id;
+ $comment->text = "text";
+ $comment->author_id = $admin->id;
+ $comment->save();
$this->assert_equal($admin->full_name, $comment->author_name());
$this->assert_equal($admin->email, $comment->author_email());
$this->assert_equal($admin->url, $comment->author_url());
- $this->assert_equal("text_$rand", $comment->text);
+ $this->assert_equal("text", $comment->text);
$this->assert_equal(1, $comment->item_id);
$this->assert_equal("REMOTE_ADDR", $comment->server_remote_addr);
diff --git a/modules/comment/tests/Comment_Model_Test.php b/modules/comment/tests/Comment_Model_Test.php
index aa91d6f2..c98eb63c 100644
--- a/modules/comment/tests/Comment_Model_Test.php
+++ b/modules/comment/tests/Comment_Model_Test.php
@@ -20,21 +20,24 @@
class Comment_Model_Test extends Unit_Test_Case {
public function cant_view_comments_for_unviewable_items_test() {
- $root = ORM::factory("item", 1);
- $album = album::create($root, rand(), rand(), rand());
- $comment = comment::create($album, identity::guest(), "text", "name", "email", "url");
+ $album = test::random_album();
+
+ $comment = ORM::factory("comment");
+ $comment->item_id = $album->id;
+ $comment->author_id = identity::admin_user()->id;
+ $comment->text = "text";
+ $comment->save();
+
identity::set_active_user(identity::guest());
// We can see the comment when permissions are granted on the album
access::allow(identity::everybody(), "view", $album);
- $this->assert_equal(
- 1,
+ $this->assert_true(
ORM::factory("comment")->viewable()->where("comments.id", "=", $comment->id)->count_all());
// We can't see the comment when permissions are denied on the album
access::deny(identity::everybody(), "view", $album);
- $this->assert_equal(
- 0,
+ $this->assert_false(
ORM::factory("comment")->viewable()->where("comments.id", "=", $comment->id)->count_all());
}
}
diff --git a/modules/digibug/tests/Digibug_Controller_Test.php b/modules/digibug/tests/Digibug_Controller_Test.php
index 015a270a..38dcd8e9 100644
--- a/modules/digibug/tests/Digibug_Controller_Test.php
+++ b/modules/digibug/tests/Digibug_Controller_Test.php
@@ -18,41 +18,41 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class Digibug_Controller_Test extends Unit_Test_Case {
- private $_proxy;
- private $_item;
private $_server;
+ public function setup() {
+ $this->_server = $_SERVER;
+ }
+
public function teardown() {
$_SERVER = $this->_server;
}
- public function setup() {
- $this->_server = $_SERVER;
+ private function _get_proxy() {
+ $album = test::random_album();
+ $photo = test::random_photo($album);
- $root = ORM::factory("item", 1);
- $this->_album = album::create($root, rand(), "test album");
- access::deny(identity::everybody(), "view_full", $this->_album);
- access::deny(identity::registered_users(), "view_full", $this->_album);
+ access::deny(identity::everybody(), "view_full", $album);
+ access::deny(identity::registered_users(), "view_full", $album);
- $rand = rand();
- $this->_item = photo::create($this->_album, MODPATH . "gallery/tests/test.jpg", "$rand.jpg",
- $rand, $rand);
- $this->_proxy = ORM::factory("digibug_proxy");
- $this->_proxy->uuid = md5(rand());
- $this->_proxy->item_id = $this->_item->id;
- $this->_proxy->save();
+ $proxy = ORM::factory("digibug_proxy");
+ $proxy->uuid = md5(rand());
+ $proxy->item_id = $photo->id;
+ return $proxy->save();
}
public function digibug_request_thumb_test() {
+ $proxy = $this->_get_proxy();
+
$controller = new Digibug_Controller();
- $controller->print_proxy("thumb", $this->_proxy->uuid);
+ $controller->print_proxy("thumb", $proxy->uuid);
}
public function digibug_request_full_malicious_ip_test() {
$_SERVER["REMOTE_ADDR"] = "123.123.123.123";
try {
$controller = new Digibug_Controller();
- $controller->print_proxy("full", $this->_proxy->uuid);
+ $controller->print_proxy("full", $this->_get_proxy()->uuid);
$this->assert_true(false, "Should have failed with an 404 exception");
} catch (Kohana_404_Exception $e) {
// expected behavior
@@ -69,6 +69,6 @@ class Digibug_Controller_Test extends Unit_Test_Case {
$_SERVER["REMOTE_ADDR"] = long2ip(rand($low, $high));
$controller = new Digibug_Controller();
- $controller->print_proxy("full", $this->_proxy->uuid);
+ $controller->print_proxy("full", $this->_get_proxy()->uuid);
}
}
diff --git a/modules/exif/tests/Exif_Test.php b/modules/exif/tests/Exif_Test.php
index 5c5a5cb1..191bdb99 100644
--- a/modules/exif/tests/Exif_Test.php
+++ b/modules/exif/tests/Exif_Test.php
@@ -19,10 +19,9 @@
*/
class Exif_Test extends Unit_Test_Case {
public function exif_extract_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- $photo = photo::create(
- $root, MODPATH . "exif/tests/data/image.jpg", "$rand.jpg", $rand, $rand);
+ $photo = test::random_photo_unsaved()
+ ->set_data_file(MODPATH . "exif/tests/data/image.jpg")
+ ->save();
$expected = array(
array("caption" => "Camera Maker", "value" => "Pentax Corporation"),
diff --git a/modules/gallery/controllers/albums.php b/modules/gallery/controllers/albums.php
index 2eeefdf1..7658a913 100644
--- a/modules/gallery/controllers/albums.php
+++ b/modules/gallery/controllers/albums.php
@@ -95,30 +95,36 @@ class Albums_Controller extends Items_Controller {
access::required("view", $album);
access::required("add", $album);
- $input = Input::instance();
$form = album::get_add_form($album);
- if ($form->validate()) {
- $new_album = album::create(
- $album,
- $input->post("name"),
- $input->post("title", $input->post("name")),
- $input->post("description"),
- identity::active_user()->id,
- $input->post("slug"));
+ try {
+ $valid = $form->validate();
+ $album = ORM::factory("item");
+ $album->type = "album";
+ $album->parent_id = $parent_id;
+ $album->name = $form->add_album->inputs["name"]->value;
+ $album->title = $form->add_album->title->value ?
+ $form->add_album->title->value : $form->add_album->inputs["name"]->value;
+ $album->description = $form->add_album->description->value;
+ $album->slug = $form->add_album->slug->value;
+ $album->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ $form->add_album->inputs[$key]->add_error($error, 1);
+ }
+ $valid = false;
+ }
+ if ($valid) {
+ $album->save();
log::success("content", "Created an album",
- html::anchor("albums/$new_album->id", "view album"));
+ html::anchor("albums/$album->id", "view album"));
message::success(t("Created album %album_title",
- array("album_title" => html::purify($new_album->title))));
+ array("album_title" => html::purify($album->title))));
- print json_encode(
- array("result" => "success",
- "location" => $new_album->url()));
+ print json_encode(array("result" => "success", "location" => $album->url()));
} else {
- print json_encode(
- array(
- "result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
@@ -129,42 +135,27 @@ class Albums_Controller extends Items_Controller {
access::required("edit", $album);
$form = album::get_edit_form($album);
- if ($valid = $form->validate()) {
- if ($album->id != 1 &&
- $form->edit_item->dirname->value != $album->name ||
- $form->edit_item->slug->value != $album->slug) {
- // Make sure that there's not a conflict
- if ($row = db::build()
- ->select(array("name", "slug"))
- ->from("items")
- ->where("parent_id", "=", $album->parent_id)
- ->where("id", "<>", $album->id)
- ->and_open()
- ->where("name", "=", $form->edit_item->dirname->value)
- ->or_where("slug", "=", $form->edit_item->slug->value)
- ->close()
- ->execute()
- ->current()) {
- if ($row->name == $form->edit_item->dirname->value) {
- $form->edit_item->dirname->add_error("name_conflict", 1);
- }
- if ($row->slug == $form->edit_item->slug->value) {
- $form->edit_item->slug->add_error("slug_conflict", 1);
- }
- $valid = false;
- }
- }
- }
-
- if ($valid) {
+ try {
+ $valid = $form->validate();
$album->title = $form->edit_item->title->value;
$album->description = $form->edit_item->description->value;
$album->sort_column = $form->edit_item->sort_order->column->value;
$album->sort_order = $form->edit_item->sort_order->direction->value;
- if ($album->id != 1) {
- $album->rename($form->edit_item->dirname->value);
- }
+ $album->name = $form->edit_item->dirname->value;
$album->slug = $form->edit_item->slug->value;
+ $album->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ if ($key == "name") {
+ $key = "dirname";
+ }
+ $form->edit_item->inputs[$key]->add_error($error, 1);
+ }
+ $valid = false;
+ }
+
+ if ($valid) {
$album->save();
module::event("item_edit_form_completed", $album, $form);
@@ -180,9 +171,7 @@ class Albums_Controller extends Items_Controller {
print json_encode(array("result" => "success"));
}
} else {
- print json_encode(
- array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
diff --git a/modules/gallery/controllers/login.php b/modules/gallery/controllers/login.php
index 75ee6b9c..464db491 100644
--- a/modules/gallery/controllers/login.php
+++ b/modules/gallery/controllers/login.php
@@ -33,9 +33,7 @@ class Login_Controller extends Controller {
print json_encode(
array("result" => "success"));
} else {
- print json_encode(
- array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
diff --git a/modules/gallery/controllers/movies.php b/modules/gallery/controllers/movies.php
index 7a8e4d2a..0908e281 100644
--- a/modules/gallery/controllers/movies.php
+++ b/modules/gallery/controllers/movies.php
@@ -61,48 +61,25 @@ class Movies_Controller extends Items_Controller {
access::required("edit", $movie);
$form = movie::get_edit_form($movie);
- $valid = $form->validate();
-
- if ($valid) {
- $new_ext = pathinfo($form->edit_item->filename->value, PATHINFO_EXTENSION);
- $old_ext = pathinfo($movie->name, PATHINFO_EXTENSION);
- if (strcasecmp($new_ext, $old_ext)) {
- $form->edit_item->filename->add_error("illegal_extension", 1);
- $valid = false;
- }
- }
-
- if ($valid) {
- if ($form->edit_item->filename->value != $movie->name ||
- $form->edit_item->slug->value != $movie->slug) {
- // Make sure that there's not a name or slug conflict
- if ($row = db::build()
- ->select(array("name", "slug"))
- ->from("items")
- ->where("parent_id", "=", $movie->parent_id)
- ->where("id", "<>", $movie->id)
- ->and_open()
- ->where("name", "=", $form->edit_item->filename->value)
- ->or_where("slug", "=", $form->edit_item->slug->value)
- ->close()
- ->execute()
- ->current()) {
- if ($row->name == $form->edit_item->filename->value) {
- $form->edit_item->filename->add_error("name_conflict", 1);
- }
- if ($row->slug == $form->edit_item->slug->value) {
- $form->edit_item->slug->add_error("slug_conflict", 1);
- }
- $valid = false;
+ try {
+ $valid = $form->validate();
+ $movie->title = $form->edit_item->title->value;
+ $movie->description = $form->edit_item->description->value;
+ $movie->slug = $form->edit_item->slug->value;
+ $movie->name = $form->edit_item->filename->value;
+ $movie->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ if ($key == "name") {
+ $key = "filename";
}
+ $form->edit_item->inputs[$key]->add_error($error, 1);
}
+ $valid = false;
}
if ($valid) {
- $movie->title = $form->edit_item->title->value;
- $movie->description = $form->edit_item->description->value;
- $movie->slug = $form->edit_item->slug->value;
- $movie->rename($form->edit_item->filename->value);
$movie->save();
module::event("item_edit_form_completed", $movie, $form);
@@ -118,9 +95,7 @@ class Movies_Controller extends Items_Controller {
print json_encode(array("result" => "success"));
}
} else {
- print json_encode(
- array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
diff --git a/modules/gallery/controllers/photos.php b/modules/gallery/controllers/photos.php
index 56b454ce..98f2126d 100644
--- a/modules/gallery/controllers/photos.php
+++ b/modules/gallery/controllers/photos.php
@@ -61,48 +61,25 @@ class Photos_Controller extends Items_Controller {
access::required("edit", $photo);
$form = photo::get_edit_form($photo);
- $valid = $form->validate();
-
- if ($valid) {
- $new_ext = pathinfo($form->edit_item->filename->value, PATHINFO_EXTENSION);
- $old_ext = pathinfo($photo->name, PATHINFO_EXTENSION);
- if (strcasecmp($new_ext, $old_ext)) {
- $form->edit_item->filename->add_error("illegal_extension", 1);
- $valid = false;
- }
- }
-
- if ($valid) {
- if ($form->edit_item->filename->value != $photo->name ||
- $form->edit_item->slug->value != $photo->slug) {
- // Make sure that there's not a name or slug conflict
- if ($row = db::build()
- ->select(array("name", "slug"))
- ->from("items")
- ->where("parent_id", "=", $photo->parent_id)
- ->where("id", "<>", $photo->id)
- ->and_open()
- ->where("name", "=", $form->edit_item->filename->value)
- ->or_where("slug", "=", $form->edit_item->slug->value)
- ->close()
- ->execute()
- ->current()) {
- if ($row->name == $form->edit_item->filename->value) {
- $form->edit_item->filename->add_error("name_conflict", 1);
- }
- if ($row->slug == $form->edit_item->slug->value) {
- $form->edit_item->slug->add_error("slug_conflict", 1);
- }
- $valid = false;
+ try {
+ $valid = $form->validate();
+ $photo->title = $form->edit_item->title->value;
+ $photo->description = $form->edit_item->description->value;
+ $photo->slug = $form->edit_item->slug->value;
+ $photo->name = $form->edit_item->filename->value;
+ $photo->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ if ($key == "name") {
+ $key = "filename";
}
+ $form->edit_item->inputs[$key]->add_error($error, 1);
}
+ $valid = false;
}
if ($valid) {
- $photo->title = $form->edit_item->title->value;
- $photo->description = $form->edit_item->description->value;
- $photo->slug = $form->edit_item->slug->value;
- $photo->rename($form->edit_item->filename->value);
$photo->save();
module::event("item_edit_form_completed", $photo, $form);
@@ -118,9 +95,7 @@ class Photos_Controller extends Items_Controller {
print json_encode(array("result" => "success"));
}
} else {
- print json_encode(
- array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
diff --git a/modules/gallery/controllers/simple_uploader.php b/modules/gallery/controllers/simple_uploader.php
index 5d32e35f..16d1d241 100644
--- a/modules/gallery/controllers/simple_uploader.php
+++ b/modules/gallery/controllers/simple_uploader.php
@@ -40,39 +40,52 @@ class Simple_Uploader_Controller extends Controller {
access::required("add", $album);
access::verify_csrf();
+ // The Flash uploader not call /start directly, so simulate it here for now.
+ if (!batch::in_progress()) {
+ batch::start();
+ }
+
+ $form = $this->_get_add_form($album);
+
+ // Uploadify adds its own field to the form, so validate that separately.
$file_validation = new Validation($_FILES);
$file_validation->add_rules(
"Filedata", "upload::valid", "upload::required", "upload::type[gif,jpg,jpeg,png,flv,mp4]");
- if ($file_validation->validate()) {
- // SimpleUploader.swf does not yet call /start directly, so simulate it here for now.
- if (!batch::in_progress()) {
- batch::start();
- }
+ if ($form->validate() && $file_validation->validate()) {
$temp_filename = upload::save("Filedata");
try {
- $name = substr(basename($temp_filename), 10); // Skip unique identifier Kohana adds
- $title = item::convert_filename_to_title($name);
+ $item = ORM::factory("item");
+ $item->name = substr(basename($temp_filename), 10); // Skip unique identifier Kohana adds
+ $item->title = item::convert_filename_to_title($item->name);
+ $item->parent_id = $album->id;
+ $item->set_data_file($temp_filename);
+
$path_info = @pathinfo($temp_filename);
if (array_key_exists("extension", $path_info) &&
in_array(strtolower($path_info["extension"]), array("flv", "mp4"))) {
- $item = movie::create($album, $temp_filename, $name, $title);
+ $item->type = "movie";
+ $item->save();
log::success("content", t("Added a movie"),
html::anchor("movies/$item->id", t("view movie")));
} else {
- $item = photo::create($album, $temp_filename, $name, $title);
+ $item->type = "photo";
+ $item->save();
log::success("content", t("Added a photo"),
html::anchor("photos/$item->id", t("view photo")));
}
- // We currently have no way of showing errors if validation fails, so only call our event
- // handlers if validation passes.
- $form = $this->_get_add_form($album);
- if ($form->validate()) {
- module::event("add_photos_form_completed", $item, $form);
- }
+ module::event("add_photos_form_completed", $item, $form);
} catch (Exception $e) {
- Kohana_Log::add("alert", $e->__toString());
+ // The Flash uploader has no good way of reporting complex errors, so just keep it simple.
+ Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+
+ // Ugh. I hate to use instanceof, But this beats catching the exception separately since
+ // we mostly want to treat it the same way as all other exceptions
+ if ($e instanceof ORM_Validation_Exception) {
+ Kohana_Log::add("error", "Validation errors: " . print_r($e->validation->errors(), 1));
+ }
+
if (file_exists($temp_filename)) {
unlink($temp_filename);
}
@@ -84,7 +97,7 @@ class Simple_Uploader_Controller extends Controller {
print "FILEID: $item->id";
} else {
header("HTTP/1.1 400 Bad Request");
- print "ERROR: " . t("Invalid Upload");
+ print "ERROR: " . t("Invalid upload");
}
}
diff --git a/modules/gallery/helpers/album.php b/modules/gallery/helpers/album.php
index feaf74cc..e99770e9 100644
--- a/modules/gallery/helpers/album.php
+++ b/modules/gallery/helpers/album.php
@@ -24,72 +24,6 @@
* Note: by design, this class does not do any permission checking.
*/
class album_Core {
- /**
- * Create a new album.
- * @param integer $parent_id id of parent album
- * @param string $name the name of this new album (it will become the directory name on disk)
- * @param integer $title the title of the new album
- * @param string $description (optional) the longer description of this album
- * @param string $slug (optional) the url component for this photo
- * @return Item_Model
- */
- static function create($parent, $name, $title, $description=null, $owner_id=null, $slug=null) {
- if (!$parent->loaded() || !$parent->is_album()) {
- throw new Exception("@todo INVALID_PARENT");
- }
-
- if (strpos($name, "/")) {
- throw new Exception("@todo NAME_CANNOT_CONTAIN_SLASH");
- }
-
- // We don't allow trailing periods as a security measure
- // ref: http://dev.kohanaphp.com/issues/684
- if (rtrim($name, ".") != $name) {
- throw new Exception("@todo NAME_CANNOT_END_IN_PERIOD");
- }
-
- if (empty($slug)) {
- $slug = item::convert_filename_to_slug($name);
- }
-
- $album = ORM::factory("item");
- $album->type = "album";
- $album->title = $title;
- $album->description = $description;
- $album->name = $name;
- $album->owner_id = $owner_id;
- $album->thumb_dirty = 1;
- $album->resize_dirty = 1;
- $album->slug = $slug;
- $album->rand_key = ((float)mt_rand()) / (float)mt_getrandmax();
- $album->sort_column = "created";
- $album->sort_order = "ASC";
-
- // Randomize the name or slug if there's a conflict
- // @todo Improve this. Random numbers are not user friendly
- while (ORM::factory("item")
- ->where("parent_id", "=", $parent->id)
- ->and_open()
- ->where("name", "=", $album->name)
- ->or_where("slug", "=", $album->slug)
- ->close()
- ->find()->id) {
- $rand = rand();
- $album->name = "{$name}-$rand";
- $album->slug = "{$slug}-$rand";
- }
-
- $album = $album->add_to_parent($parent);
- mkdir($album->file_path());
- mkdir(dirname($album->thumb_path()));
- mkdir(dirname($album->resize_path()));
-
- // @todo: publish this from inside Item_Model::save() when we refactor to the point where
- // there's only one save() happening here.
- module::event("item_created", $album);
-
- return $album;
- }
static function get_add_form($parent) {
$form = new Forge("albums/create/{$parent->id}", "", "post", array("id" => "g-add-album-form"));
@@ -98,16 +32,13 @@ class album_Core {
$group->input("title")->label(t("Title"));
$group->textarea("description")->label(t("Description"));
$group->input("name")->label(t("Directory name"))
- ->callback("item::validate_no_slashes")
->error_messages("no_slashes", t("The directory name can't contain the \"/\" character"));
$group->input("slug")->label(t("Internet Address"))
- ->callback("item::validate_url_safe")
->error_messages(
"not_url_safe",
t("The internet address should contain only letters, numbers, hyphens and underscores"));
$group->hidden("type")->value("album");
$group->submit("")->value(t("Create"));
- $form->add_rules_from(ORM::factory("item"));
$form->script("")
->url(url::abs_file("modules/gallery/js/albums_form_add.js"));
return $form;
@@ -124,15 +55,12 @@ class album_Core {
$group->input("dirname")->label(t("Directory Name"))->value($parent->name)
->rules("required")
->error_messages(
- "name_conflict", t("There is already a movie, photo or album with this name"))
- ->callback("item::validate_no_slashes")
+ "conflict", t("There is already a movie, photo or album with this name"))
->error_messages("no_slashes", t("The directory name can't contain a \"/\""))
- ->callback("item::validate_no_trailing_period")
->error_messages("no_trailing_period", t("The directory name can't end in \".\""));
$group->input("slug")->label(t("Internet Address"))->value($parent->slug)
->error_messages(
- "slug_conflict", t("There is already a movie, photo or album with this internet address"))
- ->callback("item::validate_url_safe")
+ "conflict", t("There is already a movie, photo or album with this internet address"))
->error_messages(
"not_url_safe",
t("The internet address should contain only letters, numbers, hyphens and underscores"));
@@ -159,7 +87,6 @@ class album_Core {
$group = $form->group("buttons")->label("");
$group->hidden("type")->value("album");
$group->submit("")->value(t("Modify"));
- $form->add_rules_from(ORM::factory("item"));
return $form;
}
diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php
index 679d65c2..db3b34fe 100644
--- a/modules/gallery/helpers/gallery_event.php
+++ b/modules/gallery/helpers/gallery_event.php
@@ -73,6 +73,24 @@ class gallery_event_Core {
static function item_created($item) {
access::add_item($item);
+
+ if ($item->is_photo() || $item->is_movie()) {
+ // Build our thumbnail/resizes.
+ try {
+ graphics::generate($item);
+ } catch (Exception $e) {
+ log::error("graphics", t("Couldn't create a thumbnail or resize for %item_title",
+ array("item_title" => $item->title)),
+ html::anchor($item->abs_url(), t("details")));
+ Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString());
+ }
+
+ // If the parent has no cover item, make this it.
+ $parent = $item->parent();
+ if (access::can("edit", $parent) && $parent->album_cover_item_id == null) {
+ item::make_album_cover($item);
+ }
+ }
}
static function item_deleted($item) {
diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php
index 1e0ad28c..aa297236 100644
--- a/modules/gallery/helpers/gallery_installer.php
+++ b/modules/gallery/helpers/gallery_installer.php
@@ -209,19 +209,26 @@ class gallery_installer {
t("Edit");
t("Add");
- $root = ORM::factory("item");
- $root->type = "album";
- $root->title = "Gallery";
- $root->description = "";
- $root->left_ptr = 1;
- $root->right_ptr = 2;
- $root->parent_id = 0;
- $root->level = 1;
- $root->thumb_dirty = 1;
- $root->resize_dirty = 1;
- $root->sort_column = "weight";
- $root->sort_order = "ASC";
- $root->save();
+ // Hardcode the first item to sidestep ORM validation rules
+ $now = time();
+ db::build()->insert(
+ "items",
+ array("created" => $now,
+ "description" => "",
+ "left_ptr" => 1,
+ "level" => 1,
+ "parent_id" => 0,
+ "resize_dirty" => 1,
+ "right_ptr" => 2,
+ "sort_column" => "weight",
+ "sort_order" => "ASC",
+ "thumb_dirty" => 1,
+ "title" => "Gallery",
+ "type" => "album",
+ "updated" => $now,
+ "weight" => 1))
+ ->execute();
+ $root = ORM::factory("item")->where("id", "=", 1)->find();
access::add_item($root);
module::set_var("gallery", "active_site_theme", "wind");
diff --git a/modules/gallery/helpers/gallery_rest.php b/modules/gallery/helpers/gallery_rest.php
index a87ebb4e..24733f20 100644
--- a/modules/gallery/helpers/gallery_rest.php
+++ b/modules/gallery/helpers/gallery_rest.php
@@ -17,232 +17,147 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class gallery_rest_Core {
- static function get($request) {
- $path = implode("/", $request->arguments);
-
- $item = gallery_rest::_get_item($path);
-
- $parent = $item->parent();
- $response_data = array("type" => $item->type,
- "name" => $item->name,
- "path" => $item->relative_url(),
- "parent_path" => empty($parent) ? null : $parent->relative_url(),
- "title" => $item->title,
- "thumb_url" => $item->thumb_url(true),
- "thumb_size" => array("height" => $item->thumb_height,
- "width" => $item->thumb_width),
- "resize_url" => $item->resize_url(true),
- "resize_size" => array("height" => (int)$item->resize_height,
- "width" => (int)$item->resize_width),
- "url" => $item->file_url(true),
- "size" => array("height" => $item->height,
- "width" => $item->width),
- "description" => $item->description,
- "slug" => $item->slug);
-
- $children = self::_get_children($item, $request);
- if (!empty($children) || $item->is_album()) {
- $response_data["children"] = $children;
- }
- return rest::success(array("resource" => $response_data));
- }
- static function put($request) {
- if (empty($request->arguments)) {
- throw new Rest_Exception(400, "Bad request");
- }
- $path = implode("/", $request->arguments);
- $item = gallery_rest::_get_item($path, "edit");
-
- // Validate the request data
- $new_values = gallery_rest::_validate($request, $item->parent_id, $item->id);
- $errors = $new_values->errors();
- if (empty($errors)) {
- $item->title = $new_values->title;
- $item->description = $new_values->description;
- if ($item->id != 1) {
- $item->rename($new_values->name);
- }
- $item->slug = $new_values->slug;
- $item->save();
+// @todo Add logging
+
+// Validation questions
+//
+// We need to be able to properly validate anything we want to enter here. But all of our
+// validation currently happens at the controller / form level, and we're not using the same
+// controllers or forms.
+//
+// Possible solutions:
+// 1) Move validation into the model and use it both here and in the regular controllers. But
+// if we do that, how do we translate validation failures into a user-consumable output which
+// we need so that we can return proper error responses to form submissions?
+//
+// 2) Create some kind of validation helper that can validate every field. Wait, isn't this
+// just like #1 except in a helper instead of in the model?
- log::success("content", "Updated $item->type",
- "<a href=\"{$item->type}s/$item->id\">view</a>");
+class gallery_rest_Core {
- return rest::success();
- } else {
- return rest::validation_error($errors);
- }
- }
+ /**
+ * For items that are collections, you can specify the following additional query parameters to
+ * query the collection. You can specify them in any combination.
+ *
+ * scope=direct
+ * only return items that are immediately under this one
+ * scope=all
+ * return items anywhere under this one
+ *
+ * name=<substring>
+ * only return items where the name contains this substring
+ *
+ * random=true
+ * return a single random item
+ *
+ * type=<comma separate list of photo, movie or album>
+ * limit the type to types in this list. eg, "type=photo,movie"
+ */
+ static function get($request) {
+ $item = rest::resolve($request->url);
+ access::required("view", $item);
- static function post($request) {
- if (empty($request->arguments)) {
- throw new Rest_Exception(400, "Bad request");
+ $p = $request->params;
+ if (isset($p->random)) {
+ $orm = item::random_query()->offset(0)->limit(1);
+ } else {
+ $orm = ORM::factory("item")->viewable();
}
- $components = $request->arguments;
- $name = urldecode(array_pop($components));
-
- $parent = gallery_rest::_get_item(implode("/", $components), "edit");
-
- // Validate the request data
- $request->name = $name;
- $new_values = gallery_rest::_validate($request, $parent->id);
- $errors = $new_values->errors();
- if (!empty($errors)) {
- return rest::validation_error($errors);
+ if (!empty($p->scope) && !in_array($p->scope, array("direct", "all"))) {
+ throw new Exception("Bad Request", 400);
}
-
- if (empty($new_values["image"])) {
- $new_item = album::create(
- $parent,
- $name,
- empty($new_values["title"]) ? $name : $new_values["title"],
- empty($new_values["description"]) ? null : $new_values["description"],
- identity::active_user()->id,
- empty($new_values["slug"]) ? $name : $new_values["slug"]);
- $log_message = t("Added an album");
- } else {
- $temp_filename = upload::save("image");
- $path_info = @pathinfo($temp_filename);
- if (array_key_exists("extension", $path_info) &&
- in_array(strtolower($path_info["extension"]), array("flv", "mp4"))) {
- $new_item =
- movie::create($parent, $temp_filename, $new_values["name"], $new_values["title"]);
- $log_message = t("Added a movie");
+ if (!empty($p->scope)) {
+ if ($p->scope == "direct") {
+ $orm->where("parent_id", "=", $item->id);
} else {
- $new_item =
- photo::create($parent, $temp_filename, $new_values["name"], $new_values["title"]);
- $log_message = t("Added a photo");
+ $orm->where("left_ptr", ">=", $item->left_ptr);
+ $orm->where("right_ptr", "<=", $item->left_ptr);
+ $orm->where("id", "<>", $item->id);
}
}
- log::success("content", $log_message, "<a href=\"{$new_item->type}s/$new_item->id\">view</a>");
-
- return rest::success(array("path" => $new_item->relative_url()));
- }
-
- static function delete($request) {
- if (empty($request->arguments)) {
- throw new Rest_Exception(400, "Bad request");
+ if (isset($p->name)) {
+ $orm->where("name", "LIKE", "%{$p->name}%");
}
- $path = implode("/", $request->arguments);
-
- $item = gallery_rest::_get_item($path, "edit");
- if ($item->id == 1) {
- throw new Rest_Exception(400, "Bad request");
+ if (isset($p->type)) {
+ $orm->where("type", "IN", explode(",", $p->type));
}
- $parent = $item->parent();
- $item->delete();
-
- if ($item->is_album()) {
- $msg = t("Deleted album <b>%title</b>", array("title" => html::purify($item->title)));
- } else {
- $msg = t("Deleted photo <b>%title</b>", array("title" => html::purify($item->title)));
+ $members = array();
+ foreach ($orm->find_all() as $child) {
+ $members[] = url::abs_site("rest/gallery/" . $child->relative_url());
}
- log::success("content", $msg);
- return rest::success(array("resource" => array("parent_path" => $parent->relative_url())));
+ return rest::reply(array("resource" => $item->as_array(), "members" => $members));
}
- private static function _get_item($path, $permission="view") {
- $item = url::get_item_from_uri($path);
-
- if (!$item->loaded()) {
- throw new Kohana_404_Exception();
- }
-
- if (!access::can($permission, $item)) {
- throw new Kohana_404_Exception();
+ static function put($request) {
+ $item = rest::resolve($request->url);
+ access::required("edit", $item);
+
+ $params = $request->params;
+
+ // Only change fields from a whitelist.
+ foreach (array("album_cover_item_id", "captured", "description",
+ "height", "mime_type", "name", "parent_id", "rand_key", "resize_dirty",
+ "resize_height", "resize_width", "slug", "sort_column", "sort_order",
+ "thumb_dirty", "thumb_height", "thumb_width", "title", "view_count",
+ "weight", "width") as $key) {
+ if (array_key_exists($key, $request->params)) {
+ $item->$key = $request->params->$key;
+ }
}
+ $item->save();
- return $item;
+ return rest::reply(array("url" => url::abs_site("/rest/gallery/" . $item->relative_url())));
}
- private static function _get_children($item, $request) {
- $children = array();
- $limit = empty($request->limit) ? null : $request->limit;
- $offset = empty($request->offset) ? null : $request->offset;
- $where = empty($request->filter) ? array() : array("type" => $request->filter);
- foreach ($item->viewable()->children($limit, $offset, $where) as $child) {
- $children[] = array("type" => $child->type,
- "has_children" => $child->children_count() > 0,
- "path" => $child->relative_url(),
- "thumb_url" => $child->thumb_url(true),
- "thumb_dimensions" => array("width" => $child->thumb_width,
- "height" => $child->thumb_height),
- "has_thumb" => $child->has_thumb(),
- "title" => $child->title);
+ static function post($request) {
+ $parent = rest::resolve($request->url);
+ access::required("edit", $parent);
+
+ $params = $request->params;
+ $item = ORM::factory("item");
+ switch ($params->type) {
+ case "album":
+ $item->type = "album";
+ $item->parent_id = $parent->id;
+ $item->name = $params->name;
+ $item->title = isset($params->title) ? $params->title : $name;
+ $item->description = isset($params->description) ? $params->description : null;
+ $item->save();
+ break;
+
+ case "photo":
+ case "movie":
+ $item->type = $params->type;
+ $item->parent_id = $parent->id;
+ $item->set_data_file($request->file);
+ $item->name = $params->name;
+ $item->title = isset($params->title) ? $params->title : $name;
+ $item->description = isset($params->description) ? $params->description : null;
+ $item->save();
+ break;
+
+ default:
+ throw new Rest_Exception("Invalid type: $args->type", 400);
}
- return $children;
+ return rest::reply(array("url" => url::abs_site("/rest/gallery/" . $item->relative_url())));
}
- private static function _validate($request, $parent_id, $item_id=0) {
- $item = ORM::factory("item", $item_id);
-
- // Normalize the inputs so all fields have a value
- $new_values = Validation::factory(array());
- foreach ($item->form_rules as $field => $rule_set) {
- if (isset($request->$field)) {
- $new_values[$field] = $request->$field;
- } else if (isset($item->$field)) {
- $new_values[$field] = $item->$field;
- }
- foreach (explode("|", $rule_set) as $rule) {
- $new_values->add_rules($field, $rule);
- }
- }
- $name = $new_values["name"];
- $new_values["title"] = empty($new_values["title"]) ? $name : $new_values["title"];
- $new_values["description"] =
- empty($new_values["description"]) ? null : $new_values["description"];
- $new_values["slug"] = empty($new_values["slug"]) ? $name : $new_values["slug"];
-
- if (!empty($request->image)) {
- $new_values["image"] = $request->image;
- $new_values->add_rules(
- "image", "upload::valid", "upload::required", "upload::type[gif,jpg,jpeg,png,flv,mp4]");
- }
-
- if ($new_values->validate() && $item_id != 1) {
- $errors = gallery_rest::_check_for_conflicts($parent_id, $item_id,
- $new_values["name"], $new_values["slug"]);
- if (!empty($errors)) {
- !empty($errors["name_conflict"]) OR $new_values->add_error("name", "Duplicate name");
- !empty($errors["slug_conflict"]) OR
- $new_values->add_error("slug", "Duplicate Internet address");
- }
- }
+ static function delete($request) {
+ $item = rest::resolve($request->url);
+ access::required("edit", $item);
- return $new_values;
+ $item->delete();
+ return rest::reply();
}
- private static function _check_for_conflicts($parent_id, $item_id, $new_name, $new_slug) {
- $errors = array();
-
- if ($row = db::build()
- ->select(array("name", "slug"))
- ->from("items")
- ->where("parent_id", "=", $parent_id)
- ->where("id", "<>", $item_id)
- ->and_open()
- ->where("name", "=", $new_name)
- ->or_where("slug", "=", $new_slug)
- ->close()
- ->execute()
- ->current()) {
- if ($row->name == $new_name) {
- $errors["name_conflict"] = 1;
- }
- if ($row->slug == $new_slug) {
- $errors["slug_conflict"] = 1;
- }
- }
-
- return $errors;
+ static function resolve($path) {
+ return url::get_item_from_uri($path);
}
}
diff --git a/modules/gallery/helpers/identity.php b/modules/gallery/helpers/identity.php
index eae0ea3e..ef93d72f 100644
--- a/modules/gallery/helpers/identity.php
+++ b/modules/gallery/helpers/identity.php
@@ -155,8 +155,8 @@ class identity_Core {
/**
* @see IdentityProvider_Driver::create_user.
*/
- static function create_user($name, $full_name, $password) {
- return IdentityProvider::instance()->create_user($name, $full_name, $password);
+ static function create_user($name, $full_name, $password, $email) {
+ return IdentityProvider::instance()->create_user($name, $full_name, $password, $email);
}
/**
diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php
index f6181f8a..53291ccc 100644
--- a/modules/gallery/helpers/item.php
+++ b/modules/gallery/helpers/item.php
@@ -78,24 +78,6 @@ class item_Core {
graphics::generate($album);
}
- static function validate_no_slashes($input) {
- if (strpos($input->value, "/") !== false) {
- $input->add_error("no_slashes", 1);
- }
- }
-
- static function validate_no_trailing_period($input) {
- if (rtrim($input->value, ".") !== $input->value) {
- $input->add_error("no_trailing_period", 1);
- }
- }
-
- static function validate_url_safe($input) {
- if (preg_match("/[^A-Za-z0-9-_]/", $input->value)) {
- $input->add_error("not_url_safe", 1);
- }
- }
-
/**
* Sanitize a filename into something presentable as an item title
* @param string $filename
@@ -173,4 +155,20 @@ class item_Core {
static function root() {
return model_cache::get("item", 1);
}
+
+ /**
+ * Return a query to get a random Item_Model, with optional filters
+ *
+ * @param array (optional) where tuple
+ */
+ static function random_query($where=null) {
+ // Pick a random number and find the item that's got nearest smaller number.
+ // This approach works best when the random numbers in the system are roughly evenly
+ // distributed so this is going to be more efficient with larger data sets.
+ return ORM::factory("item")
+ ->viewable()
+ ->where("rand_key", "<", ((float)mt_rand()) / (float)mt_getrandmax())
+ ->merge_where($where)
+ ->order_by("rand_key", "DESC");
+ }
} \ No newline at end of file
diff --git a/modules/gallery/helpers/movie.php b/modules/gallery/helpers/movie.php
index 01859924..b2e846d3 100644
--- a/modules/gallery/helpers/movie.php
+++ b/modules/gallery/helpers/movie.php
@@ -24,110 +24,6 @@
* Note: by design, this class does not do any permission checking.
*/
class movie_Core {
- /**
- * Create a new movie.
- * @param integer $parent_id id of parent album
- * @param string $filename path to the photo file on disk
- * @param string $name the filename to use for this photo in the album
- * @param integer $title the title of the new photo
- * @param string $description (optional) the longer description of this photo
- * @param string $slug (optional) the url component for this photo
- * @return Item_Model
- */
- static function create($parent, $filename, $name, $title,
- $description=null, $owner_id=null, $slug=null) {
- if (!$parent->loaded() || !$parent->is_album()) {
- throw new Exception("@todo INVALID_PARENT");
- }
-
- if (!is_file($filename)) {
- throw new Exception("@todo MISSING_MOVIE_FILE");
- }
-
- if (strpos($name, "/")) {
- throw new Exception("@todo NAME_CANNOT_CONTAIN_SLASH");
- }
-
- // We don't allow trailing periods as a security measure
- // ref: http://dev.kohanaphp.com/issues/684
- if (rtrim($name, ".") != $name) {
- throw new Exception("@todo NAME_CANNOT_END_IN_PERIOD");
- }
-
- try {
- $movie_info = movie::getmoviesize($filename);
- } catch (Exception $e) {
- // Assuming this is MISSING_FFMPEG for now
- $movie_info = getimagesize(MODPATH . "gallery/images/missing_movie.png");
- }
-
- // Force an extension onto the name
- $pi = pathinfo($filename);
- if (empty($pi["extension"])) {
- $pi["extension"] = image_type_to_extension($movie_info[2], false);
- $name .= "." . $pi["extension"];
- }
-
- if (empty($slug)) {
- $slug = item::convert_filename_to_slug($name);
- }
-
- $movie = ORM::factory("item");
- $movie->type = "movie";
- $movie->title = $title;
- $movie->description = $description;
- $movie->name = $name;
- $movie->owner_id = $owner_id ? $owner_id : identity::active_user()->id;
- $movie->width = $movie_info[0];
- $movie->height = $movie_info[1];
- $movie->mime_type = strtolower($pi["extension"]) == "mp4" ? "video/mp4" : "video/x-flv";
- $movie->thumb_dirty = 1;
- $movie->resize_dirty = 1;
- $movie->sort_column = "weight";
- $movie->slug = $slug;
- $movie->rand_key = ((float)mt_rand()) / (float)mt_getrandmax();
-
- // Randomize the name if there's a conflict
- // @todo Improve this. Random numbers are not user friendly
- while (ORM::factory("item")
- ->where("parent_id", "=", $parent->id)
- ->and_open()
- ->where("name", "=", $movie->name)
- ->or_where("slug", "=", $movie->slug)
- ->close()
- ->find()->id) {
- $rand = rand();
- $movie->name = "{$name}.$rand.{$pi['extension']}";
- $movie->slug = "{$slug}-$rand";
- }
-
- // This saves the photo
- $movie->add_to_parent($parent);
-
- // If the thumb or resize already exists then rename it
- if (file_exists($movie->resize_path()) ||
- file_exists($movie->thumb_path())) {
- $movie->name = $pi["filename"] . "-" . rand() . "." . $pi["extension"];
- $movie->save();
- }
-
- copy($filename, $movie->file_path());
-
- // @todo: publish this from inside Item_Model::save() when we refactor to the point where
- // there's only one save() happening here.
- module::event("item_created", $movie);
-
- // Build our thumbnail
- graphics::generate($movie);
-
- // If the parent has no cover item, make this it.
- if (access::can("edit", $parent) && $parent->album_cover_item_id == null) {
- item::make_album_cover($movie);
- }
-
- return $movie;
- }
-
static function get_edit_form($movie) {
$form = new Forge("movies/update/$movie->id", "", "post", array("id" => "g-edit-movie-form"));
$form->hidden("from_id");
@@ -135,18 +31,14 @@ class movie_Core {
$group->input("title")->label(t("Title"))->value($movie->title);
$group->textarea("description")->label(t("Description"))->value($movie->description);
$group->input("filename")->label(t("Filename"))->value($movie->name)
- ->rules("required")
->error_messages(
- "name_conflict", t("There is already a movie, photo or album with this name"))
- ->callback("item::validate_no_slashes")
+ "conflict", t("There is already a movie, photo or album with this name"))
->error_messages("no_slashes", t("The movie name can't contain a \"/\""))
- ->callback("item::validate_no_trailing_period")
->error_messages("no_trailing_period", t("The movie name can't end in \".\""))
->error_messages("illegal_extension", t("You cannot change the filename extension"));
$group->input("slug")->label(t("Internet Address"))->value($movie->slug)
- ->callback("item::validate_url_safe")
->error_messages(
- "slug_conflict", t("There is already a movie, photo or album with this internet address"))
+ "conflict", t("There is already a movie, photo or album with this internet address"))
->error_messages(
"not_url_safe",
t("The internet address should contain only letters, numbers, hyphens and underscores"));
@@ -155,7 +47,7 @@ class movie_Core {
$group = $form->group("buttons")->label("");
$group->submit("")->value(t("Modify"));
- $form->add_rules_from(ORM::factory("item"));
+
return $form;
}
diff --git a/modules/gallery/helpers/photo.php b/modules/gallery/helpers/photo.php
index 4e20e610..cb94772e 100644
--- a/modules/gallery/helpers/photo.php
+++ b/modules/gallery/helpers/photo.php
@@ -24,119 +24,6 @@
* Note: by design, this class does not do any permission checking.
*/
class photo_Core {
- /**
- * Create a new photo.
- * @param integer $parent parent album
- * @param string $filename path to the photo file on disk
- * @param string $name the filename to use for this photo in the album
- * @param integer $title the title of the new photo
- * @param string $description (optional) the longer description of this photo
- * @param string $slug (optional) the url component for this photo
- * @return Item_Model
- */
- static function create($parent, $filename, $name, $title,
- $description=null, $owner_id=null, $slug=null) {
- if (!$parent->loaded() || !$parent->is_album()) {
- throw new Exception("@todo INVALID_PARENT");
- }
-
- if (!is_file($filename)) {
- throw new Exception("@todo MISSING_IMAGE_FILE");
- }
-
- if (strpos($name, "/")) {
- throw new Exception("@todo NAME_CANNOT_CONTAIN_SLASH");
- }
-
- // We don't allow trailing periods as a security measure
- // ref: http://dev.kohanaphp.com/issues/684
- if (rtrim($name, ".") != $name) {
- throw new Exception("@todo NAME_CANNOT_END_IN_PERIOD");
- }
-
- if (filesize($filename) == 0) {
- throw new Exception("@todo EMPTY_INPUT_FILE");
- }
-
- $image_info = getimagesize($filename);
-
- // Force an extension onto the name
- $pi = pathinfo($filename);
- if (empty($pi["extension"])) {
- $pi["extension"] = image_type_to_extension($image_info[2], false);
- $name .= "." . $pi["extension"];
- }
-
- if (empty($slug)) {
- $slug = item::convert_filename_to_slug($name);
- }
-
- $photo = ORM::factory("item");
- $photo->type = "photo";
- $photo->title = $title;
- $photo->description = $description;
- $photo->name = $name;
- $photo->owner_id = $owner_id ? $owner_id : identity::active_user()->id;
- $photo->width = $image_info[0];
- $photo->height = $image_info[1];
- $photo->mime_type = empty($image_info['mime']) ? "application/unknown" : $image_info['mime'];
- $photo->thumb_dirty = 1;
- $photo->resize_dirty = 1;
- $photo->sort_column = "weight";
- $photo->slug = $slug;
- $photo->rand_key = ((float)mt_rand()) / (float)mt_getrandmax();
-
- // Randomize the name or slug if there's a conflict
- // @todo Improve this. Random numbers are not user friendly
- while (ORM::factory("item")
- ->where("parent_id", "=", $parent->id)
- ->and_open()
- ->where("name", "=", $photo->name)
- ->or_where("slug", "=", $photo->slug)
- ->close()
- ->find()->id) {
- $rand = rand();
- $photo->name = "{$name}.$rand.{$pi['extension']}";
- $photo->slug = "{$slug}-$rand";
- }
-
- // This saves the photo
- $photo->add_to_parent($parent);
-
- /*
- * If the thumb or resize already exists then rename it. We need to do this after the save
- * because the resize_path and thumb_path both call relative_path which caches the
- * path. Before add_to_parent the relative path will be incorrect.
- */
- if (file_exists($photo->resize_path()) ||
- file_exists($photo->thumb_path())) {
- $photo->name = $pi["filename"] . "-" . rand() . "." . $pi["extension"];
- $photo->save();
- }
-
- copy($filename, $photo->file_path());
-
- // @todo: publish this from inside Item_Model::save() when we refactor to the point where
- // there's only one save() happening here.
- module::event("item_created", $photo);
-
- // Build our thumbnail/resizes. If we fail to build thumbnail/resize we assume that the image
- // is bad in some way and discard it.
- try {
- graphics::generate($photo);
- } catch (Exception $e) {
- $photo->delete();
- throw $e;
- }
-
- // If the parent has no cover item, make this it.
- if (access::can("edit", $parent) && $parent->album_cover_item_id == null) {
- item::make_album_cover($photo);
- }
-
- return $photo;
- }
-
static function get_edit_form($photo) {
$form = new Forge("photos/update/$photo->id", "", "post", array("id" => "g-edit-photo-form"));
$form->hidden("from_id");
@@ -144,18 +31,13 @@ class photo_Core {
$group->input("title")->label(t("Title"))->value($photo->title);
$group->textarea("description")->label(t("Description"))->value($photo->description);
$group->input("filename")->label(t("Filename"))->value($photo->name)
- ->rules("required")
- ->error_messages(
- "name_conflict", t("There is already a movie, photo or album with this name"))
- ->callback("item::validate_no_slashes")
+ ->error_messages("conflict", t("There is already a movie, photo or album with this name"))
->error_messages("no_slashes", t("The photo name can't contain a \"/\""))
- ->callback("item::validate_no_trailing_period")
->error_messages("no_trailing_period", t("The photo name can't end in \".\""))
->error_messages("illegal_extension", t("You cannot change the filename extension"));
$group->input("slug")->label(t("Internet Address"))->value($photo->slug)
- ->callback("item::validate_url_safe")
->error_messages(
- "slug_conflict", t("There is already a movie, photo or album with this internet address"))
+ "conflict", t("There is already a movie, photo or album with this internet address"))
->error_messages(
"not_url_safe",
t("The internet address should contain only letters, numbers, hyphens and underscores"));
@@ -164,7 +46,6 @@ class photo_Core {
$group = $form->group("buttons")->label("");
$group->submit("")->value(t("Modify"));
- $form->add_rules_from(ORM::factory("item"));
return $form;
}
diff --git a/modules/gallery/libraries/IdentityProvider.php b/modules/gallery/libraries/IdentityProvider.php
index bcb3056a..30d4efa4 100644
--- a/modules/gallery/libraries/IdentityProvider.php
+++ b/modules/gallery/libraries/IdentityProvider.php
@@ -119,8 +119,8 @@ class IdentityProvider_Core {
/**
* @see IdentityProvider_Driver::create_user.
*/
- public function create_user($name, $full_name, $password) {
- return $this->driver->create_user($name, $full_name, $password);
+ public function create_user($name, $full_name, $password, $email) {
+ return $this->driver->create_user($name, $full_name, $password, $email);
}
/**
diff --git a/modules/gallery/libraries/MY_Forge.php b/modules/gallery/libraries/MY_Forge.php
index 9564f941..ee2a0bef 100644
--- a/modules/gallery/libraries/MY_Forge.php
+++ b/modules/gallery/libraries/MY_Forge.php
@@ -35,20 +35,6 @@ class Forge extends Forge_Core {
}
/**
- * Associate validation rules defined in the model with this form.
- */
- public function add_rules_from($model) {
- foreach ($this->inputs as $name => $input) {
- if (isset($input->inputs)) {
- $input->add_rules_from($model);
- }
- if (isset($model->form_rules[$name])) {
- $input->rules($model->form_rules[$name]);
- }
- }
- }
-
- /**
* Validate our CSRF value as a mandatory part of all form validation.
*/
public function validate() {
diff --git a/modules/gallery/libraries/MY_ORM.php b/modules/gallery/libraries/MY_ORM.php
index 56c776aa..8c0f084f 100644
--- a/modules/gallery/libraries/MY_ORM.php
+++ b/modules/gallery/libraries/MY_ORM.php
@@ -49,6 +49,10 @@ class ORM extends ORM_Core {
}
public function original() {
+ if (!isset($this->original)) {
+ $this->original = clone $this;
+ }
+
return $this->original;
}
}
diff --git a/modules/gallery/libraries/ORM_MPTT.php b/modules/gallery/libraries/ORM_MPTT.php
index 0ea519c9..404d61ff 100644
--- a/modules/gallery/libraries/ORM_MPTT.php
+++ b/modules/gallery/libraries/ORM_MPTT.php
@@ -40,43 +40,45 @@ class ORM_MPTT_Core extends ORM {
}
/**
- * Add this node as a child of the parent provided.
+ * Overload ORM::save() to update the MPTT tree when we add new items to the hierarchy.
*
* @chainable
- * @param integer $parent_id the id of the parent node
- * @return ORM
+ * @return ORM
*/
- function add_to_parent($parent) {
- $this->lock();
- $parent->reload(); // Assume that the prior lock holder may have changed the parent
-
- try {
- // Make a hole in the parent for this new item
- $this->db_builder
- ->update($this->table_name)
- ->set("left_ptr", new Database_Expression("`left_ptr` + 2"))
- ->where("left_ptr", ">=", $parent->right_ptr)
- ->execute();
- $this->db_builder
- ->update($this->table_name)
- ->set("right_ptr", new Database_Expression("`right_ptr` + 2"))
- ->where("right_ptr", ">=", $parent->right_ptr)
- ->execute();
- $parent->right_ptr += 2;
+ function save() {
+ if (!$this->loaded()) {
+ $this->lock();
+ $parent = ORM::factory("item")->where("id", "=", $this->parent_id)->find();
- // Insert this item into the hole
- $this->left_ptr = $parent->right_ptr - 2;
- $this->right_ptr = $parent->right_ptr - 1;
- $this->parent_id = $parent->id;
- $this->level = $parent->level + 1;
- $this->save();
- $parent->reload();
- } catch (Exception $e) {
+ try {
+ // Make a hole in the parent for this new item
+ $this->db_builder
+ ->update($this->table_name)
+ ->set("left_ptr", new Database_Expression("`left_ptr` + 2"))
+ ->where("left_ptr", ">=", $parent->right_ptr)
+ ->execute();
+ $this->db_builder
+ ->update($this->table_name)
+ ->set("right_ptr", new Database_Expression("`right_ptr` + 2"))
+ ->where("right_ptr", ">=", $parent->right_ptr)
+ ->execute();
+ $parent->right_ptr += 2;
+
+ // Insert this item into the hole
+ $this->left_ptr = $parent->right_ptr - 2;
+ $this->right_ptr = $parent->right_ptr - 1;
+ $this->parent_id = $parent->id;
+ $this->level = $parent->level + 1;
+ } catch (Exception $e) {
+ $this->unlock();
+ throw $e;
+ }
+ parent::save();
$this->unlock();
- throw $e;
+ } else {
+ parent::save();
}
- $this->unlock();
return $this;
}
@@ -165,11 +167,8 @@ class ORM_MPTT_Core extends ORM {
* @return array ORM
*/
function children($limit=null, $offset=null, $where=null, $order_by=array("id" => "ASC")) {
- if ($where) {
- $this->merge_where($where);
- }
-
return $this
+ ->merge_where($where)
->where("parent_id", "=", $this->id)
->order_by($order_by)
->find_all($limit, $offset);
@@ -183,11 +182,8 @@ class ORM_MPTT_Core extends ORM {
* @return array ORM
*/
function children_count($where=null) {
- if ($where) {
- $this->merge_where($where);
- }
-
return $this
+ ->merge_where($where)
->where("parent_id", "=", $this->id)
->count_all();
}
@@ -202,11 +198,8 @@ class ORM_MPTT_Core extends ORM {
* @return object ORM_Iterator
*/
function descendants($limit=null, $offset=null, $where=null, $order_by=array("id" => "ASC")) {
- if ($where) {
- $this->merge_where($where);
- }
-
return $this
+ ->merge_where($where)
->where("left_ptr", ">", $this->left_ptr)
->where("right_ptr", "<=", $this->right_ptr)
->order_by($order_by)
@@ -220,11 +213,8 @@ class ORM_MPTT_Core extends ORM {
* @return integer child count
*/
function descendants_count($where=null) {
- if ($where) {
- $this->merge_where($where);
- }
-
return $this
+ ->merge_where($where)
->where("left_ptr", ">", $this->left_ptr)
->where("right_ptr", "<=", $this->right_ptr)
->count_all();
diff --git a/modules/gallery/libraries/drivers/IdentityProvider.php b/modules/gallery/libraries/drivers/IdentityProvider.php
index a808c7e8..b7b1fbe8 100644
--- a/modules/gallery/libraries/drivers/IdentityProvider.php
+++ b/modules/gallery/libraries/drivers/IdentityProvider.php
@@ -38,9 +38,10 @@ interface IdentityProvider_Driver {
* @param string $name
* @param string $full_name
* @param string $password
+ * @param string $email
* @return User_Definition the user object
*/
- public function create_user($name, $full_name, $password);
+ public function create_user($name, $full_name, $password, $email);
/**
* Is the password provided correct?
diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php
index 6851e1a3..fcd9b8e6 100644
--- a/modules/gallery/models/item.php
+++ b/modules/gallery/models/item.php
@@ -18,15 +18,9 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class Item_Model extends ORM_MPTT {
- protected $children = 'items';
+ protected $children = "items";
protected $sorting = array();
-
- var $form_rules = array(
- "name" => "required|length[0,255]",
- "title" => "required|length[0,255]",
- "description" => "length[0,65535]",
- "slug" => "required|length[0,255]"
- );
+ protected $data_file = null;
/**
* Add a set of restrictions to any following queries to restrict access only to items
@@ -146,21 +140,12 @@ class Item_Model extends ORM_MPTT {
}
/**
- * Rename the underlying file for this item to a new name. Move all the files. This requires a
- * save.
+ * Rename the underlying file for this item to a new name and move all related files.
*
* @chainable
*/
- public function rename($new_name) {
- if ($new_name == $this->name) {
- return;
- }
-
- if (strpos($new_name, "/")) {
- throw new Exception("@todo NAME_CANNOT_CONTAIN_SLASH");
- }
-
- $old_relative_path = urldecode($this->relative_path());
+ private function rename($new_name) {
+ $old_relative_path = urldecode($this->original()->relative_path());
$new_relative_path = dirname($old_relative_path) . "/" . $new_name;
if (file_exists(VARPATH . "albums/$new_relative_path")) {
throw new Exception("@todo INVALID_RENAME_FILE_EXISTS: $new_relative_path");
@@ -178,18 +163,16 @@ class Item_Model extends ORM_MPTT {
@rename(VARPATH . "thumbs/$old_relative_path", VARPATH . "thumbs/$new_relative_path");
}
- $this->name = $new_name;
-
- if ($this->is_album()) {
- db::build()
- ->update("items")
- ->set("relative_url_cache", null)
- ->set("relative_path_cache", null)
- ->where("left_ptr", ">", $this->left_ptr)
- ->where("right_ptr", "<", $this->right_ptr)
- ->execute();
- }
+ return $this;
+ }
+ /**
+ * Specify the path to the data file associated with this item. To actually associate it,
+ * you still have to call save().
+ * @chainable
+ */
+ public function set_data_file($data_file) {
+ $this->data_file = $data_file;
return $this;
}
@@ -323,7 +306,7 @@ class Item_Model extends ORM_MPTT {
}
$this->relative_path_cache = implode($names, "/");
$this->relative_url_cache = implode($slugs, "/");
- $this->save();
+ return $this;
}
/**
@@ -338,7 +321,7 @@ class Item_Model extends ORM_MPTT {
}
if (!isset($this->relative_path_cache)) {
- $this->_build_relative_caches();
+ $this->_build_relative_caches()->save();
}
return $this->relative_path_cache;
}
@@ -353,7 +336,7 @@ class Item_Model extends ORM_MPTT {
}
if (!isset($this->relative_url_cache)) {
- $this->_build_relative_caches();
+ $this->_build_relative_caches()->save();
}
return $this->relative_url_cache;
}
@@ -376,30 +359,10 @@ class Item_Model extends ORM_MPTT {
}
/**
- * @see ORM::__set()
- */
- public function __set($column, $value) {
- if ($column == "name") {
- $this->relative_path_cache = null;
- } else if ($column == "slug") {
- if ($this->slug != $value) {
- // Clear the relative url cache for this item and all children
- $this->relative_url_cache = null;
- if ($this->is_album()) {
- db::build()
- ->update("items")
- ->set("relative_url_cache", null)
- ->where("left_ptr", ">", $this->left_ptr)
- ->where("right_ptr", "<", $this->right_ptr)
- ->execute();
- }
- }
- }
- parent::__set($column, $value);
- }
-
- /**
+ * Handle any business logic necessary to create or modify an item.
* @see ORM::save()
+ *
+ * @return ORM Item_Model
*/
public function save() {
$significant_changes = $this->changed;
@@ -410,18 +373,147 @@ class Item_Model extends ORM_MPTT {
if (!empty($this->changed) && $significant_changes) {
$this->updated = time();
if (!$this->loaded()) {
+ // Create a new item. Use whatever fields are set, and specify defaults for the rest.
$this->created = $this->updated;
$this->weight = item::get_max_weight();
+ $this->rand_key = ((float)mt_rand()) / (float)mt_getrandmax();
+ $this->thumb_dirty = 1;
+ $this->resize_dirty = 1;
+ if (empty($this->sort_column)) {
+ $this->sort_column = "created";
+ }
+ if (empty($this->sort_order)) {
+ $this->sort_order = "ASC";
+ }
+ if (empty($this->owner_id)) {
+ $this->owner_id = identity::active_user()->id;
+ }
+
+ // Make an url friendly slug from the name, if necessary
+ if (empty($this->slug)) {
+ $tmp = pathinfo($this->name, PATHINFO_FILENAME);
+ $tmp = preg_replace("/[^A-Za-z0-9-_]+/", "-", $tmp);
+ $this->slug = trim($tmp, "-");
+ }
+
+ // Get the width, height and mime type from our data file for photos and movies.
+ if ($this->is_movie() || $this->is_photo()) {
+ $pi = pathinfo($this->data_file);
+
+ if ($this->is_photo()) {
+ $image_info = getimagesize($this->data_file);
+ $this->width = $image_info[0];
+ $this->height = $image_info[1];
+ $this->mime_type = $image_info["mime"];
+
+ // Force an extension onto the name if necessary
+ if (empty($pi["extension"])) {
+ $pi["extension"] = image_type_to_extension($image_info[2], false);
+ $this->name .= "." . $pi["extension"];
+ }
+ } else {
+ list ($this->width, $this->height) = movie::getmoviesize($this->data_file);
+
+ // No extension? Assume FLV.
+ if (empty($pi["extension"])) {
+ $pi["extension"] = "flv";
+ $this->name .= "." . $pi["extension"];
+ }
+
+ $this->mime_type = strtolower($pi["extension"]) == "mp4" ? "video/mp4" : "video/x-flv";
+ }
+ }
+
+ // Randomize the name or slug if there's a conflict. Preserve the extension.
+ // @todo Improve this. Random numbers are not user friendly
+ $base_name = pathinfo($this->name, PATHINFO_FILENAME);
+ $base_ext = pathinfo($this->name, PATHINFO_EXTENSION);
+ $base_slug = $this->slug;
+ while (ORM::factory("item")
+ ->where("parent_id", "=", $this->parent_id)
+ ->and_open()
+ ->where("name", "=", $this->name)
+ ->or_where("slug", "=", $this->slug)
+ ->close()
+ ->find()->id) {
+ $rand = rand();
+ if ($base_ext) {
+ $this->name = "$base_name-$rand.$base_ext";
+ } else {
+ $this->name = "$base_name-$rand";
+ }
+ $this->slug = "$base_slug-$rand";
+ }
+
+ parent::save();
+
+ // Build our url caches, then save again. We have to do this after it's already been
+ // saved once because we use only information from the database to build the paths. If we
+ // could depend on a save happening later we could defer this 2nd save.
+ $this->_build_relative_caches();
+ parent::save();
+
+ // Take any actions that we can only do once all our paths are set correctly after saving.
+ switch ($this->type) {
+ case "album":
+ mkdir($this->file_path());
+ mkdir(dirname($this->thumb_path()));
+ mkdir(dirname($this->resize_path()));
+ break;
+
+ case "photo":
+ case "movie":
+ // The thumb or resize may already exist in the case where a movie and a photo generate
+ // a thumbnail of the same name (eg, foo.flv movie and foo.jpg photo will generate
+ // foo.jpg thumbnail). If that happens, randomize and save again.
+ if (file_exists($this->resize_path()) ||
+ file_exists($this->thumb_path())) {
+ $pi = pathinfo($this->name);
+ $this->name = $pi["filename"] . "-" . rand() . "." . $pi["extension"];
+ parent::save();
+ }
+
+ copy($this->data_file, $this->file_path());
+ break;
+ }
+
+ // This will almost definitely trigger another save, so put it at the end so that we're
+ // tail recursive.
+ module::event("item_created", $this);
} else {
- $send_event = 1;
+ // Update an existing item
+ if ($this->original()->name != $this->name) {
+ $this->rename($this->name);
+ $this->relative_path_cache = null;
+ }
+
+ if ($this->original()->slug != $this->slug) {
+ // Clear the relative url cache for this item and all children
+ $this->relative_url_cache = null;
+ }
+
+ // Changing the name or the slug ripples downwards
+ if ($this->is_album() &&
+ ($this->original()->name != $this->name ||
+ $this->original()->slug != $this->slug)) {
+ db::build()
+ ->update("items")
+ ->set("relative_url_cache", null)
+ ->set("relative_path_cache", null)
+ ->where("left_ptr", ">", $this->left_ptr)
+ ->where("right_ptr", "<", $this->right_ptr)
+ ->execute();
+ }
+ $original = clone $this->original();
+ parent::save();
+ module::event("item_updated", $original, $this);
}
+ } else if (!empty($this->changed)) {
+ // Insignificant changes only. Don't fire events or do any special checking to try to keep
+ // this lightweight.
+ parent::save();
}
- $original = clone $this->original();
- parent::save();
- if (isset($send_event)) {
- module::event("item_updated", $original, $this);
- }
return $this;
}
@@ -657,4 +749,188 @@ class Item_Model extends ORM_MPTT {
}
return parent::descendants($limit, $offset, $where, $order_by);
}
+
+ /**
+ * Specify our rules here so that we have access to the instance of this model.
+ */
+ public function validate($array=null) {
+ if (!$array) {
+ $this->rules = array(
+ "album_cover_item_id" => array("callbacks" => array(array($this, "valid_item"))),
+ "description" => array("rules" => array("length[0,65535]")),
+ "mime_type" => array("callbacks" => array(array($this, "valid_field"))),
+ "name" => array("rules" => array("length[0,255]", "required"),
+ "callbacks" => array(array($this, "valid_name"))),
+ "parent_id" => array("callbacks" => array(array($this, "valid_parent"))),
+ "rand_key" => array("rule" => array("decimal")),
+ "slug" => array("rules" => array("length[0,255]", "required"),
+ "callbacks" => array(array($this, "valid_slug"))),
+ "sort_column" => array("callbacks" => array(array($this, "valid_field"))),
+ "sort_order" => array("callbacks" => array(array($this, "valid_field"))),
+ "title" => array("rules" => array("length[0,255]", "required")),
+ "type" => array("callbacks" => array(array($this, "read_only"),
+ array($this, "valid_field"))),
+ );
+
+ // Conditional rules
+ if ($this->id == 1) {
+ // Root album can't have a name or slug so replace the rules
+ $this->rules["name"] = array("rules" => array("length[0]"));
+ $this->rules["slug"] = array("rules" => array("length[0]"));
+ }
+
+ // Movies and photos must have data files
+ if (($this->is_photo() || $this->is_movie()) && !$this->loaded()) {
+ $this->rules["name"]["callbacks"][] = array($this, "valid_data_file");
+ }
+ }
+
+ parent::validate($array);
+ }
+
+ /**
+ * Validate that the desired slug does not conflict.
+ */
+ public function valid_slug(Validation $v, $field) {
+ if (preg_match("/[^A-Za-z0-9-_]/", $this->slug)) {
+ $v->add_error("slug", "not_url_safe");
+ } else if (db::build()
+ ->from("items")
+ ->where("parent_id", "=", $this->parent_id)
+ ->where("id", "<>", $this->id)
+ ->where("slug", "=", $this->slug)
+ ->count_records()) {
+ $v->add_error("slug", "conflict");
+ }
+ }
+
+ /**
+ * Validate the item name. It can't conflict with other names, can't contain slashes or
+ * trailing periods.
+ */
+ public function valid_name(Validation $v, $field) {
+ if (strpos($this->name, "/") !== false) {
+ $v->add_error("name", "no_slashes");
+ return;
+ }
+
+ if (rtrim($this->name, ".") !== $this->name) {
+ $v->add_error("name", "no_trailing_period");
+ return;
+ }
+
+ if ($this->is_movie() || $this->is_photo()) {
+ if ($this->loaded()) {
+ // Existing items can't change their extension
+ $new_ext = pathinfo($this->name, PATHINFO_EXTENSION);
+ $old_ext = pathinfo($this->original()->name, PATHINFO_EXTENSION);
+ if (strcasecmp($new_ext, $old_ext)) {
+ $v->add_error("name", "illegal_data_file_extension");
+ return;
+ }
+ } else {
+ // New items must have an extension
+ if (!pathinfo($this->name, PATHINFO_EXTENSION)) {
+ $v->add_error("name", "illegal_data_file_extension");
+ }
+ }
+ }
+
+ if (db::build()
+ ->from("items")
+ ->where("parent_id", "=", $this->parent_id)
+ ->where("id", "<>", $this->id)
+ ->where("name", "=", $this->name)
+ ->count_records()) {
+ $v->add_error("name", "conflict");
+ }
+ }
+
+ /**
+ * Make sure that the data file is well formed (it exists and isn't empty).
+ */
+ public function valid_data_file(Validation $v, $field) {
+ if (!is_file($this->data_file)) {
+ $v->add_error("name", "bad_data_file_path");
+ } else if (filesize($this->data_file) == 0) {
+ $v->add_error("name", "empty_data_file");
+ }
+ }
+
+ /**
+ * Make sure that the parent id refers to an album.
+ */
+ public function valid_parent(Validation $v, $field) {
+ if ($this->id == 1) {
+ if ($this->parent_id != 0) {
+ $v->add_error("parent_id", "invalid");
+ }
+ } else {
+ if (db::build()
+ ->from("items")
+ ->where("id", "=", $this->parent_id)
+ ->where("type", "=", "album")
+ ->count_records() != 1) {
+ $v->add_error("parent_id", "invalid");
+ }
+ }
+ }
+
+ /**
+ * Make sure the field refers to a valid item by id, or is null.
+ */
+ public function valid_item(Validation $v, $field) {
+ if ($this->$field && db::build()
+ ->from("items")
+ ->where("id", "=", $this->$field)
+ ->count_records() != 1) {
+ $v->add_error($field, "invalid_item");
+ }
+ }
+
+ /**
+ * Make sure that the type is valid.
+ */
+ public function valid_field(Validation $v, $field) {
+ switch($field) {
+ case "mime_type":
+ if ($this->is_movie()) {
+ $legal_values = array("video/flv", "video/mp4");
+ } if ($this->is_photo()) {
+ $legal_values = array("image/jpeg", "image/gif", "image/png");
+ }
+ break;
+
+ case "sort_column":
+ if (!array_key_exists($this->sort_column, $this->object)) {
+ $v->add_error($field, "invalid");
+ }
+ break;
+
+ case "sort_order":
+ $legal_values = array("ASC", "DESC", "asc", "desc");
+ break;
+
+ case "type":
+ $legal_values = array("album", "photo", "movie");
+ break;
+
+ default:
+ $v->add_error($field, "unvalidated_field");
+ break;
+ }
+
+ if (isset($legal_values) && !in_array($this->$field, $legal_values)) {
+ $v->add_error($field, "invalid");
+ }
+ }
+
+ /**
+ * This field cannot be changed after it's been set.
+ */
+ public function read_only(Validation $v, $field) {
+ if ($this->loaded() && $this->original()->$field != $this->$field) {
+ $v->add_error($field, "read_only");
+ }
+ }
}
diff --git a/modules/gallery/tests/Access_Helper_Test.php b/modules/gallery/tests/Access_Helper_Test.php
index b2244766..da72f12f 100644
--- a/modules/gallery/tests/Access_Helper_Test.php
+++ b/modules/gallery/tests/Access_Helper_Test.php
@@ -40,8 +40,7 @@ class Access_Helper_Test extends Unit_Test_Case {
} catch (Exception $e) { }
// Reset some permissions that we mangle below
- $root = ORM::factory("item", 1);
- access::allow(identity::everybody(), "view", $root);
+ access::allow(identity::everybody(), "view", item::root());
}
public function setup() {
@@ -67,16 +66,15 @@ class Access_Helper_Test extends Unit_Test_Case {
public function user_can_access_test() {
$access_test = identity::create_group("access_test");
- $root = ORM::factory("item", 1);
- access::allow($access_test, "view", $root);
+ access::allow($access_test, "view", item::root());
- $item = album::create($root, rand(), "test album");
+ $item = test::random_album();
access::deny(identity::everybody(), "view", $item);
access::deny(identity::registered_users(), "view", $item);
$item->reload();
- $user = identity::create_user("access_test", "Access Test", "");
+ $user = identity::create_user("access_test", "Access Test", "*****", "user@user.com");
foreach ($user->groups() as $group) {
$user->remove($group);
}
@@ -87,13 +85,12 @@ class Access_Helper_Test extends Unit_Test_Case {
}
public function user_can_no_access_test() {
- $root = ORM::factory("item", 1);
- $item = album::create($root, rand(), "test album");
+ $item = test::random_album();
access::deny(identity::everybody(), "view", $item);
access::deny(identity::registered_users(), "view", $item);
- $user = identity::create_user("access_test", "Access Test", "");
+ $user = identity::create_user("access_test", "Access Test", "*****", "user@user.com");
foreach ($user->groups() as $group) {
$user->remove($group);
}
@@ -103,8 +100,7 @@ class Access_Helper_Test extends Unit_Test_Case {
}
public function adding_and_removing_items_adds_ands_removes_rows_test() {
- $root = ORM::factory("item", 1);
- $item = album::create($root, rand(), "test album");
+ $item = test::random_album();
// New rows exist
$this->assert_true(ORM::factory("access_cache")->where("item_id", "=", $item->id)->find()->loaded());
@@ -119,19 +115,16 @@ class Access_Helper_Test extends Unit_Test_Case {
}
public function new_photos_inherit_parent_permissions_test() {
- $root = ORM::factory("item", 1);
-
- $album = album::create($root, rand(), "test album");
+ $album = test::random_album();
access::allow(identity::everybody(), "view", $album);
- $photo = photo::create($album, MODPATH . "gallery/images/gallery.png", "", "");
+ $photo = test::random_photo($album);
$this->assert_true($photo->__get("view_" . identity::everybody()->id));
}
public function can_allow_deny_and_reset_intent_test() {
- $root = ORM::factory("item", 1);
- $album = album::create($root, rand(), "test album");
+ $album = test::random_album();
$intent = ORM::factory("access_intent")->where("item_id", "=", $album->id)->find();
// Allow
@@ -167,23 +160,21 @@ class Access_Helper_Test extends Unit_Test_Case {
}
public function can_view_item_test() {
- $root = ORM::factory("item", 1);
- access::allow(identity::everybody(), "view", $root);
- $this->assert_true(access::group_can(identity::everybody(), "view", $root));
+ access::allow(identity::everybody(), "view", item::root());
+ $this->assert_true(access::group_can(identity::everybody(), "view", item::root()));
}
public function can_always_fails_on_unloaded_items_test() {
- $root = ORM::factory("item", 1);
- access::allow(identity::everybody(), "view", $root);
- $this->assert_true(access::group_can(identity::everybody(), "view", $root));
+ access::allow(identity::everybody(), "view", item::root());
+ $this->assert_true(access::group_can(identity::everybody(), "view", item::root()));
$bogus = ORM::factory("item", -1);
$this->assert_false(access::group_can(identity::everybody(), "view", $bogus));
}
public function cant_view_child_of_hidden_parent_test() {
- $root = ORM::factory("item", 1);
- $album = album::create($root, rand(), "test album");
+ $root = item::root();
+ $album = test::random_album();
$root->reload();
access::deny(identity::everybody(), "view", $root);
@@ -194,28 +185,26 @@ class Access_Helper_Test extends Unit_Test_Case {
}
public function view_permissions_propagate_down_test() {
- $root = ORM::factory("item", 1);
- $album = album::create($root, rand(), "test album");
+ $album = test::random_album();
- access::allow(identity::everybody(), "view", $root);
+ access::allow(identity::everybody(), "view", item::root());
access::reset(identity::everybody(), "view", $album);
$album->reload();
$this->assert_true(access::group_can(identity::everybody(), "view", $album));
}
public function can_toggle_view_permissions_propagate_down_test() {
- $root = ORM::factory("item", 1);
- $album1 = album::create($root, rand(), "test album");
- $album2 = album::create($album1, rand(), "test album");
- $album3 = album::create($album2, rand(), "test album");
- $album4 = album::create($album3, rand(), "test album");
+ $album1 = test::random_album(item::root());
+ $album2 = test::random_album($album1);
+ $album3 = test::random_album($album2);
+ $album4 = test::random_album($album3);
$album1->reload();
$album2->reload();
$album3->reload();
$album4->reload();
- access::allow(identity::everybody(), "view", $root);
+ access::allow(identity::everybody(), "view", item::root());
access::deny(identity::everybody(), "view", $album1);
access::reset(identity::everybody(), "view", $album2);
access::reset(identity::everybody(), "view", $album3);
@@ -230,9 +219,9 @@ class Access_Helper_Test extends Unit_Test_Case {
}
public function revoked_view_permissions_cant_be_allowed_lower_down_test() {
- $root = ORM::factory("item", 1);
- $album1 = album::create($root, rand(), "test album");
- $album2 = album::create($album1, rand(), "test album");
+ $root = item::root();
+ $album1 = test::random_album($root);
+ $album2 = test::random_album($album1);
$root->reload();
access::deny(identity::everybody(), "view", $root);
@@ -246,38 +235,30 @@ class Access_Helper_Test extends Unit_Test_Case {
}
public function can_edit_item_test() {
- $root = ORM::factory("item", 1);
+ $root = item::root();
access::allow(identity::everybody(), "edit", $root);
$this->assert_true(access::group_can(identity::everybody(), "edit", $root));
}
public function non_view_permissions_propagate_down_test() {
- $root = ORM::factory("item", 1);
- $album = album::create($root, rand(), "test album");
+ $album = test::random_album();
- access::allow(identity::everybody(), "edit", $root);
+ access::allow(identity::everybody(), "edit", item::root());
access::reset(identity::everybody(), "edit", $album);
$this->assert_true(access::group_can(identity::everybody(), "edit", $album));
}
public function non_view_permissions_can_be_revoked_lower_down_test() {
- $root = ORM::factory("item", 1);
- $outer = album::create($root, rand(), "test album");
- $outer_photo = ORM::factory("item");
- $outer_photo->type = "photo";
- $outer_photo->add_to_parent($outer);
- access::add_item($outer_photo);
-
- $inner = album::create($outer, rand(), "test album");
- $inner_photo = ORM::factory("item");
- $inner_photo->type = "photo";
- $inner_photo->add_to_parent($inner);
- access::add_item($inner_photo);
+ $outer = test::random_album();
+ $outer_photo = test::random_photo($outer);
+
+ $inner = test::random_album($outer);
+ $inner_photo = test::random_photo($inner);
$outer->reload();
$inner->reload();
- access::allow(identity::everybody(), "edit", $root);
+ access::allow(identity::everybody(), "edit", item::root());
access::deny(identity::everybody(), "edit", $outer);
access::allow(identity::everybody(), "edit", $inner);
@@ -288,7 +269,7 @@ class Access_Helper_Test extends Unit_Test_Case {
public function i_can_edit_test() {
// Create a new user that belongs to no groups
- $user = identity::create_user("access_test", "Access Test", "");
+ $user = identity::create_user("access_test", "Access Test", "*****", "user@user.com");
foreach ($user->groups() as $group) {
$user->remove($group);
}
@@ -296,7 +277,7 @@ class Access_Helper_Test extends Unit_Test_Case {
identity::set_active_user($user);
// This user can't edit anything
- $root = ORM::factory("item", 1);
+ $root = item::root();
$this->assert_false(access::can("edit", $root));
// Now add them to a group that has edit permission
@@ -313,8 +294,7 @@ class Access_Helper_Test extends Unit_Test_Case {
}
public function everybody_view_permission_maintains_htaccess_files_test() {
- $root = ORM::factory("item", 1);
- $album = album::create($root, rand(), "test album");
+ $album = test::random_album();
$this->assert_false(file_exists($album->file_path() . "/.htaccess"));
@@ -332,8 +312,7 @@ class Access_Helper_Test extends Unit_Test_Case {
}
public function everybody_view_full_permission_maintains_htaccess_files_test() {
- $root = ORM::factory("item", 1);
- $album = album::create($root, rand(), "test album");
+ $album = test::random_album();
$this->assert_false(file_exists($album->file_path() . "/.htaccess"));
$this->assert_false(file_exists($album->resize_path() . "/.htaccess"));
@@ -363,16 +342,15 @@ class Access_Helper_Test extends Unit_Test_Case {
public function moved_items_inherit_new_permissions_test() {
identity::set_active_user(identity::lookup_user_by_name("admin"));
- $root = ORM::factory("item", 1);
- $public_album = album::create($root, rand(), "public album");
- $public_photo = photo::create($public_album, MODPATH . "gallery/images/gallery.png", "", "");
+ $public_album = test::random_album();
+ $public_photo = test::random_photo($public_album);
access::allow(identity::everybody(), "view", $public_album);
- $root->reload(); // Account for MPTT changes
+ item::root()->reload(); // Account for MPTT changes
- $private_album = album::create($root, rand(), "private album");
+ $private_album = test::random_album();
access::deny(identity::everybody(), "view", $private_album);
- $private_photo = photo::create($private_album, MODPATH . "gallery/images/gallery.png", "", "");
+ $private_photo = test::random_photo($private_album);
// Make sure that we now have a public photo and private photo.
$this->assert_true(access::group_can(identity::everybody(), "view", $public_photo));
diff --git a/modules/gallery/tests/Gallery_Rest_Helper_Test.php b/modules/gallery/tests/Gallery_Rest_Helper_Test.php
index f8cf6190..dac221b3 100644
--- a/modules/gallery/tests/Gallery_Rest_Helper_Test.php
+++ b/modules/gallery/tests/Gallery_Rest_Helper_Test.php
@@ -136,7 +136,8 @@ class Gallery_Rest_Helper_Test extends Unit_Test_Case {
try {
gallery_rest::put($request);
} catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
+ $this->assert_equal("Bad request", $e->getMessage());
+ $this->assert_equal(400, $e->getCode());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
diff --git a/modules/gallery/tests/Item_Model_Test.php b/modules/gallery/tests/Item_Model_Test.php
index d03a03f4..b41740d6 100644
--- a/modules/gallery/tests/Item_Model_Test.php
+++ b/modules/gallery/tests/Item_Model_Test.php
@@ -19,20 +19,13 @@
*/
class Item_Model_Test extends Unit_Test_Case {
public function saving_sets_created_and_updated_dates_test() {
- $item = self::_create_random_item();
+ $item = test::random_photo();
$this->assert_true(!empty($item->created));
$this->assert_true(!empty($item->updated));
}
- private static function _create_random_item($root=null, $rand=null) {
- $root = $root ? $root : ORM::factory("item", 1);
- $rand = $rand ? $rand : rand();
- $item = photo::create($root, MODPATH . "gallery/tests/test.jpg", "$rand.jpg", $rand, $rand);
- return $item;
- }
-
public function updating_doesnt_change_created_date_test() {
- $item = self::_create_random_item();
+ $item = test::random_photo();
// Force the creation date to something well known
db::build()
@@ -50,7 +43,7 @@ class Item_Model_Test extends Unit_Test_Case {
}
public function updating_view_count_only_doesnt_change_updated_date_test() {
- $item = self::_create_random_item();
+ $item = test::random_photo();
$item->reload();
$this->assert_equal(0, $item->view_count);
@@ -69,8 +62,7 @@ class Item_Model_Test extends Unit_Test_Case {
}
public function rename_photo_test() {
- // Create a test photo
- $item = self::_create_random_item();
+ $item = test::random_photo();
file_put_contents($item->thumb_path(), "thumb");
file_put_contents($item->resize_path(), "resize");
@@ -80,7 +72,8 @@ class Item_Model_Test extends Unit_Test_Case {
$new_name = rand();
// Now rename it
- $item->rename($new_name)->save();
+ $item->name = $new_name;
+ $item->save();
// Expected: the name changed, the name is now baked into all paths, and all files were moved.
$this->assert_equal($new_name, $item->name);
@@ -93,10 +86,9 @@ class Item_Model_Test extends Unit_Test_Case {
}
public function rename_album_test() {
- // Create an album with a photo in it
- $root = ORM::factory("item", 1);
- $album = album::create($root, rand(), rand(), rand());
- $photo = self::_create_random_item($album);
+ $album = test::random_album();
+ $photo = test::random_photo($album);
+ $album->reload();
file_put_contents($photo->thumb_path(), "thumb");
file_put_contents($photo->resize_path(), "resize");
@@ -107,7 +99,8 @@ class Item_Model_Test extends Unit_Test_Case {
$new_album_name = rand();
// Now rename the album
- $album->rename($new_album_name)->save();
+ $album->name = $new_album_name;
+ $album->save();
$photo->reload();
// Expected:
@@ -130,8 +123,7 @@ class Item_Model_Test extends Unit_Test_Case {
}
public function item_rename_wont_accept_slash_test() {
- // Create a test photo
- $item = self::_create_random_item();
+ $item = test::random_photo();
$new_name = rand() . "/";
@@ -146,24 +138,23 @@ class Item_Model_Test extends Unit_Test_Case {
public function item_rename_fails_with_existing_name_test() {
// Create a test photo
- $item = self::_create_random_item();
- $item2 = self::_create_random_item();
-
- $new_name = $item2->name;
+ $item = test::random_photo();
+ $item2 = test::random_photo();
try {
- $item->rename($new_name)->save();
- } catch (Exception $e) {
- // pass
- $this->assert_true(strpos($e->getMessage(), "INVALID_RENAME_FILE_EXISTS") !== false,
- "incorrect exception.");
+ $item->name = $item2->name;
+ $item->validate(); // @todo: switch this to save() once
+ // http://dev.kohanaphp.com/issues/2504 is fixed.
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_true(in_array("conflict", $e->validation->errors()));
return;
}
- $this->assert_false(true, "Item_Model::rename should fail.");
+
+ $this->assert_false(true, "rename should conflict");
}
public function save_original_values_test() {
- $item = self::_create_random_item();
+ $item = test::random_photo_unsaved();
$item->title = "ORIGINAL_VALUE";
$item->save();
$item->title = "NEW_VALUE";
@@ -172,29 +163,17 @@ class Item_Model_Test extends Unit_Test_Case {
$this->assert_same("NEW_VALUE", $item->title);
}
- public function urls_are_rawurlencoded_test() {
- $item = self::_create_random_item();
- $item->slug = "foo bar";
- $item->name = "foo bar.jpg";
- $item->save();
-
- $this->assert_equal("foo%20bar", $item->relative_url());
- $this->assert_equal("foo%20bar.jpg", $item->relative_path());
- }
-
public function move_album_test() {
- // Create an album with a photo in it
- $root = ORM::factory("item", 1);
- $album2 = album::create($root, rand(), rand(), rand());
- $album = album::create($album2, rand(), rand(), rand());
- $photo = self::_create_random_item($album);
+ $album2 = test::random_album();
+ $album = test::random_album($album2);
+ $photo = test::random_photo($album);
file_put_contents($photo->thumb_path(), "thumb");
file_put_contents($photo->resize_path(), "resize");
file_put_contents($photo->file_path(), "file");
// Now move the album
- $album->move_to($root);
+ $album->move_to(item::root());
$photo->reload();
// Expected:
@@ -212,11 +191,9 @@ class Item_Model_Test extends Unit_Test_Case {
}
public function move_photo_test() {
- // Create an album with a photo in it
- $root = ORM::factory("item", 1);
- $album2 = album::create($root, rand(), rand(), rand());
- $album = album::create($album2, rand(), rand(), rand());
- $photo = self::_create_random_item($album);
+ $album2 = test::random_album();
+ $album = test::random_album($album2);
+ $photo = test::random_photo($album);
file_put_contents($photo->thumb_path(), "thumb");
file_put_contents($photo->resize_path(), "resize");
@@ -241,42 +218,61 @@ class Item_Model_Test extends Unit_Test_Case {
}
public function move_album_fails_invalid_target_test() {
- // Create an album with a photo in it
- $root = ORM::factory("item", 1);
- $name = rand();
- $album = album::create($root, $name, $name, $name);
- $source = album::create($album, $name, $name, $name);
+ $album = test::random_album();
+ $source = test::random_album($album);
try {
- $source->move_to($root);
+ $source->move_to(item::root());
} catch (Exception $e) {
// pass
$this->assert_true(strpos($e->getMessage(), "INVALID_MOVE_TARGET_EXISTS") !== false,
"incorrect exception.");
return;
}
-
- $this->assert_false(true, "Item_Model::rename should not accept / characters");
}
public function move_photo_fails_invalid_target_test() {
- // Create an album with a photo in it
- $root = ORM::factory("item", 1);
- $photo_name = rand();
- $photo1 = self::_create_random_item($root, $photo_name);
- $name = rand();
- $album = album::create($root, $name, $name, $name);
- $photo2 = self::_create_random_item($album, $photo_name);
+ $photo1 = test::random_photo();
+ $album = test::random_album();
+ $photo2 = test::random_photo($album);
try {
- $photo2->move_to($root);
+ $photo2->move_to(item::root());
} catch (Exception $e) {
// pass
$this->assert_true(strpos($e->getMessage(), "INVALID_MOVE_TARGET_EXISTS") !== false,
"incorrect exception.");
return;
}
+ }
- $this->assert_false(true, "Item_Model::rename should not accept / characters");
+ public function basic_validation_test() {
+ $item = ORM::factory("item");
+ $item->album_cover_item_id = rand(); // invalid
+ $item->description = str_repeat("x", 70000); // invalid
+ $item->name = null;
+ $item->parent_id = rand();
+ $item->slug = null;
+ $item->sort_column = "bogus";
+ $item->sort_order = "bogus";
+ $item->title = null;
+ $item->type = "bogus";
+ try {
+ $item->save();
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_same(array("description" => "length",
+ "name" => "required",
+ "slug" => "required",
+ "title" => "required",
+ "album_cover_item_id" => "invalid_item",
+ "parent_id" => "invalid",
+ "sort_column" => "invalid",
+ "sort_order" => "invalid",
+ "type" => "invalid"),
+ $e->validation->errors());
+ return;
+ }
+
+ $this->assert_false(true, "Shouldn't get here");
}
}
diff --git a/modules/gallery/tests/Kohana_Bug_Test.php b/modules/gallery/tests/Kohana_Bug_Test.php
new file mode 100644
index 00000000..61f5d69e
--- /dev/null
+++ b/modules/gallery/tests/Kohana_Bug_Test.php
@@ -0,0 +1,38 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class Kohana_Bug_Test extends Unit_Test_Case {
+ function double_save_test_should_fail_test() {
+ // http://dev.kohanaframework.org/issues/2504
+ $group = ORM::factory("group");
+ $group->name = rand();
+ $group->save(); // this save works
+
+ try {
+ $group->name = null; // now I change to an illegal value
+ $group->save(); // this passes, but it shouldn't. My model is broken!
+
+ // This is the normal state when the bug is not fixed.
+ } catch (ORM_Validation_Exception $e) {
+ // When this triggers, the bug is fixed. Find any references to ticket #2504 in the code
+ // and update those accordingly
+ $this->assert_true(false, "Bug #2504 has been fixed");
+ }
+ }
+}
diff --git a/modules/gallery_unit_test/controllers/gallery_unit_test.php b/modules/gallery_unit_test/controllers/gallery_unit_test.php
index 498dd756..e05fcbaa 100644
--- a/modules/gallery_unit_test/controllers/gallery_unit_test.php
+++ b/modules/gallery_unit_test/controllers/gallery_unit_test.php
@@ -127,6 +127,12 @@ class Gallery_Unit_Test_Controller extends Controller {
$filter = count($_SERVER["argv"]) > 2 ? $_SERVER["argv"][2] : null;
print new Unit_Test($modules, $filter);
+ } catch (ORM_Validation_Exception $e) {
+ print "Validation Exception: {$e->getMessage()}\n";
+ print $e->getTraceAsString() . "\n";
+ foreach ($e->validation->errors() as $field => $msg) {
+ print "$field: $msg\n";
+ }
} catch (Exception $e) {
print "Exception: {$e->getMessage()}\n";
print $e->getTraceAsString() . "\n";
diff --git a/modules/gallery_unit_test/helpers/test.php b/modules/gallery_unit_test/helpers/test.php
new file mode 100644
index 00000000..5368539f
--- /dev/null
+++ b/modules/gallery_unit_test/helpers/test.php
@@ -0,0 +1,50 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class test_Core {
+ static function random_album_unsaved($parent=null) {
+ $rand = rand();
+
+ $album = ORM::factory("item");
+ $album->type = "album";
+ $album->parent_id = $parent ? $parent->id : 1;
+ $album->name = "name_$rand";
+ $album->title = "title_$rand";
+ return $album;
+ }
+
+ static function random_album($parent=null) {
+ return test::random_album_unsaved($parent)->save();
+ }
+
+ static function random_photo_unsaved($parent=null) {
+ $rand = rand();
+ $photo = ORM::factory("item");
+ $photo->type = "photo";
+ $photo->parent_id = $parent ? $parent->id : 1;
+ $photo->set_data_file(MODPATH . "gallery/tests/test.jpg");
+ $photo->name = "name_$rand.jpg";
+ $photo->title = "title_$rand";
+ return $photo;
+ }
+
+ static function random_photo($parent=null) {
+ return test::random_photo_unsaved($parent)->save();
+ }
+}
diff --git a/modules/gallery_unit_test/views/kohana_unit_test_cli.php b/modules/gallery_unit_test/views/kohana_unit_test_cli.php
index 3203ee44..a0de0f52 100644
--- a/modules/gallery_unit_test/views/kohana_unit_test_cli.php
+++ b/modules/gallery_unit_test/views/kohana_unit_test_cli.php
@@ -57,6 +57,12 @@ foreach ($results as $class => $methods) {
if ($result->getMessage()) {
echo " ", $result->getMessage(), "\n";
}
+ if ($result instanceof ORM_Validation_Exception) {
+ echo " Validation errors:\n";
+ foreach ($result->validation->errors() as $key => $value) {
+ echo " $key: $value\n";
+ }
+ }
echo " ", $result->getFile(), " (Line ", $result->getLine(), ")\n";
echo "\n";
echo $result->getTraceAsString(), "\n";
diff --git a/modules/image_block/helpers/image_block_block.php b/modules/image_block/helpers/image_block_block.php
index f591e8d1..f28e775f 100644
--- a/modules/image_block/helpers/image_block_block.php
+++ b/modules/image_block/helpers/image_block_block.php
@@ -30,29 +30,9 @@ class image_block_block_Core {
$block->css_id = "g-image-block";
$block->title = t("Random image");
$block->content = new View("image_block_block.html");
+ $block->content->items = item::random_query(array(array("type", "!=", "album")))->find_all(1);
- $random = ((float)mt_rand()) / (float)mt_getrandmax();
-
- $items = ORM::factory("item")
- ->viewable()
- ->where("type", "!=", "album")
- ->where("rand_key", "<", $random)
- ->order_by(array("rand_key" => "DESC"))
- ->find_all(1);
-
- if ($items->count() == 0) {
- // Try once more. If this fails, just ditch the block altogether
- $items = ORM::factory("item")
- ->viewable()
- ->where("type", "!=", "album")
- ->where("rand_key", ">=", $random)
- ->order_by(array("rand_key" => "DESC"))
- ->find_all(1);
- }
-
- if ($items->count() > 0) {
- $block->content->item = $items->current();
- } else {
+ if ($block->content->items->count() == 0) {
$block = "";
}
break;
diff --git a/modules/image_block/helpers/image_block_rest.php b/modules/image_block/helpers/image_block_rest.php
deleted file mode 100644
index 7afd974c..00000000
--- a/modules/image_block/helpers/image_block_rest.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php defined("SYSPATH") or die("No direct script access.");
-/**
- * Gallery - a web based photo album viewer and editor
- * Copyright (C) 2000-2009 Bharat Mediratta
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
- */
-class image_block_rest_Core {
- static function get($request) {
- $type = empty($request->type) ? "random" : $request->type;
- switch ($type) {
- case "random":
- $random = ((float)mt_rand()) / (float)mt_getrandmax();
-
- $items = ORM::factory("item")
- ->viewable()
- ->where("type", "!=", "album")
- ->where("rand_key", "<", $random)
- ->order_by(array("rand_key" => "DESC"))
- ->find_all(1);
-
- if ($items->count() == 0) {
- // Try once more. If this fails, just ditch the block altogether
- $items = ORM::factory("item")
- ->viewable()
- ->where("type", "!=", "album")
- ->where("rand_key", ">= ", $random)
- ->order_by(array("rand_key" => "DESC"))
- ->find_all(1);
- }
- break;
- default:
- return rest::fail("Unsupported image block type: '{$type}'");
- }
-
- if ($items->count() > 0) {
- $item = $items->current();
- $response_data = array("name" => $item->name,
- "path" => $item->relative_url(),
- "title" => $item->title,
- "thumb_url" => $item->thumb_url(true),
- "thumb_size" => array("height" => $item->thumb_height,
- "width" => $item->thumb_width));
-
- return rest::success(array("resource" => $response_data));
- } else {
- return rest::fail("No Image found");
- }
- }
-}
diff --git a/modules/kohana23_compat/libraries/MY_Database_Builder.php b/modules/kohana23_compat/libraries/MY_Database_Builder.php
index c82b6ac4..b2a5c92a 100644
--- a/modules/kohana23_compat/libraries/MY_Database_Builder.php
+++ b/modules/kohana23_compat/libraries/MY_Database_Builder.php
@@ -23,8 +23,10 @@ class Database_Builder extends Database_Builder_Core {
* @chainable
*/
public function merge_where($tuples) {
- foreach ($tuples as $tuple) {
- $this->where($tuple[0], $tuple[1], $tuple[2]);
+ if ($tuples) {
+ foreach ($tuples as $tuple) {
+ $this->where($tuple[0], $tuple[1], $tuple[2]);
+ }
}
return $this;
}
@@ -34,8 +36,10 @@ class Database_Builder extends Database_Builder_Core {
* @chainable
*/
public function merge_or_where($tuples) {
- foreach ($tuples as $tuple) {
- $this->or_where($tuple[0], $tuple[1], $tuple[2]);
+ if ($tuples) {
+ foreach ($tuples as $tuple) {
+ $this->or_where($tuple[0], $tuple[1], $tuple[2]);
+ }
}
return $this;
}
diff --git a/modules/rest/controllers/rest.php b/modules/rest/controllers/rest.php
index 26e5b31a..cac49740 100644
--- a/modules/rest/controllers/rest.php
+++ b/modules/rest/controllers/rest.php
@@ -18,20 +18,14 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class Rest_Controller extends Controller {
- public function access_key() {
+ public function index() {
try {
- $request = (object)Input::instance()->get();
- if (empty($request->user) || empty($request->password)) {
- throw new Rest_Exception(403, "Forbidden");
- }
-
- $user = identity::lookup_user_by_name($request->user);
- if (empty($user)) {
- throw new Rest_Exception(403, "Forbidden");
- }
+ $username = Input::instance()->post("user");
+ $password = Input::instance()->post("password");
- if (!identity::is_correct_password($user, $request->password)) {
- throw new Rest_Exception(403, "Forbidden");
+ $user = identity::lookup_user_by_name($username);
+ if (empty($user) || !identity::is_correct_password($user, $password)) {
+ throw new Rest_Exception("Forbidden", 403);
}
$key = ORM::factory("user_access_token")
@@ -42,27 +36,52 @@ class Rest_Controller extends Controller {
$key->access_key = md5($user->name . rand());
$key->save();
}
- print rest::success(array("token" => $key->access_key));
- } catch (Rest_Exception $e) {
- $e->sendHeaders();
+
+ rest::reply($key->access_key);
+ } catch (Exception $e) {
+ rest::send_headers($e);
}
}
public function __call($function, $args) {
- $request = rest::normalize_request($args);
+ $input = Input::instance();
+ switch ($method = strtolower($input->server("REQUEST_METHOD"))) {
+ case "get":
+ $request->params = (object) Input::instance()->get();
+ break;
+
+ case "post":
+ $request->params = (object) Input::instance()->post();
+ if (isset($_FILES["file"])) {
+ $request->file = upload::save("file");
+ }
+ break;
+ }
+
+ $request->method = strtolower($input->server("HTTP_X_GALLERY_REQUEST_METHOD", $method));
+ $request->access_token = $input->server("HTTP_X_GALLERY_REQUEST_KEY");
+ $request->url = url::abs_current(true);
+
try {
- if (rest::set_active_user($request->access_token)) {
- $handler_class = "{$function}_rest";
- $handler_method = $request->method;
+ rest::set_active_user($request->access_token);
- if (!method_exists($handler_class, $handler_method)) {
- throw new Rest_Exception(403, "Forbidden");
- }
+ $handler_class = "{$function}_rest";
+ $handler_method = $request->method;
+ if (!method_exists($handler_class, $handler_method)) {
+ throw new Rest_Exception("Forbidden", 403);
+ }
+
+ try {
print call_user_func(array($handler_class, $handler_method), $request);
+ } catch (ORM_Validation_Exception $e) {
+ foreach ($e->validation->errors() as $key => $value) {
+ $msgs[] = "$key: $value";
+ }
+ throw new Rest_Exception("Bad Request: " . join(", ", $msgs), 400);
}
} catch (Rest_Exception $e) {
- $e->sendHeaders();
+ rest::send_headers($e);
}
}
} \ No newline at end of file
diff --git a/modules/rest/helpers/rest.php b/modules/rest/helpers/rest.php
index be0644f2..121191f2 100644
--- a/modules/rest/helpers/rest.php
+++ b/modules/rest/helpers/rest.php
@@ -18,87 +18,57 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class rest_Core {
- /**
- * Request failed
- */
- static function fail($log_message=null) {
- if (!empty($log_message)) {
- Kohana_Log::add("info", $log_message);
- }
- // We don't need to save the session for this request
+ static function reply($data=array()) {
Session::abort_save();
- return json_encode(array("status" => "ERROR", "message" => (string)$message));
- }
- /**
- * Success
- */
- static function success($response_data=array(), $message=null) {
- $response = array("status" => "OK");
- if (!empty($message)) {
- $response["message"] = (string)$message;
+ if ($data) {
+ print json_encode($data);
}
- $response = array_merge($response, $response_data);
-
- // We don't need to save the session for this request
- Session::abort_save();
- return json_encode($response);
}
- /**
- * Validation Error
- */
- static function validation_error($error_data) {
- $response = array("status" => "VALIDATE_ERROR");
- $response = array_merge($response, array("fields" => $error_data));
-
- // We don't need to save the session for this request
- Session::abort_save();
- return json_encode($response);
- }
+ static function set_active_user($access_token) {
+ if (empty($access_token)) {
+ identity::set_active_user(identity::guest());
+ return;
+ }
+ $key = ORM::factory("user_access_token")
+ ->where("access_key", "=", $access_token)
+ ->find();
- static function normalize_request($args=array()) {
- $input = Input::instance();
- $method = strtolower($input->server("REQUEST_METHOD"));
- $request = new stdClass();
- foreach (array_keys($input->get()) as $key) {
- $request->$key = $input->get($key);
+ if (!$key->loaded()) {
+ throw new Rest_Exception("Forbidden", 403);
}
- if ($method != "get") {
- foreach (array_keys($input->post()) as $key) {
- $request->$key = $input->post($key);
- }
- foreach (array_keys($_FILES) as $key) {
- $request->$key = $_FILES[$key];
- }
+
+ $user = identity::lookup_user($key->user_id);
+ if (empty($user)) {
+ throw new Rest_Exception("Forbidden", 403);
}
- $request->method = strtolower($input->server("HTTP_X_GALLERY_REQUEST_METHOD", $method));
- $request->access_token = $input->server("HTTP_X_GALLERY_REQUEST_KEY");
- $request->arguments = $args; // Let the rest handler figure out what the arguments mean
+ identity::set_active_user($user);
+ }
- return $request;
+ static function send_headers($exception) {
+ header("HTTP/1.1 " . $exception->getCode() . " " . $exception->getMessage());
}
- static function set_active_user($access_token) {
- if (empty($access_token)) {
- $user = identity::guest();
- } else {
- $key = ORM::factory("user_access_token")
- ->where("access_key", "=", $access_token)
- ->find();
+ /**
+ * Convert a REST url into an object.
+ * Eg: "http://example.com/gallery3/index.php/rest/gallery/Family/Wedding" -> Item_Model
+ *
+ * @param string the fully qualified REST url
+ * @return mixed the corresponding object (usually a model of some kind)
+ */
+ static function resolve($url) {
+ $relative_url = substr($url, strlen(url::abs_site("rest")));
+ $path = parse_url($relative_url, PHP_URL_PATH);
+ $components = explode("/", $path, 3);
- if ($key->loaded()) {
- $user = identity::lookup_user($key->user_id);
- if (empty($user)) {
- throw new Rest_Exception(403, "Forbidden");
- }
- } else {
- throw new Rest_Exception(403, "Forbidden");
- }
+ $class = "$components[1]_rest";
+ if (!method_exists($class, "resolve")) {
+ throw new Kohana_404_Exception($url);
}
- identity::set_active_user($user);
- return true;
+
+ return call_user_func(array($class, "resolve"), !empty($components[2]) ? $components[2] : null);
}
}
diff --git a/modules/rest/libraries/Rest_Exception.php b/modules/rest/libraries/Rest_Exception.php
index 905b94a0..596b3712 100644
--- a/modules/rest/libraries/Rest_Exception.php
+++ b/modules/rest/libraries/Rest_Exception.php
@@ -18,19 +18,4 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class Rest_Exception_Core extends Exception {
- /**
- * Set internal properties.
- */
- public function __construct($code, $text) {
- parent::__construct("$code $text");
- }
-
- /**
- * Sends the headers, to emulate server behavior.
- *
- * @return void
- */
- public function sendHeaders() {
- header('HTTP/1.1 {$this->getMessage()}');
- }
-} // End Rest Exception \ No newline at end of file
+} \ No newline at end of file
diff --git a/modules/rest/tests/Rest_Controller_Test.php b/modules/rest/tests/Rest_Controller_Test.php
index 83bd9db6..c881583c 100644
--- a/modules/rest/tests/Rest_Controller_Test.php
+++ b/modules/rest/tests/Rest_Controller_Test.php
@@ -84,7 +84,8 @@ class Rest_Controller_Test extends Unit_Test_Case {
try {
$this->_call_controller();
} catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
+ $this->assert_equal(403, $e->getCode());
+ $this->assert_equal("Forbidden", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -97,7 +98,8 @@ class Rest_Controller_Test extends Unit_Test_Case {
try {
$this->_call_controller();
} catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
+ $this->assert_equal(403, $e->getCode());
+ $this->assert_equal("Forbidden", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -109,7 +111,8 @@ class Rest_Controller_Test extends Unit_Test_Case {
try {
$this->_call_controller();
} catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
+ $this->assert_equal(403, $e->getCode());
+ $this->assert_equal("Forbidden", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -137,7 +140,8 @@ class Rest_Controller_Test extends Unit_Test_Case {
try {
$this->_call_controller();
} catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
+ $this->assert_equal(403, $e->getCode());
+ $this->assert_equal("Forbidden", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -155,7 +159,8 @@ class Rest_Controller_Test extends Unit_Test_Case {
try {
$this->_call_controller("rest", explode("/", $photo->relative_url()));
} catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
+ $this->assert_equal(403, $e->getCode());
+ $this->assert_equal("Forbidden", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -171,7 +176,8 @@ class Rest_Controller_Test extends Unit_Test_Case {
try {
$this->_call_controller("rest", explode("/", $photo->relative_url()));
} catch (Rest_Exception $e) {
- $this->assert_equal("501 Not Implemented", $e->getMessage());
+ $this->assert_equal(501, $e->getCode());
+ $this->assert_equal("Not Implemented", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -218,7 +224,7 @@ class rest_rest {
$response["thumb_url"] = $item->thumb_url();
$response["description"] = $item->description;
$response["internet_address"] = $item->slug;
- return rest::success(array($item->type => $response), t("Processed"));
+ return rest::reply(array($item->type => $response));
}
}
diff --git a/modules/tag/controllers/admin_tags.php b/modules/tag/controllers/admin_tags.php
index e20b8ac8..3b605a4e 100644
--- a/modules/tag/controllers/admin_tags.php
+++ b/modules/tag/controllers/admin_tags.php
@@ -60,9 +60,7 @@ class Admin_Tags_Controller extends Admin_Controller {
array("result" => "success",
"location" => url::site("admin/tags")));
} else {
- print json_encode(
- array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
diff --git a/modules/tag/controllers/tags.php b/modules/tag/controllers/tags.php
index 992c7411..e28b7a83 100644
--- a/modules/tag/controllers/tags.php
+++ b/modules/tag/controllers/tags.php
@@ -71,9 +71,7 @@ class Tags_Controller extends Controller {
array("result" => "success",
"cloud" => tag::cloud(30)->__toString()));
} else {
- print json_encode(
- array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
diff --git a/modules/tag/helpers/tag.php b/modules/tag/helpers/tag.php
index 8075afe4..d895e08f 100644
--- a/modules/tag/helpers/tag.php
+++ b/modules/tag/helpers/tag.php
@@ -41,7 +41,7 @@ class tag_Core {
}
if (!$tag->has($item)) {
- if (!$tag->add($item, $tag)) {
+ if (!$tag->add($item)) {
throw new Exception("@todo {$tag->name} WAS_NOT_ADDED_TO {$item->id}");
}
$tag->count++;
diff --git a/modules/tag/helpers/tag_rest.php b/modules/tag/helpers/tag_rest.php
index cd1ca6c6..0aac5291 100644
--- a/modules/tag/helpers/tag_rest.php
+++ b/modules/tag/helpers/tag_rest.php
@@ -18,143 +18,76 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class tag_rest_Core {
- // If no arguments just return all the tags. If 2 or more then it is a path then
- // return the tags for that item. But if its only 1, then is it a path or a tag?
- // Assume a tag first, if nothing is found then try finding the item.
static function get($request) {
- $resources = array();
- switch (count($request->arguments)) {
- case 0:
- $tags = ORM::factory("tag")
- ->select("name", "count")
- ->order_by("count", "DESC");
- if (!empty($request->limit)) {
- $tags->limit($request->limit);
- }
- if (!empty($request->offset)) {
- $tags->offset($request->offset);
- }
- $resources = array("tags" => array());
- foreach ($tags->find_all() as $row) {
- $resources["tags"][] = array("name" => $row->name, "count" => $row->count);
- }
- break;
- case 1:
- $resources = tag_rest::_get_items($request);
- if (!empty($resources)) {
- $resources = array("resources" => $resources);
- break;
- }
- default:
- $item = ORM::factory("item")
- ->where("relative_url_cache", "=", implode("/", $request->arguments))
- ->viewable()
- ->find();
- if ($item->loaded()) {
- $resources = array("tags" => tag::item_tags($item));
- }
+ $tag = rest::resolve($request->url);
+ $items = array();
+ foreach ($tag->items() as $item) {
+ $items[] = url::abs_site("rest/gallery/" . $item->relative_url());
}
- return rest::success($resources);
+ return rest::reply(array("resource" => $tag->as_array(), "members" => $items));
}
static function post($request) {
- if (empty($request->arguments) || count($request->arguments) != 1 || empty($request->path)) {
- throw new Rest_Exception(400, "Bad request");
- }
- $path = $request->path;
- $tags = explode(",", $request->arguments[0]);
-
- $item = ORM::factory("item")
- ->where("relative_url_cache", "=", $path)
- ->viewable()
- ->find();
- if (!$item->loaded()) {
- throw new Kohana_404_Exception();
+ if (empty($request->params->url)) {
+ throw new Rest_Exception("Bad request", 400);
}
- if (!access::can("edit", $item)) {
- throw new Kohana_404_Exception();
- }
+ $tag = rest::resolve($request->url);
+ $item = rest::resolve($request->params->url);
+ access::required("edit", $item);
- foreach ($tags as $tag) {
- tag::add($item, $tag);
- }
- return rest::success();
+ tag::add($item, $tag->name);
+ return rest::reply(array("url" => url::abs_site("rest/tag/" . rawurlencode($tag->name))));
}
static function put($request) {
- if (empty($request->arguments[0]) || empty($request->new_name)) {
- throw new Rest_Exception(400, "Bad request");
- }
+ $tag = rest::resolve($request->url);
- $name = $request->arguments[0];
+ if (isset($request->params->remove)) {
+ if (!is_array($request->params->remove)) {
+ throw new Exception("Bad request", 400);
+ }
- $tag = ORM::factory("tag")
- ->where("name", "=", $name)
- ->find();
- if (!$tag->loaded()) {
- throw new Kohana_404_Exception();
+ foreach ($request->params->remove as $item_url) {
+ $item = rest::resolve($item_url);
+ access::required("edit", $item);
+ $tag->remove($item);
+ }
}
- $tag->name = $request->new_name;
- $tag->save();
+ if (isset($request->params->name)) {
+ $tag->name = $request->params->name;
+ }
- return rest::success();
+ $tag->save();
+ return rest::reply(array("url" => url::abs_site("rest/tag/" . rawurlencode($tag->name))));
}
static function delete($request) {
- if (empty($request->arguments[0])) {
- throw new Rest_Exception(400, "Bad request");
- }
- $tags = explode(",", $request->arguments[0]);
- if (!empty($request->path)) {
- $tag_list = ORM::factory("tag")
- ->join("items_tags", "tags.id", "items_tags.tag_id")
- ->join("items", "items.id", "items_tags.item_id")
- ->where("tags.name", "IN", $tags)
- ->where("relative_url_cache", "=", $request->path)
- ->viewable()
- ->find_all();
- } else {
- $tag_list = ORM::factory("tag")
- ->where("name", "IN", $tags)
- ->find_all();
- }
+ $tag = rest::resolve($request->url);
- foreach ($tag_list as $row) {
- $row->delete();
- };
+ if (empty($request->params->url)) {
+ // Delete the tag
+ $tag->delete();
+ return rest::reply();
+ } else {
+ // Remove an item from the tag
+ $item = rest::resolve($request->params->url);
+ $tag->remove($item);
+ $tag->save();
- tag::compact();
- return rest::success();
+ tag::compact();
+ return rest::reply(array("url" => url::abs_site("rest/tag/" . rawurlencode($tag->name))));
+ }
}
- private static function _get_items($request) {
- $tags = explode(",", $request->arguments[0]);
- $items = ORM::factory("item")
- ->select_distinct("*")
- ->join("items_tags", "items.id", "items_tags.item_id")
- ->join("tags", "tags.id", "items_tags.tag_id")
- ->where("tags.name", "IN", $tags);
- if (!empty($request->limit)) {
- $items->limit($request->limit);
- }
- if (!empty($request->offset)) {
- $items->offset($request->offset);
- }
- $resources = array();
- foreach ($items->find_all() as $item) {
- $resources[] = array("type" => $item->type,
- "has_children" => $item->children_count() > 0,
- "path" => $item->relative_url(),
- "thumb_url" => $item->thumb_url(true),
- "thumb_dimensions" => array("width" => $item->thumb_width,
- "height" => $item->thumb_height),
- "has_thumb" => $item->has_thumb(),
- "title" => $item->title);
+ static function resolve($tag_name) {
+ $tag = ORM::factory("tag")->where("name", "=", $tag_name)->find();
+ if (!$tag->loaded()) {
+ throw new Kohana_404_Exception();
}
- return $resources;
+ return $tag;
}
}
diff --git a/modules/tag/helpers/tags_rest.php b/modules/tag/helpers/tags_rest.php
new file mode 100644
index 00000000..7f0ed66a
--- /dev/null
+++ b/modules/tag/helpers/tags_rest.php
@@ -0,0 +1,48 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class tags_rest_Core {
+ static function get($request) {
+ $tags = array();
+ foreach (ORM::factory("tag")->find_all() as $tag) {
+ $tags[$tag->name] = url::abs_site("rest/tags/" . rawurlencode($tag->name));
+ }
+ return rest::reply(array("members" => $tags));
+ }
+
+ static function post($request) {
+ // @todo: what permission should be required to create a tag here?
+ // for now, require edit at the top level. Perhaps later, just require any edit perms,
+ // anywhere in the gallery?
+ access::required("edit", item::root());
+
+ if (empty($request->params->name)) {
+ throw new Rest_Exception("Bad Request: missing name", 400);
+ }
+
+ $tag = ORM::factory("tag")->where("name", "=", $request->params->name)->find();
+ if (!$tag->loaded()) {
+ $tag->name = $request->params->name;
+ $tag->count = 0;
+ $tag->save();
+ }
+
+ return rest::reply(array("url" => url::abs_site("rest/tag/" . rawurlencode($tag->name))));
+ }
+}
diff --git a/modules/tag/tests/Tag_Rest_Helper_Test.php b/modules/tag/tests/Tag_Rest_Helper_Test.php
index 514538d4..555539fd 100644
--- a/modules/tag/tests/Tag_Rest_Helper_Test.php
+++ b/modules/tag/tests/Tag_Rest_Helper_Test.php
@@ -133,7 +133,8 @@ class Tag_Rest_Helper_Test extends Unit_Test_Case {
try {
tag_rest::post($request);
} catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
+ $this->assert_equal(400, $e->getCode());
+ $this->assert_equal("Bad request", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -191,7 +192,8 @@ class Tag_Rest_Helper_Test extends Unit_Test_Case {
try {
tag_rest::put($request);
} catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
+ $this->assert_equal(400, $e->getCode());
+ $this->assert_equal("Bad request", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -202,7 +204,8 @@ class Tag_Rest_Helper_Test extends Unit_Test_Case {
try {
tag_rest::put($request);
} catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
+ $this->assert_equal(400, $e->getCode());
+ $this->assert_equal("Bad request", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
@@ -211,7 +214,8 @@ class Tag_Rest_Helper_Test extends Unit_Test_Case {
try {
tag_rest::put($request);
} catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
+ $this->assert_equal(400, $e->getCode());
+ $this->assert_equal("Bad request", $e->getMessage());
} catch (Exception $e) {
$this->assert_false(true, $e->__toString());
}
diff --git a/modules/user/controllers/admin_users.php b/modules/user/controllers/admin_users.php
index 96b86fff..bc68d154 100644
--- a/modules/user/controllers/admin_users.php
+++ b/modules/user/controllers/admin_users.php
@@ -21,12 +21,8 @@ class Admin_Users_Controller extends Admin_Controller {
public function index() {
$view = new Admin_View("admin.html");
$view->content = new View("admin_users.html");
- $view->content->users = ORM::factory("user")
- ->order_by("name", "ASC")
- ->find_all();
- $view->content->groups = ORM::factory("group")
- ->order_by("name", "ASC")
- ->find_all();
+ $view->content->users = ORM::factory("user")->order_by("name", "ASC")->find_all();
+ $view->content->groups = ORM::factory("group")->order_by("name", "ASC")->find_all();
print $view;
}
@@ -34,31 +30,32 @@ class Admin_Users_Controller extends Admin_Controller {
access::verify_csrf();
$form = $this->_get_user_add_form_admin();
- $valid = $form->validate();
- $name = $form->add_user->inputs["name"]->value;
- if ($user = user::lookup_by_name($name)) {
- $form->add_user->inputs["name"]->add_error("in_use", 1);
+ try {
+ $user = ORM::factory("user");
+ $valid = $form->validate();
+ $user->name = $form->add_user->inputs["name"]->value;
+ $user->full_name = $form->add_user->full_name->value;
+ $user->password = $form->add_user->password->value;
+ $user->email = $form->add_user->email->value;
+ $user->url = $form->edit_user->url->value;
+ $user->locale = $form->add_user->locale->value;
+ $user->admin = $form->edit_user->admin->checked;
+ $user->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ $form->add_user->inputs[$key]->add_error($error, 1);
+ }
$valid = false;
}
if ($valid) {
- $user = user::create(
- $name, $form->add_user->full_name->value, $form->add_user->password->value);
- $user->email = $form->add_user->email->value;
- $user->admin = $form->add_user->admin->checked;
-
- if ($form->add_user->locale) {
- $desired_locale = $form->add_user->locale->value;
- $user->locale = $desired_locale == "none" ? null : $desired_locale;
- }
$user->save();
module::event("user_add_form_admin_completed", $user, $form);
-
message::success(t("Created user %user_name", array("user_name" => $user->name)));
print json_encode(array("result" => "success"));
} else {
- print json_encode(array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
@@ -85,8 +82,7 @@ class Admin_Users_Controller extends Admin_Controller {
$name = $user->name;
$user->delete();
} else {
- print json_encode(array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
$message = t("Deleted user %user_name", array("user_name" => $name));
@@ -112,43 +108,34 @@ class Admin_Users_Controller extends Admin_Controller {
}
$form = $this->_get_user_edit_form_admin($user);
- $valid = $form->validate();
- if ($valid) {
- $new_name = $form->edit_user->inputs["name"]->value;
- $temp_user = user::lookup_by_name($new_name);
- if ($new_name != $user->name &&
- ($temp_user && $temp_user->id != $user->id)) {
- $form->edit_user->inputs["name"]->add_error("in_use", 1);
- $valid = false;
- } else {
- $user->name = $new_name;
- }
- }
-
- if ($valid) {
+ try {
+ $valid = $form->validate();
+ $user->name = $form->edit_user->inputs["name"]->value;
$user->full_name = $form->edit_user->full_name->value;
- if ($form->edit_user->password->value) {
- $user->password = $form->edit_user->password->value;
- }
+ $user->password = $form->edit_user->password->value;
$user->email = $form->edit_user->email->value;
$user->url = $form->edit_user->url->value;
- if ($form->edit_user->locale) {
- $desired_locale = $form->edit_user->locale->value;
- $user->locale = $desired_locale == "none" ? null : $desired_locale;
- }
-
- // An admin can change the admin status for any user but themselves
+ $user->locale = $form->edit_user->locale->value;
if ($user->id != identity::active_user()->id) {
$user->admin = $form->edit_user->admin->checked;
}
+
+ $user->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ $form->edit_user->inputs[$key]->add_error($error, 1);
+ }
+ $valid = false;
+ }
+
+ if ($valid) {
$user->save();
module::event("user_edit_form_admin_completed", $user, $form);
-
message::success(t("Changed user %user_name", array("user_name" => $user->name)));
print json_encode(array("result" => "success"));
} else {
- print json_encode(array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
@@ -193,25 +180,26 @@ class Admin_Users_Controller extends Admin_Controller {
access::verify_csrf();
$form = $this->_get_group_add_form_admin();
- $valid = $form->validate();
- if ($valid) {
- $new_name = $form->add_group->inputs["name"]->value;
- $group = group::lookup_by_name($new_name);
- if (!empty($group)) {
- $form->add_group->inputs["name"]->add_error("in_use", 1);
- $valid = false;
+ try {
+ $valid = $form->validate();
+ $group = ORM::factory("group");
+ $group->name = $form->add_group->inputs["name"]->value;
+ $group->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ $form->add_group->inputs[$key]->add_error($error, 1);
}
+ $valid = false;
}
if ($valid) {
- $group = group::create($new_name);
$group->save();
message::success(
t("Created group %group_name", array("group_name" => $group->name)));
print json_encode(array("result" => "success"));
} else {
- print json_encode(array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
@@ -232,8 +220,7 @@ class Admin_Users_Controller extends Admin_Controller {
$name = $group->name;
$group->delete();
} else {
- print json_encode(array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
$message = t("Deleted group %group_name", array("group_name" => $name));
@@ -260,19 +247,19 @@ class Admin_Users_Controller extends Admin_Controller {
}
$form = $this->_get_group_edit_form_admin($group);
- $valid = $form->validate();
-
- if ($valid) {
- $new_name = $form->edit_group->inputs["name"]->value;
- $group = group::lookup_by_name($name);
- if ($group->loaded()) {
- $form->edit_group->inputs["name"]->add_error("in_use", 1);
- $valid = false;
+ try {
+ $valid = $form->validate();
+ $group->name = $form->edit_group->inputs["name"]->value;
+ $group->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ $form->edit_group->inputs[$key]->add_error($error, 1);
}
+ $valid = false;
}
if ($valid) {
- $group->name = $form->edit_group->inputs["name"]->value;
$group->save();
message::success(
t("Changed group %group_name", array("group_name" => $group->name)));
@@ -280,8 +267,7 @@ class Admin_Users_Controller extends Admin_Controller {
} else {
message::error(
t("Failed to change group %group_name", array("group_name" => $group->name)));
- print json_encode(array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
@@ -301,7 +287,7 @@ class Admin_Users_Controller extends Admin_Controller {
$group = $form->group("edit_user")->label(t("Edit user"));
$group->input("name")->label(t("Username"))->id("g-username")->value($user->name);
$group->inputs["name"]->error_messages(
- "in_use", t("There is already a user with that username"));
+ "conflict", t("There is already a user with that username"));
$group->input("full_name")->label(t("Full name"))->id("g-fullname")->value($user->full_name);
self::_add_locale_dropdown($group, $user);
$group->password("password")->label(t("Password"))->id("g-password");
@@ -310,10 +296,6 @@ class Admin_Users_Controller extends Admin_Controller {
$group->input("email")->label(t("Email"))->id("g-email")->value($user->email);
$group->input("url")->label(t("URL"))->id("g-url")->value($user->url);
$group->checkbox("admin")->label(t("Admin"))->id("g-admin")->checked($user->admin);
- $form->add_rules_from($user);
- $minimum_length = module::get_var("user", "mininum_password_length", 5);
- $form->edit_user->password
- ->rules($minimum_length ? "length[$minimum_length, 40]" : "length[40]");
module::event("user_edit_form_admin", $user, $form);
$group->submit("")->value(t("Modify User"));
@@ -324,7 +306,7 @@ class Admin_Users_Controller extends Admin_Controller {
$form = new Forge("admin/users/add_user", "", "post", array("id" => "g-add-user-form"));
$group = $form->group("add_user")->label(t("Add user"));
$group->input("name")->label(t("Username"))->id("g-username")
- ->error_messages("in_use", t("There is already a user with that username"));
+ ->error_messages("conflict", t("There is already a user with that username"));
$group->input("full_name")->label(t("Full name"))->id("g-fullname");
$group->password("password")->label(t("Password"))->id("g-password");
$group->password("password2")->label(t("Confirm password"))->id("g-password2")
@@ -333,11 +315,6 @@ class Admin_Users_Controller extends Admin_Controller {
$group->input("url")->label(t("URL"))->id("g-url");
self::_add_locale_dropdown($group);
$group->checkbox("admin")->label(t("Admin"))->id("g-admin");
- $form->add_rules_from(ORM::factory("user"));
-
- $minimum_length = module::get_var("user", "mininum_password_length", 5);
- $form->add_user->password
- ->rules($minimum_length ? "required|length[$minimum_length, 40]" : "length[40]");
module::event("user_add_form_admin", $user, $form);
$group->submit("")->value(t("Add user"));
@@ -349,15 +326,14 @@ class Admin_Users_Controller extends Admin_Controller {
foreach ($locales as $locale => $display_name) {
$locales[$locale] = SafeString::of_safe_html($display_name);
}
- if (count($locales) > 1) {
- // Put "none" at the first position in the array
- $locales = array_merge(array("" => t("« none »")), $locales);
- $selected_locale = ($user && $user->locale) ? $user->locale : "";
- $form->dropdown("locale")
- ->label(t("Language Preference"))
- ->options($locales)
- ->selected($selected_locale);
- }
+
+ // Put "none" at the first position in the array
+ $locales = array_merge(array("" => t("« none »")), $locales);
+ $selected_locale = ($user && $user->locale) ? $user->locale : "";
+ $form->dropdown("locale")
+ ->label(t("Language Preference"))
+ ->options($locales)
+ ->selected($selected_locale);
}
private function _get_user_delete_form_admin($user) {
@@ -375,9 +351,8 @@ class Admin_Users_Controller extends Admin_Controller {
$form_group = $form->group("edit_group")->label(t("Edit group"));
$form_group->input("name")->label(t("Name"))->id("g-name")->value($group->name);
$form_group->inputs["name"]->error_messages(
- "in_use", t("There is already a group with that name"));
+ "conflict", t("There is already a group with that name"));
$form_group->submit("")->value(t("Save"));
- $form->add_rules_from($group);
return $form;
}
@@ -386,9 +361,8 @@ class Admin_Users_Controller extends Admin_Controller {
$form_group = $form->group("add_group")->label(t("Add group"));
$form_group->input("name")->label(t("Name"))->id("g-name");
$form_group->inputs["name"]->error_messages(
- "in_use", t("There is already a group with that name"));
+ "conflict", t("There is already a group with that name"));
$form_group->submit("")->value(t("Add group"));
- $form->add_rules_from(ORM::factory("group"));
return $form;
}
diff --git a/modules/user/controllers/users.php b/modules/user/controllers/users.php
index ca218393..b3f39b47 100644
--- a/modules/user/controllers/users.php
+++ b/modules/user/controllers/users.php
@@ -26,34 +26,36 @@ class Users_Controller extends Controller {
}
$form = $this->_get_edit_form($user);
- $valid = $form->validate();
- if ($valid) {
+ try {
+ $valid = $form->validate();
$user->full_name = $form->edit_user->full_name->value;
- if ($form->edit_user->password->value) {
- $user->password = $form->edit_user->password->value;
- }
+ $user->password = $form->edit_user->password->value;
$user->email = $form->edit_user->email->value;
$user->url = $form->edit_user->url->value;
- if ($form->edit_user->locale) {
- $desired_locale = $form->edit_user->locale->value;
- $new_locale = $desired_locale == "none" ? null : $desired_locale;
- if ($new_locale != $user->locale) {
- // Delete the session based locale preference
- setcookie("g_locale", "", time() - 24 * 3600, "/");
- }
- $user->locale = $new_locale;
+ $user->locale = $form->edit_user->locale->value;
+ $user->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ $form->edit_user->inputs[$key]->add_error($error, 1);
+ }
+ $valid = false;
+ }
+
+ if ($valid) {
+ if ($user->original()->locale != $user->locale) {
+ // Delete the session based locale preference
+ setcookie("g_locale", "", time() - 24 * 3600, "/");
}
+
$user->save();
module::event("user_edit_form_completed", $user, $form);
-
message::success(t("User information updated."));
print json_encode(
array("result" => "success",
"resource" => url::site("users/{$user->id}")));
} else {
- print json_encode(
- array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
@@ -78,11 +80,6 @@ class Users_Controller extends Controller {
->matches($group->password);
$group->input("email")->label(t("Email"))->id("g-email")->value($user->email);
$group->input("url")->label(t("URL"))->id("g-url")->value($user->url);
- $form->add_rules_from($user);
-
- $minimum_length = module::get_var("user", "mininum_password_length", 5);
- $form->edit_user->password
- ->rules($minimum_length ? "length[$minimum_length, 40]" : "length[40]");
module::event("user_edit_form", $user, $form);
$group->submit("")->value(t("Save"));
@@ -95,14 +92,13 @@ class Users_Controller extends Controller {
foreach ($locales as $locale => $display_name) {
$locales[$locale] = SafeString::of_safe_html($display_name);
}
- if (count($locales) > 1) {
- // Put "none" at the first position in the array
- $locales = array_merge(array("" => t("« none »")), $locales);
- $selected_locale = ($user && $user->locale) ? $user->locale : "";
- $form->dropdown("locale")
- ->label(t("Language Preference"))
- ->options($locales)
- ->selected($selected_locale);
- }
+
+ // Put "none" at the first position in the array
+ $locales = array_merge(array("" => t("« none »")), $locales);
+ $selected_locale = ($user && $user->locale) ? $user->locale : "";
+ $form->dropdown("locale")
+ ->label(t("Language Preference"))
+ ->options($locales)
+ ->selected($selected_locale);
}
}
diff --git a/modules/user/helpers/group.php b/modules/user/helpers/group.php
index 2ada0ac1..38124b0d 100644
--- a/modules/user/helpers/group.php
+++ b/modules/user/helpers/group.php
@@ -25,23 +25,6 @@
*/
class group_Core {
/**
- * Create a new group.
- *
- * @param string $name
- * @return Group_Definition the group object
- */
- static function create($name) {
- $group = ORM::factory("group")->where("name", "=", $name)->find();
- if ($group->loaded()) {
- throw new Exception("@todo GROUP_ALREADY_EXISTS $name");
- }
-
- $group->name = $name;
- $group->save();
- return $group;
- }
-
- /**
* The group of all possible visitors. This includes the guest user.
*
* @return Group_Definition the group object
diff --git a/modules/user/helpers/user.php b/modules/user/helpers/user.php
index e092aecc..3561021f 100644
--- a/modules/user/helpers/user.php
+++ b/modules/user/helpers/user.php
@@ -36,32 +36,6 @@ class user_Core {
}
/**
- * Create a new user.
- *
- * @param string $name
- * @param string $full_name
- * @param string $password
- * @return User_Model
- */
- static function create($name, $full_name, $password) {
- $user = ORM::factory("user")->where("name", "=", $name)->find();
- if ($user->loaded()) {
- throw new Exception("@todo USER_ALREADY_EXISTS $name");
- }
-
- $user->name = $name;
- $user->full_name = $full_name;
- $user->password = $password;
-
- // Required groups
- $user->add(group::everybody());
- $user->add(group::registered_users());
-
- $user->save();
- return $user;
- }
-
- /**
* Is the password provided correct?
*
* @param user User Model
diff --git a/modules/user/helpers/user_installer.php b/modules/user/helpers/user_installer.php
index 0cba502f..f7e3b60b 100644
--- a/modules/user/helpers/user_installer.php
+++ b/modules/user/helpers/user_installer.php
@@ -53,21 +53,40 @@ class user_installer {
UNIQUE KEY(`user_id`, `group_id`))
DEFAULT CHARSET=utf8;");
- $everybody = group::create("Everybody");
+ $everybody = ORM::factory("group");
+ $everybody->name = "Everybody";
$everybody->special = true;
$everybody->save();
- $registered = group::create("Registered Users");
+ $registered = ORM::factory("group");
+ $registered->name = "Registered Users";
$registered->special = true;
$registered->save();
- $guest = user::create("guest", "Guest User", "");
- $guest->guest = true;
- $guest->remove($registered);
+ // Avoid ORM to sidestep validation.
+ db::build()->insert(
+ "users",
+ array("name" => "guest",
+ "full_name" => "Guest User",
+ "password" => "",
+ "guest" => true))
+ ->execute();
+
+ $guest = ORM::factory("user")->where("id", "=", 1)->find();
+ $guest->add($everybody);
$guest->save();
- $admin = user::create("admin", "Gallery Administrator", "admin");
- $admin->admin = true;
+ db::build()->insert(
+ "users",
+ array("name" => "admin",
+ "full_name" => "Gallery Administrator",
+ "password" => "admin",
+ "admin" => true))
+ ->execute();
+
+ $admin = ORM::factory("user")->where("id", "=", 2)->find();
+ $admin->add($everybody);
+ $admin->add($registered);
$admin->save();
$current_provider = module::get_var("gallery", "identity_provider");
diff --git a/modules/user/libraries/drivers/IdentityProvider/Gallery.php b/modules/user/libraries/drivers/IdentityProvider/Gallery.php
index d874512c..666f185f 100644
--- a/modules/user/libraries/drivers/IdentityProvider/Gallery.php
+++ b/modules/user/libraries/drivers/IdentityProvider/Gallery.php
@@ -38,8 +38,13 @@ class IdentityProvider_Gallery_Driver implements IdentityProvider_Driver {
/**
* @see IdentityProvider_Driver::create_user.
*/
- public function create_user($name, $full_name, $password) {
- return user::create($name, $full_name, $password);
+ public function create_user($name, $full_name, $password, $email) {
+ $user = ORM::factory("user");
+ $user->name = $name;
+ $user->full_name = $full_name;
+ $user->password = $password;
+ $user->email = $email;
+ return $user->save();
}
/**
@@ -91,7 +96,9 @@ class IdentityProvider_Gallery_Driver implements IdentityProvider_Driver {
* @see IdentityProvider_Driver::create_group.
*/
public function create_group($name) {
- return group::create($name);
+ $group = ORM::factory("group");
+ $group->name = $name;
+ return $group->save();
}
/**
diff --git a/modules/user/models/group.php b/modules/user/models/group.php
index 10f6f4b3..c00bf5c9 100644
--- a/modules/user/models/group.php
+++ b/modules/user/models/group.php
@@ -20,9 +20,6 @@
class Group_Model extends ORM implements Group_Definition {
protected $has_and_belongs_to_many = array("users");
- var $form_rules = array(
- "name" => "required|length[4,255]");
-
/**
* @see ORM::delete()
*/
@@ -37,18 +34,44 @@ class Group_Model extends ORM implements Group_Definition {
return $this->users->find_all();
}
- public function save() {
- if (!$this->loaded()) {
- $created = 1;
+ /**
+ * Specify our rules here so that we have access to the instance of this model.
+ */
+ public function validate($array=null) {
+ // validate() is recursive, only modify the rules on the outermost call.
+ if (!$array) {
+ $this->rules = array(
+ "name" => array("rules" => array("required", "length[4,255]"),
+ "callbacks" => array(array($this, "valid_name"))));
}
- $original = clone $this->original();
- parent::save();
- if (isset($created)) {
+ parent::validate($array);
+ }
+
+ public function save() {
+ if (!$this->loaded()) {
+ // New group
+ parent::save();
module::event("group_created", $this);
} else {
+ // Updated group
+ $original = clone $this->original();
+ parent::save();
module::event("group_updated", $original, $this);
}
+
return $this;
}
+
+ /**
+ * Validate the user name. Make sure there are no conflicts.
+ */
+ public function valid_name(Validation $v, $field) {
+ if (db::build()->from("groups")
+ ->where("name", "=", $this->name)
+ ->where("id", "<>", $this->id)
+ ->count_records() == 1) {
+ $v->add_error("name", "conflict");
+ }
+ }
} \ No newline at end of file
diff --git a/modules/user/models/user.php b/modules/user/models/user.php
index edba2a2c..451b5ffb 100644
--- a/modules/user/models/user.php
+++ b/modules/user/models/user.php
@@ -19,14 +19,7 @@
*/
class User_Model extends ORM implements User_Definition {
protected $has_and_belongs_to_many = array("groups");
-
- var $form_rules = array(
- "name" => "required|length[1,32]",
- "full_name" => "length[0,255]",
- "email" => "required|valid_email|length[1,255]",
- "password" => "length[1,40]",
- "url" => "valid_url",
- "locale" => "length[2,10]");
+ protected $password_length = null;
public function __set($column, $value) {
switch ($column) {
@@ -35,6 +28,7 @@ class User_Model extends ORM implements User_Definition {
break;
case "password":
+ $this->password_length = strlen($value);
$value = user::hash_password($value);
break;
}
@@ -65,18 +59,48 @@ class User_Model extends ORM implements User_Definition {
return $this->groups->find_all();
}
+ /**
+ * Specify our rules here so that we have access to the instance of this model.
+ */
+ public function validate($array=null) {
+ // validate() is recursive, only modify the rules on the outermost call.
+ if (!$array) {
+ $this->rules = array(
+ "admin" => array("callbacks" => array(array($this, "valid_admin"))),
+ "email" => array("rules" => array("length[1,255]", "required", "valid::email")),
+ "full_name" => array("rules" => array("length[0,255]")),
+ "locale" => array("rules" => array("length[2,10]")),
+ "name" => array("rules" => array("length[1,32]", "required"),
+ "callbacks" => array(array($this, "valid_name"))),
+ "password" => array("callbacks" => array(array($this, "valid_password"))),
+ "url" => array("rules" => array("valid::url")),
+ );
+ }
+
+ parent::validate($array);
+ }
+
+ /**
+ * Handle any business logic necessary to create or update a user.
+ * @see ORM::save()
+ *
+ * @return ORM User_Model
+ */
public function save() {
if (!$this->loaded()) {
- $created = 1;
- }
+ // New user
+ $this->add(group::everybody());
+ $this->add(group::registered_users());
- $original = clone $this->original();
- parent::save();
- if (isset($created)) {
+ parent::save();
module::event("user_created", $this);
} else {
+ // Updated user
+ $original = clone $this->original();
+ parent::save();
module::event("user_updated", $original, $this);
}
+
return $this;
}
@@ -88,4 +112,37 @@ class User_Model extends ORM implements User_Definition {
public function display_name() {
return empty($this->full_name) ? $this->name : $this->full_name;
}
+
+ /**
+ * Validate the user name. Make sure there are no conflicts.
+ */
+ public function valid_name(Validation $v, $field) {
+ if (db::build()->from("users")
+ ->where("name", "=", $this->name)
+ ->where("id", "<>", $this->id)
+ ->count_records() == 1) {
+ $v->add_error("name", "conflict");
+ }
+ }
+
+ /**
+ * Validate the password.
+ */
+ public function valid_password(Validation $v, $field) {
+ if (!$this->loaded() || $this->password_length) {
+ $minimum_length = module::get_var("user", "mininum_password_length", 5);
+ if ($this->password_length < $minimum_length) {
+ $v->add_error("password", "min_length");
+ }
+ }
+ }
+
+ /**
+ * Validate the admin bit.
+ */
+ public function valid_admin(Validation $v, $field) {
+ if ($this->id == identity::active_user()->id && !$this->admin) {
+ $v->add_error("admin", "locked");
+ }
+ }
}
diff --git a/modules/user/views/user_form.html.php b/modules/user/views/user_form.html.php
index 039ae8a5..4ce2b532 100644
--- a/modules/user/views/user_form.html.php
+++ b/modules/user/views/user_form.html.php
@@ -1,5 +1,5 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
-<script type="text/javascript">
+<script type="text/javascript">
$("form").ready(function(){
$('input[name="password"]').user_password_strength();
});
diff --git a/modules/watermark/controllers/admin_watermarks.php b/modules/watermark/controllers/admin_watermarks.php
index 2a1d5f60..f535ad08 100644
--- a/modules/watermark/controllers/admin_watermarks.php
+++ b/modules/watermark/controllers/admin_watermarks.php
@@ -52,9 +52,7 @@ class Admin_Watermarks_Controller extends Admin_Controller {
array("result" => "success",
"location" => url::site("admin/watermarks")));
} else {
- print json_encode(
- array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
@@ -84,9 +82,7 @@ class Admin_Watermarks_Controller extends Admin_Controller {
array("result" => "success",
"location" => url::site("admin/watermarks")));
} else {
- print json_encode(
- array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}
@@ -127,9 +123,7 @@ class Admin_Watermarks_Controller extends Admin_Controller {
array("result" => "success",
"location" => url::site("admin/watermarks")));
} else {
- print json_encode(
- array("result" => "error",
- "form" => $form->__toString()));
+ print json_encode(array("result" => "error", "form" => (string) $form));
}
}