summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/config/config.php1
-rw-r--r--core/controllers/welcome.php27
-rw-r--r--core/helpers/album.php54
-rw-r--r--core/helpers/core_installer.php21
-rw-r--r--core/helpers/photo.php65
-rw-r--r--core/libraries/ORM_MPTT.php142
-rw-r--r--core/models/item.php45
-rw-r--r--core/tests/Album_Test.php47
-rw-r--r--core/tests/Core_Installer_Test.php7
-rw-r--r--core/tests/File_Structure_Test.php1
-rw-r--r--core/tests/Item_Test.php29
-rw-r--r--core/tests/Photo_Test.php57
-rw-r--r--core/tests/test.jpgbin0 -> 6232 bytes
-rw-r--r--core/views/welcome.html.php39
-rw-r--r--modules/mptt/libraries/MPTT.php1187
-rw-r--r--themes/default/images/carousel.pngbin0 -> 15631 bytes
-rw-r--r--themes/default/views/footer.html.php8
-rw-r--r--themes/default/views/photo.html.php64
-rw-r--r--themes/default/views/sidebar.html.php159
19 files changed, 605 insertions, 1348 deletions
diff --git a/core/config/config.php b/core/config/config.php
index 5ab35a0e..de872455 100644
--- a/core/config/config.php
+++ b/core/config/config.php
@@ -120,7 +120,6 @@ $config['modules'] = array
(
MODPATH . 'gallery_unit_test',
MODPATH . 'unit_test',
- MODPATH . 'mptt',
MODPATH . 'forge',
THEMEPATH . 'default',
diff --git a/core/controllers/welcome.php b/core/controllers/welcome.php
index f1201cff..a5719cf0 100644
--- a/core/controllers/welcome.php
+++ b/core/controllers/welcome.php
@@ -42,6 +42,33 @@ class Welcome_Controller extends Template_Controller {
url::redirect("welcome");
}
+ function add($count) {
+ srand(time());
+ $parents = ORM::factory("item")->where("type", "album")->find_all()->as_array();
+ for ($i = 0; $i < $count; $i++) {
+ $parent = $parents[array_rand($parents)];
+ switch(rand(0, 1)) {
+ case 0:
+ $album = album::create($parent->id, "rnd_" . rand(), "Rnd $i", "rnd $i");
+ $parents[] = $album;
+ break;
+
+ case 1:
+ photo::create($parent->id, DOCROOT . "themes/default/images/thumbnail.jpg",
+ "thumbnail.jpg", "rnd_" . rand(), "sample thumbnail");
+ break;
+ }
+
+ print "$i ";
+ if (!($i % 100)) {
+ set_time_limit(30);
+ }
+ }
+ print "<br/>";
+ print html::anchor("welcome", "return");
+ $this->auto_render = false;
+ }
+
private function _get_config_errors() {
$errors = array();
if (!file_exists(VARPATH)) {
diff --git a/core/helpers/album.php b/core/helpers/album.php
new file mode 100644
index 00000000..415e654c
--- /dev/null
+++ b/core/helpers/album.php
@@ -0,0 +1,54 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2008 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * This is the API for handling albums.
+ *
+ * Note: by design, this class does not do any permission checking.
+ */
+class Album_Core {
+ /**
+ * Create a new album.
+ * @param integer $parent_id id of parent album
+ * @param string $name the name of this new album (it will become the directory name on disk)
+ * @param integer $title the title of the new album
+ * @param string $description (optional) the longer description of this album
+ * @return Item_Model
+ */
+ static function create($parent_id, $name, $title, $description=null) {
+ $album = ORM::factory("item");
+ $album->type = "album";
+ $album->title = $title;
+ $album->description = $description;
+ $album->name = $name;
+
+ while (ORM::Factory("item")
+ ->where("parent_id", $parent_id)
+ ->where("name", $album->name)
+ ->find()->id) {
+ $album->name = "{$name}-" . rand();
+ }
+
+ $album = $album->add_to_parent($parent_id);
+ mkdir($album->path());
+ mkdir($album->thumbnail_path());
+ return $album;
+ }
+}
diff --git a/core/helpers/core_installer.php b/core/helpers/core_installer.php
index 5720976b..d100e0d1 100644
--- a/core/helpers/core_installer.php
+++ b/core/helpers/core_installer.php
@@ -41,14 +41,14 @@ class core_installer {
$db->query("CREATE TABLE `items` (
`id` int(9) NOT NULL auto_increment,
- `type` char(32) default NULL,
+ `type` char(32) NOT NULL,
`title` char(255) default NULL,
`description` char(255) default NULL,
- `path` char(255) default NULL,
- `left` int(9) default NULL,
- `right` int(9) default NULL,
- `parent_id` int(9) default NULL,
- `scope` int(9) default NULL,
+ `name` char(255) default NULL,
+ `left` int(9) NOT NULL,
+ `right` int(9) NOT NULL,
+ `parent_id` int(9) NOT NULL,
+ `level` int(9) NOT NULL,
PRIMARY KEY (`id`),
KEY `parent_id` (`parent_id`),
KEY `type` (`type`))
@@ -64,9 +64,14 @@ class core_installer {
$core->save();
$root = ORM::factory("item");
+ $root->type = 'album';
$root->title = "Gallery";
$root->description = "Welcome to your Gallery3";
- $root->make_root();
+ $root->left = 1;
+ $root->right = 2;
+ $root->parent_id = 0;
+ $root->level = 1;
+ $root->save();
}
}
@@ -74,5 +79,7 @@ class core_installer {
$db = Database::instance();
$db->query("DROP TABLE IF EXISTS `items`;");
$db->query("DROP TABLE IF EXISTS `modules`;");
+ system("/bin/rm -rf " . VARPATH . "albums");
+ system("/bin/rm -rf " . VARPATH . "thumbnails");
}
}
diff --git a/core/helpers/photo.php b/core/helpers/photo.php
new file mode 100644
index 00000000..e796ef03
--- /dev/null
+++ b/core/helpers/photo.php
@@ -0,0 +1,65 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2008 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * This is the API for handling photos.
+ *
+ * Note: by design, this class does not do any permission checking.
+ */
+class Photo_Core {
+ /**
+ * Create a new photo.
+ * @param integer $parent_id id of parent album
+ * @param string $filename path to the photo file on disk
+ * @param string $name the filename to use for this photo in the album
+ * @param integer $title the title of the new photo
+ * @param string $description (optional) the longer description of this photo
+ * @return Item_Model
+ */
+ static function create($parent_id, $filename, $name, $title, $description=null) {
+ $photo = ORM::factory("item");
+ $photo->type = "photo";
+ $photo->title = $title;
+ $photo->description = $description;
+ $photo->name = $name;
+
+ $pi = pathinfo(basename($filename));
+ if (empty($pi["extension"])) {
+ throw new Exception("@todo UNKNOWN_FILE_TYPE");
+ }
+
+ while (ORM::Factory("item")
+ ->where("parent_id", $parent_id)
+ ->where("name", $photo->name)
+ ->find()->id) {
+ $photo->name = rand() . "." . $pi["extension"];
+ }
+
+ $photo->add_to_parent($parent_id);
+
+ copy($filename, $photo->path());
+
+ /** @todo: parameterize these values */
+ $image = Image::factory($filename);
+ $image->resize(200, 140, Image::WIDTH)->save($photo->thumbnail_path());
+ $image->resize(800, 600, Image::WIDTH)->save($photo->resize_path());
+ return $photo;
+ }
+}
diff --git a/core/libraries/ORM_MPTT.php b/core/libraries/ORM_MPTT.php
new file mode 100644
index 00000000..6d3478ad
--- /dev/null
+++ b/core/libraries/ORM_MPTT.php
@@ -0,0 +1,142 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2008 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+/**
+ * Implement Modified Preorder Tree Traversal on top of ORM.
+ *
+ * MPTT is an efficient way to store and retrieve hierarchical data in a single database table.
+ * For a good description, read http://www.sitepoint.com/article/hierarchical-data-database/3/
+ *
+ * This code was heavily influenced by code from:
+ * - http://code.google.com/p/kohana-mptt/
+ * - http://code.google.com/p/kohana-mptt/wiki/Documentation
+ * - http://code.google.com/p/s7ncms/source/browse/trunk/modules/s7ncms/libraries/ORM_MPTT.php
+ *
+ * Unfortunately that code was not ready for production and I did not want to absorb their code
+ * and licensing issues so I've reimplemented just the features that we need.
+ */
+class ORM_MPTT_Core extends ORM {
+ private $model_name = null;
+ private $parent = null;
+ private $parents = null;
+ private $children = null;
+
+ function __construct($id=null) {
+ parent::__construct($id);
+ $this->model_name = inflector::singular($this->table_name);
+ }
+
+ /**
+ * Add this node as a child of the parent provided.
+ *
+ * @param integer $parent_id the id of the parent node
+ * @return ORM
+ */
+ function add_to_parent($parent_id) {
+ $this->_lock();
+
+ try {
+ $parent = ORM::factory($this->model_name, $parent_id);
+ $parent->_grow();
+ $this->left = $parent->right - 2;
+ $this->right = $parent->right - 1;
+ $this->parent_id = $parent->id;
+ $this->level = $parent->level + 1;
+ $this->save();
+ } catch (Exception $e) {
+ $this->_unlock();
+ throw $e;
+ }
+
+ $this->_unlock();
+ return $this;
+ }
+
+ /**
+ * Return the parent of this node
+ *
+ * @return ORM
+ */
+ function parent() {
+ if (!isset($this->parent)) {
+ $this->parent =
+ ORM::factory($this->model_name)->where("id", $this->parent_id)->find();
+ }
+ return $this->parent;
+ }
+
+ /**
+ * Return all the parents of this node, in order from root to leaf.
+ *
+ * @return array ORM
+ */
+ function parents() {
+ if (!isset($this->parents)) {
+ $this->parents = $this->where("`left` <= {$this->left}")
+ ->where("`right` >= {$this->right}")
+ ->orderby("left", "ASC")
+ ->find_all();
+ }
+ return $this->parents;
+ }
+
+ /**
+ * Return all of the children of this node, unordered.
+ *
+ * @return array ORM
+ */
+ function children() {
+ if (!isset($this->children)) {
+ $this->children =
+ $this->where("parent_id", $this->id)->find_all();
+ }
+ return $this->children;
+ }
+
+ /**
+ * Grow this node's space enough to make room for 1 or more new nodes.
+ *
+ * @param integer $count the number of new nodes to add
+ */
+ private function _grow($count=1) {
+ $size = $count * 2;
+ $this->db->query(
+ "UPDATE `{$this->table_name}` SET `left` = `left` + $size WHERE `left` >= {$this->right}");
+ $this->db->query(
+ "UPDATE `{$this->table_name}` SET `right` = `right` + $size WHERE `right` >= {$this->right}");
+ $this->right += 2;
+ }
+
+ /**
+ * Lock the tree to prevent concurrent modification.
+ */
+ private function _lock() {
+ $result = $this->db->query("SELECT GET_LOCK('{$this->table_name}', 1) AS L")->current();
+ if (empty($result->L)) {
+ throw new Exception("@todo UNABLE_TO_LOCK_EXCEPTION");
+ }
+ }
+
+ /**
+ * Unlock the tree.
+ */
+ private function _unlock() {
+ $this->db->query("SELECT RELEASE_LOCK('{$this->table_name}')");
+ }
+}
diff --git a/core/models/item.php b/core/models/item.php
index 8b08b699..3d5f08a2 100644
--- a/core/models/item.php
+++ b/core/models/item.php
@@ -17,9 +17,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
-class Item_Model extends MPTT {
- protected $left_column = "left";
- protected $right_column = "right";
+class Item_Model extends ORM_MPTT {
+ protected $children = 'items';
public function is_album() {
return $this->type == 'album';
@@ -29,13 +28,39 @@ class Item_Model extends MPTT {
return $this->type == 'photo';
}
- // MPTT::get_children returns null if there are no children; change that to an empty array for
- // consistency.
- public function get_children() {
- $children = parent::get_children();
- if (empty($children)) {
- $children = array();
+ private function _get_path() {
+ $paths = array();
+ foreach ($this->parents() as $parent) {
+ if ($parent->id > 1) {
+ $paths[] = $parent->name;
+ }
+ }
+ $path = implode($paths, "/");
+ if (!$this->saved) {
+ $path .= $this->name;
+ }
+ return $path;
+ }
+
+ public function path() {
+ return VARPATH . "albums/{$this->_get_path()}";
+ }
+
+ public function thumbnail_path() {
+ if ($this->is_album()) {
+ return VARPATH . "thumbnails/{$this->_get_path()}";
+ } else {
+ $pi = pathinfo(VARPATH . "thumbnails/{$this->_get_path()}");
+ return "{$pi['dirname']}/{$pi['filename']}_thumb.{$pi['extension']}";
+ }
+ }
+
+ public function resize_path() {
+ if ($this->is_album()) {
+ return VARPATH . "thumbnails/{$this->_get_path()}";
+ } else {
+ $pi = pathinfo(VARPATH . "thumbnails/{$this->_get_path()}");
+ return "{$pi['dirname']}/{$pi['filename']}_resize.{$pi['extension']}";
}
- return $children;
}
}
diff --git a/core/tests/Album_Test.php b/core/tests/Album_Test.php
new file mode 100644
index 00000000..52ee4833
--- /dev/null
+++ b/core/tests/Album_Test.php
@@ -0,0 +1,47 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2008 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class Album_Test extends Unit_Test_Case {
+ public function create_album_test() {
+ $rand = rand();
+ $album = album::create(1, $rand, $rand, $rand);
+
+ $this->assert_equal(VARPATH . "albums/$rand", $album->path());
+ $this->assert_equal(VARPATH . "thumbnails/$rand", $album->thumbnail_path());
+ $this->assert_equal(VARPATH . "thumbnails/$rand", $album->resize_path());
+
+ $this->assert_true(is_dir($album->path()), "missing path: {$album->path()}");
+ $this->assert_true(is_dir($album->resize_path()), "missing path: {$album->resize_path()}");
+
+ $this->assert_equal(1, $album->parent_id); // MPTT tests will cover other hierarchy checks
+ $this->assert_equal($rand, $album->name);
+ $this->assert_equal($rand, $album->title);
+ $this->assert_equal($rand, $album->description);
+
+ $this->assert_equal($album->parent()->right - 2, $album->left);
+ $this->assert_equal($album->parent()->right - 1, $album->right);
+ }
+
+ public function create_conflicting_album_test() {
+ $rand = rand();
+ $album1 = album::create(1, $rand, $rand, $rand);
+ $album2 = album::create(1, $rand, $rand, $rand);
+ $this->assert_true($album1->name != $album2->name);
+ }
+}
diff --git a/core/tests/Core_Installer_Test.php b/core/tests/Core_Installer_Test.php
index 7758f472..4903805b 100644
--- a/core/tests/Core_Installer_Test.php
+++ b/core/tests/Core_Installer_Test.php
@@ -40,11 +40,14 @@ class Core_Installer_Test extends Unit_Test_Case {
}
public function install_creates_root_item_test() {
+ $max_right =
+ Database::instance()->query("SELECT MAX(`right`) AS `right` FROM items")->current()->right;
+
$root = ORM::factory('item')->find(1);
$this->assert_equal("Gallery", $root->title);
$this->assert_equal(1, $root->left);
- $this->assert_equal(2, $root->right);
+ $this->assert_equal($max_right, $root->right);
$this->assert_equal(null, $root->parent_id);
- $this->assert_equal(1, $root->scope);
+ $this->assert_equal(1, $root->level);
}
}
diff --git a/core/tests/File_Structure_Test.php b/core/tests/File_Structure_Test.php
index 00663bc6..d3f4ae23 100644
--- a/core/tests/File_Structure_Test.php
+++ b/core/tests/File_Structure_Test.php
@@ -110,6 +110,7 @@ class GalleryCodeFilterIterator extends FilterIterator {
strstr($path_name, MODPATH . 'forge') !== false ||
strstr($path_name, MODPATH . 'unit_test') !== false ||
strstr($path_name, MODPATH . 'mptt') !== false ||
+ strstr($path_name, MODPATH . 'kodoc') !== false ||
strstr($path_name, DOCROOT . 'var') !== false ||
strstr($path_name, DOCROOT . 'test') !== false);
}
diff --git a/core/tests/Item_Test.php b/core/tests/Item_Test.php
deleted file mode 100644
index d077932f..00000000
--- a/core/tests/Item_Test.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php defined("SYSPATH") or die("No direct script access.");
-/**
- * Gallery - a web based photo album viewer and editor
- * Copyright (C) 2000-2008 Bharat Mediratta
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
- */
-class Item_Test extends Unit_Test_Case {
- public function create_item_test() {
- ORM::factory('item');
- }
-
- public function create_root_item_test() {
- $root = ORM::factory('item')->find(1);
- $this->assert_equal("Gallery", $root->title);
- }
-}
diff --git a/core/tests/Photo_Test.php b/core/tests/Photo_Test.php
new file mode 100644
index 00000000..8b0a48cc
--- /dev/null
+++ b/core/tests/Photo_Test.php
@@ -0,0 +1,57 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2008 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class Photo_Test extends Unit_Test_Case {
+ public function create_photo_test() {
+ $rand = rand();
+ $photo = photo::create(1, DOCROOT . "core/tests/test.jpg", "$rand.jpg", $rand, $rand);
+
+ $this->assert_equal(VARPATH . "albums/$rand.jpg", $photo->path());
+ $this->assert_equal(VARPATH . "thumbnails/{$rand}_thumb.jpg", $photo->thumbnail_path());
+ $this->assert_equal(VARPATH . "thumbnails/{$rand}_resize.jpg", $photo->resize_path());
+
+ $this->assert_true(is_file($photo->path()), "missing: {$photo->path()}");
+ $this->assert_true(is_file($photo->resize_path()), "missing: {$photo->resize_path()}");
+ $this->assert_true(is_file($photo->thumbnail_path()), "missing: {$photo->thumbnail_path()}");
+
+ $this->assert_equal(1, $photo->parent_id); // MPTT tests will cover other hierarchy checks
+ $this->assert_equal("$rand.jpg", $photo->name);
+ $this->assert_equal($rand, $photo->title);
+ $this->assert_equal($rand, $photo->description);
+
+ $this->assert_equal($photo->parent()->right - 2, $photo->left);
+ $this->assert_equal($photo->parent()->right - 1, $photo->right);
+ }
+
+ public function create_conflicting_photo_test() {
+ $rand = rand();
+ $photo1 = photo::create(1, DOCROOT . "core/tests/test.jpg", "$rand.jpg", $rand, $rand);
+ $photo2 = photo::create(1, DOCROOT . "core/tests/test.jpg", "$rand.jpg", $rand, $rand);
+ $this->assert_true($photo1->name != $photo2->name);
+ }
+
+ public function create_photo_with_no_extension_test() {
+ try {
+ photo::create(1, "unknown_file", "name", "title", "description");
+ $this->assert_false("should fail with an exception");
+ } catch (Exception $e) {
+ // pass
+ }
+ }
+}
diff --git a/core/tests/test.jpg b/core/tests/test.jpg
new file mode 100644
index 00000000..1f3525e5
--- /dev/null
+++ b/core/tests/test.jpg
Binary files differ
diff --git a/core/views/welcome.html.php b/core/views/welcome.html.php
index b7a290a0..3bc85dc4 100644
--- a/core/views/welcome.html.php
+++ b/core/views/welcome.html.php
@@ -26,7 +26,7 @@
}
p {
- margin: 0 0 1em 0;
+ margin: 0 0 0 0;
padding-left: 1em;
}
@@ -59,6 +59,18 @@
ul {
margin-top: -.25em;
}
+
+ ul.choices {
+ padding-top: 0;
+ padding-left: 1em;
+ margin: 0px;
+ }
+
+ ul.choices li {
+ display: inline;
+ list-stype-type: none;
+ padding: 0px;
+ }
</style>
</head>
<body>
@@ -72,24 +84,25 @@
This is
a <b><a href="http://www.google.com/images?q=scaffold">scaffold</a></b>:
a <i>temporary structure built to support the developers as
- they create the real product</i>.
- </p>
-
- <p>
- As we flesh out Gallery 3, we'll make it possible for you to
- peer inside and see the application taking shape.
- Eventually, this page will go away and you'll start in the
- application itself. In the meantime, here are some useful
- links to get you started.
+ they create the real product</i>. As we flesh out Gallery 3,
+ we'll make it possible for you to peer inside and see the
+ application taking shape. Eventually, this page will go
+ away and you'll start in the application itself. In the
+ meantime, here are some useful links to get you started.
</p>
<h2>System Configuration</h2>
<?= $syscheck ?>
<h2>Activities</h2>
- <p>
- <?= html::anchor("album/1", "Browse Gallery") ?>
- </p>
+ <p> <?= html::anchor("album/1", "Browse Gallery") ?> </p>
+ <ul class="choices">
+ <li> add: [</li>
+ <? foreach (array(1, 10, 50, 100, 500, 1000) as $count): ?>
+ <li> <?= html::anchor("welcome/add/$count", "$count") ?> </li>
+ <? endforeach ?>
+ <li>] photos and albums </li>
+ </ul>
<h2>Documentation</h2>
<ul>
diff --git a/modules/mptt/libraries/MPTT.php b/modules/mptt/libraries/MPTT.php
deleted file mode 100644
index 84182a90..00000000
--- a/modules/mptt/libraries/MPTT.php
+++ /dev/null
@@ -1,1187 +0,0 @@
-<?php
-
-/**
-* File: libraries/MPTT.php
-*
-* An implementation of Joe Celko's Nested Sets as a Kohana model with ORM support.
-*
-*
-* Many thanks to
-* * Thunder who supplied a similar class for Code Igniter and gave permission to me
-* to release it under whatever license I deem necessary:
-* http://www.codeigniter.com/wiki/Nested_Sets/
-* * mpatek, his class was the initial start
-* http://bakery.cakephp.org/articles/view/modified-preorder-tree-traversal-component
-* * Propel, for inspiring some methods and the parent_id and scope stuff
-*
-* MPTT class
-* author - dlib
-* license - BSD
-*/
-
-class MPTT extends ORM {
-
- public $children;
-
- public $parent;
-
- protected $left_column = 'lft';
-
- protected $right_column = 'rgt';
-
- protected $parent_column = 'parent_id';
-
- protected $scope_column = 'scope';
-
- protected $_scope = 1;
-
- /**
- * Patch through to ORM construct
- *
- * @return void
- */
- public function __construct($id = FALSE)
- {
- parent::__construct($id);
-
- if (!empty($id))
- {
- //Set the right scope on new objects
- $scope_column=$this->scope_column;
- $this->set_scope($this->$scope_column);
- $this->where='';
- }
-
-
- }
-
- //////////////////////////////////////////
- // Lock functions
- //////////////////////////////////////////
-
- /**
- * Locks tree table
- * This is a straight write lock - the database blocks until the previous lock is released
- */
- protected function lock_tree($aliases = array())
- {
- $sql = "LOCK TABLE " . $this->table . " WRITE";
- return self::$db->query($sql);
- }
-
- /**
- * Unlocks tree table
- * Releases previous lock
- */
- protected function unlock_tree()
- {
- $sql = "UNLOCK TABLES";
- return self::$db->query($sql);
- }
-
- /**
- * Bit of an odd function since the node is supplied
- * supply a node object and it will return a whole bunch of descendants
- * @return tree object
- * @param $root_node mixed
-
- */
- public function get_tree($root_node)
- {
-
- $lft_col = $this->left_column;
- $rgt_col = $this->right_column;
-
- if(is_object($root_node))
- {
- $root=$root_node;
- }
- else
- {
- $root=$this->get_node($root_node);
- }
-
- $children=$this->new_node();
- $children->where('`'.$lft_col.'`>'.$root->$lft_col.' AND `'.$rgt_col.'`<'.$root->$rgt_col);
- $children->where($this->scope_column,$this->get_scope());
- $children->orderby($lft_col,'ASC');
- $children=$children->find_all();
-
- if(count($children)>0)
- {
-
- $parent=$root;
- $parent->children=array();
-
- foreach($children as $child_data)
- {
-
- $child=$child_data;
- $child->children=array();
- $child->parent=$parent;
- $child->scope=$this->get_scope();
-
- while(!$this->_is_descendant_of($child, $parent))
- {
- $parent = $parent->parent;
- }
-
- $parent->children[]=$child;
- $parent=$child;
-
- }
- }
-
- return $root;
- }
- /*
- * *****************
- * Retrieval methods
- * *****************
- */
- /**
- * Current object will obtain its children
- * @see http://trac.symfony-project.com/wiki/sfPropelActAsNestedSetBehaviorPlugin
- * @see http://www.phpriot.com/articles/nested-trees-2/5
- * @return
- */
- public function get_children($return=false)
- {
- if(!$this->has_descendants())
- return false;
-
- $parent_id=$this->id;
-
- $this->children=array();
- $children=$this->new_node();
- $children->where($this->parent_column,$parent_id);
- $children->where($this->scope_column,$this->get_scope());
- $children->orderby($this->left_column);
-
- foreach($children->find_all() as $child)
- {
- $child->parent=$this;
-
- $this->children[]=$child;
- }
- if($return== true)
- {
- return $this->children;
- }
- return $this;
- }
-
- /**
- * The current object will obtain all descendants
- * @return ORM object
- * @param $node_id Object
- */
- public function get_descendants()
- {
- if($this->has_descendants())
- return $this->get_tree($this);
- }
- /**
- * Return an array of all leaves in the entire tree
- *
- * @return array of ORM objects
- */
- public function get_leaves()
- {
-
- $lft_col = $this->left_column;
- $rgt_col = $this->right_column;
-
- $leaves=$this->new_node();
- $leaves->where($this->scope_column,$this->get_scope());
- $leaves->where($rgt_col.' = '.$lft_col . ' + 1');
-
- return $leaves->find_all();
- }
- /**
- * Get the path leading up to the current node
- * @return array with ORM objects
- *
- */
- public function get_path()
- {
-
- $lft_col = $this->left_column;
- $rgt_col = $this->right_column;
-
- $path=$this->new_node();
- $path->where($this->scope_column,$this->get_scope());
- $path->where($lft_col . ' <= '.$this->$lft_col . ' AND ' . $rgt_col . ' >=' .$this->$rgt_col . ' ORDER BY '.$lft_col);
-
-
- return $path->find_all();
-
- }
-
- /**
- * Returns the root node
- * @return array $resultNode The node returned
- */
- function get_root()
- {
- return $this->get_node_where('`'.$this->left_column . '` = 1 ');
- }
- /**
- * Returns a node by id
- * @return object
- * @param $node_id integer [optional]
- */
- function get_node($node_id)
- {
- $scope_column=$this->scope_column;
- $class = get_class($this);
- $node=new $class();
-
- $node=$node->find($node_id,true);
-
- return $node;
- }
- /**
- * Returns a new empty node
- * @return object
- * @param $node_id integer [optional]
- */
- function new_node(){
-
- $class = get_class($this);
- $node=new $class();
- return $node;
- }
- /**
- * Returns one node with where condition
- * @return object
- * @param $node_id integer [optional]
- */
- function get_node_where($where)
- {
- $scope_column=$this->scope_column;
- $class = get_class($this);
- $node = new $class();
- $node->where($where);
- $node->where($this->scope_column,$this->get_scope());
-
- $node=$node->find(false,false);
- return $node;
- }
- /**
- * Returns the first child node of the given parentNode
- *
- * @return array $resultNode The first child of the parent node supplied
- */
- function get_first_child()
- {
- $lft_col = $this->left_column;
-
- return $this->get_node_where($this->left_column . " = " . ($this->$lft_col+1));
- }
-
- /**
- * Returns the last child node of the given parentNode
- *
- * @return array $resultNode the last child of the parent node supplied
- */
- function get_last_child()
- {
- $rgt_col = $this->right_column;
-
- return $this->get_node_where($this->right_column . " = " . ($this->$rgt_col-1));
- }
-
- /**
- * Returns the node that is the immediately prior sibling of the given node
- *
- * @return array $resultNode The node returned
- */
- function get_prev_sibling()
- {
- $lft_col = $this->left_column;
-
- return $this->get_node_where($this->right_column . " = " . ($this->$lft_col-1));
- }
-
- /**
- * Returns the node that is the next sibling of the given node
- *
- * @return array $resultNode The node returned
- */
- function get_next_sibling()
- {
- $rgt_col = $this->right_column;
-
- return $this->get_node_where($this->left_column . " = " . ($this->$rgt_col+1));
- }
- /**
- * Returns the node that represents the parent of the given node
- *
- * @return array $resultNode the node returned
- */
- function get_parent()
- {
-
- $leftcol = $this->left_column;
- $rightcol = $this->right_column;
-
- $whereArg = " $leftcol < " . $this->$leftcol .
- " AND $rightcol > " . $this->$rightcol .
- " ORDER BY $rightcol ASC";
- return $this->get_node_where($whereArg);
- }
-/*
- * *****************
- * Modifying methods
- * *****************
- */
- /**
- * Adds the first entry to the table (only call once in an empty table) else corruption will follow
- * @return $node an array of left and right values
- */
- function make_root()
- {
- $lft_col = $this->left_column;
- $rgt_col = $this->right_column;
- $scp_col=$this->scope_column;
-
- if(is_numeric($this->$lft_col) )
- {
- Log::add('error', 'Cannot make existing node root' );
- //existing nodes cannot become root
- return false;
- }
-
- $this->$lft_col=1;
- $this->$rgt_col=2;
- $this->$scp_col=$this->get_scope();
-
- $this->save_node();
-
- return $this;
- }
- /**
- * Not yet implemented
- *
- */
- function insert_as_parent_of($child_node)
- {
-
- }
- /**
- * inserts a the object node as the first child of the supplied parent node
- * @param array $parentNode The node array of the parent to use
- *
- * @return
- */
- function insert_as_first_child_of($parent_node)
- {
- $lft_col = $this->left_column;
- $rgt_col = $this->right_column;
- $scp_col=$this->scope_column;
- $parent_column=$this->parent_column;
-
- //Set parent id (id of the parent, is childs parent id)
- $this->$parent_column=$parent_node->id;
-
- $this->$lft_col=$parent_node->$lft_col+1;
- $this->$rgt_col=$parent_node->$lft_col+2;
- //Get scope from current object (obsolete)
- $this->$scp_col=$this->get_scope();
-
- $this->lock_tree();
- $this->modify_node($this->$lft_col,2);
- $this->save_node();
- $this->unlock_tree();
-
- return $this;
- }
- /**
- * Same as insertNewChild except the new node is added as the last child
- * @param array $parentNode The node array of the parent to use
- *
- * @return
- */
- function insert_as_last_child_of($parent_node)
- {
- $lft_col = $this->left_column;
- $rgt_col = $this->right_column;
- $scp_col=$this->scope_column;
- $parent_column=$this->parent_column;
-
- //Set parent id (id of the parent, is childs parent id)
- $this->$parent_column=$parent_node->id;
-
- $this->$lft_col=$parent_node->$rgt_col;
- $this->$rgt_col=$parent_node->$rgt_col+1;
- $this->$scp_col=$this->get_scope();
-
- $this->lock_tree();
- $this->modify_node($this->$lft_col,2);
- $this->save_node();
- $this->unlock_tree();
-
- return $this;
- }
- /**
- * Adds a new node to the left of the supplied focusNode
- * @param array $focusNode The node to use as the position marker
- *
- * @return
- */
- function insert_as_prev_sibling_of($focus_node)
- {
- $lft_col = $this->left_column;
- $rgt_col = $this->right_column;
- $parent_column=$this->parent_column;
- $scp_col=$this->scope_column;
-
- //Set parent id (siblings have the same parent)
- $this->$parent_column=$focus_node->$parent_column;
-
- $this->$lft_col=$focus_node->$lft_col;
- $this->$rgt_col=$focus_node->$lft_col+1;
- $this->$scp_col=$this->get_scope();
-
- $this->lock_tree();
- $this->modify_node($this->$lft_col,2);
- $this->save_node();
- $this->unlock_tree();
-
- return $this;
- }
- /**
- * Adds a new node to the right of the supplied focusNode
- * @param array $focusNode The node to use as the position marker
- *
- * @return
- */
- function insert_as_next_sibling_of($focus_node)
- {
- $lft_col = $this->left_column;
- $rgt_col = $this->right_column;
- $parent_column=$this->parent_column;
- $scp_col=$this->scope_column;
-
- //Set parent id (siblings have the same parent)
- $this->$parent_column=$focus_node->$parent_column;
-
- $this->$lft_col=$focus_node->$rgt_col+1;
- $this->$rgt_col=$focus_node->$rgt_col+2;
- $this->$scp_col=$this->get_scope();
-
- $this->lock_tree();
- $this->modify_node($this->$lft_col,2);
- $this->save_node();
- $this->unlock_tree();
-
- return $this;
- }
- /**
- * Why not, kill the entire tree
- *
- * @return
- */
- function delete_tree()
- {
- $where=array($this->scope_column=>$this->get_scope());
-
- self::$db->delete($this->table, $where);
- return;
- }
- /**
- *
- * overrides delete of ORM
- */
- public function delete()
- {
- return $this->delete_node();
- }
- /**
- * Deletes the given node ((itself) from the tree table
- * @param children boolean set to false to not delete children
- * and move them up the tree
- * @return boolean
- */
- function delete_node($children=true)
- {
-
- $table = $this->table;
- $leftcol = $this->left_column;
- $rightcol = $this->right_column;
- $leftanchor = $this->$leftcol;
- $leftval = $this->$leftcol;
- $rightval = $this->$rightcol;
- $parent_column = $this->parent_column;
- if($children==true)
- {
-
- $where=$leftcol . '>='.$leftval .'
- AND '. $rightcol .' <= ' . $rightval . '
- AND '. $this->scope_column .' = '.$this->get_scope() ;
-
- $this->lock_tree();
- //Delete node and children
- self::$db->delete($this->table, $where);
- //Modify other nodes to restore tree integrity
- $this->modify_node($rightval+1, $leftval - $rightval - 1);
- $this->unlock_tree();
- }
- else
- {
- if($this->is_root()){
- Log::add('error', 'Cannot delete root node without deleting its children' );
- return false;
- }
- $this->lock_tree();
- //Get children before the parent is gone
- //Set parent ids right again
- $parent_node=$this->get_node($this->$parent_column);
-
- $children=$this->get_children(true);
-
- //Delete the node
- $where=array('id'=>$this->id);
- self::$db->delete($this->table, $where);
-
- //First update
- $sql = 'UPDATE `' . $this->table . '`
- SET '. $this->left_column .'='.$this->left_column .'-1, '.
- $this->right_column.' = '.$this->right_column . '-1
- WHERE '. $this->left_column .' >= '.$this->$leftcol . '
- AND '.$this->right_column .' <= '.$this->$rightcol .'
- AND '.$this->scope_column.' = '.$this->get_scope().';';
- self::$db->query($sql);
-
- //Second update
- $sql = 'UPDATE `' . $this->table . '`
- SET '. $this->left_column .'='.$this->left_column .' -2
- WHERE '. $this->right_column .' > '.$this->$rightcol . '-1
- AND '.$this->left_column .' > '.$this->$rightcol .'-1
- AND '.$this->scope_column.' = '.$this->get_scope().';';
- self::$db->query($sql);
-
- //Third update
- $sql = 'UPDATE `' . $this->table . '`
- SET '. $this->right_column .'='.$this->right_column .'-2
- WHERE '. $this->right_column .' > '.$this->$rightcol . '-1
- AND '.$this->scope_column.' = '.$this->get_scope().';';
- self::$db->query($sql);
-
- //Set the parent ids
- if(is_array($children))
- {
- foreach($children as $child)
- {
- $child->$parent_column=$parent_node->id;
- $child->save_node();
- }
- }
- $this->unlock_tree();
-
- }
-
-
- return true;
- }
-
- /**
- * Delete descendants but not node itself
- *
- * @return
- */
- function delete_descendants()
- {
- $this->lock_tree();
- $this->get_children();
- foreach($this->children as $child)
- {
- $child->delete_node();
-
- }
- $this->unlock_tree();
- $this->children=array();
- return true;
- }
- /**
- * Deletes children but not descendants,
- * descendants move up the tree
- * @return
- */
- function delete_children()
- {
- $this->get_children();
- foreach($this->children as $child)
- {
- $child->delete_node(false);
-
- }
- $this->unlock_tree();
- $this->children=array();
- return true;
- }
-
- // -------------------------------------------------------------------------
- // MODIFY/REORGANISE TREE
- //
- // Methods to move nodes around the tree. Method names should be
- // relatively self-explanatory! Hopefully ;)
- //
- // -------------------------------------------------------------------------
-
- //inter-scope moves might be something for later
- /**
- * Moves the given node to make it the next sibling of "target"
- *
- * @param array $target The node to use as the position marker
- * @return array $newpos The new left and right values of the node moved
- */
- function move_to_next_sibling_of( $target)
- {
- $rgt_col = $this->right_column;
- $parent_column=$this->parent_column;
-
- //Set parent id (siblings have the same parent)
- $parent_id=$target->$parent_column;
-
- //only move when scopes are equal
- if($target->get_scope()==$this->get_scope())
- {
- $this->update_parent_id($parent_id);
-
- return $this->move_sub_tree( $target->$rgt_col+1);
- }
- return false;
- }
-
- /**
- * Moves the given node to make it the prior sibling of "target"
- *
- * @param array $target The node to use as the position marker
- * @return array $newpos The new left and right values of the node moved
- */
- function move_to_prev_sibling_of( $target)
- {
- $lft_col = $this->left_column;
- $parent_column=$this->parent_column;
-
- //Set parent id (siblings have the same parent)
- $parent_id=$target->$parent_column;
-
- //only move when scopes are equal
- if($target->get_scope()==$this->get_scope())
- {
- $this->update_parent_id($parent_id);
-
- return $this->move_sub_tree( $target->$lft_col);
- }
- return false;
-
- }
-
- /**
- * Moves the given node to make it the first child of "target"
- *
- * @param array $target The node to use as the position marker
- * @return array $newpos The new left and right values of the node moved
- */
- function move_to_first_child_of( $target)
- {
- $lft_col = $this->left_column;
- $parent_column=$this->parent_column;
-
- //Set parent id (id of the parent, is childs parent id)
- $parent_id=$target->id;
-
- //only move when scopes are equal
- if($target->get_scope()==$this->get_scope())
- {
- $this->update_parent_id($parent_id);
-
- return $this->move_sub_tree( $target->$lft_col+1);
- }
- return false;
- }
-
- /**
- * Moves the given node to make it the last child of "target"
- *
- * @param array $target The node to use as the position marker
- * @return array $newpos The new left and right values of the node moved
- */
- function move_to_last_child_of($target)
- {
- $rgt_col = $this->right_column;
- $parent_column=$this->parent_column;
-
- //Set parent id (id of the parent, is childs parent id)
- $parent_id=$target->id;
-
- //only move when scopes are equal
- if($target->get_scope()==$this->get_scope())
- {
- $this->update_parent_id($parent_id);
-
- return $this->move_sub_tree($target->$rgt_col);
- }
- return false;
- }
-
- /*
- * *****************
- * Check methods
- * *****************
- */
- /**
- * Returns true or false
- * (in reality, it checks to see if the given left and
- * right values _appear_ to be valid not necessarily that they _are_ valid)
- *
- * @return boolean
- */
- function is_valid_node()
- {
- $leftcol = $this->left_column;
- $rightcol = $this->right_column;
-
- return ($this->$leftcol < $this->$rightcol);
- }
-
- /**
- * Tests whether the given node has an ancestor
- * (effectively the opposite of isRoot yes|no)
- *
- * @return boolean
- */
- function has_parent()
- {
- return $this->is_valid_node($this->get_parent());
- }
-
- /**
- * Tests whether the given node has a prior sibling or not
- *
- * @return boolean
- */
- function has_prev_sibling()
- {
- return $this->is_valid_node($this->get_prev_sibling());
- }
-
- /**
- * Test to see if node has siblings after itself
- *
- * @return boolean
- */
- function has_next_sibling()
- {
- return $this->is_valid_node($this->get_next_sibling());
- }
-
- /**
- * Test to see if node has children
- *
- * @return boolean
- */
- function has_descendants()
- {
- $leftcol = $this->left_column;
- $rightcol = $this->right_column;
- return (($this->$rightcol - $this->$leftcol) > 1);
- }
-
- /**
- * Test to see if the given node is also the root node
- *
- * @return boolean
- */
- function is_root()
- {
- $leftcol = $this->left_column;
- return ($this->$leftcol == 1);
- }
-
- /**
- * Test to see if the given node is a leaf node (ie has no children)
- *
- * @return boolean
- */
- function is_leaf()
- {
- $leftcol = $this->left_column;
- $rightcol = $this->right_column;
- return (($this->$rightcol - $this->$leftcol) == 1);
- }
-
- /**
- * Test to see if the node is a descendant of the given node
- * @param array $control_node the node to use as the parent or ancestor
- * @return boolean
- */
- function is_descendant_of($control_node)
- {
- $leftcol = $this->left_column;
- $rightcol = $this->right_column;
-
- return ( ($this->$leftcol > $control_node->$leftcol)
- and ($this->$rightcol < $control_node->$rightcol)
- );
- }
-
- /**
- * Test to see if the node is a descendant of the given node
- * @param array $control_node the node to use as the parent or ancestor
- * @return boolean
- */
- function is_child_of($control_node)
- {
- $child_id=$this->id;
- $parent_id=$control_node->id;
-
- self::$db->select('count(*) as is_child');
- self::$db->from($this->table);
- self::$db->where('id',$child_id);
- self::$db->where($this->parent_column,$parent_id);
- self::$db->where($this->scope_column, $this->get_scope());
-
- $result=self::$db->get();
-
- if ($row = $result->current())
- {
- return $row->is_child > 0;
- }
-
- return false;
-
- }
-
- /**
- * Test to determine whether the node is infact also the $control_node (is A === B)
- * @param array $control_node The node prototype to use for the comparison
- * @return boolean
- */
- function is_equal_to($control_node)
- {
- $leftcol = $this->left_column;
- $rightcol = $this->right_column;
-
- return (($this->$leftcol==$control_node->$leftcol) and ($this->$rightcol==$control_node->$rightcol));
- }
-
- /**
- * Combination method of is_descendant and is_equal
- *
- * @param array $controlNode The node prototype to use for the comparison
- * @return boolean
- */
- function is_descendant_or_equal_to($controlNode)
- {
- $leftcol = $this->left_column;
- $rightcol = $this->right_column;
-
- return (($this->$leftcol>=$control_node->$leftcol) and ($this->$rightcol<=$control_node->$rightcol));
- }
- /*
- * *****************
- * Informational methods
- * *****************
- */
- /**
- * Returns the tree level for the given node (assuming root node is at level 0)
- *
- * @return integer The level of the supplied node
- */
- function get_level()
- {
- $leftval = (int) $this->$lft_col;
- $rightval = (int) $this->$rgt_col;
-
- self::$db->select('COUNT(*) AS level');
- self::$db->from($this->table);
- self::$db->where($this->left_column.' < '.$leftval);
- self::$db->where($this->right_column.' < '.$rightval);
- self::$db->where($this->scope_column, $this->get_scope());
-
- $query=self::$db->get();
- if($query->count() > 0) {
- $result = $query->current();
- return (int) $result->level;
- } else {
- return 0;
- }
- }
- /**
- * Output number of descendants this node has
- * @return integer
- *
- */
- function get_number_of_descendants(){
- $lft_col = $this->left_column;
- $rgt_col = $this->right_column;
- // Generate WHERE
-
- return (int) ( $this->$rgt_col - $this->$lft_col -1)/2;
-
- }
- /**
- * Output number of children of this node
- * @return integer
- */
- function get_number_of_children()
- {
-
- self::$db->select('count(*) as num_children');
- self::$db->from($this->table);
- self::$db->where($this->parent_column,$this->id);
- self::$db->where($this->scope_column, $this->get_scope());
-
- $result=self::$db->get();
-
- if($row = $result->current())
- return (int) $row->num_children;
-
- return -1;
- }
- /**
- * Get current scope of the object
- * @return integer
- */
- function get_scope()
- {
- return $this->_scope;
- }
- /**
- * Set scope of current object, retrieved objects calls this in constructor
- */
- function set_scope($value)
- {
- $this->_scope=$value;
- return $this;
- }
-
-
-
- /* *****************************************
- * Print methods, more or less debug methods
- * *****************************************
- */
- /**
- * Debug tree
- */
- function debug_tree($tree, $disp_col, $ind = '')
- {
- $lft_col = $this->left_column;
- $rgt_col = $this->right_column;
- $parent_column=$this->parent_column;
-
- echo $ind .'#'.$tree->id.' '.$tree->$lft_col.'- '.$tree->$disp_col .' p:'.$tree->$parent_column.' -'.$tree->$rgt_col.'<br>';
- if(is_array($tree->children))
- {
- foreach($tree->children as $child)
- {
- $this->debug_tree($child,$disp_col,'....'.$ind);
- }
- }
-
-
- }
- /**
- * Will rebuild tree according to the parent_id column
- * Warning, the order of the tree might not exactly be maintained
- * Might be slow for big trees
- * Call this method only with the root_id and its left value.
- * @return
- * @param $parent_id Object
- * @param $left Object
- */
- function rebuild_tree($parent_id, $left) {
- $this->lock_tree();
- // the right value of this node is the left value + 1
- $right = $left+1;
-
- // get all children of this node
- self::$db->select('id');
- self::$db->where($this->parent_column, $parent_id);
- self::$db->where($this->scope_column, $this->get_scope());
- self::$db->from($this->table);
- $result=self::$db->get();
-
- foreach ($result as $row) {
- // recursive execution of this function for each
- // child of this node
- // $right is the current right value, which is
- // incremented by the rebuild_tree function
- $right = $this->rebuild_tree($row->id, $right);
- }
-
- // we've got the left value, and now that we've processed
- // the children of this node we also know the right value
-
- self::$db->set($this->left_column, $left);
- self::$db->set($this->right_column, $right);
- self::$db->where('id',$parent_id);
- self::$db->where($this->scope_column, $this->get_scope());
- self::$db->update($this->table);
- // return the right value of this node + 1
- return $right+1;
-
- $this->unlock_tree();
- }
-
- /*
- * Protected functions
- *
- */
- /**
- * check whether child is child of parent (internal)
- *
- * @return
- * @param $child Object
- * @param $parent Object
- */
- protected function _is_descendant_of($child, $parent)
- {
- $lft_col = $this->left_column;
- $rgt_col = $this->right_column;
-
- return ($child->$lft_col > $parent->$lft_col && $child->$rgt_col < $parent->$rgt_col);
- }
-
- /**
- * The method that performs moving/renumbering operations
- *
- * @param array $targetValue Position integer to use as the target
- * @return array $newpos The new left and right values of the node moved
- * @access private
- */
- protected function move_sub_tree($targetValue)
- {
- $leftcol = $this->left_column;
- $rightcol = $this->right_column;
-
- $sizeOfTree = $this->$rightcol - $this->$leftcol + 1;
- $this->modify_node($targetValue, $sizeOfTree);
-
-
- if($this->$leftcol >= $targetValue)
- {
- $this->$leftcol += $sizeOfTree;
- $this->$rightcol += $sizeOfTree;
- }
-
- $newpos = $this->modify_node_range($this->$leftcol, $this->$rightcol, $targetValue - $this->$leftcol);
-
- $this->modify_node($this->$rightcol+1, - $sizeOfTree);
-
- if($this->$leftcol <= $targetValue)
- {
- $newpos[$this->left_column] -= $sizeOfTree;
- $newpos[$this->right_column] -= $sizeOfTree;
- }
-
- return $newpos;
- }
- /**
- * _modifyNodeRange
- *
- * @param $lowerbound integer value of lowerbound of range to move
- * @param $upperbound integer value of upperbound of range to move
- * @param $changeVal unsigned integer of change amount
- * @access private
- */
-
- protected function modify_node_range($lowerbound, $upperbound, $changeVal)
- {
- $leftcol = $this->left_column;
- $rightcol = $this->right_column;
- $table = $this->table;
- $scope_col = $this->scope_column;
-
- $sql = "UPDATE $table
- SET $leftcol = $leftcol + $changeVal
- WHERE $leftcol >= $lowerbound
- AND $leftcol <= $upperbound
- AND ".$this->scope_column.' = '.$this->$scope_col.';';
-
- self::$db->query($sql);
-
- $sql = "UPDATE $table
- SET $rightcol = $rightcol + $changeVal
- WHERE $rightcol >= $lowerbound
- AND $rightcol <= $upperbound
- AND ".$this->scope_column.' = '.$this->$scope_col.';';
-
- self::$db->query($sql);
-
- $retArray = array(
- $this->left_column => $lowerbound+$changeVal,
- $this->right_column => $upperbound+$changeVal
- );
- return $retArray;
- } // END: Method _modifyNodeRange
-
- /**
- * Update the parent id of this record, the ORM class handles
- * it when the parent id didn't change
- * @return
- * @param $node Object
- * @param $parent_id Object
- */
- protected function update_parent_id($parent_id)
- {
- $parent_column=$this->parent_column;
- $this->$parent_column=$parent_id;
- return $this->save_node();
- }
- /**
- * _modifyNode
- *
- * Adds $changeVal to all left and right values that are greater than or
- * equal to $node_int
- *
- * @param $node_int The value to start the shift from
- * @param $changeVal unsigned integer value for change
- * @access private
- */
- protected function modify_node($node_int, $changeVal)
- {
- $leftcol = $this->left_column;
- $rightcol = $this->right_column;
- $table = $this->table;
- $scope_col = $this->scope_column;
-
- $sql = "UPDATE $table " .
- "SET $leftcol = $leftcol + $changeVal ".
- "WHERE $leftcol >= $node_int
- AND ".$this->scope_column.' = '.$this->$scope_col.';';
-
- self::$db->query($sql);
-
- $sql = "UPDATE $table " .
- "SET $rightcol = $rightcol + $changeVal ".
- "WHERE $rightcol >= $node_int
- AND ".$this->scope_column.' = '.$this->$scope_col.';';
-
- self::$db->query($sql);
-
- return true;
- } // END: _modifyNode
- /**
- * save_node
- *
- * Inserts a new node into the tree, or saves the current one
- *
- * @return boolean True/False dependent upon the success of the operation
- * @access private
- */
- protected function save_node( )
- {
- if ($this->save()) {
- // Return true on success
- return TRUE;
- }
-
- return false;
- }
-}
diff --git a/themes/default/images/carousel.png b/themes/default/images/carousel.png
new file mode 100644
index 00000000..e516b1d3
--- /dev/null
+++ b/themes/default/images/carousel.png
Binary files differ
diff --git a/themes/default/views/footer.html.php b/themes/default/views/footer.html.php
index ab40a417..9a080a57 100644
--- a/themes/default/views/footer.html.php
+++ b/themes/default/views/footer.html.php
@@ -1,7 +1,9 @@
<? defined("SYSPATH") or die("No direct script access."); ?>
- <div id="gFooter">
- Powered by <a href="#">GalleryX</a> | <a href="#">About this Gallery</a> | ...
- </div>
+ <div id="ft">
+ <div id="gFooter">
+ Powered by <a href="#">Gallery3</a> | <a href="#">About this Gallery</a> | ...
+ </div><!-- END #gFooter -->
+ </div><!-- END YUI #ft -->
</div>
</body>
</html>
diff --git a/themes/default/views/photo.html.php b/themes/default/views/photo.html.php
new file mode 100644
index 00000000..e4d47d61
--- /dev/null
+++ b/themes/default/views/photo.html.php
@@ -0,0 +1,64 @@
+<? defined("SYSPATH") or die("No direct script access."); ?>
+<?= $theme->display('header.html') ?>
+<div id="bd">
+ <div id="yui-main">
+ <div id="gContent" class="yui-b">
+
+ <div id="gItem">
+ <a href="" class="buttonlink">Full size (1024x768)</a>
+ <a href="" class="buttonlink">Slideshow</a>
+
+ <img id="photo-id-1" alt="photo" src="images/thumbnail.jpg" />
+ <h1>Photo title</h1>
+ <p>Photo description: Lorem ipsum dolor sit amet.</p>
+ </div>
+
+ <div id="gComments">
+ <h2>Comments</h2>
+
+ <ul id="gCommentThread">
+ <li id="gComment-1" class="gComment odd">
+ <p><a href="#" class="gAuthor">Andy</a> said 2 hours ago <span class="understate">(October 23, 2008 11:30am)</span></p>
+ <div>
+ Lorem ipsum dolor sit amet.
+ </div>
+ </li>
+ <li id="gComment-2" class="gComment even">
+ <p>
+ <a href="#" class="gAuthor">Other user</a> said 30 minutes ago <span class="understate">(October 23, 2008 1:00pm)</span>
+ </p>
+ <div>
+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard
+ dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
+ It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It
+ was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with
+ desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ </div>
+ </li>
+ </ul>
+
+ <form id="gCommentAdd" class="gExpandedForm">
+ <fieldset>
+ <legend>Add comment</legend>
+ <div class="row">
+ <label for="gCommentAuthor">Your Name</label>
+ <input type="text" id="gCommentAuthor" class="text" />
+ </div>
+ <div>
+ <label for="gCommentEmail">Your Email (not displayed)</label>
+ <input type="text" id="gCommentEmail" class="text" />
+ </div>
+ <div class="row">
+ <label for="gCommentText">Comment</label>
+ <textarea id="gCommentText"></textarea>
+ </div>
+ <input type="submit" class="button" value="Add" />
+ </fieldset>
+ </form>
+ </div><!-- END #gComments -->
+
+ </div><!-- END #gContent -->
+ </div><!-- END yui-main -->
+ <?= $theme->display('sidebar.html') ?>
+</div><!-- END YUI #bd -->
+<?= $theme->display('footer.html'); ?>
diff --git a/themes/default/views/sidebar.html.php b/themes/default/views/sidebar.html.php
index f8acc25b..9f4509e3 100644
--- a/themes/default/views/sidebar.html.php
+++ b/themes/default/views/sidebar.html.php
@@ -1,106 +1,24 @@
<? defined("SYSPATH") or die("No direct script access."); ?>
<div id="gSidebar" class="yui-b">
- <div id="gAlbumTree">
- <h2>Album Navigation</h2>
-
- <div id="gTreeContainer"><!-- there might be a better way to make this accessible to the JS -->
- <ul>
- <li>Gallery
- <ul>
- <li>Friends &amp; Family
- <ul>
- <li>Christmas 2006</li>
- <li>Family Reunion</li>
- <li>Christmas 2007</li>
- </ul>
- </li>
- <li>Vactions
- <ul>
- <li>Cuba</li>
- <li>Europe</li>
- </ul>
- </li>
- </ul>
- </li>
- </ul>
+ <div id="gCarousel" class="gBlock">
+ <div class="gBlockHeader">
+ <h2>Album: <a href="browse.html">Christmas 2007</a></h2>
+ <a href="#" class="minimize">[-]</a>
</div>
- </div>
-
- <script type="text/javascript">
- //global variable to allow console inspection of tree:
- var tree;
-
- //anonymous function wraps the remainder of the logic:
- (function() {
-
- //function to initialize the tree:
- function treeInit() {
- buildRandomTextNodeTree();
- }
-
- //Function creates the tree and
- //builds between 3 and 7 children of the root node:
- function buildRandomTextNodeTree() {
- //instantiate the tree:
- tree = new YAHOO.widget.TreeView("gTreeContainer");
-
- // Expand and collapse happen prior to the actual expand/collapse,
- // and can be used to cancel the operation
- tree.subscribe("expand", function(node) {
- YAHOO.log(node.index + " was expanded", "info", "example");
- // return false; // return false to cancel the expand
- });
-
- tree.subscribe("collapse", function(node) {
- YAHOO.log(node.index + " was collapsed", "info", "example");
- });
-
- // Trees with TextNodes will fire an event for when the label is clicked:
- tree.subscribe("labelClick", function(node) {
- YAHOO.log(node.index + " label was clicked", "info", "example");
- });
-
- //The tree is not created in the DOM until this method is called:
- tree.draw();
- }
-
- //Add an onDOMReady handler to build the tree when the document is ready
- YAHOO.util.Event.onDOMReady(treeInit);
- })();
- </script>
+ <img src="<?= $theme->url("images/carousel.png") ?>" width="214" class="gBlockContent" />
+ </div>
- <table class="gMetadata">
- <caption><h2>Album Info</h2></caption>
- <tbody>
- <tr>
- <th>Name:</th>
- <td><strong>Christmas 2007</strong></td>
- </tr>
- <tr>
- <th>Taken:</th>
- <td><span class="date" title="January 21, 2008 8:30pm">January 21, 2008</td>
- </tr>
- <tr>
- <th>Location:</th>
- <td><a href="#" title="see the location on a map">Mountain View</a></td>
- </tr>
- <tr>
- <th>Owner:</th>
- <td><a href="#">username</a></td>
- </tr>
- <tr>
- <th>Uploaded:</th>
- <td><span class="date" title="October 23, 2008 11:37am">October 23, 2008</td>
- </tr>
- </tbody>
- </table>
+ <div class="gTagCloud gBlock">
+ <div class="gBlockHeader">
+ <h2>Tags</h2> &nbsp;
+ <a href="#">?</a>
+ <a href="#" class="minimize">[-]</a>
+ </div>
- <div class="gTagCloud">
- <h2>Tag cloud</h2>
- <ul>
+ <ul class="gBlockContent">
<li><a href="#" class="m size0">animation</a></li>
<li><a href="#" class="m size0">art</a></li>
<li><a href="#" class="m size1">blind</a></li>
@@ -137,5 +55,54 @@
<li><a href="#" class="m size1">usability</a></li>
<li><a href="#" class="m size0">writing</a></li>
</ul>
+
+ <form id="gAddTag" class="gBlockContent">
+ <input type="text" class="text" value="add new tags ..." id="newtags" />
+ <input type="submit" class="submit" value="add" />
+ <label for="newtags" class="understate">(separated by commas)</label>
+ </form>
+ </div>
+
+ <div class="gBlock">
+ <div class="gBlockHeader">
+ <h2>Item Info</h2>
+ <a href="#" class="minimize">[-]</a>
+ </div>
+ <table class="gMetadata gBlockContent">
+ <tbody>
+ <tr>
+ <th>Title:</th>
+ <td>Christmas 2007</td>
+ </tr>
+ <tr>
+ <th>Taken:</th>
+ <td>January 21, 2008</td>
+ </tr>
+ <tr>
+ <th>Uploaded:</th>
+ <td>January 27, 2008</td>
+ </tr>
+ <tr>
+ <th>Owner:</th>
+ <td><a href="#">username</a></td>
+ </tr>
+ <tr>
+ <td colspan="2" class="toggle">
+ <a href="#">more \/</a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
</div>
-</div>
+
+ <div class="gBlock">
+ <div class="gBlockHeader">
+ <h2>Location</h2>
+ <a href="#" class="minimize">[-]</a>
+ </div>
+ <iframe class="gBlockContent" width="214" height="214" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.com/maps?f=q&amp;hl=en&amp;geocode=&amp;q=mountain+view&amp;sll=37.0625,-95.677068&amp;sspn=50.823846,89.648437&amp;ie=UTF8&amp;z=12&amp;g=mountain+view&amp;ll=37.433704,-122.056046&amp;output=embed&amp;s=AARTsJoyjpSOFMFEv5XZbREeW_hGGS28pQ"></iframe>
+ <br />
+ <small class="gBlockContent"><a href="http://maps.google.com/maps?f=q&amp;hl=en&amp;geocode=&amp;q=mountain+view&amp;sll=37.0625,-95.677068&amp;sspn=50.823846,89.648437&amp;ie=UTF8&amp;z=12&amp;g=mountain+view&amp;ll=37.433704,-122.056046&amp;source=embed" style="color:#0000FF;text-align:left">View Larger Map</a></small>
+ </div>
+
+</div><!-- END #gSideBar -->