diff --git a/3.1/modules/calendarview/views/calendarview_year.html.php b/3.1/modules/calendarview/views/calendarview_year.html.php
index 880e0267..b40d7d58 100644
--- a/3.1/modules/calendarview/views/calendarview_year.html.php
+++ b/3.1/modules/calendarview/views/calendarview_year.html.php
@@ -38,7 +38,7 @@
// Check and see if any photos were taken in January,
// If so, make the month title into a clickable link.
print "
";
- if (date("n", $items_for_year[$counter]->captured) == 1) {
+ if ((count($items_for_year) > 0) && (date("n", $items_for_year[$counter]->captured) == 1)) {
$month_url = url::site("calendarview/month/" . $calendar_year . "/" . $calendar_user . "/" . $counter_months . "/");
} else {
$month_url = "";
diff --git a/3.1/modules/noffmpeg/helpers/movie.php b/3.1/modules/noffmpeg/helpers/movie.php
index a42804d2..99308994 100644
--- a/3.1/modules/noffmpeg/helpers/movie.php
+++ b/3.1/modules/noffmpeg/helpers/movie.php
@@ -24,6 +24,7 @@
* Note: by design, this class does not do any permission checking.
*/
+// rWatcher edit: include MP4Info.php library.
include MODPATH . "noffmpeg/libraries/MP4Info.php";
class movie_Core {
@@ -61,7 +62,7 @@ class movie_Core {
}
static function extract_frame($input_file, $output_file) {
- $ffmpeg = self::find_ffmpeg();
+ $ffmpeg = movie::find_ffmpeg();
if (empty($ffmpeg)) {
// BEGIN rWatcher Edit.
copy(MODPATH . "noffmpeg/images/missing_movie.png", $output_file);
@@ -89,27 +90,23 @@ class movie_Core {
}
}
+ /**
+ * Return the path to the ffmpeg binary if one exists and is executable, or null.
+ */
static function find_ffmpeg() {
if (!($ffmpeg_path = module::get_var("gallery", "ffmpeg_path")) || !file_exists($ffmpeg_path)) {
- $graphics_path = module::get_var("gallery", "graphics_toolkit_path", null);
-
- putenv("PATH=" . getenv("PATH") . (empty($graphics_path) ? "" : ":$graphics_path") .
- ":/usr/local/bin:/opt/local/bin:/opt/bin");
- if (function_exists("exec")) {
- $ffmpeg_path = exec("which ffmpeg");
- }
-
+ $ffmpeg_path = system::find_binary(
+ "ffmpeg", module::get_var("gallery", "graphics_toolkit_path"));
module::set_var("gallery", "ffmpeg_path", $ffmpeg_path);
}
return $ffmpeg_path;
}
-
/**
* Return the width, height, mime_type and extension of the given movie file.
*/
static function get_file_metadata($file_path) {
- $ffmpeg = self::find_ffmpeg();
+ $ffmpeg = movie::find_ffmpeg();
if (empty($ffmpeg)) {
// BEGIN rWatcher Edit.
$pi = pathinfo($file_path);
@@ -147,4 +144,4 @@ class movie_Core {
return array($width, $height, $mime_type, $extension);
}
-}
+}
\ No newline at end of file
diff --git a/3.1/modules/noffmpeg/views/form_uploadify.html.php b/3.1/modules/noffmpeg/views/form_uploadify.html.php
new file mode 100644
index 00000000..911e02d5
--- /dev/null
+++ b/3.1/modules/noffmpeg/views/form_uploadify.html.php
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+ if ($suhosin_session_encrypt || (identity::active_user()->admin && !$movies_allowed)): ?>
+
+ if ($suhosin_session_encrypt): ?>
+
+ = t("Error: your server is configured to use the suhosin.session.encrypt
setting from Suhosin . You must disable this setting to upload photos.",
+ array("encrypt_url" => "http://www.hardened-php.net/suhosin/configuration.html#suhosin.session.encrypt",
+ "suhosin_url" => "http://www.hardened-php.net/suhosin/")) ?>
+
+ endif ?>
+
+ if (identity::active_user()->admin && !$movies_allowed): ?>
+
+ = t("Can't find ffmpeg on your system. Movie uploading disabled. Help! ", array("help_url" => "http://codex.gallery2.org/Gallery3:FAQ#Why_does_it_say_I.27m_missing_ffmpeg.3F")) ?>
+
+ endif ?>
+
+ endif ?>
+
+
+
+ = t("Photos will be uploaded to album: ") ?>
+
+
+ foreach ($album->parents() as $i => $parent): ?>
+ > = html::clean($parent->title) ?>
+ endforeach ?>
+ = html::purify($album->title) ?>
+
+
+
+
+ = t("Select photos...") ?>
+
+
+
+
+
+
+
+ = t("Your browser must have Adobe Flash Player version %flash_minimum_version or greater installed to use this feature.", array("flash_minimum_version" => $flash_minimum_version)) ?>
+
+
+ for_js() ?> />
+
+
\ No newline at end of file
diff --git a/3.1/modules/tagsinalbum/helpers/tagsinalbum_installer.php b/3.1/modules/tagsinalbum/helpers/tagsinalbum_installer.php
index 4357ab87..09f82108 100644
--- a/3.1/modules/tagsinalbum/helpers/tagsinalbum_installer.php
+++ b/3.1/modules/tagsinalbum/helpers/tagsinalbum_installer.php
@@ -19,7 +19,15 @@
*/
class tagsinalbum_installer {
static function install() {
- module::set_version("tagsinalbum", 1);
+ module::set_var("tagsinalbum", "max_display_tags", 0);
+ module::set_version("tagsinalbum", 2);
+ }
+
+ static function upgrade($version) {
+ if ($version == 1) {
+ module::set_var("tagsinalbum", "max_display_tags", 0);
+ module::set_version("tagsinalbum", $version = 2);
+ }
}
static function deactivate() {
diff --git a/3.1/modules/tagsinalbum/module.info b/3.1/modules/tagsinalbum/module.info
index 94b7699b..5d9b91f1 100644
--- a/3.1/modules/tagsinalbum/module.info
+++ b/3.1/modules/tagsinalbum/module.info
@@ -1,3 +1,3 @@
name = "Tags In Album"
description = "Creates a sidebar block to display tags used by photos and videos in the current album."
-version = 1
+version = 2
diff --git a/3.1/modules/tagsinalbum/views/tagsinalbum_sidebar.html.php b/3.1/modules/tagsinalbum/views/tagsinalbum_sidebar.html.php
index 803e46ee..6c8b1dff 100644
--- a/3.1/modules/tagsinalbum/views/tagsinalbum_sidebar.html.php
+++ b/3.1/modules/tagsinalbum/views/tagsinalbum_sidebar.html.php
@@ -12,6 +12,11 @@
$display_tags[] = array(html::clean($tag->name), $tag->url());
$last_tagid = $one_tag->id;
}
+ if (module::get_var("tagsinalbum", "max_display_tags") > 0) {
+ if (count($display_tags) == module::get_var("tagsinalbum", "max_display_tags")) {
+ break;
+ }
+ }
}
// Sort the array.
diff --git a/3.1/modules/themeroller/module.info b/3.1/modules/themeroller/module.info
index 0e50286e..74512420 100755
--- a/3.1/modules/themeroller/module.info
+++ b/3.1/modules/themeroller/module.info
@@ -1,3 +1,3 @@
-name = "Theme generator"
+name = "Theme Roller"
description = "Use a JQuery UI theme to create a Gallery3 Theme"
version = 1
diff --git a/3.1/modules/videos/controllers/admin_videos.php b/3.1/modules/videos/controllers/admin_videos.php
index afeb4353..b5fe1cf3 100644
--- a/3.1/modules/videos/controllers/admin_videos.php
+++ b/3.1/modules/videos/controllers/admin_videos.php
@@ -1,7 +1,7 @@
page_title = t("Add videos from server");
+ $view->page_title = t("Add from server");
$view->content = new View("admin_videos.html");
$view->content->form = $this->_get_admin_form();
$paths = unserialize(module::get_var("videos", "authorized_paths", "a:0:{}"));
diff --git a/3.1/modules/videos/controllers/file_proxy.php b/3.1/modules/videos/controllers/file_proxy.php
new file mode 100644
index 00000000..f69bff1b
--- /dev/null
+++ b/3.1/modules/videos/controllers/file_proxy.php
@@ -0,0 +1,144 @@
+server("REQUEST_URI"));
+
+ // get rid of query parameters
+ // request_uri: gallery3/var/albums/foo/bar.jpg
+ $request_uri = preg_replace("/\?.*/", "", $request_uri);
+
+ // var_uri: gallery3/var/
+ $var_uri = url::file("var/");
+
+ // Make sure that the request is for a file inside var
+ $offset = strpos(rawurldecode($request_uri), $var_uri);
+ if ($offset !== 0) {
+ throw new Kohana_404_Exception();
+ }
+
+ // file_uri: albums/foo/bar.jpg
+ $file_uri = substr($request_uri, strlen($var_uri));
+
+ // type: albums
+ // path: foo/bar.jpg
+ list ($type, $path) = explode("/", $file_uri, 2);
+ if ($type != "resizes" && $type != "albums" && $type != "thumbs") {
+ throw new Kohana_404_Exception();
+ }
+
+ // If the last element is .album.jpg, pop that off since it's not a real item
+ $path = preg_replace("|/.album.jpg$|", "", $path);
+
+ $item = item::find_by_path($path);
+ if (!$item->loaded()) {
+ // We didn't turn it up. If we're looking for a .jpg then it's it's possible that we're
+ // requesting the thumbnail for a movie. In that case, the .flv, .mp4 or .m4v file would
+ // have been converted to a .jpg. So try some alternate types:
+ if (preg_match('/.jpg$/', $path)) {
+ // rWatcher Mod: look for videos with file extensions supported by the videos module in addition to flv mp4 and m4v
+ // Original Line: foreach (array("flv", "mp4", "m4v") as $ext) {
+ foreach (array_merge(array("flv", "mp4", "m4v"), unserialize(module::get_var("videos", "allowed_extensions"))) as $ext) {
+ $movie_path = preg_replace('/.jpg$/', ".$ext", $path);
+ $item = item::find_by_path($movie_path);
+ if ($item->loaded()) {
+ break;
+ }
+ }
+ }
+ // rWatcher Mod:
+ // If we're looking for a .flv then it's it's possible that we're requesting a flash resize
+ // for a movie.
+ if (strtolower(substr($path, strlen($path)-4)) == ".flv") {
+ $movie_path = str_ireplace(".flv", "", $path);
+ $item = ORM::factory("item")->where("relative_path_cache", "=", $movie_path)->find();
+ }
+ // END rWatcher Mod
+ }
+
+ if (!$item->loaded()) {
+ throw new Kohana_404_Exception();
+ }
+
+ // Make sure we have access to the item
+ if (!access::can("view", $item)) {
+ throw new Kohana_404_Exception();
+ }
+
+ // Make sure we have view_full access to the original
+ if ($type == "albums" && !access::can("view_full", $item)) {
+ throw new Kohana_404_Exception();
+ }
+
+ // Don't try to load a directory
+ if ($type == "albums" && $item->is_album()) {
+ throw new Kohana_404_Exception();
+ }
+
+ if ($type == "albums") {
+ $file = $item->file_path();
+ } else if ($type == "resizes") {
+ $file = $item->resize_path();
+ // rWatcher MOD
+ // If the resize is for a movie, assume it needs a .flv extension.
+ if ($item->is_movie()) {
+ $file = $file . ".flv";
+ }
+ // End rWatcher MOD
+ } else {
+ $file = $item->thumb_path();
+ }
+
+ if (!file_exists($file)) {
+ throw new Kohana_404_Exception();
+ }
+
+ header("Content-Length: " . filesize($file));
+
+ header("Pragma:");
+ // Check that the content hasn't expired or it wasn't changed since cached
+ expires::check(2592000, $item->updated);
+
+ // We don't need to save the session for this request
+ Session::instance()->abort_save();
+
+ expires::set(2592000, $item->updated); // 30 days
+
+ // Dump out the image. If the item is a movie, then its thumbnail will be a JPG.
+ if ($item->is_movie() && $type != "albums") {
+ header("Content-Type: image/jpeg");
+ } else {
+ header("Content-Type: $item->mime_type");
+ }
+ Kohana::close_buffers(false);
+ readfile($file);
+ }
+}
diff --git a/3.1/modules/videos/controllers/videos.php b/3.1/modules/videos/controllers/videos.php
index 78121ae4..b30f4f0e 100644
--- a/3.1/modules/videos/controllers/videos.php
+++ b/3.1/modules/videos/controllers/videos.php
@@ -1,7 +1,7 @@
where("task_id", "NOT IN", db::build()->select("id")->from("tasks"))
+ ->delete("videos_entries")
+ ->execute();
+
$item = ORM::factory("item", $id);
$view = new View("videos_tree_dialog.html");
$view->item = $item;
@@ -55,6 +67,7 @@ class Videos_Controller extends Admin_Controller {
}
if (!is_dir($file)) {
$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
+ // rWatcher Edit
//if (!in_array($ext, array("gif", "jpeg", "jpg", "png", "flv", "mp4", "m4v"))) {
if (!in_array($ext, unserialize(module::get_var("videos", "allowed_extensions")))) {
continue;
@@ -74,23 +87,28 @@ class Videos_Controller extends Admin_Controller {
}
/**
- * Begin the task of adding files.
+ * Begin the task of adding photos.
*/
public function start() {
access::verify_csrf();
$item = ORM::factory("item", Input::instance()->get("item_id"));
- foreach (Input::instance()->post("paths") as $path) {
- if (videos::is_valid_path($path)) {
- $paths[] = array($path, null);
- }
- }
-
$task_def = Task_Definition::factory()
->callback("Videos_Controller::add")
- ->description(t("Add videos from the local server"))
+ ->description(t("Add photos or movies from the local server"))
->name(t("Add from server"));
- $task = task::create($task_def, array("item_id" => $item->id, "queue" => $paths));
+ $task = task::create($task_def, array("item_id" => $item->id));
+
+ foreach (Input::instance()->post("paths") as $path) {
+ if (videos::is_valid_path($path)) {
+ $entry = ORM::factory("videos_entry");
+ $entry->path = $path;
+ $entry->is_directory = intval(is_dir($path));
+ $entry->parent_id = null;
+ $entry->task_id = $task->id;
+ $entry->save();
+ }
+ }
json::reply(
array("result" => "started",
@@ -99,7 +117,7 @@ class Videos_Controller extends Admin_Controller {
}
/**
- * Run the task of adding files
+ * Run the task of adding photos
*/
function run($task_id) {
access::verify_csrf();
@@ -119,7 +137,7 @@ class Videos_Controller extends Admin_Controller {
/**
* This is the task code that adds photos and albums. It first examines all the target files
- * and creates a set of Server_Add_File_Models, then runs through the list of models and adds
+ * and creates a set of Server_Add_Entry_Models, then runs through the list of models and adds
* them one at a time.
*/
static function add($task) {
@@ -129,6 +147,7 @@ class Videos_Controller extends Admin_Controller {
switch ($mode) {
case "init":
$task->set("mode", "build-file-list");
+ $task->set("dirs_scanned", 0);
$task->percent_complete = 0;
$task->status = t("Starting up");
batch::start();
@@ -137,59 +156,64 @@ class Videos_Controller extends Admin_Controller {
case "build-file-list": // 0% to 10%
// We can't fit an arbitrary number of paths in a task, so store them in a separate table.
// Don't use an iterator here because we can't get enough control over it when we're dealing
- // with a deep hierarchy and we don't want to go over our time quota. The queue is in the
- // form [path, parent_id] where the parent_id refers to another Server_Add_File_Model. We
- // have this extra level of abstraction because we don't know its Item_Model id yet.
- $queue = $task->get("queue");
+ // with a deep hierarchy and we don't want to go over our time quota.
$paths = unserialize(module::get_var("videos", "authorized_paths"));
+ $dirs_scanned = $task->get("dirs_scanned");
+ while (microtime(true) - $start < 0.5) {
+ // Process every directory that doesn't yet have a parent id, these are the
+ // paths that we're importing.
+ $entry = ORM::factory("videos_entry")
+ ->where("task_id", "=", $task->id)
+ ->where("is_directory", "=", 1)
+ ->where("checked", "=", 0)
+ ->order_by("id", "ASC")
+ ->find();
- while ($queue && microtime(true) - $start < 0.5) {
- list($file, $parent_entry_id) = array_shift($queue);
- // Ignore the staging directories as directories to be imported.
- if (empty($paths[$file])) {
- $entry = ORM::factory("videos_file");
- $entry->task_id = $task->id;
- $entry->file = $file;
- $entry->parent_id = $parent_entry_id;
- $entry->save();
- $entry_id = $entry->id;
- } else {
- $entry_id = null;
- }
-
- $file = preg_quote($file);
- foreach (glob("$file/*") as $child) {
- if (is_dir($child)) {
- $queue[] = array($child, $entry_id);
- } else {
- $ext = strtolower(pathinfo($child, PATHINFO_EXTENSION));
- //if (in_array($ext, array("gif", "jpeg", "jpg", "png", "flv", "mp4", "m4v")) &&
- if (in_array($ext, unserialize(module::get_var("videos", "allowed_extensions"))) &&
- filesize($child) > 0) {
- $child_entry = ORM::factory("videos_file");
- $child_entry->task_id = $task->id;
- $child_entry->file = $child;
- $child_entry->parent_id = $entry_id;
- $child_entry->save();
- }
+ if ($entry->loaded()) {
+ $child_paths = glob(preg_quote($entry->path) . "/*");
+ if (!$child_paths) {
+ $child_paths = glob("{$entry->path}/*");
}
+ foreach ($child_paths as $child_path) {
+ if (!is_dir($child_path)) {
+ $ext = strtolower(pathinfo($child_path, PATHINFO_EXTENSION));
+ // rWatcher Edit.
+ //if (!in_array($ext, array("gif", "jpeg", "jpg", "png", "flv", "mp4", "m4v")) ||
+ // !filesize($child_path)) {
+ if (!in_array($ext, unserialize(module::get_var("videos", "allowed_extensions"))) ||
+ !filesize($child_path)) {
+ // Not importable, skip it.
+ continue;
+ }
+ }
+
+ $child_entry = ORM::factory("videos_entry");
+ $child_entry->task_id = $task->id;
+ $child_entry->path = $child_path;
+ $child_entry->parent_id = $entry->id; // null if the parent was a staging dir
+ $child_entry->is_directory = is_dir($child_path);
+ $child_entry->save();
+ }
+
+ // We've processed this entry, mark it as done.
+ $entry->checked = 1;
+ $entry->save();
+ $dirs_scanned++;
}
}
// We have no idea how long this can take because we have no idea how deep the tree
// hierarchy rabbit hole goes. Leave ourselves room here for 100 iterations and don't go
// over 10% in percent_complete.
- $task->set("queue", $queue);
+ $task->set("dirs_scanned", $dirs_scanned);
$task->percent_complete = min($task->percent_complete + 0.1, 10);
- $task->status = t2(
- "Found one file", "Found %count files",
- ORM::factory("videos_file")->where("task_id", "=", $task->id)->count_all());
+ $task->status = t2("Scanned one directory", "Scanned %count directories", $dirs_scanned);
- if (!$queue) {
+ if (!$entry->loaded()) {
$task->set("mode", "add-files");
$task->set(
"total_files",
- ORM::factory("videos_file")->where("task_id", "=", $task->id)->count_all());
+ ORM::factory("videos_entry")->where("task_id", "=", $task->id)->count_all());
$task->percent_complete = 10;
}
break;
@@ -201,7 +225,7 @@ class Videos_Controller extends Admin_Controller {
// Ordering by id ensures that we add them in the order that we created the entries, which
// will create albums first. Ignore entries which already have an Item_Model attached,
// they're done.
- $entries = ORM::factory("videos_file")
+ $entries = ORM::factory("videos_entry")
->where("task_id", "=", $task->id)
->where("item_id", "IS", null)
->order_by("id", "ASC")
@@ -220,43 +244,59 @@ class Videos_Controller extends Admin_Controller {
// Look up the parent item for this entry. By now it should exist, but if none was
// specified, then this belongs as a child of the current item.
- $parent_entry = ORM::factory("videos_file", $entry->parent_id);
+ $parent_entry = ORM::factory("videos_entry", $entry->parent_id);
if (!$parent_entry->loaded()) {
$parent = ORM::factory("item", $task->get("item_id"));
} else {
$parent = ORM::factory("item", $parent_entry->item_id);
}
- $name = basename($entry->file);
+ $name = basename($entry->path);
$title = item::convert_filename_to_title($name);
- if (is_dir($entry->file)) {
+ if ($entry->is_directory) {
$album = ORM::factory("item");
$album->type = "album";
$album->parent_id = $parent->id;
$album->name = $name;
$album->title = $title;
$album->owner_id = $owner_id;
+ $album->sort_order = $parent->sort_order;
+ $album->sort_column = $parent->sort_column;
$album->save();
$entry->item_id = $album->id;
} else {
try {
$extension = strtolower(pathinfo($name, PATHINFO_EXTENSION));
- if (in_array($extension, unserialize(module::get_var("videos", "allowed_extensions")))) {
+ if (in_array($extension, array("gif", "png", "jpg", "jpeg"))) {
+ $photo = ORM::factory("item");
+ $photo->type = "photo";
+ $photo->parent_id = $parent->id;
+ $photo->set_data_file($entry->path);
+ $photo->name = $name;
+ $photo->title = $title;
+ $photo->owner_id = $owner_id;
+ $photo->save();
+ $entry->item_id = $photo->id;
+ // rWatcher EDIT
+ //} else if (in_array($extension, array("flv", "mp4", "m4v"))) {
+ } else if (in_array($extension, unserialize(module::get_var("videos", "allowed_extensions")))) {
$movie = ORM::factory("item");
$movie->type = "movie";
$movie->parent_id = $parent->id;
- $movie->set_data_file($entry->file);
+ $movie->set_data_file($entry->path);
$movie->name = $name;
$movie->title = $title;
$movie->owner_id = $owner_id;
$movie->save();
$entry->item_id = $movie->id;
+ // rWatcher EDIT: Add record to items_video db.
$items_video = ORM::factory("items_video");
$items_video->item_id = $movie->id;
$items_video->save();
- if (file_exists($entry->file . ".flv")) {
- copy($entry->file . ".flv", $movie->resize_path() . ".flv");
- list ($vid_width, $vid_height, $mime_type) = movie::get_file_metadata($entry->file . ".flv");
+ // rWatcher EDIT: Scan for flv resizes and copy to resize directory.
+ if (file_exists($entry->path . ".flv")) {
+ copy($entry->path . ".flv", $movie->resize_path() . ".flv");
+ list ($vid_width, $vid_height, $mime_type) = movie::get_file_metadata($entry->path . ".flv");
$movie->height = $vid_height;
$movie->width = $vid_width;
$movie->save();
@@ -266,12 +306,12 @@ class Videos_Controller extends Admin_Controller {
// process. But just in, case.. set this to a non-null value so that we skip this
// entry.
$entry->item_id = 0;
- $task->log("Skipping unknown file type: $entry->file");
+ $task->log("Skipping unknown file type: {$entry->path}");
}
} catch (Exception $e) {
// This can happen if a photo file is invalid, like a BMP masquerading as a .jpg
$entry->item_id = 0;
- $task->log("Skipping invalid file: $entry->file");
+ $task->log("Skipping invalid file: {$entry->file}");
}
}
@@ -290,12 +330,11 @@ class Videos_Controller extends Admin_Controller {
$task->done = true;
$task->state = "success";
$task->percent_complete = 100;
- db::build()
- ->delete("videos_files")
+ ORM::factory("videos_entry")
->where("task_id", "=", $task->id)
- ->execute();
- message::info(t2("Successfully added one file",
- "Successfully added %count files",
+ ->delete_all();
+ message::info(t2("Successfully added one photo / album",
+ "Successfully added %count photos / albums",
$task->get("completed_files")));
}
}
diff --git a/3.1/modules/videos/css/videos.css b/3.1/modules/videos/css/videos.css
index 36746ab5..559e5481 100644
--- a/3.1/modules/videos/css/videos.css
+++ b/3.1/modules/videos/css/videos.css
@@ -1,23 +1,23 @@
-#g-server-add button {
+#g-videos button {
margin-bottom: .5em;
}
-#g-server-add-tree {
+#g-videos-tree {
cursor: pointer;
padding-left: 4px;
width: 95%;
}
-#g-server-add-tree li {
+#g-videos-tree li {
padding: 0;
float: none;
}
-#g-server-add-tree span.selected {
+#g-videos-tree span.selected {
background: #ddd;
}
-#g-server-add-tree {
+#g-videos-tree {
border: 1px solid #ccc;
height: 20em;
overflow: auto;
@@ -25,14 +25,14 @@
padding: .5em;
}
-#g-server-add ul ul li {
+#g-videos ul ul li {
padding-left: 1.2em;
}
-#g-server-add-paths li .ui-icon {
+#g-videos-paths li .ui-icon {
margin-top: .4em;
}
-#g-server-add-admin-form .textbox {
+#g-videos-admin-form .textbox {
width: 400px;
}
diff --git a/3.1/modules/videos/helpers/videos.php b/3.1/modules/videos/helpers/videos.php
index 6169e038..0bb15c31 100644
--- a/3.1/modules/videos/helpers/videos.php
+++ b/3.1/modules/videos/helpers/videos.php
@@ -1,7 +1,7 @@
get("settings_menu")
@@ -34,7 +38,7 @@ class videos_event_Core {
is_writable($item->is_album() ? $item->file_path() : $item->parent()->file_path())) {
$menu->get("add_menu")
->append(Menu::factory("dialog")
- ->id("videos")
+ ->id("Videos")
->label(t("Add videos"))
->url(url::site("videos/browse/$item->id")));
}
diff --git a/3.1/modules/videos/helpers/videos_installer.php b/3.1/modules/videos/helpers/videos_installer.php
index 7bfca0db..cbd4922a 100644
--- a/3.1/modules/videos/helpers/videos_installer.php
+++ b/3.1/modules/videos/helpers/videos_installer.php
@@ -1,7 +1,7 @@
query("CREATE TABLE {videos_files} (
+ $db->query("CREATE TABLE {videos_entries} (
`id` int(9) NOT NULL auto_increment,
- `file` varchar(255) NOT NULL,
+ `checked` boolean default 0,
+ `is_directory` boolean default 0,
`item_id` int(9),
`parent_id` int(9),
+ `path` varchar(255) NOT NULL,
`task_id` int(9) NOT NULL,
PRIMARY KEY (`id`))
DEFAULT CHARSET=utf8;");
+
+ // rWatcher Edit: My Table.
$db->query("CREATE TABLE {items_videos} (
`id` int(9) NOT NULL auto_increment,
`item_id` int(9) NOT NULL,
PRIMARY KEY (`id`),
KEY (`item_id`, `id`))
DEFAULT CHARSET=utf8;");
+ // rWatcher Edit: My Variable.
module::set_var("videos", "allowed_extensions", serialize(array("avi", "mpg", "mpeg", "mov", "wmv", "asf", "mts")));
- module::set_version("videos", 1);
+
+ module::set_version("videos", 4);
videos::check_config();
}
+ static function upgrade($version) {
+ $db = Database::instance();
+
+ if ($version < 4) {
+ $db->query("DROP TABLE {videos_files}");
+ $db->query("CREATE TABLE {videos_entries} (
+ `id` int(9) NOT NULL auto_increment,
+ `checked` boolean default 0,
+ `is_directory` boolean default 0,
+ `item_id` int(9),
+ `parent_id` int(9),
+ `path` varchar(255) NOT NULL,
+ `task_id` int(9) NOT NULL,
+ PRIMARY KEY (`id`))
+ DEFAULT CHARSET=utf8;");
+ module::set_version("videos", $version = 4);
+ }
+ }
+
static function deactivate() {
site_status::clear("videos_configuration");
}
-
- static function uninstall() {
- $db = Database::instance();
- $db->query("DROP TABLE IF EXISTS {videos_files};");
- $db->query("DROP TABLE IF EXISTS {items_videos};");
- module::delete("videos");
- }
}
diff --git a/3.1/modules/videos/helpers/videos_theme.php b/3.1/modules/videos/helpers/videos_theme.php
index 4b59370f..a14f69a2 100644
--- a/3.1/modules/videos/helpers/videos_theme.php
+++ b/3.1/modules/videos/helpers/videos_theme.php
@@ -1,7 +1,7 @@
where("item_id", "=", $item->id)
->find();
- if ($items_video->loaded()) {
- $view = new View("videos_display_js.html");
- //$view->embed_code = addslashes($embedded_video->embed_code);
- return $buf . $view;
+ if (($items_video->loaded()) && (!file_exists($item->resize_path() . ".flv"))) {
+ $buf .= $theme->script("videos_download.js");
}
}
+ return $buf;
}
static function admin_head($theme) {
$buf = "";
if (strpos(Router::$current_uri, "admin/videos") !== false) {
- $buf .= $theme->css("videos.css");
- $buf .= $theme->css("jquery.autocomplete.css");
+ $buf .= $theme->css("videos.css")
+ . $theme->css("jquery.autocomplete.css");
$base = url::site("__ARGS__");
$csrf = access::csrf_token();
$buf .= "";
- $buf .= $theme->script("jquery.autocomplete.js");
- $buf .= $theme->script("admin_videos.js");
+ $buf .= $theme->script("jquery.autocomplete.js")
+ . $theme->script("admin_videos.js"); // rWatcher edit.
}
return $buf;
}
-}
\ No newline at end of file
+}
diff --git a/3.1/modules/videos/js/admin_videos.js b/3.1/modules/videos/js/admin_videos.js
index 9bb61ed1..2a4f462c 100644
--- a/3.1/modules/videos/js/admin_videos.js
+++ b/3.1/modules/videos/js/admin_videos.js
@@ -2,6 +2,11 @@
* Set up autocomplete on the server path list
*
*/
+/**
+ * rWatcher Edit: This file used to be admin.js from server_add module.
+ * All occurences of server_add have been replaced with videos
+ *
+ */
$("document").ready(function() {
$("#g-path").autocomplete(
base_url.replace("__ARGS__", "admin/videos/autocomplete"), {max: 256});
diff --git a/3.1/modules/videos/js/videos.js b/3.1/modules/videos/js/videos.js
index 02dda4c0..27627193 100644
--- a/3.1/modules/videos/js/videos.js
+++ b/3.1/modules/videos/js/videos.js
@@ -1,36 +1,41 @@
+/**
+ * rWatcher Edit: This file used to be server_add.js from server_add module.
+ * All occurences of server-add have been replaced with videos
+ *
+ */
(function($) {
- $.widget("ui.gallery_server_add", {
+ $.widget("ui.gallery_videos", {
_init: function() {
var self = this;
- $("#g-server-add-add-button", this.element).click(function(event) {
+ $("#g-videos-add-button", this.element).click(function(event) {
event.preventDefault();
$(".g-progress-bar", this.element).
progressbar().
progressbar("value", 0);
- $("#g-server-add-progress", this.element).slideDown("fast", function() { self.start_add(); });
+ $("#g-videos-progress", this.element).slideDown("fast", function() { self.start_add(); });
});
- $("#g-server-add-pause-button", this.element).click(function(event) {
+ $("#g-videos-pause-button", this.element).click(function(event) {
self.pause = true;
- $("#g-server-add-pause-button", this.element).hide();
- $("#g-server-add-continue-button", this.element).show();
+ $("#g-videos-pause-button", this.element).hide();
+ $("#g-videos-continue-button", this.element).show();
});
- $("#g-server-add-continue-button", this.element).click(function(event) {
+ $("#g-videos-continue-button", this.element).click(function(event) {
self.pause = false;
- $("#g-server-add-pause-button", this.element).show();
- $("#g-server-add-continue-button", this.element).hide();
+ $("#g-videos-pause-button", this.element).show();
+ $("#g-videos-continue-button", this.element).hide();
self.run_add();
});
- $("#g-server-add-close-button", this.element).click(function(event) {
+ $("#g-videos-close-button", this.element).click(function(event) {
$("#g-dialog").dialog("close");
window.location.reload();
});
- $("#g-server-add-tree span.g-directory", this.element).dblclick(function(event) {
+ $("#g-videos-tree span.g-directory", this.element).dblclick(function(event) {
self.open_dir(event);
});
- $("#g-server-add-tree span.g-file, #g-server-add-tree span.g-directory", this.element).click(function(event) {
+ $("#g-videos-tree span.g-file, #g-videos-tree span.g-directory", this.element).click(function(event) {
self.select_file(event);
});
- $("#g-server-add-tree span.g-directory", this.element).dblclick(function(event) {
+ $("#g-videos-tree span.g-directory", this.element).dblclick(function(event) {
self.open_dir(event);
});
$("#g-dialog").bind("dialogclose", function(event, ui) {
@@ -48,8 +53,8 @@
paths.push($(this).attr("ref"));
});
- $("#g-server-add-add-button", this.element).hide();
- $("#g-server-add-pause-button", this.element).show();
+ $("#g-videos-add-button", this.element).hide();
+ $("#g-videos-pause-button", this.element).show();
$.ajax({
url: START_URL,
@@ -77,10 +82,10 @@
$("#g-status").html(data.status);
$(".g-progress-bar", self.element).progressbar("value", data.percent_complete);
if (data.done) {
- $("#g-server-add-progress", this.element).slideUp();
- $("#g-server-add-add-button", this.element).show();
- $("#g-server-add-pause-button", this.element).hide();
- $("#g-server-add-continue-button", this.element).hide();
+ $("#g-videos-progress", this.element).slideUp();
+ $("#g-videos-add-button", this.element).show();
+ $("#g-videos-pause-button", this.element).hide();
+ $("#g-videos-continue-button", this.element).hide();
} else {
if (!self.pause) {
setTimeout(function() { self.run_add(); }, 25);
@@ -99,11 +104,11 @@
$.ajax({
url: GET_CHILDREN_URL.replace("__PATH__", path),
success: function(data, textStatus) {
- $("#g-server-add-tree", self.element).html(data);
- $("#g-server-add-tree span.g-directory", self.element).dblclick(function(event) {
+ $("#g-videos-tree", self.element).html(data);
+ $("#g-videos-tree span.g-directory", self.element).dblclick(function(event) {
self.open_dir(event);
});
- $("#g-server-add-tree span.g-file, #g-server-add-tree span.g-directory", this.element).click(function(event) {
+ $("#g-videos-tree span.g-file, #g-videos-tree span.g-directory", this.element).click(function(event) {
self.select_file(event);
});
}
@@ -115,10 +120,10 @@
*/
select_file: function (event) {
$(event.target).toggleClass("selected");
- if ($("#g-server-add span.selected").length) {
- $("#g-server-add-add-button").enable(true).removeClass("ui-state-disabled");
+ if ($("#g-videos span.selected").length) {
+ $("#g-videos-add-button").enable(true).removeClass("ui-state-disabled");
} else {
- $("#g-server-add-add-button").enable(false).addClass("ui-state-disabled");
+ $("#g-videos-add-button").enable(false).addClass("ui-state-disabled");
}
}
});
diff --git a/3.1/modules/videos/js/videos_download.js b/3.1/modules/videos/js/videos_download.js
new file mode 100644
index 00000000..b0777ec2
--- /dev/null
+++ b/3.1/modules/videos/js/videos_download.js
@@ -0,0 +1,8 @@
+/**
+ * rWatcher Edit: This file is one of mine.
+ *
+ */
+$("document").ready(function() {
+ var original_url = document.getElementById('g-videos-full-url');
+ $("#g-movie").replaceWith("
");
+});
diff --git a/3.1/modules/videos/models/item.php b/3.1/modules/videos/models/item.php
new file mode 100644
index 00000000..171d664c
--- /dev/null
+++ b/3.1/modules/videos/models/item.php
@@ -0,0 +1,1030 @@
+loaded()) {
+ // Set reasonable defaults
+ $this->created = time();
+ $this->rand_key = random::percent();
+ $this->thumb_dirty = 1;
+ $this->resize_dirty = 1;
+ $this->sort_column = "created";
+ $this->sort_order = "ASC";
+ $this->owner_id = identity::active_user()->id;
+ }
+ }
+
+ /**
+ * Add a set of restrictions to any following queries to restrict access only to items
+ * viewable by the active user.
+ * @chainable
+ */
+ public function viewable() {
+ return item::viewable($this);
+ }
+
+ /**
+ * Is this item an album?
+ * @return true if it's an album
+ */
+ public function is_album() {
+ return $this->type == 'album';
+ }
+
+ /**
+ * Is this item a photo?
+ * @return true if it's a photo
+ */
+ public function is_photo() {
+ return $this->type == 'photo';
+ }
+
+ /**
+ * Is this item a movie?
+ * @return true if it's a movie
+ */
+ public function is_movie() {
+ return $this->type == 'movie';
+ }
+
+ public function delete($ignored_id=null) {
+ if (!$this->loaded()) {
+ // Concurrent deletes may result in this item already being gone. Ignore it.
+ return;
+ }
+
+ if ($this->id == 1) {
+ $v = new Validation(array("id"));
+ $v->add_error("id", "cant_delete_root_album");
+ ORM_Validation_Exception::handle_validation($this->table_name, $v);
+ }
+
+ $old = clone $this;
+ module::event("item_before_delete", $this);
+
+ $parent = $this->parent();
+ if ($parent->album_cover_item_id == $this->id) {
+ item::remove_album_cover($parent);
+ }
+
+ $path = $this->file_path();
+ $resize_path = $this->resize_path();
+ $thumb_path = $this->thumb_path();
+
+ parent::delete();
+ if (is_dir($path)) {
+ // Take some precautions against accidentally deleting way too much
+ $delete_resize_path = dirname($resize_path);
+ $delete_thumb_path = dirname($thumb_path);
+ if ($delete_resize_path == VARPATH . "resizes" ||
+ $delete_thumb_path == VARPATH . "thumbs" ||
+ $path == VARPATH . "albums") {
+ throw new Exception(
+ "@todo DELETING_TOO_MUCH ($delete_resize_path, $delete_thumb_path, $path)");
+ }
+ @dir::unlink($path);
+ @dir::unlink($delete_resize_path);
+ @dir::unlink($delete_thumb_path);
+ } else {
+ @unlink($path);
+ @unlink($resize_path);
+ @unlink($thumb_path);
+ }
+
+ module::event("item_deleted", $old);
+ }
+
+ /**
+ * 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) {
+ $this->data_file = $data_file;
+ return $this;
+ }
+
+ /**
+ * 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($this->relative_url());
+ 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($this->relative_url());
+ 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/" . urldecode($this->relative_path());
+ }
+
+ /**
+ * 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) {
+ $relative_path = "var/albums/" . $this->relative_path();
+ $cache_buster = $this->_cache_buster($this->file_path());
+ return ($full_uri ? url::abs_file($relative_path) : url::file($relative_path))
+ . $cache_buster;
+ }
+
+ /**
+ * album: /var/resizes/album1/.thumb.jpg
+ * photo: /var/albums/album1/photo.thumb.jpg
+ */
+ public function thumb_path() {
+ $base = VARPATH . "thumbs/" . urldecode($this->relative_path());
+ if ($this->is_photo()) {
+ return $base;
+ } else if ($this->is_album()) {
+ return $base . "/.album.jpg";
+ } else if ($this->is_movie()) {
+ // Replace the extension with jpg
+ return preg_replace("/...$/", "jpg", $base);
+ }
+ }
+
+ /**
+ * Return true if there is a thumbnail for this item.
+ */
+ public function has_thumb() {
+ return $this->thumb_width && $this->thumb_height;
+ }
+
+ /**
+ * 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) {
+ $cache_buster = $this->_cache_buster($this->thumb_path());
+ $relative_path = "var/thumbs/" . $this->relative_path();
+ $base = ($full_uri ? url::abs_file($relative_path) : url::file($relative_path));
+ if ($this->is_photo()) {
+ return $base . $cache_buster;
+ } else if ($this->is_album()) {
+ return $base . "/.album.jpg" . $cache_buster;
+ } else if ($this->is_movie()) {
+ // Replace the extension with jpg
+ $base = preg_replace("/...$/", "jpg", $base);
+ return $base . $cache_buster;
+ }
+ }
+
+ /**
+ * album: /var/resizes/album1/.resize.jpg
+ * photo: /var/albums/album1/photo.resize.jpg
+ */
+ public function resize_path() {
+ return VARPATH . "resizes/" . urldecode($this->relative_path()) .
+ ($this->is_album() ? "/.album.jpg" : "");
+ }
+
+ /**
+ * 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) {
+ $relative_path = "var/resizes/" . $this->relative_path();
+ $cache_buster = $this->_cache_buster($this->resize_path());
+ return ($full_uri ? url::abs_file($relative_path) : url::file($relative_path)) .
+ ($this->is_album() ? "/.album.jpg" : "") . $cache_buster;
+ }
+
+ /**
+ * Rebuild the relative_path_cache and relative_url_cache.
+ */
+ private function _build_relative_caches() {
+ $names = array();
+ $slugs = array();
+ foreach (db::build()
+ ->select(array("name", "slug"))
+ ->from("items")
+ ->where("left_ptr", "<=", $this->left_ptr)
+ ->where("right_ptr", ">=", $this->right_ptr)
+ ->where("id", "<>", 1)
+ ->order_by("left_ptr", "ASC")
+ ->execute() as $row) {
+ // Don't encode the names segment
+ $names[] = rawurlencode($row->name);
+ $slugs[] = rawurlencode($row->slug);
+ }
+ $this->relative_path_cache = implode($names, "/");
+ $this->relative_url_cache = implode($slugs, "/");
+ return $this;
+ }
+
+ /**
+ * 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() {
+ if (!$this->loaded()) {
+ return;
+ }
+
+ if (!isset($this->relative_url_cache)) {
+ $this->_build_relative_caches()->save();
+ }
+ return $this->relative_url_cache;
+ }
+
+ /**
+ * @see ORM::__get()
+ */
+ public function __get($column) {
+ if ($column == "owner") {
+ // This relationship depends on an outside module, which may not be present so handle
+ // failures gracefully.
+ try {
+ return identity::lookup_user($this->owner_id);
+ } catch (Exception $e) {
+ return null;
+ }
+ } else {
+ return parent::__get($column);
+ }
+ }
+
+ /**
+ * Handle any business logic necessary to create or modify an item.
+ * @see ORM::save()
+ *
+ * @return ORM Item_Model
+ */
+ public function save() {
+ $significant_changes = $this->changed;
+ unset($significant_changes["view_count"]);
+ unset($significant_changes["relative_url_cache"]);
+ unset($significant_changes["relative_path_cache"]);
+
+ if ((!empty($this->changed) && $significant_changes) || isset($this->data_file)) {
+ $this->updated = time();
+ if (!$this->loaded()) {
+ // Create a new item.
+ module::event("item_before_create", $this);
+
+ // Set a weight if it's missing. We don't do this in the constructor because it's not a
+ // simple assignment.
+ if (empty($this->weight)) {
+ $this->weight = item::get_max_weight();
+ }
+
+ // Make an url friendly slug from the name, if necessary
+ if (empty($this->slug)) {
+ $tmp = pathinfo($this->name, PATHINFO_FILENAME);
+ $tmp = preg_replace("/[^A-Za-z0-9-_]+/", "-", $tmp);
+ $this->slug = trim($tmp, "-");
+
+ // If the filename is all invalid characters, then the slug may be empty here. Pick a
+ // random value.
+ if (empty($this->slug)) {
+ $this->slug = (string)rand(1000, 9999);
+ }
+ }
+
+ // Get the width, height and mime type from our data file for photos and movies.
+ if ($this->is_photo() || $this->is_movie()) {
+ if ($this->is_photo()) {
+ list ($this->width, $this->height, $this->mime_type, $extension) =
+ photo::get_file_metadata($this->data_file);
+ } else if ($this->is_movie()) {
+ list ($this->width, $this->height, $this->mime_type, $extension) =
+ movie::get_file_metadata($this->data_file);
+ }
+
+ // Force an extension onto the name if necessary
+ $pi = pathinfo($this->data_file);
+ if (empty($pi["extension"])) {
+ $this->name = "{$this->name}.$extension";
+ }
+ }
+
+ $this->_randomize_name_or_slug_on_conflict();
+
+ parent::save();
+
+ // Build our url caches, then save again. We have to do this after it's already been
+ // saved once because we use only information from the database to build the paths. If we
+ // could depend on a save happening later we could defer this 2nd save.
+ $this->_build_relative_caches();
+ parent::save();
+
+ // Take any actions that we can only do once all our paths are set correctly after saving.
+ switch ($this->type) {
+ case "album":
+ mkdir($this->file_path());
+ mkdir(dirname($this->thumb_path()));
+ mkdir(dirname($this->resize_path()));
+ break;
+
+ case "photo":
+ case "movie":
+ // The thumb or resize may already exist in the case where a movie and a photo generate
+ // a thumbnail of the same name (eg, foo.flv movie and foo.jpg photo will generate
+ // foo.jpg thumbnail). If that happens, randomize and save again.
+ if (file_exists($this->resize_path()) ||
+ file_exists($this->thumb_path())) {
+ $pi = pathinfo($this->name);
+ $this->name = $pi["filename"] . "-" . random::int() . "." . $pi["extension"];
+ parent::save();
+ }
+
+ copy($this->data_file, $this->file_path());
+ break;
+ }
+
+ // This will almost definitely trigger another save, so put it at the end so that we're
+ // tail recursive. Null out the data file variable first, otherwise the next save will
+ // trigger an item_updated_data_file event.
+ $this->data_file = null;
+ module::event("item_created", $this);
+ } else {
+ // Update an existing item
+ module::event("item_before_update", $item);
+
+ // If any significant fields have changed, load up a copy of the original item and
+ // keep it around.
+ $original = ORM::factory("item", $this->id);
+ if (array_intersect($this->changed, array("parent_id", "name", "slug"))) {
+ $original->_build_relative_caches();
+ $this->relative_path_cache = null;
+ $this->relative_url_cache = null;
+ }
+
+ $this->_randomize_name_or_slug_on_conflict();
+
+ parent::save();
+
+ // Now update the filesystem and any database caches if there were significant value
+ // changes. If anything past this point fails, then we'll have an inconsistent database
+ // so this code should be as robust as we can make it.
+
+ // Update the MPTT pointers, if necessary. We have to do this before we generate any
+ // cached paths!
+ if ($original->parent_id != $this->parent_id) {
+ parent::move_to($this->parent());
+ }
+
+ if ($original->parent_id != $this->parent_id || $original->name != $this->name) {
+ // Move all of the items associated data files
+ @rename($original->file_path(), $this->file_path());
+ if ($this->is_album()) {
+ @rename(dirname($original->resize_path()), dirname($this->resize_path()));
+ @rename(dirname($original->thumb_path()), dirname($this->thumb_path()));
+ } else {
+ @rename($original->resize_path(), $this->resize_path());
+ @rename($original->thumb_path(), $this->thumb_path());
+ }
+
+ if ($original->parent_id != $this->parent_id) {
+ // This will result in 2 events since we'll still fire the item_updated event below
+ module::event("item_moved", $this, $original->parent());
+ }
+ }
+
+ // Changing the name, slug or parent ripples downwards
+ if ($this->is_album() &&
+ ($original->name != $this->name ||
+ $original->slug != $this->slug ||
+ $original->parent_id != $this->parent_id)) {
+ db::build()
+ ->update("items")
+ ->set("relative_url_cache", null)
+ ->set("relative_path_cache", null)
+ ->where("left_ptr", ">", $this->left_ptr)
+ ->where("right_ptr", "<", $this->right_ptr)
+ ->execute();
+ }
+
+ // Replace the data file, if requested.
+ // @todo: we don't handle the case where you swap in a file of a different mime type
+ // should we prevent that in validation? or in set_data_file()
+ if ($this->data_file && ($this->is_photo() || $this->is_movie())) {
+ copy($this->data_file, $this->file_path());
+
+ // Get the width, height and mime type from our data file for photos and movies.
+ if ($this->is_photo()) {
+ list ($this->width, $this->height) = photo::get_file_metadata($this->file_path());
+ } else if ($this->is_movie()) {
+ list ($this->width, $this->height) = movie::get_file_metadata($this->file_path());
+ }
+ $this->thumb_dirty = 1;
+ $this->resize_dirty = 1;
+ }
+
+ module::event("item_updated", $original, $this);
+
+ if ($this->data_file) {
+ // Null out the data file variable here, otherwise this event will trigger another
+ // save() which will think that we're doing another file move.
+ $this->data_file = null;
+ module::event("item_updated_data_file", $this);
+ }
+ }
+ } else if (!empty($this->changed)) {
+ // Insignificant changes only. Don't fire events or do any special checking to try to keep
+ // this lightweight.
+ parent::save();
+ }
+
+ return $this;
+ }
+
+ /**
+ * Check to see if there's another item that occupies the same name or slug that this item
+ * intends to use, and if so choose a new name/slug while preserving the extension.
+ * @todo Improve this. Random numbers are not user friendly
+ */
+ private function _randomize_name_or_slug_on_conflict() {
+ $base_name = pathinfo($this->name, PATHINFO_FILENAME);
+ $base_ext = pathinfo($this->name, PATHINFO_EXTENSION);
+ $base_slug = $this->slug;
+ while (ORM::factory("item")
+ ->where("parent_id", "=", $this->parent_id)
+ ->where("id", $this->id ? "<>" : "IS NOT", $this->id)
+ ->and_open()
+ ->where("name", "=", $this->name)
+ ->or_where("slug", "=", $this->slug)
+ ->close()
+ ->find()->id) {
+ $rand = random::int();
+ if ($base_ext) {
+ $this->name = "$base_name-$rand.$base_ext";
+ } else {
+ $this->name = "$base_name-$rand";
+ }
+ $this->slug = "$base_slug-$rand";
+ }
+ }
+
+ /**
+ * Return the Item_Model representing the cover for this album.
+ * @return Item_Model or null if there's no cover
+ */
+ public function album_cover() {
+ if (!$this->is_album()) {
+ return null;
+ }
+
+ if (empty($this->album_cover_item_id)) {
+ return null;
+ }
+
+ try {
+ return model_cache::get("item", $this->album_cover_item_id);
+ } catch (Exception $e) {
+ // It's possible (unlikely) that the item was deleted, if so keep going.
+ 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.
+ *
+ * This method stands as a backward compatibility for gallery 3.0, and will
+ * be deprecated in version 3.1.
+ */
+ public function get_position($child, $where=array()) {
+ return item::get_position($child, $where);
+ }
+
+ /**
+ * 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) {
+ list ($height, $width) = $this->scale_dimensions($max);
+ if ($center_vertically && $max) {
+ // The constant is divide by 2 to calculate the file and 10 to convert to em
+ $margin_top = (int)(($max - $height) / 20);
+ $extra_attrs["style"] = "margin-top: {$margin_top}em";
+ $extra_attrs["title"] = $this->title;
+ }
+ $attrs = array_merge($extra_attrs,
+ array(
+ "src" => $this->thumb_url(),
+ "alt" => $this->title,
+ "width" => $width,
+ "height" => $height)
+ );
+ // html::image forces an absolute url which we don't want
+ return "
";
+ }
+
+ /**
+ * Calculate the largest width/height that fits inside the given maximum, while preserving the
+ * aspect ratio. Don't upscale.
+ * @param int $max Maximum size of the largest dimension
+ * @return array
+ */
+ public function scale_dimensions($max) {
+ $width = $this->thumb_width;
+ $height = $this->thumb_height;
+
+ if ($width <= $max && $height <= $max) {
+ return array($height, $width);
+ }
+
+ if ($height) {
+ if (isset($max)) {
+ if ($width > $height) {
+ $height = (int)($max * $height / $width);
+ $width = $max;
+ } else {
+ $width = (int)($max * $width / $height);
+ $height = $max;
+ }
+ }
+ } else {
+ // Missing thumbnail, can happen on albums with no photos yet.
+ // @todo we should enforce a placeholder for those albums.
+ $width = 0;
+ $height = 0;
+ }
+ return array($height, $width);
+ }
+
+ /**
+ * 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) {
+ $attrs = array_merge($extra_attrs,
+ array("src" => $this->resize_url(),
+ "alt" => $this->title,
+ "width" => $this->resize_width,
+ "height" => $this->resize_height)
+ );
+ // html::image forces an absolute url which we don't want
+ return "
";
+ }
+
+ /**
+ * Return a flowplayer
- } ?>
diff --git a/3.1/modules/videos/views/videos_tree.html.php b/3.1/modules/videos/views/videos_tree.html.php
index 91354329..366d4fb4 100644
--- a/3.1/modules/videos/views/videos_tree.html.php
+++ b/3.1/modules/videos/views/videos_tree.html.php
@@ -1,4 +1,5 @@
+ // rWatcher Edit: This file used to be server_add_tree.html.php ?>
diff --git a/3.1/modules/videos/views/videos_tree_dialog.html.php b/3.1/modules/videos/views/videos_tree_dialog.html.php
index a235ffbf..a0c0f7b7 100644
--- a/3.1/modules/videos/views/videos_tree_dialog.html.php
+++ b/3.1/modules/videos/views/videos_tree_dialog.html.php
@@ -1,13 +1,14 @@
+ // rWatcher Edit: This file used to be server_add_tree_dialog.html.php, server_add has been replaced with videos ?>
-
-
= t("Add Videos to '%title'", array("title" => html::purify($item->title))) ?>
+
+
= t("Add Photos to '%title'", array("title" => html::purify($item->title))) ?>
-
= t("Videos will be added to album:") ?>
+
= t("Photos will be added to album:") ?>
$i = 0 ?>
foreach ($item->parents() as $parent): ?>
@@ -17,35 +18,35 @@
= html::purify($item->title) ?>
-
+
-
+
-
= t("Add") ?>
-
+
= t("Pause") ?>
-
+
= t("Continue") ?>
-
+
= t("Close") ?>