PageRenderTime 51ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/server_add/controllers/server_add.php

https://github.com/cybot35/gallery3
PHP | 300 lines | 83 code | 16 blank | 201 comment | 11 complexity | 9ec04c82046649bf34902995d9a18916 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php defined("SYSPATH") or die("No direct script access.");
  2. /**
  3. * Gallery - a web based photo album viewer and editor
  4. * Copyright (C) 2000-2010 Bharat Mediratta
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. class Server_Add_Controller extends Admin_Controller {
  21. public function browse($id) {
  22. $paths = unserialize(module::get_var("server_add", "authorized_paths"));
  23. foreach (array_keys($paths) as $path) {
  24. $files[] = $path;
  25. }
  26. $item = ORM::factory("item", $id);
  27. $view = new View("server_add_tree_dialog.html");
  28. $view->item = $item;
  29. $view->tree = new View("server_add_tree.html");
  30. $view->tree->files = $files;
  31. $view->tree->parents = array();
  32. print $view;
  33. }
  34. public function children() {
  35. $path = Input::instance()->get("path");
  36. $tree = new View("server_add_tree.html");
  37. $tree->files = array();
  38. $tree->parents = array();
  39. // Make a tree with the parents back up to the authorized path, and all the children under the
  40. // current path.
  41. if (server_add::is_valid_path($path)) {
  42. $tree->parents[] = $path;
  43. while (server_add::is_valid_path(dirname($tree->parents[0]))) {
  44. array_unshift($tree->parents, dirname($tree->parents[0]));
  45. }
  46. $glob_path = str_replace(array("{", "}", "[", "]"), array("\{", "\}", "\[", "\]"), $path);
  47. foreach (glob("$glob_path/*") as $file) {
  48. if (!is_readable($file)) {
  49. continue;
  50. }
  51. if (!is_dir($file)) {
  52. $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
  53. if (!in_array($ext, array("gif", "jpeg", "jpg", "png", "flv", "mp4", "m4v"))) {
  54. continue;
  55. }
  56. }
  57. $tree->files[] = $file;
  58. }
  59. } else {
  60. // Missing or invalid path; print out the list of authorized path
  61. $paths = unserialize(module::get_var("server_add", "authorized_paths"));
  62. foreach (array_keys($paths) as $path) {
  63. $tree->files[] = $path;
  64. }
  65. }
  66. print $tree;
  67. }
  68. /**
  69. * Begin the task of adding photos.
  70. */
  71. public function start() {
  72. access::verify_csrf();
  73. $item = ORM::factory("item", Input::instance()->get("item_id"));
  74. foreach (Input::instance()->post("paths") as $path) {
  75. if (server_add::is_valid_path($path)) {
  76. $paths[] = array($path, null);
  77. }
  78. }
  79. $task_def = Task_Definition::factory()
  80. ->callback("Server_Add_Controller::add")
  81. ->description(t("Add photos or movies from the local server"))
  82. ->name(t("Add from server"));
  83. $task = task::create($task_def, array("item_id" => $item->id, "queue" => $paths));
  84. json::reply(
  85. array("result" => "started",
  86. "status" => (string)$task->status,
  87. "url" => url::site("server_add/run/$task->id?csrf=" . access::csrf_token())));
  88. }
  89. /**
  90. * Run the task of adding photos
  91. */
  92. function run($task_id) {
  93. access::verify_csrf();
  94. $task = ORM::factory("task", $task_id);
  95. if (!$task->loaded() || $task->owner_id != identity::active_user()->id) {
  96. access::forbidden();
  97. }
  98. $task = task::run($task_id);
  99. // Prevent the JavaScript code from breaking by forcing a period as
  100. // decimal separator for all locales with sprintf("%F", $value).
  101. json::reply(array("done" => (bool)$task->done,
  102. "status" => (string)$task->status,
  103. "percent_complete" => sprintf("%F", $task->percent_complete)));
  104. }
  105. /**
  106. * This is the task code that adds photos and albums. It first examines all the target files
  107. * and creates a set of Server_Add_File_Models, then runs through the list of models and adds
  108. * them one at a time.
  109. */
  110. static function add($task) {
  111. $mode = $task->get("mode", "init");
  112. $start = microtime(true);
  113. switch ($mode) {
  114. case "init":
  115. $task->set("mode", "build-file-list");
  116. $task->percent_complete = 0;
  117. $task->status = t("Starting up");
  118. batch::start();
  119. break;
  120. case "build-file-list": // 0% to 10%
  121. // We can't fit an arbitrary number of paths in a task, so store them in a separate table.
  122. // Don't use an iterator here because we can't get enough control over it when we're dealing
  123. // with a deep hierarchy and we don't want to go over our time quota. The queue is in the
  124. // form [path, parent_id] where the parent_id refers to another Server_Add_File_Model. We
  125. // have this extra level of abstraction because we don't know its Item_Model id yet.
  126. $queue = $task->get("queue");
  127. $paths = unserialize(module::get_var("server_add", "authorized_paths"));
  128. while ($queue && microtime(true) - $start < 0.5) {
  129. list($file, $parent_entry_id) = array_shift($queue);
  130. // Ignore the staging directories as directories to be imported.
  131. if (empty($paths[$file])) {
  132. $entry = ORM::factory("server_add_file");
  133. $entry->task_id = $task->id;
  134. $entry->file = $file;
  135. $entry->parent_id = $parent_entry_id;
  136. $entry->save();
  137. $entry_id = $entry->id;
  138. } else {
  139. $entry_id = null;
  140. }
  141. $file = preg_quote($file);
  142. foreach (glob("$file/*") as $child) {
  143. if (is_dir($child)) {
  144. $queue[] = array($child, $entry_id);
  145. } else {
  146. $ext = strtolower(pathinfo($child, PATHINFO_EXTENSION));
  147. if (in_array($ext, array("gif", "jpeg", "jpg", "png", "flv", "mp4", "m4v")) &&
  148. filesize($child) > 0) {
  149. $child_entry = ORM::factory("server_add_file");
  150. $child_entry->task_id = $task->id;
  151. $child_entry->file = $child;
  152. $child_entry->parent_id = $entry_id;
  153. $child_entry->save();
  154. }
  155. }
  156. }
  157. }
  158. // We have no idea how long this can take because we have no idea how deep the tree
  159. // hierarchy rabbit hole goes. Leave ourselves room here for 100 iterations and don't go
  160. // over 10% in percent_complete.
  161. $task->set("queue", $queue);
  162. $task->percent_complete = min($task->percent_complete + 0.1, 10);
  163. $task->status = t2(
  164. "Found one file", "Found %count files",
  165. ORM::factory("server_add_file")->where("task_id", "=", $task->id)->count_all());
  166. if (!$queue) {
  167. $task->set("mode", "add-files");
  168. $task->set(
  169. "total_files",
  170. ORM::factory("server_add_file")->where("task_id", "=", $task->id)->count_all());
  171. $task->percent_complete = 10;
  172. }
  173. break;
  174. case "add-files": // 10% to 100%
  175. $completed_files = $task->get("completed_files", 0);
  176. $total_files = $task->get("total_files");
  177. // Ordering by id ensures that we add them in the order that we created the entries, which
  178. // will create albums first. Ignore entries which already have an Item_Model attached,
  179. // they're done.
  180. $entries = ORM::factory("server_add_file")
  181. ->where("task_id", "=", $task->id)
  182. ->where("item_id", "IS", null)
  183. ->order_by("id", "ASC")
  184. ->limit(10)
  185. ->find_all();
  186. if ($entries->count() == 0) {
  187. // Out of entries, we're done.
  188. $task->set("mode", "done");
  189. }
  190. $owner_id = identity::active_user()->id;
  191. foreach ($entries as $entry) {
  192. if (microtime(true) - $start > 0.5) {
  193. break;
  194. }
  195. // Look up the parent item for this entry. By now it should exist, but if none was
  196. // specified, then this belongs as a child of the current item.
  197. $parent_entry = ORM::factory("server_add_file", $entry->parent_id);
  198. if (!$parent_entry->loaded()) {
  199. $parent = ORM::factory("item", $task->get("item_id"));
  200. } else {
  201. $parent = ORM::factory("item", $parent_entry->item_id);
  202. }
  203. $name = basename($entry->file);
  204. $title = item::convert_filename_to_title($name);
  205. if (is_dir($entry->file)) {
  206. $album = ORM::factory("item");
  207. $album->type = "album";
  208. $album->parent_id = $parent->id;
  209. $album->name = $name;
  210. $album->title = $title;
  211. $album->owner_id = $owner_id;
  212. $album->save();
  213. $entry->item_id = $album->id;
  214. } else {
  215. try {
  216. $extension = strtolower(pathinfo($name, PATHINFO_EXTENSION));
  217. if (in_array($extension, array("gif", "png", "jpg", "jpeg"))) {
  218. $photo = ORM::factory("item");
  219. $photo->type = "photo";
  220. $photo->parent_id = $parent->id;
  221. $photo->set_data_file($entry->file);
  222. $photo->name = $name;
  223. $photo->title = $title;
  224. $photo->owner_id = $owner_id;
  225. $photo->save();
  226. $entry->item_id = $photo->id;
  227. } else if (in_array($extension, array("flv", "mp4", "m4v"))) {
  228. $movie = ORM::factory("item");
  229. $movie->type = "movie";
  230. $movie->parent_id = $parent->id;
  231. $movie->set_data_file($entry->file);
  232. $movie->name = $name;
  233. $movie->title = $title;
  234. $movie->owner_id = $owner_id;
  235. $movie->save();
  236. $entry->item_id = $movie->id;
  237. } else {
  238. // This should never happen, because we don't add stuff to the list that we can't
  239. // process. But just in, case.. set this to a non-null value so that we skip this
  240. // entry.
  241. $entry->item_id = 0;
  242. $task->log("Skipping unknown file type: $entry->file");
  243. }
  244. } catch (Exception $e) {
  245. // This can happen if a photo file is invalid, like a BMP masquerading as a .jpg
  246. $entry->item_id = 0;
  247. $task->log("Skipping invalid file: $entry->file");
  248. }
  249. }
  250. $completed_files++;
  251. $entry->save();
  252. }
  253. $task->set("completed_files", $completed_files);
  254. $task->status = t("Adding photos / albums (%completed of %total)",
  255. array("completed" => $completed_files,
  256. "total" => $total_files));
  257. $task->percent_complete = $total_files ? 10 + 100 * ($completed_files / $total_files) : 100;
  258. break;
  259. case "done":
  260. batch::stop();
  261. $task->done = true;
  262. $task->state = "success";
  263. $task->percent_complete = 100;
  264. db::build()
  265. ->delete("server_add_files")
  266. ->where("task_id", "=", $task->id)
  267. ->execute();
  268. message::info(t2("Successfully added one photo / album",
  269. "Successfully added %count photos / albums",
  270. $task->get("completed_files")));
  271. }
  272. }
  273. }