summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Kinkade <nkinkade@nkinka.de>2010-02-02 02:59:20 +0000
committerNathan Kinkade <nkinkade@nkinka.de>2010-02-02 02:59:20 +0000
commit9d0927dda936756f1f5003813f437d714fe481f8 (patch)
treefe1b887345b37387ab0ddcfd78bf344f6150b6cc
parenta6f794c20dc3592bcaef17c622413c1b670a20d8 (diff)
parent43985ea2fb137aa7d532617271e37d7c20def3c5 (diff)
Merge branch 'master' of git://github.com/gallery/gallery3
-rw-r--r--index.php3
-rwxr-xr-xinstaller/init_var.php3
-rw-r--r--installer/install.sql19
-rw-r--r--lib/flowplayer.js155
-rw-r--r--modules/akismet/controllers/admin_akismet.php11
-rw-r--r--modules/akismet/helpers/akismet.php17
-rw-r--r--modules/akismet/tests/Akismet_Helper_Test.php45
-rw-r--r--modules/comment/controllers/admin_comments.php1
-rw-r--r--modules/comment/controllers/comments.php57
-rw-r--r--modules/comment/helpers/comment.php61
-rw-r--r--modules/comment/helpers/comment_rss.php1
-rw-r--r--modules/comment/models/comment.php92
-rw-r--r--modules/comment/tests/Comment_Event_Test.php17
-rw-r--r--modules/comment/tests/Comment_Helper_Test.php34
-rw-r--r--modules/comment/tests/Comment_Model_Test.php19
-rw-r--r--modules/comment/views/admin_block_recent_comments.html.php6
-rw-r--r--modules/comment/views/comment.html.php6
-rw-r--r--modules/comment/views/comments.html.php6
-rw-r--r--modules/digibug/controllers/digibug.php4
-rw-r--r--modules/digibug/tests/Digibug_Controller_Test.php38
-rw-r--r--modules/digibug/views/digibug_form.html.php8
-rw-r--r--modules/exif/helpers/exif_task.php2
-rw-r--r--modules/exif/tests/Exif_Test.php9
-rw-r--r--modules/forge/libraries/Form_Group.php2
-rw-r--r--modules/g2_import/controllers/admin_g2_import.php5
-rw-r--r--modules/g2_import/controllers/g2.php2
-rw-r--r--modules/g2_import/helpers/g2_import.php93
-rw-r--r--modules/g2_import/helpers/g2_import_installer.php2
-rw-r--r--modules/g2_import/helpers/g2_import_task.php10
-rw-r--r--modules/g2_import/views/admin_g2_import.html.php2
-rw-r--r--modules/gallery/config/locale.php6
-rw-r--r--modules/gallery/config/routes.php4
-rw-r--r--modules/gallery/controllers/admin_dashboard.php2
-rw-r--r--modules/gallery/controllers/admin_maintenance.php4
-rw-r--r--modules/gallery/controllers/admin_modules.php1
-rw-r--r--modules/gallery/controllers/albums.php90
-rw-r--r--modules/gallery/controllers/combined.php2
-rw-r--r--modules/gallery/controllers/file_proxy.php2
-rw-r--r--modules/gallery/controllers/login.php11
-rw-r--r--modules/gallery/controllers/movies.php54
-rw-r--r--modules/gallery/controllers/packager.php9
-rw-r--r--modules/gallery/controllers/photos.php54
-rw-r--r--modules/gallery/controllers/quick.php1
-rw-r--r--modules/gallery/controllers/simple_uploader.php47
-rw-r--r--modules/gallery/controllers/user_profile.php4
-rw-r--r--modules/gallery/helpers/MY_url.php4
-rw-r--r--modules/gallery/helpers/access.php37
-rw-r--r--modules/gallery/helpers/album.php106
-rw-r--r--modules/gallery/helpers/auth.php55
-rw-r--r--modules/gallery/helpers/gallery_block.php2
-rw-r--r--modules/gallery/helpers/gallery_event.php34
-rw-r--r--modules/gallery/helpers/gallery_installer.php97
-rw-r--r--modules/gallery/helpers/gallery_rest.php248
-rw-r--r--modules/gallery/helpers/gallery_rss.php1
-rw-r--r--modules/gallery/helpers/gallery_task.php28
-rw-r--r--modules/gallery/helpers/graphics.php3
-rw-r--r--modules/gallery/helpers/identity.php10
-rw-r--r--modules/gallery/helpers/item.php40
-rw-r--r--modules/gallery/helpers/item_rest.php176
-rw-r--r--modules/gallery/helpers/l10n_client.php1
-rw-r--r--modules/gallery/helpers/locales.php4
-rw-r--r--modules/gallery/helpers/module.php3
-rw-r--r--modules/gallery/helpers/movie.php128
-rw-r--r--modules/gallery/helpers/photo.php137
-rw-r--r--modules/gallery/helpers/task.php11
-rw-r--r--modules/gallery/libraries/Form_Script.php4
-rw-r--r--modules/gallery/libraries/IdentityProvider.php6
-rw-r--r--modules/gallery/libraries/InPlaceEdit.php1
-rw-r--r--modules/gallery/libraries/MY_Database.php2
-rw-r--r--modules/gallery/libraries/MY_Forge.php14
-rw-r--r--modules/gallery/libraries/MY_Kohana_Exception.php7
-rw-r--r--modules/gallery/libraries/MY_ORM.php34
-rw-r--r--modules/gallery/libraries/MY_View.php2
-rw-r--r--modules/gallery/libraries/ORM_MPTT.php116
-rw-r--r--modules/gallery/libraries/drivers/IdentityProvider.php3
-rw-r--r--modules/gallery/models/failed_login.php20
-rw-r--r--modules/gallery/models/item.php543
-rw-r--r--modules/gallery/models/task.php4
-rw-r--r--modules/gallery/module.info3
-rw-r--r--modules/gallery/tests/Access_Helper_Test.php125
-rw-r--r--modules/gallery/tests/Album_Helper_Test.php88
-rw-r--r--modules/gallery/tests/Albums_Controller_Test.php38
-rw-r--r--modules/gallery/tests/Cache_Test.php2
-rw-r--r--modules/gallery/tests/Controller_Auth_Test.php2
-rw-r--r--modules/gallery/tests/Database_Test.php10
-rw-r--r--modules/gallery/tests/Dir_Helper_Test.php2
-rw-r--r--modules/gallery/tests/DrawForm_Test.php2
-rw-r--r--modules/gallery/tests/File_Structure_Test.php4
-rw-r--r--modules/gallery/tests/Gallery_I18n_Test.php2
-rw-r--r--modules/gallery/tests/Gallery_Installer_Test.php2
-rw-r--r--modules/gallery/tests/Gallery_Rest_Helper_Test.php277
-rw-r--r--modules/gallery/tests/Html_Helper_Test.php2
-rw-r--r--modules/gallery/tests/Item_Helper_Test.php33
-rw-r--r--modules/gallery/tests/Item_Model_Test.php301
-rw-r--r--modules/gallery/tests/Item_Rest_Helper_Test.php241
-rw-r--r--modules/gallery/tests/Locales_Helper_Test.php2
-rw-r--r--modules/gallery/tests/Menu_Test.php2
-rw-r--r--modules/gallery/tests/Movie_Helper_Test.php56
-rw-r--r--modules/gallery/tests/ORM_MPTT_Test.php156
-rw-r--r--modules/gallery/tests/Photo_Helper_Test.php130
-rw-r--r--modules/gallery/tests/Photos_Controller_Test.php30
-rw-r--r--modules/gallery/tests/SafeString_Test.php2
-rw-r--r--modules/gallery/tests/Sendmail_Test.php2
-rw-r--r--modules/gallery/tests/Url_Security_Test.php2
-rw-r--r--modules/gallery/tests/Var_Test.php2
-rw-r--r--modules/gallery/tests/Xss_Security_Test.php2
-rw-r--r--modules/gallery/tests/controller_auth_data.txt6
-rw-r--r--modules/gallery/tests/xss_data.txt34
-rw-r--r--modules/gallery/views/admin_block_log_entries.html.php4
-rw-r--r--modules/gallery/views/admin_modules.html.php4
-rw-r--r--modules/gallery/views/admin_modules_confirm.html.php4
-rw-r--r--modules/gallery/views/form_uploadify.html.php2
-rw-r--r--modules/gallery/views/in_place_edit.html.php9
-rw-r--r--modules/gallery/views/kohana/error.php3
-rw-r--r--modules/gallery/views/user_languages_block.html.php2
-rw-r--r--modules/gallery/views/user_profile.html.php3
-rw-r--r--modules/gallery/views/user_profile_info.html.php6
-rw-r--r--modules/gallery_unit_test/controllers/gallery_unit_test.php12
-rw-r--r--modules/gallery_unit_test/helpers/test.php85
-rw-r--r--modules/gallery_unit_test/libraries/Gallery_Unit_Test_Case.php36
-rw-r--r--modules/gallery_unit_test/views/kohana/error.php6
-rw-r--r--modules/gallery_unit_test/views/kohana_error_page.php18
-rw-r--r--modules/gallery_unit_test/views/kohana_unit_test_cli.php6
-rw-r--r--modules/image_block/helpers/image_block_block.php35
-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/organize/controllers/organize.php10
-rw-r--r--modules/recaptcha/controllers/admin_recaptcha.php2
-rw-r--r--modules/recaptcha/helpers/recaptcha.php40
-rw-r--r--modules/rest/controllers/rest.php83
-rw-r--r--modules/rest/helpers/rest.php158
-rw-r--r--modules/rest/libraries/Rest_Exception.php20
-rw-r--r--modules/rest/tests/Rest_Controller_Test.php249
-rw-r--r--modules/rest/views/user_profile_rest.html.php2
-rw-r--r--modules/search/helpers/search.php3
-rw-r--r--modules/server_add/controllers/server_add.php29
-rw-r--r--modules/tag/controllers/admin_tags.php7
-rw-r--r--modules/tag/controllers/tags.php6
-rw-r--r--modules/tag/helpers/item_tags_rest.php64
-rw-r--r--modules/tag/helpers/tag.php29
-rw-r--r--modules/tag/helpers/tag_event.php12
-rw-r--r--modules/tag/helpers/tag_item_rest.php50
-rw-r--r--modules/tag/helpers/tag_items_rest.php65
-rw-r--r--modules/tag/helpers/tag_rest.php161
-rw-r--r--modules/tag/helpers/tag_rss.php2
-rw-r--r--modules/tag/helpers/tags_rest.php60
-rw-r--r--modules/tag/models/tag.php2
-rw-r--r--modules/tag/tests/Tag_Item_Rest_Helper_Test.php70
-rw-r--r--modules/tag/tests/Tag_Rest_Helper_Test.php300
-rw-r--r--modules/tag/tests/Tag_Test.php23
-rw-r--r--modules/tag/tests/Tags_Rest_Helper_Test.php71
-rw-r--r--modules/user/controllers/admin_users.php166
-rw-r--r--modules/user/controllers/users.php72
-rw-r--r--modules/user/helpers/group.php17
-rw-r--r--modules/user/helpers/user.php26
-rw-r--r--modules/user/helpers/user_installer.php34
-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.php104
-rw-r--r--modules/user/module.info2
-rw-r--r--modules/user/tests/No_Direct_ORM_Access_Test.php2
-rw-r--r--modules/user/tests/User_Groups_Test.php29
-rw-r--r--modules/user/tests/User_Installer_Test.php2
-rw-r--r--modules/user/views/user_form.html.php2
-rw-r--r--modules/watermark/controllers/admin_watermarks.php12
-rw-r--r--modules/watermark/helpers/watermark_installer.php2
166 files changed, 3464 insertions, 3349 deletions
diff --git a/index.php b/index.php
index 8bfbbb54..1816d7fa 100644
--- a/index.php
+++ b/index.php
@@ -27,7 +27,8 @@ version_compare(PHP_VERSION, "5.2.3", "<") and
// Gallery requires short_tags to be on
!ini_get("short_open_tag") and exit("Gallery requires short_open_tag to be on.");
-// Set the error reporting level. Use E_ALL unless you have a special need.
+// Suppress errors. For information on how to debug Gallery 3, see:
+// http://codex.gallery2.org/Gallery3:FAQ#How_do_I_see_debug_information.3F
error_reporting(0);
// Disabling display_errors will effectively disable Kohana error display
diff --git a/installer/init_var.php b/installer/init_var.php
index c010888c..353665a3 100755
--- a/installer/init_var.php
+++ b/installer/init_var.php
@@ -7,3 +7,6 @@
!file_exists(VARPATH . "thumbs") && mkdir(VARPATH . "thumbs");
!file_exists(VARPATH . "tmp") && mkdir(VARPATH . "tmp");
!file_exists(VARPATH . "uploads") && mkdir(VARPATH . "uploads");
+file_put_contents(VARPATH . "logs/.htaccess", base64_decode("RGlyZWN0b3J5SW5kZXggLmh0YWNjZXNzClNldEhhbmRsZXIgR2FsbGVyeV9TZWN1cml0eV9Eb19Ob3RfUmVtb3ZlCk9wdGlvbnMgTm9uZQo8SWZNb2R1bGUgbW9kX3Jld3JpdGUuYz4KUmV3cml0ZUVuZ2luZSBvZmYKPC9JZk1vZHVsZT4KT3JkZXIgYWxsb3csZGVueQpEZW55IGZyb20gYWxsCg=="));
+file_put_contents(VARPATH . "tmp/.htaccess", base64_decode("RGlyZWN0b3J5SW5kZXggLmh0YWNjZXNzClNldEhhbmRsZXIgR2FsbGVyeV9TZWN1cml0eV9Eb19Ob3RfUmVtb3ZlCk9wdGlvbnMgTm9uZQo8SWZNb2R1bGUgbW9kX3Jld3JpdGUuYz4KUmV3cml0ZUVuZ2luZSBvZmYKPC9JZk1vZHVsZT4KT3JkZXIgYWxsb3csZGVueQpEZW55IGZyb20gYWxsCg=="));
+file_put_contents(VARPATH . "uploads/.htaccess", base64_decode("RGlyZWN0b3J5SW5kZXggLmh0YWNjZXNzClNldEhhbmRsZXIgR2FsbGVyeV9TZWN1cml0eV9Eb19Ob3RfUmVtb3ZlCk9wdGlvbnMgTm9uZQo8SWZNb2R1bGUgbW9kX3Jld3JpdGUuYz4KUmV3cml0ZUVuZ2luZSBvZmYKPC9JZk1vZHVsZT4KT3JkZXIgYWxsb3csZGVueQpEZW55IGZyb20gYWxsCg=="));
diff --git a/installer/install.sql b/installer/install.sql
index 95a57d86..20b632fa 100644
--- a/installer/install.sql
+++ b/installer/install.sql
@@ -74,6 +74,17 @@ CREATE TABLE {comments} (
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
SET character_set_client = @saved_cs_client;
+DROP TABLE IF EXISTS {failed_logins};
+SET @saved_cs_client = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE {failed_logins} (
+ `id` int(9) NOT NULL auto_increment,
+ `count` int(9) NOT NULL,
+ `name` varchar(255) NOT NULL,
+ `time` int(9) NOT NULL,
+ PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8;
+SET character_set_client = @saved_cs_client;
DROP TABLE IF EXISTS {graphics_rules};
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
@@ -228,7 +239,7 @@ CREATE TABLE {modules} (
UNIQUE KEY `name` (`name`)
) AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
SET character_set_client = @saved_cs_client;
-INSERT INTO {modules} VALUES (1,1,'gallery',21);
+INSERT INTO {modules} VALUES (1,1,'gallery',25);
INSERT INTO {modules} VALUES (2,1,'user',2);
INSERT INTO {modules} VALUES (3,1,'comment',2);
INSERT INTO {modules} VALUES (4,1,'organize',1);
@@ -355,7 +366,7 @@ CREATE TABLE {users} (
) AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
SET character_set_client = @saved_cs_client;
INSERT INTO {users} VALUES (1,'guest','Guest User','',0,0,NULL,0,1,NULL,NULL,NULL);
-INSERT INTO {users} VALUES (2,'admin','Gallery Administrator','',0,0,NULL,1,0,NULL,NULL,NULL);
+INSERT INTO {users} VALUES (2,'admin','Gallery Administrator','',0,0,'unknown@unknown.com',1,0,NULL,NULL,NULL);
DROP TABLE IF EXISTS {vars};
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
@@ -366,7 +377,7 @@ CREATE TABLE {vars} (
`value` text,
PRIMARY KEY (`id`),
UNIQUE KEY `module_name` (`module_name`,`name`)
-) AUTO_INCREMENT=37 DEFAULT CHARSET=utf8;
+) AUTO_INCREMENT=39 DEFAULT CHARSET=utf8;
SET character_set_client = @saved_cs_client;
INSERT INTO {vars} VALUES (NULL,'gallery','active_site_theme','wind');
INSERT INTO {vars} VALUES (NULL,'gallery','active_admin_theme','admin_wind');
@@ -385,8 +396,8 @@ INSERT INTO {vars} VALUES (NULL,'gallery','date_time_format','Y-M-d H:i:s');
INSERT INTO {vars} VALUES (NULL,'gallery','date_format','Y-M-d');
INSERT INTO {vars} VALUES (NULL,'gallery','blocks_dashboard_center','a:3:{i:6;a:2:{i:0;s:7:\"gallery\";i:1;s:7:\"welcome\";}i:7;a:2:{i:0;s:7:\"gallery\";i:1;s:12:\"photo_stream\";}i:8;a:2:{i:0;s:7:\"gallery\";i:1;s:11:\"log_entries\";}}');
INSERT INTO {vars} VALUES (NULL,'gallery','choose_default_tookit','1');
+INSERT INTO {vars} VALUES (NULL,'gallery','identity_provider','user');
INSERT INTO {vars} VALUES (NULL,'user','mininum_password_length','5');
INSERT INTO {vars} VALUES (NULL,'comment','spam_caught','0');
-INSERT INTO {vars} VALUES (NULL,'gallery','identity_provider','user');
INSERT INTO {vars} VALUES (NULL,'gallery','blocks_site_sidebar','a:3:{i:9;a:2:{i:0;s:4:\"info\";i:1;s:8:\"metadata\";}i:10;a:2:{i:0;s:3:\"rss\";i:1;s:9:\"rss_feeds\";}i:11;a:2:{i:0;s:3:\"tag\";i:1;s:3:\"tag\";}}');
INSERT INTO {vars} VALUES (NULL,'slideshow','max_scale','0');
diff --git a/lib/flowplayer.js b/lib/flowplayer.js
index b1c33150..d4b619c3 100644
--- a/lib/flowplayer.js
+++ b/lib/flowplayer.js
@@ -1,24 +1,131 @@
-/**
- * flowplayer.js 3.0.5. The Flowplayer API
- *
- * Copyright 2009 Flowplayer Oy
- *
- * This file is part of Flowplayer.
- *
- * Flowplayer 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 3 of the License, or
- * (at your option) any later version.
- *
- * Flowplayer 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 Flowplayer. If not, see <http://www.gnu.org/licenses/>.
- *
- * Version: 3.0.5 - Tue Feb 03 2009 13:14:17 GMT-0000 (GMT+00:00)
- */
-(function(){function log(args){console.log("$f.fireEvent",[].slice.call(args));}function clone(obj){if(!obj||typeof obj!='object'){return obj;}var temp=new obj.constructor();for(var key in obj){if(obj.hasOwnProperty(key)){temp[key]=clone(obj[key]);}}return temp;}function each(obj,fn){if(!obj){return;}var name,i=0,length=obj.length;if(length===undefined){for(name in obj){if(fn.call(obj[name],name,obj[name])===false){break;}}}else{for(var value=obj[0];i<length&&fn.call(value,i,value)!==false;value=obj[++i]){}}return obj;}function el(id){return document.getElementById(id);}function extend(to,from,skipFuncs){if(to&&from){each(from,function(name,value){if(!skipFuncs||typeof value!='function'){to[name]=value;}});}}function select(query){var index=query.indexOf(".");if(index!=-1){var tag=query.substring(0,index)||"*";var klass=query.substring(index+1,query.length);var els=[];each(document.getElementsByTagName(tag),function(){if(this.className&&this.className.indexOf(klass)!=-1){els.push(this);}});return els;}}function stopEvent(e){e=e||window.event;if(e.preventDefault){e.stopPropagation();e.preventDefault();}else{e.returnValue=false;e.cancelBubble=true;}return false;}function bind(to,evt,fn){to[evt]=to[evt]||[];to[evt].push(fn);}function makeId(){return"_"+(""+Math.random()).substring(2,10);}var Clip=function(json,index,player){var self=this;var cuepoints={};var listeners={};self.index=index;if(typeof json=='string'){json={url:json};}extend(this,json,true);each(("Begin*,Start,Pause*,Resume*,Seek*,Stop*,Finish*,LastSecond,Update,BufferFull,BufferEmpty,BufferStop").split(","),function(){var evt="on"+this;if(evt.indexOf("*")!=-1){evt=evt.substring(0,evt.length-1);var before="onBefore"+evt.substring(2);self[before]=function(fn){bind(listeners,before,fn);return self;};}self[evt]=function(fn){bind(listeners,evt,fn);return self;};if(index==-1){if(self[before]){player[before]=self[before];}if(self[evt]){player[evt]=self[evt];}}});extend(this,{onCuepoint:function(points,fn){if(arguments.length==1){cuepoints.embedded=[null,points];return self;}if(typeof points=='number'){points=[points];}var fnId=makeId();cuepoints[fnId]=[points,fn];if(player.isLoaded()){player._api().fp_addCuepoints(points,index,fnId);}return self;},update:function(json){extend(self,json);if(player.isLoaded()){player._api().fp_updateClip(json,index);}var conf=player.getConfig();var clip=(index==-1)?conf.clip:conf.playlist[index];extend(clip,json,true);},_fireEvent:function(evt,arg1,arg2,target){if(evt=='onLoad'){each(cuepoints,function(key,val){if(val[0]){player._api().fp_addCuepoints(val[0],index,key);}});return false;}target=target||self;if(evt=='onCuepoint'){var fn=cuepoints[arg1];if(fn){return fn[1].call(player,target,arg2);}}if(evt=='onStart'||evt=='onUpdate'){extend(target,arg1);if(!target.duration){target.duration=arg1.metaData.duration;}else{target.fullDuration=arg1.metaData.duration;}}var ret=true;each(listeners[evt],function(){ret=this.call(player,target,arg1,arg2);});return ret;}});if(json.onCuepoint){var arg=json.onCuepoint;self.onCuepoint.apply(self,typeof arg=='function'?[arg]:arg);delete json.onCuepoint;}each(json,function(key,val){if(typeof val=='function'){bind(listeners,key,val);delete json[key];}});if(index==-1){player.onCuepoint=this.onCuepoint;}};var Plugin=function(name,json,player,fn){var listeners={};var self=this;var hasMethods=false;if(fn){extend(listeners,fn);}each(json,function(key,val){if(typeof val=='function'){listeners[key]=val;delete json[key];}});extend(this,{animate:function(props,speed,fn){if(!props){return self;}if(typeof speed=='function'){fn=speed;speed=500;}if(typeof props=='string'){var key=props;props={};props[key]=speed;speed=500;}if(fn){var fnId=makeId();listeners[fnId]=fn;}if(speed===undefined){speed=500;}json=player._api().fp_animate(name,props,speed,fnId);return self;},css:function(props,val){if(val!==undefined){var css={};css[props]=val;props=css;}json=player._api().fp_css(name,props);extend(self,json);return self;},show:function(){this.display='block';player._api().fp_showPlugin(name);return self;},hide:function(){this.display='none';player._api().fp_hidePlugin(name);return self;},toggle:function(){this.display=player._api().fp_togglePlugin(name);return self;},fadeTo:function(o,speed,fn){if(typeof speed=='function'){fn=speed;speed=500;}if(fn){var fnId=makeId();listeners[fnId]=fn;}this.display=player._api().fp_fadeTo(name,o,speed,fnId);this.opacity=o;return self;},fadeIn:function(speed,fn){return self.fadeTo(1,speed,fn);},fadeOut:function(speed,fn){return self.fadeTo(0,speed,fn);},getName:function(){return name;},_fireEvent:function(evt,arg){if(evt=='onUpdate'){var json=player._api().fp_getPlugin(name);if(!json){return;}extend(self,json);delete self.methods;if(!hasMethods){each(json.methods,function(){var method=""+this;self[method]=function(){var a=[].slice.call(arguments);var ret=player._api().fp_invoke(name,method,a);return ret=='undefined'?self:ret;};});hasMethods=true;}}var fn=listeners[evt];if(fn){fn.call(self,arg);if(evt.substring(0,1)=="_"){delete listeners[evt];}}}});};function Player(wrapper,params,conf){var
-self=this,api=null,html,commonClip,playlist=[],plugins={},listeners={},playerId,apiId,playerIndex,activeIndex,swfHeight,wrapperHeight;extend(self,{id:function(){return playerId;},isLoaded:function(){return(api!==null);},getParent:function(){return wrapper;},hide:function(all){if(all){wrapper.style.height="0px";}if(api){api.style.height="0px";}return self;},show:function(){wrapper.style.height=wrapperHeight+"px";if(api){api.style.height=swfHeight+"px";}return self;},isHidden:function(){return api&&parseInt(api.style.height,10)===0;},load:function(fn){if(!api&&self._fireEvent("onBeforeLoad")!==false){each(players,function(){this.unload();});html=wrapper.innerHTML;flashembed(wrapper,params,{config:conf});if(fn){fn.cached=true;bind(listeners,"onLoad",fn);}}return self;},unload:function(){try{if(api&&api.fp_isFullscreen()){}}catch(error){return;}if(api&&html.replace(/\s/g,'')!==''&&!api.fp_isFullscreen()&&self._fireEvent("onBeforeUnload")!==false){api.fp_close();wrapper.innerHTML=html;self._fireEvent("onUnload");api=null;}return self;},getClip:function(index){if(index===undefined){index=activeIndex;}return playlist[index];},getCommonClip:function(){return commonClip;},getPlaylist:function(){return playlist;},getPlugin:function(name){var plugin=plugins[name];if(!plugin&&self.isLoaded()){var json=self._api().fp_getPlugin(name);if(json){plugin=new Plugin(name,json,self);plugins[name]=plugin;}}return plugin;},getScreen:function(){return self.getPlugin("screen");},getControls:function(){return self.getPlugin("controls");},getConfig:function(copy){return copy?clone(conf):conf;},getFlashParams:function(){return params;},loadPlugin:function(name,url,props,fn){if(typeof props=='function'){fn=props;props={};}var fnId=fn?makeId():"_";self._api().fp_loadPlugin(name,url,props,fnId);var arg={};arg[fnId]=fn;var p=new Plugin(name,null,self,arg);plugins[name]=p;return p;},getState:function(){return api?api.fp_getState():-1;},play:function(clip){function play(){if(clip!==undefined){self._api().fp_play(clip);}else{self._api().fp_play();}}if(api){play();}else{self.load(function(){play();});}return self;},getVersion:function(){var js="flowplayer.js 3.0.5";if(api){var ver=api.fp_getVersion();ver.push(js);return ver;}return js;},_api:function(){if(!api){throw"Flowplayer "+self.id()+" not loaded. Try moving your call to player's onLoad event";}return api;},_dump:function(){console.log(listeners);},setClip:function(clip){self.setPlaylist([clip]);},getIndex:function(){return playerIndex;}});each(("Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,Fullscreen*,FullscreenExit,Error").split(","),function(){var name="on"+this;if(name.indexOf("*")!=-1){name=name.substring(0,name.length-1);var name2="onBefore"+name.substring(2);self[name2]=function(fn){bind(listeners,name2,fn);return self;};}self[name]=function(fn){bind(listeners,name,fn);return self;};});each(("pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,reset,close,setPlaylist").split(","),function(){var name=this;self[name]=function(arg){if(!api){return self;}var ret=(arg===undefined)?api["fp_"+name]():api["fp_"+name](arg);return ret=='undefined'?self:ret;};});self._fireEvent=function(evt,arg0,arg1,arg2){if(conf.debug){log(arguments);}if(!api&&evt=='onLoad'&&arg0=='player'){api=api||el(apiId);swfHeight=api.clientHeight;each(playlist,function(){this._fireEvent("onLoad");});each(plugins,function(name,p){p._fireEvent("onUpdate");});commonClip._fireEvent("onLoad");}if(evt=='onLoad'&&arg0!='player'){return;}if(evt=='onError'){if(typeof arg0=='string'||(typeof arg0=='number'&&typeof arg1=='number')){arg0=arg1;arg1=arg2;}}if(evt=='onContextMenu'){each(conf.contextMenu[arg0],function(key,fn){fn.call(self);});return;}if(evt=='onPluginEvent'){var name=arg0.name||arg0;var p=plugins[name];if(p){p._fireEvent("onUpdate",arg0);p._fireEvent(arg1);}return;}if(evt=='onPlaylistReplace'){playlist=[];var index=0;each(arg0,function(){playlist.push(new Clip(this,index++,self));});}var ret=true;if(typeof arg0=='number'&&arg0<playlist.length){activeIndex=arg0;var clip=playlist[arg0];if(clip){ret=clip._fireEvent(evt,arg1,arg2);}if(!clip||ret!==false){ret=commonClip._fireEvent(evt,arg1,arg2,clip);}}var i=0;each(listeners[evt],function(){ret=this.call(self,arg0,arg1);if(this.cached){listeners[evt].splice(i,1);}if(ret===false){return false;}i++;});return ret;};function init(){if($f(wrapper)){$f(wrapper).getParent().innerHTML="";playerIndex=$f(wrapper).getIndex();players[playerIndex]=self;}else{players.push(self);playerIndex=players.length-1;}wrapperHeight=parseInt(wrapper.style.height,10)||wrapper.clientHeight;if(typeof params=='string'){params={src:params};}playerId=wrapper.id||"fp"+makeId();apiId=params.id||playerId+"_api";params.id=apiId;conf.playerId=playerId;if(typeof conf=='string'){conf={clip:{url:conf}};}if(typeof conf.clip=='string'){conf.clip={url:conf.clip};}conf.clip=conf.clip||{};if(wrapper.getAttribute("href",2)&&!conf.clip.url){conf.clip.url=wrapper.getAttribute("href",2);}commonClip=new Clip(conf.clip,-1,self);conf.playlist=conf.playlist||[conf.clip];var index=0;each(conf.playlist,function(){var clip=this;if(typeof clip=='object'&&clip.length){clip=""+clip;}if(typeof clip=='string'){clip={url:clip};}each(conf.clip,function(key,val){if(conf.clip[key]!==undefined&&typeof val!='function'){clip[key]=val;}});conf.playlist[index]=clip;clip=new Clip(clip,index,self);playlist.push(clip);index++;});each(conf,function(key,val){if(typeof val=='function'){bind(listeners,key,val);delete conf[key];}});each(conf.plugins,function(name,val){if(val){plugins[name]=new Plugin(name,val,self);}});if(!conf.plugins||conf.plugins.controls===undefined){plugins.controls=new Plugin("controls",null,self);}params.bgcolor=params.bgcolor||"#000000";params.version=params.version||[9,0];params.expressInstall='http://www.flowplayer.org/swf/expressinstall.swf';function doClick(e){if(!self.isLoaded()&&self._fireEvent("onBeforeClick")!==false){self.load();}return stopEvent(e);}html=wrapper.innerHTML;if(html.replace(/\s/g,'')!==''){if(wrapper.addEventListener){wrapper.addEventListener("click",doClick,false);}else if(wrapper.attachEvent){wrapper.attachEvent("onclick",doClick);}}else{if(wrapper.addEventListener){wrapper.addEventListener("click",stopEvent,false);}self.load();}}if(typeof wrapper=='string'){flashembed.domReady(function(){var node=el(wrapper);if(!node){throw"Flowplayer cannot access element: "+wrapper;}else{wrapper=node;init();}});}else{init();}}var players=[];function Iterator(arr){this.length=arr.length;this.each=function(fn){each(arr,fn);};this.size=function(){return arr.length;};}window.flowplayer=window.$f=function(){var instance=null;var arg=arguments[0];if(!arguments.length){each(players,function(){if(this.isLoaded()){instance=this;return false;}});return instance||players[0];}if(arguments.length==1){if(typeof arg=='number'){return players[arg];}else{if(arg=='*'){return new Iterator(players);}each(players,function(){if(this.id()==arg.id||this.id()==arg||this.getParent()==arg){instance=this;return false;}});return instance;}}if(arguments.length>1){var swf=arguments[1];var conf=(arguments.length==3)?arguments[2]:{};if(typeof arg=='string'){if(arg.indexOf(".")!=-1){var instances=[];each(select(arg),function(){instances.push(new Player(this,clone(swf),clone(conf)));});return new Iterator(instances);}else{var node=el(arg);return new Player(node!==null?node:arg,swf,conf);}}else if(arg){return new Player(arg,swf,conf);}}return null;};extend(window.$f,{fireEvent:function(id,evt,a0,a1,a2){var p=$f(id);return p?p._fireEvent(evt,a0,a1,a2):null;},addPlugin:function(name,fn){Player.prototype[name]=fn;return $f;},each:each,extend:extend});if(document.all){window.onbeforeunload=function(){$f("*").each(function(){if(this.isLoaded()){this.close();}});};}if(typeof jQuery=='function'){jQuery.prototype.flowplayer=function(params,conf){if(!arguments.length||typeof arguments[0]=='number'){var arr=[];this.each(function(){var p=$f(this);if(p){arr.push(p);}});return arguments.length?arr[arguments[0]]:new Iterator(arr);}return this.each(function(){$f(this,clone(params),conf?clone(conf):{});});};}})();(function(){var jQ=typeof jQuery=='function';function isDomReady(){if(domReady.done){return false;}var d=document;if(d&&d.getElementsByTagName&&d.getElementById&&d.body){clearInterval(domReady.timer);domReady.timer=null;for(var i=0;i<domReady.ready.length;i++){domReady.ready[i].call();}domReady.ready=null;domReady.done=true;}}var domReady=jQ?jQuery:function(f){if(domReady.done){return f();}if(domReady.timer){domReady.ready.push(f);}else{domReady.ready=[f];domReady.timer=setInterval(isDomReady,13);}};function extend(to,from){if(from){for(key in from){if(from.hasOwnProperty(key)){to[key]=from[key];}}}return to;}function asString(obj){switch(typeOf(obj)){case'string':obj=obj.replace(new RegExp('(["\\\\])','g'),'\\$1');obj=obj.replace(/^\s?(\d+)%/,"$1pct");return'"'+obj+'"';case'array':return'['+map(obj,function(el){return asString(el);}).join(',')+']';case'function':return'"function()"';case'object':var str=[];for(var prop in obj){if(obj.hasOwnProperty(prop)){str.push('"'+prop+'":'+asString(obj[prop]));}}return'{'+str.join(',')+'}';}return String(obj).replace(/\s/g," ").replace(/\'/g,"\"");}function typeOf(obj){if(obj===null||obj===undefined){return false;}var type=typeof obj;return(type=='object'&&obj.push)?'array':type;}if(window.attachEvent){window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};});}function map(arr,func){var newArr=[];for(var i in arr){if(arr.hasOwnProperty(i)){newArr[i]=func(arr[i]);}}return newArr;}function getHTML(p,c){var ie=document.all;var html='<object width="'+p.width+'" height="'+p.height+'"';if(ie&&!p.id){p.id="_"+(""+Math.random()).substring(9);}if(p.id){html+=' id="'+p.id+'"';}if(p.w3c||!ie){html+=' data="'+p.src+'" type="application/x-shockwave-flash"';}else{html+=' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';}html+='>';if(p.w3c||ie){html+='<param name="movie" value="'+p.src+'" />';}var e=extend({},p);e.width=e.height=e.id=e.w3c=e.src=null;for(var k in e){if(e[k]!==null){html+='<param name="'+k+'" value="'+e[k]+'" />';}}var vars="";if(c){for(var key in c){if(c[key]!==null){vars+=key+'='+(typeof c[key]=='object'?asString(c[key]):c[key])+'&';}}vars=vars.substring(0,vars.length-1);html+='<param name="flashvars" value=\''+vars+'\' />';}html+="</object>";return html;}function Flash(root,opts,flashvars){var version=flashembed.getVersion();extend(this,{getContainer:function(){return root;},getConf:function(){return conf;},getVersion:function(){return version;},getFlashvars:function(){return flashvars;},getApi:function(){return root.firstChild;},getHTML:function(){return getHTML(opts,flashvars);}});var required=opts.version;var express=opts.expressInstall;var ok=!required||flashembed.isSupported(required);if(ok){opts.onFail=opts.version=opts.expressInstall=null;root.innerHTML=getHTML(opts,flashvars);}else if(required&&express&&flashembed.isSupported([6,65])){extend(opts,{src:express});flashvars={MMredirectURL:location.href,MMplayerType:'PlugIn',MMdoctitle:document.title};root.innerHTML=getHTML(opts,flashvars);}else{if(root.innerHTML.replace(/\s/g,'')!==''){}else{root.innerHTML="<h2>Flash version "+required+" or greater is required</h2>"+"<h3>"+(version[0]>0?"Your version is "+version:"You have no flash plugin installed")+"</h3>"+"<p>Download latest version from <a href='http://www.adobe.com/go/getflashplayer'>here</a></p>";}}if(!ok&&opts.onFail){var ret=opts.onFail.call(this);if(typeof ret=='string'){root.innerHTML=ret;}}}window.flashembed=function(root,conf,flashvars){if(typeof root=='string'){var el=document.getElementById(root);if(el){root=el;}else{domReady(function(){flashembed(root,conf,flashvars);});return;}}if(!root){return;}var opts={width:'100%',height:'100%',allowfullscreen:true,allowscriptaccess:'always',quality:'high',version:null,onFail:null,expressInstall:null,w3c:false};if(typeof conf=='string'){conf={src:conf};}extend(opts,conf);return new Flash(root,opts,flashvars);};extend(window.flashembed,{getVersion:function(){var version=[0,0];if(navigator.plugins&&typeof navigator.plugins["Shockwave Flash"]=="object"){var _d=navigator.plugins["Shockwave Flash"].description;if(typeof _d!="undefined"){_d=_d.replace(/^.*\s+(\S+\s+\S+$)/,"$1");var _m=parseInt(_d.replace(/^(.*)\..*$/,"$1"),10);var _r=/r/.test(_d)?parseInt(_d.replace(/^.*r(.*)$/,"$1"),10):0;version=[_m,_r];}}else if(window.ActiveXObject){try{var _a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{_a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");version=[6,0];_a.AllowScriptAccess="always";}catch(ee){if(version[0]==6){return;}}try{_a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(eee){}}if(typeof _a=="object"){_d=_a.GetVariable("$version");if(typeof _d!="undefined"){_d=_d.replace(/^\S+\s+(.*)$/,"$1").split(",");version=[parseInt(_d[0],10),parseInt(_d[2],10)];}}}return version;},isSupported:function(version){var now=flashembed.getVersion();var ret=(now[0]>version[0])||(now[0]==version[0]&&now[1]>=version[1]);return ret;},domReady:domReady,asString:asString,getHTML:getHTML});if(jQ){jQuery.prototype.flashembed=function(conf,flashvars){return this.each(function(){flashembed(this,conf,flashvars);});};}})(); \ No newline at end of file
+
+(function(){function log(args){console.log("$f.fireEvent",[].slice.call(args));}
+function clone(obj){if(!obj||typeof obj!='object'){return obj;}
+var temp=new obj.constructor();for(var key in obj){if(obj.hasOwnProperty(key)){temp[key]=clone(obj[key]);}}
+return temp;}
+function each(obj,fn){if(!obj){return;}
+var name,i=0,length=obj.length;if(length===undefined){for(name in obj){if(fn.call(obj[name],name,obj[name])===false){break;}}}else{for(var value=obj[0];i<length&&fn.call(value,i,value)!==false;value=obj[++i]){}}
+return obj;}
+function el(id){return document.getElementById(id);}
+function extend(to,from,skipFuncs){if(typeof from!='object'){return to;}
+if(to&&from){each(from,function(name,value){if(!skipFuncs||typeof value!='function'){to[name]=value;}});}
+return to;}
+function select(query){var index=query.indexOf(".");if(index!=-1){var tag=query.substring(0,index)||"*";var klass=query.substring(index+1,query.length);var els=[];each(document.getElementsByTagName(tag),function(){if(this.className&&this.className.indexOf(klass)!=-1){els.push(this);}});return els;}}
+function stopEvent(e){e=e||window.event;if(e.preventDefault){e.stopPropagation();e.preventDefault();}else{e.returnValue=false;e.cancelBubble=true;}
+return false;}
+function bind(to,evt,fn){to[evt]=to[evt]||[];to[evt].push(fn);}
+function makeId(){return"_"+(""+Math.random()).substring(2,10);}
+var Clip=function(json,index,player){var self=this;var cuepoints={};var listeners={};self.index=index;if(typeof json=='string'){json={url:json};}
+extend(this,json,true);each(("Begin*,Start,Pause*,Resume*,Seek*,Stop*,Finish*,LastSecond,Update,BufferFull,BufferEmpty,BufferStop").split(","),function(){var evt="on"+this;if(evt.indexOf("*")!=-1){evt=evt.substring(0,evt.length-1);var before="onBefore"+evt.substring(2);self[before]=function(fn){bind(listeners,before,fn);return self;};}
+self[evt]=function(fn){bind(listeners,evt,fn);return self;};if(index==-1){if(self[before]){player[before]=self[before];}
+if(self[evt]){player[evt]=self[evt];}}});extend(this,{onCuepoint:function(points,fn){if(arguments.length==1){cuepoints.embedded=[null,points];return self;}
+if(typeof points=='number'){points=[points];}
+var fnId=makeId();cuepoints[fnId]=[points,fn];if(player.isLoaded()){player._api().fp_addCuepoints(points,index,fnId);}
+return self;},update:function(json){extend(self,json);if(player.isLoaded()){player._api().fp_updateClip(json,index);}
+var conf=player.getConfig();var clip=(index==-1)?conf.clip:conf.playlist[index];extend(clip,json,true);},_fireEvent:function(evt,arg1,arg2,target){if(evt=='onLoad'){each(cuepoints,function(key,val){if(val[0]){player._api().fp_addCuepoints(val[0],index,key);}});return false;}
+target=target||self;if(evt=='onCuepoint'){var fn=cuepoints[arg1];if(fn){return fn[1].call(player,target,arg2);}}
+if(arg1&&"onBeforeBegin,onMetaData,onStart,onUpdate,onResume".indexOf(evt)!=-1){extend(target,arg1);if(arg1.metaData){if(!target.duration){target.duration=arg1.metaData.duration;}else{target.fullDuration=arg1.metaData.duration;}}}
+var ret=true;each(listeners[evt],function(){ret=this.call(player,target,arg1,arg2);});return ret;}});if(json.onCuepoint){var arg=json.onCuepoint;self.onCuepoint.apply(self,typeof arg=='function'?[arg]:arg);delete json.onCuepoint;}
+each(json,function(key,val){if(typeof val=='function'){bind(listeners,key,val);delete json[key];}});if(index==-1){player.onCuepoint=this.onCuepoint;}};var Plugin=function(name,json,player,fn){var listeners={};var self=this;var hasMethods=false;if(fn){extend(listeners,fn);}
+each(json,function(key,val){if(typeof val=='function'){listeners[key]=val;delete json[key];}});extend(this,{animate:function(props,speed,fn){if(!props){return self;}
+if(typeof speed=='function'){fn=speed;speed=500;}
+if(typeof props=='string'){var key=props;props={};props[key]=speed;speed=500;}
+if(fn){var fnId=makeId();listeners[fnId]=fn;}
+if(speed===undefined){speed=500;}
+json=player._api().fp_animate(name,props,speed,fnId);return self;},css:function(props,val){if(val!==undefined){var css={};css[props]=val;props=css;}
+json=player._api().fp_css(name,props);extend(self,json);return self;},show:function(){this.display='block';player._api().fp_showPlugin(name);return self;},hide:function(){this.display='none';player._api().fp_hidePlugin(name);return self;},toggle:function(){this.display=player._api().fp_togglePlugin(name);return self;},fadeTo:function(o,speed,fn){if(typeof speed=='function'){fn=speed;speed=500;}
+if(fn){var fnId=makeId();listeners[fnId]=fn;}
+this.display=player._api().fp_fadeTo(name,o,speed,fnId);this.opacity=o;return self;},fadeIn:function(speed,fn){return self.fadeTo(1,speed,fn);},fadeOut:function(speed,fn){return self.fadeTo(0,speed,fn);},getName:function(){return name;},getPlayer:function(){return player;},_fireEvent:function(evt,arg,arg2){if(evt=='onUpdate'){var json=player._api().fp_getPlugin(name);if(!json){return;}
+extend(self,json);delete self.methods;if(!hasMethods){each(json.methods,function(){var method=""+this;self[method]=function(){var a=[].slice.call(arguments);var ret=player._api().fp_invoke(name,method,a);return ret==='undefined'||ret===undefined?self:ret;};});hasMethods=true;}}
+var fn=listeners[evt];if(fn){fn.apply(self,arg);if(evt.substring(0,1)=="_"){delete listeners[evt];}}}});};function Player(wrapper,params,conf){var
+self=this,api=null,html,commonClip,playlist=[],plugins={},listeners={},playerId,apiId,playerIndex,activeIndex,swfHeight,wrapperHeight;extend(self,{id:function(){return playerId;},isLoaded:function(){return(api!==null);},getParent:function(){return wrapper;},hide:function(all){if(all){wrapper.style.height="0px";}
+if(api){api.style.height="0px";}
+return self;},show:function(){wrapper.style.height=wrapperHeight+"px";if(api){api.style.height=swfHeight+"px";}
+return self;},isHidden:function(){return api&&parseInt(api.style.height,10)===0;},load:function(fn){if(!api&&self._fireEvent("onBeforeLoad")!==false){each(players,function(){this.unload();});html=wrapper.innerHTML;if(html&&!flashembed.isSupported(params.version)){wrapper.innerHTML="";}
+flashembed(wrapper,params,{config:conf});if(fn){fn.cached=true;bind(listeners,"onLoad",fn);}}
+return self;},unload:function(){if(html.replace(/\s/g,'')!==''){if(self._fireEvent("onBeforeUnload")===false){return self;}
+try{if(api){api.fp_close();self._fireEvent("onUnload");}}catch(error){}
+api=null;wrapper.innerHTML=html;}
+return self;},getClip:function(index){if(index===undefined){index=activeIndex;}
+return playlist[index];},getCommonClip:function(){return commonClip;},getPlaylist:function(){return playlist;},getPlugin:function(name){var plugin=plugins[name];if(!plugin&&self.isLoaded()){var json=self._api().fp_getPlugin(name);if(json){plugin=new Plugin(name,json,self);plugins[name]=plugin;}}
+return plugin;},getScreen:function(){return self.getPlugin("screen");},getControls:function(){return self.getPlugin("controls");},getConfig:function(copy){return copy?clone(conf):conf;},getFlashParams:function(){return params;},loadPlugin:function(name,url,props,fn){if(typeof props=='function'){fn=props;props={};}
+var fnId=fn?makeId():"_";self._api().fp_loadPlugin(name,url,props,fnId);var arg={};arg[fnId]=fn;var p=new Plugin(name,null,self,arg);plugins[name]=p;return p;},getState:function(){return api?api.fp_getState():-1;},play:function(clip,instream){function play(){if(clip!==undefined){self._api().fp_play(clip,instream);}else{self._api().fp_play();}}
+if(api){play();}else{self.load(function(){play();});}
+return self;},getVersion:function(){var js="flowplayer.js @VERSION";if(api){var ver=api.fp_getVersion();ver.push(js);return ver;}
+return js;},_api:function(){if(!api){throw"Flowplayer "+self.id()+" not loaded when calling an API method";}
+return api;},setClip:function(clip){self.setPlaylist([clip]);return self;},getIndex:function(){return playerIndex;}});each(("Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,ClipAdd,Fullscreen*,FullscreenExit,Error,MouseOver,MouseOut").split(","),function(){var name="on"+this;if(name.indexOf("*")!=-1){name=name.substring(0,name.length-1);var name2="onBefore"+name.substring(2);self[name2]=function(fn){bind(listeners,name2,fn);return self;};}
+self[name]=function(fn){bind(listeners,name,fn);return self;};});each(("pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,toggleFullscreen,reset,close,setPlaylist,addClip,playFeed").split(","),function(){var name=this;self[name]=function(a1,a2){if(!api){return self;}
+var ret=null;if(a1!==undefined&&a2!==undefined){ret=api["fp_"+name](a1,a2);}else{ret=(a1===undefined)?api["fp_"+name]():api["fp_"+name](a1);}
+return ret==='undefined'||ret===undefined?self:ret;};});self._fireEvent=function(a){if(typeof a=='string'){a=[a];}
+var evt=a[0],arg0=a[1],arg1=a[2],arg2=a[3],i=0;if(conf.debug){log(a);}
+if(!api&&evt=='onLoad'&&arg0=='player'){api=api||el(apiId);swfHeight=api.clientHeight;each(playlist,function(){this._fireEvent("onLoad");});each(plugins,function(name,p){p._fireEvent("onUpdate");});commonClip._fireEvent("onLoad");}
+if(evt=='onLoad'&&arg0!='player'){return;}
+if(evt=='onError'){if(typeof arg0=='string'||(typeof arg0=='number'&&typeof arg1=='number')){arg0=arg1;arg1=arg2;}}
+if(evt=='onContextMenu'){each(conf.contextMenu[arg0],function(key,fn){fn.call(self);});return;}
+if(evt=='onPluginEvent'){var name=arg0.name||arg0;var p=plugins[name];if(p){p._fireEvent("onUpdate",arg0);p._fireEvent(arg1,a.slice(3));}
+return;}
+if(evt=='onPlaylistReplace'){playlist=[];var index=0;each(arg0,function(){playlist.push(new Clip(this,index++,self));});}
+if(evt=='onClipAdd'){if(arg0.isInStream){return;}
+arg0=new Clip(arg0,arg1,self);playlist.splice(arg1,0,arg0);for(i=arg1+1;i<playlist.length;i++){playlist[i].index++;}}
+var ret=true;if(typeof arg0=='number'&&arg0<playlist.length){activeIndex=arg0;var clip=playlist[arg0];if(clip){ret=clip._fireEvent(evt,arg1,arg2);}
+if(!clip||ret!==false){ret=commonClip._fireEvent(evt,arg1,arg2,clip);}}
+each(listeners[evt],function(){ret=this.call(self,arg0,arg1);if(this.cached){listeners[evt].splice(i,1);}
+if(ret===false){return false;}
+i++;});return ret;};function init(){if($f(wrapper)){$f(wrapper).getParent().innerHTML="";playerIndex=$f(wrapper).getIndex();players[playerIndex]=self;}else{players.push(self);playerIndex=players.length-1;}
+wrapperHeight=parseInt(wrapper.style.height,10)||wrapper.clientHeight;if(typeof params=='string'){params={src:params};}
+playerId=wrapper.id||"fp"+makeId();apiId=params.id||playerId+"_api";params.id=apiId;conf.playerId=playerId;if(typeof conf=='string'){conf={clip:{url:conf}};}
+if(typeof conf.clip=='string'){conf.clip={url:conf.clip};}
+conf.clip=conf.clip||{};if(wrapper.getAttribute("href",2)&&!conf.clip.url){conf.clip.url=wrapper.getAttribute("href",2);}
+commonClip=new Clip(conf.clip,-1,self);conf.playlist=conf.playlist||[conf.clip];var index=0;each(conf.playlist,function(){var clip=this;if(typeof clip=='object'&&clip.length){clip={url:""+clip};}
+each(conf.clip,function(key,val){if(val!==undefined&&clip[key]===undefined&&typeof val!='function'){clip[key]=val;}});conf.playlist[index]=clip;clip=new Clip(clip,index,self);playlist.push(clip);index++;});each(conf,function(key,val){if(typeof val=='function'){if(commonClip[key]){commonClip[key](val);}else{bind(listeners,key,val);}
+delete conf[key];}});each(conf.plugins,function(name,val){if(val){plugins[name]=new Plugin(name,val,self);}});if(!conf.plugins||conf.plugins.controls===undefined){plugins.controls=new Plugin("controls",null,self);}
+plugins.canvas=new Plugin("canvas",null,self);params.bgcolor=params.bgcolor||"#000000";params.version=params.version||[9,0];params.expressInstall='http://www.flowplayer.org/swf/expressinstall.swf';function doClick(e){if(!self.isLoaded()&&self._fireEvent("onBeforeClick")!==false){self.load();}
+return stopEvent(e);}
+html=wrapper.innerHTML;if(html.replace(/\s/g,'')!==''){if(wrapper.addEventListener){wrapper.addEventListener("click",doClick,false);}else if(wrapper.attachEvent){wrapper.attachEvent("onclick",doClick);}}else{if(wrapper.addEventListener){wrapper.addEventListener("click",stopEvent,false);}
+self.load();}}
+if(typeof wrapper=='string'){flashembed.domReady(function(){var node=el(wrapper);if(!node){throw"Flowplayer cannot access element: "+wrapper;}else{wrapper=node;init();}});}else{init();}}
+var players=[];function Iterator(arr){this.length=arr.length;this.each=function(fn){each(arr,fn);};this.size=function(){return arr.length;};}
+window.flowplayer=window.$f=function(){var instance=null;var arg=arguments[0];if(!arguments.length){each(players,function(){if(this.isLoaded()){instance=this;return false;}});return instance||players[0];}
+if(arguments.length==1){if(typeof arg=='number'){return players[arg];}else{if(arg=='*'){return new Iterator(players);}
+each(players,function(){if(this.id()==arg.id||this.id()==arg||this.getParent()==arg){instance=this;return false;}});return instance;}}
+if(arguments.length>1){var swf=arguments[1];var conf=(arguments.length==3)?arguments[2]:{};if(typeof arg=='string'){if(arg.indexOf(".")!=-1){var instances=[];each(select(arg),function(){instances.push(new Player(this,clone(swf),clone(conf)));});return new Iterator(instances);}else{var node=el(arg);return new Player(node!==null?node:arg,swf,conf);}}else if(arg){return new Player(arg,swf,conf);}}
+return null;};extend(window.$f,{fireEvent:function(){var a=[].slice.call(arguments);var p=$f(a[0]);return p?p._fireEvent(a.slice(1)):null;},addPlugin:function(name,fn){Player.prototype[name]=fn;return $f;},each:each,extend:extend});if(typeof jQuery=='function'){jQuery.prototype.flowplayer=function(params,conf){if(!arguments.length||typeof arguments[0]=='number'){var arr=[];this.each(function(){var p=$f(this);if(p){arr.push(p);}});return arguments.length?arr[arguments[0]]:new Iterator(arr);}
+return this.each(function(){$f(this,clone(params),conf?clone(conf):{});});};}})();(function(){var jQ=typeof jQuery=='function';var options={width:'100%',height:'100%',allowfullscreen:true,allowscriptaccess:'always',quality:'high',version:null,onFail:null,expressInstall:null,w3c:false,cachebusting:false};if(jQ){jQuery.tools=jQuery.tools||{};jQuery.tools.flashembed={version:'1.0.4',conf:options};}
+function isDomReady(){if(domReady.done){return false;}
+var d=document;if(d&&d.getElementsByTagName&&d.getElementById&&d.body){clearInterval(domReady.timer);domReady.timer=null;for(var i=0;i<domReady.ready.length;i++){domReady.ready[i].call();}
+domReady.ready=null;domReady.done=true;}}
+var domReady=jQ?jQuery:function(f){if(domReady.done){return f();}
+if(domReady.timer){domReady.ready.push(f);}else{domReady.ready=[f];domReady.timer=setInterval(isDomReady,13);}};function extend(to,from){if(from){for(key in from){if(from.hasOwnProperty(key)){to[key]=from[key];}}}
+return to;}
+var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function string2JsonString(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
+function asString(obj){switch(typeOf(obj)){case'string':return string2JsonString(obj);case'array':return'['+map(obj,function(el){return asString(el);}).join(',')+']';case'function':return'"function()"';case'object':var str=[];for(var prop in obj){if(obj.hasOwnProperty(prop)){str.push('"'+prop+'":'+asString(obj[prop]));}}
+return'{'+str.join(',')+'}';}
+return String(obj).replace(/\s/g," ").replace(/\'/g,"\"");}
+function typeOf(obj){if(obj===null||obj===undefined){return false;}
+var type=typeof obj;return(type=='object'&&obj.push)?'array':type;}
+if(window.attachEvent){window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};});}
+function map(arr,func){var newArr=[];for(var i in arr){if(arr.hasOwnProperty(i)){newArr[i]=func(arr[i]);}}
+return newArr;}
+function getHTML(p,c){var e=extend({},p);var ie=document.all;var html='<object width="'+e.width+'" height="'+e.height+'"';if(ie&&!e.id){e.id="_"+(""+Math.random()).substring(9);}
+if(e.id){html+=' id="'+e.id+'"';}
+if(e.cachebusting){e.src+=((e.src.indexOf("?")!=-1?"&":"?")+Math.random());}
+if(e.w3c||!ie){html+=' data="'+e.src+'" type="application/x-shockwave-flash"';}else{html+=' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';}
+html+='>';if(e.w3c||ie){html+='<param name="movie" value="'+e.src+'" />';}
+e.width=e.height=e.id=e.w3c=e.src=null;for(var k in e){if(e[k]!==null){html+='<param name="'+k+'" value="'+e[k]+'" />';}}
+var vars="";if(c){for(var key in c){if(c[key]!==null){vars+=encodeURIComponent(key)+'='
++encodeURIComponent(typeof c[key]=='object'?asString(c[key]):c[key])
++'&';}}
+vars=vars.substring(0,vars.length-1);html+='<param name="flashvars" value="'+vars+'" />';}
+html+="</object>";return html;}
+function Flash(root,opts,flashvars){var version=flashembed.getVersion();extend(this,{getContainer:function(){return root;},getConf:function(){return opts;},getVersion:function(){return version;},getFlashvars:function(){return flashvars;},getApi:function(){return root.firstChild;},getHTML:function(){return getHTML(opts,flashvars);}});var required=opts.version;var express=opts.expressInstall;var ok=!required||flashembed.isSupported(required);if(ok){opts.onFail=opts.version=opts.expressInstall=null;root.innerHTML=getHTML(opts,flashvars);}else if(required&&express&&flashembed.isSupported([6,65])){extend(opts,{src:express});flashvars={MMredirectURL:location.href,MMplayerType:'PlugIn',MMdoctitle:document.title};root.innerHTML=getHTML(opts,flashvars);}else{if(root.innerHTML.replace(/\s/g,'')!==''){}else{root.innerHTML="<h2>Flash version "+required+" or greater is required</h2>"+"<h3>"+
+(version[0]>0?"Your version is "+version:"You have no flash plugin installed")+"</h3>"+
+(root.tagName=='A'?"<p>Click here to download latest version</p>":"<p>Download latest version from <a href='http://www.adobe.com/go/getflashplayer'>here</a></p>");if(root.tagName=='A'){root.onclick=function(){location.href='http://www.adobe.com/go/getflashplayer';};}}}
+if(!ok&&opts.onFail){var ret=opts.onFail.call(this);if(typeof ret=='string'){root.innerHTML=ret;}}
+if(document.all){window[opts.id]=document.getElementById(opts.id);}}
+window.flashembed=function(root,conf,flashvars){if(typeof root=='string'){var el=document.getElementById(root);if(el){root=el;}else{domReady(function(){flashembed(root,conf,flashvars);});return;}}
+if(!root){return;}
+if(typeof conf=='string'){conf={src:conf};}
+var opts=extend({},options);extend(opts,conf);return new Flash(root,opts,flashvars);};extend(window.flashembed,{getVersion:function(){var version=[0,0];if(navigator.plugins&&typeof navigator.plugins["Shockwave Flash"]=="object"){var _d=navigator.plugins["Shockwave Flash"].description;if(typeof _d!="undefined"){_d=_d.replace(/^.*\s+(\S+\s+\S+$)/,"$1");var _m=parseInt(_d.replace(/^(.*)\..*$/,"$1"),10);var _r=/r/.test(_d)?parseInt(_d.replace(/^.*r(.*)$/,"$1"),10):0;version=[_m,_r];}}else if(window.ActiveXObject){try{var _a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{_a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");version=[6,0];_a.AllowScriptAccess="always";}catch(ee){if(version[0]==6){return version;}}
+try{_a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(eee){}}
+if(typeof _a=="object"){_d=_a.GetVariable("$version");if(typeof _d!="undefined"){_d=_d.replace(/^\S+\s+(.*)$/,"$1").split(",");version=[parseInt(_d[0],10),parseInt(_d[2],10)];}}}
+return version;},isSupported:function(version){var now=flashembed.getVersion();var ret=(now[0]>version[0])||(now[0]==version[0]&&now[1]>=version[1]);return ret;},domReady:domReady,asString:asString,getHTML:getHTML});if(jQ){jQuery.fn.flashembed=function(conf,flashvars){var el=null;this.each(function(){el=flashembed(this,conf,flashvars);});return conf.api===false?this:el;};}})(); \ No newline at end of file
diff --git a/modules/akismet/controllers/admin_akismet.php b/modules/akismet/controllers/admin_akismet.php
index ca3a1473..4847db53 100644
--- a/modules/akismet/controllers/admin_akismet.php
+++ b/modules/akismet/controllers/admin_akismet.php
@@ -25,17 +25,8 @@ class Admin_Akismet_Controller extends Admin_Controller {
// @todo move the "post" handler part of this code into a separate function
access::verify_csrf();
- $valid = $form->validate();
-
- if ($valid) {
+ if ($form->validate()) {
$new_key = $form->configure_akismet->api_key->value;
- if ($new_key && !akismet::validate_key($new_key)) {
- $form->configure_akismet->api_key->add_error("invalid", 1);
- $valid = false;
- }
- }
-
- if ($valid) {
$old_key = module::get_var("akismet", "api_key");
if ($old_key && !$new_key) {
message::success(t("Your Akismet key has been cleared."));
diff --git a/modules/akismet/helpers/akismet.php b/modules/akismet/helpers/akismet.php
index 46a305b2..b4405de5 100644
--- a/modules/akismet/helpers/akismet.php
+++ b/modules/akismet/helpers/akismet.php
@@ -23,8 +23,9 @@ class akismet_Core {
static function get_configure_form() {
$form = new Forge("admin/akismet", "", "post", array("id" => "g-configure-akismet-form"));
$group = $form->group("configure_akismet")->label(t("Configure Akismet"));
- $group->input("api_key")->label(t("API Key"))->value(module::get_var("akismet", "api_key"));
- $group->api_key->error_messages("invalid", t("The API key you provided is invalid."));
+ $group->input("api_key")->label(t("API Key"))->value(module::get_var("akismet", "api_key"))
+ ->callback("akismet::validate_key")
+ ->error_messages("invalid", t("The API key you provided is invalid."));
$group->submit("")->value(t("Save"));
return $form;
}
@@ -82,10 +83,14 @@ class akismet_Core {
* @param string $api_key the API key
* @return boolean
*/
- static function validate_key($api_key) {
- $request = self::_build_verify_request($api_key);
- $response = self::_http_post($request, "rest.akismet.com");
- return "valid" == $response->body[0];
+ static function validate_key($api_key_input) {
+ if ($api_key_input->value) {
+ $request = self::_build_verify_request($api_key_input->value);
+ $response = self::_http_post($request, "rest.akismet.com");
+ if ("valid" != $response->body[0]) {
+ $api_key_input->add_error("invalid", 1);
+ }
+ }
}
diff --git a/modules/akismet/tests/Akismet_Helper_Test.php b/modules/akismet/tests/Akismet_Helper_Test.php
index d8605d5c..e185f280 100644
--- a/modules/akismet/tests/Akismet_Helper_Test.php
+++ b/modules/akismet/tests/Akismet_Helper_Test.php
@@ -17,25 +17,32 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Akismet_Helper_Test extends Unit_Test_Case {
+class Akismet_Helper_Test extends Gallery_Unit_Test_Case {
private $_comment;
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/admin_comments.php b/modules/comment/controllers/admin_comments.php
index b7dc5fb3..3dd45919 100644
--- a/modules/comment/controllers/admin_comments.php
+++ b/modules/comment/controllers/admin_comments.php
@@ -92,6 +92,7 @@ class Admin_Comments_Controller extends Admin_Controller {
}
private function _counts() {
+ $counts = new stdClass();
$counts->unpublished = 0;
$counts->published = 0;
$counts->spam = 0;
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..f710ad92 100644
--- a/modules/comment/helpers/comment.php
+++ b/modules/comment/helpers/comment.php
@@ -24,53 +24,23 @@
* 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"));
- $group->input("name") ->label(t("Name")) ->id("g-author");
- $group->input("email") ->label(t("Email (hidden)")) ->id("g-email");
- $group->input("url") ->label(t("Website (hidden)"))->id("g-url");
- $group->textarea("text")->label(t("Comment")) ->id("g-text");
+ $group->input("name")
+ ->label(t("Name"))
+ ->id("g-author")
+ ->error_messages("required", t("You must enter a name for yourself"));
+ $group->input("email")
+ ->label(t("Email (hidden)"))
+ ->id("g-email");
+ $group->input("url")
+ ->label(t("Website (hidden)"))
+ ->id("g-url");
+ $group->textarea("text")
+ ->label(t("Comment"))
+ ->id("g-text")
+ ->error_messages("required", t("You must enter a comment"));
$group->hidden("item_id")->value($item->id);
module::event("comment_add_form", $form);
$group->submit("")->value(t("Add"))->class("ui-state-default ui-corner-all");
@@ -80,10 +50,7 @@ class comment_Core {
$group->inputs["name"]->value($active->full_name)->disabled("disabled");
$group->email->value($active->email)->disabled("disabled");
$group->url->value($active->url)->disabled("disabled");
- } else {
- $group->inputs["name"]->error_messages("missing", t("You must provide a name"));
}
- $group->text->error_messages("missing", t("You must provide a comment"));
return $form;
}
diff --git a/modules/comment/helpers/comment_rss.php b/modules/comment/helpers/comment_rss.php
index 77044884..79fa07df 100644
--- a/modules/comment/helpers/comment_rss.php
+++ b/modules/comment/helpers/comment_rss.php
@@ -42,6 +42,7 @@ class comment_rss_Core {
$comments->where("item_id", "=", $id);
}
+ $feed = new stdClass();
$feed->view = "comment.mrss";
$feed->children = array();
foreach ($comments->find_all($limit, $offset) as $comment) {
diff --git a/modules/comment/models/comment.php b/modules/comment/models/comment.php
index e0b82039..d9d05995 100644
--- a/modules/comment/models/comment.php
+++ b/modules/comment/models/comment.php
@@ -54,30 +54,70 @@ class Comment_Model extends ORM {
}
/**
+ * Add some custom per-instance rules.
+ */
+ public function validate(Validation $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();
+ // 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);
+ }
- if (isset($created)) {
+ $visible_change = $this->state == "published";
+ parent::save();
module::event("comment_created", $this);
} else {
+ // Updated comment
+ $original = ORM::factory("comment", $this->id);
+ $visible_change = $original->state == "published" || $this->state == "published";
+ parent::save();
module::event("comment_updated", $original, $this);
}
// We only notify on the related items if we're making a visible change.
if ($visible_change) {
- module::event("item_related_update", $this->item());
+ $item = $this->item();
+ module::event("item_related_update", $item);
}
return $this;
@@ -92,4 +132,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..08f55b3f 100644
--- a/modules/comment/tests/Comment_Event_Test.php
+++ b/modules/comment/tests/Comment_Event_Test.php
@@ -17,16 +17,19 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Comment_Event_Test extends Unit_Test_Case {
+class Comment_Event_Test extends Gallery_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", $comment->id)->loaded());
}
}
diff --git a/modules/comment/tests/Comment_Helper_Test.php b/modules/comment/tests/Comment_Helper_Test.php
index 8e726869..7ba024c7 100644
--- a/modules/comment/tests/Comment_Helper_Test.php
+++ b/modules/comment/tests/Comment_Helper_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Comment_Helper_Test extends Unit_Test_Case {
+class Comment_Helper_Test extends Gallery_Unit_Test_Case {
private $_ip_address;
private $_user_agent;
@@ -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..f0449c05 100644
--- a/modules/comment/tests/Comment_Model_Test.php
+++ b/modules/comment/tests/Comment_Model_Test.php
@@ -17,24 +17,27 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Comment_Model_Test extends Unit_Test_Case {
+class Comment_Model_Test extends Gallery_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/comment/views/admin_block_recent_comments.html.php b/modules/comment/views/admin_block_recent_comments.html.php
index 99f72a30..4017e4f9 100644
--- a/modules/comment/views/admin_block_recent_comments.html.php
+++ b/modules/comment/views/admin_block_recent_comments.html.php
@@ -8,10 +8,16 @@
width="32"
height="32" />
<?= gallery::date_time($comment->created) ?>
+ <? if ($comment->author()->guest): ?>
+ <?= t('%author_name said <em>%comment_text</em>',
+ array("author_name" => html::clean($comment->author_name()),
+ "comment_text" => text::limit_words(nl2br(html::purify($comment->text)), 50))); ?>
+ <? else: ?>
<?= t('<a href="%url">%author_name</a> said <em>%comment_text</em>',
array("author_name" => html::clean($comment->author_name()),
"url" => user_profile::url($comment->author_id),
"comment_text" => text::limit_words(nl2br(html::purify($comment->text)), 50))); ?>
+ <? endif ?>
</li>
<? endforeach ?>
</ul>
diff --git a/modules/comment/views/comment.html.php b/modules/comment/views/comment.html.php
index c4cf1ce0..263e5f97 100644
--- a/modules/comment/views/comment.html.php
+++ b/modules/comment/views/comment.html.php
@@ -8,10 +8,16 @@
width="40"
height="40" />
</a>
+ <? if ($comment->author()->guest): ?>
+ <?= t("on %date_time, %name said",
+ array("date_time" => gallery::date_time($comment->created),
+ "name" => html::clean($comment->author_name()))) ?>
+ <? else: ?>
<?= t("on %date_time, <a href=\"%url\">%name</a> said",
array("date_time" => gallery::date_time($comment->created),
"url" => user_profile::url($comment->author_id),
"name" => html::clean($comment->author_name()))) ?>
+ <? endif ?>
</p>
<div>
<?= nl2br(html::purify($comment->text)) ?>
diff --git a/modules/comment/views/comments.html.php b/modules/comment/views/comments.html.php
index c8236997..0ed07c22 100644
--- a/modules/comment/views/comments.html.php
+++ b/modules/comment/views/comments.html.php
@@ -22,10 +22,16 @@
width="40"
height="40" />
</a>
+ <? if ($comment->author()->guest): ?>
+ <?= t('on %date %name said',
+ array("date" => date("Y-M-d H:i:s", $comment->created),
+ "name" => html::clean($comment->author_name()))); ?>
+ <? else: ?>
<?= t('on %date <a href="%url">%name</a> said',
array("date" => date("Y-M-d H:i:s", $comment->created),
"url" => user_profile::url($comment->author_id),
"name" => html::clean($comment->author_name()))); ?>
+ <? endif ?>
</p>
<div>
<?= nl2br(html::purify($comment->text)) ?>
diff --git a/modules/digibug/controllers/digibug.php b/modules/digibug/controllers/digibug.php
index 6e6009db..c98ae20c 100644
--- a/modules/digibug/controllers/digibug.php
+++ b/modules/digibug/controllers/digibug.php
@@ -36,7 +36,7 @@ class Digibug_Controller extends Controller {
}
$v = new View("digibug_form.html");
- $v->order_parms = array(
+ $v->order_params = array(
"digibug_api_version" => "100",
"company_id" => module::get_var("digibug", "company_id"),
"event_id" => module::get_var("digibug", "event_id"),
@@ -91,7 +91,7 @@ class Digibug_Controller extends Controller {
}
// We don't need to save the session for this request
- Session::abort_save();
+ Session::instance()->abort_save();
if (!TEST_MODE) {
// Dump out the image
diff --git a/modules/digibug/tests/Digibug_Controller_Test.php b/modules/digibug/tests/Digibug_Controller_Test.php
index 015a270a..561dd3c9 100644
--- a/modules/digibug/tests/Digibug_Controller_Test.php
+++ b/modules/digibug/tests/Digibug_Controller_Test.php
@@ -17,42 +17,42 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Digibug_Controller_Test extends Unit_Test_Case {
- private $_proxy;
- private $_item;
+class Digibug_Controller_Test extends Gallery_Unit_Test_Case {
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/digibug/views/digibug_form.html.php b/modules/digibug/views/digibug_form.html.php
index c6994cbe..af5a88b4 100644
--- a/modules/digibug/views/digibug_form.html.php
+++ b/modules/digibug/views/digibug_form.html.php
@@ -2,10 +2,12 @@
<html>
<body>
<?= form::open("http://www.digibug.com/dapi/order.php") ?>
- <?= form::hidden($order_parms) ?>
- <?= form::close() ?>
+ <? foreach ($order_params as $key => $value): ?>
+ <?= form::hidden($key, $value) ?>
+ <? endforeach ?>
+ </form>
<script type="text/javascript">
- document.forms[0].submit();
+ document.forms[0].submit();
</script>
</body>
</html>
diff --git a/modules/exif/helpers/exif_task.php b/modules/exif/helpers/exif_task.php
index 27352643..90869630 100644
--- a/modules/exif/helpers/exif_task.php
+++ b/modules/exif/helpers/exif_task.php
@@ -82,7 +82,7 @@ class exif_task_Core {
$task->done = true;
$task->state = "error";
$task->status = $e->getMessage();
- $task->log($e->__toString());
+ $task->log((string)$e);
}
}
}
diff --git a/modules/exif/tests/Exif_Test.php b/modules/exif/tests/Exif_Test.php
index 5c5a5cb1..e4835b7f 100644
--- a/modules/exif/tests/Exif_Test.php
+++ b/modules/exif/tests/Exif_Test.php
@@ -17,12 +17,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Exif_Test extends Unit_Test_Case {
+class Exif_Test extends Gallery_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/forge/libraries/Form_Group.php b/modules/forge/libraries/Form_Group.php
index e0601321..0a04912b 100644
--- a/modules/forge/libraries/Form_Group.php
+++ b/modules/forge/libraries/Form_Group.php
@@ -80,7 +80,7 @@ class Form_Group_Core extends Forge {
}
}
- public function render()
+ public function render($template = 'forge_template', $custom = FALSE)
{
// No Sir, we don't want any html today thank you
return;
diff --git a/modules/g2_import/controllers/admin_g2_import.php b/modules/g2_import/controllers/admin_g2_import.php
index 1c65f482..6dd155b9 100644
--- a/modules/g2_import/controllers/admin_g2_import.php
+++ b/modules/g2_import/controllers/admin_g2_import.php
@@ -19,6 +19,7 @@
*/
class Admin_g2_import_Controller extends Admin_Controller {
public function index() {
+ g2_import::lower_error_reporting();
if (g2_import::is_configured()) {
g2_import::init();
}
@@ -31,6 +32,7 @@ class Admin_g2_import_Controller extends Admin_Controller {
$view = new Admin_View("admin.html");
$view->content = new View("admin_g2_import.html");
$view->content->form = $this->_get_import_form();
+ $view->content->version = g2_import::version();
if (g2_import::is_initialized()) {
$view->content->g2_stats = $g2_stats;
@@ -38,11 +40,13 @@ class Admin_g2_import_Controller extends Admin_Controller {
$view->content->thumb_size = module::get_var("gallery", "thumb_size");
$view->content->resize_size = module::get_var("gallery", "resize_size");
}
+ g2_import::restore_error_reporting();
print $view;
}
public function save() {
access::verify_csrf();
+ g2_import::lower_error_reporting();
$form = $this->_get_import_form();
if ($form->validate()) {
@@ -63,6 +67,7 @@ class Admin_g2_import_Controller extends Admin_Controller {
$view = new Admin_View("admin.html");
$view->content = new View("admin_g2_import.html");
$view->content->form = $form;
+ g2_import::restore_error_reporting();
print $view;
}
diff --git a/modules/g2_import/controllers/g2.php b/modules/g2_import/controllers/g2.php
index 3e002758..5fd4400c 100644
--- a/modules/g2_import/controllers/g2.php
+++ b/modules/g2_import/controllers/g2.php
@@ -50,7 +50,7 @@ class G2_Controller extends Admin_Controller {
throw new Kohana_404_Exception();
}
- $item = ORM::factory("item")->where("id", "=", $g2_map->g3_id)->find();
+ $item = ORM::factory("item", $g2_map->g3_id);
if (!$item->loaded() || !access::can("view", $item)) {
throw new Kohana_404_Exception();
}
diff --git a/modules/g2_import/helpers/g2_import.php b/modules/g2_import/helpers/g2_import.php
index 8724ae50..0fcc0539 100644
--- a/modules/g2_import/helpers/g2_import.php
+++ b/modules/g2_import/helpers/g2_import.php
@@ -24,6 +24,7 @@ class g2_import_Core {
public static $g2_base_url = null;
private static $current_g2_item = null;
+ private static $error_reporting = null;
static function is_configured() {
return module::get_var("g2_import", "embed_path");
@@ -239,7 +240,7 @@ class g2_import_Core {
$g2_group = g2(GalleryCoreApi::loadEntitiesById($g2_group_id));
} catch (Exception $e) {
return t("Failed to import Gallery 2 group with id: %id\n%exception",
- array("id" => $g2_group_id, "exception" => $e->__toString()));
+ array("id" => $g2_group_id, "exception" => (string)$e));
}
switch ($g2_group->getGroupType()) {
@@ -295,21 +296,20 @@ class g2_import_Core {
$g2_user = g2(GalleryCoreApi::loadEntitiesById($g2_user_id));
} catch (Exception $e) {
return t("Failed to import Gallery 2 user with id: %id\n%exception",
- array("id" => $g2_user_id, "exception" => $e->__toString()));
+ array("id" => $g2_user_id, "exception" => (string)$e));
}
$g2_groups = g2(GalleryCoreApi::fetchGroupsForUser($g2_user->getId()));
- try {
+ $user = identity::lookup_user_by_name($g2_user->getUsername());
+ if ($user) {
+ $message = t("Loaded existing user: '%name'.", array("name" => $user->name));
+ } else {
$user = identity::create_user($g2_user->getUsername(), $g2_user->getfullname(), "");
$message = t("Created user: '%name'.", array("name" => $user->name));
- } catch (Exception $e) {
- // @todo For now we assume this is a "duplicate user" exception
- $user = identity::lookup_user_by_name($g2_user->getUsername());
- $message = t("Loaded existing user: '%name'.", array("name" => $user->name));
}
$user->hashed_password = $g2_user->getHashedPassword();
- $user->email = $g2_user->getEmail();
+ $user->email = $g2_user->getEmail() ? $g2_user->getEmail() : "unknown@unknown.com";
$user->locale = $g2_user->getLanguage();
foreach ($g2_groups as $g2_group_id => $g2_group_name) {
if ($g2_group_id == $g2_admin_group_id) {
@@ -353,7 +353,7 @@ class g2_import_Core {
$g2_album = g2(GalleryCoreApi::loadEntitiesById($g2_album_id));
} catch (Exception $e) {
return t("Failed to import Gallery 2 album with id: %id\n%exception",
- array("id" => $g2_album_id, "exception" => $e->__toString()));
+ array("id" => $g2_album_id, "exception" => (string)$e));
}
if ($g2_album->getParentId() == null) {
@@ -361,13 +361,13 @@ class g2_import_Core {
}
$parent_album = ORM::factory("item", self::map($g2_album->getParentId()));
- $album = album::create(
- $parent_album,
- $g2_album->getPathComponent(),
- self::_decode_html_special_chars($g2_album->getTitle()),
- self::_decode_html_special_chars(self::extract_description($g2_album)),
- self::map($g2_album->getOwnerId()));
-
+ $album = ORM::factory("item");
+ $album->type = "album";
+ $album->parent_id = self::map($g2_album->getParentId());
+ $album->name = $g2_album->getPathComponent();
+ $album->title = self::_decode_html_special_chars($g2_album->getTitle());
+ $album->description = self::_decode_html_special_chars(self::extract_description($g2_album));
+ $album->owner_id = self::map($g2_album->getOwnerId());
$album->view_count = g2(GalleryCoreApi::fetchItemViewCount($g2_album_id));
$album->created = $g2_album->getCreationTimestamp();
@@ -449,7 +449,7 @@ class g2_import_Core {
$g2_path = g2($g2_item->fetchPath());
} catch (Exception $e) {
return t("Failed to import Gallery 2 item with id: %id\n%exception",
- array("id" => $g2_item_id, "exception" => $e->__toString()));
+ array("id" => $g2_item_id, "exception" => (string)$e));
}
$parent = ORM::factory("item", self::map($g2_item->getParentId()));
@@ -482,19 +482,21 @@ class g2_import_Core {
$corrupt = 1;
}
try {
- $item = photo::create(
- $parent,
- $g2_path,
- $g2_item->getPathComponent(),
- self::_decode_html_special_chars($g2_item->getTitle()),
- self::_decode_html_special_chars(self::extract_description($g2_item)),
- self::map($g2_item->getOwnerId()));
+ $item = ORM::factory("item");
+ $item->type = "photo";
+ $item->parent_id = $parent->id;
+ $item->set_data_file($g2_path);
+ $item->name = $g2_item->getPathComponent();
+ $item->title = self::_decode_html_special_chars($g2_item->getTitle());
+ $item->description = self::_decode_html_special_chars(self::extract_description($g2_item));
+ $item->owner_id = self::map($g2_item->getOwnerId());
+ $item->save();
} catch (Exception $e) {
- Kohana_Log::add(
- "alert", "Corrupt image $g2_path\n" . $e->__toString());
+ Kohana_Log::add("alert", "Corrupt image $g2_path\n" . (string)$e);
$message[] = t("Corrupt image '%path'", array("path" => $g2_path));
- $message[] = $e->__toString();
+ $message[] = (string)$e;
$corrupt = 1;
+ $item = null;
}
break;
@@ -502,18 +504,19 @@ class g2_import_Core {
// @todo we should transcode other types into FLV
if (in_array($g2_item->getMimeType(), array("video/mp4", "video/x-flv"))) {
try {
- $item = movie::create(
- $parent,
- $g2_path,
- $g2_item->getPathComponent(),
- self::_decode_html_special_chars($g2_item->getTitle()),
- self::_decode_html_special_chars(self::extract_description($g2_item)),
- self::map($g2_item->getOwnerId()));
+ $item = ORM::factory("item");
+ $item->parent_id = $parent->id;
+ $item->set_data_file($g2_path);
+ $item->name = $g2_item->getPathComponent();
+ $item->title = self::_decode_html_special_chars($g2_item->getTitle());
+ $item->description = self::_decode_html_special_chars(self::extract_description($g2_item));
+ $item->owner_id = self::map($g2_item->getOwnerId());
} catch (Exception $e) {
- Kohana_Log::add("alert", "Corrupt movie $g2_path\n" . $e->__toString());
+ Kohana_Log::add("alert", "Corrupt movie $g2_path\n" . (string)$e);
$message[] = t("Corrupt movie '%path'", array("path" => $g2_path));
- $message[] = $e->__toString();
+ $message[] = (string)$e;
$corrupt = 1;
+ $item = null;
}
} else {
Kohana_Log::add("alert", "$g2_path is an unsupported movie type");
@@ -593,7 +596,7 @@ class g2_import_Core {
$g2_comment = g2(GalleryCoreApi::loadEntitiesById($g2_comment_id));
} catch (Exception $e) {
return t("Failed to import Gallery 2 comment with id: %id\%exception",
- array("id" => $g2_comment_id, "exception" => $e->__toString()));
+ array("id" => $g2_comment_id, "exception" => (string)$e));
}
$text = $g2_comment->getSubject();
@@ -631,15 +634,17 @@ class g2_import_Core {
GalleryCoreApi::requireOnce("modules/tags/classes/TagsHelper.class");
$g2_item_id = array_shift($queue);
$g3_item = ORM::factory("item", self::map($g2_item_id));
+ if (!$g3_item->loaded()) {
+ return;
+ }
try {
$tag_names = array_values(g2(TagsHelper::getTagsByItemId($g2_item_id)));
} catch (Exception $e) {
return t("Failed to import Gallery 2 tags for item with id: %id\n%exception",
- array("id" => $g2_item_id, "exception" => $e->__toString()));
+ array("id" => $g2_item_id, "exception" => (string)$e));
}
- // Multiword tags have the space changed to dots.s
foreach ($tag_names as $tag_name) {
tag::add($g3_item, $tag_name);
}
@@ -927,6 +932,16 @@ class g2_import_Core {
"useAuthToken" => false));
return str_replace(self::$g2_base_url, "", $url);
}
+
+ static function lower_error_reporting() {
+ // Gallery 2 was not designed to run in E_STRICT mode and will barf out errors. So dial down
+ // the error reporting when we make G2 calls.
+ self::$error_reporting = error_reporting(error_reporting() & ~E_STRICT);
+ }
+
+ static function restore_error_reporting() {
+ error_reporting(self::$error_reporting);
+ }
}
/**
diff --git a/modules/g2_import/helpers/g2_import_installer.php b/modules/g2_import/helpers/g2_import_installer.php
index 77b61d3e..1ec8afa9 100644
--- a/modules/g2_import/helpers/g2_import_installer.php
+++ b/modules/g2_import/helpers/g2_import_installer.php
@@ -31,7 +31,7 @@ class g2_import_installer {
KEY `g2_id` (`g2_id`))
DEFAULT CHARSET=utf8;");
- module::set_version("g2_import", 1);
+ module::set_version("g2_import", 2);
mkdir(VARPATH . "modules/g2_import");
}
diff --git a/modules/g2_import/helpers/g2_import_task.php b/modules/g2_import/helpers/g2_import_task.php
index e80b88b9..21ba4c3a 100644
--- a/modules/g2_import/helpers/g2_import_task.php
+++ b/modules/g2_import/helpers/g2_import_task.php
@@ -19,17 +19,19 @@
*/
class g2_import_task_Core {
static function available_tasks() {
+ g2_import::lower_error_reporting();
if (g2_import::is_configured()) {
g2_import::init();
}
-
+ $version = g2_import::version();
+ g2_import::restore_error_reporting();
if (class_exists("GalleryCoreApi")) {
return array(Task_Definition::factory()
->callback("g2_import_task::import")
->name(t("Import from Gallery 2"))
->description(
- t("Gallery %version detected", array("version" => g2_import::version())))
+ t("Gallery %version detected", array("version" => $version)))
->severity(log::SUCCESS));
}
@@ -37,6 +39,8 @@ class g2_import_task_Core {
}
static function import($task) {
+ g2_import::lower_error_reporting();
+
$start = microtime(true);
g2_import::init();
@@ -207,5 +211,7 @@ class g2_import_task_Core {
$task->set("mode", $mode);
$task->set("queue", $queue);
$task->set("done", $done);
+
+ g2_import::restore_error_reporting();
}
}
diff --git a/modules/g2_import/views/admin_g2_import.html.php b/modules/g2_import/views/admin_g2_import.html.php
index 0875e7f7..6a5214a3 100644
--- a/modules/g2_import/views/admin_g2_import.html.php
+++ b/modules/g2_import/views/admin_g2_import.html.php
@@ -34,7 +34,7 @@
<h2> <?= t("Import") ?> </h2>
<ul id="g-action-status" class="g-message-block">
<li class="g-success">
- <?= t("Gallery version %version detected", array("version" => g2_import::version())) ?>
+ <?= t("Gallery version %version detected", array("version" => $version)) ?>
</li>
<? if ($g2_sizes["thumb"]["size"] && $thumb_size != $g2_sizes["thumb"]["size"]): ?>
<li class="g-warning">
diff --git a/modules/gallery/config/locale.php b/modules/gallery/config/locale.php
index 4789dc2b..f8241444 100644
--- a/modules/gallery/config/locale.php
+++ b/modules/gallery/config/locale.php
@@ -32,7 +32,11 @@ $config['language'] = array('en_US', 'English_United States');
* Locale timezone. Defaults to use the server timezone.
* @see http://php.net/timezones
*/
-$config['timezone'] = '';
+$config['timezone'] = ini_get('date.timezone');
+if (empty($config['timezone'])) {
+ // This is a required field. Pick something as a default.
+ $config['timezone'] = "America/Los_Angeles";
+}
// i18n settings
diff --git a/modules/gallery/config/routes.php b/modules/gallery/config/routes.php
index 63cc6150..8ccd5a01 100644
--- a/modules/gallery/config/routes.php
+++ b/modules/gallery/config/routes.php
@@ -21,6 +21,10 @@
// Admin controllers are not available, except via /admin
$config["^admin_.*"] = null;
+// Redirect /form/add/admin/controller and /form/edit/admin/controller to
+// admin/controller/form_(add|edit)/parms. provides the same as below for admin pages
+$config["^form/(edit|add)/admin/(\w+)/(.*)$"] = "admin/$2/form_$1/$3";
+
// Redirect /form/add and /form/edit to the module/form_(add|edit)/parms.
$config["^form/(edit|add)/(\w+)/(.*)$"] = "$2/form_$1/$3";
diff --git a/modules/gallery/controllers/admin_dashboard.php b/modules/gallery/controllers/admin_dashboard.php
index 5f2cb41d..42a3c081 100644
--- a/modules/gallery/controllers/admin_dashboard.php
+++ b/modules/gallery/controllers/admin_dashboard.php
@@ -91,7 +91,5 @@ class Admin_Dashboard_Controller extends Admin_Controller {
}
block_manager::set_active($location, $new_blocks);
}
-
- $this->_force_block_adder();
}
}
diff --git a/modules/gallery/controllers/admin_maintenance.php b/modules/gallery/controllers/admin_maintenance.php
index aa4fb29f..3062ea09 100644
--- a/modules/gallery/controllers/admin_maintenance.php
+++ b/modules/gallery/controllers/admin_maintenance.php
@@ -215,7 +215,7 @@ class Admin_Maintenance_Controller extends Admin_Controller {
print json_encode(array("result" => "success",
"task" => array(
"percent_complete" => $task->percent_complete,
- "status" => $task->status,
+ "status" => (string) $task->status,
"done" => (bool) $task->done),
"location" => url::site("admin/maintenance")));
@@ -223,7 +223,7 @@ class Admin_Maintenance_Controller extends Admin_Controller {
print json_encode(array("result" => "in_progress",
"task" => array(
"percent_complete" => $task->percent_complete,
- "status" => $task->status,
+ "status" => (string) $task->status,
"done" => (bool) $task->done)));
}
}
diff --git a/modules/gallery/controllers/admin_modules.php b/modules/gallery/controllers/admin_modules.php
index 84fee25d..081b3f12 100644
--- a/modules/gallery/controllers/admin_modules.php
+++ b/modules/gallery/controllers/admin_modules.php
@@ -67,6 +67,7 @@ class Admin_Modules_Controller extends Admin_Controller {
}
private function _do_save() {
+ $changes = new stdClass();
$changes->activate = array();
$changes->deactivate = array();
$activated_names = array();
diff --git a/modules/gallery/controllers/albums.php b/modules/gallery/controllers/albums.php
index 2eeefdf1..a378f3ee 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,24 @@ 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->inputs["name"]->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) {
+ $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 +168,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/combined.php b/modules/gallery/controllers/combined.php
index e90a2f1a..7f3a3c7d 100644
--- a/modules/gallery/controllers/combined.php
+++ b/modules/gallery/controllers/combined.php
@@ -41,7 +41,7 @@ class Combined_Controller extends Controller {
$input = Input::instance();
// We don't need to save the session for this request
- Session::abort_save();
+ Session::instance()->abort_save();
// Our data is immutable, so if they already have a copy then it needs no updating.
if ($input->server("HTTP_IF_MODIFIED_SINCE")) {
diff --git a/modules/gallery/controllers/file_proxy.php b/modules/gallery/controllers/file_proxy.php
index 646edf17..33952366 100644
--- a/modules/gallery/controllers/file_proxy.php
+++ b/modules/gallery/controllers/file_proxy.php
@@ -121,7 +121,7 @@ class File_Proxy_Controller extends Controller {
expires::check(2592000, $item->updated);
// We don't need to save the session for this request
- Session::abort_save();
+ Session::instance()->abort_save();
expires::set(2592000, $item->updated); // 30 days
diff --git a/modules/gallery/controllers/login.php b/modules/gallery/controllers/login.php
index cfccaf17..1426f0d8 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));
}
}
@@ -64,11 +62,10 @@ class Login_Controller extends Controller {
if ($valid) {
$user = identity::lookup_user_by_name($form->login->inputs["name"]->value);
if (empty($user) || !identity::is_correct_password($user, $form->login->password->value)) {
- log::warning(
- "user",
- t("Failed login for %name",
- array("name" => $form->login->inputs["name"]->value)));
$form->login->inputs["name"]->add_error("invalid_login", 1);
+ $name = $form->login->inputs["name"]->value;
+ log::warning("user", t("Failed login for %name", array("name" => $name)));
+ module::event("user_login_failed", $name);
$valid = false;
}
}
diff --git a/modules/gallery/controllers/movies.php b/modules/gallery/controllers/movies.php
index 7a8e4d2a..b51282b3 100644
--- a/modules/gallery/controllers/movies.php
+++ b/modules/gallery/controllers/movies.php
@@ -61,48 +61,22 @@ 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->inputs["name"]->value;
+ $movie->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ $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 +92,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/packager.php b/modules/gallery/controllers/packager.php
index cb64f1bf..66626483 100644
--- a/modules/gallery/controllers/packager.php
+++ b/modules/gallery/controllers/packager.php
@@ -164,7 +164,7 @@ class Packager_Controller extends Controller {
foreach($objects as $name => $file){
if ($file->getBasename() == "database.php") {
continue;
- } else if (basename($file->getPath()) == "logs") {
+ } else if (basename($file->getPath()) == "logs" && $file->getBasename() != ".htaccess") {
continue;
}
@@ -172,8 +172,8 @@ class Packager_Controller extends Controller {
$paths[] = "VARPATH . \"" . substr($name, strlen(VARPATH)) . "\"";
} else {
// @todo: serialize non-directories
- print "IGNORING FILE: $name\n";
- return;
+ $files["VARPATH . \"" . substr($name, strlen(VARPATH)) . "\""] =
+ base64_encode(file_get_contents($name));
}
}
// Sort the paths so that the var file is stable
@@ -185,6 +185,9 @@ class Packager_Controller extends Controller {
foreach ($paths as $path) {
fwrite($fd, "!file_exists($path) && mkdir($path);\n");
}
+ foreach ($files as $file => $contents) {
+ fwrite($fd, "file_put_contents($file, base64_decode(\"$contents\"));\n");
+ }
fclose($fd);
}
} \ No newline at end of file
diff --git a/modules/gallery/controllers/photos.php b/modules/gallery/controllers/photos.php
index 56b454ce..b5da3884 100644
--- a/modules/gallery/controllers/photos.php
+++ b/modules/gallery/controllers/photos.php
@@ -61,48 +61,22 @@ 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->inputs["name"]->value;
+ $photo->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ $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 +92,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/quick.php b/modules/gallery/controllers/quick.php
index 7f9a9826..04aab8dc 100644
--- a/modules/gallery/controllers/quick.php
+++ b/modules/gallery/controllers/quick.php
@@ -47,6 +47,7 @@ class Quick_Controller extends Controller {
graphics::generate($item);
$parent = $item->parent();
+ // @todo: this is an inadequate way to regenerate the parent's thumbnail after rotation.
if ($parent->album_cover_item_id == $item->id) {
copy($item->thumb_path(), $parent->thumb_path());
$parent->thumb_width = $item->thumb_width;
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/controllers/user_profile.php b/modules/gallery/controllers/user_profile.php
index a0e6619e..327d2ff1 100644
--- a/modules/gallery/controllers/user_profile.php
+++ b/modules/gallery/controllers/user_profile.php
@@ -53,11 +53,11 @@ class User_Profile_Controller extends Controller {
if ($form->validate()) {
Sendmail::factory()
->to($user->email)
- ->subject($form->message->subject->value)
+ ->subject(html::clean($form->message->subject->value))
->header("Mime-Version", "1.0")
->header("Content-type", "text/html; charset=iso-8859-1")
->reply_to($form->message->reply_to->value)
- ->message($form->message->message->value)
+ ->message(html::purify($form->message->message->value))
->send();
message::success(t("Sent message to %user_name", array("user_name" => $user->display_name())));
print json_encode(array("result" => "success"));
diff --git a/modules/gallery/helpers/MY_url.php b/modules/gallery/helpers/MY_url.php
index 8a7909b6..323cae37 100644
--- a/modules/gallery/helpers/MY_url.php
+++ b/modules/gallery/helpers/MY_url.php
@@ -93,8 +93,8 @@ class url extends url_Core {
/**
* Just like url::merge except that it escapes any XSS in the path.
*/
- static function merge($params) {
- return htmlspecialchars(parent::merge($params));
+ static function merge(array $arguments) {
+ return htmlspecialchars(parent::merge($arguments));
}
/**
diff --git a/modules/gallery/helpers/access.php b/modules/gallery/helpers/access.php
index e0a0e979..29b981e8 100644
--- a/modules/gallery/helpers/access.php
+++ b/modules/gallery/helpers/access.php
@@ -183,10 +183,10 @@ class access_Core {
}
/**
- * Terminate immediately with an HTTP 503 Forbidden response.
+ * Terminate immediately with an HTTP 403 Forbidden response.
*/
static function forbidden() {
- throw new Exception("@todo FORBIDDEN", 503);
+ throw new Kohana_Exception("@todo FORBIDDEN", null, 403);
}
/**
@@ -663,23 +663,28 @@ class access_Core {
* working and our permission system works.
*/
static function htaccess_works() {
- $success_url = url::file("var/tmp/security_test/success");
+ $success_url = url::file("var/security_test/success");
- @mkdir(VARPATH . "tmp/security_test");
- if ($fp = @fopen(VARPATH . "tmp/security_test/.htaccess", "w+")) {
- fwrite($fp, "RewriteEngine On\n");
- fwrite($fp, "RewriteRule verify $success_url [L]\n");
- fclose($fp);
- }
+ @mkdir(VARPATH . "security_test");
+ try {
+ if ($fp = @fopen(VARPATH . "security_test/.htaccess", "w+")) {
+ fwrite($fp, "RewriteEngine On\n");
+ fwrite($fp, "RewriteRule verify $success_url [L]\n");
+ fclose($fp);
+ }
- if ($fp = @fopen(VARPATH . "tmp/security_test/success", "w+")) {
- fwrite($fp, "success");
- fclose($fp);
- }
+ if ($fp = @fopen(VARPATH . "security_test/success", "w+")) {
+ fwrite($fp, "success");
+ fclose($fp);
+ }
- list ($response) = remote::do_request(url::abs_file("var/tmp/security_test/verify"));
- $works = $response == "HTTP/1.1 200 OK";
- @dir::unlink(VARPATH . "tmp/security_test");
+ list ($response) = remote::do_request(url::abs_file("var/security_test/verify"));
+ $works = $response == "HTTP/1.1 200 OK";
+ } catch (Exception $e) {
+ @dir::unlink(VARPATH . "security_test");
+ throw $e;
+ }
+ @dir::unlink(VARPATH . "security_test");
return $works;
}
diff --git a/modules/gallery/helpers/album.php b/modules/gallery/helpers/album.php
index feaf74cc..389f6e48 100644
--- a/modules/gallery/helpers/album.php
+++ b/modules/gallery/helpers/album.php
@@ -24,90 +24,27 @@
* 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"));
$group = $form->group("add_album")
->label(t("Add an album to %album_title", array("album_title" => $parent->title)));
- $group->input("title")->label(t("Title"));
+ $group->input("title")->label(t("Title"))
+ ->error_messages("required", t("You must provide a title"))
+ ->error_messages("length", t("Your title is too long"));
$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"));
+ ->error_messages("no_slashes", t("The directory name can't contain the \"/\" character"))
+ ->error_messages("required", t("You must provide a directory name"))
+ ->error_messages("length", t("Your directory name is too long"));
$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"));
+ t("The internet address should contain only letters, numbers, hyphens and underscores"))
+ ->error_messages("required", t("You must provide an internet address"))
+ ->error_messages("length", t("Your internet address is too long"));
$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;
@@ -118,26 +55,28 @@ class album_Core {
$form->hidden("from_id");
$group = $form->group("edit_item")->label(t("Edit Album"));
- $group->input("title")->label(t("Title"))->value($parent->title);
+ $group->input("title")->label(t("Title"))->value($parent->title)
+ ->error_messages("required", t("You must provide a title"))
+ ->error_messages("length", t("Your title is too long"));
$group->textarea("description")->label(t("Description"))->value($parent->description);
if ($parent->id != 1) {
- $group->input("dirname")->label(t("Directory Name"))->value($parent->name)
- ->rules("required")
+ $group->input("name")->label(t("Directory Name"))->value($parent->name)
->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 \".\""));
+ ->error_messages("no_trailing_period", t("The directory name can't end in \".\""))
+ ->error_messages("required", t("You must provide a directory name"))
+ ->error_messages("length", t("Your directory name is too long"));
$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"));
+ t("The internet address should contain only letters, numbers, hyphens and underscores"))
+ ->error_messages("required", t("You must provide an internet address"))
+ ->error_messages("length", t("Your internet address is too long"));
} else {
- $group->hidden("dirname")->value($parent->name);
+ $group->hidden("name")->value($parent->name);
$group->hidden("slug")->value($parent->slug);
}
@@ -159,7 +98,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/auth.php b/modules/gallery/helpers/auth.php
index 21a39bfb..16f8915a 100644
--- a/modules/gallery/helpers/auth.php
+++ b/modules/gallery/helpers/auth.php
@@ -22,7 +22,10 @@ class auth_Core {
$form = new Forge($url, "", "post", array("id" => "g-login-form"));
$form->set_attr('class', "g-narrow");
$group = $form->group("login")->label(t("Login"));
- $group->input("name")->label(t("Username"))->id("g-username")->class(null);
+ $group->input("name")->label(t("Username"))->id("g-username")->class(null)
+ ->callback("auth::validate_too_many_failed_logins")
+ ->error_messages(
+ "too_many_failed_logins", t("Too many failed login attempts. Try again later"));
$group->password("password")->label(t("Password"))->id("g-password")->class(null);
$group->inputs["name"]->error_messages("invalid_login", t("Invalid name or password"));
$group->submit("")->value(t("Login"));
@@ -30,12 +33,12 @@ class auth_Core {
}
static function login($user) {
+ identity::set_active_user($user);
if (identity::is_writable()) {
$user->login_count += 1;
$user->last_login = time();
$user->save();
}
- identity::set_active_user($user);
log::info("user", t("User %name logged in", array("name" => $user->name)));
module::event("user_login", $user);
}
@@ -51,6 +54,52 @@ class auth_Core {
module::event("user_logout", $user);
}
log::info("user", t("User %name logged out", array("name" => $user->name)),
- html::anchor("user/$user->id", html::clean($user->name)));
+ t('<a href="%url">%user_name</a>',
+ array("url" => user_profile::url($user->id),
+ "user_name" => html::clean($user->name))));
+ }
+
+ /**
+ * After there have been 5 failed login attempts, any failure leads to getting locked out for a
+ * minute.
+ */
+ static function too_many_failed_logins($name) {
+ $failed_login = ORM::factory("failed_login")
+ ->where("name", "=", $name)
+ ->find();
+ return ($failed_login->loaded() &&
+ $failed_login->count > 5 &&
+ (time() - $failed_login->time < 60));
+ }
+
+ static function validate_too_many_failed_logins($name_input) {
+ if (self::too_many_failed_logins($name_input->value)) {
+ $name_input->add_error("too_many_failed_logins", 1);
+ }
+ }
+
+ /**
+ * Record a failed login for this user
+ */
+ static function record_failed_login($name) {
+ $failed_login = ORM::factory("failed_login")
+ ->where("name", "=", $name)
+ ->find();
+ if (!$failed_login->loaded()) {
+ $failed_login->name = $name;
+ }
+ $failed_login->time = time();
+ $failed_login->count++;
+ $failed_login->save();
+ }
+
+ /**
+ * Clear any failed logins for this user
+ */
+ static function record_successful_login($user) {
+ db::build()
+ ->delete("failed_logins")
+ ->where("name", "=", $user->name)
+ ->execute();
}
} \ No newline at end of file
diff --git a/modules/gallery/helpers/gallery_block.php b/modules/gallery/helpers/gallery_block.php
index 9d4e81b6..be0f11b8 100644
--- a/modules/gallery/helpers/gallery_block.php
+++ b/modules/gallery/helpers/gallery_block.php
@@ -72,7 +72,7 @@ class gallery_block_Core {
$block->content = new View("admin_block_platform.html");
if (is_readable("/proc/loadavg")) {
$block->content->load_average =
- join(" ", array_slice(explode(" ", array_shift(file("/proc/loadavg"))), 0, 3));
+ join(" ", array_slice(explode(" ", current(file("/proc/loadavg"))), 0, 3));
} else {
$block->content->load_average = t("Unavailable");
}
diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php
index b35ae3c4..6479e2c3 100644
--- a/modules/gallery/helpers/gallery_event.php
+++ b/modules/gallery/helpers/gallery_event.php
@@ -75,6 +75,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) {
@@ -92,6 +110,11 @@ class gallery_event_Core {
graphics::choose_default_toolkit();
module::clear_var("gallery", "choose_default_tookit");
}
+ auth::record_successful_login($user);
+ }
+
+ static function user_login_failed($name) {
+ auth::record_failed_login($name);
}
static function item_index_data($item, $data) {
@@ -268,6 +291,7 @@ class gallery_event_Core {
->label(t("Options"))
->css_class("ui-icon-carat-1-n"));
+ $page_type = $theme->page_type();
if (access::can("edit", $item)) {
switch ($item->type) {
case "movie":
@@ -306,7 +330,7 @@ class gallery_event_Core {
->css_class("ui-icon-rotate-ccw")
->ajax_handler("function(data) { " .
"\$.gallery_replace_image(data, \$('$thumb_css_selector')) }")
- ->url(url::site("quick/rotate/$item->id/ccw?csrf=$csrf&from_id=$theme_item->id")))
+ ->url(url::site("quick/rotate/$item->id/ccw?csrf=$csrf&from_id=$theme_item->id&page_type=$page_type")))
->append(
Menu::factory("ajax_link")
->id("rotate_cw")
@@ -314,7 +338,7 @@ class gallery_event_Core {
->css_class("ui-icon-rotate-cw")
->ajax_handler("function(data) { " .
"\$.gallery_replace_image(data, \$('$thumb_css_selector')) }")
- ->url(url::site("quick/rotate/$item->id/cw?csrf=$csrf&from_id=$theme_item->id")));
+ ->url(url::site("quick/rotate/$item->id/cw?csrf=$csrf&from_id=$theme_item->id&page_type=$page_type")));
}
// @todo Don't move photos from the photo page; we don't yet have a good way of redirecting
@@ -354,7 +378,7 @@ class gallery_event_Core {
->label($delete_title)
->css_class("ui-icon-trash")
->css_id("g-quick-delete")
- ->url(url::site("quick/form_delete/$item->id?csrf=$csrf&from_id=$theme_item->id")));
+ ->url(url::site("quick/form_delete/$item->id?csrf=$csrf&from_id=$theme_item->id&page_type=$page_type")));
}
if ($item->is_album()) {
@@ -386,14 +410,14 @@ class gallery_event_Core {
if (!$data->display_all) {
$fields = array("name" => t("Name"), "full_name" => t("Full name"), "url" => "Web site");
}
- $v->fields = array();
+ $v->user_profile_data = array();
foreach ($fields as $field => $label) {
if (!empty($data->user->$field)) {
$value = $data->user->$field;
if ($field == "locale") {
$value = locales::display_name($value);
}
- $v->fields[(string) $label] = html::clean($value);
+ $v->user_profile_data[(string) $label] = $value;
}
}
$data->content[] = (object) array("title" => t("User information"), "view" => $v);
diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php
index 1e0ad28c..bffef8e6 100644
--- a/modules/gallery/helpers/gallery_installer.php
+++ b/modules/gallery/helpers/gallery_installer.php
@@ -42,6 +42,14 @@ class gallery_installer {
KEY (`tags`))
DEFAULT CHARSET=utf8;");
+ $db->query("CREATE TABLE {failed_logins} (
+ `id` int(9) NOT NULL auto_increment,
+ `count` int(9) NOT NULL,
+ `name` varchar(255) NOT NULL,
+ `time` int(9) NOT NULL,
+ PRIMARY KEY (`id`))
+ DEFAULT CHARSET=utf8;");
+
$db->query("CREATE TABLE {graphics_rules} (
`id` int(9) NOT NULL auto_increment,
`active` BOOLEAN default 0,
@@ -196,6 +204,9 @@ class gallery_installer {
foreach (array("albums", "logs", "modules", "resizes", "thumbs", "tmp", "uploads") as $dir) {
@mkdir(VARPATH . $dir);
+ if (in_array($dir, array("logs", "tmp", "uploads"))) {
+ self::_protect_directory(VARPATH . $dir);
+ }
}
access::register_permission("view", "View");
@@ -209,19 +220,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", 1);
access::add_item($root);
module::set_var("gallery", "active_site_theme", "wind");
@@ -269,7 +287,7 @@ class gallery_installer {
// @todo this string needs to be picked up by l10n_scanner
module::set_var("gallery", "credits", "Powered by <a href=\"%url\">Gallery %version</a>");
module::set_var("gallery", "simultaneous_upload_limit", 5);
- module::set_version("gallery", 21);
+ module::set_version("gallery", 25);
}
static function upgrade($version) {
@@ -443,7 +461,7 @@ class gallery_installer {
// Update the graphics rules table so that the maximum height for resizes is 640 not 480.
// Fixes ticket #671
- if ( $version == 21) {
+ if ($version == 21) {
$resize_rule = ORM::factory("graphics_rule")
->where("id", "=", "2")
->find();
@@ -456,6 +474,46 @@ class gallery_installer {
}
module::set_version("gallery", $version = 22);
}
+
+ // Update slug values to be legal. We should have done this in the 11->12 upgrader, but I was
+ // lazy. Mea culpa!
+ if ($version == 22) {
+ foreach (db::build()
+ ->from("items")
+ ->select("id", "slug")
+ ->where(new Database_Expression("`slug` REGEXP '[^_A-Za-z0-9-]'"), "=", 1)
+ ->execute() as $row) {
+ $new_slug = item::convert_filename_to_slug($row->slug);
+ if (empty($new_slug)) {
+ $new_slug = rand();
+ }
+ db::build()
+ ->update("items")
+ ->set("slug", $new_slug)
+ ->set("relative_url_cache", null)
+ ->where("id", "=", $row->id)
+ ->execute();
+ }
+ module::set_version("gallery", $version = 23);
+ }
+
+ if ($version == 23) {
+ $db->query("CREATE TABLE {failed_logins} (
+ `id` int(9) NOT NULL auto_increment,
+ `count` int(9) NOT NULL,
+ `name` varchar(255) NOT NULL,
+ `time` int(9) NOT NULL,
+ PRIMARY KEY (`id`))
+ DEFAULT CHARSET=utf8;");
+ module::set_version("gallery", $version = 24);
+ }
+
+ if ($version == 24) {
+ foreach (array("logs", "tmp", "uploads") as $dir) {
+ self::_protect_directory(VARPATH . $dir);
+ }
+ module::set_version("gallery", $version = 25);
+ }
}
static function uninstall() {
@@ -464,6 +522,7 @@ class gallery_installer {
$db->query("DROP TABLE IF EXISTS {access_intents}");
$db->query("DROP TABLE IF EXISTS {graphics_rules}");
$db->query("DROP TABLE IF EXISTS {incoming_translations}");
+ $db->query("DROP TABLE IF EXISTS {failed_logins}");
$db->query("DROP TABLE IF EXISTS {items}");
$db->query("DROP TABLE IF EXISTS {logs}");
$db->query("DROP TABLE IF EXISTS {modules}");
@@ -479,4 +538,12 @@ class gallery_installer {
system("/bin/rm -rf " . VARPATH . $entry);
}
}
+
+ static function _protect_directory($dir) {
+ $fp = @fopen("$dir/.htaccess", "w+");
+ fwrite($fp, "DirectoryIndex .htaccess\nSetHandler Gallery_Security_Do_Not_Remove\n" .
+ "Options None\n<IfModule mod_rewrite.c>\nRewriteEngine off\n</IfModule>\n" .
+ "Order allow,deny\nDeny from all\n");
+ fclose($fp);
+ }
}
diff --git a/modules/gallery/helpers/gallery_rest.php b/modules/gallery/helpers/gallery_rest.php
deleted file mode 100644
index a87ebb4e..00000000
--- a/modules/gallery/helpers/gallery_rest.php
+++ /dev/null
@@ -1,248 +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 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();
-
- log::success("content", "Updated $item->type",
- "<a href=\"{$item->type}s/$item->id\">view</a>");
-
- return rest::success();
- } else {
- return rest::validation_error($errors);
- }
- }
-
- static function post($request) {
- if (empty($request->arguments)) {
- throw new Rest_Exception(400, "Bad request");
- }
-
- $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($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");
- } else {
- $new_item =
- photo::create($parent, $temp_filename, $new_values["name"], $new_values["title"]);
- $log_message = t("Added a photo");
- }
- }
-
- 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");
- }
- $path = implode("/", $request->arguments);
-
- $item = gallery_rest::_get_item($path, "edit");
-
- if ($item->id == 1) {
- throw new Rest_Exception(400, "Bad request");
- }
-
- $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)));
- }
- log::success("content", $msg);
-
- return rest::success(array("resource" => array("parent_path" => $parent->relative_url())));
- }
-
- 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();
- }
-
- return $item;
- }
-
- 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);
- }
-
- return $children;
- }
-
- 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");
- }
- }
-
- return $new_values;
- }
-
- 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;
- }
-}
diff --git a/modules/gallery/helpers/gallery_rss.php b/modules/gallery/helpers/gallery_rss.php
index d422636f..c1790d28 100644
--- a/modules/gallery/helpers/gallery_rss.php
+++ b/modules/gallery/helpers/gallery_rss.php
@@ -25,6 +25,7 @@ class gallery_rss_Core {
}
static function feed($feed_id, $offset, $limit, $id) {
+ $feed = new stdClass();
switch ($feed_id) {
case "latest":
$feed->children = ORM::factory("item")
diff --git a/modules/gallery/helpers/gallery_task.php b/modules/gallery/helpers/gallery_task.php
index 5402b5d1..3e6278e5 100644
--- a/modules/gallery/helpers/gallery_task.php
+++ b/modules/gallery/helpers/gallery_task.php
@@ -40,7 +40,7 @@ class gallery_task_Core {
$tasks[] = Task_Definition::factory()
->callback("gallery_task::file_cleanup")
->name(t("Remove old files"))
- ->description(t("Remove files from the logs and tmp directory"))
+ ->description(t("Remove expired files from the logs and tmp directory"))
->severity(log::SUCCESS);
return $tasks;
}
@@ -81,7 +81,7 @@ class gallery_task_Core {
} catch (Exception $e) {
$errors[] = t("Unable to rebuild images for '%title'",
array("title" => html::purify($item->title)));
- $errors[] = $e->__toString();
+ $errors[] = (string)$e;
$ignored[$item->id] = 1;
}
}
@@ -111,10 +111,11 @@ class gallery_task_Core {
site_status::clear("graphics_dirty");
}
} catch (Exception $e) {
+ Kohana_Log::add("error",(string)$e);
$task->done = true;
$task->state = "error";
$task->status = $e->getMessage();
- $errors[] = $e->__toString();
+ $errors[] = (string)$e;
}
if ($errors) {
$task->log($errors);
@@ -214,10 +215,11 @@ class gallery_task_Core {
Cache::instance()->delete("update_l10n_cache:{$task->id}");
}
} catch (Exception $e) {
+ Kohana_Log::add("error",(string)$e);
$task->done = true;
$task->state = "error";
$task->status = $e->getMessage();
- $errors[] = $e->__toString();
+ $errors[] = (string)$e;
}
if ($errors) {
$task->log($errors);
@@ -233,13 +235,13 @@ class gallery_task_Core {
try {
$start = microtime(true);
$data = Cache::instance()->get("file_cleanup_cache:{$task->id}");
- if ($data) {
- $files = unserialize($data);
- }
+ $files = $data ? unserialize($data) : array();
$i = 0;
+ $current = 0;
+ $total = 0;
switch ($task->get("mode", "init")) {
- case "init": // 0%
+ case "init":
$threshold = time() - 1209600; // older than 2 weeks
foreach(array("logs", "tmp") as $dir) {
$dir = VARPATH . $dir;
@@ -262,6 +264,7 @@ class gallery_task_Core {
if (count($files) == 0) {
break;
}
+
case "delete_files":
$current = $task->get("current");
$total = $task->get("total");
@@ -273,18 +276,21 @@ class gallery_task_Core {
$task->set("current", $current);
}
- $task->status = t("Removed: %count files. Total: %total_count.",
- array("count" => $current, "total_count" => $total));
+ $task->status = t2("Removed: 1 file. Total: %total_count.",
+ "Removed: %count files. Total: %total_count.",
+ $current, array("total_count" => $total));
if ($total == $current) {
$task->done = true;
$task->state = "success";
+ $task->percent_complete = 100;
}
} catch (Exception $e) {
+ Kohana_Log::add("error",(string)$e);
$task->done = true;
$task->state = "error";
$task->status = $e->getMessage();
- $errors[] = $e->__toString();
+ $errors[] = (string)$e;
}
if ($errors) {
$task->log($errors);
diff --git a/modules/gallery/helpers/graphics.php b/modules/gallery/helpers/graphics.php
index 5a290905..c85c7750 100644
--- a/modules/gallery/helpers/graphics.php
+++ b/modules/gallery/helpers/graphics.php
@@ -262,6 +262,9 @@ class graphics_Core {
*/
static function detect_toolkits() {
$toolkits = new stdClass();
+ $toolkits->gd = new stdClass();
+ $toolkits->imagemagick = new stdClass();
+ $toolkits->graphicsmagick = new stdClass();
// GD is special, it doesn't use exec()
$gd = function_exists("gd_info") ? gd_info() : array();
diff --git a/modules/gallery/helpers/identity.php b/modules/gallery/helpers/identity.php
index eae0ea3e..6df860d6 100644
--- a/modules/gallery/helpers/identity.php
+++ b/modules/gallery/helpers/identity.php
@@ -68,9 +68,7 @@ class identity_Core {
// upconvert into a user.
// @todo set the user name into the session instead of 2 and then use it to get the user object
if ($user === 2) {
- $user = IdentityProvider::instance()->admin_user();
- self::set_active_user($user);
- $session->set("user", $user);
+ auth::login(IdentityProvider::instance()->admin_user());
}
if (!$session->get("group_ids")) {
@@ -82,7 +80,7 @@ class identity_Core {
}
} catch (Exception $e) {
// Log it, so we at least have so notification that we swallowed the exception.
- Kohana_Log::add("error", "Load_user Exception: " .
+ Kohana_Log::add("error", "load_user Exception: " .
$e->getMessage() . "\n" . $e->getTraceAsString());
try {
Session::instance()->destroy();
@@ -155,8 +153,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..41d49ce9 100644
--- a/modules/gallery/helpers/item.php
+++ b/modules/gallery/helpers/item.php
@@ -39,7 +39,8 @@ class item_Core {
}
}
- $source->move_to($target);
+ $source->parent_id = $target->id;
+ $source->save();
// If the target has no cover item, make this it.
if ($target->album_cover_item_id == null) {
@@ -59,7 +60,8 @@ class item_Core {
$parent->save();
graphics::generate($parent);
$grand_parent = $parent->parent();
- if ($grand_parent && $grand_parent->album_cover_item_id == null) {
+ if ($grand_parent && access::can("edit", $grand_parent) &&
+ $grand_parent->album_cover_item_id == null) {
item::make_album_cover($parent);
}
}
@@ -78,24 +80,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 +157,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/item_rest.php b/modules/gallery/helpers/item_rest.php
new file mode 100644
index 00000000..c0fc422a
--- /dev/null
+++ b/modules/gallery/helpers/item_rest.php
@@ -0,0 +1,176 @@
+<?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 item_rest_Core {
+ /**
+ * 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);
+
+ $p = $request->params;
+ if (isset($p->random)) {
+ $orm = item::random_query()->offset(0)->limit(1);
+ } else {
+ $orm = ORM::factory("item")->viewable();
+ }
+
+ if (empty($p->scope)) {
+ $p->scope = "direct";
+ }
+
+ if (!in_array($p->scope, array("direct", "all"))) {
+ throw new Rest_Exception("Bad Request", 400);
+ }
+
+ if ($p->scope == "direct") {
+ $orm->where("parent_id", "=", $item->id);
+ } else {
+ $orm->where("left_ptr", ">", $item->left_ptr);
+ $orm->where("right_ptr", "<", $item->right_ptr);
+ }
+
+ if (isset($p->name)) {
+ $orm->where("name", "LIKE", "%{$p->name}%");
+ }
+
+ if (isset($p->type)) {
+ $orm->where("type", "IN", explode(",", $p->type));
+ }
+
+ $members = array();
+ foreach ($orm->find_all() as $child) {
+ $members[] = rest::url("item", $child);
+ }
+
+ return array(
+ "url" => $request->url,
+ "entity" => $item->as_restful_array(),
+ "members" => $members,
+ "relationships" => rest::relationships("item", $item));
+ }
+
+ 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", "captured", "description",
+ "height", "mime_type", "name", "parent", "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) {
+ switch ($key) {
+ case "album_cover":
+ if (property_exists($request->params, "album_cover")) {
+ $album_cover_item = rest::resolve($request->params->album_cover);
+ access::required("view", $album_cover_item);
+ $item->album_cover_item_id = $album_cover_item->id;
+ }
+ break;
+
+ case "parent":
+ if (property_exists($request->params, "parent")) {
+ $parent = rest::resolve($request->params->parent);
+ access::required("edit", $parent);
+ $item->parent_id = $parent->id;
+ }
+ break;
+ default:
+ if (property_exists($request->params, $key)) {
+ $item->$key = $request->params->$key;
+ }
+ }
+ }
+ $item->save();
+ }
+
+ 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->slug = isset($params->slug) ? $params->slug : 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 : $params->name;
+ $item->description = isset($params->description) ? $params->description : null;
+ $item->slug = isset($params->slug) ? $params->slug : null;
+ $item->save();
+ break;
+
+ default:
+ throw new Rest_Exception("Invalid type: $params->type", 400);
+ }
+
+ return array("url" => rest::url("item", $item));
+ }
+
+ static function delete($request) {
+ $item = rest::resolve($request->url);
+ access::required("edit", $item);
+
+ $item->delete();
+ }
+
+ static function resolve($id) {
+ $item = ORM::factory("item", $id);
+ if (!access::can("view", $item)) {
+ throw new Kohana_404_Exception();
+ }
+ return $item;
+ }
+
+ static function url($item) {
+ return url::abs_site("rest/item/{$item->id}");
+ }
+}
diff --git a/modules/gallery/helpers/l10n_client.php b/modules/gallery/helpers/l10n_client.php
index 086245e8..c27e4e5b 100644
--- a/modules/gallery/helpers/l10n_client.php
+++ b/modules/gallery/helpers/l10n_client.php
@@ -77,6 +77,7 @@ class l10n_client_Core {
* translations for.
*/
static function fetch_updates(&$num_fetched) {
+ $request = new stdClass();
$request->locales = array();
$request->messages = new stdClass();
diff --git a/modules/gallery/helpers/locales.php b/modules/gallery/helpers/locales.php
index 5c8c227a..dc32b12f 100644
--- a/modules/gallery/helpers/locales.php
+++ b/modules/gallery/helpers/locales.php
@@ -238,7 +238,9 @@ class locales_Core {
}
static function cookie_locale() {
- $cookie_data = Input::instance()->cookie("g_locale");
+ // Can't use Input framework for client side cookies since
+ // they're not signed.
+ $cookie_data = isset($_COOKIE["g_locale"]) ? $_COOKIE["g_locale"] : null;
$locale = null;
if ($cookie_data) {
if (preg_match("/^([a-z]{2,3}(?:_[A-Z]{2})?)$/", trim($cookie_data), $matches)) {
diff --git a/modules/gallery/helpers/module.php b/modules/gallery/helpers/module.php
index 95e426c4..9523d1d2 100644
--- a/modules/gallery/helpers/module.php
+++ b/modules/gallery/helpers/module.php
@@ -430,7 +430,8 @@ class module_Core {
// This could happen if there's a race condition
continue;
}
- self::$var_cache->{$row->module_name}->{$row->name} = $row->value;
+ // Mute the "Creating default object from empty value" warning below
+ @self::$var_cache->{$row->module_name}->{$row->name} = $row->value;
}
$cache = ORM::factory("var");
$cache->module_name = "gallery";
diff --git a/modules/gallery/helpers/movie.php b/modules/gallery/helpers/movie.php
index 01859924..7033b7da 100644
--- a/modules/gallery/helpers/movie.php
+++ b/modules/gallery/helpers/movie.php
@@ -24,138 +24,36 @@
* 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");
$group = $form->group("edit_item")->label(t("Edit Movie"));
- $group->input("title")->label(t("Title"))->value($movie->title);
+ $group->input("title")->label(t("Title"))->value($movie->title)
+ ->error_messages("required", t("You must provide a title"))
+ ->error_messages("length", t("Your title is too long"));
$group->textarea("description")->label(t("Description"))->value($movie->description);
- $group->input("filename")->label(t("Filename"))->value($movie->name)
- ->rules("required")
+ $group->input("name")->label(t("Filename"))->value($movie->name)
->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"));
+ ->error_messages("illegal_data_file_extension", t("You cannot change the movie file extension"))
+ ->error_messages("required", t("You must provide a movie file name"))
+ ->error_messages("length", t("Your movie file name is too long"));
$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"));
+ t("The internet address should contain only letters, numbers, hyphens and underscores"))
+ ->error_messages("required", t("You must provide an internet address"))
+ ->error_messages("length", t("Your internet address is too long"));
module::event("item_edit_form", $movie, $form);
$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..bbdf2e3b 100644
--- a/modules/gallery/helpers/photo.php
+++ b/modules/gallery/helpers/photo.php
@@ -24,147 +24,34 @@
* 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");
$group = $form->group("edit_item")->label(t("Edit Photo"));
- $group->input("title")->label(t("Title"))->value($photo->title);
+ $group->input("title")->label(t("Title"))->value($photo->title)
+ ->error_messages("required", t("You must provide a title"))
+ ->error_messages("length", t("Your title is too long"));
$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")
+ $group->input("name")->label(t("Filename"))->value($photo->name)
+ ->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"));
+ ->error_messages("illegal_data_file_extension", t("You cannot change the photo file extension"))
+ ->error_messages("required", t("You must provide a photo file name"))
+ ->error_messages("length", t("Your photo file name is too long"));
$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"));
+ t("The internet address should contain only letters, numbers, hyphens and underscores"))
+ ->error_messages("required", t("You must provide an internet address"))
+ ->error_messages("length", t("Your internet address is too long"));
module::event("item_edit_form", $photo, $form);
$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/task.php b/modules/gallery/helpers/task.php
index 4aa95f33..645850d1 100644
--- a/modules/gallery/helpers/task.php
+++ b/modules/gallery/helpers/task.php
@@ -84,8 +84,15 @@ class task_Core {
}
$task->save();
} catch (Exception $e) {
- Kohana_Log::add("error", $e->__toString());
- $task->log($e->__toString());
+ Kohana_Log::add("error", (string)$e);
+
+ // 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));
+ }
+
+ $task->log((string)$e);
$task->state = "error";
$task->done = true;
$task->status = substr($e->getMessage(), 0, 255);
diff --git a/modules/gallery/libraries/Form_Script.php b/modules/gallery/libraries/Form_Script.php
index e841408d..1f965767 100644
--- a/modules/gallery/libraries/Form_Script.php
+++ b/modules/gallery/libraries/Form_Script.php
@@ -50,7 +50,7 @@ class Form_Script_Core extends Forge {
return $this;
}
- public function render() {
+ public function render($template="forge_template", $custom=false) {
$script = array();
if (!empty($this->data["url"])) {
$script[] = html::script($this->data["url"]);
@@ -63,4 +63,4 @@ class Form_Script_Core extends Forge {
return implode("\n", $script);
}
-} // End Form Script \ No newline at end of file
+} \ No newline at end of file
diff --git a/modules/gallery/libraries/IdentityProvider.php b/modules/gallery/libraries/IdentityProvider.php
index 2ed85bd1..3f1666eb 100644
--- a/modules/gallery/libraries/IdentityProvider.php
+++ b/modules/gallery/libraries/IdentityProvider.php
@@ -83,7 +83,7 @@ class IdentityProvider_Core {
module::event("identity_provider_changed", $current_provider, $new_provider);
- auth::login($provider->admin_user());
+ identity::set_active_user($provider->admin_user());
Session::instance()->regenerate();
} catch (Exception $e) {
static $restore_already_running;
@@ -174,8 +174,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/InPlaceEdit.php b/modules/gallery/libraries/InPlaceEdit.php
index 67ab3805..04a2e9a5 100644
--- a/modules/gallery/libraries/InPlaceEdit.php
+++ b/modules/gallery/libraries/InPlaceEdit.php
@@ -70,7 +70,6 @@ class InPlaceEdit_Core {
public function render() {
$v = new View("in_place_edit.html");
- $v->hidden = array("csrf" => access::csrf_token());
$v->action = url::site($this->action);
$v->form = $this->form;
$v->errors = $this->errors;
diff --git a/modules/gallery/libraries/MY_Database.php b/modules/gallery/libraries/MY_Database.php
index 61f23fb0..e2ef68cd 100644
--- a/modules/gallery/libraries/MY_Database.php
+++ b/modules/gallery/libraries/MY_Database.php
@@ -38,7 +38,7 @@ abstract class Database extends Database_Core {
* Parse the query string and convert any strings of the form `\([a-zA-Z0-9_]*?)\]
* table prefix . $1
*/
- public function query($sql = '') {
+ public function query($sql) {
if (!empty($sql)) {
$sql = $this->add_table_prefixes($sql);
}
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_Kohana_Exception.php b/modules/gallery/libraries/MY_Kohana_Exception.php
index dd5998a1..1c40091a 100644
--- a/modules/gallery/libraries/MY_Kohana_Exception.php
+++ b/modules/gallery/libraries/MY_Kohana_Exception.php
@@ -28,4 +28,11 @@ class Kohana_Exception extends Kohana_Exception_Core {
$e->getFile(), $e->getLine(),
$e->getTraceAsString());
}
+
+ public static function handle(Exception $e) {
+ if ($e instanceof ORM_Validation_Exception) {
+ Kohana_Log::add("error", "Validation errors: " . print_r($e->validation->errors(), 1));
+ }
+ return parent::handle($e);
+ }
} \ No newline at end of file
diff --git a/modules/gallery/libraries/MY_ORM.php b/modules/gallery/libraries/MY_ORM.php
index 198a430b..a158d853 100644
--- a/modules/gallery/libraries/MY_ORM.php
+++ b/modules/gallery/libraries/MY_ORM.php
@@ -18,41 +18,9 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class ORM extends ORM_Core {
- // Track the original value of this ORM so that we can look it up in ORM::original()
- protected $original = null;
-
public function save() {
model_cache::clear();
- $result = parent::save();
- $this->original = clone $this;
- return $result;
- }
-
- public function __set($column, $value) {
- if (!isset($this->original)) {
- $this->original = clone $this;
- }
-
- if ($value instanceof SafeString) {
- $value = $value->unescaped();
- }
-
- return parent::__set($column, $value);
- }
-
- public function __unset($column) {
- if (!isset($this->original)) {
- $this->original = clone $this;
- }
-
- return parent::__unset($column);
- }
-
- public function original() {
- if (!isset($this->original)) {
- $this->original = clone $this;
- }
- return $this->original;
+ return parent::save();
}
}
diff --git a/modules/gallery/libraries/MY_View.php b/modules/gallery/libraries/MY_View.php
index cec59ec1..83e0d0be 100644
--- a/modules/gallery/libraries/MY_View.php
+++ b/modules/gallery/libraries/MY_View.php
@@ -27,7 +27,7 @@ class View extends View_Core {
View::$global_data[$key] = $value;
}
- public function is_set($key) {
+ public function is_set($key=null) {
return parent::is_set($key) ? true : array_key_exists($key, View::$global_data);
}
diff --git a/modules/gallery/libraries/ORM_MPTT.php b/modules/gallery/libraries/ORM_MPTT.php
index 0ea519c9..3668d42d 100644
--- a/modules/gallery/libraries/ORM_MPTT.php
+++ b/modules/gallery/libraries/ORM_MPTT.php
@@ -40,50 +40,52 @@ 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;
-
- // 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) {
+ function save() {
+ if (!$this->loaded()) {
+ $this->lock();
+ $parent = ORM::factory("item", $this->parent_id);
+
+ try {
+ // Make a hole in the parent for this new item
+ db::build()
+ ->update($this->table_name)
+ ->set("left_ptr", new Database_Expression("`left_ptr` + 2"))
+ ->where("left_ptr", ">=", $parent->right_ptr)
+ ->execute();
+ db::build()
+ ->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;
}
/**
* Delete this node and all of its children.
*/
- public function delete() {
+ public function delete($ignored_id=null) {
$children = $this->children();
if ($children) {
foreach ($this->children() as $item) {
@@ -100,12 +102,12 @@ class ORM_MPTT_Core extends ORM {
$this->lock();
$this->reload(); // Assume that the prior lock holder may have changed this entry
try {
- $this->db_builder
+ db::build()
->update($this->table_name)
->set("left_ptr", new Database_Expression("`left_ptr` - 2"))
->where("left_ptr", ">", $this->right_ptr)
->execute();
- $this->db_builder
+ db::build()
->update($this->table_name)
->set("right_ptr", new Database_Expression("`right_ptr` - 2"))
->where("right_ptr", ">", $this->right_ptr)
@@ -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();
@@ -237,11 +227,15 @@ class ORM_MPTT_Core extends ORM {
* @param Item_Model $target Target node
* @return ORM_MTPP
*/
- function move_to($target) {
+ protected function move_to($target) {
if ($this->contains($target)) {
throw new Exception("@todo INVALID_TARGET can't move item inside itself");
}
+ $this->lock();
+ $this->reload(); // Assume that the prior lock holder may have changed this entry
+ $target->reload();
+
$number_to_move = (int)(($this->right_ptr - $this->left_ptr) / 2 + 1);
$size_of_hole = $number_to_move * 2;
$original_left_ptr = $this->left_ptr;
@@ -249,13 +243,10 @@ class ORM_MPTT_Core extends ORM {
$target_right_ptr = $target->right_ptr;
$level_delta = ($target->level + 1) - $this->level;
- $this->lock();
- $this->reload(); // Assume that the prior lock holder may have changed this entry
- $target->reload();
try {
if ($level_delta) {
// Update the levels for the to-be-moved items
- $this->db_builder
+ db::build()
->update($this->table_name)
->set("level", new Database_Expression("`level` + $level_delta"))
->where("left_ptr", ">=", $original_left_ptr)
@@ -264,25 +255,26 @@ class ORM_MPTT_Core extends ORM {
}
// Make a hole in the target for the move
- $target->db_builder
+ db::build()
->update($this->table_name)
->set("left_ptr", new Database_Expression("`left_ptr` + $size_of_hole"))
->where("left_ptr", ">=", $target_right_ptr)
->execute();
- $target->db_builder
+ db::build()
->update($this->table_name)
->set("right_ptr", new Database_Expression("`right_ptr` + $size_of_hole"))
->where("right_ptr", ">=", $target_right_ptr)
->execute();
// Change the parent.
- $this->db_builder
+ db::build()
->update($this->table_name)
->set("parent_id", $target->id)
->where("id", "=", $this->id)
->execute();
- // If the source is to the right of the target then we just adjusted its left_ptr and right_ptr above.
+ // If the source is to the right of the target then we just adjusted its left_ptr and
+ // right_ptr above.
$left_ptr = $original_left_ptr;
$right_ptr = $original_right_ptr;
if ($original_left_ptr > $target_right_ptr) {
@@ -291,7 +283,7 @@ class ORM_MPTT_Core extends ORM {
}
$new_offset = $target->right_ptr - $left_ptr;
- $this->db_builder
+ db::build()
->update($this->table_name)
->set("left_ptr", new Database_Expression("`left_ptr` + $new_offset"))
->set("right_ptr", new Database_Expression("`right_ptr` + $new_offset"))
@@ -300,12 +292,12 @@ class ORM_MPTT_Core extends ORM {
->execute();
// Close the hole in the source's parent after the move
- $this->db_builder
+ db::build()
->update($this->table_name)
->set("left_ptr", new Database_Expression("`left_ptr` - $size_of_hole"))
->where("left_ptr", ">", $right_ptr)
->execute();
- $this->db_builder
+ db::build()
->update($this->table_name)
->set("right_ptr", new Database_Expression("`right_ptr` - $size_of_hole"))
->where("right_ptr", ">", $right_ptr)
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/failed_login.php b/modules/gallery/models/failed_login.php
new file mode 100644
index 00000000..0b84c295
--- /dev/null
+++ b/modules/gallery/models/failed_login.php
@@ -0,0 +1,20 @@
+<?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 Failed_Login_Model extends ORM {}
diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php
index 6851e1a3..dbd56fa2 100644
--- a/modules/gallery/models/item.php
+++ b/modules/gallery/models/item.php
@@ -18,15 +18,24 @@
* 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();
+ protected $data_file = null;
- var $form_rules = array(
- "name" => "required|length[0,255]",
- "title" => "required|length[0,255]",
- "description" => "length[0,65535]",
- "slug" => "required|length[0,255]"
- );
+ public function __construct($id=null) {
+ parent::__construct($id);
+
+ if (!$this->loaded()) {
+ // Set reasonable defaults
+ $this->created = time();
+ $this->rand_key = ((float)mt_rand()) / (float)mt_getrandmax();
+ $this->thumb_dirty = 1;
+ $this->resize_dirty = 1;
+ $this->sort_column = "created";
+ $this->sort_order = "ASC";
+ $this->owner_id = identity::active_user()->id;
+ }
+ }
/**
* Add a set of restrictions to any following queries to restrict access only to items
@@ -61,7 +70,13 @@ class Item_Model extends ORM_MPTT {
return $this->type == 'movie';
}
- public function delete() {
+ public function delete($ignored_id=null) {
+ if ($this->id == 1) {
+ $v = new Validation(array("id"));
+ $v->add_error("id", "cant_delete_root_album");
+ ORM_Validation_Exception::handle_validation($this->table_name, $v);
+ }
+
$old = clone $this;
module::event("item_before_delete", $this);
@@ -98,98 +113,12 @@ class Item_Model extends ORM_MPTT {
}
/**
- * Move this item to the specified target.
+ * Specify the path to the data file associated with this item. To actually associate it,
+ * you still have to call save().
* @chainable
- * @param Item_Model $target Target item (must be an album)
- * @return ORM_MPTT
*/
- function move_to($target) {
- if (!$target->is_album()) {
- throw new Exception("@todo INVALID_MOVE_TYPE $target->type");
- }
-
- if (file_exists($target_file = "{$target->file_path()}/$this->name")) {
- throw new Exception("@todo INVALID_MOVE_TARGET_EXISTS: $target_file");
- }
-
- if ($this->id == 1) {
- throw new Exception("@todo INVALID_SOURCE root album");
- }
-
- $original_path = $this->file_path();
- $original_resize_path = $this->resize_path();
- $original_thumb_path = $this->thumb_path();
- $original_parent = $this->parent();
-
- parent::move_to($target, true);
- model_cache::clear();
- $this->relative_path_cache = null;
-
- rename($original_path, $this->file_path());
- if ($this->is_album()) {
- @rename(dirname($original_resize_path), dirname($this->resize_path()));
- @rename(dirname($original_thumb_path), dirname($this->thumb_path()));
- db::build()
- ->update("items")
- ->set("relative_path_cache", null)
- ->set("relative_url_cache", null)
- ->where("left_ptr", ">", $this->left_ptr)
- ->where("right_ptr", "<", $this->right_ptr)
- ->execute();
- } else {
- @rename($original_resize_path, $this->resize_path());
- @rename($original_thumb_path, $this->thumb_path());
- }
-
- module::event("item_moved", $this, $original_parent);
- return $this;
- }
-
- /**
- * Rename the underlying file for this item to a new name. Move all the files. This requires a
- * save.
- *
- * @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());
- $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");
- }
-
- @rename(VARPATH . "albums/$old_relative_path", VARPATH . "albums/$new_relative_path");
- @rename(VARPATH . "resizes/$old_relative_path", VARPATH . "resizes/$new_relative_path");
- if ($this->is_movie()) {
- // Movie thumbnails have a .jpg extension
- $old_relative_thumb_path = preg_replace("/...$/", "jpg", $old_relative_path);
- $new_relative_thumb_path = preg_replace("/...$/", "jpg", $new_relative_path);
- @rename(VARPATH . "thumbs/$old_relative_thumb_path",
- VARPATH . "thumbs/$new_relative_thumb_path");
- } else {
- @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();
- }
-
+ public function set_data_file($data_file) {
+ $this->data_file = $data_file;
return $this;
}
@@ -323,7 +252,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 +267,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 +282,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 +305,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 +319,168 @@ class Item_Model extends ORM_MPTT {
if (!empty($this->changed) && $significant_changes) {
$this->updated = time();
if (!$this->loaded()) {
- $this->created = $this->updated;
- $this->weight = item::get_max_weight();
+ // Create a new item.
+
+ // Set a weight if it's missing. We don't do this in the constructor because it's not a
+ // simple assignment.
+ if (empty($this->weight)) {
+ $this->weight = item::get_max_weight();
+ }
+
+ // 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 any significant fields have changed, load up a copy of the original item and
+ // keep it around.
+ $original = ORM::factory("item", $this->id);
+ if (array_intersect($this->changed, array("parent_id", "name", "slug"))) {
+ $original->_build_relative_caches();
+ $this->relative_path_cache = null;
+ $this->relative_url_cache = null;
+ }
+
+ parent::save();
+
+ // Now update the filesystem and any database caches if there were significant value
+ // changes. If anything past this point fails, then we'll have an inconsistent database
+ // so this code should be as robust as we can make it.
+
+ // Update the MPTT pointers, if necessary. We have to do this before we generate any
+ // cached paths!
+ if ($original->parent_id != $this->parent_id) {
+ parent::move_to($this->parent());
+ }
+
+ if ($original->parent_id != $this->parent_id || $original->name != $this->name) {
+ // Move all of the items associated data files
+ @rename($original->file_path(), $this->file_path());
+ if ($this->is_album()) {
+ @rename(dirname($original->resize_path()), dirname($this->resize_path()));
+ @rename(dirname($original->thumb_path()), dirname($this->thumb_path()));
+ } else {
+ @rename($original->resize_path(), $this->resize_path());
+ @rename($original->thumb_path(), $this->thumb_path());
+ }
+
+ if ($original->parent_id != $this->parent_id) {
+ // This will result in 2 events since we'll still fire the item_updated event below
+ module::event("item_moved", $this, $original->parent());
+ }
+ }
+
+ // Changing the name, slug or parent ripples downwards
+ if ($this->is_album() &&
+ ($original->name != $this->name ||
+ $original->slug != $this->slug ||
+ $original->parent_id != $this->parent_id)) {
+ 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();
+ }
+
+ 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 +716,224 @@ 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(Validation $array=null) {
+ if (!$array) {
+ $this->rules = array(
+ "album_cover_item_id" => array("callbacks" => array(array($this, "valid_album_cover"))),
+ "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;
+ } else 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
+ $original = ORM::factory("item", $this->id);
+ $new_ext = pathinfo($this->name, PATHINFO_EXTENSION);
+ $old_ext = pathinfo($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");
+ return;
+ }
+ }
+ }
+
+ if (db::build()
+ ->from("items")
+ ->where("parent_id", "=", $this->parent_id)
+ ->where("name", "=", $this->name)
+ ->merge_where($this->id ? array(array("id", "<>", $this->id)) : null)
+ ->count_records()) {
+ $v->add_error("name", "conflict");
+ return;
+ }
+ }
+
+ /**
+ * 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 {
+ $query = db::build()
+ ->from("items")
+ ->where("id", "=", $this->parent_id)
+ ->where("type", "=", "album");
+
+ // If this is an existing item, make sure the new parent is not part of our hierarchy
+ if ($this->loaded()) {
+ $query->and_open()
+ ->where("left_ptr", "<", $this->left_ptr)
+ ->or_where("right_ptr", ">", $this->right_ptr)
+ ->close();
+ }
+
+ if ($query->count_records() != 1) {
+ $v->add_error("parent_id", "invalid");
+ }
+ }
+ }
+
+ /**
+ * Make sure the album cover item id refers to a valid item, or is null.
+ */
+ public function valid_album_cover(Validation $v, $field) {
+ if ($this->id == 1) {
+ return;
+ }
+
+ if ($this->album_cover_item_id && db::build()
+ ->from("items")
+ ->where("id", "=", $this->album_cover_item_id)
+ ->count_records() != 1) {
+ $v->add_error("album_cover_item_id", "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/x-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() && isset($this->changed[$field])) {
+ $v->add_error($field, "read_only");
+ }
+ }
+
+ /**
+ * Same as ORM::as_array() but convert id fields into their RESTful form.
+ */
+ public function as_restful_array() {
+ // Convert item ids to rest URLs for consistency
+ $data = $this->as_array();
+ if ($tmp = $this->parent()) {
+ $data["parent"] = rest::url("item", $tmp);
+ }
+ unset($data["parent_id"]);
+ if ($tmp = $this->album_cover()) {
+ $data["album_cover"] = rest::url("item", $tmp);
+ }
+ unset($data["album_cover_item_id"]);
+
+ // Elide some internal-only data that is going to cause confusion in the client.
+ foreach (array("relative_path_cache", "relative_url_cache", "left_ptr", "right_ptr") as $key) {
+ unset($data[$key]);
+ }
+ return $data;
+ }
}
diff --git a/modules/gallery/models/task.php b/modules/gallery/models/task.php
index f40be492..24d909cb 100644
--- a/modules/gallery/models/task.php
+++ b/modules/gallery/models/task.php
@@ -27,7 +27,7 @@ class Task_Model extends ORM {
}
}
- public function set($key, $value) {
+ public function set($key, $value=null) {
$context = unserialize($this->context);
$context[$key] = $value;
$this->context = serialize($context);
@@ -40,7 +40,7 @@ class Task_Model extends ORM {
return parent::save();
}
- public function delete() {
+ public function delete($ignored_id=null) {
Cache::instance()->delete($this->_cache_key());
return parent::delete();
}
diff --git a/modules/gallery/module.info b/modules/gallery/module.info
index 107d9a12..50a1505f 100644
--- a/modules/gallery/module.info
+++ b/modules/gallery/module.info
@@ -1,4 +1,3 @@
name = "Gallery 3"
description = "Gallery core application"
-version = 22
-
+version = 25
diff --git a/modules/gallery/tests/Access_Helper_Test.php b/modules/gallery/tests/Access_Helper_Test.php
index b2244766..5331117d 100644
--- a/modules/gallery/tests/Access_Helper_Test.php
+++ b/modules/gallery/tests/Access_Helper_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Access_Helper_Test extends Unit_Test_Case {
+class Access_Helper_Test extends Gallery_Unit_Test_Case {
private $_group;
public function teardown() {
@@ -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,39 @@ 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 view_permissions_propagate_down_to_photos_test() {
+ $album = test::random_album();
+ $photo = test::random_photo($album);
+ identity::set_active_user(identity::guest());
+
+ $this->assert_true(access::can("view", $photo));
+ $album->reload(); // MPTT pointers have changed, so reload before calling access::deny
+ access::deny(identity::everybody(), "view", $album);
+
+ $photo->reload(); // view permissions are cached in the photo, so reload before checking
+ $this->assert_false(access::can("view", $photo));
+ }
+
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 +232,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 +248,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 +282,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 +290,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 +307,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 +325,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 +355,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/Album_Helper_Test.php b/modules/gallery/tests/Album_Helper_Test.php
deleted file mode 100644
index ef0905da..00000000
--- a/modules/gallery/tests/Album_Helper_Test.php
+++ /dev/null
@@ -1,88 +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 Album_Helper_Test extends Unit_Test_Case {
- public function create_album_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- $album = album::create($root, $rand, $rand, $rand);
-
- $this->assert_equal(VARPATH . "albums/$rand", $album->file_path());
- $this->assert_equal(VARPATH . "thumbs/$rand/.album.jpg", $album->thumb_path());
- $this->assert_true(is_dir(VARPATH . "thumbs/$rand"), "missing thumb dir");
-
- // It's unclear that a resize makes sense for an album. But we have one.
- $this->assert_equal(VARPATH . "resizes/$rand/.album.jpg", $album->resize_path());
- $this->assert_true(is_dir(VARPATH . "resizes/$rand"), "missing resizes dir");
-
- $this->assert_equal(1, $album->parent_id); // MPTT tests will cover other hierarchy checks
- $this->assert_equal($rand, $album->name);
- $this->assert_equal($rand, $album->title);
- $this->assert_equal($rand, $album->description);
- }
-
- public function create_conflicting_album_test() {
- $rand = "name_" . rand();
- $root = ORM::factory("item", 1);
- $album1 = album::create($root, $rand, $rand, $rand);
- $album2 = album::create($root, $rand, $rand, $rand);
- $this->assert_true($album1->name != $album2->name);
- }
-
- public function thumb_url_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- $album = album::create($root, $rand, $rand, $rand);
- $this->assert_equal(
- "http://./var/thumbs/$rand/.album.jpg?m={$album->updated}", $album->thumb_url());
- }
-
- public function resize_url_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- $album = album::create($root, $rand, $rand, $rand);
- $this->assert_equal("http://./var/resizes/$rand/.album.jpg?m={$album->updated}", $album->resize_url());
- }
-
- public function create_album_shouldnt_allow_names_with_slash_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- try {
- $album = album::create($root, $rand . "/", $rand, $rand);
- } catch (Exception $e) {
- // pass
- return;
- }
-
- $this->assert_true(false, "Shouldn't create an album with / in the name");
- }
-
- public function create_album_silently_trims_trailing_periods_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- try {
- $album = album::create($root, $rand . "..", $rand, $rand);
- } catch (Exception $e) {
- $this->assert_equal("@todo NAME_CANNOT_END_IN_PERIOD", $e->getMessage());
- return;
- }
-
- $this->assert_true(false, "Shouldn't create an album with trailing . in the name");
- }
-}
diff --git a/modules/gallery/tests/Albums_Controller_Test.php b/modules/gallery/tests/Albums_Controller_Test.php
index 4d8935cd..76c9a628 100644
--- a/modules/gallery/tests/Albums_Controller_Test.php
+++ b/modules/gallery/tests/Albums_Controller_Test.php
@@ -17,64 +17,58 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Albums_Controller_Test extends Unit_Test_Case {
+class Albums_Controller_Test extends Gallery_Unit_Test_Case {
public function setup() {
$this->_save = array($_POST, $_SERVER);
}
public function teardown() {
list($_POST, $_SERVER) = $this->_save;
- if (isset($this->_album)) {
- $this->_album->delete();
- }
}
public function change_album_test() {
$controller = new Albums_Controller();
- $root = ORM::factory("item", 1);
- $this->_album = album::create($root, "test", "test", "test");
- $orig_name = $this->_album->name;
+ $album = test::random_album();
// Randomize to avoid conflicts.
- $new_dirname = "new_name_" . rand();
+ $new_name = "new_name_" . rand();
- $_POST["dirname"] = $new_dirname;
+ $_POST["name"] = $new_name;
$_POST["title"] = "new title";
$_POST["description"] = "new description";
$_POST["column"] = "weight";
$_POST["direction"] = "ASC";
$_POST["csrf"] = access::csrf_token();
$_POST["slug"] = "new-name";
- access::allow(identity::everybody(), "edit", $root);
+ access::allow(identity::everybody(), "edit", item::root());
ob_start();
- $controller->update($this->_album->id);
- $this->_album->reload();
+ $controller->update($album->id);
+ $album->reload();
$results = ob_get_contents();
ob_end_clean();
- $this->assert_equal(
- json_encode(array("result" => "success")),
- $results);
- $this->assert_equal($new_dirname, $this->_album->name);
- $this->assert_equal("new title", $this->_album->title);
- $this->assert_equal("new description", $this->_album->description);
+ $this->assert_equal(json_encode(array("result" => "success")), $results);
+ $this->assert_equal($new_name, $album->name);
+ $this->assert_equal("new title", $album->title);
+ $this->assert_equal("new description", $album->description);
}
public function change_album_no_csrf_fails_test() {
$controller = new Albums_Controller();
- $root = ORM::factory("item", 1);
- $this->_album = album::create($root, "test", "test", "test");
+ $album = test::random_album();
+
$_POST["name"] = "new name";
$_POST["title"] = "new title";
$_POST["description"] = "new description";
- access::allow(identity::everybody(), "edit", $root);
+ access::allow(identity::everybody(), "edit", item::root());
try {
- $controller->_update($this->_album);
+ $controller->update($album->id);
$this->assert_true(false, "This should fail");
} catch (Exception $e) {
// pass
+ $this->assert_same("@todo FORBIDDEN", $e->getMessage());
}
}
}
diff --git a/modules/gallery/tests/Cache_Test.php b/modules/gallery/tests/Cache_Test.php
index d5bf37cc..1023568b 100644
--- a/modules/gallery/tests/Cache_Test.php
+++ b/modules/gallery/tests/Cache_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Cache_Test extends Unit_Test_Case {
+class Cache_Test extends Gallery_Unit_Test_Case {
private $_driver;
public function setup() {
db::build()->delete("caches")->execute();
diff --git a/modules/gallery/tests/Controller_Auth_Test.php b/modules/gallery/tests/Controller_Auth_Test.php
index 124d8b4c..c27196da 100644
--- a/modules/gallery/tests/Controller_Auth_Test.php
+++ b/modules/gallery/tests/Controller_Auth_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Controller_Auth_Test extends Unit_Test_Case {
+class Controller_Auth_Test extends Gallery_Unit_Test_Case {
public function find_missing_auth_test() {
$found = array();
$controllers = explode("\n", `git ls-files '*/*/controllers/*.php'`);
diff --git a/modules/gallery/tests/Database_Test.php b/modules/gallery/tests/Database_Test.php
index 6aa186e5..861f7bba 100644
--- a/modules/gallery/tests/Database_Test.php
+++ b/modules/gallery/tests/Database_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Database_Test extends Unit_Test_Case {
+class Database_Test extends Gallery_Unit_Test_Case {
function setup() {
$config = Kohana_Config::instance();
$config->set("database.mock.connection.type", "mock");
@@ -168,12 +168,12 @@ class Database_Mock extends Database {
return array("test");
}
- public function quote_column($val) {
- return "[$val]";
+ public function quote_column($val, $alias=null) {
+ return $alias ? "[$val,$alias]" : "[$val]";
}
- public function quote_table($val) {
- return "[$val]";
+ public function quote_table($val, $alias=null) {
+ return $alias ? "[$val,$alias]" : "[$val]";
}
public function quote($val) {
diff --git a/modules/gallery/tests/Dir_Helper_Test.php b/modules/gallery/tests/Dir_Helper_Test.php
index 46bb871c..69241447 100644
--- a/modules/gallery/tests/Dir_Helper_Test.php
+++ b/modules/gallery/tests/Dir_Helper_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Dir_Helper_Test extends Unit_Test_Case {
+class Dir_Helper_Test extends Gallery_Unit_Test_Case {
public function remove_album_test() {
$dirname = (VARPATH . "albums/testdir");
mkdir($dirname, 0777, true);
diff --git a/modules/gallery/tests/DrawForm_Test.php b/modules/gallery/tests/DrawForm_Test.php
index da8a6b04..f7b727c0 100644
--- a/modules/gallery/tests/DrawForm_Test.php
+++ b/modules/gallery/tests/DrawForm_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class DrawForm_Test extends Unit_Test_Case {
+class DrawForm_Test extends Gallery_Unit_Test_Case {
function no_group_test() {
$form = new Forge("test/controller", "", "post", array("id" => "g-test-group-form"));
$form->input("title")->label(t("Title"));
diff --git a/modules/gallery/tests/File_Structure_Test.php b/modules/gallery/tests/File_Structure_Test.php
index b5026188..4590e95d 100644
--- a/modules/gallery/tests/File_Structure_Test.php
+++ b/modules/gallery/tests/File_Structure_Test.php
@@ -19,7 +19,7 @@
*/
require_once(MODPATH . "gallery/tests/Gallery_Filters.php");
-class File_Structure_Test extends Unit_Test_Case {
+class File_Structure_Test extends Gallery_Unit_Test_Case {
public function no_trailing_closing_php_tag_test() {
$dir = new GalleryCodeFilterIterator(
new RecursiveIteratorIterator(new RecursiveDirectoryIterator(DOCROOT)));
@@ -36,7 +36,7 @@ class File_Structure_Test extends Unit_Test_Case {
$dir = new GalleryCodeFilterIterator(
new RecursiveIteratorIterator(new RecursiveDirectoryIterator(DOCROOT)));
foreach ($dir as $file) {
- if (strpos($file, "modules/gallery/views/kohana/error.php")) {
+ if (strpos($file, "views/kohana/error.php")) {
continue;
}
diff --git a/modules/gallery/tests/Gallery_I18n_Test.php b/modules/gallery/tests/Gallery_I18n_Test.php
index 5d2fd994..f6e50d71 100644
--- a/modules/gallery/tests/Gallery_I18n_Test.php
+++ b/modules/gallery/tests/Gallery_I18n_Test.php
@@ -18,7 +18,7 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Gallery_I18n_Test extends Unit_Test_Case {
+class Gallery_I18n_Test extends Gallery_Unit_Test_Case {
private $i18n;
public function setup() {
diff --git a/modules/gallery/tests/Gallery_Installer_Test.php b/modules/gallery/tests/Gallery_Installer_Test.php
index 74a07b1a..3db434bc 100644
--- a/modules/gallery/tests/Gallery_Installer_Test.php
+++ b/modules/gallery/tests/Gallery_Installer_Test.php
@@ -22,7 +22,7 @@
* This test case operates under the assumption that gallery_installer::install() is called by the
* test controller before it starts.
*/
-class Gallery_Installer_Test extends Unit_Test_Case {
+class Gallery_Installer_Test extends Gallery_Unit_Test_Case {
public function install_creates_dirs_test() {
$this->assert_true(file_exists(VARPATH . "albums"));
$this->assert_true(file_exists(VARPATH . "resizes"));
diff --git a/modules/gallery/tests/Gallery_Rest_Helper_Test.php b/modules/gallery/tests/Gallery_Rest_Helper_Test.php
deleted file mode 100644
index f8cf6190..00000000
--- a/modules/gallery/tests/Gallery_Rest_Helper_Test.php
+++ /dev/null
@@ -1,277 +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 Gallery_Rest_Helper_Test extends Unit_Test_Case {
- public function setup() {
- $this->_save = array($_GET, $_POST, $_SERVER, $_FILES);
- $this->_saved_active_user = identity::active_user();
- }
-
- public function teardown() {
- list($_GET, $_POST, $_SERVER, $_FILES) = $this->_save;
- identity::set_active_user($this->_saved_active_user);
- if (!empty($this->_user)) {
- try {
- $this->_user->delete();
- } catch (Exception $e) { }
- }
- }
-
- private function _create_user() {
- if (empty($this->_user)) {
- $this->_user = identity::create_user("access_test" . rand(), "Access Test", "password");
- $key = ORM::factory("user_access_token");
- $key->access_key = md5($this->_user->name . rand());
- $key->user_id = $this->_user->id;
- $key->save();
- identity::set_active_user($this->_user);
- }
- return $this->_user;
- }
-
- private function _create_album($parent=null) {
- $album_name = "rest_album_" . rand();
- if (empty($parent)) {
- $parent = ORM::factory("item", 1);
- }
- return album::create($parent, $album_name, $album_name, $album_name);
- }
-
- private function _create_image($parent=null) {
- $filename = MODPATH . "gallery/tests/test.jpg";
- $image_name = "rest_image_" . rand();
- if (empty($parent)) {
- $parent = ORM::factory("item", 1);
- }
- return photo::create($parent, $filename, "$image_name.jpg", $image_name);
- }
-
- public function gallery_rest_get_album_test() {
- $album = $this->_create_album();
- $child = $this->_create_album($album);
- $photo = $this->_create_image($child);
- $child->reload();
- $request = (object)array("arguments" => explode("/", $child->relative_url()));
-
- $this->assert_equal(
- json_encode(array("status" => "OK",
- "resource" =>
- array("type" => $child->type,
- "name" => $child->name,
- "path" => $child->relative_url(),
- "parent_path" => $album->relative_url(),
- "title" => $child->title,
- "thumb_url" => $child->thumb_url(),
- "thumb_size" => array("height" => $child->thumb_height,
- "width" => $child->thumb_width),
- "resize_url" => $child->resize_url(),
- "resize_size" => array("height" => 0,
- "width" => 0),
- "url" => $child->file_url(),
- "size" => array("height" => $child->height,
- "width" => $child->width),
- "description" => $child->description,
- "slug" => $child->slug,
- "children" => array(array(
- "type" => "photo",
- "has_children" => false,
- "path" => $photo->relative_url(),
- "thumb_url" => $photo->thumb_url(),
- "thumb_dimensions" => array(
- "width" => (string)$photo->thumb_width,
- "height" => (string)$photo->thumb_height),
- "has_thumb" => true,
- "title" => $photo->title))))),
- gallery_rest::get($request));
- }
-
- public function gallery_rest_get_photo_test() {
- $child = $this->_create_album();
- $photo = $this->_create_image($child);
- $request = (object)array("arguments" => explode("/", $photo->relative_url()));
-
- $this->assert_equal(
- json_encode(array("status" => "OK",
- "resource" =>
- array("type" => $photo->type,
- "name" => $photo->name,
- "path" => $photo->relative_url(),
- "parent_path" => $child->relative_url(),
- "title" => $photo->title,
- "thumb_url" => $photo->thumb_url(),
- "thumb_size" => array("height" => (string)$photo->thumb_height,
- "width" => (string)$photo->thumb_width),
- "resize_url" => $photo->resize_url(),
- "resize_size" => array("height" => $photo->resize_height,
- "width" => $photo->resize_width),
- "url" => $photo->file_url(),
- "size" => array("height" => (string)$photo->height,
- "width" => (string)$photo->width),
- "description" => $photo->description,
- "slug" => $photo->slug))),
- gallery_rest::get($request));
- }
-
- public function gallery_rest_put_album_no_path_test() {
- $request = (object)array("description" => "Updated description",
- "title" => "Updated Title",
- "name" => "new name");
-
- try {
- gallery_rest::put($request);
- } catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
- }
- }
-
- public function gallery_rest_put_album_not_found_test() {
- $photo = $this->_create_image();
- $request = (object)array("arguments" => explode("/", $photo->relative_url() . rand()),
- "description" => "Updated description",
- "title" => "Updated Title",
- "name" => "new name");
-
- try {
- gallery_rest::put($request);
- } catch (Kohana_404_Exception $k404) {
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
- }
- }
-
- public function gallery_rest_put_album_no_edit_permission_test() {
- $child = $this->_create_album();
- $this->_create_user();
- $request = (object)array("arguments" => explode("/", $child->relative_url()),
- "description" => "Updated description",
- "title" => "Updated Title",
- "name" => "new name");
-
- try {
- gallery_rest::put($request);
- } catch (Kohana_404_Exception $k404) {
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
- }
- }
-
- public function gallery_rest_put_album_rename_conflict_test() {
- $child = $this->_create_album();
- $sibling = $this->_create_image();
- $this->_create_user();
- access::allow(identity::registered_users(), "edit", $child);
- $request = (object)array("arguments" => explode("/", $child->relative_url()),
- "description" => "Updated description",
- "title" => "Updated Title",
- "name" => $sibling->name);
-
- $this->assert_equal(
- json_encode(array("status" => "VALIDATE_ERROR",
- "fields" => array("slug" => "Duplicate Internet address"))),
- gallery_rest::put($request));
- }
-
- public function gallery_rest_put_album_test() {
- $child = $this->_create_album();
- $sibling = $this->_create_image();
- $this->_create_user();
- access::allow(identity::registered_users(), "edit", $child);
-
- $new_name = "new_album_name" . rand();
- $request = (object)array("arguments" => explode("/", $child->relative_url()),
- "description" => "Updated description",
- "title" => "Updated Title",
- "name" => $new_name);
-
- $this->assert_equal(json_encode(array("status" => "OK")), gallery_rest::put($request));
- $child->reload();
- $this->assert_equal("Updated description", $child->description);
- $this->assert_equal("Updated Title", $child->title);
- $this->assert_equal($new_name, $child->name);
- }
-
- public function gallery_rest_put_photo_test() {
- $child = $this->_create_album();
- $photo = $this->_create_image($child);
- $this->_create_user();
- access::allow(identity::registered_users(), "edit", $child);
-
- $request = (object)array("arguments" => explode("/", $photo->relative_url()),
- "description" => "Updated description",
- "title" => "Updated Title",
- "name" => "new name");
-
- $this->assert_equal(json_encode(array("status" => "OK")), gallery_rest::put($request));
- $photo->reload();
- $this->assert_equal("Updated description", $photo->description);
- $this->assert_equal("Updated Title", $photo->title);
- $this->assert_equal("new name", $photo->name);
- }
-
- public function gallery_rest_delete_album_test() {
- $album = $this->_create_album();
- $child = $this->_create_album($album);
- $this->_create_user();
- access::allow(identity::registered_users(), "edit", $album);
-
- $request = (object)array("arguments" => explode("/", $child->relative_url()));
-
- $this->assert_equal(json_encode(array("status" => "OK",
- "resource" => array(
- "parent_path" => $album->relative_url()))),
- gallery_rest::delete($request));
- $child->reload();
- $this->assert_false($child->loaded());
- }
-
- public function gallery_rest_delete_photo_test() {
- $album = $this->_create_album();
- $photo = $this->_create_image($album);
- $this->_create_user();
- access::allow(identity::registered_users(), "edit", $album);
-
- $request = (object)array("arguments" => explode("/", $photo->relative_url()));
-
- $this->assert_equal(json_encode(array("status" => "OK",
- "resource" => array(
- "parent_path" => $album->relative_url()))),
- gallery_rest::delete($request));
- $photo->reload();
- $this->assert_false($photo->loaded());
- }
-
- public function gallery_rest_post_album_test() {
- $album = $this->_create_album();
- $this->_create_user();
- access::allow(identity::registered_users(), "edit", $album);
-
- $new_path = $album->relative_url() . "/new%20child";
- $request = (object)array("arguments" => explode("/", $new_path));
-
- $this->assert_equal(json_encode(array("status" => "OK", "path" => $new_path)),
- gallery_rest::post($request));
- $album = ORM::factory("item")
- ->where("relative_url_cache", "=", $new_path)
- ->find();
- $this->assert_true($album->loaded());
- $this->assert_equal("new child", $album->slug);
- }
-}
diff --git a/modules/gallery/tests/Html_Helper_Test.php b/modules/gallery/tests/Html_Helper_Test.php
index 1662b866..be318632 100644
--- a/modules/gallery/tests/Html_Helper_Test.php
+++ b/modules/gallery/tests/Html_Helper_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Html_Helper_Test extends Unit_Test_Case {
+class Html_Helper_Test extends Gallery_Unit_Test_Case {
public function clean_test() {
$safe_string = html::clean("hello <p >world</p>");
$this->assert_equal("hello &lt;p &gt;world&lt;/p&gt;",
diff --git a/modules/gallery/tests/Item_Helper_Test.php b/modules/gallery/tests/Item_Helper_Test.php
index f0c653c0..cdbdd324 100644
--- a/modules/gallery/tests/Item_Helper_Test.php
+++ b/modules/gallery/tests/Item_Helper_Test.php
@@ -17,12 +17,12 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Item_Helper_Test extends Unit_Test_Case {
+class Item_Helper_Test extends Gallery_Unit_Test_Case {
public function viewable_test() {
- $root = ORM::factory("item", 1);
- $album = album::create($root, rand(), rand(), rand());
- $item = self::_create_random_item($album);
+ $album = test::random_album();
+ $item = test::random_photo($album);
+ $album->reload();
identity::set_active_user(identity::guest());
// We can see the item when permissions are granted
@@ -38,33 +38,8 @@ class Item_Helper_Test extends Unit_Test_Case {
ORM::factory("item")->viewable()->where("id", "=", $item->id)->count_all());
}
- public function validate_url_safe_test() {
- $input = new MockInput();
- $input->value = "Ab_cd-ef-d9";
- item::validate_url_safe($input);
- $this->assert_true(!isset($input->not_url_safe));
-
- $input->value = "ab&cd";
- item::validate_url_safe($input);
- $this->assert_equal(1, $input->not_url_safe);
- }
-
public function convert_filename_to_slug_test() {
$this->assert_equal("foo", item::convert_filename_to_slug("{[foo]}"));
$this->assert_equal("foo-bar", item::convert_filename_to_slug("{[foo!@#!$@#^$@($!(@bar]}"));
}
-
- private static function _create_random_item($album) {
- // Set all required fields (values are irrelevant)
- $item = ORM::factory("item");
- $item->name = rand();
- $item->type = "photo";
- return $item->add_to_parent($album);
- }
}
-
-class MockInput {
- function add_error($error, $value) {
- $this->$error = $value;
- }
-} \ No newline at end of file
diff --git a/modules/gallery/tests/Item_Model_Test.php b/modules/gallery/tests/Item_Model_Test.php
index d03a03f4..9f632fb5 100644
--- a/modules/gallery/tests/Item_Model_Test.php
+++ b/modules/gallery/tests/Item_Model_Test.php
@@ -17,22 +17,15 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Item_Model_Test extends Unit_Test_Case {
+class Item_Model_Test extends Gallery_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,18 +62,16 @@ 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();
+ $original_name = $item->name;
file_put_contents($item->thumb_path(), "thumb");
file_put_contents($item->resize_path(), "resize");
file_put_contents($item->file_path(), "file");
- $original_name = $item->name;
- $new_name = rand();
-
// Now rename it
- $item->rename($new_name)->save();
+ $item->name = ($new_name = test::random_name($item));
+ $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 +84,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");
@@ -104,10 +94,11 @@ class Item_Model_Test extends Unit_Test_Case {
$original_album_name = $album->name;
$original_photo_name = $photo->name;
- $new_album_name = rand();
+ $new_album_name = test::random_name();
// Now rename the album
- $album->rename($new_album_name)->save();
+ $album->name = $new_album_name;
+ $album->save();
$photo->reload();
// Expected:
@@ -120,9 +111,9 @@ class Item_Model_Test extends Unit_Test_Case {
$this->assert_equal($new_album_name, basename(dirname($album->thumb_path())));
$this->assert_equal($new_album_name, basename(dirname($album->resize_path())));
- $this->assert_same(0, strpos($photo->file_path(), $album->file_path()));
- $this->assert_same(0, strpos($photo->thumb_path(), dirname($album->thumb_path())));
- $this->assert_same(0, strpos($photo->resize_path(), dirname($album->resize_path())));
+ $this->assert_true(test::starts_with($photo->file_path(), $album->file_path()));
+ $this->assert_true(test::starts_with($photo->thumb_path(), dirname($album->thumb_path())));
+ $this->assert_true(test::starts_with($photo->resize_path(), dirname($album->resize_path())));
$this->assert_equal("thumb", file_get_contents($photo->thumb_path()));
$this->assert_equal("resize", file_get_contents($photo->resize_path()));
@@ -130,81 +121,56 @@ 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();
-
- $new_name = rand() . "/";
-
+ $item = test::random_photo();
try {
- $item->rename($new_name)->save();
- } catch (Exception $e) {
- // pass
+ $item->name = test::random_name() . "/";
+ $item->save();
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_equal(array("name" => "no_slashes"), $e->validation->errors());
return;
}
- $this->assert_false(true, "Item_Model::rename should not accept / characters");
+ $this->assert_true(false, "Shouldn't get here");
}
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->save();
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_true(in_array("conflict", $e->validation->errors()));
return;
}
- $this->assert_false(true, "Item_Model::rename should fail.");
- }
- public function save_original_values_test() {
- $item = self::_create_random_item();
- $item->title = "ORIGINAL_VALUE";
- $item->save();
- $item->title = "NEW_VALUE";
-
- $this->assert_same("ORIGINAL_VALUE", $item->original()->title);
- $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());
+ $this->assert_false(true, "rename should conflict");
}
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();
+ $album1 = test::random_album($album2);
+ $photo = test::random_photo($album1);
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);
+ $album1->parent_id = item::root()->id;
+ $album1->save();
$photo->reload();
// Expected:
- // * the album dirs are all moved
+ // * album is not inside album2 anymore
// * the photo's paths are all inside the albums paths
// * the photo files are all still intact and accessible
- $this->assert_same(0, strpos($photo->file_path(), $album->file_path()));
- $this->assert_same(0, strpos($photo->thumb_path(), dirname($album->thumb_path())));
- $this->assert_same(0, strpos($photo->resize_path(), dirname($album->resize_path())));
+ $this->assert_false(test::starts_with($album2->file_path(), $album1->file_path()));
+ $this->assert_true(test::starts_with($photo->file_path(), $album1->file_path()));
+ $this->assert_true(test::starts_with($photo->thumb_path(), dirname($album1->thumb_path())));
+ $this->assert_true(test::starts_with($photo->resize_path(), dirname($album1->resize_path())));
$this->assert_equal("thumb", file_get_contents($photo->thumb_path()));
$this->assert_equal("resize", file_get_contents($photo->resize_path()));
@@ -212,71 +178,184 @@ 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);
+ $album1 = test::random_album();
+ $photo = test::random_photo($album1);
+
+ $album2 = test::random_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
- $photo->move_to($album2);
- $photo->reload();
+ // Now move the photo
+ $photo->parent_id = $album2->id;
+ $photo->save();
// Expected:
- // * the album dirs are all moved
- // * the photo's paths are all inside the albums paths
+ // * the photo's paths are inside the album2 not album1
// * the photo files are all still intact and accessible
- $this->assert_same(0, strpos($photo->file_path(), $album->file_path()));
- $this->assert_same(0, strpos($photo->thumb_path(), dirname($album->thumb_path())));
- $this->assert_same(0, strpos($photo->resize_path(), dirname($album->resize_path())));
+ $this->assert_true(test::starts_with($photo->file_path(), $album2->file_path()));
+ $this->assert_true(test::starts_with($photo->thumb_path(), dirname($album2->thumb_path())));
+ $this->assert_true(test::starts_with($photo->resize_path(), dirname($album2->resize_path())));
$this->assert_equal("thumb", file_get_contents($photo->thumb_path()));
$this->assert_equal("resize", file_get_contents($photo->resize_path()));
$this->assert_equal("file", file_get_contents($photo->file_path()));
}
- 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);
+ public function move_album_fails_conflicting_target_test() {
+ $album = test::random_album();
+ $source = test::random_album_unsaved($album);
+ $source->name = $album->name;
+ $source->save();
+
+ // $source and $album have the same name, so if we move $source into the root they should
+ // conflict.
try {
- $source->move_to($root);
- } catch (Exception $e) {
- // pass
- $this->assert_true(strpos($e->getMessage(), "INVALID_MOVE_TARGET_EXISTS") !== false,
- "incorrect exception.");
+ $source->parent_id = item::root()->id;
+ $source->save();
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_equal(
+ array("name" => "conflict", "slug" => "conflict"), $e->validation->errors());
return;
}
+ $this->assert_true(false, "Shouldn't get here");
+ }
+
+ public function move_album_fails_wrong_target_type_test() {
+ $album = test::random_album();
+ $photo = test::random_photo();
- $this->assert_false(true, "Item_Model::rename should not accept / characters");
+ // $source and $album have the same name, so if we move $source into the root they should
+ // conflict.
+
+ try {
+ $album->parent_id = $photo->id;
+ $album->save();
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_equal(array("parent_id" => "invalid"), $e->validation->errors());
+ return;
+ }
+ $this->assert_true(false, "Shouldn't get here");
}
- 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);
+ public function move_photo_fails_conflicting_target_test() {
+ $photo1 = test::random_photo();
+ $album = test::random_album();
+ $photo2 = test::random_photo_unsaved($album);
+ $photo2->name = $photo1->name;
+ $photo2->save();
+
+ // $photo1 and $photo2 have the same name, so if we move $photo1 into the root they should
+ // conflict.
try {
- $photo2->move_to($root);
+ $photo2->parent_id = item::root()->id;
+ $photo2->save();
} catch (Exception $e) {
// pass
- $this->assert_true(strpos($e->getMessage(), "INVALID_MOVE_TARGET_EXISTS") !== false,
- "incorrect exception.");
+ $this->assert_equal(
+ array("name" => "conflict", "slug" => "conflict"), $e->validation->errors());
+ return;
+ }
+ $this->assert_true(false, "Shouldn't get here");
+ }
+
+ public function move_album_inside_descendent_fails_test() {
+ $album1 = test::random_album();
+ $album2 = test::random_album($album1);
+ $album3 = test::random_album($album2);
+
+ try {
+ $album1->parent_id = $album3->id;
+ $album1->save();
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_equal(array("parent_id" => "invalid"), $e->validation->errors());
+ return;
+ }
+ $this->assert_true(false, "Shouldn't get here");
+ }
+
+
+ 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, "Item_Model::rename should not accept / characters");
+ $this->assert_false(true, "Shouldn't get here");
+ }
+
+ public function slug_is_url_safe_test() {
+ try {
+ $album = test::random_album_unsaved();
+ $album->slug = "illegal chars! !@#@#$!@~";
+ $album->save();
+ $this->assert_true(false, "Shouldn't be able to save");
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_same(array("slug" => "not_url_safe"), $e->validation->errors());
+ }
+
+ // This should work
+ $album->slug = "the_quick_brown_fox";
+ $album->save();
+ }
+
+ public function cant_change_item_type_test() {
+ $photo = test::random_photo();
+ try {
+ $photo->type = "movie";
+ $photo->mime_type = "video/x-flv";
+ $photo->save();
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_same(array("type" => "read_only"), $e->validation->errors());
+ return; // pass
+ }
+ $this->assert_true(false, "Shouldn't get here");
+ }
+
+ public function cant_delete_root_album_test() {
+ try {
+ item::root()->delete();
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_same(array("id" => "cant_delete_root_album"), $e->validation->errors());
+ return; // pass
+ }
+ $this->assert_true(false, "Shouldn't get here");
+ }
+
+ public function as_restful_array_test() {
+ $album = test::random_album();
+ $photo = test::random_photo($album);
+ $album->reload();
+
+ $result = $album->as_restful_array();
+ $this->assert_same(rest::url("item", item::root()), $result["parent"]);
+ $this->assert_same(rest::url("item", $photo), $result["album_cover"]);
+ $this->assert_true(!array_key_exists("parent_id", $result));
+ $this->assert_true(!array_key_exists("album_cover_item_id", $result));
}
}
diff --git a/modules/gallery/tests/Item_Rest_Helper_Test.php b/modules/gallery/tests/Item_Rest_Helper_Test.php
new file mode 100644
index 00000000..6d1dd864
--- /dev/null
+++ b/modules/gallery/tests/Item_Rest_Helper_Test.php
@@ -0,0 +1,241 @@
+<?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 Item_Rest_Helper_Test extends Gallery_Unit_Test_Case {
+ public function resolve_test() {
+ $album = test::random_album();
+ $resolved = rest::resolve(rest::url("item", $album));
+ $this->assert_equal($album->id, $resolved->id);
+ }
+
+ public function get_scope_test() {
+ $album1 = test::random_album();
+ $photo1 = test::random_photo($album1);
+ $album2 = test::random_album($album1);
+ $photo2 = test::random_photo($album2);
+ $album1->reload();
+
+ // No scope is the same as "direct"
+ $request = new stdClass();
+ $request->url = rest::url("item", $album1);
+ $request->params = new stdClass();
+ $this->assert_equal_array(
+ array("url" => rest::url("item", $album1),
+ "entity" => $album1->as_restful_array(),
+ "members" => array(
+ rest::url("item", $photo1),
+ rest::url("item", $album2)),
+ "relationships" => array(
+ "tags" => array(
+ "url" => rest::url("item_tags", $album1),
+ "members" => array()))),
+ item_rest::get($request));
+
+ $request->url = rest::url("item", $album1);
+ $request->params->scope = "direct";
+ $this->assert_equal_array(
+ array("url" => rest::url("item", $album1),
+ "entity" => $album1->as_restful_array(),
+ "members" => array(
+ rest::url("item", $photo1),
+ rest::url("item", $album2)),
+ "relationships" => array(
+ "tags" => array(
+ "url" => rest::url("item_tags", $album1),
+ "members" => array()))),
+ item_rest::get($request));
+
+ $request->url = rest::url("item", $album1);
+ $request->params->scope = "all";
+ $this->assert_equal_array(
+ array("url" => rest::url("item", $album1),
+ "entity" => $album1->as_restful_array(),
+ "members" => array(
+ rest::url("item", $photo1),
+ rest::url("item", $album2),
+ rest::url("item", $photo2)),
+ "relationships" => array(
+ "tags" => array(
+ "url" => rest::url("item_tags", $album1),
+ "members" => array()))),
+ item_rest::get($request));
+ }
+
+ public function get_children_like_test() {
+ $album1 = test::random_album();
+ $photo1 = test::random_photo($album1);
+ $photo2 = test::random_photo_unsaved($album1);
+ $photo2->name = "foo.jpg";
+ $photo2->save();
+ $album1->reload();
+
+ $request = new stdClass();
+ $request->url = rest::url("item", $album1);
+ $request->params = new stdClass();
+ $request->params->name = "foo";
+ $this->assert_equal_array(
+ array("url" => rest::url("item", $album1),
+ "entity" => $album1->as_restful_array(),
+ "members" => array(
+ rest::url("item", $photo2)),
+ "relationships" => array(
+ "tags" => array(
+ "url" => rest::url("item_tags", $album1),
+ "members" => array()))),
+ item_rest::get($request));
+ }
+
+ public function get_children_type_test() {
+ $album1 = test::random_album();
+ $photo1 = test::random_photo($album1);
+ $album2 = test::random_album($album1);
+ $album1->reload();
+
+ $request = new stdClass();
+ $request->url = rest::url("item", $album1);
+ $request->params = new stdClass();
+ $request->params->type = "album";
+ $this->assert_equal_array(
+ array("url" => rest::url("item", $album1),
+ "entity" => $album1->as_restful_array(),
+ "members" => array(
+ rest::url("item", $album2)),
+ "relationships" => array(
+ "tags" => array(
+ "url" => rest::url("item_tags", $album1),
+ "members" => array() ))),
+ item_rest::get($request));
+ }
+
+ public function update_album_test() {
+ $album1 = test::random_album();
+ access::allow(identity::everybody(), "edit", $album1);
+
+ $request = new stdClass();
+ $request->url = rest::url("item", $album1);
+ $request->params = new stdClass();
+ $request->params->title = "my new title";
+
+ item_rest::put($request);
+ $this->assert_equal("my new title", $album1->reload()->title);
+ }
+
+ public function update_album_illegal_value_fails_test() {
+ $album1 = test::random_album();
+ access::allow(identity::everybody(), "edit", $album1);
+
+ $request = new stdClass();
+ $request->url = rest::url("item", $album1);
+ $request->params = new stdClass();
+ $request->params->title = "my new title";
+ $request->params->slug = "not url safe";
+
+ try {
+ item_rest::put($request);
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_equal(array("slug" => "not_url_safe"), $e->validation->errors());
+ return;
+ }
+ $this->assert_true(false, "Shouldn't get here");
+ }
+
+ public function add_album_test() {
+ $album1 = test::random_album();
+ access::allow(identity::everybody(), "edit", $album1);
+
+ $request = new stdClass();
+ $request->url = rest::url("item", $album1);
+ $request->params = new stdClass();
+ $request->params->type = "album";
+ $request->params->name = "my album";
+ $request->params->title = "my album";
+ $response = item_rest::post($request);
+ $new_album = rest::resolve($response["url"]);
+
+ $this->assert_true($new_album->is_album());
+ $this->assert_equal($album1->id, $new_album->parent_id);
+ }
+
+ public function add_album_illegal_value_fails_test() {
+ $album1 = test::random_album();
+ access::allow(identity::everybody(), "edit", $album1);
+
+ $request = new stdClass();
+ $request->url = rest::url("item", $album1);
+ $request->params = new stdClass();
+ $request->params->type = "album";
+ $request->params->name = "my album";
+ $request->params->title = "my album";
+ $request->params->slug = "not url safe";
+
+ try {
+ item_rest::post($request);
+ } catch (ORM_Validation_Exception $e) {
+ $this->assert_equal(array("slug" => "not_url_safe"), $e->validation->errors());
+ return;
+ }
+ $this->assert_true(false, "Shouldn't get here");
+ }
+
+
+ public function add_photo_test() {
+ $album1 = test::random_album();
+ access::allow(identity::everybody(), "edit", $album1);
+
+ $request = new stdClass();
+ $request->url = rest::url("item", $album1);
+ $request->params = new stdClass();
+ $request->params->type = "photo";
+ $request->params->name = "my photo.jpg";
+ $request->file = MODPATH . "gallery/tests/test.jpg";
+ $response = item_rest::post($request);
+ $new_photo = rest::resolve($response["url"]);
+
+ $this->assert_true($new_photo->is_photo());
+ $this->assert_equal($album1->id, $new_photo->parent_id);
+ }
+
+ public function delete_album_test() {
+ $album1 = test::random_album();
+ access::allow(identity::everybody(), "edit", $album1);
+
+ $request = new stdClass();
+ $request->url = rest::url("item", $album1);
+ item_rest::delete($request);
+
+ $album1->reload();
+ $this->assert_false($album1->loaded());
+ }
+
+ public function delete_album_fails_without_permission_test() {
+ $album1 = test::random_album();
+ access::deny(identity::everybody(), "edit", $album1);
+ identity::set_active_user(identity::guest());
+
+ $request = new stdClass();
+ $request->url = rest::url("item", $album1);
+ try {
+ item_rest::delete($request);
+ } catch (Exception $e) {
+ $this->assert_equal("@todo FORBIDDEN", $e->getMessage());
+ return;
+ }
+ $this->assert_true(false, "Shouldn't get here");
+ }
+}
diff --git a/modules/gallery/tests/Locales_Helper_Test.php b/modules/gallery/tests/Locales_Helper_Test.php
index 4c03d8d4..a2680928 100644
--- a/modules/gallery/tests/Locales_Helper_Test.php
+++ b/modules/gallery/tests/Locales_Helper_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Locales_Helper_Test extends Unit_Test_Case {
+class Locales_Helper_Test extends Gallery_Unit_Test_Case {
static $installed_locales;
static $default_locale;
diff --git a/modules/gallery/tests/Menu_Test.php b/modules/gallery/tests/Menu_Test.php
index c91aee0b..643aa727 100644
--- a/modules/gallery/tests/Menu_Test.php
+++ b/modules/gallery/tests/Menu_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Menu_Test extends Unit_Test_Case {
+class Menu_Test extends Gallery_Unit_Test_Case {
public function find_menu_item_test() {
$menu = new Menu(true);
$menu
diff --git a/modules/gallery/tests/Movie_Helper_Test.php b/modules/gallery/tests/Movie_Helper_Test.php
deleted file mode 100644
index 23544934..00000000
--- a/modules/gallery/tests/Movie_Helper_Test.php
+++ /dev/null
@@ -1,56 +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 Movie_Helper_Test extends Unit_Test_Case {
- public function create_movie_shouldnt_allow_names_with_slash_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- try {
- $movie = movie::create($root, MODPATH . "gallery/tests/test.flv", "$rand/.flv", $rand, $rand);
- } catch (Exception $e) {
- // pass
- return;
- }
-
- $this->assert_true(false, "Shouldn't create a movie with / in the name");
- }
-
- public function create_movie_shouldnt_allow_names_with_trailing_periods_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- try {
- $movie = movie::create($root, MODPATH . "gallery/tests/test.flv", "$rand.flv.", $rand, $rand);
- } catch (Exception $e) {
- $this->assert_equal("@todo NAME_CANNOT_END_IN_PERIOD", $e->getMessage());
- return;
- }
-
- $this->assert_true(false, "Shouldn't create a movie with trailing . in the name");
- }
-
- public function create_movie_creates_reasonable_slug_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- $album = album::create($root, $rand, $rand, $rand);
- $movie = movie::create(
- $album, MODPATH . "gallery/tests/test.flv", "This (is) my file%name.flv", $rand, $rand);
-
- $this->assert_equal("This-is-my-file-name", $movie->slug);
- }
-}
diff --git a/modules/gallery/tests/ORM_MPTT_Test.php b/modules/gallery/tests/ORM_MPTT_Test.php
index 69b6bea9..5e741537 100644
--- a/modules/gallery/tests/ORM_MPTT_Test.php
+++ b/modules/gallery/tests/ORM_MPTT_Test.php
@@ -17,21 +17,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class ORM_MPTT_Test extends Unit_Test_Case {
-
- private function create_item_and_add_to_parent($parent) {
- $album = album::create($parent, rand(), "test album");
- return $album;
- }
+class ORM_MPTT_Test extends Gallery_Unit_Test_Case {
public function add_to_parent_test() {
- $root = ORM::factory("item", 1);
- $album = ORM::factory("item");
- $album->type = "album";
- $album->rand_key = ((float)mt_rand()) / (float)mt_getrandmax();
- $album->sort_column = "weight";
- $album->sort_order = "ASC";
- $album->add_to_parent($root);
+ $album = test::random_album();
$this->assert_equal($album->parent()->right_ptr - 2, $album->left_ptr);
$this->assert_equal($album->parent()->right_ptr - 1, $album->right_ptr);
@@ -40,12 +29,11 @@ class ORM_MPTT_Test extends Unit_Test_Case {
}
public function add_hierarchy_test() {
- $root = ORM::factory("item", 1);
- $album1 = self::create_item_and_add_to_parent($root);
- $album1_1 = self::create_item_and_add_to_parent($album1);
- $album1_2 = self::create_item_and_add_to_parent($album1);
- $album1_1_1 = self::create_item_and_add_to_parent($album1_1);
- $album1_1_2 = self::create_item_and_add_to_parent($album1_1);
+ $album1 = test::random_album();
+ $album1_1 = test::random_album($album1);
+ $album1_2 = test::random_album($album1);
+ $album1_1_1 = test::random_album($album1_1);
+ $album1_1_2 = test::random_album($album1_1);
$album1->reload();
$this->assert_equal(9, $album1->right_ptr - $album1->left_ptr);
@@ -55,12 +43,11 @@ class ORM_MPTT_Test extends Unit_Test_Case {
}
public function delete_hierarchy_test() {
- $root = ORM::factory("item", 1);
- $album1 = self::create_item_and_add_to_parent($root);
- $album1_1 = self::create_item_and_add_to_parent($album1);
- $album1_2 = self::create_item_and_add_to_parent($album1);
- $album1_1_1 = self::create_item_and_add_to_parent($album1_1);
- $album1_1_2 = self::create_item_and_add_to_parent($album1_1);
+ $album1 = test::random_album();
+ $album1_1 = test::random_album($album1);
+ $album1_2 = test::random_album($album1);
+ $album1_1_1 = test::random_album($album1_1);
+ $album1_1_2 = test::random_album($album1_1);
$album1_1->delete();
$album1->reload();
@@ -70,17 +57,17 @@ class ORM_MPTT_Test extends Unit_Test_Case {
}
public function move_to_test() {
- $root = ORM::factory("item", 1);
- $album1 = album::create($root, "move_to_test_1", "move_to_test_1");
- $album1_1 = album::create($album1, "move_to_test_1_1", "move_to_test_1_1");
- $album1_2 = album::create($album1, "move_to_test_1_2", "move_to_test_1_2");
- $album1_1_1 = album::create($album1_1, "move_to_test_1_1_1", "move_to_test_1_1_1");
- $album1_1_2 = album::create($album1_1, "move_to_test_1_1_2", "move_to_test_1_1_2");
+ $album1 = test::random_album();
+ $album1_1 = test::random_album($album1);
+ $album1_2 = test::random_album($album1);
+ $album1_1_1 = test::random_album($album1_1);
+ $album1_1_2 = test::random_album($album1_1);
$album1_2->reload();
$album1_1_1->reload();
- $album1_1_1->move_to($album1_2);
+ $album1_1_1->parent_id = $album1_2->id;
+ $album1_1_1->save();
$album1_1->reload();
$album1_2->reload();
@@ -89,39 +76,38 @@ class ORM_MPTT_Test extends Unit_Test_Case {
$this->assert_equal(3, $album1_2->right_ptr - $album1_2->left_ptr);
$this->assert_equal(
- array($album1_1_2->id => "move_to_test_1_1_2"),
+ array($album1_1_2->id => $album1_1_2->name),
$album1_1->children()->select_list());
$this->assert_equal(
- array($album1_1_1->id => "move_to_test_1_1_1"),
+ array($album1_1_1->id => $album1_1_1->name),
$album1_2->children()->select_list());
}
public function cant_move_parent_into_own_subtree_test() {
- $album1 = album::create(item::root(), "move_to_test", "move_to_test");
- $album2 = album::create($album1, "move_to_test", "move_to_test");
- $album3 = album::create($album2, "move_to_test", "move_to_test");
+ $album1 = test::random_album(item::root());
+ $album2 = test::random_album($album1);
+ $album3 = test::random_album($album2);
try {
- $album1->move_to($album3);
- $self->assert_true(false, "We should be unable to move an item inside its own hierarchy");
+ $album1->parent_id = $album3->id;
+ $album1->save();
+ $this->assert_true(false, "We should be unable to move an item inside its own hierarchy");
} catch (Exception $e) {
// pass
}
}
public function parent_test() {
- $root = ORM::factory("item", 1);
- $album = self::create_item_and_add_to_parent($root);
+ $album = test::random_album();
$parent = ORM::factory("item", 1);
$this->assert_equal($parent->id, $album->parent()->id);
}
public function parents_test() {
- $root = ORM::factory("item", 1);
- $outer = self::create_item_and_add_to_parent($root);
- $inner = self::create_item_and_add_to_parent($outer);
+ $outer = test::random_album();
+ $inner = test::random_album($outer);
$parent_ids = array();
foreach ($inner->parents() as $parent) {
@@ -131,10 +117,9 @@ class ORM_MPTT_Test extends Unit_Test_Case {
}
public function children_test() {
- $root = ORM::factory("item", 1);
- $outer = self::create_item_and_add_to_parent($root);
- $inner1 = self::create_item_and_add_to_parent($outer);
- $inner2 = self::create_item_and_add_to_parent($outer);
+ $outer = test::random_album();
+ $inner1 = test::random_album($outer);
+ $inner2 = test::random_album($outer);
$child_ids = array();
foreach ($outer->children() as $child) {
@@ -144,48 +129,27 @@ class ORM_MPTT_Test extends Unit_Test_Case {
}
public function children_limit_test() {
- $root = ORM::factory("item", 1);
- $outer = self::create_item_and_add_to_parent($root);
- $inner1 = self::create_item_and_add_to_parent($outer);
- $inner2 = self::create_item_and_add_to_parent($outer);
+ $outer = test::random_album();
+ $inner1 = test::random_album($outer);
+ $inner2 = test::random_album($outer);
$this->assert_equal(array($inner2->id => $inner2->name),
$outer->children(1, 1)->select_list('id'));
}
public function children_count_test() {
- $root = ORM::factory("item", 1);
- $outer = self::create_item_and_add_to_parent($root);
- $inner1 = self::create_item_and_add_to_parent($outer);
- $inner2 = self::create_item_and_add_to_parent($outer);
+ $outer = test::random_album();
+ $inner1 = test::random_album($outer);
+ $inner2 = test::random_album($outer);
$this->assert_equal(2, $outer->children_count());
}
public function descendant_test() {
- $root = ORM::factory("item", 1);
-
- $parent = ORM::factory("item");
- $parent->type = "album";
- $parent->rand_key = ((float)mt_rand()) / (float)mt_getrandmax();
- $parent->sort_column = "weight";
- $parent->sort_order = "ASC";
- $parent->add_to_parent($root);
-
- $photo = ORM::factory("item");
- $photo->type = "photo";
- $photo->add_to_parent($parent);
-
- $album1 = ORM::factory("item");
- $album1->type = "album";
- $album1->rand_key = ((float)mt_rand()) / (float)mt_getrandmax();
- $album1->sort_column = "weight";
- $album1->sort_order = "ASC";
- $album1->add_to_parent($parent);
-
- $photo1 = ORM::factory("item");
- $photo1->type = "photo";
- $photo1->add_to_parent($album1);
+ $parent = test::random_album();
+ $photo = test::random_photo($parent);
+ $album1 = test::random_album($parent);
+ $photo1 = test::random_photo($album1);
$parent->reload();
@@ -195,36 +159,20 @@ class ORM_MPTT_Test extends Unit_Test_Case {
}
public function descendant_limit_test() {
- $root = ORM::factory("item", 1);
-
- $parent = self::create_item_and_add_to_parent($root);
- $album1 = self::create_item_and_add_to_parent($parent);
- $album2 = self::create_item_and_add_to_parent($parent);
- $album3 = self::create_item_and_add_to_parent($parent);
-
+ $parent = test::random_album();
+ $album1 = test::random_album($parent);
+ $album2 = test::random_album($parent);
+ $album3 = test::random_album($parent);
$parent->reload();
+
$this->assert_equal(2, $parent->descendants(2)->count());
}
public function descendant_count_test() {
- $root = ORM::factory("item", 1);
-
- $parent = ORM::factory("item");
- $parent->type = "album";
- $parent->add_to_parent($root);
-
- $photo = ORM::factory("item");
- $photo->type = "photo";
- $photo->add_to_parent($parent);
-
- $album1 = ORM::factory("item");
- $album1->type = "album";
- $album1->add_to_parent($parent);
-
- $photo1 = ORM::factory("item");
- $photo1->type = "photo";
- $photo1->add_to_parent($album1);
-
+ $parent = test::random_album();
+ $photo = test::random_photo($parent);
+ $album1 = test::random_album($parent);
+ $photo1 = test::random_photo($album1);
$parent->reload();
$this->assert_equal(3, $parent->descendants_count());
diff --git a/modules/gallery/tests/Photo_Helper_Test.php b/modules/gallery/tests/Photo_Helper_Test.php
deleted file mode 100644
index 97923f90..00000000
--- a/modules/gallery/tests/Photo_Helper_Test.php
+++ /dev/null
@@ -1,130 +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 Photo_Helper_Test extends Unit_Test_Case {
- public function create_photo_test() {
- $rand = rand();
-
- $filename = MODPATH . "gallery/tests/test.jpg";
- $image_info = getimagesize($filename);
-
- $root = ORM::factory("item", 1);
- $photo = photo::create($root, $filename, "$rand.jpg", $rand, $rand);
-
- $this->assert_equal(VARPATH . "albums/$rand.jpg", $photo->file_path());
- $this->assert_equal(VARPATH . "thumbs/{$rand}.jpg", $photo->thumb_path());
- $this->assert_equal(VARPATH . "resizes/{$rand}.jpg", $photo->resize_path());
-
- $this->assert_true(is_file($photo->file_path()), "missing: {$photo->file_path()}");
- $this->assert_true(is_file($photo->resize_path()), "missing: {$photo->resize_path()}");
- $this->assert_true(is_file($photo->thumb_path()), "missing: {$photo->thumb_path()}");
-
- $this->assert_equal($root->id, $photo->parent_id); // MPTT tests cover other hierarchy checks
- $this->assert_equal("$rand.jpg", $photo->name);
- $this->assert_equal($rand, $photo->title);
- $this->assert_equal($rand, $photo->description);
- $this->assert_equal("image/jpeg", $photo->mime_type);
- $this->assert_equal($image_info[0], $photo->width);
- $this->assert_equal($image_info[1], $photo->height);
-
- $this->assert_equal($photo->parent()->right_ptr - 2, $photo->left_ptr);
- $this->assert_equal($photo->parent()->right_ptr - 1, $photo->right_ptr);
- }
-
- public function create_conflicting_photo_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- $photo1 = photo::create($root, MODPATH . "gallery/tests/test.jpg", "$rand.jpg", $rand, $rand);
- $photo2 = photo::create($root, MODPATH . "gallery/tests/test.jpg", "$rand.jpg", $rand, $rand);
- $this->assert_true($photo1->name != $photo2->name);
- }
-
- public function create_photo_with_no_extension_test() {
- $root = ORM::factory("item", 1);
- try {
- photo::create($root, "/tmp", "name", "title", "description");
- $this->assert_false("should fail with an exception");
- } catch (Exception $e) {
- // pass
- }
- }
-
- public function thumb_url_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- $photo = photo::create($root, MODPATH . "gallery/tests/test.jpg", "$rand.jpg", $rand, $rand);
- $this->assert_equal("http://./var/thumbs/{$rand}.jpg?m={$photo->updated}", $photo->thumb_url());
- }
-
- public function resize_url_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- $album = album::create($root, $rand, $rand, $rand);
- $photo = photo::create($album, MODPATH . "gallery/tests/test.jpg", "$rand.jpg", $rand, $rand);
-
- $this->assert_equal(
- "http://./var/resizes/{$rand}/{$rand}.jpg?m={$photo->updated}", $photo->resize_url());
- }
-
- public function file_url_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- $album = album::create($root, $rand, $rand, $rand);
- $photo = photo::create($album, MODPATH . "gallery/tests/test.jpg", "$rand.jpg", $rand, $rand);
-
- $this->assert_equal(
- "http://./var/albums/{$rand}/{$rand}.jpg?m={$photo->updated}", $photo->file_url());
- }
-
- public function create_photo_creates_reasonable_slug_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- $album = album::create($root, $rand, $rand, $rand);
- $photo = photo::create(
- $album, MODPATH . "gallery/tests/test.jpg", "This (is) my file%name.jpg", $rand, $rand);
-
- $this->assert_equal("This-is-my-file-name", $photo->slug);
- }
-
- public function create_photo_shouldnt_allow_names_with_slash_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- try {
- $photo = photo::create($root, MODPATH . "gallery/tests/test.jpg", "$rand/.jpg", $rand, $rand);
- } catch (Exception $e) {
- // pass
- return;
- }
-
- $this->assert_true(false, "Shouldn't create a photo with / in the name");
- }
-
- public function create_photo_silently_trims_trailing_periods_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- try {
- $photo = photo::create($root, MODPATH . "gallery/tests/test.jpg", "$rand.jpg.", $rand, $rand);
- } catch (Exception $e) {
- $this->assert_equal("@todo NAME_CANNOT_END_IN_PERIOD", $e->getMessage());
- return;
- }
-
- $this->assert_true(false, "Shouldn't create a photo with trailing . in the name");
- }
-}
diff --git a/modules/gallery/tests/Photos_Controller_Test.php b/modules/gallery/tests/Photos_Controller_Test.php
index b6c6df47..50d49fcc 100644
--- a/modules/gallery/tests/Photos_Controller_Test.php
+++ b/modules/gallery/tests/Photos_Controller_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Photos_Controller_Test extends Unit_Test_Case {
+class Photos_Controller_Test extends Gallery_Unit_Test_Case {
public function setup() {
$this->_save = array($_POST, $_SERVER);
$_SERVER["HTTP_REFERER"] = "HTTP_REFERER";
@@ -29,19 +29,14 @@ class Photos_Controller_Test extends Unit_Test_Case {
public function change_photo_test() {
$controller = new Photos_Controller();
- $root = ORM::factory("item", 1);
- $photo = photo::create(
- $root, MODPATH . "gallery/tests/test.jpg", "test.jpeg",
- "test", "test", identity::active_user()->id, "slug");
- $orig_name = $photo->name;
+ $photo = test::random_photo();
- $_POST["filename"] = "test.jpeg";
- $_POST["name"] = "new name";
+ $_POST["name"] = "new name.jpg";
$_POST["title"] = "new title";
$_POST["description"] = "new description";
$_POST["slug"] = "new-slug";
$_POST["csrf"] = access::csrf_token();
- access::allow(identity::everybody(), "edit", $root);
+ access::allow(identity::everybody(), "edit", item::root());
ob_start();
$controller->update($photo->id);
@@ -53,26 +48,25 @@ class Photos_Controller_Test extends Unit_Test_Case {
$this->assert_equal("new-slug", $photo->slug);
$this->assert_equal("new title", $photo->title);
$this->assert_equal("new description", $photo->description);
-
- // We don't change the name, yet.
- $this->assert_equal($orig_name, $photo->name);
+ $this->assert_equal("new name.jpg", $photo->name);
}
public function change_photo_no_csrf_fails_test() {
$controller = new Photos_Controller();
- $root = ORM::factory("item", 1);
- $photo = photo::create(
- $root, MODPATH . "gallery/tests/test.jpg", "test.jpg", "test", "test");
- $_POST["name"] = "new name";
+ $photo = test::random_photo();
+
+ $_POST["name"] = "new name.jpg";
$_POST["title"] = "new title";
$_POST["description"] = "new description";
- access::allow(identity::everybody(), "edit", $root);
+ $_POST["slug"] = "new slug";
+ access::allow(identity::everybody(), "edit", item::root());
try {
- $controller->_update($photo);
+ $controller->update($photo);
$this->assert_true(false, "This should fail");
} catch (Exception $e) {
// pass
+ $this->assert_same("@todo FORBIDDEN", $e->getMessage());
}
}
}
diff --git a/modules/gallery/tests/SafeString_Test.php b/modules/gallery/tests/SafeString_Test.php
index 2c07d934..7002a874 100644
--- a/modules/gallery/tests/SafeString_Test.php
+++ b/modules/gallery/tests/SafeString_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class SafeString_Test extends Unit_Test_Case {
+class SafeString_Test extends Gallery_Unit_Test_Case {
public function toString_escapes_for_html_test() {
$safe_string = new SafeString("hello <p>world</p>");
$this->assert_equal("hello &lt;p&gt;world&lt;/p&gt;",
diff --git a/modules/gallery/tests/Sendmail_Test.php b/modules/gallery/tests/Sendmail_Test.php
index f3a8d897..bc57e434 100644
--- a/modules/gallery/tests/Sendmail_Test.php
+++ b/modules/gallery/tests/Sendmail_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Sendmail_Test extends Unit_Test_Case {
+class Sendmail_Test extends Gallery_Unit_Test_Case {
public function setup() {
Kohana_Config::instance()->set("sendmail.from", "from@gallery3.com");
}
diff --git a/modules/gallery/tests/Url_Security_Test.php b/modules/gallery/tests/Url_Security_Test.php
index de25880f..255b3909 100644
--- a/modules/gallery/tests/Url_Security_Test.php
+++ b/modules/gallery/tests/Url_Security_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Url_Security_Test extends Unit_Test_Case {
+class Url_Security_Test extends Gallery_Unit_Test_Case {
public function setup() {
$this->save = array(Router::$current_uri, Router::$complete_uri, $_GET);
}
diff --git a/modules/gallery/tests/Var_Test.php b/modules/gallery/tests/Var_Test.php
index 355d94a7..fb19da7a 100644
--- a/modules/gallery/tests/Var_Test.php
+++ b/modules/gallery/tests/Var_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Var_Test extends Unit_Test_Case {
+class Var_Test extends Gallery_Unit_Test_Case {
public function add_parameter_test() {
module::set_var("gallery", "Parameter", "original value");
$this->assert_equal("original value", module::get_var("gallery", "Parameter"));
diff --git a/modules/gallery/tests/Xss_Security_Test.php b/modules/gallery/tests/Xss_Security_Test.php
index b296d97c..a39a069d 100644
--- a/modules/gallery/tests/Xss_Security_Test.php
+++ b/modules/gallery/tests/Xss_Security_Test.php
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Xss_Security_Test extends Unit_Test_Case {
+class Xss_Security_Test extends Gallery_Unit_Test_Case {
public function find_unescaped_variables_in_views_test() {
$found = array();
foreach (glob("*/*/views/*.php") as $view) {
diff --git a/modules/gallery/tests/controller_auth_data.txt b/modules/gallery/tests/controller_auth_data.txt
index da7108d8..0aa26057 100644
--- a/modules/gallery/tests/controller_auth_data.txt
+++ b/modules/gallery/tests/controller_auth_data.txt
@@ -19,12 +19,12 @@ modules/gallery/controllers/quick.php form_edit
modules/gallery/controllers/simple_uploader.php start DIRTY_AUTH
modules/gallery/controllers/simple_uploader.php finish DIRTY_AUTH
modules/gallery/controllers/upgrader.php index DIRTY_AUTH
-modules/gallery/controllers/user_profile.php show DIRTY_CSRF|DIRTY_AUTH
+modules/gallery/controllers/user_profile.php show DIRTY_AUTH
modules/gallery/controllers/user_profile.php contact DIRTY_AUTH
modules/gallery/controllers/user_profile.php send DIRTY_AUTH
modules/gallery/controllers/welcome_message.php index DIRTY_AUTH
-modules/rest/controllers/rest.php access_key DIRTY_CSRF|DIRTY_AUTH
-modules/rest/controllers/rest.php __call DIRTY_AUTH
+modules/rest/controllers/rest.php index DIRTY_CSRF|DIRTY_AUTH
+modules/rest/controllers/rest.php __call DIRTY_CSRF|DIRTY_AUTH
modules/rss/controllers/rss.php feed DIRTY_CSRF|DIRTY_AUTH
modules/search/controllers/search.php index DIRTY_CSRF|DIRTY_AUTH
modules/server_add/controllers/admin_server_add.php autocomplete DIRTY_CSRF
diff --git a/modules/gallery/tests/xss_data.txt b/modules/gallery/tests/xss_data.txt
index a89725c0..65b45a08 100644
--- a/modules/gallery/tests/xss_data.txt
+++ b/modules/gallery/tests/xss_data.txt
@@ -34,19 +34,21 @@ modules/comment/views/comment.mrss.php 35 DIRTY_ATTR $chi
modules/comment/views/comment.mrss.php 35 DIRTY_ATTR $child->thumb_width
modules/comment/views/comments.html.php 16 DIRTY_ATTR $comment->id
modules/comment/views/comments.html.php 19 DIRTY_ATTR $comment->author()->avatar_url(40,$theme->url(,true))
+modules/comment/views/user_profile_comments.html.php 5 DIRTY_ATTR $comment->id
+modules/comment/views/user_profile_comments.html.php 10 DIRTY_JS $comment->item()->url()
+modules/comment/views/user_profile_comments.html.php 11 DIRTY $comment->item()->thumb_img(array(),50)
modules/digibug/views/digibug_form.html.php 4 DIRTY form::open("http://www.digibug.com/dapi/order.php")
-modules/digibug/views/digibug_form.html.php 5 DIRTY form::hidden($order_parms)
-modules/digibug/views/digibug_form.html.php 6 DIRTY form::close()
+modules/digibug/views/digibug_form.html.php 6 DIRTY form::hidden($key,$value)
modules/exif/views/exif_dialog.html.php 14 DIRTY $details[$i]["caption"]
modules/exif/views/exif_dialog.html.php 21 DIRTY $details[$i]["caption"]
modules/g2_import/views/admin_g2_import.html.php 30 DIRTY $form
modules/gallery/views/admin_advanced_settings.html.php 21 DIRTY_ATTR text::alternate("g-odd","g-even")
modules/gallery/views/admin_advanced_settings.html.php 22 DIRTY $var->module_name
modules/gallery/views/admin_block_log_entries.html.php 4 DIRTY_ATTR log::severity_class($entry->severity)
-modules/gallery/views/admin_block_log_entries.html.php 5 DIRTY_JS user_profile::url($entryr->id)
-modules/gallery/views/admin_block_log_entries.html.php 6 DIRTY gallery::date_time($entry->timestamp)
-modules/gallery/views/admin_block_log_entries.html.php 7 DIRTY $entry->message
-modules/gallery/views/admin_block_log_entries.html.php 8 DIRTY $entry->html
+modules/gallery/views/admin_block_log_entries.html.php 8 DIRTY_JS user_profile::url($entry->user->id)
+modules/gallery/views/admin_block_log_entries.html.php 10 DIRTY gallery::date_time($entry->timestamp)
+modules/gallery/views/admin_block_log_entries.html.php 11 DIRTY $entry->message
+modules/gallery/views/admin_block_log_entries.html.php 12 DIRTY $entry->html
modules/gallery/views/admin_block_news.html.php 5 DIRTY_JS $entry["link"]
modules/gallery/views/admin_block_news.html.php 5 DIRTY $entry["title"]
modules/gallery/views/admin_block_news.html.php 7 DIRTY text::limit_words(strip_tags($entry["description"]),25);
@@ -94,13 +96,11 @@ modules/gallery/views/admin_maintenance.html.php 158 DIRTY $task-
modules/gallery/views/admin_maintenance_show_log.html.php 8 DIRTY_JS url::site("admin/maintenance/save_log/$task->id?csrf=$csrf")
modules/gallery/views/admin_maintenance_show_log.html.php 13 DIRTY $task->name
modules/gallery/views/admin_maintenance_task.html.php 55 DIRTY $task->name
-modules/gallery/views/admin_modules.html.php 25 DIRTY_JS t("Continue")
-modules/gallery/views/admin_modules.html.php 35 DIRTY_JS t("Continue")
modules/gallery/views/admin_modules.html.php 51 DIRTY access::csrf_form_field()
modules/gallery/views/admin_modules.html.php 60 DIRTY_ATTR text::alternate("g-odd","g-even")
modules/gallery/views/admin_modules.html.php 63 DIRTY form::checkbox($data,'1',module::is_active($module_name))
modules/gallery/views/admin_modules.html.php 65 DIRTY $module_info->version
-modules/gallery/views/admin_modules_confirm.html.php 11 DIRTY_ATTR $class
+modules/gallery/views/admin_modules_confirm.html.php 11 DIRTY_ATTR $css_class
modules/gallery/views/admin_modules_confirm.html.php 11 DIRTY $message
modules/gallery/views/admin_modules_confirm.html.php 16 DIRTY access::csrf_form_field()
modules/gallery/views/admin_modules_confirm.html.php 18 DIRTY form::hidden($module,1)
@@ -124,11 +124,9 @@ modules/gallery/views/form_uploadify.html.php 30 DIRTY_JS url::f
modules/gallery/views/form_uploadify.html.php 31 DIRTY_JS url::site("simple_uploader/add_photo/{$album->id}")
modules/gallery/views/form_uploadify.html.php 35 DIRTY_JS url::file("lib/uploadify/cancel.png")
modules/gallery/views/form_uploadify.html.php 36 DIRTY_JS $simultaneous_upload_limit
-modules/gallery/views/form_uploadify.html.php 61 DIRTY_JS t("Completed")
-modules/gallery/views/in_place_edit.html.php 2 DIRTY form::open($action,array("method"=>"post","id"=>"g-in-place-edit-form","class"=>"g-short-form"),$hidden)
-modules/gallery/views/in_place_edit.html.php 5 DIRTY form::input("input",$form["input"]," class=\"textbox\"")
-modules/gallery/views/in_place_edit.html.php 12 DIRTY form::close()
-modules/gallery/views/in_place_edit.html.php 14 DIRTY $errors["input"]
+modules/gallery/views/in_place_edit.html.php 2 DIRTY form::open($action,array("method"=>"post","id"=>"g-in-place-edit-form","class"=>"g-short-form"))
+modules/gallery/views/in_place_edit.html.php 3 DIRTY access::csrf_form_field()
+modules/gallery/views/in_place_edit.html.php 6 DIRTY form::input("input",$form["input"]," class=\"textbox\"")
modules/gallery/views/kohana_error_page.php 102 DIRTY $message
modules/gallery/views/kohana_error_page.php 116 DIRTY $trace
modules/gallery/views/kohana_profiler.php 32 DIRTY $profile->render();
@@ -219,10 +217,8 @@ modules/gallery/views/upgrader.html.php 77 DIRTY $modul
modules/gallery/views/upgrader.html.php 99 DIRTY_ATTR $done?"muted":""
modules/gallery/views/upgrader.html.php 102 DIRTY_ATTR $done?"muted":""
modules/gallery/views/user_languages_block.html.php 2 DIRTY form::dropdown("g-select-session-locale",$installed_locales,$selected)
-modules/gallery/views/user_profile.html.php 35 DIRTY_ATTR $height
-modules/gallery/views/user_profile.html.php 44 DIRTY $field
-modules/gallery/views/user_profile.html.php 45 DIRTY $value
-modules/gallery/views/user_profile.html.php 65 DIRTY_JS $return->for_html_attr()
+modules/gallery/views/user_profile.html.php 36 DIRTY_ATTR $user->avatar_url(40,$theme->url(,true))
+modules/gallery/views/user_profile.html.php 47 DIRTY $info->view
modules/image_block/views/image_block_block.html.php 3 DIRTY_JS $item->url()
modules/image_block/views/image_block_block.html.php 4 DIRTY $item->thumb_img(array("class"=>"g-thumbnail"))
modules/info/views/info_block.html.php 22 DIRTY date("M j, Y H:i:s",$item->captured)
@@ -235,6 +231,8 @@ modules/notification/views/item_deleted.html.php 18 DIRTY_JS $item-
modules/notification/views/item_deleted.html.php 19 DIRTY $item->parent()->abs_url()
modules/notification/views/item_updated.html.php 20 DIRTY_JS $item->abs_url()
modules/notification/views/item_updated.html.php 20 DIRTY $item->abs_url()
+modules/notification/views/user_profile_notification.html.php 5 DIRTY_ATTR $subscription->id
+modules/notification/views/user_profile_notification.html.php 6 DIRTY_JS $subscription->url
modules/organize/views/organize_dialog.html.php 3 DIRTY_JS url::site("organize/move_to/__ALBUM_ID__?csrf=$csrf")
modules/organize/views/organize_dialog.html.php 4 DIRTY_JS url::site("organize/rearrange/__TARGET_ID__/__BEFORE__?csrf=$csrf")
modules/organize/views/organize_dialog.html.php 5 DIRTY_JS url::site("organize/sort_order/__ALBUM_ID__/__COL__/__DIR__?csrf=$csrf")
diff --git a/modules/gallery/views/admin_block_log_entries.html.php b/modules/gallery/views/admin_block_log_entries.html.php
index 453724cb..5a8ed23c 100644
--- a/modules/gallery/views/admin_block_log_entries.html.php
+++ b/modules/gallery/views/admin_block_log_entries.html.php
@@ -2,7 +2,11 @@
<ul>
<? foreach ($entries as $entry): ?>
<li class="<?= log::severity_class($entry->severity) ?>" style="direction: ltr">
+ <? if ($entry->user->guest): ?>
+ </span><?= html::clean($entry->user->name) ?></span>
+ <? else: ?>
<a href="<?= user_profile::url($entry->user->id) ?>"><?= html::clean($entry->user->name) ?></a>
+ <? endif ?>
<?= gallery::date_time($entry->timestamp) ?>
<?= $entry->message ?>
<?= $entry->html ?>
diff --git a/modules/gallery/views/admin_modules.html.php b/modules/gallery/views/admin_modules.html.php
index 26b2c87c..c5015e68 100644
--- a/modules/gallery/views/admin_modules.html.php
+++ b/modules/gallery/views/admin_modules.html.php
@@ -22,7 +22,7 @@
buttons: {
<?= t("Continue")->for_js() ?>: function() {
$("form", this).submit();
- $(".ui-dialog-buttonpane button:contains(<?= t("Continue") ?>)")
+ $(".ui-dialog-buttonpane button:contains(" + <?= t("Continue")->for_js() ?> + ")")
.attr("disabled", "disabled")
.addClass("ui-state-disabled");
},
@@ -32,7 +32,7 @@
}
});
if (!data.allow_continue) {
- $(".ui-dialog-buttonpane button:contains(<?= t("Continue") ?>)")
+ $(".ui-dialog-buttonpane button:contains(" + <?= t("Continue")->for_js() ?> + ")")
.attr("disabled", "disabled")
.addClass("ui-state-disabled");
}
diff --git a/modules/gallery/views/admin_modules_confirm.html.php b/modules/gallery/views/admin_modules_confirm.html.php
index 59592505..8c4cb2bd 100644
--- a/modules/gallery/views/admin_modules_confirm.html.php
+++ b/modules/gallery/views/admin_modules_confirm.html.php
@@ -6,9 +6,9 @@
<div id="g-admin-modules-messages" class="g-block-content">
<ul>
- <? foreach (array("error" => "g-error", "warn" => "g-warning") as $type => $class): ?>
+ <? foreach (array("error" => "g-error", "warn" => "g-warning") as $type => $css_class): ?>
<? foreach ($messages[$type] as $message): ?>
- <li class="<?= $class ?>" style="padding-bottom: 0"><?= $message ?></li>
+ <li class="<?= $css_class ?>" style="padding-bottom: 0"><?= $message ?></li>
<? endforeach ?>
<? endforeach ?>
</ul>
diff --git a/modules/gallery/views/form_uploadify.html.php b/modules/gallery/views/form_uploadify.html.php
index b3b81ecb..137cb353 100644
--- a/modules/gallery/views/form_uploadify.html.php
+++ b/modules/gallery/views/form_uploadify.html.php
@@ -58,7 +58,7 @@
"<li class=\"g-error\">" + fileObj.name + " - " + msg[1] + "</li>");
} else {
$("#g-add-photos-status ul").append(
- "<li class=\"g-success\">" + fileObj.name + " - <?= t("Completed") ?></li>");
+ "<li class=\"g-success\">" + fileObj.name + " - " + <?= t("Completed")->for_js() ?> + "</li>");
}
return true;
},
diff --git a/modules/gallery/views/in_place_edit.html.php b/modules/gallery/views/in_place_edit.html.php
index 45cf1d8c..05a16ad4 100644
--- a/modules/gallery/views/in_place_edit.html.php
+++ b/modules/gallery/views/in_place_edit.html.php
@@ -1,5 +1,6 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
-<?= form::open($action, array("method" => "post", "id" => "g-in-place-edit-form", "class" => "g-short-form"), $hidden) ?>
+<?= form::open($action, array("method" => "post", "id" => "g-in-place-edit-form", "class" => "g-short-form")) ?>
+ <?= access::csrf_form_field() ?>
<ul>
<li<? if (!empty($errors["input"])): ?> class="g-error"<? endif ?>>
<?= form::input("input", $form["input"], " class=\"textbox\"") ?>
@@ -9,8 +10,6 @@
</li>
<li><a href="#" class="g-cancel"><?= t("Cancel") ?></a></li>
</ul>
-<?= form::close() ?>
-<? if (!empty($errors["input"])): ?>
-<div id="g-in-place-edit-message" class="g-error"><?= $errors["input"] ?></div>
-<? endif ?>
+</form>
+
diff --git a/modules/gallery/views/kohana/error.php b/modules/gallery/views/kohana/error.php
index 7271db14..26628cf2 100644
--- a/modules/gallery/views/kohana/error.php
+++ b/modules/gallery/views/kohana/error.php
@@ -1,5 +1,6 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
<? $error_id = uniqid("error") ?>
+<? if (!function_exists("t")) { function t($msg) { return $msg; } } ?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<style type="text/css">
@@ -131,7 +132,7 @@
</head>
<body>
<? try { $user = identity::active_user(); } catch (Exception $e) { } ?>
- <? $admin = php_sapi_name() == "cli" || isset($user) && $user->admin ?>
+ <? $admin = php_sapi_name() == "cli" || (class_exists("User_Model") && isset($user) && $user->admin) ?>
<div class="big_box" id="framework_error">
<h1>
<?= t("Dang... Something went wrong!") ?>
diff --git a/modules/gallery/views/user_languages_block.html.php b/modules/gallery/views/user_languages_block.html.php
index 89185967..3776ca13 100644
--- a/modules/gallery/views/user_languages_block.html.php
+++ b/modules/gallery/views/user_languages_block.html.php
@@ -1,7 +1,7 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
<?= form::dropdown("g-select-session-locale", $installed_locales, $selected) ?>
<script type="text/javascript">
- $("#g-select-session-locale").change(function() {
+ $("select[name=g-select-session-locale]").change(function() {
var old_locale_preference = <?= html::js_string($selected) ?>;
var locale = $(this).val();
if (old_locale_preference == locale) {
diff --git a/modules/gallery/views/user_profile.html.php b/modules/gallery/views/user_profile.html.php
index 708b1613..f35f8c3f 100644
--- a/modules/gallery/views/user_profile.html.php
+++ b/modules/gallery/views/user_profile.html.php
@@ -26,6 +26,7 @@
$(document).ready(function() {
$("#g-profile-return").click(function(event) {
history.go(-1);
+ return false;
})
});
</script>
@@ -41,7 +42,7 @@
<? foreach ($info_parts as $info): ?>
<div>
<fieldset>
- <label><?= $info->title ?></label>
+ <label><?= html::purify($info->title) ?></label>
<div>
<?= $info->view ?>
</div>
diff --git a/modules/gallery/views/user_profile_info.html.php b/modules/gallery/views/user_profile_info.html.php
index 2a2549c8..58e134bb 100644
--- a/modules/gallery/views/user_profile_info.html.php
+++ b/modules/gallery/views/user_profile_info.html.php
@@ -1,9 +1,9 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
<table>
- <? foreach ($fields as $field => $value): ?>
+ <? foreach ($user_profile_data as $label => $value): ?>
<tr>
- <td><?= $field ?></td>
- <td><?= $value ?></td>
+ <td><?= html::clean($label) ?></td>
+ <td><?= html::purify($value) ?></td>
</tr>
<? endforeach ?>
</table>
diff --git a/modules/gallery_unit_test/controllers/gallery_unit_test.php b/modules/gallery_unit_test/controllers/gallery_unit_test.php
index 498dd756..2690ad24 100644
--- a/modules/gallery_unit_test/controllers/gallery_unit_test.php
+++ b/modules/gallery_unit_test/controllers/gallery_unit_test.php
@@ -18,11 +18,15 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class Gallery_Unit_Test_Controller extends Controller {
- function Index() {
+ function index() {
if (!TEST_MODE) {
throw new Kohana_404_Exception();
}
+ // Force strict behavior to flush out bugs early
+ ini_set("display_errors", true);
+ error_reporting(-1);
+
// Jump through some hoops to satisfy the way that we check for the site_domain in
// config.php. We structure this such that the code in config will leave us with a
// site_domain of "." (for historical reasons)
@@ -127,6 +131,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..3e116808
--- /dev/null
+++ b/modules/gallery_unit_test/helpers/test.php
@@ -0,0 +1,85 @@
+<?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()->reload();
+ }
+
+ 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()->reload();
+ }
+
+ static function random_user($password="password") {
+ $rand = "name_" . rand();
+ return identity::create_user($rand, $rand, $password, "$rand@rand.com");
+ }
+
+ static function random_group() {
+ return identity::create_group((string)rand());
+ }
+
+ static function random_name($item=null) {
+ $rand = "name_" . rand();
+ if ($item && $item->is_photo()) {
+ $rand .= ".jpg";
+ }
+ return $rand;
+ }
+
+ static function starts_with($outer, $inner) {
+ return strpos($outer, $inner) === 0;
+ }
+
+ static function call_and_capture($callback) {
+ ob_start();
+ call_user_func($callback);
+ return ob_get_clean();
+ }
+
+ static function random_tag() {
+ $tag = ORM::factory("tag");
+ $tag->name = (string)rand();
+
+ // Reload so that ORM coerces all fields into strings.
+ return $tag->save()->reload();
+ }
+}
diff --git a/modules/gallery_unit_test/libraries/Gallery_Unit_Test_Case.php b/modules/gallery_unit_test/libraries/Gallery_Unit_Test_Case.php
new file mode 100644
index 00000000..509b4125
--- /dev/null
+++ b/modules/gallery_unit_test/libraries/Gallery_Unit_Test_Case.php
@@ -0,0 +1,36 @@
+<?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 Gallery_Unit_Test_Case extends Unit_Test_Case {
+ public function assert_equal_array($expected, $actual, $debug=null) {
+ if ($expected !== $actual) {
+ throw new Kohana_Unit_Test_Exception(
+ sprintf("Expected (%s) %s but received (%s) %s\n Diff: %s",
+ gettype($expected), var_export($expected, true),
+ gettype($actual), var_export($actual, true),
+ diff::compare(var_export($expected, true), var_export($actual, true))),
+ $debug);
+ }
+ return $this;
+ }
+
+ public function assert_array_equal_to_json($expected_array, $actual_json, $debug=null) {
+ return $this->assert_equal_array($expected_array, json_decode($actual_json, true), $debug);
+ }
+}
diff --git a/modules/gallery_unit_test/views/kohana/error.php b/modules/gallery_unit_test/views/kohana/error.php
new file mode 100644
index 00000000..079a279b
--- /dev/null
+++ b/modules/gallery_unit_test/views/kohana/error.php
@@ -0,0 +1,6 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<?
+echo $e->getMessage(), "\n";
+echo $e->getFile(), ":", $e->getLine(), "\n";
+echo $e->getTraceAsString(), "\n";
+
diff --git a/modules/gallery_unit_test/views/kohana_error_page.php b/modules/gallery_unit_test/views/kohana_error_page.php
deleted file mode 100644
index c0ae7173..00000000
--- a/modules/gallery_unit_test/views/kohana_error_page.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php defined("SYSPATH") or die("No direct script access.") ?>
-<?
-echo $error, "\n\n";
-echo wordwrap($description, 80), "\n\n";
-if (!empty($line) && !empty($file)) {
- echo $file, "[", $line, "]:\n";
-}
-echo $message, "\n\n";
-
-if (!empty($trace)) {
- $trace = preg_replace(
- array('/<li>/', '/<(.*?)>/', '/&gt;/'),
- array(" ", '', '>'),
- $trace);
- echo "Stack Trace:\n";
- echo $trace, "\n";
-}
-
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..185df850 100644
--- a/modules/image_block/helpers/image_block_block.php
+++ b/modules/image_block/helpers/image_block_block.php
@@ -26,34 +26,13 @@ class image_block_block_Core {
$block = "";
switch ($block_id) {
case "random_image":
- $block = new Block();
- $block->css_id = "g-image-block";
- $block->title = t("Random image");
- $block->content = new View("image_block_block.html");
-
- $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 {
- $block = "";
+ $item = item::random_query(array(array("type", "!=", "album")))->find_all(1)->current();
+ if ($item && $item->loaded()) {
+ $block = new Block();
+ $block->css_id = "g-image-block";
+ $block->title = t("Random image");
+ $block->content = new View("image_block_block.html");
+ $block->content->item = $item;
}
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/organize/controllers/organize.php b/modules/organize/controllers/organize.php
index 201ced30..4a4b9f13 100644
--- a/modules/organize/controllers/organize.php
+++ b/modules/organize/controllers/organize.php
@@ -36,7 +36,7 @@ class Organize_Controller extends Controller {
access::required("edit", $album);
print json_encode(
- array("grid" => self::_get_micro_thumb_grid($album, $offset)->__toString(),
+ array("grid" => (string)self::_get_micro_thumb_grid($album, $offset),
"sort_column" => $album->sort_column,
"sort_order" => $album->sort_order));
}
@@ -57,8 +57,8 @@ class Organize_Controller extends Controller {
}
print json_encode(
- array("tree" => self::_expanded_tree(ORM::factory("item", 1), $target_album)->__toString(),
- "grid" => self::_get_micro_thumb_grid($target_album, 0)->__toString()));
+ array("tree" => (string)self::_expanded_tree(ORM::factory("item", 1), $target_album),
+ "grid" => (string)self::_get_micro_thumb_grid($target_album, 0)));
}
function rearrange($target_id, $before_or_after) {
@@ -114,7 +114,7 @@ class Organize_Controller extends Controller {
module::event("album_rearrange", $album);
print json_encode(
- array("grid" => self::_get_micro_thumb_grid($album, 0)->__toString(),
+ array("grid" => (string)self::_get_micro_thumb_grid($album, 0),
"sort_column" => $album->sort_column,
"sort_order" => $album->sort_order));
}
@@ -136,7 +136,7 @@ class Organize_Controller extends Controller {
$album->save();
print json_encode(
- array("grid" => self::_get_micro_thumb_grid($album, 0)->__toString(),
+ array("grid" => (string)self::_get_micro_thumb_grid($album, 0),
"sort_column" => $album->sort_column,
"sort_order" => $album->sort_order));
}
diff --git a/modules/recaptcha/controllers/admin_recaptcha.php b/modules/recaptcha/controllers/admin_recaptcha.php
index 6874fce9..0ddb98c1 100644
--- a/modules/recaptcha/controllers/admin_recaptcha.php
+++ b/modules/recaptcha/controllers/admin_recaptcha.php
@@ -42,7 +42,7 @@ class Admin_Recaptcha_Controller extends Admin_Controller {
} else {
module::set_var("recaptcha", "public_key", "");
module::set_var("recaptcha", "private_key", "");
- message::success(t("reCAPTCHA disabled!"));
+ message::success(t("No keys provided. reCAPTCHA is disabled!"));
log::success("recaptcha", t("reCAPTCHA public and private keys cleared"));
url::redirect("admin/recaptcha");
}
diff --git a/modules/recaptcha/helpers/recaptcha.php b/modules/recaptcha/helpers/recaptcha.php
index 789bae85..5df22cbc 100644
--- a/modules/recaptcha/helpers/recaptcha.php
+++ b/modules/recaptcha/helpers/recaptcha.php
@@ -24,12 +24,16 @@ class recaptcha_Core {
->label(t("Configure reCAPTCHA"));
$group->input("public_key")
->label(t("Public Key"))
- ->value(module::get_var("recaptcha", "public_key"));
- $group->public_key->error_messages("invalid", t("The public key you provided is invalid."));
+ ->value(module::get_var("recaptcha", "public_key"))
+ ->rules("required")
+ ->error_messages("required", t("You must enter a public key"))
+ ->error_messages("invalid", t("This public key is invalid"));
$group->input("private_key")
->label(t("Private Key"))
- ->value(module::get_var("recaptcha", "private_key"));
- $group->private_key->error_messages("invalid", t("The private key you provided is invalid."));
+ ->value(module::get_var("recaptcha", "private_key"))
+ ->callback("recaptcha::verify_key")
+ ->error_messages("required", t("You must enter a private key"))
+ ->error_messages("invalid", t("This private key is invalid"));
$group->submit("")->value(t("Save"));
$site_domain = urlencode(stripslashes($_SERVER["HTTP_HOST"]));
@@ -55,19 +59,23 @@ class recaptcha_Core {
* @param string $private_key
* @return boolean
*/
- static function verify_key($private_key) {
+ static function verify_key($private_key_input) {
+ if (!$private_key_input->value) {
+ $private_key_input->add_error("required", 1);
+ return;
+ }
+
$remote_ip = Input::instance()->server("REMOTE_ADDR");
$response = self::_http_post("api-verify.recaptcha.net", "/verify",
- array("privatekey" => $private_key,
+ array("privatekey" => $private_key_input->value,
"remoteip" => $remote_ip,
"challenge" => "right",
"response" => "wrong"));
- $answers = explode("\n", $response[1]);
- if (trim($answers[0]) == "true") {
- return null;
- } else {
- return $answers[1];
+ if ($response[1] == "false\ninvalid-site-private-key") {
+ // This is the only thing I can figure out how to verify.
+ // See http://recaptcha.net/apidocs/captcha for possible return values
+ $private_key_input->add_error("invalid", 1);
}
}
@@ -80,16 +88,16 @@ class recaptcha_Core {
$input = Input::instance();
$remote_ip = $input->server("REMOTE_ADDR");
- //discard spam submissions
+ // discard spam submissions
if (empty($challenge) || empty($response)) {
return "incorrect-captcha-sol";
}
$response = self::_http_post("api-verify.recaptcha.net", "/verify",
- array ("privatekey" => $private_key,
- "remoteip" => $remote_ip,
- "challenge" => $challenge,
- "response" => $response));
+ array("privatekey" => $private_key,
+ "remoteip" => $remote_ip,
+ "challenge" => $challenge,
+ "response" => $response));
$answers = explode ("\n", $response [1]);
if (trim ($answers [0]) == "true") {
diff --git a/modules/rest/controllers/rest.php b/modules/rest/controllers/rest.php
index 26e5b31a..374ae0d2 100644
--- a/modules/rest/controllers/rest.php
+++ b/modules/rest/controllers/rest.php
@@ -18,51 +18,62 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class Rest_Controller extends Controller {
- public function access_key() {
- try {
- $request = (object)Input::instance()->get();
- if (empty($request->user) || empty($request->password)) {
- throw new Rest_Exception(403, "Forbidden");
- }
+ public function index() {
+ $username = Input::instance()->post("user");
+ $password = Input::instance()->post("password");
- $user = identity::lookup_user_by_name($request->user);
- if (empty($user)) {
- throw new Rest_Exception(403, "Forbidden");
- }
-
- if (!identity::is_correct_password($user, $request->password)) {
- throw new Rest_Exception(403, "Forbidden");
- }
+ if (empty($username) || auth::too_many_failed_logins($username)) {
+ throw new Rest_Exception("Forbidden", 403);
+ }
- $key = ORM::factory("user_access_token")
- ->where("user_id", "=", $user->id)
- ->find();
- if (!$key->loaded()) {
- $key->user_id = $user->id;
- $key->access_key = md5($user->name . rand());
- $key->save();
- }
- print rest::success(array("token" => $key->access_key));
- } catch (Rest_Exception $e) {
- $e->sendHeaders();
+ $user = identity::lookup_user_by_name($username);
+ if (empty($user) || !identity::is_correct_password($user, $password)) {
+ module::event("user_login_failed", $username);
+ throw new Rest_Exception("Forbidden", 403);
}
+
+ auth::login($user);
+
+ $key = rest::get_access_token($user->id);
+ rest::reply($key->access_key);
}
public function __call($function, $args) {
- $request = rest::normalize_request($args);
- try {
- if (rest::set_active_user($request->access_token)) {
- $handler_class = "{$function}_rest";
- $handler_method = $request->method;
+ $input = Input::instance();
+ $request = new stdClass();
+ switch ($method = strtolower($input->server("REQUEST_METHOD"))) {
+ case "get":
+ $request->params = (object) $input->get();
+ break;
+
+ case "post":
+ $request->params = (object) $input->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);
- if (!method_exists($handler_class, $handler_method)) {
- throw new Rest_Exception(403, "Forbidden");
- }
+ rest::set_active_user($request->access_token);
- print call_user_func(array($handler_class, $handler_method), $request);
+ $handler_class = "{$function}_rest";
+ $handler_method = $request->method;
+
+ if (!method_exists($handler_class, $handler_method)) {
+ throw new Rest_Exception("Bad Request", 400);
+ }
+
+ try {
+ print rest::reply(call_user_func(array($handler_class, $handler_method), $request));
+ } catch (ORM_Validation_Exception $e) {
+ foreach ($e->validation->errors() as $key => $value) {
+ $msgs[] = "$key: $value";
}
- } catch (Rest_Exception $e) {
- $e->sendHeaders();
+ throw new Rest_Exception("Bad Request: " . join(", ", $msgs), 400);
}
}
} \ No newline at end of file
diff --git a/modules/rest/helpers/rest.php b/modules/rest/helpers/rest.php
index be0644f2..a61aba2f 100644
--- a/modules/rest/helpers/rest.php
+++ b/modules/rest/helpers/rest.php
@@ -18,87 +18,123 @@
* 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);
+ static function reply($data=array()) {
+ Session::instance()->abort_save();
+
+ if ($data) {
+ if (Input::instance()->get("output") == "html") {
+ header("Content-type: text/html");
+ $html = preg_replace(
+ "#([\w]+?://[\w]+[^ \'\"\n\r\t<]*)#ise", "'<a href=\"\\1\" >\\1</a>'",
+ var_export($data, 1));
+ print "<pre>$html</pre>";
+ } else {
+ header("Content-type: application/json");
+ print json_encode($data);
+ }
}
- // We don't need to save the session for this request
- 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;
+ static function set_active_user($access_token) {
+ if (empty($access_token)) {
+ identity::set_active_user(identity::guest());
+ return;
}
- $response = array_merge($response, $response_data);
- // We don't need to save the session for this request
- Session::abort_save();
- return json_encode($response);
+ $key = ORM::factory("user_access_token")
+ ->where("access_key", "=", $access_token)
+ ->find();
+
+ if (!$key->loaded()) {
+ throw new Rest_Exception("Forbidden", 403);
+ }
+
+ $user = identity::lookup_user($key->user_id);
+ if (empty($user)) {
+ throw new Rest_Exception("Forbidden", 403);
+ }
+
+ identity::set_active_user($user);
+ }
+
+ static function get_access_token($user_id) {
+ $key = ORM::factory("user_access_token")
+ ->where("user_id", "=", $user_id)
+ ->find();
+
+ if (!$key->loaded()) {
+ $key->user_id = $user_id;
+ $key->access_key = md5(md5(uniqid(mt_rand(), true) . access::private_key()));
+ $key->save();
+ }
+ return $key;
}
/**
- * Validation Error
+ * Convert a REST url into an object.
+ * Eg:
+ * http://example.com/gallery3/index.php/rest/item/35 -> Item_Model
+ * http://example.com/gallery3/index.php/rest/tag/16 -> Tag_Model
+ * http://example.com/gallery3/index.php/rest/tagged_item/1,16 -> [Tag_Model, Item_Model]
+ *
+ * @param string the fully qualified REST url
+ * @return mixed the corresponding object (usually a model of some kind)
*/
- static function validation_error($error_data) {
- $response = array("status" => "VALIDATE_ERROR");
- $response = array_merge($response, array("fields" => $error_data));
+ 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 (count($components) != 3) {
+ throw new Kohana_404_Exception($url);
+ }
+
+ $class = "$components[1]_rest";
+ if (!method_exists($class, "resolve")) {
+ throw new Kohana_404_Exception($url);
+ }
- // We don't need to save the session for this request
- Session::abort_save();
- return json_encode($response);
+ return call_user_func(array($class, "resolve"), !empty($components[2]) ? $components[2] : null);
}
+ /**
+ * Return an absolute url used for REST resource location.
+ * @param string resource type (eg, "item", "tag")
+ * @param object resource
+ */
+ static function url() {
+ $args = func_get_args();
+ $resource_type = array_shift($args);
- 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);
+ $class = "{$resource_type}_rest";
+ if (!method_exists($class, "url")) {
+ throw new Rest_Exception("Bad Request", 400);
}
- 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];
+
+ $url = call_user_func_array(array($class, "url"), $args);
+ if (Input::instance()->get("output") == "html") {
+ if (strpos($url, "?") === false) {
+ $url .= "?output=html";
+ } else {
+ $url .= "&output=html";
}
}
-
- $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
-
- return $request;
+ return $url;
}
- 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();
-
- if ($key->loaded()) {
- $user = identity::lookup_user($key->user_id);
- if (empty($user)) {
- throw new Rest_Exception(403, "Forbidden");
+ static function relationships($resource_type, $resource) {
+ $results = array();
+ foreach (module::active() as $module) {
+ foreach (glob(MODPATH . "{$module->name}/helpers/*_rest.php") as $filename) {
+ $class = str_replace(".php", "", basename($filename));
+ if (method_exists($class, "relationships")) {
+ $results = array_merge(
+ $results,
+ call_user_func(array($class, "relationships"), $resource_type, $resource));
}
- } else {
- throw new Rest_Exception(403, "Forbidden");
}
}
- identity::set_active_user($user);
- return true;
+
+ return $results;
}
}
diff --git a/modules/rest/libraries/Rest_Exception.php b/modules/rest/libraries/Rest_Exception.php
index 905b94a0..c3548b7e 100644
--- a/modules/rest/libraries/Rest_Exception.php
+++ b/modules/rest/libraries/Rest_Exception.php
@@ -17,20 +17,14 @@
* along with this program; if not, write to the Free Software
* 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");
+class Rest_Exception_Core extends Kohana_Exception {
+ public function __construct($message, $code) {
+ parent::__construct($message, null, $code);
}
- /**
- * Sends the headers, to emulate server behavior.
- *
- * @return void
- */
public function sendHeaders() {
- header('HTTP/1.1 {$this->getMessage()}');
+ if (!headers_sent()) {
+ header("HTTP/1.1 " . $this->getCode() . " " . $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..9f73bed9 100644
--- a/modules/rest/tests/Rest_Controller_Test.php
+++ b/modules/rest/tests/Rest_Controller_Test.php
@@ -17,208 +17,129 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Rest_Controller_Test extends Unit_Test_Case {
+class Rest_Controller_Test extends Gallery_Unit_Test_Case {
public function setup() {
$this->_save = array($_GET, $_POST, $_SERVER);
}
- private function _create_user() {
- if (empty($this->_user)) {
- $this->_user = identity::create_user("access_test" . rand(), "Access Test", "password");
- $this->_key = ORM::factory("user_access_token");
- $this->_key->access_key = md5($this->_user->name . rand());
- $this->_key->user_id = $this->_user->id;
- $this->_key->save();
- identity::set_active_user($this->_user);
- }
- return array($this->_key->access_key, $this->_user);
- }
-
public function teardown() {
list($_GET, $_POST, $_SERVER) = $this->_save;
- if (!empty($this->_user)) {
- try {
- $this->_user->delete();
- } catch (Exception $e) { }
- }
- }
-
- private function _create_image($parent=null) {
- $filename = MODPATH . "gallery/tests/test.jpg";
- $image_name = "image_" . rand();
- if (empty($parent)) {
- $parent = ORM::factory("item", 1);
- }
- return photo::create($parent, $filename, "$image_name.jpg", $image_name);
}
- public function rest_access_key_exists_test() {
- list ($access_key, $user) = $this->_create_user();
- $_SERVER["REQUEST_METHOD"] = "GET";
- $_GET["user"] = $user->name;;
- $_GET["password"] = "password";
+ public function login_test() {
+ $user = test::random_user("password");
- $this->assert_equal(
- json_encode(array("status" => "OK", "token" => $access_key)),
- $this->_call_controller());
- }
+ // There's no access key at first
+ $this->assert_false(
+ ORM::factory("user_access_token")->where("user_id", "=", $user->id)->find()->loaded());
- public function rest_access_key_generated_test() {
- list ($access_key, $user) = $this->_create_user();
- ORM::factory("user_access_token")
- ->where("access_key", $access_key)
- ->delete();
- $_SERVER["REQUEST_METHOD"] = "GET";
- $_GET["user"] = $user->name;
- $_GET["password"] = "password";
+ $_POST["user"] = $user->name;
+ $_POST["password"] = "password";
- $results = json_decode($this->_call_controller());
+ $response = test::call_and_capture(array(new Rest_Controller(), "index"));
+ $expected =
+ ORM::factory("user_access_token")->where("user_id", "=", $user->id)->find()->access_key;
- $this->assert_equal("OK", $results->status);
- $this->assert_false(empty($results->token));
+ // Now there is an access key, and it was returned
+ $this->assert_equal(json_encode($expected), $response);
}
- public function rest_access_key_no_parameters_test() {
- $_SERVER["REQUEST_METHOD"] = "GET";
+ public function login_failed_test() {
+ $user = test::random_user("password");
try {
- $this->_call_controller();
+ $_POST["user"] = $user->name;
+ $_POST["password"] = "WRONG PASSWORD";
+ test::call_and_capture(array(new Rest_Controller(), "index"));
} catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
+ $this->assert_equal(403, $e->getCode());
+ return;
}
- }
-
- public function rest_access_key_user_not_found_test() {
- $_SERVER["REQUEST_METHOD"] = "POST";
- $_POST["request"] = json_encode(array("user" => "access_test2", "password" => "password"));
- try {
- $this->_call_controller();
- } catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
- }
+ $this->assert_true(false, "Shouldn't get here");
}
- public function rest_access_key_invalid_password_test() {
- $_SERVER["REQUEST_METHOD"] = "POST";
+ public function get_test() {
+ $_SERVER["REQUEST_METHOD"] = "GET";
+ $_GET["key"] = "value";
- try {
- $this->_call_controller();
- } catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
- }
+ $this->assert_array_equal_to_json(
+ array("params" => array("key" => "value"),
+ "method" => "get",
+ "access_token" => null,
+ "url" => "http://./index.php/gallery_unit_test"),
+ test::call_and_capture(array(new Rest_Controller(), "mock")));
}
- public function rest_get_resource_no_request_key_test() {
- $_SERVER["REQUEST_METHOD"] = "GET";
- $photo = $this->_create_image();
-
- $this->assert_equal(
- json_encode(array("status" => "OK", "message" => (string)t("Processed"),
- "photo" => array("path" => $photo->relative_url(),
- "title" => $photo->title,
- "thumb_url" => $photo->thumb_url(),
- "description" => $photo->description,
- "internet_address" => $photo->slug))),
- $this->_call_controller("rest", explode("/", $photo->relative_url())));
- }
+ public function get_with_access_key_test() {
+ $key = rest::get_access_token(1); // admin user
- public function rest_get_resource_invalid_key_test() {
- list ($access_key, $user) = $this->_create_user();
- $_SERVER["HTTP_X_GALLERY_REQUEST_KEY"] = md5($access_key); // screw up the access key;
$_SERVER["REQUEST_METHOD"] = "GET";
+ $_SERVER["HTTP_X_GALLERY_REQUEST_KEY"] = $key->access_key;
+ $_GET["key"] = "value";
- try {
- $this->_call_controller();
- } catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
- }
+ $this->assert_array_equal_to_json(
+ array("params" => array("key" => "value"),
+ "method" => "get",
+ "access_token" => $key->access_key,
+ "url" => "http://./index.php/gallery_unit_test"),
+ test::call_and_capture(array(new Rest_Controller(), "mock")));
}
- public function rest_get_resource_no_user_for_key_test() {
- list ($access_key, $user) = $this->_create_user();
- $_SERVER["REQUEST_METHOD"] = "GET";
- $_SERVER["HTTP_X_GALLERY_REQUEST_KEY"] = $access_key;
+ public function post_test() {
+ $_SERVER["REQUEST_METHOD"] = "POST";
+ $_POST["key"] = "value";
- $user->delete();
+ $this->assert_array_equal_to_json(
+ array("params" => array("key" => "value"),
+ "method" => "post",
+ "access_token" => null,
+ "url" => "http://./index.php/gallery_unit_test"),
+ test::call_and_capture(array(new Rest_Controller(), "mock")));
+ }
- $photo = $this->_create_image();
+ public function put_test() {
+ $_SERVER["REQUEST_METHOD"] = "POST";
+ $_SERVER["HTTP_X_GALLERY_REQUEST_METHOD"] = "put";
+ $_POST["key"] = "value";
- try {
- $this->_call_controller("rest", explode("/", $photo->relative_url()));
- } catch (Rest_Exception $e) {
- $this->assert_equal("403 Forbidden", $e->getMessage());
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
- }
+ $this->assert_array_equal_to_json(
+ array("params" => array("key" => "value"),
+ "method" => "put",
+ "access_token" => null,
+ "url" => "http://./index.php/gallery_unit_test"),
+ test::call_and_capture(array(new Rest_Controller(), "mock")));
}
- public function rest_get_resource_no_handler_test() {
- list ($access_key, $user) = $this->_create_user();
- $_SERVER["REQUEST_METHOD"] = "GET";
- $_SERVER["HTTP_X_GALLERY_REQUEST_KEY"] = $access_key;
- $_SERVER["HTTP_X_GALLERY_REQUEST_METHOD"] = "PUT";
- $photo = $this->_create_image();
+ public function delete_test() {
+ $_SERVER["REQUEST_METHOD"] = "POST";
+ $_SERVER["HTTP_X_GALLERY_REQUEST_METHOD"] = "delete";
+ $_POST["key"] = "value";
+ $this->assert_array_equal_to_json(
+ array("params" => array("key" => "value"),
+ "method" => "delete",
+ "access_token" => null,
+ "url" => "http://./index.php/gallery_unit_test"),
+ test::call_and_capture(array(new Rest_Controller(), "mock")));
+ }
+
+ public function bogus_method_test() {
+ $_SERVER["REQUEST_METHOD"] = "POST";
+ $_SERVER["HTTP_X_GALLERY_REQUEST_METHOD"] = "BOGUS";
try {
- $this->_call_controller("rest", explode("/", $photo->relative_url()));
- } catch (Rest_Exception $e) {
- $this->assert_equal("501 Not Implemented", $e->getMessage());
+ test::call_and_capture(array(new Rest_Controller(), "mock"));
} catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
+ $this->assert_equal(400, $e->getCode());
+ return;
}
- }
-
- public function rest_get_resource_test() {
- list ($access_key, $user) = $this->_create_user();
- $_SERVER["REQUEST_METHOD"] = "GET";
- $_SERVER["HTTP_X_GALLERY_REQUEST_KEY"] = $access_key;
-
- $photo = $this->_create_image();
- $this->assert_equal(
- json_encode(array("status" => "OK", "message" => (string)t("Processed"),
- "photo" => array("path" => $photo->relative_url(),
- "title" => $photo->title,
- "thumb_url" => $photo->thumb_url(),
- "description" => $photo->description,
- "internet_address" => $photo->slug))),
- $this->_call_controller("rest", explode("/", $photo->relative_url())));
- }
-
- private function _call_controller($method="access_key", $arg=null) {
- $controller = new Rest_Controller();
-
- ob_start();
- call_user_func_array(array($controller, $method), $arg);
- $results = ob_get_contents();
- ob_end_clean();
-
- return $results;
+ $this->assert_true(false, "Shouldn't get here");
}
}
-class rest_rest {
- static $request = null;
-
- static function get($request) {
- self::$request = $request;
- $item = ORM::factory("item")
- ->where("relative_url_cache", "=", implode("/", $request->arguments))
- ->find();
- $response["path"] = $item->relative_url();
- $response["title"] = $item->title;
- $response["thumb_url"] = $item->thumb_url();
- $response["description"] = $item->description;
- $response["internet_address"] = $item->slug;
- return rest::success(array($item->type => $response), t("Processed"));
- }
-
-}
+class mock_rest {
+ static function get($request) { return $request; }
+ static function post($request) { return $request; }
+ static function put($request) { return $request; }
+ static function delete($request) { return $request; }
+} \ No newline at end of file
diff --git a/modules/rest/views/user_profile_rest.html.php b/modules/rest/views/user_profile_rest.html.php
index 3807817e..397afa89 100644
--- a/modules/rest/views/user_profile_rest.html.php
+++ b/modules/rest/views/user_profile_rest.html.php
@@ -2,7 +2,7 @@
<div id="g-rest-detail">
<ul>
<li id="g-rest-key">
- <p><b><?= t("Key") ?></b>:<?= $rest_key ?></p>
+ <p><b><?= t("Key") ?></b>:<?= html::clean($rest_key) ?></p>
</li>
</ul>
</div>
diff --git a/modules/search/helpers/search.php b/modules/search/helpers/search.php
index b2497eae..9018ffa2 100644
--- a/modules/search/helpers/search.php
+++ b/modules/search/helpers/search.php
@@ -65,7 +65,8 @@ class search_Core {
$record->item_id = $item->id;
}
- module::event("item_index_data", $record->item(), $data);
+ $item = $record->item();
+ module::event("item_index_data", $item, $data);
$record->data = join(" ", (array)$data);
$record->dirty = 0;
$record->save();
diff --git a/modules/server_add/controllers/server_add.php b/modules/server_add/controllers/server_add.php
index d7572b52..f68335df 100644
--- a/modules/server_add/controllers/server_add.php
+++ b/modules/server_add/controllers/server_add.php
@@ -42,7 +42,6 @@ class Server_Add_Controller extends Admin_Controller {
// Make a tree with the parents back up to the authorized path, and all the children under the
// current path.
- Kohana_Log::add("error", $path);
if (server_add::is_valid_path($path)) {
$tree->parents[] = $path;
while (server_add::is_valid_path(dirname($tree->parents[0]))) {
@@ -110,7 +109,7 @@ class Server_Add_Controller extends Admin_Controller {
}
$task = task::run($task_id);
- print json_encode(array("done" => $task->done,
+ print json_encode(array("done" => (bool)$task->done,
"status" => $task->status,
"percent_complete" => $task->percent_complete));
}
@@ -226,16 +225,36 @@ class Server_Add_Controller extends Admin_Controller {
$name = basename($entry->file);
$title = item::convert_filename_to_title($name);
if (is_dir($entry->file)) {
- $album = album::create($parent, $name, $title, null, $owner_id);
+ $album = ORM::factory("item");
+ $album->type = "album";
+ $album->parent_id = $parent->id;
+ $album->name = $name;
+ $album->title = $title;
+ $album->owner_id = $owner_id;
+ $album->save();
$entry->item_id = $album->id;
} else {
try {
$extension = strtolower(pathinfo($name, PATHINFO_EXTENSION));
if (in_array($extension, array("gif", "png", "jpg", "jpeg"))) {
- $photo = photo::create($parent, $entry->file, $name, $title, null, $owner_id);
+ $photo = ORM::factory("item");
+ $photo->type = "photo";
+ $photo->parent_id = $parent->id;
+ $photo->set_data_file($entry->file);
+ $photo->name = $name;
+ $photo->title = $title;
+ $photo->owner_id = $owner_id;
+ $photo->save();
$entry->item_id = $photo->id;
} else if (in_array($extension, array("flv", "mp4"))) {
- $movie = movie::create($parent, $entry->file, $name, $title, null, $owner_id);
+ $movie = ORM::factory("item");
+ $movie->type = "movie";
+ $movie->parent_id = $parent->id;
+ $movie->set_data_file($entry->file);
+ $movie->name = $name;
+ $movie->title = $title;
+ $movie->owner_id = $owner_id;
+ $movie->save();
$entry->item_id = $movie->id;
} else {
// This should never happen, because we don't add stuff to the list that we can't
diff --git a/modules/tag/controllers/admin_tags.php b/modules/tag/controllers/admin_tags.php
index e20b8ac8..9092ec68 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));
}
}
@@ -99,7 +97,8 @@ class Admin_Tags_Controller extends Admin_Controller {
message::success($message);
log::success("tags", $message);
- print json_encode(array("result" => "success"));
+ print json_encode(array("result" => "success",
+ "location" => url::site("admin/tags")));
} else {
print json_encode(array("result" => "error", "form" => $in_place_edit->render()));
}
diff --git a/modules/tag/controllers/tags.php b/modules/tag/controllers/tags.php
index 992c7411..1eede907 100644
--- a/modules/tag/controllers/tags.php
+++ b/modules/tag/controllers/tags.php
@@ -69,11 +69,9 @@ class Tags_Controller extends Controller {
print json_encode(
array("result" => "success",
- "cloud" => tag::cloud(30)->__toString()));
+ "cloud" => (string)tag::cloud(30)));
} 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/item_tags_rest.php b/modules/tag/helpers/item_tags_rest.php
new file mode 100644
index 00000000..43e2cef0
--- /dev/null
+++ b/modules/tag/helpers/item_tags_rest.php
@@ -0,0 +1,64 @@
+<?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 item_tags_rest_Core {
+ static function get($request) {
+ $item = rest::resolve($request->url);
+ $tags = array();
+ foreach (tag::item_tags($item) as $tag) {
+ $tags[] = rest::url("tag_item", $tag, $item);
+ }
+
+ return array(
+ "url" => $request->url,
+ "members" => $tags);
+ }
+
+ static function post($request) {
+ $tag = rest::resolve($request->params->tag);
+ $item = rest::resolve($request->params->item);
+ access::required("view", $item);
+
+ tag::add($item, $tag->name);
+ return array(
+ "url" => rest::url("tag_item", $tag, $item),
+ "members" => array(
+ rest::url("tag", $tag),
+ rest::url("item", $item)));
+ }
+
+ static function delete($request) {
+ list ($tag, $item) = rest::resolve($request->url);
+ $tag->remove($item);
+ $tag->save();
+ }
+
+ static function resolve($id) {
+ $item = ORM::factory("item", $id);
+ if (!access::can("view", $item)) {
+ throw new Kohana_404_Exception();
+ }
+
+ return $item;
+ }
+
+ static function url($item) {
+ return url::abs_site("rest/item_tags/{$item->id}");
+ }
+}
diff --git a/modules/tag/helpers/tag.php b/modules/tag/helpers/tag.php
index 8075afe4..a500be58 100644
--- a/modules/tag/helpers/tag.php
+++ b/modules/tag/helpers/tag.php
@@ -37,17 +37,11 @@ class tag_Core {
if (!$tag->loaded()) {
$tag->name = $tag_name;
$tag->count = 0;
- $tag->save();
}
- if (!$tag->has($item)) {
- if (!$tag->add($item, $tag)) {
- throw new Exception("@todo {$tag->name} WAS_NOT_ADDED_TO {$item->id}");
- }
- $tag->count++;
- $tag->save();
- }
- return $tag;
+ $tag->add($item);
+ $tag->count++;
+ return $tag->save();
}
/**
@@ -73,6 +67,9 @@ class tag_Core {
if ($tags) {
$cloud = new View("tag_cloud.html");
$cloud->max_count = $tags[0]->count;
+ if (!$cloud->max_count) {
+ return;
+ }
usort($tags, array("tag", "sort_by_name"));
$cloud->tags = $tags;
return $cloud;
@@ -88,16 +85,10 @@ class tag_Core {
* @return array
*/
static function item_tags($item) {
- $tags = array();
- foreach (db::build()
- ->select("name")
- ->from("tags")
- ->join("items_tags", "tags.id", "items_tags.tag_id", "left")
- ->where("items_tags.item_id", "=", $item->id)
- ->execute() as $row) {
- $tags[] = $row->name;
- }
- return $tags;
+ return ORM::factory("tag")
+ ->join("items_tags", "tags.id", "items_tags.tag_id", "left")
+ ->where("items_tags.item_id", "=", $item->id)
+ ->find_all();
}
static function get_add_form($item) {
diff --git a/modules/tag/helpers/tag_event.php b/modules/tag/helpers/tag_event.php
index 6ee8e708..403ccd52 100644
--- a/modules/tag/helpers/tag_event.php
+++ b/modules/tag/helpers/tag_event.php
@@ -71,9 +71,13 @@ class tag_event_Core {
$('form input[id=tags]').autocomplete(
'$url', {max: 30, multiple: true, multipleSeparator: ',', cacheLength: 1});
});");
- $tag_value = implode(", ", tag::item_tags($item));
+
+ $tag_names = array();
+ foreach (tag::item_tags($item) as $tag) {
+ $tag_names[] = $tag->name;
+ }
$form->edit_item->input("tags")->label(t("Tags (comma separated)"))
- ->value($tag_value);
+ ->value(implode(", ", $tag_names));
}
static function item_edit_form_completed($item, $form) {
@@ -95,7 +99,9 @@ class tag_event_Core {
}
static function item_index_data($item, $data) {
- $data[] = join(" ", tag::item_tags($item));
+ foreach (tag::item_tags($item) as $tag) {
+ $data[] = $tag->name;
+ }
}
static function add_photos_form($album, $form) {
diff --git a/modules/tag/helpers/tag_item_rest.php b/modules/tag/helpers/tag_item_rest.php
new file mode 100644
index 00000000..672cec53
--- /dev/null
+++ b/modules/tag/helpers/tag_item_rest.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 tag_item_rest_Core {
+ static function get($request) {
+ list ($tag, $item) = rest::resolve($request->url);
+ return array(
+ "url" => $request->url,
+ "members" => array(
+ "tag" => rest::url("tag", $tag),
+ "item" => rest::url("item", $item)));
+ }
+
+ static function delete($request) {
+ list ($tag, $item) = rest::resolve($request->url);
+ $tag->remove($item);
+ $tag->save();
+ }
+
+ static function resolve($tuple) {
+ list ($tag_id, $item_id) = split(",", $tuple);
+ $tag = ORM::factory("tag", $tag_id);
+ $item = ORM::factory("item", $item_id);
+ if (!$tag->loaded() || !$item->loaded() || !$tag->has($item) || !access::can("view", $item)) {
+ throw new Kohana_404_Exception();
+ }
+
+ return array($tag, $item);
+ }
+
+ static function url($tag, $item) {
+ return url::abs_site("rest/tag_item/{$tag->id},{$item->id}");
+ }
+}
diff --git a/modules/tag/helpers/tag_items_rest.php b/modules/tag/helpers/tag_items_rest.php
new file mode 100644
index 00000000..18973ebb
--- /dev/null
+++ b/modules/tag/helpers/tag_items_rest.php
@@ -0,0 +1,65 @@
+<?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 tag_items_rest_Core {
+ static function get($request) {
+ $tag = rest::resolve($request->url);
+ $items = array();
+ foreach ($tag->items() as $item) {
+ if (access::can("view", $item)) {
+ $items[] = rest::url("tag_item", $tag, $item);
+ }
+ }
+
+ return array(
+ "url" => $request->url,
+ "members" => $items);
+ }
+
+ static function post($request) {
+ $tag = rest::resolve($request->params->tag);
+ $item = rest::resolve($request->params->item);
+ access::required("view", $item);
+
+ if (!$tag->loaded()) {
+ throw new Kohana_404_Exception();
+ }
+
+ tag::add($item, $tag->name);
+ return array(
+ "url" => rest::url("tag_item", $tag, $item),
+ "members" => array(
+ "tag" => rest::url("tag", $tag),
+ "item" => rest::url("item", $item)));
+ }
+
+ static function delete($request) {
+ list ($tag, $item) = rest::resolve($request->url);
+ $tag->remove($item);
+ $tag->save();
+ }
+
+ static function resolve($id) {
+ return ORM::factory("tag", $id);
+ }
+
+ static function url($tag) {
+ return url::abs_site("rest/tag_items/{$tag->id}");
+ }
+}
diff --git a/modules/tag/helpers/tag_rest.php b/modules/tag/helpers/tag_rest.php
index cd1ca6c6..4879cf63 100644
--- a/modules/tag/helpers/tag_rest.php
+++ b/modules/tag/helpers/tag_rest.php
@@ -18,143 +18,74 @@
* 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);
+ $tag_items = array();
+ foreach ($tag->items() as $item) {
+ if (access::can("view", $item)) {
+ $tag_items[] = rest::url("tag_item", $tag, $item);
}
}
- return rest::success($resources);
+ return array(
+ "url" => $request->url,
+ "entity" => $tag->as_array(),
+ "relationships" => array(
+ "items" => array(
+ "url" => rest::url("tag_items", $tag),
+ "members" => $tag_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 array("url" => rest::url("tag_item", $tag, $item));
}
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);
+ if (isset($request->params->name)) {
+ $tag->name = $request->params->name;
+ $tag->save();
}
+ }
- $name = $request->arguments[0];
+ static function delete($request) {
+ $tag = rest::resolve($request->url);
+ $tag->delete();
+ }
- $tag = ORM::factory("tag")
- ->where("name", "=", $name)
- ->find();
- if (!$tag->loaded()) {
- throw new Kohana_404_Exception();
+ static function relationships($resource_type, $resource) {
+ switch ($resource_type) {
+ case "item":
+ $tags = array();
+ foreach (tag::item_tags($resource) as $tag) {
+ $tags[] = rest::url("tag_item", $tag, $resource);
+ }
+ return array(
+ "tags" => array(
+ "url" => rest::url("item_tags", $resource),
+ "members" => $tags));
}
-
- $tag->name = $request->new_name;
- $tag->save();
-
- return rest::success();
}
- 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();
+ static function resolve($id) {
+ $tag = ORM::factory("tag", $id);
+ if (!$tag->loaded()) {
+ throw new Kohana_404_Exception();
}
- foreach ($tag_list as $row) {
- $row->delete();
- };
-
- tag::compact();
- return rest::success();
+ return $tag;
}
- 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);
- }
-
- return $resources;
+ static function url($tag) {
+ return url::abs_site("rest/tag/{$tag->id}");
}
}
diff --git a/modules/tag/helpers/tag_rss.php b/modules/tag/helpers/tag_rss.php
index f09a4530..5d42caab 100644
--- a/modules/tag/helpers/tag_rss.php
+++ b/modules/tag/helpers/tag_rss.php
@@ -34,6 +34,8 @@ class tag_rss_Core {
if (!$tag->loaded()) {
throw new Kohana_404_Exception();
}
+
+ $feed = new stdClass();
$feed->children = $tag->items($limit, $offset, "photo");
$feed->max_pages = ceil($tag->count / $limit);
$feed->title = $tag->name;
diff --git a/modules/tag/helpers/tags_rest.php b/modules/tag/helpers/tags_rest.php
new file mode 100644
index 00000000..f28be7b5
--- /dev/null
+++ b/modules/tag/helpers/tags_rest.php
@@ -0,0 +1,60 @@
+<?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[] = rest::url("tag", $tag);
+ }
+ return array("url" => rest::url("tags"),
+ "members" => $tags);
+ }
+
+ static function post($request) {
+ // The user must have some edit permission somewhere to create a tag.
+ if (!identity::active_user()->admin) {
+ $query = db::build()->from("access_caches")->and_open();
+ foreach (identity::active_user()->groups() as $group) {
+ $query->or_where("edit_{$group->id}", "=", access::ALLOW);
+ }
+ $has_any_edit_perm = $query->close()->count_records();
+ if (!$has_any_edit_perm) {
+ access::forbidden();
+ }
+ }
+
+ if (empty($request->params->name)) {
+ throw new Rest_Exception("Bad Request", 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 array("url" => rest::url("tag", $tag));
+ }
+
+ static function url() {
+ return url::abs_site("rest/tags");
+ }
+}
diff --git a/modules/tag/models/tag.php b/modules/tag/models/tag.php
index 2b33c30d..38a8ed69 100644
--- a/modules/tag/models/tag.php
+++ b/modules/tag/models/tag.php
@@ -95,7 +95,7 @@ class Tag_Model extends ORM {
* Overload ORM::delete() to trigger an item_related_update event for all items that are
* related to this tag.
*/
- public function delete() {
+ public function delete($ignored_id=null) {
$related_item_ids = array();
foreach (db::build()
->select("item_id")
diff --git a/modules/tag/tests/Tag_Item_Rest_Helper_Test.php b/modules/tag/tests/Tag_Item_Rest_Helper_Test.php
new file mode 100644
index 00000000..cb368790
--- /dev/null
+++ b/modules/tag/tests/Tag_Item_Rest_Helper_Test.php
@@ -0,0 +1,70 @@
+<?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 Tag_Item_Rest_Helper_Test extends Gallery_Unit_Test_Case {
+ public function setup() {
+ try {
+ Database::instance()->query("TRUNCATE {tags}");
+ Database::instance()->query("TRUNCATE {items_tags}");
+ } catch (Exception $e) { }
+ }
+
+ public function get_test() {
+ $tag = tag::add(item::root(), "tag1")->reload();
+
+ $request = new stdClass();
+ $request->url = rest::url("tag_item", $tag, item::root());
+ $this->assert_equal_array(
+ array("url" => rest::url("tag_item", $tag, item::root()),
+ "members" => array(
+ "tag" => rest::url("tag", $tag),
+ "item" => rest::url("item", item::root()))),
+ tag_item_rest::get($request));
+ }
+
+ public function get_with_invalid_url_test() {
+ $request = new stdClass();
+ $request->url = "bogus";
+ try {
+ tag_item_rest::get($request);
+ } catch (Kohana_404_Exception $e) {
+ return; // pass
+ }
+ $this->assert_true(false, "Shouldn't get here");
+ }
+
+ public function delete_test() {
+ $tag = tag::add(item::root(), "tag1")->reload();
+
+ $request = new stdClass();
+ $request->url = rest::url("tag_item", $tag, item::root());
+ tag_item_rest::delete($request);
+
+ $this->assert_false($tag->reload()->has(item::root()));
+ }
+
+ public function resolve_test() {
+ $album = test::random_album();
+ $tag = tag::add($album, "tag1")->reload();
+
+ $tuple = rest::resolve(rest::url("tag_item", $tag, $album));
+ $this->assert_equal_array($tag->as_array(), $tuple[0]->as_array());
+ $this->assert_equal_array($album->as_array(), $tuple[1]->as_array());
+ }
+}
diff --git a/modules/tag/tests/Tag_Rest_Helper_Test.php b/modules/tag/tests/Tag_Rest_Helper_Test.php
index 514538d4..838de975 100644
--- a/modules/tag/tests/Tag_Rest_Helper_Test.php
+++ b/modules/tag/tests/Tag_Rest_Helper_Test.php
@@ -17,272 +17,110 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Tag_Rest_Helper_Test extends Unit_Test_Case {
+class Tag_Rest_Helper_Test extends Gallery_Unit_Test_Case {
public function setup() {
try {
Database::instance()->query("TRUNCATE {tags}");
Database::instance()->query("TRUNCATE {items_tags}");
} catch (Exception $e) { }
- $this->_save = array($_GET, $_POST, $_SERVER, $_FILES);
- $this->_saved_active_user = identity::active_user();
}
- public function teardown() {
- list($_GET, $_POST, $_SERVER, $_FILES) = $this->_save;
- identity::set_active_user($this->_saved_active_user);
+ public function get_test() {
+ $tag = tag::add(item::root(), "tag1")->reload();
- try {
- if (!empty($this->_user)) {
- $this->_user->delete();
- }
- } catch (Exception $e) { }
- }
-
- private function _create_user() {
- if (empty($this->_user)) {
- $this->_user = identity::create_user("access_test" . rand(), "Access Test", "password");
- $key = ORM::factory("user_access_token");
- $key->access_key = md5($this->_user->name . rand());
- $key->user_id = $this->_user->id;
- $key->save();
- identity::set_active_user($this->_user);
- }
- return $this->_user;
- }
-
- private function _create_album($tags=array(), $parent=null) {
- $album_name = "tag_album_" . rand();
- if (empty($parent)) {
- $parent = ORM::factory("item", 1);
- }
- $album = album::create($parent, $album_name, $album_name, $album_name);
- foreach ($tags as $tag) {
- tag::add($album, $tag);
- }
- return $album;
+ $request = new stdClass();
+ $request->url = rest::url("tag", $tag);
+ $this->assert_equal_array(
+ array("url" => rest::url("tag", $tag),
+ "entity" => $tag->as_array(),
+ "relationships" => array(
+ "items" => array(
+ "url" => rest::url("tag_items", $tag),
+ "members" => array(
+ rest::url("tag_item", $tag, item::root()))))),
+ tag_rest::get($request));
}
- private function _create_image($tags=array(), $parent=null) {
- $filename = MODPATH . "gallery/tests/test.jpg";
- $image_name = "tag_image_" . rand();
- if (empty($parent)) {
- $parent = ORM::factory("item", 1);
- }
- $photo = photo::create($parent, $filename, "$image_name.jpg", $image_name);
- foreach ($tags as $tag) {
- tag::add($photo, $tag);
+ public function get_with_invalid_url_test() {
+ $request = new stdClass();
+ $request->url = "bogus";
+ try {
+ tag_rest::get($request);
+ } catch (Kohana_404_Exception $e) {
+ return; // pass
}
- return $photo;
- }
-
- public function tag_rest_get_all_test() {
- $album = $this->_create_album(array("albums", "A1", "T1"));
- $child = $this->_create_album(array("albums", "C1", "T1"), $album);
- $photo = $this->_create_image(array("photos", "P1", "T1"), $child);
- $sibling = $this->_create_image(array("photos", "P3"), $album);
-
- $request = (object)array("arguments" => array(), "limit" => 2, "offset" => 1);
-
- $this->assert_equal(
- json_encode(array("status" => "OK",
- "tags" => array(array("name" => "albums", "count" => "2"),
- array("name" => "photos", "count" => "2")))),
- tag_rest::get($request));
+ $this->assert_true(false, "Shouldn't get here");
}
- public function tag_rest_get_tags_for_item_test() {
- $photo = $this->_create_image(array("photos", "P1", "T1"));
-
- $request = (object)array("arguments" => explode("/", $photo->relative_url()));
+ public function get_with_no_relationships_test() {
+ $tag = test::random_tag();
- $this->assert_equal(
- json_encode(array("status" => "OK",
- "tags" => array("photos", "P1", "T1"))),
+ $request = new stdClass();
+ $request->url = rest::url("tag", $tag);
+ $this->assert_equal_array(
+ array("url" => rest::url("tag", $tag),
+ "entity" => $tag->as_array(),
+ "relationships" => array(
+ "items" => array(
+ "url" => rest::url("tag_items", $tag),
+ "members" => array()))),
tag_rest::get($request));
}
- public function tag_rest_get_items_test() {
- $album = $this->_create_album(array("albums", "A1", "T1"));
- $child = $this->_create_album(array("albums", "A1", "T1"), $album);
- $photo = $this->_create_image(array("photos", "P1", "T1"), $child);
- $sibling = $this->_create_image(array("photos", "P3"), $album);
- $child->reload();
- $album->reload();
+ public function post_test() {
+ $tag = test::random_tag();
- $request = (object)array("arguments" => array("albums"));
+ // Create an editable item to be tagged
+ $album = test::random_album();
+ access::allow(identity::everybody(), "edit", $album);
- $resources = array();
- foreach (array($album, $child) as $resource) {
- $resources[] = array("type" => $resource->type,
- "has_children" => $resource->children_count() > 0,
- "path" => $resource->relative_url(),
- "thumb_url" => $resource->thumb_url(),
- "thumb_dimensions" => array("width" => $resource->thumb_width,
- "height" => $resource->thumb_height),
- "has_thumb" => $resource->has_thumb(),
- "title" => $resource->title);
-
- }
- $this->assert_equal(json_encode(array("status" => "OK", "resources" => $resources)),
- tag_rest::get($request));
+ // Add the album to the tag
+ $request = new stdClass();
+ $request->url = rest::url("tag", $tag);
+ $request->params = new stdClass();
+ $request->params->url = rest::url("item", $album);
+ $this->assert_equal_array(
+ array("url" => rest::url("tag_item", $tag, $album)),
+ tag_rest::post($request));
}
- public function tag_rest_add_tags_for_item_no_path_test() {
- $request = (object)array("arguments" => array("new,one"));
-
+ public function post_with_no_item_url_test() {
+ $request = new stdClass();
try {
tag_rest::post($request);
} catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
- }
- }
-
- public function tag_rest_add_tags_for_item_not_found_test() {
- $photo = $this->_create_image(array("photos", "P1", "T1"));
- $request = (object)array("path" => $photo->relative_url() . "b",
- "arguments" => array("new,one"));
- try {
- tag_rest::post($request);
- } catch (Kohana_404_Exception $k404) {
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
- }
- }
-
- public function tag_rest_add_tags_for_item_no_access_test() {
- $photo = $this->_create_image(array("photos", "P1", "T1"));
- $this->_create_user();
- $request = (object)array("path" => $photo->relative_url(),
- "arguments" => array("new,one"));
-
- try {
- tag_rest::post($request);
- } catch (Kohana_404_Exception $k404) {
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
+ $this->assert_equal(400, $e->getCode());
+ return;
}
- }
-
- public function tag_rest_add_tags_for_item_test() {
- $album = $this->_create_album(array("albums", "A1", "T1"));
- $child = $this->_create_album(array("albums", "A1", "T1"), $album);
- $photo = $this->_create_image(array("photos", "P1", "T1"), $child);
- $sibling = $this->_create_image(array("photos", "P3"), $album);
- access::allow(identity::registered_users(), "edit", $child);
- $this->_create_user();
- $request = (object)array("path" => $photo->relative_url(),
- "arguments" => array("new,one"));
- $this->assert_equal(
- json_encode(array("status" => "OK")),
- tag_rest::post($request));
- $request = (object)array("arguments" => explode("/", $photo->relative_url()));
- $this->assert_equal(
- json_encode(array("status" => "OK",
- "tags" => array("photos", "P1", "T1", "new", "one"))),
- tag_rest::get($request));
+ $this->assert_true(false, "Shouldn't get here");
}
- public function tag_rest_update_tag_no_arguments_test() {
- $request = (object)array("arguments" => array());
+ public function put_test() {
+ $tag = test::random_tag();
+ $request = new stdClass();
+ $request->url = rest::url("tag", $tag);
+ $request->params = new stdClass();
+ $request->params->name = "new name";
- try {
- tag_rest::put($request);
- } catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
- }
- }
-
- public function tag_rest_update_tag_one_arguments_test() {
- $request = (object)array("arguments" => array("photos"));
- try {
- tag_rest::put($request);
- } catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
- }
-
- $request = (object)array("arguments" => array(), "new_name" => "valid");
- try {
- tag_rest::put($request);
- } catch (Rest_Exception $e) {
- $this->assert_equal("400 Bad request", $e->getMessage());
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
- }
+ tag_rest::put($request);
+ $this->assert_equal("new name", $tag->reload()->name);
}
- public function tag_rest_update_tags_not_found_test() {
- $request = (object)array("arguments" => array("not"), "new_name" => "found");
+ public function delete_tag_test() {
+ $tag = test::random_tag();
+ $request = new stdClass();
+ $request->url = rest::url("tag", $tag);
+ tag_rest::delete($request);
- try {
- tag_rest::put($request);
- } catch (Kohana_404_Exception $k404) {
- } catch (Exception $e) {
- $this->assert_false(true, $e->__toString());
- }
+ $this->assert_false($tag->reload()->loaded());
}
- public function tag_rest_update_tags_test() {
- $album = $this->_create_album(array("albums", "A1", "T1"));
- $child = $this->_create_album(array("albums", "A1", "T1"), $album);
- $photo = $this->_create_image(array("photos", "P1", "T1"), $child);
- $child->reload();
- $sibling = $this->_create_image(array("photos", "P3"), $album);
- $child->reload();
- $album->reload();
-
- $request = (object)array("arguments" => array("albums"), "new_name" => "new name");
+ public function resolve_test() {
+ $tag = test::random_tag();
- $this->assert_equal(json_encode(array("status" => "OK")), tag_rest::put($request));
-
- $request = (object)array("arguments" => array("new name"));
- $resources = array();
- foreach (array($album, $child) as $resource) {
- $resources[] = array("type" => $resource->type,
- "has_children" => $resource->children_count() > 0,
- "path" => $resource->relative_url(),
- "thumb_url" => $resource->thumb_url(),
- "thumb_dimensions" => array("width" => $resource->thumb_width,
- "height" => $resource->thumb_height),
- "has_thumb" => $resource->has_thumb(),
- "title" => $resource->title);
-
- }
$this->assert_equal(
- json_encode(array("status" => "OK", "resources" => $resources)),
- tag_rest::get($request));
- }
-
- public function tag_rest_delete_tag_test() {
- $album = $this->_create_album(array("albums", "A1", "T1"));
- $child = $this->_create_album(array("albums", "A1", "T1"), $album);
- $photo = $this->_create_image(array("photos", "P1", "T1"), $child);
-
- $request = (object)array("arguments" => array("T1,P1"));
- $this->assert_equal(json_encode(array("status" => "OK")), tag_rest::delete($request));
-
- $request = (object)array("arguments" => array("T1,P1"));
- $this->assert_equal(json_encode(array("status" => "OK")),
- tag_rest::get($request));
- }
-
- public function tag_rest_delete_tagc_from_item_test() {
- $album = $this->_create_album(array("albums", "A1", "T1"));
- $child = $this->_create_album(array("albums", "A1", "T1"), $album);
- $photo = $this->_create_image(array("photos", "P1", "T1"), $child);
- $request = (object)array("arguments" => array("T1,P1"),
- $photo->relative_url());
-
- $this->assert_equal(json_encode(array("status" => "OK")), tag_rest::delete($request));
-
- $request = (object)array("arguments" => explode("/", $photo->relative_url()));
- $this->assert_equal(json_encode(array("status" => "OK", "tags" => array("photos"))),
- tag_rest::get($request));
+ $tag->as_array(),
+ rest::resolve(rest::url("tag", $tag))->as_array());
}
}
diff --git a/modules/tag/tests/Tag_Test.php b/modules/tag/tests/Tag_Test.php
index c96e7f2b..defc4e89 100644
--- a/modules/tag/tests/Tag_Test.php
+++ b/modules/tag/tests/Tag_Test.php
@@ -17,26 +17,19 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Tag_Test extends Unit_Test_Case {
+class Tag_Test extends Gallery_Unit_Test_Case {
public function create_tag_test() {
- $rand = rand();
- $root = ORM::factory("item", 1);
- $album = album::create($root, $rand, $rand, $rand);
- $tag1 = "tag1";
+ $album = test::random_album();
- tag::add($album, $tag1);
- $tag = ORM::factory("tag")->where("name", "=", $tag1)->find();
+ tag::add($album, "tag1");
+ $tag = ORM::factory("tag")->where("name", "=", "tag1")->find();
$this->assert_true(1, $tag->count);
// Make sure adding the tag again doesn't increase the count
- tag::add($album, $tag1);
- $tag = ORM::factory("tag")->where("name", "=", $tag1)->find();
- $this->assert_true(1, $tag->count);
+ tag::add($album, "tag1");
+ $this->assert_true(1, $tag->reload()->count);
- $rand = rand();
- $album = album::create($root, $rand, $rand, $rand);
- tag::add($album, $tag1);
- $tag = ORM::factory("tag")->where("name", "=", $tag1)->find();
- $this->assert_true(2, $tag->count);
+ tag::add(test::random_album(), "tag1");
+ $this->assert_true(2, $tag->reload()->count);
}
} \ No newline at end of file
diff --git a/modules/tag/tests/Tags_Rest_Helper_Test.php b/modules/tag/tests/Tags_Rest_Helper_Test.php
new file mode 100644
index 00000000..cdf7bfdf
--- /dev/null
+++ b/modules/tag/tests/Tags_Rest_Helper_Test.php
@@ -0,0 +1,71 @@
+<?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_Helper_Test extends Gallery_Unit_Test_Case {
+ public function setup() {
+ try {
+ Database::instance()->query("TRUNCATE {tags}");
+ Database::instance()->query("TRUNCATE {items_tags}");
+ } catch (Exception $e) {
+ }
+ }
+
+ public function get_test() {
+ $t1 = tag::add(item::root(), "t1");
+ $t2 = tag::add(item::root(), "t2");
+
+ $request = new stdClass();
+ $this->assert_equal_array(
+ array(
+ "url" => rest::url("tags"),
+ "members" => array(
+ rest::url("tag", $t1),
+ rest::url("tag", $t2))),
+ tags_rest::get($request));
+ }
+
+ public function post_test() {
+ access::allow(identity::everybody(), "edit", item::root());
+
+ $request = new stdClass();
+ $request->params = new stdClass();
+ $request->params->name = "test tag";
+ $this->assert_equal(
+ array("url" => url::site("rest/tag/1")),
+ tags_rest::post($request));
+ }
+
+ public function post_fails_without_permissions_test() {
+ // We have to remove edit permissions from everywhere
+ Database::instance()->query("UPDATE {access_caches} SET edit_1=0");
+ identity::set_active_user(identity::guest());
+
+ try {
+ $request = new stdClass();
+ $request->params = new stdClass();
+ $request->params->name = "test tag";
+ tags_rest::post($request);
+ } catch (Exception $e) {
+ $this->assert_equal(403, $e->getCode());
+ return;
+ }
+ $this->assert_true(false, "Shouldnt get here");
+ }
+
+}
diff --git a/modules/user/controllers/admin_users.php b/modules/user/controllers/admin_users.php
index 96b86fff..03d9858b 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->add_user->url->value;
+ $user->locale = $form->add_user->locale->value;
+ $user->admin = $form->add_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,36 @@ 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->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 +182,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 +222,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 +249,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 +269,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 +289,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 +298,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 +308,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,31 +317,25 @@ 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"));
return $form;
}
- private function _add_locale_dropdown(&$form, $user=null) {
+ private static function _add_locale_dropdown(&$form, $user=null) {
$locales = locales::installed();
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 +353,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 +363,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..d0c67dd1 100644
--- a/modules/user/controllers/users.php
+++ b/modules/user/controllers/users.php
@@ -26,34 +26,43 @@ 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->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;
+
+ if ($user->locale != $form->edit_user->locale->value) {
+ $user->locale = $form->edit_user->locale->value;
+ $flush_locale_cookie = true;
+ }
+
+ $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 (isset($flush_locale_cookie)) {
+ // 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));
}
}
@@ -71,18 +80,18 @@ class Users_Controller extends Controller {
private function _get_edit_form($user) {
$form = new Forge("users/update/$user->id", "", "post", array("id" => "g-edit-user-form"));
$group = $form->group("edit_user")->label(t("Edit User: %name", array("name" => $user->name)));
- $group->input("full_name")->label(t("Full Name"))->id("g-fullname")->value($user->full_name);
+ $group->input("full_name")->label(t("Full Name"))->id("g-fullname")->value($user->full_name)
+ ->error_messages("length", t("Your name is too long"));
self::_add_locale_dropdown($group, $user);
- $group->password("password")->label(t("Password"))->id("g-password");
+ $group->password("password")->label(t("Password"))->id("g-password")
+ ->error_messages("min_length", t("Your password is too short"));
$group->password("password2")->label(t("Confirm Password"))->id("g-password2")
- ->matches($group->password);
- $group->input("email")->label(t("Email"))->id("g-email")->value($user->email);
+ ->matches($group->password)
+ ->error_messages("matches", t("The passwords you entered do not match"));
+ $group->input("email")->label(t("Email"))->id("g-email")->value($user->email)
+ ->error_messages("email", t("You must enter a valid email address"))
+ ->error_messages("required", t("You must enter a valid email address"));
$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 +104,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 38f8020b..729f087a 100644
--- a/modules/user/helpers/user_installer.php
+++ b/modules/user/helpers/user_installer.php
@@ -29,9 +29,21 @@ class user_installer {
static function upgrade($version) {
if ($version == 1) {
module::set_var("user", "mininum_password_length", 5);
-
module::set_version("user", $version = 2);
}
+
+ if ($version == 2) {
+ db::build()
+ ->update("users")
+ ->set("email", "unknown@unknown.com")
+ ->where("guest", "=", 0)
+ ->and_open()
+ ->where("email", "IS", null)
+ ->or_where("email", "=", "")
+ ->close()
+ ->execute();
+ module::set_version("user", $version = 3);
+ }
}
static function uninstall() {
@@ -85,20 +97,28 @@ 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 = ORM::factory("user");
+ $guest->name = "guest";
+ $guest->full_name = "Guest User";
+ $guest->password = "";
$guest->guest = true;
- $guest->remove($registered);
$guest->save();
- $admin = user::create("admin", "Gallery Administrator", "admin");
+ $admin = ORM::factory("user");
+ $admin->name = "admin";
+ $admin->full_name = "Gallery Administrator";
+ $admin->password = "admin";
+ $admin->email = "unknown@unknown.com";
$admin->admin = true;
$admin->save();
@@ -109,7 +129,7 @@ class user_installer {
access::allow($registered, "view", $root);
access::allow($registered, "view_full", $root);
- module::set_version("user", 2);
module::set_var("user", "mininum_password_length", 5);
+ module::set_version("user", 3);
}
} \ No newline at end of file
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..82843ad1 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(Validation $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 = ORM::factory("group", $this->id);
+ 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..baac9315 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,51 @@ 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(Validation $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]", "valid::email"),
+ "callbacks" => array(array($this, "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());
+ if (!$this->guest) {
+ $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 = ORM::factory("user", $this->id);
+ parent::save();
module::event("user_updated", $original, $this);
}
+
return $this;
}
@@ -88,4 +115,55 @@ 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->guest) {
+ return;
+ }
+
+ 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) {
+ $active = identity::active_user();
+ if ($this->id == $active->id && $active->admin && !$this->admin) {
+ $v->add_error("admin", "locked");
+ }
+ }
+
+ /**
+ * Validate the email field.
+ */
+ public function valid_email(Validation $v, $field) {
+ if ($this->guest) { // guests don't require an email address
+ return;
+ }
+
+ if (empty($this->email)) {
+ $v->add_error("email", "required");
+ }
+ }
}
diff --git a/modules/user/module.info b/modules/user/module.info
index d1e02382..185a3e3a 100644
--- a/modules/user/module.info
+++ b/modules/user/module.info
@@ -1,4 +1,4 @@
name = "Users and Groups"
description = "Gallery 3 user and group management"
-version = 2
+version = 3
diff --git a/modules/user/tests/No_Direct_ORM_Access_Test.php b/modules/user/tests/No_Direct_ORM_Access_Test.php
index 440321fa..c372258e 100644
--- a/modules/user/tests/No_Direct_ORM_Access_Test.php
+++ b/modules/user/tests/No_Direct_ORM_Access_Test.php
@@ -19,7 +19,7 @@
*/
require_once(MODPATH . "gallery/tests/Gallery_Filters.php");
-class No_Direct_ORM_Access_Test extends Unit_Test_Case {
+class No_Direct_ORM_Access_Test extends Gallery_Unit_Test_Case {
public function no_access_to_users_table_test() {
$dir = new UserModuleFilterIterator(
new PhpCodeFilterIterator(
diff --git a/modules/user/tests/User_Groups_Test.php b/modules/user/tests/User_Groups_Test.php
index 163b7d79..d0026d89 100644
--- a/modules/user/tests/User_Groups_Test.php
+++ b/modules/user/tests/User_Groups_Test.php
@@ -18,33 +18,10 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class User_Groups_Test extends Unit_Test_Case {
- public function teardown() {
- try {
- $group = ORM::factory("group")->where("name", "=", "user_groups_test")->find();
- if ($group->loaded()) {
- $group->delete();
- }
- } catch (Exception $e) { }
-
- try {
- $user = ORM::factory("user")->where("name", "=", "user_groups_test")->find();
- if ($user->loaded()) {
- $user->delete();
- }
- } catch (Exception $e) { }
- }
-
+class User_Groups_Test extends Gallery_Unit_Test_Case {
public function add_user_to_group_test() {
- $user = ORM::factory("user");
- $user->name = "user_groups_test";
- $user->full_name = "user groups test";
- $user->password = "test password";
- $user->save();
-
- $group = ORM::factory("group");
- $group->name = "user_groups_test";
- $group->save();
+ $user = test::random_user();
+ $group = test::random_group();
$group->add($user);
$group->save();
diff --git a/modules/user/tests/User_Installer_Test.php b/modules/user/tests/User_Installer_Test.php
index 12a10eda..b3c5960a 100644
--- a/modules/user/tests/User_Installer_Test.php
+++ b/modules/user/tests/User_Installer_Test.php
@@ -22,7 +22,7 @@
* This test case operates under the assumption that user_installer::install() is called by the
* test controller before it starts.
*/
-class User_Installer_Test extends Unit_Test_Case {
+class User_Installer_Test extends Gallery_Unit_Test_Case {
public function install_creates_admin_user_test() {
$user = ORM::factory("user", 1);
$this->assert_equal("guest", $user->name);
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));
}
}
diff --git a/modules/watermark/helpers/watermark_installer.php b/modules/watermark/helpers/watermark_installer.php
index b3e91044..e45ef746 100644
--- a/modules/watermark/helpers/watermark_installer.php
+++ b/modules/watermark/helpers/watermark_installer.php
@@ -33,7 +33,7 @@ class watermark_installer {
DEFAULT CHARSET=utf8;");
@mkdir(VARPATH . "modules/watermark");
- module::set_version("watermark", 1);
+ module::set_version("watermark", 2);
}
static function uninstall() {