diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..dbf1b472
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.DS_Store
+tmp
+*~
+*.swp
diff --git a/client/Gallery3.php b/client/Gallery3.php
index 991e85de..d1135ae9 100644
--- a/client/Gallery3.php
+++ b/client/Gallery3.php
@@ -69,7 +69,7 @@ class Gallery3 {
}
/**
- * Set a value on the remote resource. You must call save for it to take effect.
+ * Set a value on the remote resource's entity. You must call save for it to take effect.
*
* @param string key
* @param string value
@@ -81,6 +81,18 @@ class Gallery3 {
return $this;
}
+ /**
+ * Replace the members for the remote resource
+ *
+ * @param array members
+ * @return object Gallery3
+ * @chainable
+ */
+ public function set_members($members) {
+ $this->data->members = $members;
+ return $this;
+ }
+
/**
* Attach a file to the remote resource.
*
@@ -99,8 +111,12 @@ class Gallery3 {
* @return object Gallery3
*/
public function create($url, $token) {
+ if (!is_string($url)) {
+ throw new Gallery3_Exception("Invalid url: " . var_export($url));
+ }
+
$response = Gallery3_Helper::request(
- "post", $url, $token, $this->data->entity, $this->file);
+ "post", $url, $token, array("entity" => $this->data->entity), $this->file);
$this->url = $response->url;
$this->token = $token;
return $this->load();
@@ -115,7 +131,8 @@ class Gallery3 {
public function save() {
$response = Gallery3_Helper::request(
"put", $this->url, $this->token,
- array_diff($this->original_entity, (array)$this->data->entity));
+ array("entity" => array_diff((array)$this->data->entity, $this->original_entity),
+ "members" => $this->data->members));
return $this->load();
}
@@ -140,7 +157,7 @@ class Gallery3 {
public function load() {
$response = Gallery3_Helper::request("get", $this->url, $this->token);
$this->data = $response;
- $this->original_entity = (array)$response->entity;
+ $this->original_entity = isset($response->entity) ? (array)$response->entity : null;
return $this;
}
}
@@ -154,7 +171,7 @@ class Gallery3_Helper {
$req->addHeader("X-Gallery-Request-Key", $token);
}
foreach ($params as $key => $value) {
- $req->addPostData($key, $value);
+ $req->addPostData($key, is_string($value) ? $value : json_encode($value));
}
if ($file) {
$req->addFile("file", $file, mime_content_type($file));
@@ -163,6 +180,7 @@ class Gallery3_Helper {
switch ($req->getResponseCode()) {
case 200:
+ case 201:
return json_decode($req->getResponseBody());
case 403:
diff --git a/client/example.php b/client/example.php
index 7a9c8a27..1c96cd1b 100644
--- a/client/example.php
+++ b/client/example.php
@@ -13,13 +13,13 @@ alert("Connect to $SITE_URL");
$auth = Gallery3::login($SITE_URL, $USER, $PASSWORD);
$root = Gallery3::factory("$SITE_URL/item/1", $auth);
$tags = Gallery3::factory("$SITE_URL/tags", $auth);
+$comments = Gallery3::factory("$SITE_URL/comments", $auth);
$tag = Gallery3::factory()
->set("name", "My Tag")
->create($tags->url, $auth);
alert("Created tag: {$tag->url}");
-
$album = Gallery3::factory()
->set("type", "album")
->set("name", "Sample Album")
@@ -34,16 +34,31 @@ $album
->save();
alert("New title: {$album->data->entity->title}");
-
-$photo = Gallery3::factory()
- ->set("type", "photo")
- ->set("name", "Sample Photo.png")
- ->set("title", "Sample Photo")
- ->set_file("gallery.png")
- ->create($album->url, $auth);
-alert("Uploaded photo: {$photo->url}");
+for ($i = 0; $i < 2; $i++) {
+ $photo = Gallery3::factory()
+ ->set("type", "photo")
+ ->set("name", "Sample Photo.png")
+ ->set("title", "Sample Photo")
+ ->set_file("gallery.png")
+ ->create($album->url, $auth);
+ alert("Uploaded photo: {$photo->url}");
+}
+$album->load();
alert("Album members: " . join(", ", $album->data->members) . "");
+$comment = Gallery3::factory()
+ ->set("item", $album->data->members[0])
+ ->set("type", "comment")
+ ->set("text", "This is a random comment-- whee!")
+ ->create($comments->url, $auth);
+alert("Comment: {$comment->url}");
+
+alert("Reorder the album");
+$album
+ ->set_members(array($album->data->members[1], $album->data->members[0]))
+ ->set("sort_column", "weight")
+ ->save();
+alert("New order: " . join(", ", $album->data->members) . "");
alert("Search for the photo");
$photos = Gallery3::factory($root->url, $auth)
@@ -86,7 +101,7 @@ $tag->delete();
alert("Done!");
function alert($msg) {
- print "$msg
";
+ print "$msg
\n";
flush();
}
?>
\ No newline at end of file
diff --git a/modules/basket/controllers/admin_postage_bands.php b/modules/basket/controllers/admin_postage_bands.php
index 977128e3..d1b9dc97 100644
--- a/modules/basket/controllers/admin_postage_bands.php
+++ b/modules/basket/controllers/admin_postage_bands.php
@@ -60,9 +60,9 @@ class Admin_Postage_Bands_Controller extends Controller
$postage_band->save();
message::success(t("Created postage band %postage_name", array(
"postage_name" => html::clean($postage_band->name))));
- print json_encode(array("result" => "success"));
+ json::reply(array("result" => "success"));
} else {
- print json_encode(array("result" => "error", "form" => (string)$form));
+ json::reply(array("result" => "error", "html" => (string)$form));
}
}
@@ -91,13 +91,13 @@ class Admin_Postage_Bands_Controller extends Controller
$name = $postage->name;
$postage->delete();
} else {
- print json_encode(array("result" => "error", "form" => (string)$form));
+ json::reply(array("result" => "error", "html" => (string)$form));
}
$message = t("Deleted user %postage_band", array("postage_band" => html::clean($name)));
log::success("user", $message);
message::success($message);
- print json_encode(array("result" => "success"));
+ json::reply(array("result" => "success"));
}
public function edit_postage_band($id) {
@@ -127,9 +127,9 @@ class Admin_Postage_Bands_Controller extends Controller
$postage->save();
message::success(t("Changed postage band %postage_name",
array("postage_name" => html::clean($postage->name))));
- print json_encode(array("result" => "success"));
+ json::reply(array("result" => "success"));
} else {
- print json_encode(array("result" => "error", "form" => (string)$form));
+ json::reply(array("result" => "error", "html" => (string)$form));
}
}
diff --git a/modules/basket/controllers/admin_product_lines.php b/modules/basket/controllers/admin_product_lines.php
index fd11928e..bc01c19b 100644
--- a/modules/basket/controllers/admin_product_lines.php
+++ b/modules/basket/controllers/admin_product_lines.php
@@ -60,9 +60,9 @@ class Admin_Product_Lines_Controller extends Controller
$product->save();
message::success(t("Created product %product_name", array(
"product_name" => html::clean($product->name))));
- print json_encode(array("result" => "success"));
+ json::reply(array("result" => "success"));
} else {
- print json_encode(array("result" => "error", "form" => (string)$form));
+ json::reply(array("result" => "error", "html" => (string)$form));
}
}
@@ -91,14 +91,13 @@ class Admin_Product_Lines_Controller extends Controller
$name = $product->name;
$product->delete();
} else {
- print json_encode(array("result" => "error",
- "form" => $form->__toString()));
+ json::reply(array("result" => "error", "html" => (string)$form));
}
$message = t("Deleted user %product_name", array("product_name" => html::clean($name)));
log::success("user", $message);
message::success($message);
- print json_encode(array("result" => "success"));
+ json::reply(array("result" => "success"));
}
public function edit_product($id) {
@@ -129,9 +128,9 @@ class Admin_Product_Lines_Controller extends Controller
$product->save();
message::success(t("Changed product %product_name",
array("product_name" => html::clean($product->name))));
- print json_encode(array("result" => "success"));
+ json::reply(array("result" => "success"));
} else {
- print json_encode(array("result" => "error", "form" => (string)$form));
+ json::reply(array("result" => "error", "html" => (string)$form));
}
}
diff --git a/modules/basket/controllers/basket.php b/modules/basket/controllers/basket.php
index 1620fcdc..612708c4 100644
--- a/modules/basket/controllers/basket.php
+++ b/modules/basket/controllers/basket.php
@@ -189,7 +189,7 @@ Items Ordered:
$form->add_to_basket->product->value,
$form->add_to_basket->quantity->value);
- print json_encode(array("result" => "success"));
+ json::reply(array("result" => "success"));
}
else
{
diff --git a/modules/calendarview/controllers/calendarview.php b/modules/calendarview/controllers/calendarview.php
index d975d040..d5d23943 100644
--- a/modules/calendarview/controllers/calendarview.php
+++ b/modules/calendarview/controllers/calendarview.php
@@ -265,7 +265,6 @@ class CalendarView_Controller extends Controller {
$str_year_id = Input::instance()->post("cal_year");
// redirect to the currect page.
- url::redirect(url::site("calendarview/calendar/" . $str_year_id . "/" . $str_user_id));
-
+ url::redirect(url::site("calendarview/calendar/" . $str_year_id . "/" . $str_user_id, request::protocol()));
}
}
\ No newline at end of file
diff --git a/modules/calendarview/css/calendarview_calendar.css b/modules/calendarview/css/calendarview_calendar.css
index e6d010e2..53807042 100644
--- a/modules/calendarview/css/calendarview_calendar.css
+++ b/modules/calendarview/css/calendarview_calendar.css
@@ -37,7 +37,6 @@ table.calendar caption {
table.calendar th, table.calendar td {
padding: 0.2em;
- background: #ffffff;
border: 0px;
}
diff --git a/modules/calendarview/helpers/calendarview_block.php b/modules/calendarview/helpers/calendarview_block.php
index 46a605d8..1037ecaa 100644
--- a/modules/calendarview/helpers/calendarview_block.php
+++ b/modules/calendarview/helpers/calendarview_block.php
@@ -38,14 +38,32 @@ class calendarview_block_Core {
$display_date = $item->created;
}
+ // Make sure there are photo's to display.
+ $day_count = ORM::factory("item")
+ ->viewable()
+ ->where("type", "!=", "album")
+ ->where("captured", ">=", mktime(0, 0, 0, date("n", $display_date), date("j", $display_date), date("Y", $display_date)))
+ ->where("captured", "<", mktime(0, 0, 0, date("n", $display_date), date("j", $display_date)+1, date("Y", $display_date)))
+ ->find_all()
+ ->count();
+ $month_count = ORM::factory("item")
+ ->viewable()
+ ->where("type", "!=", "album")
+ ->where("captured", ">=", mktime(0, 0, 0, date("n", $display_date), 1, date("Y", $display_date)))
+ ->where("captured", "<", mktime(0, 0, 0, date("n", $display_date)+1, 1, date("Y", $display_date)))
+ ->find_all()
+ ->count();
+
switch ($block_id) {
case "calendarview_photo":
- if ($display_date != "") {
+ if ( ($display_date != "") && (($day_count > 0) || ($month_count > 0)) ) {
$block = new Block();
$block->css_id = "g-calendarview-sidebar";
$block->title = t("Calendar");
$block->content = new View("calendarview_sidebar.html");
$block->content->date = $display_date;
+ $block->content->day_count = $day_count;
+ $block->content->month_count = $month_count;
}
break;
}
diff --git a/modules/calendarview/views/calendarview_sidebar.html.php b/modules/calendarview/views/calendarview_sidebar.html.php
index c5a8b3f5..b4f1f6fe 100644
--- a/modules/calendarview/views/calendarview_sidebar.html.php
+++ b/modules/calendarview/views/calendarview_sidebar.html.php
@@ -1,5 +1,9 @@
\ No newline at end of file
diff --git a/themes/okat_dark/controllers/three_nids.php b/modules/database_info/helpers/database_info_block.php
similarity index 65%
rename from themes/okat_dark/controllers/three_nids.php
rename to modules/database_info/helpers/database_info_block.php
index 042f9b3d..3607b19d 100644
--- a/themes/okat_dark/controllers/three_nids.php
+++ b/modules/database_info/helpers/database_info_block.php
@@ -17,20 +17,20 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Three_Nids_Controller extends Controller {
- public function show_comments($id) {
- $item = ORM::factory("item", $id);
- access::required("view", $item);
+class database_info_block_Core {
+ static function get_admin_list() {
+ return array("database_info" => t("Database info"));
+ }
- $comments = ORM::factory("comment")
- ->where("item_id", "=", $item->id)
- ->where("state", "=", "published")
- ->order_by("created", "ASC")
- ->find_all();
-
- $v = new Theme_View("comments.html", "other", "comment-fragment");
- $v->comments = $comments;
- $v->item = $item;
- print $v;
+ static function get($block_id) {
+ $block = new Block();
+ switch ($block_id) {
+ case "database_info":
+ $block->css_id = "g-database-info";
+ $block->title = t("Database information");
+ $block->content = new View("admin_block_db.html");
+ break;
+ }
+ return $block;
}
}
diff --git a/modules/database_info/module.info b/modules/database_info/module.info
new file mode 100644
index 00000000..cdf8479a
--- /dev/null
+++ b/modules/database_info/module.info
@@ -0,0 +1,3 @@
+name = "Database Info"
+description = "View information about your Gallery 3 database on the admin dashboard."
+version = 1
diff --git a/modules/database_info/views/admin_block_db.html.php b/modules/database_info/views/admin_block_db.html.php
new file mode 100644
index 00000000..cf13d535
--- /dev/null
+++ b/modules/database_info/views/admin_block_db.html.php
@@ -0,0 +1,18 @@
+
+
+ $db = Database::instance();
+ $tables = $db->query("SHOW TABLE STATUS");
+ $database_size = 0;
+ foreach($tables as $table) {
+ $database_size += ($table->Data_length + $table->Index_length);
+ }
+ $database_size = $database_size / 1024 / 1024;
+?>
+
+ -
+ = t("Database size: %dbsize MB", array("dbsize" => number_format($database_size, 2))) ?>
+
+ -
+ = t("Number of tables: %dbtables", array("dbtables" => count($tables))) ?>
+
+
diff --git a/modules/developer/controllers/admin_developer.php b/modules/developer/controllers/admin_developer.php
index c7061320..a7d334bd 100644
--- a/modules/developer/controllers/admin_developer.php
+++ b/modules/developer/controllers/admin_developer.php
@@ -68,16 +68,15 @@ class Admin_Developer_Controller extends Admin_Controller {
$task_context = array("step" => 0, "success_msg" => $success_msg, "error_msg" => $error_msg);
$task = task::create($task_def, array_merge($task_context, $post->as_array()));
- print json_encode(array("result" => "started",
- "max_iterations" => 15,
- "url" => url::site("admin/developer/run_task/{$task->id}?csrf=" .
- access::csrf_token()),
- "task" => $task->as_array()));
+ json::reply(array("result" => "started",
+ "max_iterations" => 15,
+ "url" => url::site("admin/developer/run_task/{$task->id}?csrf=" .
+ access::csrf_token()),
+ "task" => $task->as_array()));
} else {
$v = $this->_get_module_create_content(arr::overwrite($form, $post->as_array()),
arr::overwrite($errors, $post->errors()));
- print json_encode(array("result" => "error",
- "form" => $v->__toString()));
+ json::reply(array("result" => "error", "html" => (string)$v));
}
}
@@ -119,16 +118,15 @@ class Admin_Developer_Controller extends Admin_Controller {
"comments" => $post->comments, "tags" => $post->tags));
batch::start();
- print json_encode(array("result" => "started",
- "max_iterations" => $total + 5,
- "url" => url::site("admin/developer/run_task/{$task->id}?csrf=" .
- access::csrf_token()),
- "task" => $task->as_array()));
+ json::reply(array("result" => "started",
+ "max_iterations" => $total + 5,
+ "url" => url::site("admin/developer/run_task/{$task->id}?csrf=" .
+ access::csrf_token()),
+ "task" => $task->as_array()));
} else {
$v = $this->_get_test_data_view(arr::overwrite($form, $post->as_array()),
- arr::overwrite($errors, $post->errors()));
- print json_encode(array("result" => "error",
- "form" => $v->__toString()));
+ arr::overwrite($errors, $post->errors()));
+ json::reply(array("result" => "error", "html" => (string)$v));
}
}
@@ -152,12 +150,10 @@ class Admin_Developer_Controller extends Admin_Controller {
message::success(empty($error_msg) ? $context["error_msg"] : $error_msg);
break;
}
- print json_encode(array("result" => "success",
- "task" => $task->as_array()));
+ json::reply(array("result" => "success", "task" => $task->as_array()));
} else {
- print json_encode(array("result" => "in_progress",
- "task" => $task->as_array()));
+ json::reply(array("result" => "in_progress", "task" => $task->as_array()));
}
}
diff --git a/modules/developer/helpers/developer_task.php b/modules/developer/helpers/developer_task.php
index 0110127e..01abd04f 100644
--- a/modules/developer/helpers/developer_task.php
+++ b/modules/developer/helpers/developer_task.php
@@ -25,7 +25,6 @@ class developer_task_Core {
static function create_module($task) {
$context = unserialize($task->context);
- Kohana_Log::add("error", "task context:\n" . Kohana::debug($context));
if (empty($context["module"])) {
$context["class_name"] = strtr($context["name"], " ", "_");
diff --git a/modules/developer/views/controller.txt.php b/modules/developer/views/controller.txt.php
index cffefe4d..b73ae815 100644
--- a/modules/developer/views/controller.txt.php
+++ b/modules/developer/views/controller.txt.php
@@ -32,15 +32,12 @@ class = $class_name ?>_Controller extends Controller {
message::success(t("= $name ?> Processing Successfully"));
- print json_encode(
- array("result" => "success"));
+ json::reply(array("result" => "success"));
} else {
- print json_encode(
- array("result" => "error",
- "form" => $form->__toString()));
+ json::reply(array("result" => "error", "html" => (string)$form));
}
}
-
+
private function _get_form() {
$form = new Forge("= $module ?>/handler", "", "post",
array("id" => "g-= $css_id ?>-form"));
@@ -50,4 +47,4 @@ class = $class_name ?>_Controller extends Controller {
return $form;
}
-}
\ No newline at end of file
+}
diff --git a/modules/downloadalbum/controllers/downloadalbum.php b/modules/downloadalbum/controllers/downloadalbum.php
new file mode 100644
index 00000000..c2f939f7
--- /dev/null
+++ b/modules/downloadalbum/controllers/downloadalbum.php
@@ -0,0 +1,272 @@
+init($id);
+ $files = $this->getFilesList($album);
+
+ // Calculate ZIP size (look behind for details)
+ $zipsize = 22;
+ foreach($files as $f) {
+ $zipsize += 76 + 2*strlen($f) + filesize($f);
+ }
+
+ // Send headers
+ $this->prepareOutput();
+ $this->sendHeaders($album->name.'.zip', $zipsize);
+
+ // Generate and send ZIP file
+ // http://www.pkware.com/documents/casestudies/APPNOTE.TXT (v6.3.2)
+ $lfh_offset = 0;
+ $cds = '';
+ $cds_offset = 0;
+ foreach($files as $f) {
+ $f_namelen = strlen($f);
+ $f_size = filesize($f);
+ $f_mtime = $this->unix2dostime(filemtime($f));
+ $f_crc32 = $this->fixBug45028(hexdec(hash_file('crc32b', $f, false)));
+
+ // Local file header
+ echo pack('VvvvVVVVvva' . $f_namelen,
+ 0x04034b50, // local file header signature (4 bytes)
+ 0x0a, // version needed to extract (2 bytes) => 1.0
+ 0x0800, // general purpose bit flag (2 bytes) => UTF-8
+ 0x00, // compression method (2 bytes) => store
+ $f_mtime, // last mod file time and date (4 bytes)
+ $f_crc32, // crc-32 (4 bytes)
+ $f_size, // compressed size (4 bytes)
+ $f_size, // uncompressed size (4 bytes)
+ $f_namelen, // file name length (2 bytes)
+ 0, // extra field length (2 bytes)
+
+ $f // file name (variable size)
+ // extra field (variable size) => n/a
+ );
+
+ // File data
+ readfile($f);
+
+ // Data descriptor (n/a)
+
+ // Central directory structure: File header
+ $cds .= pack('VvvvvVVVVvvvvvVVa' . $f_namelen,
+ 0x02014b50, // central file header signature (4 bytes)
+ 0x031e, // version made by (2 bytes) => v3 / Unix
+ 0x0a, // version needed to extract (2 bytes) => 1.0
+ 0x0800, // general purpose bit flag (2 bytes) => UTF-8
+ 0x00, // compression method (2 bytes) => store
+ $f_mtime, // last mod file time and date (4 bytes)
+ $f_crc32, // crc-32 (4 bytes)
+ $f_size, // compressed size (4 bytes)
+ $f_size, // uncompressed size (4 bytes)
+ $f_namelen, // file name length (2 bytes)
+ 0, // extra field length (2 bytes)
+ 0, // file comment length (2 bytes)
+ 0, // disk number start (2 bytes)
+ 0, // internal file attributes (2 bytes)
+ 0x81b40000, // external file attributes (4 bytes) => chmod 664
+ $lfh_offset, // relative offset of local header (4 bytes)
+
+ $f // file name (variable size)
+ // extra field (variable size) => n/a
+ // file comment (variable size) => n/a
+ );
+
+ // Update local file header/central directory structure offset
+ $cds_offset = $lfh_offset += 30 + $f_namelen + $f_size;
+ }
+
+ // Archive decryption header (n/a)
+ // Archive extra data record (n/a)
+
+ // Central directory structure: Digital signature (n/a)
+ echo $cds; // send Central directory structure
+
+ // Zip64 end of central directory record (n/a)
+ // Zip64 end of central directory locator (n/a)
+
+ // End of central directory record
+ $numfile = count($files);
+ $cds_len = strlen($cds);
+ echo pack('VvvvvVVv',
+ 0x06054b50, // end of central dir signature (4 bytes)
+ 0, // number of this disk (2 bytes)
+ 0, // number of the disk with the start of
+ // the central directory (2 bytes)
+ $numfile, // total number of entries in the
+ // central directory on this disk (2 bytes)
+ $numfile, // total number of entries in the
+ // central directory (2 bytes)
+ $cds_len, // size of the central directory (4 bytes)
+ $cds_offset, // offset of start of central directory
+ // with respect to the
+ // starting disk number (4 bytes)
+ 0 // .ZIP file comment length (2 bytes)
+ // .ZIP file comment (variable size)
+ );
+ }
+
+
+ /**
+ * Init
+ */
+ private function init($id) {
+ $item = ORM::factory("item", $id);
+
+ // Only send an album
+ if (!$item->is_album()) {
+ // @todo: throw an exception?
+ Kohana::log('error', 'item is not an album: '.$item->relative_path());
+ exit;
+ }
+
+ // Must have view_full to download the originals files
+ access::required("view_full", $item);
+
+ return $item;
+ }
+
+ /**
+ * Return the files that must be included in the archive.
+ */
+ private function getFilesList($album) {
+ $files = array();
+
+ // Go to the parent of album so the ZIP will not contains all the
+ // server hierarchy
+ if (!chdir($album->file_path().'/../')) {
+ // @todo: throw an exception?
+ Kohana::log('error', 'unable to chdir('.$item->file_path().'/../)');
+ exit;
+ }
+ $cwd = getcwd();
+
+ $items = $album->viewable()
+ ->descendants(null, null, array(array("type", "<>", "album")));
+ foreach($items as $i) {
+ if (!access::can('view_full', $i)) {
+ continue;
+ }
+
+ $relative_path = str_replace($cwd.'/', '', realpath($i->file_path()));
+ if (!is_readable($relative_path)) {
+ continue;
+ }
+
+ $files[] = $relative_path;
+ }
+
+ if (count($files) === 0) {
+ // @todo: throw an exception?
+ Kohana::log('error', 'no zippable files in ['.$album->relative_path().']');
+ exit;
+ }
+
+ return $files;
+ }
+
+
+ /**
+ * See system/helpers/download.php
+ */
+ private function prepareOutput() {
+ // Close output buffers
+ Kohana::close_buffers(FALSE);
+ // Clear any output
+ Event::add('system.display', create_function('', 'Kohana::$output = "";'));
+ }
+
+ /**
+ * See system/helpers/download.php
+ */
+ private function sendHeaders($filename, $filesize = null) {
+ if (!is_null($filesize)) {
+ header('Content-Length: '.$filesize);
+ }
+
+ // Retrieve MIME type by extension
+ $mime = Kohana::config('mimes.'.strtolower(substr(strrchr($filename, '.'), 1)));
+ $mime = empty($mime) ? 'application/octet-stream' : $mime[0];
+ header("Content-Type: $mime");
+ header('Content-Transfer-Encoding: binary');
+
+ // Send headers necessary to invoke a "Save As" dialog
+ header('Content-Disposition: attachment; filename="'.$filename.'"');
+
+ // Prevent caching
+ header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
+
+ $pragma = 'no-cache';
+ $cachecontrol = 'no-cache, max-age=0';
+
+ // request::user_agent('browser') seems bugged
+ if (request::user_agent('browser') === 'Internet Explorer'
+ || stripos(request::user_agent(), 'msie') !== false
+ || stripos(request::user_agent(), 'internet explorer') !== false)
+ {
+ if (request::protocol() === 'https') {
+ // See http://support.microsoft.com/kb/323308/en-us
+ $pragma = 'cache';
+ $cachecontrol = 'private';
+
+ } else if (request::user_agent('version') <= '6.0') {
+ $pragma = '';
+ $cachecontrol = 'must-revalidate, post-check=0, pre-check=0';
+ }
+ }
+
+ header('Pragma: '.$pragma);
+ header('Cache-Control: '.$cachecontrol);
+ }
+
+ /**
+ * @return integer DOS date and time
+ * @param integer _timestamp Unix timestamp
+ * @desc returns DOS date and time of the timestamp
+ */
+ private function unix2dostime($timestamp)
+ {
+ $timebit = getdate($timestamp);
+
+ if ($timebit['year'] < 1980) {
+ return (1 << 21 | 1 << 16);
+ }
+
+ $timebit['year'] -= 1980;
+
+ return ($timebit['year'] << 25 | $timebit['mon'] << 21 |
+ $timebit['mday'] << 16 | $timebit['hours'] << 11 |
+ $timebit['minutes'] << 5 | $timebit['seconds'] >> 1);
+ }
+
+ /**
+ * See http://bugs.php.net/bug.php?id=45028
+ */
+ private function fixBug45028($hash) {
+ return (version_compare(PHP_VERSION, '5.2.7', '<'))
+ ? (($hash & 0x000000ff) << 24) + (($hash & 0x0000ff00) << 8)
+ + (($hash & 0x00ff0000) >> 8) + (($hash & 0xff000000) >> 24)
+ : $hash;
+ }
+}
diff --git a/modules/downloadalbum/css/downloadalbum_menu.css b/modules/downloadalbum/css/downloadalbum_menu.css
new file mode 100644
index 00000000..e3c4c67e
--- /dev/null
+++ b/modules/downloadalbum/css/downloadalbum_menu.css
@@ -0,0 +1,3 @@
+#g-view-menu #g-download-album-link {
+ background-image: url('../images/ico-view-downloadalbum.png');
+}
diff --git a/modules/downloadalbum/helpers/downloadalbum_event.php b/modules/downloadalbum/helpers/downloadalbum_event.php
new file mode 100644
index 00000000..e2fe4420
--- /dev/null
+++ b/modules/downloadalbum/helpers/downloadalbum_event.php
@@ -0,0 +1,32 @@
+item)) {
+ $downloadLink = url::site("downloadalbum/zip/{$theme->item->id}");
+ $menu
+ ->append(Menu::factory("link")
+ ->id("downloadalbum")
+ ->label(t("Download Album"))
+ ->url($downloadLink)
+ ->css_id("g-download-album-link"));
+ }
+ }
+}
diff --git a/modules/downloadalbum/helpers/downloadalbum_theme.php b/modules/downloadalbum/helpers/downloadalbum_theme.php
new file mode 100644
index 00000000..2fd23552
--- /dev/null
+++ b/modules/downloadalbum/helpers/downloadalbum_theme.php
@@ -0,0 +1,26 @@
+item && access::can("view_full", $theme->item)) {
+ $theme->css("downloadalbum_menu.css");
+ }
+ }
+}
diff --git a/modules/downloadalbum/images/ico-view-downloadalbum.png b/modules/downloadalbum/images/ico-view-downloadalbum.png
new file mode 100644
index 00000000..ce7804d2
Binary files /dev/null and b/modules/downloadalbum/images/ico-view-downloadalbum.png differ
diff --git a/modules/downloadalbum/module.info b/modules/downloadalbum/module.info
new file mode 100644
index 00000000..177ad4a8
--- /dev/null
+++ b/modules/downloadalbum/module.info
@@ -0,0 +1,3 @@
+name = "DownloadAlbum"
+description = "Displays a link to download a ZIP archive of the current album."
+version = 1
diff --git a/modules/ecard/controllers/admin_ecards.php b/modules/ecard/controllers/admin_ecards.php
new file mode 100644
index 00000000..b2bde957
--- /dev/null
+++ b/modules/ecard/controllers/admin_ecards.php
@@ -0,0 +1,63 @@
+page_title = t("eCard settings");
+ $view->content = new View("admin_ecards.html");
+ $view->content->form = $this->_get_admin_form();
+ print $view;
+ }
+
+ public function save() {
+ access::verify_csrf();
+ $form = $this->_get_admin_form();
+ if ($form->validate()) {
+ module::set_var("ecard", "sender", $form->ecard->sender->value);
+ module::set_var("ecard", "subject", $form->ecard->subject->value);
+ module::set_var("ecard", "message", $form->ecard->message->value);
+ module::set_var("ecard", "access_permissions", $form->ecard->access_permissions->value);
+ message::success(t("eCard settings updated"));
+ url::redirect("admin/ecards");
+ } else {
+ print $form;
+ }
+ }
+
+ private function _get_admin_form() {
+ $form = new Forge("admin/ecards/save", "", "post", array("id" => "g-ecards-admin-form"));
+ $ecard_settings = $form->group("ecard")->label(t("eCard settings"));
+ $ecard_settings->input("sender")
+ ->label(t("E-mail sender (leave blank for a user-defined address)"))
+ ->value(module::get_var("ecard", "sender", ""));
+ $ecard_settings->input("subject")->label(t("E-mail subject"))
+ ->value(module::get_var("ecard", "subject"));
+ $ecard_settings->textarea("message")->label(t("E-mail message"))
+ ->value(module::get_var("ecard", "message"));
+ $ecard_settings->dropdown("access_permissions")
+ ->label(t("Who can send eCards?"))
+ ->options(array("everybody" => t("Everybody"),
+ "registered_users" => t("Only registered users")))
+ ->selected(module::get_var("ecard", "access_permissions"));
+ $ecard_settings->submit("save")->value(t("Save"));
+ return $form;
+ }
+}
+
diff --git a/modules/ecard/controllers/ecards.php b/modules/ecard/controllers/ecards.php
new file mode 100644
index 00000000..6ea77a00
--- /dev/null
+++ b/modules/ecard/controllers/ecards.php
@@ -0,0 +1,53 @@
+validate()) {
+ Kohana_Log::add("error",print_r($form,1));
+ // Send the ecard here, based on the form data
+ json::reply(array("result" => "success"));
+ } else {
+ json::reply(array("result" => "error", "html" => (string)$form));
+ }
+ }
+
+ /**
+ * Present a form for adding a new ecard to this item or editing an existing ecard.
+ */
+ public function form_send($item_id) {
+ $item = ORM::factory("item", $item_id);
+ access::required("view", $item);
+ if (!ecard::can_send_ecard()) {
+ access::forbidden();
+ }
+
+ print ecard::prefill_send_form(ecard::get_send_form($item));
+ }
+}
diff --git a/modules/ecard/helpers/ecard.php b/modules/ecard/helpers/ecard.php
new file mode 100644
index 00000000..0b4d63db
--- /dev/null
+++ b/modules/ecard/helpers/ecard.php
@@ -0,0 +1,79 @@
+id}", "", "post", array("id" => "g-ecard-form"));
+ $group = $form->group("send_ecard")->label(t("Send eCard"));
+ $group->input("from_name")
+ ->label(t("Your name"))
+ ->id("g-author")
+ ->rules("required")
+ ->error_messages("required", t("You must enter a name for yourself"));
+ $group->input("from_email")
+ ->label(t("Your e-mail"))
+ ->id("g-email")
+ ->rules("required|valid_email")
+ ->error_messages("required", t("You must enter a valid email address"))
+ ->error_messages("invalid", t("You must enter a valid email address"));
+ $group->input("to_name")
+ ->label(t("Recipient's Name"))
+ ->id("g-recipient")
+ ->rules("required")
+ ->error_messages("required", t("You must enter a recipient's name"));
+ $group->input("to_email")
+ ->label(t("Recipient's e-mail"))
+ ->id("g-recip-email")
+ ->rules("required|valid_email")
+ ->error_messages("required", t("You must enter a valid email address"))
+ ->error_messages("invalid", t("You must enter a valid email address"));
+ $group->textarea("text")
+ ->label(t("Message"))
+ ->id("g-text")
+ ->rules("required")
+ ->error_messages("required", t("You must enter a message"));
+ $group->hidden("item_id")->value($item->id);
+ module::event("ecard_send_form", $form);
+ $group->submit("")->value(t("Send"))->class("ui-state-default ui-corner-all");
+
+ return $form;
+ }
+
+ static function prefill_send_form($form) {
+ $active = identity::active_user();
+ if (!$active->guest) {
+ $group = $form->send_ecard;
+ $group->inputs["from_name"]->value($active->full_name);
+ $group->from_email->value($active->email);
+ }
+ return $form;
+ }
+
+ static function can_send_ecard() {
+ return !identity::active_user()->guest ||
+ module::get_var("ecard", "access_permissions") == "everybody";
+ }
+}
+
diff --git a/modules/ecard/helpers/ecard_event.php b/modules/ecard/helpers/ecard_event.php
new file mode 100644
index 00000000..b7517185
--- /dev/null
+++ b/modules/ecard/helpers/ecard_event.php
@@ -0,0 +1,28 @@
+get("settings_menu")
+ ->append(Menu::factory("link")
+ ->id("ecard")
+ ->label(t("eCard Settings"))
+ ->url(url::site("admin/ecards")));
+ }
+}
diff --git a/modules/ecard/helpers/ecard_installer.php b/modules/ecard/helpers/ecard_installer.php
new file mode 100644
index 00000000..2f514b09
--- /dev/null
+++ b/modules/ecard/helpers/ecard_installer.php
@@ -0,0 +1,29 @@
+css_id = "g-ecards";
+ $block->title = t("eCards");
+ $block->content = new View("ecards.html");
+ return $block;
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/ecard/module.info b/modules/ecard/module.info
new file mode 100644
index 00000000..bc50f729
--- /dev/null
+++ b/modules/ecard/module.info
@@ -0,0 +1,3 @@
+name = "E-Card"
+description = "Send a photo as a postcard"
+version = 1
diff --git a/modules/ecard/views/admin_ecards.html.php b/modules/ecard/views/admin_ecards.html.php
new file mode 100644
index 00000000..0dd6b926
--- /dev/null
+++ b/modules/ecard/views/admin_ecards.html.php
@@ -0,0 +1,7 @@
+
+
+
= t("eCard settings") ?>
+
+ = $form ?>
+
+
diff --git a/modules/ecard/views/ecards.html.php b/modules/ecard/views/ecards.html.php
new file mode 100644
index 00000000..e655debb
--- /dev/null
+++ b/modules/ecard/views/ecards.html.php
@@ -0,0 +1,6 @@
+
+id}") ?>" id="g-add-ecard"
+ class="g-button ui-corner-all ui-icon-left ui-state-default g-dialog-link">
+
+ = t("Send an eCard") ?>
+
diff --git a/modules/exif_gps/controllers/admin_exif_gps.php b/modules/exif_gps/controllers/admin_exif_gps.php
new file mode 100644
index 00000000..04f540e0
--- /dev/null
+++ b/modules/exif_gps/controllers/admin_exif_gps.php
@@ -0,0 +1,129 @@
+content = new View("admin_exif_gps.html");
+ $view->content->exifgps_form = $this->_get_admin_form();
+ print $view;
+ }
+
+ public function saveprefs() {
+ // Save user preferences to the database.
+
+ // Prevent Cross Site Request Forgery
+ access::verify_csrf();
+
+ // Make sure the user filled out the form properly.
+ $form = $this->_get_admin_form();
+ if ($form->validate()) {
+ Kohana_Log::add("error",print_r($form,1));
+
+ // Save settings to Gallery's database.
+ module::set_var("exif_gps", "googlemap_api_key", $form->Global->google_api_key->value);
+ module::set_var("exif_gps", "googlemap_max_autozoom", $form->Global->max_auto_zoom_level->value);
+ module::set_var("exif_gps", "sidebar_zoom", $form->Sidebar->sidebar_default_zoom->value);
+ module::set_var("exif_gps", "sidebar_mapformat", $form->Sidebar->sidebar_mapformat->value);
+ module::set_var("exif_gps", "sidebar_maptype", $form->Sidebar->sidebar_maptype->value);
+ module::set_var("exif_gps", "largemap_maptype", $form->LargeMap->largemap_maptype->value);
+ $checkbox_album = false;
+ $checkbox_user = false;
+ for ($i = 0; $i < count($form->Global->toolbar_map_album); $i++) {
+ if ($form->Global->toolbar_map_album->value[$i] == "checkbox_album") {
+ $checkbox_album = true;
+ }
+ }
+ for ($i = 0; $i < count($form->Global->toolbar_map_user); $i++) {
+ if ($form->Global->toolbar_map_user->value[$i] == "checkbox_user") {
+ $checkbox_user = true;
+ }
+ }
+ module::set_var("exif_gps", "toolbar_map_album", $checkbox_album);
+ module::set_var("exif_gps", "toolbar_map_user", $checkbox_user);
+
+ // Display a success message and redirect back to the TagsMap admin page.
+ message::success(t("Your settings have been saved."));
+ url::redirect("admin/exif_gps");
+ }
+
+ // Else show the page with errors
+ $view = new Admin_View("admin.html");
+ $view->content = new View("admin_exif_gps.html");
+ $view->content->exifgps_form = $form;
+ print $view;
+ }
+
+ private function _get_admin_form() {
+ // Make a new Form.
+ $form = new Forge("admin/exif_gps/saveprefs", "", "post",
+ array("id" => "g-exif-gps-adminForm"));
+
+ // Create group for global settings, like the Maps API Key
+ $gps_global_group = $form->group("Global")
+ ->label(t("Global Settings"));
+ $gps_global_group->input("google_api_key")
+ ->label(t("Google Maps API Key"))
+ ->value(module::get_var("exif_gps", "googlemap_api_key"))
+ ->rules("required");
+ $gps_global_group->input("max_auto_zoom_level")
+ ->label(t("Maximum Auto-Zoom Level:"))
+ ->value(module::get_var("exif_gps", "googlemap_max_autozoom"));
+ $checkbox_user["checkbox_user"] = array(t("Show \"Map this user\" icon?"), module::get_var("exif_gps", "toolbar_map_user"));
+ $checkbox_album["checkbox_album"] = array(t("Show \"Map this album\" icon?"), module::get_var("exif_gps", "toolbar_map_album"));
+ $gps_global_group->checklist("toolbar_map_album")
+ ->options($checkbox_album);
+ $gps_global_group->checklist("toolbar_map_user")
+ ->options($checkbox_user);
+
+ // Create a group for sidebar settings
+ $gps_sidebar = $form->group("Sidebar")
+ ->label(t("Sidebar Settings"));
+ $gps_sidebar->input("sidebar_default_zoom")
+ ->label(t("Default Zoom Level"))
+ ->value(module::get_var("exif_gps", "sidebar_zoom"))
+ ->rules("required");
+ $gps_sidebar->dropdown("sidebar_mapformat")
+ ->label(t("Map Interface"))
+ ->options(array(t("Static"), t("Interactive")))
+ ->selected(module::get_var("exif_gps", "sidebar_mapformat"));
+ $gps_sidebar->dropdown("sidebar_maptype")
+ ->label(t("Default Map Type"))
+ ->options(array(t("Map"), t("Satellite"),
+ t("Hybrid"), t("Terrain")))
+ ->selected(module::get_var("exif_gps", "sidebar_maptype"));
+
+ // Create a group for map album/user settings
+ $gps_large_map_group = $form->group("LargeMap")
+ ->label(t("Map Album/User Settings"));
+ $gps_large_map_group->dropdown("largemap_maptype")
+ ->label(t("Default Map Type"))
+ ->options(array(t("Map"), t("Satellite"),
+ t("Hybrid"), t("Terrain")))
+ ->selected(module::get_var("exif_gps", "largemap_maptype"));
+
+ // Add a save button to the form.
+ $form->submit("SaveSettings")->value(t("Save"));
+
+ // Return the newly generated form.
+ return $form;
+ }
+}
diff --git a/modules/exif_gps/controllers/exif_gps.php b/modules/exif_gps/controllers/exif_gps.php
new file mode 100644
index 00000000..262c7938
--- /dev/null
+++ b/modules/exif_gps/controllers/exif_gps.php
@@ -0,0 +1,78 @@
+join("exif_coordinates", "items.id", "exif_coordinates.item_id")
+ ->viewable()
+ ->order_by("exif_coordinates.latitude", "ASC")
+ ->descendants();
+ $curr_album = ORM::factory("item")->where("id", "=", $type_id)->find_all();
+ $map_title = $curr_album[0]->name;
+ } elseif ($map_type == "user") {
+ // Generate an array of all items uploaded by the current user that
+ // have exif gps coordinates and order by latitude (to group items
+ // w/ the same coordinates together).
+ $items = ORM::factory("item")
+ ->join("exif_coordinates", "items.id", "exif_coordinates.item_id")
+ ->where("items.owner_id", "=", $type_id)
+ ->viewable()
+ ->order_by("exif_coordinates.latitude", "ASC")
+ ->find_all();
+ $curr_user = ORM::factory("user")->where("id", "=", $type_id)->find_all();
+ $map_title = $curr_user[0]->full_name . "'s " . t("Photos");
+ }
+
+ // Make a new page.
+ $template = new Theme_View("page.html", "other", "EXIFMap");
+ $template->page_title = t("Gallery :: Map");
+ $template->content = new View("exif_gps_map.html");
+ if ($map_title == "") {
+ $template->content->title = t("Map");
+ } else {
+ $template->content->title = t("Map of") . " " . $map_title;
+ }
+
+ // Figure out default map type.
+ $int_map_type = module::get_var("exif_gps", "largemap_maptype");
+ if ($int_map_type == 0) $map_type = "ROADMAP";
+ if ($int_map_type == 1) $map_type = "SATELLITE";
+ if ($int_map_type == 2) $map_type = "HYBRID";
+ if ($int_map_type == 3) $map_type = "TERRAIN";
+ $template->content->map_type = $map_type;
+
+ // When mapping an album, generate a "return to album" link.
+ if (isset($curr_album)) $template->content->return_url = url::abs_site("{$curr_album[0]->type}s/{$curr_album[0]->id}");
+
+ // Load in module preferences.
+ $template->content->items = $items;
+ $template->content->google_map_key = module::get_var("exif_gps", "googlemap_api_key");
+
+ // Display the page.
+ print $template;
+ }
+}
diff --git a/modules/exif_gps/css/exif_gps_menu.css b/modules/exif_gps/css/exif_gps_menu.css
new file mode 100644
index 00000000..3f8afa28
--- /dev/null
+++ b/modules/exif_gps/css/exif_gps_menu.css
@@ -0,0 +1,6 @@
+#g-view-menu #g-exif-gps-album-link {
+ background-image: url('../images/ico-view-exif_gps_album.png');
+}
+#g-view-menu #g-exif-gps-user-link {
+ background-image: url('../images/ico-view-exif_gps_user.png');
+}
diff --git a/modules/exif_gps/helpers/exif_gps.php b/modules/exif_gps/helpers/exif_gps.php
index 1cab6558..d3440424 100644
--- a/modules/exif_gps/helpers/exif_gps.php
+++ b/modules/exif_gps/helpers/exif_gps.php
@@ -17,12 +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.
*/
-
-/**
- * This is the API for handling exif data.
- */
class exif_gps_Core {
-
protected static $exif_keys;
static function extract($item) {
@@ -52,10 +47,10 @@ class exif_gps_Core {
$record->latitude = str_replace(",", ".", $keys["Latitude"]);
$record->longitude = str_replace(",", ".", $keys["Longitude"]);
// Represent N/S/E/W as postive and negative numbers
- if ($keys["Latitude Reference"] == "S") {
+ if (substr(strtoupper($keys["Latitude Reference"]), 0, 1) == "S") {
$record->latitude = "-" . $record->latitude;
}
- if ($keys["Longitude Reference"] == "W") {
+ if (substr(strtoupper($keys["Longitude Reference"]), 0, 1) == "W") {
$record->longitude = "-" . $record->longitude;
}
$record->save();
@@ -74,4 +69,4 @@ class exif_gps_Core {
}
return self::$exif_keys;
}
-}
\ No newline at end of file
+}
diff --git a/modules/exif_gps/helpers/exif_gps_block.php b/modules/exif_gps/helpers/exif_gps_block.php
index 77e3d5e5..78d29609 100644
--- a/modules/exif_gps/helpers/exif_gps_block.php
+++ b/modules/exif_gps/helpers/exif_gps_block.php
@@ -19,48 +19,130 @@
*/
class exif_gps_block_Core {
static function get_site_list() {
- return array("exif_gps_map" => t("EXIF GPS Map"));
+ return array("exif_gps_location" => t("EXIF GPS Location"),
+ "exif_gps_maps" => t("EXIF GPS Maps"));
}
static function get($block_id, $theme) {
$block = "";
- // Make sure the current page belongs to an item.
- if (!$theme->item()) {
- return;
- }
-
switch ($block_id) {
- case "exif_gps_map":
- // Check and see if the item has exif coordinates associated with it.
- $record = ORM::factory("exif_coordinate")->where("item_id", "=", $theme->item->id)->find();
- if ($record->loaded()) {
- $block = new Block();
- $block->css_id = "g-exif-gps-sidebar";
- $block->title = t("Location");
- $block->content = new View("exif_gps_sidebar.html");
- $block->content->latitude = $record->latitude;
- $block->content->longitude = $record->longitude;
- } elseif (module::is_active("tagsmap") && module::is_active("tag")) {
- // If there are no exif coordinates, check for tagsmap coordinates instead.
- $tagsItem = ORM::factory("tag")
- ->join("items_tags", "tags.id", "items_tags.tag_id")
- ->where("items_tags.item_id", "=", $theme->item->id)
- ->find_all();
- if (count($tagsItem) > 0) {
- foreach ($tagsItem as $oneTag) {
- $tagsGPS = ORM::factory("tags_gps")->where("tag_id", "=", $oneTag->id)->find();
- if ($tagsGPS->loaded()) {
- $block = new Block();
- $block->css_id = "g-exif-gps-sidebar";
- $block->title = t("Location");
- $block->content = new View("exif_gps_sidebar.html");
- $block->content->latitude = $tagsGPS->latitude;
- $block->content->longitude = $tagsGPS->longitude;
- break;
+ case "exif_gps_maps":
+ // Display links to a map of the current album and
+ // a map of the current user.
+ if ($theme->item()) {
+ $album_id = "";
+ $item = $theme->item;
+ if ($item->is_album()) {
+ $album_id = $item->id;
+ } else {
+ $album_id = $item->parent_id;
+ }
+ $curr_user = ORM::factory("user")->where("id", "=", $item->owner_id)->find_all();
+ $user_name = $curr_user[0]->full_name;
+
+ // Make sure there are actually map-able items to display.
+ $album_items_count = ORM::factory("item", $album_id)
+ ->join("exif_coordinates", "items.id", "exif_coordinates.item_id")
+ ->viewable()
+ ->order_by("exif_coordinates.latitude", "ASC")
+ ->descendants_count();
+ $user_items_count = ORM::factory("item")
+ ->join("exif_coordinates", "items.id", "exif_coordinates.item_id")
+ ->where("items.owner_id", "=", $item->owner_id)
+ ->viewable()
+ ->order_by("exif_coordinates.latitude", "ASC")
+ ->count_all();
+
+ if (($album_items_count > 0) || ($user_items_count > 0)) {
+ $block = new Block();
+ $block->css_id = "g-exif-gps-maps";
+ $block->title = t("Maps");
+ $block->content = new View("exif_gps_maps_sidebar.html");
+ $block->content->album_id = $album_id;
+ $block->content->user_id = $item->owner_id;
+ $block->content->user_name = $user_name;
+ $block->content->album_items = $album_items_count;
+ $block->content->user_items = $user_items_count;
+ }
+ }
+ break;
+
+ case "exif_gps_location":
+ // Look for coordinates to display.
+ $latitude = "";
+ $longitude = "";
+ if ($theme->item()) {
+ // Check and see if the item has exif coordinates associated with it.
+ $record = ORM::factory("exif_coordinate")->where("item_id", "=", $theme->item->id)->find();
+ if ($record->loaded()) {
+ $latitude = $record->latitude;
+ $longitude = $record->longitude;
+ } elseif (module::is_active("tagsmap") && module::is_active("tag")) {
+ // If there are no exif coordinates, check for tagsmap coordinates instead.
+ $tagsItem = ORM::factory("tag")
+ ->join("items_tags", "tags.id", "items_tags.tag_id")
+ ->where("items_tags.item_id", "=", $theme->item->id)
+ ->find_all();
+ if (count($tagsItem) > 0) {
+ foreach ($tagsItem as $oneTag) {
+ $tagsGPS = ORM::factory("tags_gps")->where("tag_id", "=", $oneTag->id)->find();
+ if ($tagsGPS->loaded()) {
+ $latitude = $tagsGPS->latitude;
+ $longitude = $tagsGPS->longitude;
+ break;
+ }
}
}
}
+ } elseif ( ($theme->tag()) && (module::is_active("tagsmap") && module::is_active("tag")) ) {
+ // If the current page belongs to a tag, check and see if the tag has GPS coordinates.
+ $tagsGPS = ORM::factory("tags_gps")->where("tag_id", "=", $theme->tag()->id)->find();
+ if ($tagsGPS->loaded()) {
+ $latitude = $tagsGPS->latitude;
+ $longitude = $tagsGPS->longitude;
+ }
+ }
+
+ // If coordinates were found, create the block.
+ if ($latitude != "" && $longitude != "") {
+ $block = new Block();
+ $block->css_id = "g-exif-gps-location";
+ $block->title = t("Location");
+ if (module::get_var("exif_gps", "sidebar_mapformat") == 1) {
+ $block->content = new View("exif_gps_dynamic_sidebar.html");
+ if (module::get_var("exif_gps", "sidebar_maptype") == 0) $block->content->sidebar_map_type = "ROADMAP";
+ if (module::get_var("exif_gps", "sidebar_maptype") == 1) $block->content->sidebar_map_type = "SATELLITE";
+ if (module::get_var("exif_gps", "sidebar_maptype") == 2) $block->content->sidebar_map_type = "HYBRID";
+ if (module::get_var("exif_gps", "sidebar_maptype") == 3) $block->content->sidebar_map_type = "TERRAIN";
+ } else {
+ $block->content = new View("exif_gps_static_sidebar.html");
+ if (module::get_var("exif_gps", "sidebar_maptype") == 0) $block->content->sidebar_map_type = "roadmap";
+ if (module::get_var("exif_gps", "sidebar_maptype") == 1) $block->content->sidebar_map_type = "satellite";
+ if (module::get_var("exif_gps", "sidebar_maptype") == 2) $block->content->sidebar_map_type = "hybrid";
+ if (module::get_var("exif_gps", "sidebar_maptype") == 3) $block->content->sidebar_map_type = "terrain";
+ }
+ $block->content->latitude = $latitude;
+ $block->content->longitude = $longitude;
+ } elseif (($theme->item()) && ($theme->item->is_album() && (module::get_var("exif_gps", "sidebar_mapformat") == 1))) {
+ // If coordinates were NOT found, and this is an album with a dynamic map, then map the contents of the album.
+ $items = ORM::factory("item", $theme->item->id)
+ ->join("exif_coordinates", "items.id", "exif_coordinates.item_id")
+ ->viewable()
+ ->order_by("exif_coordinates.latitude", "ASC")
+ ->descendants();
+ if (count($items) > 0) {
+ $block = new Block();
+ $block->css_id = "g-exif-gps-location";
+ $block->title = t("Location");
+ $block->content = new View("exif_gps_dynamic2_sidebar.html");
+ if (module::get_var("exif_gps", "sidebar_maptype") == 0) $block->content->sidebar_map_type = "ROADMAP";
+ if (module::get_var("exif_gps", "sidebar_maptype") == 1) $block->content->sidebar_map_type = "SATELLITE";
+ if (module::get_var("exif_gps", "sidebar_maptype") == 2) $block->content->sidebar_map_type = "HYBRID";
+ if (module::get_var("exif_gps", "sidebar_maptype") == 3) $block->content->sidebar_map_type = "TERRAIN";
+ $block->content->items = $items;
+ $block->content->google_map_key = module::get_var("exif_gps", "googlemap_api_key");
+ }
}
break;
}
diff --git a/modules/exif_gps/helpers/exif_gps_event.php b/modules/exif_gps/helpers/exif_gps_event.php
index e19f2a17..7e1a6396 100644
--- a/modules/exif_gps/helpers/exif_gps_event.php
+++ b/modules/exif_gps/helpers/exif_gps_event.php
@@ -56,14 +56,15 @@ class exif_gps_event_Core {
static function item_edit_form($item, $form) {
// Allow users to set / edit the GPS coordinates associated with the current item.
$record = ORM::factory("exif_coordinate")->where("item_id", "=", $item->id)->find();
+ $gpsdata = $form->edit_item->group("gps_data")->label("GPS Data");
if ($record->loaded()) {
- $form->edit_item->input("latitude")->label(t("Latitude"))
+ $gpsdata->input("latitude")->label(t("Latitude"))
->value($record->latitude);
- $form->edit_item->input("longitude")->label(t("Longitude"))
+ $gpsdata->input("longitude")->label(t("Longitude"))
->value($record->longitude);
} else {
- $form->edit_item->input("latitude")->label(t("Latitude"));
- $form->edit_item->input("longitude")->label(t("Longitude"));
+ $gpsdata->input("latitude")->label(t("Latitude"));
+ $gpsdata->input("longitude")->label(t("Longitude"));
}
}
@@ -72,7 +73,7 @@ class exif_gps_event_Core {
// Require a set of coordinates (both latitude and longitude).
// If one or both fields are blank, completely delete any coordinates associated with this item.
- if (($form->edit_item->latitude->value == "") || ($form->edit_item->longitude->value == "")) {
+ if (($form->edit_item->gps_data->latitude->value == "") || ($form->edit_item->gps_data->longitude->value == "")) {
db::build()
->delete("exif_coordinates")
->where("item_id", "=", $item->id)
@@ -82,9 +83,138 @@ class exif_gps_event_Core {
if (!$record->loaded()) {
$record->item_id = $item->id;
}
- $record->latitude = $form->edit_item->latitude->value;
- $record->longitude = $form->edit_item->longitude->value;
+ $record->latitude = $form->edit_item->gps_data->latitude->value;
+ $record->longitude = $form->edit_item->gps_data->longitude->value;
$record->save();
}
}
+
+ static function admin_menu($menu, $theme) {
+ // Add a link to the EXIF_GPS admin page to the Settings menu.
+ $menu->get("settings_menu")
+ ->append(Menu::factory("link")
+ ->id("exif_gps")
+ ->label(t("EXIF_GPS Settings"))
+ ->url(url::site("admin/exif_gps")));
+ }
+
+ static function photo_menu($menu, $theme) {
+ $album_id = "";
+ $item = $theme->item;
+ if ($item->is_album()) {
+ $album_id = $item->id;
+ } else {
+ $album_id = $item->parent_id;
+ }
+ $curr_user = ORM::factory("user")->where("id", "=", $item->owner_id)->find_all();
+ $user_name = $curr_user[0]->full_name;
+
+ // Make sure there are actually map-able items to display.
+ $album_items_count = ORM::factory("item", $album_id)
+ ->join("exif_coordinates", "items.id", "exif_coordinates.item_id")
+ ->viewable()
+ ->order_by("exif_coordinates.latitude", "ASC")
+ ->descendants_count();
+ $user_items_count = ORM::factory("item")
+ ->join("exif_coordinates", "items.id", "exif_coordinates.item_id")
+ ->where("items.owner_id", "=", $item->owner_id)
+ ->viewable()
+ ->order_by("exif_coordinates.latitude", "ASC")
+ ->count_all();
+
+ if (($album_items_count > 0) && (module::get_var("exif_gps", "toolbar_map_album") == true)) {
+ $menu->append(Menu::factory("link")
+ ->id("exif_gps_album")
+ ->label(t("Map this album"))
+ ->url(url::site("exif_gps/map/album/" . $album_id))
+ ->css_id("g-exif-gps-album-link"));
+ }
+ if (($user_items_count > 0) && (module::get_var("exif_gps", "toolbar_map_user") == true)) {
+ $menu->append(Menu::factory("link")
+ ->id("exif_gps_user")
+ ->label(t("Map ") . $user_name . t("'s photos"))
+ ->url(url::site("exif_gps/map/user/" . $item->owner_id))
+ ->css_id("g-exif-gps-user-link"));
+ }
+ }
+
+ static function movie_menu($menu, $theme) {
+ $album_id = "";
+ $item = $theme->item;
+ if ($item->is_album()) {
+ $album_id = $item->id;
+ } else {
+ $album_id = $item->parent_id;
+ }
+ $curr_user = ORM::factory("user")->where("id", "=", $item->owner_id)->find_all();
+ $user_name = $curr_user[0]->full_name;
+
+ // Make sure there are actually map-able items to display.
+ $album_items_count = ORM::factory("item", $album_id)
+ ->join("exif_coordinates", "items.id", "exif_coordinates.item_id")
+ ->viewable()
+ ->order_by("exif_coordinates.latitude", "ASC")
+ ->descendants_count();
+ $user_items_count = ORM::factory("item")
+ ->join("exif_coordinates", "items.id", "exif_coordinates.item_id")
+ ->where("items.owner_id", "=", $item->owner_id)
+ ->viewable()
+ ->order_by("exif_coordinates.latitude", "ASC")
+ ->count_all();
+
+ if (($album_items_count > 0) && (module::get_var("exif_gps", "toolbar_map_album") == true)) {
+ $menu->append(Menu::factory("link")
+ ->id("exif_gps_album")
+ ->label(t("Map this album"))
+ ->url(url::site("exif_gps/map/album/" . $album_id))
+ ->css_id("g-exif-gps-album-link"));
+ }
+ if (($user_items_count > 0) && (module::get_var("exif_gps", "toolbar_map_user") == true)) {
+ $menu->append(Menu::factory("link")
+ ->id("exif_gps_user")
+ ->label(t("Map ") . $user_name . t("'s photos"))
+ ->url(url::site("exif_gps/map/user/" . $item->owner_id))
+ ->css_id("g-exif-gps-user-link"));
+ }
+ }
+
+ static function album_menu($menu, $theme) {
+ $album_id = "";
+ $item = $theme->item;
+ if ($item->is_album()) {
+ $album_id = $item->id;
+ } else {
+ $album_id = $item->parent_id;
+ }
+ $curr_user = ORM::factory("user")->where("id", "=", $item->owner_id)->find_all();
+ $user_name = $curr_user[0]->full_name;
+
+ // Make sure there are actually map-able items to display.
+ $album_items_count = ORM::factory("item", $album_id)
+ ->join("exif_coordinates", "items.id", "exif_coordinates.item_id")
+ ->viewable()
+ ->order_by("exif_coordinates.latitude", "ASC")
+ ->descendants_count();
+ $user_items_count = ORM::factory("item")
+ ->join("exif_coordinates", "items.id", "exif_coordinates.item_id")
+ ->where("items.owner_id", "=", $item->owner_id)
+ ->viewable()
+ ->order_by("exif_coordinates.latitude", "ASC")
+ ->count_all();
+
+ if (($album_items_count > 0) && (module::get_var("exif_gps", "toolbar_map_album") == true)) {
+ $menu->append(Menu::factory("link")
+ ->id("exif_gps_album")
+ ->label(t("Map this album"))
+ ->url(url::site("exif_gps/map/album/" . $album_id))
+ ->css_id("g-exif-gps-album-link"));
+ }
+ if (($user_items_count > 0) && (module::get_var("exif_gps", "toolbar_map_user") == true)) {
+ $menu->append(Menu::factory("link")
+ ->id("exif_gps_user")
+ ->label(t("Map ") . $user_name . t("'s photos"))
+ ->url(url::site("exif_gps/map/user/" . $item->owner_id))
+ ->css_id("g-exif-gps-user-link"));
+ }
+ }
}
diff --git a/modules/exif_gps/helpers/exif_gps_installer.php b/modules/exif_gps/helpers/exif_gps_installer.php
index 6377228b..4e75c546 100644
--- a/modules/exif_gps/helpers/exif_gps_installer.php
+++ b/modules/exif_gps/helpers/exif_gps_installer.php
@@ -30,7 +30,35 @@ class exif_gps_installer {
KEY(`item_id`, `id`))
DEFAULT CHARSET=utf8;");
- module::set_version("exif_gps", 1);
+ // If tagsmap is installed, copy the API key over.
+ if (module::is_active("tagsmap")) {
+ module::set_var("exif_gps", "googlemap_api_key", module::get_var("tagsmap", "googlemap_api_key"));
+ }
+
+ // Set some default values.
+ module::set_var("exif_gps", "sidebar_zoom", "14");
+ module::set_var("exif_gps", "sidebar_mapformat", "1");
+ module::set_var("exif_gps", "sidebar_maptype", "1");
+ module::set_var("exif_gps", "largemap_maptype", "2");
+
+ // Set the module version number.
+ module::set_version("exif_gps", 2);
+ }
+
+ static function upgrade($version) {
+ if ($version == 1) {
+ // If tagsmap is installed, copy the API key over.
+ if (module::is_active("tagsmap")) {
+ module::set_var("exif_gps", "googlemap_api_key", module::get_var("tagsmap", "googlemap_api_key"));
+ }
+
+ // Set some default values.
+ module::set_var("exif_gps", "sidebar_zoom", "14");
+ module::set_var("exif_gps", "sidebar_mapformat", "1");
+ module::set_var("exif_gps", "sidebar_maptype", "1");
+ module::set_var("exif_gps", "largemap_maptype", "2");
+ module::set_version("exif_gps", 2);
+ }
}
static function deactivate() {
diff --git a/modules/exif_gps/helpers/exif_gps_theme.php b/modules/exif_gps/helpers/exif_gps_theme.php
new file mode 100644
index 00000000..160373a2
--- /dev/null
+++ b/modules/exif_gps/helpers/exif_gps_theme.php
@@ -0,0 +1,24 @@
+css("exif_gps_menu.css");
+ }
+}
diff --git a/modules/exif_gps/images/ico-view-exif_gps_album.png b/modules/exif_gps/images/ico-view-exif_gps_album.png
new file mode 100644
index 00000000..255d6496
Binary files /dev/null and b/modules/exif_gps/images/ico-view-exif_gps_album.png differ
diff --git a/modules/exif_gps/images/ico-view-exif_gps_user.png b/modules/exif_gps/images/ico-view-exif_gps_user.png
new file mode 100644
index 00000000..e9f72b3b
Binary files /dev/null and b/modules/exif_gps/images/ico-view-exif_gps_user.png differ
diff --git a/modules/exif_gps/models/exif_coordinate.php b/modules/exif_gps/models/exif_coordinate.php
index 8e898f45..481da1cd 100644
--- a/modules/exif_gps/models/exif_coordinate.php
+++ b/modules/exif_gps/models/exif_coordinate.php
@@ -18,4 +18,4 @@
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class EXIF_Coordinate_Model extends ORM {
-}
\ No newline at end of file
+}
diff --git a/modules/exif_gps/module.info b/modules/exif_gps/module.info
index be30a70b..05a3aae3 100644
--- a/modules/exif_gps/module.info
+++ b/modules/exif_gps/module.info
@@ -1,3 +1,3 @@
name = "Exif GPS Data"
description = "Extract Exif GPS data from photos."
-version = 1
+version = 2
diff --git a/modules/exif_gps/views/admin_exif_gps.html.php b/modules/exif_gps/views/admin_exif_gps.html.php
new file mode 100644
index 00000000..dcfed2c9
--- /dev/null
+++ b/modules/exif_gps/views/admin_exif_gps.html.php
@@ -0,0 +1,7 @@
+
+
+
= t("EXIF GPS Settings") ?>
+
+ = $exifgps_form ?>
+
=t("Default Zoom Level:"); ?> =t("This value represents how far zoomed in or out the map will start out at. A value of 0 (the coarsest) will zoom the map all of the way out, while higher numbers will zoom the map further in. Depending on the map type, the highest zoom value you can use will be around 19-23."); ?>
+
diff --git a/modules/exif_gps/views/exif_gps_dynamic2_sidebar.html.php b/modules/exif_gps/views/exif_gps_dynamic2_sidebar.html.php
new file mode 100644
index 00000000..24b69acb
--- /dev/null
+++ b/modules/exif_gps/views/exif_gps_dynamic2_sidebar.html.php
@@ -0,0 +1,59 @@
+
+
+
+
+
diff --git a/modules/exif_gps/views/exif_gps_dynamic_sidebar.html.php b/modules/exif_gps/views/exif_gps_dynamic_sidebar.html.php
new file mode 100644
index 00000000..d5b497dc
--- /dev/null
+++ b/modules/exif_gps/views/exif_gps_dynamic_sidebar.html.php
@@ -0,0 +1,22 @@
+
+
+
+
diff --git a/modules/exif_gps/views/exif_gps_map.html.php b/modules/exif_gps/views/exif_gps_map.html.php
new file mode 100644
index 00000000..6c8a59ee
--- /dev/null
+++ b/modules/exif_gps/views/exif_gps_map.html.php
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+ if ($return_url != ""): ?>
+
=t("Return to album"); ?>
+ endif ?>
+= $theme->dynamic_bottom() ?>
diff --git a/modules/exif_gps/views/exif_gps_maps_sidebar.html.php b/modules/exif_gps/views/exif_gps_maps_sidebar.html.php
new file mode 100644
index 00000000..495554ac
--- /dev/null
+++ b/modules/exif_gps/views/exif_gps_maps_sidebar.html.php
@@ -0,0 +1,9 @@
+
+
diff --git a/modules/exif_gps/views/exif_gps_sidebar.html.php b/modules/exif_gps/views/exif_gps_sidebar.html.php
deleted file mode 100644
index 93aa3594..00000000
--- a/modules/exif_gps/views/exif_gps_sidebar.html.php
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/modules/exif_gps/views/exif_gps_static_sidebar.html.php b/modules/exif_gps/views/exif_gps_static_sidebar.html.php
new file mode 100644
index 00000000..11d80c74
--- /dev/null
+++ b/modules/exif_gps/views/exif_gps_static_sidebar.html.php
@@ -0,0 +1,2 @@
+
+
&size=205x214&maptype==$sidebar_map_type ?>&markers=color:red|color:red|=$latitude; ?>,=$longitude; ?>&sensor=false">
diff --git a/modules/favourites/controllers/admin_favourites_configure.php b/modules/favourites/controllers/admin_favourites_configure.php
new file mode 100644
index 00000000..ad6af6f6
--- /dev/null
+++ b/modules/favourites/controllers/admin_favourites_configure.php
@@ -0,0 +1,50 @@
+validate()) {
+
+ favourites_configuration::extractForm($form);
+ message::success(t("Favourites Module Configured!"));
+ }
+ }
+ else
+ {
+ favourites_configuration::populateForm($form);
+ }
+
+ $view = new Admin_View("admin.html");
+ $view->content = new View("admin_favourites_configure.html");
+
+ $view->content->form = $form;
+
+ print $view;
+ }
+}
diff --git a/modules/favourites/controllers/favourites.php b/modules/favourites/controllers/favourites.php
new file mode 100644
index 00000000..d7989682
--- /dev/null
+++ b/modules/favourites/controllers/favourites.php
@@ -0,0 +1,206 @@
+name =="guest"){
+ //login required.
+ url::redirect("login/html");
+ return;
+ }
+
+ $album = Favourites::getOrCreate()->get_as_album();
+
+ $page_size = module::get_var("gallery", "page_size", 9);
+ $input = Input::instance();
+ $show = $input->get("show");
+
+ if ($show) {
+ $child = ORM::factory("item", $show);
+ $index = $album->get_position($child);
+ if ($index) {
+ $page = ceil($index / $page_size);
+ if ($page == 1) {
+ //url::redirect("favourites");
+ } else {
+ //url::redirect("favourites?page=$page");
+ }
+ }
+ }
+
+
+ $page = $input->get("page", "1");
+ $children_count = $album->viewable()->children_count();
+ $offset = ($page - 1) * $page_size;
+ $max_pages = max(ceil($children_count / $page_size), 1);
+
+
+ // Make sure that the page references a valid offset
+ if ($page < 1) {
+ //url::redirect($album->abs_url());
+ } else if ($page > $max_pages) {
+ //url::redirect($album->abs_url("page=$max_pages"));
+ }
+
+
+
+ $template = new Theme_View("page.html", "collection", "favourites");
+ $template->set_global("page", $page);
+ $template->set_global("page_title", null);
+ $template->set_global("max_pages", $max_pages);
+ $template->set_global("page_size", $page_size);
+ $template->set_global("children", $album->viewable()->children($page_size, $offset));
+ $template->set_global("children_count", $children_count);
+ $template->content = new View("dynamic.html");
+
+ print $template;
+ }
+
+ public function view(){
+ if (favourites_configuration::isUsersOnly() && identity::active_user()->name =="guest"){
+ //login required.
+ Session::instance()->set("continue_url", url::current(true));
+ $template = new Theme_View("page.html", "collection", "album");
+ $template->content = new View("login_required.html");
+ $template->content->login_form = new View("login_ajax.html");
+ $template->content->login_form->form = auth::get_login_form("login/auth_html");
+ print $template;
+ return;
+ }
+
+ // extract details from url
+ $favourites = Favourites::getOrCreate();
+ $favourites->clear();
+ $array = func_get_args();
+ foreach($array as $i=>$item){
+ $favourites->toggle($item);
+ }
+ url::redirect("favourites");
+ }
+
+ private function getSaveForm(){
+
+ $form = new Forge("favourites/save_favourites", "", "post", array("id" => "gAddToBasketForm"));
+ $group = $form->group("save")->label(t("Save Favourites"));
+ $group->hidden("id");
+ $group->input("fullname")->label(t("Name"))->id("gname")
+ ->error_messages("required", t("You must provide your name"))
+ ->error_messages("not_logged_in", t("You must be logged in to send favourites."))
+ ->rules("required");
+ $group->input("email")->label(t("Email Address"))->id("gemail")
+ ->error_messages("required", t("You must provide an email address"))
+ ->error_messages("valid_email", t("You must provide a valid email address"))
+ ->rules("valid_email")
+ ->rules("required");
+ $group->textarea("details")->label(t("Comments"))->id("gdetails");
+
+ $group->submit("")->value(t("save"));
+ return $form;
+ }
+ public function save(){
+ $view = new View("save_dialog.html");
+
+ // get the basket to add to
+ $form = self::getSaveForm();
+ $view->form = $form;
+
+ print $view;
+
+ }
+
+ public function save_favourites($id){
+
+ access::verify_csrf();
+
+ $form = self::getSaveForm();
+ $valid = $form->validate();
+ $name = $form->save->fullname->value;
+ $email_address = $form->save->email->value;
+ $comments = $form->save->details->value;
+
+
+ if (!isset($email_address ) || strlen($email_address) == 0) {
+ $valid=false;
+ $form->save->email->add_error("required", 1);
+ }
+
+ if (!isset($name ) || strlen($name) == 0) {
+ $valid=false;
+ $form->save->fullname->add_error("required", 1);
+ }
+
+ if (favourites_configuration::isUsersOnly() && identity::active_user()->name =="guest"){
+ $valid=false;
+ $form->save->fullname->add_error("not_logged_in", 1);
+ }
+
+ if ($valid){
+
+ $favourites = Favourites::getOrCreate();
+
+ $from = "From: ".favourites_configuration::getFromEmailAddress();
+
+ if (favourites_configuration::isEmailAdmin())
+ {
+ $admin_email = $name." has chosen following photo as his or her favourites.\n";
+
+ // create the order items
+ $items = ORM::factory("item")->where("id","in", $favourites->contents)->find_all();
+ foreach ($items->contents as $id=>$item){
+ $admin_email = $admin_email."
+ ".$item->title." - ".$item->url()."";
+ }
+ $admin_email = $admin_email."\n you can view this favourite list at \n".$favourites->getUrl()
+ ."\n\n He or she has included the additional comments. \n".$comments
+ ."\n You can e-mail him or her with the following e-mail address ".$email_address;
+
+ mail(favourites_configuration::getEmailAddress(), $name."'s favourites.", $admin_email, $from);
+ }
+
+ $email = favourites_configuration::replaceStrings(
+ favourites_configuration::getEmailTemplate(),
+ Array(
+ "name"=>$name,
+ "comments"=>$comments,
+ "url"=>$favourites->getUrl(),
+ "owner"=>favourites_configuration::getOwner()));
+
+ mail($email_address,$name."'s Favourites",$email, $from);
+
+ json::reply(array("result" => "success", "location" => url::site("favourites")));
+ return;
+ }
+ json::reply(array("result" => "error", "html" => (string)$form));
+ }
+
+ public function toggle_favourites($id){
+ $favourites = Favourites::getOrCreate();
+ $infavour = $favourites ->toggle($id);
+ $title = $infavour?t("Remove from favourites"):t("Add to favourites");
+ json::reply(array("result" => "success",
+ "favourite" => $infavour,
+ "hasfavourites" => $favourites->hasFavourites(),
+ "title" => (string)$title));
+ }
+
+ public function clear_favourites(){
+ Favourites::getOrCreate()->clear();
+ }
+}
diff --git a/modules/favourites/css/favourites.css b/modules/favourites/css/favourites.css
new file mode 100644
index 00000000..2f025504
--- /dev/null
+++ b/modules/favourites/css/favourites.css
@@ -0,0 +1,15 @@
+.icon-f{width:32px; height:32px; display:inline-block; background-image: url(../images/faves.png); position:absolute; top:20px; left:0; z-index:20}
+.icon-f:hover{background-position: 0 -64px ;}
+.icon-f.f-selected{background-position: 0 -32px ;}
+.icon-f.f-working{background-position: 0 -96px ;}
+#f-view-link {float:right;position:relative; width:50px; height:50px;}
+#f-view-link a{width:64px; height:64px; display:inline-block;background-position: -96px 0px;background-image: url(../images/faves.png); position:absolute; top:15px; right:0;}
+#f-view-link a:hover{background-position: -96px -64px ;}
+#f-save-link {float:right;position:relative; width:64px; height:64px;}
+#f-save-link a{width:64px; height:64px; display:inline-block;background-position: -32px 0px;background-image: url(../images/faves.png); position:absolute; top:15px; right:0;}
+#f-save-link a:hover{background-position: -32px -64px ;}
+.rtl .icon-f{right:0;left:auto;}
+.rtl #f-view-link{float:left;}
+.rtl #f-view-link a{left:0;right:auto;}
+.rtl #f-save-link{float:left;}
+.rtl #f-save-link a{left:0;right:auto;}
\ No newline at end of file
diff --git a/modules/favourites/helpers/favourites_configuration.php b/modules/favourites/helpers/favourites_configuration.php
new file mode 100644
index 00000000..cae987f4
--- /dev/null
+++ b/modules/favourites/helpers/favourites_configuration.php
@@ -0,0 +1,144 @@
+ "g-configure-form"));
+
+ $group = $form->group("configure")->label(t("Configure Favourites"));
+ $group->dropdown("select_allow")
+ ->label(t("Please choose what a user can select as a favourite"))
+ ->options(Array(1=>t("Items only"), 2=>"albums only", 3=>"Both"));
+ $group->input("fromemail")->label(t("From Email address for site emails"))->id("g-from-email-address");
+ $group->checkbox("email_admin")->label(t("Email site owner every saved favourites list"))->id("g-email-admin");
+ $group->input("email")->label(t("Email address of Site Owner"))->id("g-owner-email-address");
+ $group->input("owner")->label(t("Site Owners name"))->id("g-owner-name");
+ $group->checkbox("users_only")->label(t("Only Registered users can create favourites"))->id("g-users-only");
+ $group->textarea("email_template")->label(t("Email Template"))->id("g-email-template");
+ $group->submit("")->value(t("Save"));
+ return $form;
+ }
+
+ static function populateForm($form){
+ $form->configure->email->value(favourites_configuration::getEmailAddress());
+ $form->configure->fromemail->value(favourites_configuration::getFromEmailAddress());
+ $form->configure->email_admin->checked(favourites_configuration::isEmailAdmin());
+ $form->configure->users_only->checked(favourites_configuration::isUsersOnly());
+ $form->configure->owner->value(favourites_configuration::getOwner());
+ $form->configure->email_template->value(favourites_configuration::getEmailTemplate());
+ $form->configure->select_allow->selected(favourites_configuration::getSelectAllow());
+ }
+
+ static function extractForm($form){
+ $email = $form->configure->email->value;
+ $emailfrom = $form->configure->fromemail->value;
+ $owner = $form->configure->owner->value;
+ $is_email_admin = $form->configure->email_admin->value;
+ $is_users_only = $form->configure->users_only->value;
+ $email_template = $form->configure->email_template->value;
+ $select_from = $form->configure->select_allow->selected;
+ favourites_configuration::setEmailAddress($email);
+ favourites_configuration::setEmailAdmin($is_email_admin);
+ favourites_configuration::setFromEmailAddress($emailfrom);
+ favourites_configuration::setOwner($owner);
+ favourites_configuration::setUsersOnly($is_users_only);
+ favourites_configuration::setEmailTemplate($email_template);
+ favourites_configuration::setSelectAllow($select_from);
+ }
+
+ static function replaceStrings($string, $key_values) {
+ // Replace x_y before replacing x.
+ krsort($key_values, SORT_STRING);
+
+ $keys = array();
+ $values = array();
+ foreach ($key_values as $key => $value) {
+ $keys[] = "%$key";
+ $values[] = $value;
+ }
+ return str_replace($keys, $values, $string);
+ }
+
+ static function getEmailAddress(){
+ return module::get_var("favourites","email");
+ }
+
+ static function setEmailAddress($email){
+ module::set_var("favourites","email",$email);
+ }
+
+ static function getOwner(){
+ return module::get_var("favourites","owner");
+ }
+
+ static function setOwner($owner){
+ module::set_var("favourites","owner",$owner);
+ }
+
+ static function getFromEmailAddress(){
+ return module::get_var("favourites","from_email");
+ }
+
+ static function setFromEmailAddress($fromemail){
+ module::set_var("favourites","from_email",$fromemail);
+ }
+
+ static function isEmailAdmin(){
+ return module::get_var("favourites","email_admin");
+ }
+
+ static function setEmailAdmin($email_admin){
+ module::set_var("favourites","email_admin",$email_admin);
+ }
+
+ static function isUsersOnly(){
+ return module::get_var("favourites","users_only");
+ }
+
+ static function setUsersOnly($users_only){
+ module::set_var("favourites","users_only",$users_only);
+ }
+
+ static function getSelectAllow(){
+ return module::get_var("favourites","select_from",1);
+ }
+
+ static function setSelectAllow($select_from){
+ module::set_var("favourites","select_from",$select_from);
+ }
+
+ static function getEmailTemplate(){
+ return module::get_var("favourites","email_template");
+ }
+
+ static function setEmailTemplate($email_template){
+ module::set_var("favourites","email_template",$email_template);
+ }
+
+ static function canSelectAlbums(){
+ return self::getSelectAllow()!=1;
+ }
+
+ static function canSelectItems(){
+ return self::getSelectAllow()!=2;
+ }
+
+}
\ No newline at end of file
diff --git a/modules/favourites/helpers/favourites_event.php b/modules/favourites/helpers/favourites_event.php
new file mode 100644
index 00000000..a96ada02
--- /dev/null
+++ b/modules/favourites/helpers/favourites_event.php
@@ -0,0 +1,34 @@
+add_after("users_groups",
+ Menu::factory("link")
+ ->id("configure_favourites")
+ ->label(t("Favourites"))
+ ->url(url::site("admin/favourites_configure")));
+ }
+
+}
\ No newline at end of file
diff --git a/modules/favourites/helpers/favourites_installer.php b/modules/favourites/helpers/favourites_installer.php
new file mode 100644
index 00000000..91250521
--- /dev/null
+++ b/modules/favourites/helpers/favourites_installer.php
@@ -0,0 +1,37 @@
+css("favourites.css");
+ $theme->script("favourites.js");
+ }
+
+ static function header_top($theme) {
+
+ if (favourites_configuration::isUsersOnly() && identity::active_user()->name =="guest"){
+ return;
+ }
+
+ if ($theme->page_subtype=="favourites"){
+ $view = new View("save_favourites.html");
+ $view->favourites = Favourites::getOrCreate();
+ return $view->render();
+ }
+ else{
+ $view = new View("view_favourites.html");
+ $view->favourites = Favourites::getOrCreate();
+ return $view->render();
+ }
+ }
+
+ static function photo_top($theme){
+ if (!favourites_configuration::canSelectItems() ||
+ (favourites_configuration::isUsersOnly() && identity::active_user()->name =="guest")){
+ return;
+ }
+
+ $view = new View("add_to_favourites.html");
+ $view->item = $theme->item();
+ $view->favourites = Favourites::getOrCreate();
+ return $view->render();
+ }
+
+ static function thumb_top($theme, $item){
+ if (favourites_configuration::isUsersOnly() && identity::active_user()->name =="guest"){
+ return;
+ }
+
+ if (($item->type=="album" && favourites_configuration::canSelectAlbums()) ||
+ ($item->type!="album" && favourites_configuration::canSelectItems())){
+ $view = new View("add_to_favourites.html");
+ $view->item = $item;
+ $view->favourites = Favourites::getOrCreate();
+ return $view->render();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/modules/favourites/images/faves.png b/modules/favourites/images/faves.png
new file mode 100644
index 00000000..ebcccad0
Binary files /dev/null and b/modules/favourites/images/faves.png differ
diff --git a/modules/favourites/js/favourites.js b/modules/favourites/js/favourites.js
new file mode 100644
index 00000000..1eac91a8
--- /dev/null
+++ b/modules/favourites/js/favourites.js
@@ -0,0 +1,30 @@
+$(window).load(function() {
+ var favlink = $("#f-view-link");
+
+ $(".icon-f").each(function(){
+ var elem = $(this);
+ var href = elem.attr("href");
+ function clickFavourite(e){
+ elem.addClass("f-working");
+ $.getJSON(href,function (data){
+ elem.removeClass("f-working");
+ if (data.favourite){
+ elem.addClass("f-selected");
+ elem.attr("title",data.title);
+ }
+ else{
+ elem.removeClass("f-selected");
+ elem.attr("title",data.title);
+ }
+ if (data.hasfavourites){
+ favlink.css('display','block');
+ }else{
+ favlink.css('display','none');
+ }
+
+ });
+ return false;
+ }
+ elem.bind("click",clickFavourite);
+ });
+});
\ No newline at end of file
diff --git a/modules/favourites/libraries/Favourites.php b/modules/favourites/libraries/Favourites.php
new file mode 100644
index 00000000..93af434c
--- /dev/null
+++ b/modules/favourites/libraries/Favourites.php
@@ -0,0 +1,63 @@
+contents as $i => $value) {
+ if ($value==$id){
+ unset($this->contents[$i]);
+ return false;
+ }
+ }
+ $this->contents[]=$id;
+ return true;
+ }
+
+ public function contains($id){
+ foreach ($this->contents as $i => $value){
+ if ($value==$id) return true;
+ }
+ return false;
+ }
+
+ public function hasFavourites(){
+ return !empty($this->contents);
+ }
+
+ public function get_as_album(){
+ return Pseudo_album::create($this);
+ }
+
+ public function clear(){
+ $this->contents = array();
+ }
+
+ public function getUrl(){
+
+ $toReturn = url::site("favourites/view","http");
+
+ foreach ($this->contents as $i => $value){
+ $toReturn = $toReturn."/".$value;
+ }
+ return $toReturn;
+ }
+
+ public static function get(){
+ return Session::instance()->get("favourites");
+ }
+
+
+ public static function getOrCreate(){
+ $session = Session::instance();
+
+ $favourites = $session->get("favourites");
+ if (!$favourites)
+ {
+ $favourites = new Favourites();
+ $session->set("favourites", $favourites);
+ }
+ return $favourites;
+ }
+}
diff --git a/modules/favourites/libraries/Pseudo_album.php b/modules/favourites/libraries/Pseudo_album.php
new file mode 100644
index 00000000..b4372121
--- /dev/null
+++ b/modules/favourites/libraries/Pseudo_album.php
@@ -0,0 +1,396 @@
+favourites = $favourites;
+ // 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;
+ $this->parent_id = 1;
+
+ $this->id = 1;
+ $this->type="album";
+ $this->title=t("Favourites");
+ $this->description=t("Currently selected favourites");
+ }
+
+ public function parent(){
+ return ORM::factory("item")->where("id","=",1)->find();
+ }
+
+ public static function create($favourites)
+ {
+ return new Pseudo_album($favourites);
+ }
+
+ public function loaded(){
+ return true;
+ }
+
+ public function children_count(){
+ return count($this->favourites->contents);
+ }
+
+ public function parents(){
+ return ORM::factory("item")->where("id","=", 1)->find_all();
+ }
+
+ /**
+ * Add a set of restrictions to any following queries to restrict access only to items
+ * viewable by the active user.
+ * @chainable
+ */
+ public function viewable() {
+ return $this;
+ }
+
+ /**
+ * Is this item an album?
+ * @return true if it's an album
+ */
+ public function is_album() {
+ return true;
+ }
+
+ /**
+ * Is this item a photo?
+ * @return true if it's a photo
+ */
+ public function is_photo() {
+ return false;
+ }
+
+ /**
+ * Is this item a movie?
+ * @return true if it's a movie
+ */
+ public function is_movie() {
+ return false;
+ }
+
+ public function delete($ignored_id=null) {
+ }
+
+ /**
+ * Specify the path to the data file associated with this item. To actually associate it,
+ * you still have to call save().
+ * @chainable
+ */
+ public function set_data_file($data_file) {
+ }
+
+ /**
+ * Return the server-relative url to this item, eg:
+ * /gallery3/index.php/BobsWedding?page=2
+ * /gallery3/index.php/BobsWedding/Eating-Cake.jpg
+ *
+ * @param string $query the query string (eg "show=3")
+ */
+ public function url($query=null) {
+ $url = url::site("favourites");
+ if ($query) {
+ $url .= "?$query";
+ }
+ return $url;
+ }
+
+ /**
+ * Return the full url to this item, eg:
+ * http://example.com/gallery3/index.php/BobsWedding?page=2
+ * http://example.com/gallery3/index.php/BobsWedding/Eating-Cake.jpg
+ *
+ * @param string $query the query string (eg "show=3")
+ */
+ public function abs_url($query=null) {
+ $url = url::abs_site("favourites");
+ if ($query) {
+ $url .= "?$query";
+ }
+ return $url;
+ }
+
+ /**
+ * album: /var/albums/album1/album2
+ * photo: /var/albums/album1/album2/photo.jpg
+ */
+ public function file_path() {
+ return VARPATH . "albums/";
+ }
+
+ /**
+ * album: http://example.com/gallery3/var/resizes/album1/
+ * photo: http://example.com/gallery3/var/albums/album1/photo.jpg
+ */
+ public function file_url($full_uri=false) {
+ return;
+ }
+
+ /**
+ * album: /var/resizes/album1/.thumb.jpg
+ * photo: /var/albums/album1/photo.thumb.jpg
+ */
+ public function thumb_path() {
+ }
+
+ /**
+ * Return true if there is a thumbnail for this item.
+ */
+ public function has_thumb() {
+ return false;
+ }
+
+ /**
+ * album: http://example.com/gallery3/var/resizes/album1/.thumb.jpg
+ * photo: http://example.com/gallery3/var/albums/album1/photo.thumb.jpg
+ */
+ public function thumb_url($full_uri=false) {
+ }
+
+ /**
+ * album: /var/resizes/album1/.resize.jpg
+ * photo: /var/albums/album1/photo.resize.jpg
+ */
+ public function resize_path() {
+ }
+
+ /**
+ * album: http://example.com/gallery3/var/resizes/album1/.resize.jpg
+ * photo: http://example.com/gallery3/var/albums/album1/photo.resize.jpg
+ */
+ public function resize_url($full_uri=false) {
+ }
+
+
+ /**
+ * Return the relative path to this item's file. Note that the components of the path are
+ * urlencoded so if you want to use this as a filesystem path, you need to call urldecode
+ * on it.
+ * @return string
+ */
+ public function relative_path() {
+ if (!$this->loaded()) {
+ return;
+ }
+
+ if (!isset($this->relative_path_cache)) {
+ $this->_build_relative_caches()->save();
+ }
+ return $this->relative_path_cache;
+ }
+
+ /**
+ * Return the relative url to this item's file.
+ * @return string
+ */
+ public function relative_url() {
+ }
+
+
+ /**
+ * Handle any business logic necessary to create or modify an item.
+ * @see ORM::save()
+ *
+ * @return ORM Item_Model
+ */
+ public function save() {
+ }
+
+ /**
+ * Return the Item_Model representing the cover for this album.
+ * @return Item_Model or null if there's no cover
+ */
+ public function album_cover() {
+ return null;
+ }
+
+ /**
+ * Find the position of the given child id in this album. The resulting value is 1-indexed, so
+ * the first child in the album is at position 1.
+ */
+ public function get_position($child, $where=array()) {
+ /*
+ if ($this->sort_order == "DESC") {
+ $comp = ">";
+ } else {
+ $comp = "<";
+ }
+ $db = db::build();
+
+ // If the comparison column has NULLs in it, we can't use comparators on it and will have to
+ // deal with it the hard way.
+ $count = $db->from("items")
+ ->where("parent_id", "=", $this->id)
+ ->where($this->sort_column, "IS", null)
+ ->merge_where($where)
+ ->count_records();
+
+ if (empty($count)) {
+ // There are no NULLs in the sort column, so we can just use it directly.
+ $sort_column = $this->sort_column;
+
+ $position = $db->from("items")
+ ->where("parent_id", "=", $this->id)
+ ->where($sort_column, $comp, $child->$sort_column)
+ ->merge_where($where)
+ ->count_records();
+
+ // We stopped short of our target value in the sort (notice that we're using a < comparator
+ // above) because it's possible that we have duplicate values in the sort column. An
+ // equality check would just arbitrarily pick one of those multiple possible equivalent
+ // columns, which would mean that if you choose a sort order that has duplicates, it'd pick
+ // any one of them as the child's "position".
+ //
+ // Fix this by doing a 2nd query where we iterate over the equivalent columns and add them to
+ // our base value.
+ foreach ($db
+ ->select("id")
+ ->from("items")
+ ->where("parent_id", "=", $this->id)
+ ->where($sort_column, "=", $child->$sort_column)
+ ->merge_where($where)
+ ->order_by(array("id" => "ASC"))
+ ->execute() as $row) {
+ $position++;
+ if ($row->id == $child->id) {
+ break;
+ }
+ }
+ } else {
+ // There are NULLs in the sort column, so we can't use MySQL comparators. Fall back to
+ // iterating over every child row to get to the current one. This can be wildly inefficient
+ // for really large albums, but it should be a rare case that the user is sorting an album
+ // with null values in the sort column.
+ //
+ // Reproduce the children() functionality here using Database directly to avoid loading the
+ // whole ORM for each row.
+ $order_by = array($this->sort_column => $this->sort_order);
+ // Use id as a tie breaker
+ if ($this->sort_column != "id") {
+ $order_by["id"] = "ASC";
+ }
+
+ $position = 0;
+ foreach ($db->select("id")
+ ->from("items")
+ ->where("parent_id", "=", $this->id)
+ ->merge_where($where)
+ ->order_by($order_by)
+ ->execute() as $row) {
+ $position++;
+ if ($row->id == $child->id) {
+ break;
+ }
+ }
+ }
+
+ return $position;*/
+ }
+
+ /**
+ * Return an
tag for the thumbnail.
+ * @param array $extra_attrs Extra attributes to add to the img tag
+ * @param int (optional) $max Maximum size of the thumbnail (default: null)
+ * @param boolean (optional) $center_vertically Center vertically (default: false)
+ * @return string
+ */
+ public function thumb_img($extra_attrs=array(), $max=null, $center_vertically=false) {
+ return "";
+ }
+
+ /**
+ * Calculate the largest width/height that fits inside the given maximum, while preserving the
+ * aspect ratio.
+ * @param int $max Maximum size of the largest dimension
+ * @return array
+ */
+ public function scale_dimensions($max) {
+ }
+
+ /**
+ * Return an
tag for the resize.
+ * @param array $extra_attrs Extra attributes to add to the img tag
+ * @return string
+ */
+ public function resize_img($extra_attrs) {
+ }
+
+ /**
+ * Return a flowplayer