From 605d2de336eac8c8f80b916d30989b347d813e94 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Tue, 4 Nov 2008 21:24:42 +0000 Subject: Lots of new stuff! Replace theme HTML with *almost* the latest stuff from the mockups. (it doesn't include r18467 yet). Our theme format is now modelled after WordPress / Habari's style where you have one entry point per type (eg: album.php) which can load up whatever parts it needs (eg: $theme->display("header")) Created album and photo helpers which have create() functions that form the base of our new API, along with tests for them. Created our own version of the ORM_MPTT since the existing versions were too buggy and unsupported to depend upon. Only has a minimal implementation so far, and the tests are not yet committed. Added path(), thumbnail_path() and resize_path() to Item_Model Extended the scaffolding to allow you to add lots of photos/albums into your hierarchy. Deleted modules/mptt -- we're not going to use this anymore. --- core/config/config.php | 1 - core/controllers/welcome.php | 27 +++++++ core/helpers/album.php | 54 ++++++++++++++ core/helpers/core_installer.php | 21 ++++-- core/helpers/photo.php | 65 +++++++++++++++++ core/libraries/ORM_MPTT.php | 142 +++++++++++++++++++++++++++++++++++++ core/models/item.php | 45 +++++++++--- core/tests/Album_Test.php | 47 ++++++++++++ core/tests/Core_Installer_Test.php | 7 +- core/tests/File_Structure_Test.php | 1 + core/tests/Item_Test.php | 29 -------- core/tests/Photo_Test.php | 57 +++++++++++++++ core/tests/test.jpg | Bin 0 -> 6232 bytes core/views/welcome.html.php | 39 ++++++---- 14 files changed, 473 insertions(+), 62 deletions(-) create mode 100644 core/helpers/album.php create mode 100644 core/helpers/photo.php create mode 100644 core/libraries/ORM_MPTT.php create mode 100644 core/tests/Album_Test.php delete mode 100644 core/tests/Item_Test.php create mode 100644 core/tests/Photo_Test.php create mode 100644 core/tests/test.jpg (limited to 'core') 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 "
"; + 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 @@ +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 @@ +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 @@ +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 @@ +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 @@ -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 @@ +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 Binary files /dev/null and b/core/tests/test.jpg 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; + } @@ -72,24 +84,25 @@ This is a scaffold: a temporary structure built to support the developers as - they create the real product. -

- -

- 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. 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.

System Configuration

Activities

-

- -

+

+

Documentation