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..8d0c50be
--- /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);
+
+ print json_encode(array("result" => "success","location" => url::site("favourites")));
+ return;
+ }
+ print json_encode(array("result" => "error", "form" => (string) $form));
+ }
+
+ public function toggle_favourites($id){
+ $favourites = Favourites::getOrCreate();
+ $infavour = $favourites ->toggle($id);
+ $title = $infavour?t("Remove from favourites"):t("Add to favourites");
+ print json_encode(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