diff options
| author | Nathan Kinkade <nath@nkinka.de> | 2011-05-12 23:48:54 +0000 | 
|---|---|---|
| committer | Nathan Kinkade <nath@nkinka.de> | 2011-05-12 23:48:54 +0000 | 
| commit | 2ad445441974c64599df496ba4a585415aa41169 (patch) | |
| tree | 49b2860fdac2d2ff16134bfa2aa8d8a972b93301 /modules | |
| parent | 1f7c1f18c651c58048e92d615c71ac0fe6691c10 (diff) | |
| parent | 9aeb824aa1d15bd94bd7cef0a322c4e8a667e67b (diff) | |
Manually merged a conflict after pulling from upstream.
Diffstat (limited to 'modules')
80 files changed, 1760 insertions, 700 deletions
| diff --git a/modules/akismet/module.info b/modules/akismet/module.info index b61ed107..63473468 100644 --- a/modules/akismet/module.info +++ b/modules/akismet/module.info @@ -1,3 +1,7 @@  name = "Akismet"  description = "Filter comments through the Akismet web service to detect and eliminate spam (http://akismet.com).  You'll need a WordPress.com API key to use it."  version = 1 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:akismet" +discuss_url = "http://gallery.menalto.com/forum_module_akismet" diff --git a/modules/comment/controllers/admin_manage_comments.php b/modules/comment/controllers/admin_manage_comments.php index 9bd1d7f6..72684e70 100644 --- a/modules/comment/controllers/admin_manage_comments.php +++ b/modules/comment/controllers/admin_manage_comments.php @@ -28,8 +28,10 @@ class Admin_Manage_Comments_Controller extends Admin_Controller {        ->where("updated", "<", db::expr("UNIX_TIMESTAMP() - 86400 * 7"))        ->execute(); -    // Redirect to the appropriate queue -    url::redirect("admin/manage_comments/queue/unpublished"); +    $view = new Admin_View("admin.html"); +    $view->content = new View("admin_manage_comments.html"); +    $view->content->menu = $this->_menu($this->_counts()); +    print $view;    }    public function menu_labels() { @@ -43,25 +45,32 @@ class Admin_Manage_Comments_Controller extends Admin_Controller {    public function queue($state) {      $page = max(Input::instance()->get("page"), 1); -    $view = new Admin_View("admin.html"); -    $view->page_title = t("Manage comments"); -    $view->content = new View("admin_manage_comments.html"); -    $view->content->counts = $this->_counts(); -    $view->content->menu = $this->_menu($view->content->counts); -    $view->content->state = $state; -    $view->content->comments = ORM::factory("comment") +    $view = new Gallery_View("admin_manage_comments_queue.html"); +    $view->counts = $this->_counts(); +    $view->menu = $this->_menu($view->counts); +    $view->state = $state; +    $view->comments = ORM::factory("comment")        ->order_by("created", "DESC")        ->order_by("id", "DESC")        ->where("state", "=", $state)        ->limit(self::$items_per_page)        ->offset(($page - 1) * self::$items_per_page)        ->find_all(); -    $view->content->pager = new Pagination(); -    $view->content->pager->initialize( -      array("query_string" => "page", -            "total_items" => $view->content->counts->$state, -            "items_per_page" => self::$items_per_page, -            "style" => "classic")); + +    // This view is not themed so we can't use $theme->url() in the view and have to +    // reproduce Gallery_View::url() logic here. +    $atn = theme::$admin_theme_name; +    $view->fallback_avatar_url = url::abs_file("themes/$atn/images/avatar.jpg"); + +    $view->page = $page; +    $view->page_type = "collection"; +    $view->page_subtype = "admin_comments"; +    $view->page_size = self::$items_per_page; +    $view->children_count = $this->_counts()->$state; +    $view->max_pages = ceil($view->children_count / $view->page_size); + +    // Also we want to use $theme->paginator() so we need a dummy theme +    $view->theme = $view;      print $view;    } diff --git a/modules/comment/module.info b/modules/comment/module.info index e5aa454d..4e7df6f1 100644 --- a/modules/comment/module.info +++ b/modules/comment/module.info @@ -1,3 +1,7 @@  name = "Comments"  description = "Allows users and guests to leave comments on photos and albums."  version = 4 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:comment" +discuss_url = "http://gallery.menalto.com/forum_module_comment" diff --git a/modules/comment/views/admin_manage_comments.html.php b/modules/comment/views/admin_manage_comments.html.php index 34a28986..e3c8546c 100644 --- a/modules/comment/views/admin_manage_comments.html.php +++ b/modules/comment/views/admin_manage_comments.html.php @@ -2,200 +2,45 @@  <script type="text/javascript">    var set_state_url =      <?= html::js_string(url::site("admin/manage_comments/set_state/__ID__/__STATE__?csrf=$csrf")) ?>; -  function set_state(state, id) { -    $.get(set_state_url.replace("__STATE__", state).replace("__ID__", id), +  var set_state = function(state, id) { +    $("#g-comment-" + id).fadeOut("fast", function() { +      $.get(set_state_url.replace("__STATE__", state).replace("__ID__", id),            {}, -          function() { -            $("#g-comment-" + id).slideUp(); -            update_menu(); -          }); +          update_menu); +      });    } -  var delete_url = -    <?= html::js_string(url::site("admin/manage_comments/delete/__ID__?csrf=$csrf")) ?>; - -  function del(id) { -    $.get(delete_url.replace("__ID__", id), -          {}, -          function() { -            $("#g-comment-" + id).slideUp(); -            update_menu(); -          }); -  } - -  function update_menu() { +  var update_menu = function() {      $.get(<?= html::js_string(url::site("admin/manage_comments/menu_labels")) ?>, {},            function(data) {              for (var i = 0; i < data.length; i++) { -              $("#g-admin-comments-menu li:eq(" + i + ") a").html(data[i]); +              $("#g-admin-comments ul li:eq(" + i + ") a").html(data[i]);              }            },            "json");    } -</script> - -<div id="g-admin-comments" class="g-block"> -  <h1> <?= t("Manage comments") ?> </h1> -  <div class="g-block-content"> -    <!-- @todo: Highlight active menu option --> -    <div id="g-admin-comments-menu" class="ui-helper-clearfix"> -      <?= $menu->render() ?> -    </div> - -    <!-- @todo: Remove after setting active option? --> -    <h2> -      <? if ($state == "published"): ?> -      <?= t("Approved comments") ?> -      <? elseif ($state == "unpublished"): ?> -      <?= t("Comments awaiting moderation") ?> -      <? elseif ($state == "spam"): ?> -      <?= t("Spam comments") ?> -      <? elseif ($state == "deleted"): ?> -      <?= t("Recently deleted comments") ?> -      <? endif ?> -    </h2> - -    <? if ($state == "spam"): ?> -    <div> -      <? $spam_caught = module::get_var("comment", "spam_caught") ?> -      <? if ($spam_caught > 0): ?> -      <p> -        <?= t2("Gallery has caught %count spam for you since you installed spam filtering.", -               "Gallery has caught %count spam for you since you installed spam filtering.", -               $spam_caught) ?> -      </p> -      <? endif ?> -      <p> -        <? if ($counts->spam): ?> -        <?= t2("There is currently one comment in your spam queue.  You can delete it with a single click, but there is no undo operation so you may want to check the message first to make sure that it really is spam.", -               "There are currently %count comments in your spam queue.  You can delete them all with a single click, but there is no undo operation so you may want to check the messages first to make sure that they really are spam.  All spam messages will be deleted after 7 days automatically.", -               $counts->spam) ?> -      </p> -      <p> -        <a href="<?= url::site("admin/manage_comments/delete_all_spam?csrf=$csrf") ?>"> -          <?= t("Delete all spam") ?> -        </a> -        <? else: ?> -        <?= t("Your spam queue is empty!") ?> -        <? endif ?> -      </p> -    </div> -    <? endif ?> - -    <? if ($state == "deleted"): ?> -    <div> -      <p> -        <?= t("These are messages that have been recently deleted.  They will be permanently erased automatically after 7 days.") ?> -      </p> -    </div> -    <? endif ?> - -    <table id="g-admin-comments-list"> -      <tr> -        <th> -          <?= t("Author") ?> -        </th> -        <th> -          <?= t("Comment") ?> -        </th> -        <th> -          <?= t("Actions") ?> -        </th> -      </tr> -      <? foreach ($comments as $comment): ?> -      <tr id="g-comment-<?= $comment->id ?>" class="<?= text::alternate("g-odd", "g-even") ?>"> -        <td> -          <a href="#"> -            <img src="<?= $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>" -                 class="g-avatar" -                 alt="<?= html::clean_attribute($comment->author_name()) ?>" -                 width="40" -                 height="40" /> -          </a> -          <p><a href="mailto:<?= html::clean_attribute($comment->author_email()) ?>" -                title="<?= html::clean_attribute($comment->author_email()) ?>"> <?= html::clean($comment->author_name()) ?> </a></p> -        </td> -        <td> -          <div class="g-right"> -            <? $item = $comment->item() ?> -            <div class="g-item g-photo"> -              <a href="<?= $item->url() ?>"> -                <? if ($item->has_thumb()): ?> -                <img src="<?= $item->thumb_url() ?>" -                   alt="<?= html::purify($item->title)->for_html_attr() ?>" -                   <?= photo::img_dimensions($item->thumb_width, $item->thumb_height, 75) ?> -                /> -                <? else: ?> -                <?= t("No thumbnail") ?> -                <? endif ?> -              </a> -            </div> -          </div> -          <p><?= gallery::date($comment->created) ?></p> -             <?= nl2br(html::purify($comment->text)) ?> -        </td> -        <td> -          <ul class="g-buttonset-vertical"> -          <? if ($comment->state != "unpublished"): ?> -            <li> -              <a href="javascript:set_state('unpublished',<?=$comment->id?>)" -                  class="g-button ui-state-default ui-icon-left"> -                <span class="ui-icon ui-icon-check"></span> -                <?= t("Unapprove") ?> -              </a> -            </li> -          <? endif ?> -          <? if ($comment->state != "published"): ?> -            <li> -              <a href="javascript:set_state('published',<?=$comment->id?>)" -                  class="g-button ui-state-default ui-icon-left"> -                <span class="ui-icon ui-icon-check"></span> -                <?= t("Approve") ?> -              </a> -            </li> -          <? endif ?> -          <? if ($comment->state != "spam"): ?> -            <li> -              <a href="javascript:set_state('spam',<?=$comment->id?>)" -                  class="g-button ui-state-default ui-icon-left"> -                <span class="ui-icon ui-icon-cancel"></span> -                <?= t("Spam") ?> -              </a> -            </li> -          <? endif ?> -            <!-- -            <li> -              <a href="javascript:reply(<?=$comment->id?>)" -                  class="g-button ui-state-default ui-icon-left"> -                <span class="ui-icon ui-icon-arrowreturnthick-1-w"></span> -                <?= t("Reply") ?> -              </a> -            </li> -            <li> -              <a href="javascript:Edit(<?=$comment->id?>)" -                  class="g-button ui-state-default ui-icon-left"> -                <span class="ui-icon ui-icon-pencil"></span> -                <?= t("Edit") ?> -              </a> -            </li> -            --> -            <li> -              <a href="javascript:set_state('deleted',<?=$comment->id?>)" -                  class="g-button ui-state-default ui-icon-left"> -                <span class="ui-icon ui-icon-trash"></span> -                <?= t("Delete") ?> -              </a> -            </li> -          </ul> -        </td> -      </tr> -      <? endforeach ?> -    </table> +  // Paginator clicks load their href in the active tab panel +  var fix_links = function() { +    $(".g-paginator a, a#g-delete-all-spam").click(function(event) { +      event.stopPropagation(); +      $.scrollTo(0, 800, { easing: "swing" }); +      $(this).parents(".ui-tabs-panel").load( +        $(this).attr("href"), +        function() { +          fix_links(); +        }); +      return false; +    }); +  } -    <div class="g-paginator"> -      <?= $pager ?> -    </div> +  $(document).ready(function() { +    $("#g-admin-comments").tabs({ +      show: fix_links, +    }); +  }); +</script> -  </div> +<div id="g-admin-comments" class="g-block"> +  <?= $menu->render() ?>  </div> diff --git a/modules/comment/views/admin_manage_comments_queue.html.php b/modules/comment/views/admin_manage_comments_queue.html.php new file mode 100644 index 00000000..d847d729 --- /dev/null +++ b/modules/comment/views/admin_manage_comments_queue.html.php @@ -0,0 +1,157 @@ +<?php defined("SYSPATH") or die("No direct script access.") ?> +<div class="g-block-content"> +  <? if ($state == "spam"): ?> +  <div> +    <? $spam_caught = module::get_var("comment", "spam_caught") ?> +    <? if ($spam_caught > 0): ?> +    <p> +      <?= t2("Gallery has caught %count spam for you since you installed spam filtering.", +             "Gallery has caught %count spam for you since you installed spam filtering.", +             $spam_caught) ?> +    </p> +    <? endif ?> +    <p> +      <? if ($counts->spam): ?> +      <?= t2("There is currently one comment in your spam queue.  You can delete it with a single click, but there is no undo operation so you may want to check the message first to make sure that it really is spam.", +             "There are currently %count comments in your spam queue.  You can delete them all with a single click, but there is no undo operation so you may want to check the messages first to make sure that they really are spam.  All spam messages will be deleted after 7 days automatically.", +             $counts->spam) ?> +    </p> +    <p> +      <a id="g-delete-all-spam" +         href="<?= url::site("admin/manage_comments/delete_all_spam?csrf=$csrf") ?>"> +        <?= t("Delete all spam") ?> +      </a> +      <? else: ?> +      <?= t("Your spam queue is empty!") ?> +      <? endif ?> +    </p> +  </div> +  <? endif ?> + +  <? if ($state == "deleted"): ?> +  <div> +    <p> +      <?= t("These are messages that have been recently deleted.  They will be permanently erased automatically after 7 days.") ?> +    </p> +  </div> +  <? endif ?> + +  <div class="g-paginator"> +    <?= $theme->paginator() ?> +  </div> +  <table id="g-admin-comments-list"> +    <tr> +      <th> +        <?= t("Author") ?> +      </th> +      <th> +        <?= t("Comment") ?> +      </th> +      <th> +        <?= t("Actions") ?> +      </th> +    </tr> +    <? foreach ($comments as $comment): ?> +    <tr id="g-comment-<?= $comment->id ?>" class="<?= text::alternate("g-odd", "g-even") ?>"> +      <td> +        <a href="#"> +          <img src="<?= $comment->author()->avatar_url(40, $fallback_avatar_url) ?>" +               class="g-avatar" +               alt="<?= html::clean_attribute($comment->author_name()) ?>" +               width="40" +               height="40" /> +        </a> +        <p> +          <a href="mailto:<?= html::clean_attribute($comment->author_email()) ?>" +             title="<?= html::clean_attribute($comment->author_email()) ?>"> +            <?= html::clean($comment->author_name()) ?> +          </a> +        </p> +      </td> +      <td> +        <div class="g-right"> +          <? $item = $comment->item() ?> +          <div class="g-item g-photo"> +            <a href="<?= $item->url() ?>"> +              <? if ($item->has_thumb()): ?> +              <img src="<?= $item->thumb_url() ?>" +                 alt="<?= html::purify($item->title)->for_html_attr() ?>" +                 <?= photo::img_dimensions($item->thumb_width, $item->thumb_height, 75) ?> +              /> +              <? else: ?> +              <?= t("No thumbnail") ?> +              <? endif ?> +            </a> +          </div> +        </div> +        <p><?= gallery::date($comment->created) ?></p> +           <?= nl2br(html::purify($comment->text)) ?> +      </td> +      <td> +        <ul class="g-buttonset-vertical"> +        <? if ($comment->state != "unpublished" && $comment->state != "deleted"): ?> +          <li> +            <a href="javascript:set_state('unpublished',<?=$comment->id?>)" +                class="g-button ui-state-default ui-icon-left"> +              <span class="ui-icon ui-icon-check"></span> +              <?= t("Unapprove") ?> +            </a> +          </li> +        <? endif ?> +        <? if ($comment->state != "published"): ?> +          <li> +            <a href="javascript:set_state('published',<?=$comment->id?>)" +                class="g-button ui-state-default ui-icon-left"> +              <span class="ui-icon ui-icon-check"></span> +              <? if ($state == "deleted"): ?> +              <?= t("Undelete") ?> +              <? else: ?> +              <?= t("Approve") ?> +              <? endif ?> +            </a> +          </li> +        <? endif ?> +        <? if ($comment->state != "spam"): ?> +          <li> +            <a href="javascript:set_state('spam',<?=$comment->id?>)" +                class="g-button ui-state-default ui-icon-left"> +              <span class="ui-icon ui-icon-cancel"></span> +              <?= t("Spam") ?> +            </a> +          </li> +        <? endif ?> +          <!-- +          <li> +            <a href="javascript:reply(<?=$comment->id?>)" +                class="g-button ui-state-default ui-icon-left"> +              <span class="ui-icon ui-icon-arrowreturnthick-1-w"></span> +              <?= t("Reply") ?> +            </a> +          </li> +          <li> +            <a href="javascript:Edit(<?=$comment->id?>)" +                class="g-button ui-state-default ui-icon-left"> +              <span class="ui-icon ui-icon-pencil"></span> +              <?= t("Edit") ?> +            </a> +          </li> +          --> +        <? if ($comment->state != "deleted"): ?> +          <li> +            <a href="javascript:set_state('deleted',<?=$comment->id?>)" +                class="g-button ui-state-default ui-icon-left"> +              <span class="ui-icon ui-icon-trash"></span> +              <?= t("Delete") ?> +            </a> +          </li> +        <? endif ?> +        </ul> +      </td> +    </tr> +    <? endforeach ?> +  </table> + +  <div class="g-paginator"> +    <?= $theme->paginator() ?> +  </div> +</div> diff --git a/modules/digibug/controllers/digibug.php b/modules/digibug/controllers/digibug.php index 4acb6513..672afe57 100644 --- a/modules/digibug/controllers/digibug.php +++ b/modules/digibug/controllers/digibug.php @@ -33,8 +33,8 @@ class Digibug_Controller extends Controller {        $proxy->uuid = random::hash();        $proxy->item_id = $item->id;        $proxy->save(); -      $full_url = url::abs_site("digibug/print_proxy/full/$proxy->uuid"); -      $thumb_url = url::abs_site("digibug/print_proxy/thumb/$proxy->uuid"); +      $full_url = url::abs_site("digibug/print_proxy/full/$proxy->uuid/$item->id"); +      $thumb_url = url::abs_site("digibug/print_proxy/thumb/$proxy->uuid/$item->id");      }      $v = new View("digibug_form.html"); @@ -114,7 +114,7 @@ class Digibug_Controller extends Controller {    private function _clean_expired() {      db::build()        ->delete("digibug_proxies") -      ->where("request_date", "<=", db::expr("(CURDATE() - INTERVAL 10 DAY)")) +      ->where("request_date", "<=", db::expr("(CURDATE() - INTERVAL 90 DAY)"))        ->limit(20)        ->execute();    } diff --git a/modules/digibug/module.info b/modules/digibug/module.info index be4e880a..781d5f01 100644 --- a/modules/digibug/module.info +++ b/modules/digibug/module.info @@ -1,3 +1,7 @@  name = "Digibug"  description = "Digibug Photo Printing Module"  version = 2 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:digibug" +discuss_url = "http://gallery.menalto.com/forum_module_digibug" diff --git a/modules/exif/module.info b/modules/exif/module.info index c8ae688e..e266e20e 100644 --- a/modules/exif/module.info +++ b/modules/exif/module.info @@ -1,3 +1,7 @@  name = "Exif Data"  description = "Extract Exif data and display it on photo pages."  version = 1 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:exif" +discuss_url = "http://gallery.menalto.com/forum_module_exif" diff --git a/modules/g2_import/controllers/admin_g2_import.php b/modules/g2_import/controllers/admin_g2_import.php index 33186fb5..1a705bea 100644 --- a/modules/g2_import/controllers/admin_g2_import.php +++ b/modules/g2_import/controllers/admin_g2_import.php @@ -24,23 +24,42 @@ class Admin_g2_import_Controller extends Admin_Controller {        g2_import::init();      } -    if (class_exists("GalleryCoreApi")) { -      $g2_stats = g2_import::stats(); -      $g2_sizes = g2_import::common_sizes(); -    } -      $view = new Admin_View("admin.html");      $view->page_title = t("Gallery 2 import");      $view->content = new View("admin_g2_import.html"); + +    if (class_exists("GalleryCoreApi")) { +      $view->content->g2_stats = $g2_stats = g2_import::g2_stats(); +      $view->content->g3_stats = $g3_stats = g2_import::g3_stats(); +      $view->content->g2_sizes = g2_import::common_sizes(); +      $view->content->g2_version = g2_import::version(); + +      // Don't count tags because we don't track them in g2_map +      $view->content->g2_resource_count = +        $g2_stats["users"] + $g2_stats["groups"] + $g2_stats["albums"] + +        $g2_stats["photos"] + $g2_stats["movies"] + $g2_stats["comments"]; +      $view->content->g3_resource_count = +        $g3_stats["user"] + $g3_stats["group"] + $g3_stats["album"] + +        $g3_stats["item"] + $g3_stats["comment"] + $g3_stats["tag"]; +    } +      $view->content->form = $this->_get_import_form();      $view->content->version = ""; +    $view->content->thumb_size = module::get_var("gallery", "thumb_size"); +    $view->content->resize_size = module::get_var("gallery", "resize_size");      if (g2_import::is_initialized()) { -      $view->content->g2_stats = $g2_stats; -      $view->content->g2_sizes = $g2_sizes; -      $view->content->thumb_size = module::get_var("gallery", "thumb_size"); -      $view->content->resize_size = module::get_var("gallery", "resize_size"); -      $view->content->version = g2_import::version(); +      if ((bool)ini_get("eaccelerator.enable") || (bool)ini_get("xcache.cacher")) { +        message::warning(t("The eAccelerator and XCache PHP performance extensions are known to cause issues.  If you're using either of those and are having problems, please disable them while you do your import.  Add the following lines: <pre>%lines</pre> to gallery3/.htaccess and remove them when the import is done.", array("lines" => "\n\n  php_value eaccelerator.enable 0\n  php_value xcache.cacher off\n  php_value xcache.optimizer off\n\n"))); +      } + +      foreach (array("notification", "search", "exif") as $module_id) { +        if (module::is_active($module_id)) { +          message::warning( +            t("<a href=\"%url\">Deactivating</a> the <b>%module_id</b> module during your import will make it faster", +              array("url" => url::site("admin/modules"), "module_id" => $module_id))); +        } +      }      } else if (g2_import::is_configured()) {        $view->content->form->configure_g2_import->embed_path->add_error("invalid", 1);      } @@ -59,12 +78,12 @@ class Admin_g2_import_Controller extends Admin_Controller {          $embed_path = "$embed_path/embed.php";        } -      if (g2_import::is_valid_embed_path($embed_path)) { +      if (($g2_init_error = g2_import::is_valid_embed_path($embed_path)) == "ok") {          message::success(t("Gallery 2 path saved"));          module::set_var("g2_import", "embed_path", $embed_path);          url::redirect("admin/g2_import");        } else { -        $form->configure_g2_import->embed_path->add_error("invalid", 1); +        $form->configure_g2_import->embed_path->add_error($g2_init_error, 1);        }      } @@ -75,15 +94,37 @@ class Admin_g2_import_Controller extends Admin_Controller {      print $view;    } +  public function autocomplete() { +    $directories = array(); +    $path_prefix = Input::instance()->get("q"); +    foreach (glob("{$path_prefix}*") as $file) { +      if (is_dir($file) && !is_link($file)) { +        $directories[] = $file; + +        // If we find an embed.php, include it as well +        if (file_exists("$file/embed.php")) { +          $directories[] = "$file/embed.php"; +        } +      } +    } + +    print implode("\n", $directories); +  } +    private function _get_import_form() { +    $embed_path = module::get_var("g2_import", "embed_path", "");      $form = new Forge(        "admin/g2_import/save", "", "post", array("id" => "g-admin-configure-g2-import-form"));      $group = $form->group("configure_g2_import")->label(t("Configure Gallery 2 Import"));      $group->input("embed_path")->label(t("Filesystem path to your Gallery 2 embed.php file")) -      ->value(module::get_var("g2_import", "embed_path", "")); +      ->value($embed_path);      $group->embed_path->error_messages(        "invalid", t("The path you entered is not a Gallery 2 installation.")); -    $group->submit("")->value(t("Save")); +    $group->embed_path->error_messages( +      "broken", t("Your Gallery 2 install isn't working properly.  Please verify it!")); +    $group->embed_path->error_messages( +      "missing", t("The path you entered does not exist.")); +    $group->submit("")->value($embed_path ? t("Change") : t("Continue"));      return $form;    }  }
\ No newline at end of file diff --git a/modules/g2_import/controllers/g2.php b/modules/g2_import/controllers/g2.php index 6e60bed0..90984e84 100644 --- a/modules/g2_import/controllers/g2.php +++ b/modules/g2_import/controllers/g2.php @@ -41,7 +41,9 @@ class G2_Controller extends Controller {          // (bbcode, embedding) people are using the id style URLs although URL rewriting is enabled.          $where = array(array("g2_id", "=", $id));          $view = $input->get("g2_view"); -        if ($view) { +        if ($view == "core.DownloadItem") { +          $where[] = array("resource_type", "IN", array("file", "resize", "thumbnail", "full")); +        } else if ($view) {            $where[] = array("g2_url", "like", "%g2_view=$view%");          } // else: Assuming that the first search hit is sufficiently good.        } else if ($path) { diff --git a/modules/g2_import/helpers/g2_import.php b/modules/g2_import/helpers/g2_import.php index 22fb68c6..c79a8d36 100644 --- a/modules/g2_import/helpers/g2_import.php +++ b/modules/g2_import/helpers/g2_import.php @@ -31,7 +31,7 @@ class g2_import_Core {    }    static function is_initialized() { -    return g2_import::$init; +    return g2_import::$init == "ok";    }    static function init() { @@ -52,146 +52,163 @@ class g2_import_Core {      if (file_exists($mod_path)) {        dir::unlink($mod_path);      } -    return file_exists($embed_path) && g2_import::init_embed($embed_path); +    return g2_import::init_embed($embed_path);    }    /**     * Initialize the embedded Gallery 2 instance.  Call this before any other Gallery 2 calls. +   * +   * Return values: +   *  "ok"      - the Gallery 2 install is fine +   *  "missing" - the embed path does not exist +   *  "invalid" - the install path is not a valid Gallery 2 code base +   *  "broken"  - the embed path is correct, but the Gallery 2 install is broken     */    static function init_embed($embed_path) {      if (!is_file($embed_path)) { -      return false; +      return "missing";      } -    // Gallery 2 defines a class called Gallery.  So does Gallery 3.  They don't get along.  So do -    // a total hack here and copy over a few critical files (embed.php, main.php, bootstrap.inc -    // and Gallery.class) and munge them so that we can rename the Gallery class to be -    // G2_Gallery.   Is this retarded?  Why yes it is. -    // -    // Store the munged files in a directory that's the md5 hash of the embed path so that -    // multiple import sources don't interfere with each other. - -    $mod_path = VARPATH . "modules/g2_import/" . md5($embed_path); -    if (!file_exists($mod_path) || !file_exists("$mod_path/embed.php")) { -      @dir::unlink($mod_path); -      mkdir($mod_path); +    try { +     // Gallery 2 defines a class called Gallery.  So does Gallery 3.  They don't get along.  So do +     // a total hack here and copy over a few critical files (embed.php, main.php, bootstrap.inc +     // and Gallery.class) and munge them so that we can rename the Gallery class to be +     // G2_Gallery.   Is this retarded?  Why yes it is. +     // +     // Store the munged files in a directory that's the md5 hash of the embed path so that +     // multiple import sources don't interfere with each other. -      $config_dir = dirname($embed_path); -      if (filesize($embed_path) > 200) { -        // Regular install -        $base_dir = $config_dir; -      } else { -        // Multisite install.  Line 2 of embed.php will be something like: -        //   require('/usr/home/bharat/public_html/gallery2/embed.php'); -        $lines = file($embed_path); -        preg_match("#require\('(.*)/embed.php'\);#", $lines[2], $matches); -        $base_dir = $matches[1]; -      } +     $mod_path = VARPATH . "modules/g2_import/" . md5($embed_path); +     if (!file_exists($mod_path) || !file_exists("$mod_path/embed.php")) { +       @dir::unlink($mod_path); +       mkdir($mod_path); -      file_put_contents( -        "$mod_path/embed.php", -        str_replace( -          array( -            "require_once(dirname(__FILE__) . '/modules/core/classes/GalleryDataCache.class');", -            "require(dirname(__FILE__) . '/modules/core/classes/GalleryEmbed.class');"), -          array( -            "require_once('$base_dir/modules/core/classes/GalleryDataCache.class');", -            "require('$base_dir/modules/core/classes/GalleryEmbed.class');"), -          array_merge(array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"), -                      file("$base_dir/embed.php")))); +       $config_dir = dirname($embed_path); +       if (filesize($embed_path) > 200) { +         // Regular install +         $base_dir = $config_dir; +       } else { +         // Multisite install.  Line 2 of embed.php will be something like: +         //   require('/usr/home/bharat/public_html/gallery2/embed.php'); +         $lines = file($embed_path); +         preg_match("#require\('(.*)/embed.php'\);#", $lines[2], $matches); +         $base_dir = $matches[1]; +       } -      file_put_contents( -        "$mod_path/main.php", -        str_replace( -          array( -            "include(dirname(__FILE__) . '/bootstrap.inc');", -            "require_once(dirname(__FILE__) . '/init.inc');"), -          array( -            "include(dirname(__FILE__) . '/bootstrap.inc');", -            "require_once('$base_dir/init.inc');"), -          array_merge(array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"), -                      file("$base_dir/main.php")))); +       file_put_contents( +         "$mod_path/embed.php", +         str_replace( +           array( +             "require_once(dirname(__FILE__) . '/modules/core/classes/GalleryDataCache.class');", +             "require(dirname(__FILE__) . '/modules/core/classes/GalleryEmbed.class');"), +           array( +             "require_once('$base_dir/modules/core/classes/GalleryDataCache.class');", +             "require('$base_dir/modules/core/classes/GalleryEmbed.class');"), +           array_merge( +             array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"), +             file("$base_dir/embed.php")))); -      file_put_contents( -        "$mod_path/bootstrap.inc", -        str_replace( -          array("require_once(dirname(__FILE__) . '/modules/core/classes/Gallery.class');", -                "require_once(dirname(__FILE__) . '/modules/core/classes/GalleryDataCache.class');", -                "define('GALLERY_CONFIG_DIR', dirname(__FILE__));", -                "\$gallery =& new Gallery();", -                "\$GLOBALS['gallery'] =& new Gallery();", -                "\$gallery = new Gallery();"), -          array("require_once(dirname(__FILE__) . '/Gallery.class');", -                "require_once('$base_dir/modules/core/classes/GalleryDataCache.class');", -                "define('GALLERY_CONFIG_DIR', '$config_dir');", -                "\$gallery =& new G2_Gallery();", -                "\$GLOBALS['gallery'] =& new G2_Gallery();", -                "\$gallery = new G2_Gallery();"), -          array_merge(array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"), -                      file("$base_dir/bootstrap.inc")))); +       file_put_contents( +         "$mod_path/main.php", +         str_replace( +           array( +             "include(dirname(__FILE__) . '/bootstrap.inc');", +             "require_once(dirname(__FILE__) . '/init.inc');"), +           array( +             "include(dirname(__FILE__) . '/bootstrap.inc');", +             "require_once('$base_dir/init.inc');"), +           array_merge( +             array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"), +             file("$base_dir/main.php")))); -      file_put_contents( -        "$mod_path/Gallery.class", -        str_replace( -          array("class Gallery", -                "function Gallery"), -          array("class G2_Gallery", -                "function G2_Gallery"), -          array_merge(array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"), -                      file("$base_dir/modules/core/classes/Gallery.class")))); -    } else { -      // Ok, this is a good one.  If you're running a bytecode accelerator and you move your -      // Gallery install, these files sometimes get cached with the wrong path and then fail to -      // load properly. -      // Documented in https://sourceforge.net/apps/trac/gallery/ticket/1253 -      touch("$mod_path/embed.php"); -      touch("$mod_path/main.php"); -      touch("$mod_path/bootstrap.inc"); -      touch("$mod_path/Gallery.class.inc"); -    } +       file_put_contents( +         "$mod_path/bootstrap.inc", +         str_replace( +           array( +             "require_once(dirname(__FILE__) . '/modules/core/classes/Gallery.class');", +             "require_once(dirname(__FILE__) . '/modules/core/classes/GalleryDataCache.class');", +             "define('GALLERY_CONFIG_DIR', dirname(__FILE__));", +             "\$gallery =& new Gallery();", +             "\$GLOBALS['gallery'] =& new Gallery();", +             "\$gallery = new Gallery();"), +           array( +             "require_once(dirname(__FILE__) . '/Gallery.class');", +             "require_once('$base_dir/modules/core/classes/GalleryDataCache.class');", +             "define('GALLERY_CONFIG_DIR', '$config_dir');", +             "\$gallery =& new G2_Gallery();", +             "\$GLOBALS['gallery'] =& new G2_Gallery();", +             "\$gallery = new G2_Gallery();"), +           array_merge( +             array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"), +             file("$base_dir/bootstrap.inc")))); -    require("$mod_path/embed.php"); -    if (!class_exists("GalleryEmbed")) { -      return false; -    } +       file_put_contents( +         "$mod_path/Gallery.class", +         str_replace( +           array("class Gallery", +                 "function Gallery"), +           array("class G2_Gallery", +                 "function G2_Gallery"), +           array_merge( +             array("<?php defined(\"SYSPATH\") or die(\"No direct script access.\") ?>\n"), +             file("$base_dir/modules/core/classes/Gallery.class")))); +     } else { +       // Ok, this is a good one.  If you're running a bytecode accelerator and you move your +       // Gallery install, these files sometimes get cached with the wrong path and then fail to +       // load properly. +       // Documented in https://sourceforge.net/apps/trac/gallery/ticket/1253 +       touch("$mod_path/embed.php"); +       touch("$mod_path/main.php"); +       touch("$mod_path/bootstrap.inc"); +       touch("$mod_path/Gallery.class.inc"); +     } -    $ret = GalleryEmbed::init(); -    if ($ret) { -      Kohana_Log::add("error", "Gallery 2 call failed with: " . $ret->getAsText()); -      return false; -    } +      require("$mod_path/embed.php"); +      if (!class_exists("GalleryEmbed")) { +        return "invalid"; +      } -    $admin_group_id = g2(GalleryCoreApi::getPluginParameter("module", "core", "id.adminGroup")); -    $admins = g2(GalleryCoreApi::fetchUsersForGroup($admin_group_id, 1)); -    $admin_id = current(array_flip($admins)); -    $admin = g2(GalleryCoreApi::loadEntitiesById($admin_id)); -    $GLOBALS["gallery"]->setActiveUser($admin); +      $ret = GalleryEmbed::init(); +      if ($ret) { +        Kohana_Log::add("error", "Gallery 2 call failed with: " . $ret->getAsText()); +        return "broken"; +      } -    // Make sure we have an embed location so that embedded url generation comes out ok.  Without -    // this, the Gallery2 ModRewrite code won't try to do url generation. -    $g2_embed_location = -      g2(GalleryCoreApi::getPluginParameter("module", "rewrite", "modrewrite.embeddedLocation")); +      $admin_group_id = g2(GalleryCoreApi::getPluginParameter("module", "core", "id.adminGroup")); +      $admins = g2(GalleryCoreApi::fetchUsersForGroup($admin_group_id, 1)); +      $admin_id = current(array_flip($admins)); +      $admin = g2(GalleryCoreApi::loadEntitiesById($admin_id)); +      $GLOBALS["gallery"]->setActiveUser($admin); -    if (empty($g2_embed_location)) { +      // Make sure we have an embed location so that embedded url generation comes out ok.  Without +      // this, the Gallery2 ModRewrite code won't try to do url generation.        $g2_embed_location = -        g2(GalleryCoreApi::getPluginParameter("module", "rewrite", "modrewrite.galleryLocation")); -      g2(GalleryCoreApi::setPluginParameter( -           "module", "rewrite", "modrewrite.embeddedLocation", $g2_embed_location)); -      g2($gallery->getStorage()->checkPoint()); -    } +        g2(GalleryCoreApi::getPluginParameter("module", "rewrite", "modrewrite.embeddedLocation")); -    if ($g2_embed_location) { -      self::$g2_base_url = $g2_embed_location; -    } else { -      self::$g2_base_url = $GLOBALS["gallery"]->getUrlGenerator()->generateUrl( -        array(), -        array("forceSessionId" => false, -              "htmlEntities" => false, -              "urlEncode" => false, -              "useAuthToken" => false)); +      if (empty($g2_embed_location)) { +        $g2_embed_location = +          g2(GalleryCoreApi::getPluginParameter("module", "rewrite", "modrewrite.galleryLocation")); +        g2(GalleryCoreApi::setPluginParameter("module", "rewrite", "modrewrite.embeddedLocation", +                                              $g2_embed_location)); +        g2($gallery->getStorage()->checkPoint()); +      } + +      if ($g2_embed_location) { +        self::$g2_base_url = $g2_embed_location; +      } else { +        self::$g2_base_url = $GLOBALS["gallery"]->getUrlGenerator()->generateUrl( +          array(), +          array("forceSessionId" => false, +                "htmlEntities" => false, +                "urlEncode" => false, +                "useAuthToken" => false)); +      } +    } catch (ErrorException $e) { +      Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString()); +      return "broken";      } -    return true; +    return "ok";    }    /** @@ -219,7 +236,7 @@ class g2_import_Core {     * Return a set of statistics about the number of users, groups, albums, photos, movies and     * comments available for import from the Gallery 2 instance.     */ -  static function stats() { +  static function g2_stats() {      global $gallery;      $root_album_id = g2(GalleryCoreApi::getDefaultAlbumId());      $stats["users"] = g2(GalleryCoreApi::fetchUserCount()); @@ -248,6 +265,25 @@ class g2_import_Core {    }    /** +   * Return a set of statistics about the number of users, groups, albums, photos, movies and +   * comments already imported into the Gallery 3 instance. +   */ +  static function g3_stats() { +    $g3_stats = array( +      "album" => 0, "comment" => 0, "item" => 0, "user" => 0, "group" => 0, "tag" => 0); +    foreach (db::build() +             ->select("resource_type") +             ->select(array("C" => 'COUNT("*")')) +             ->from("g2_maps") +             ->where("resource_type", "IN", array("album", "comment", "item", "user", "group")) +             ->group_by("resource_type") +             ->execute() as $row) { +      $g3_stats[$row->resource_type] = $row->C; +    } +    return $g3_stats; +  } + +  /**     * Import a single group.     */    static function import_group(&$queue) { @@ -429,49 +465,8 @@ class g2_import_Core {        $album = ORM::factory("item");        $album->type = "album";        $album->parent_id = self::map($g2_album->getParentId()); -      $album->name = $g2_album->getPathComponent(); -      $album->title = self::_decode_html_special_chars($g2_album->getTitle()); -      $album->title or $album->title = $album->name; -      $album->description = self::_decode_html_special_chars(self::extract_description($g2_album)); -      $album->owner_id = self::map($g2_album->getOwnerId()); -      try { -        $album->view_count = (int) g2(GalleryCoreApi::fetchItemViewCount($g2_album_id)); -      } catch (Exception $e) { -        // @todo log -        $album->view_count = 0; -      } -      $album->created = $g2_album->getCreationTimestamp(); -      $order_map = array( -        "originationTimestamp" => "captured", -        "creationTimestamp" => "created", -        "description" => "description", -        "modificationTimestamp" => "updated", -        "orderWeight" => "weight", -        "pathComponent" => "name", -        "summary" => "description", -        "title" => "title", -        "viewCount" => "view_count"); -      $direction_map = array( -        1 => "ASC", -        ORDER_ASCENDING => "ASC", -        ORDER_DESCENDING => "DESC"); -      // Only consider G2's first sort order -      $g2_order = explode("|", $g2_album->getOrderBy() . ""); -      $g2_order = $g2_order[0]; -      if (empty($g2_order)) { -        $g2_order = g2(GalleryCoreApi::getPluginParameter('module', 'core', 'default.orderBy')); -      } -      $g2_order_direction = explode("|", $g2_album->getOrderDirection() . ""); -      $g2_order_direction = $g2_order_direction[0]; -      if (empty($g2_order_direction)) { -        $g2_order_direction = -          g2(GalleryCoreApi::getPluginParameter('module', 'core', 'default.orderDirection')); -      } -      if (array_key_exists($g2_order, $order_map)) { -        $album->sort_column = $order_map[$g2_order]; -        $album->sort_order = $direction_map[$g2_order_direction]; -      } +      g2_import::set_album_values($album, $g2_album);        try {          $album->save(); @@ -494,17 +489,66 @@ class g2_import_Core {    }    /** +   * Transfer over all the values from a G2 album to a G3 album. +   */ +  static function set_album_values($album, $g2_album) { +    $album->name = $g2_album->getPathComponent(); +    $album->title = self::_decode_html_special_chars($g2_album->getTitle()); +    $album->title or $album->title = $album->name; +    $album->description = self::_decode_html_special_chars(self::extract_description($g2_album)); +    $album->owner_id = self::map($g2_album->getOwnerId()); +    try { +      $album->view_count = (int) g2(GalleryCoreApi::fetchItemViewCount($g2_album_id)); +    } catch (Exception $e) { +      // @todo log +      $album->view_count = 0; +    } +    $album->created = $g2_album->getCreationTimestamp(); + +    $order_map = array( +      "originationTimestamp" => "captured", +      "creationTimestamp" => "created", +      "description" => "description", +      "modificationTimestamp" => "updated", +      "orderWeight" => "weight", +      "pathComponent" => "name", +      "summary" => "description", +      "title" => "title", +      "viewCount" => "view_count"); +    $direction_map = array( +      1 => "ASC", +      ORDER_ASCENDING => "ASC", +      ORDER_DESCENDING => "DESC"); +    // G2 sorts can either be <sort> or <presort>|<sort>.  Right now we can't +    // map presorts so ignore them. +    $g2_order = explode("|", $g2_album->getOrderBy() . ""); +    $g2_order = end($g2_order); +    if (empty($g2_order)) { +      $g2_order = g2(GalleryCoreApi::getPluginParameter('module', 'core', 'default.orderBy')); +    } +    $g2_order_direction = explode("|", $g2_album->getOrderDirection() . ""); +    $g2_order_direction = $g2_order_direction[0]; +    if (empty($g2_order_direction)) { +      $g2_order_direction = +        g2(GalleryCoreApi::getPluginParameter('module', 'core', 'default.orderDirection')); +    } +    if (array_key_exists($g2_order, $order_map)) { +      $album->sort_column = $order_map[$g2_order]; +      $album->sort_order = $direction_map[$g2_order_direction]; +    } +  } + +  /**     * Set the highlight properly for a single album     */    static function set_album_highlight(&$queue) {      // Dequeue the current album and enqueue its children      list($g2_album_id, $children) = each($queue); -    if (empty($children)) { -      return; -    }      unset($queue[$g2_album_id]); -    foreach ($children as $key => $value) { -      $queue[$key] = $value; +    if (!empty($children)) { +      foreach ($children as $key => $value) { +        $queue[$key] = $value; +      }      }      $messages = array(); @@ -516,7 +560,7 @@ class g2_import_Core {      $table = g2(GalleryCoreApi::fetchThumbnailsByItemIds(array($g2_album_id)));      if (isset($table[$g2_album_id])) {        // Backtrack the source id to an item -      $g2_source = $table[$g2_album_id]; +      $orig_g2_source = $g2_source = $table[$g2_album_id];        while (GalleryUtilities::isA($g2_source, "GalleryDerivative")) {          $g2_source = g2(GalleryCoreApi::loadEntitiesById($g2_source->getDerivativeSourceId()));        } @@ -540,6 +584,11 @@ class g2_import_Core {                  array("name" => $g3_album->name)),                $e);          } + +        self::set_map( +          $orig_g2_source->getId(), $g3_album->id, +          "thumbnail", +          self::g2_url(array("view" => "core.DownloadItem", "itemId" => $orig_g2_source->getId())));        }      }    } diff --git a/modules/g2_import/helpers/g2_import_event.php b/modules/g2_import/helpers/g2_import_event.php index 0e078d08..0afa62d8 100644 --- a/modules/g2_import/helpers/g2_import_event.php +++ b/modules/g2_import/helpers/g2_import_event.php @@ -34,7 +34,7 @@ class g2_import_event_Core {        ->get("settings_menu")        ->append(Menu::factory("link")                 ->id("g2_import") -               ->label(t("Gallery 2 Import")) +               ->label(t("Gallery 2 import"))                 ->url(url::site("admin/g2_import")));    }  } diff --git a/modules/g2_import/helpers/g2_import_task.php b/modules/g2_import/helpers/g2_import_task.php index 6bda8f17..31615a55 100644 --- a/modules/g2_import/helpers/g2_import_task.php +++ b/modules/g2_import/helpers/g2_import_task.php @@ -56,7 +56,7 @@ class g2_import_task_Core {      $mode = $task->get("mode");      $queue = $task->get("queue");      if (!isset($mode)) { -      $stats = g2_import::stats(); +      $stats = g2_import::g2_stats();        $stats["items"] = $stats["photos"] + $stats["movies"];        unset($stats["photos"]);        unset($stats["movies"]); @@ -127,6 +127,12 @@ class g2_import_task_Core {            $g2_root_id = g2(GalleryCoreApi::getDefaultAlbumId());            $tree = g2(GalleryCoreApi::fetchAlbumTree());            $task->set("queue", $queue = array($g2_root_id => $tree)); + +          // Update the root album to reflect the Gallery2 root album. +          $root_album = item::root(); +          g2_import::set_album_values( +            $root_album, g2(GalleryCoreApi::loadEntitiesById($g2_root_id))); +          $root_album->save();          }          $log_message = g2_import::import_album($queue);          if ($log_message) { diff --git a/modules/g2_import/module.info b/modules/g2_import/module.info index 977af251..30fb46d4 100644 --- a/modules/g2_import/module.info +++ b/modules/g2_import/module.info @@ -1,3 +1,7 @@  name = "Gallery2 Import"  description = "Import your Gallery 2 content into Gallery 3"  version = 2 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:g2_import" +discuss_url = "http://gallery.menalto.com/forum_module_g2_import" diff --git a/modules/g2_import/views/admin_g2_import.html.php b/modules/g2_import/views/admin_g2_import.html.php index cb13363a..9c4eb840 100644 --- a/modules/g2_import/views/admin_g2_import.html.php +++ b/modules/g2_import/views/admin_g2_import.html.php @@ -1,24 +1,64 @@  <?php defined("SYSPATH") or die("No direct script access.") ?> +<?= $theme->css("jquery.autocomplete.css") ?> +<?= $theme->script("jquery.autocomplete.js") ?> +<script type="text/javascript"> +$("document").ready(function() { +  $("form input[name=embed_path]").autocomplete( +    "<?= url::site("__ARGS__") ?>".replace("__ARGS__", "admin/g2_import/autocomplete"), +    { +      max: 256, +      loadingClass: "g-loading-small", +    }); +}); +</script> +  <div id="g-admin-g2-import" class="g-block">    <h1> <?= t("Gallery 2 import") ?> </h1>    <p>      <?= t("Import your Gallery 2 users, photos, movies, comments and tags into your new Gallery 3 installation.") ?>    </p> -  <div class="g-block-content"> -    <?= $form ?> -  </div> +  <script type="text/javascript"> +    $(document).ready(function() { +      $("#g-admin-g2-import-tabs").tabs() +      <? if (!isset($g2_version)): ?> +      .tabs("disable", 1) +      .tabs("disable", 2) +      <? elseif ($g3_resource_count > .9 * $g2_resource_count):  ?> +      .tabs("select", 2) +      <? else: ?> +      .tabs("select", 1) +      <? endif ?> +      ; -  <div class="g-block-content"> -    <? if (g2_import::is_initialized()): ?> -    <div id="g-admin-g2-import-details"> -      <h2> <?= t("Import") ?> </h2> -      <ul id="g-action-status" class="g-message-block"> -        <li class="g-success"> -          <?= t("Gallery version %version detected", array("version" => $version)) ?> +      // Show the tabs after the page has loaded to prevent Firefox from rendering the +      // unstyled page and then flashing. +      $("#g-admin-g2-import-tabs").show(); +    }); +  </script> +  <div id="g-admin-g2-import-tabs" class="g-block-content" style="display: none"> +    <ul> +      <li> +        <a href="#g-admin-g2-import-configure"><?= t("1. Configure Gallery2 path") ?></a> +      </li> +      <li> +        <a href="#g-admin-g2-import-import"><?= t("2. Import!") ?></a> +      </li> +      <li> +        <a href="#g-admin-g2-import-notes"><?= t("3. After your import") ?></a> +      </li> +    </ul> +    <div id="g-admin-g2-import-configure" class="g-block-content"> +      <?= $form ?> +    </div> +    <div id="g-admin-g2-import-import"> +      <? if (isset($g2_version)): ?> +      <ul> +        <li> +          <?= t("Gallery version %version detected", array("version" => $g2_version)) ?>          </li>          <? if ($g2_sizes["thumb"]["size"] && $thumb_size != $g2_sizes["thumb"]["size"]): ?> -        <li class="g-warning"> +        <li>            <?= t("Your most common thumbnail size in Gallery 2 is %g2_pixels pixels, but your Gallery 3 thumbnail size is set to %g3_pixels pixels. <a href=\"%url\">Using the same value</a> will speed up your import.",                  array("g2_pixels" => $g2_sizes["thumb"]["size"],                        "g3_pixels" => $thumb_size, @@ -27,73 +67,84 @@          <? endif ?>          <? if ($g2_sizes["resize"]["size"] && $resize_size != $g2_sizes["resize"]["size"]): ?> -        <li class="g-warning"> +        <li>            <?= t("Your most common intermediate size in Gallery 2 is %g2_pixels pixels, but your Gallery 3 intermediate size is set to %g3_pixels pixels. <a href=\"%url\">Using the same value</a> will speed up your import.", -              array("g2_pixels" => $g2_sizes["resize"]["size"], -                    "g3_pixels" => $resize_size, -                    "url" => html::mark_clean(url::site("admin/theme_options")))) ?> +                array("g2_pixels" => $g2_sizes["resize"]["size"], +                      "g3_pixels" => $resize_size, +                      "url" => html::mark_clean(url::site("admin/theme_options")))) ?>          </li>          <? endif ?> -        <li class="g-info"> -          <?= t("Your Gallery 2 has the following importable data in it:") ?> -          <p> -            <?= t2("1 user", "%count users", $g2_stats["users"]) ?>, -            <?= t2("1 group", "%count groups", $g2_stats["groups"]) ?>, -            <?= t2("1 album", "%count albums", $g2_stats["albums"]) ?>, -            <?= t2("1 photo", "%count photos", $g2_stats["photos"]) ?>, -            <?= t2("1 movie", "%count movies", $g2_stats["movies"]) ?>, -            <?= t2("1 comment", "%count comments", $g2_stats["comments"]) ?>, -            <?= t2("1 tagged photo/movie/album", -                "%count tagged photos/movies/albums", $g2_stats["tags"]) ?> -          </p> +        <li> +          <? +          $t = array(); +          $t[] = t2("1 user", "%count users", $g2_stats["users"]); +          $t[] = t2("1 group", "%count groups", $g2_stats["groups"]); +          $t[] = t2("1 album", "%count albums", $g2_stats["albums"]); +          $t[] = t2("1 photo", "%count photos/movies", $g2_stats["photos"] + $g2_stats["movies"]); +          $t[] = t2("1 comment", "%count comments", $g2_stats["comments"]); +          $t[] = t2("1 tagged photo/movie/album", "%count tagged photos/movies/albums", +                    $g2_stats["tags"]); +          ?> +          <?= t("Your Gallery 2 has the following importable data in it: %t0, %t1, %t2, %t3, %t4, %t5", +                array("t0" => $t[0], "t1" => $t[1], "t2" => $t[2], +                      "t3" => $t[3], "t4" => $t[4], "t5" => $t[5])) ?>          </li> -      </ul> +        <? if ($g3_resource_count): ?> +        <li> +          <? +          $t = array(); +          $t[] = t2("1 user", "%count users", $g3_stats["user"]); +          $t[] = t2("1 group", "%count groups", $g3_stats["group"]); +          $t[] = t2("1 album", "%count albums", $g3_stats["album"]); +          $t[] = t2("1 photo/movie", "%count photos/movies", $g3_stats["item"]); +          $t[] = t2("1 comment", "%count comments", $g3_stats["comment"]); +          $t[] = t2("1 tagged photo/movie/album", "%count tagged photos/movies/albums", $g3_stats["tag"]); +          ?> +          <?= t("It looks like you've imported the following Gallery 2 data already: %t0, %t1, %t2, %t3, %t4, %t5", +                array("t0" => $t[0], "t1" => $t[1], "t2" => $t[2], +                      "t3" => $t[3], "t4" => $t[4], "t5" => $t[5])) ?> +        </li> +        <? endif ?> +      </ul>        <p>          <a class="g-button g-dialog-link ui-state-default ui-corner-all"             href="<?= url::site("admin/maintenance/start/g2_import_task::import?csrf=$csrf") ?>">            <?= t("Begin import!") ?>          </a>        </p> +      <? endif ?>      </div> +    <div id="g-admin-g2-import-notes" class="g-text"> +      <ul> +        <li> +          <?= t("Gallery 3 does not support per-user / per-item permissions.  <b>Review permissions!</b>") ?> +        </li> +        <li> +          <?= t("The only supported file formats are JPG, PNG and GIF, FLV and MP4.  Other formats will be skipped.") ?> +        </li> +        <li> +          <p> +            <?= t("Redirecting Gallery 2 URLs once your migration is complete.  Put this block at the top of your gallery2/.htaccess file and all Gallery 2 urls will be redirected to Gallery 3") ?> +          </p> -    <div class="g-block-content"> -      <div id="g-admin-g2-import-notes"> -        <h2> <?= t("Notes") ?> </h2> -        <ul class="enumeration"> -          <li> -            <?= t("Gallery 3 does not support per-user / per-item permissions.  <b>Review permissions after your import is done.</b>") ?> -          </li> -          <li> -            <?= t("The only supported file formats are JPG, PNG and GIF, FLV and MP4.  Other formats will be skipped.") ?> -          </li> -          <li> -            <?= t("Deactivating the <b>notification</b>, <b>search</b> and <b>exif</b> modules during your import will make it go faster.") ?> -          </li> -          <li> -            <?= t("The eAccelerator and XCache PHP performance extensions are known to cause issues.  If you're using either of those and are having problems, please disable them while you do your import.  Add the following lines: <pre>%lines</pre> to gallery3/.htaccess and remove them when the import is done.", array("lines" => "\n\n  php_value eaccelerator.enable 0\n  php_value xcache.cacher off\n  php_value xcache.optimizer off\n\n")) ?> -          </li> -        </ul> -      </div> -    </div> - -    <div class="g-block-content"> -      <div> -        <h2> <?= t("Migrating from Gallery 2") ?> </h2> -        <p> -          <?= t("Once your migration is complete, put this block at the top of your gallery2/.htaccess file and all Gallery 2 urls will be redirected to Gallery 3") ?> -        </p> - -        <textarea rows="4" cols="60"><IfModule mod_rewrite.c> -  Options +FollowSymLinks -  RewriteEngine On -  RewriteBase <?= html::clean(g2_import::$g2_base_url) ?> +          <textarea id="g-g2-redirect-rules" rows="4" cols="60"><IfModule mod_rewrite.c> +      Options +FollowSymLinks +      RewriteEngine On +      RewriteBase <?= html::clean(g2_import::$g2_base_url) ?> -  RewriteRule ^(.*)$ <?= url::site("g2/map?path=\$1") ?>   [QSA,L,R=301] -</IfModule></textarea> -      </div> -      <? endif ?> +      RewriteRule ^(.*)$ <?= url::site("g2/map?path=\$1") ?>   [QSA,L,R=301] +    </IfModule></textarea> +          <script type="text/javascript"> +            $(document).ready(function() { +              $("#g-g2-redirect-rules").click(function(event) { +                this.select(); +              }); +            }); +          </script> +        </li> +      </ul>      </div>    </div>  </div> diff --git a/modules/gallery/config/locale.php b/modules/gallery/config/locale.php index 0509e45f..bce7fb49 100644 --- a/modules/gallery/config/locale.php +++ b/modules/gallery/config/locale.php @@ -29,13 +29,14 @@  $config['language'] = array('en_US', 'English_United States');  /** - * Locale timezone. Defaults to use the server timezone. + * Locale timezone.  Set in 'Advanced' settings, falling back to the server's zone.   * @see http://php.net/timezones   */ -$config['timezone'] = ini_get('date.timezone'); -if (empty($config['timezone'])) { -  // This is a required field.  Pick something as a default. -  $config['timezone'] = "America/Los_Angeles"; +if (file_exists(VARPATH . "database.php")) { +  $config['timezone'] = module::get_var("gallery", "timezone", date_default_timezone_get()); +} else { +  // Gallery3 is not installed yet -- don't make module::get_var() calls. +  $config['timezone'] = date_default_timezone_get();  }  // i18n settings diff --git a/modules/gallery/controllers/admin_modules.php b/modules/gallery/controllers/admin_modules.php index 787785ea..b712d14f 100644 --- a/modules/gallery/controllers/admin_modules.php +++ b/modules/gallery/controllers/admin_modules.php @@ -19,6 +19,9 @@   */  class Admin_Modules_Controller extends Admin_Controller {    public function index() { +    // If modules need upgrading, this will get recreated in module::available() +    site_status::clear("upgrade_now"); +      $view = new Admin_View("admin.html");      $view->page_title = t("Modules");      $view->content = new View("admin_modules.html"); @@ -103,9 +106,6 @@ class Admin_Modules_Controller extends Admin_Controller {      module::event("module_change", $changes); -    // If modules need upgrading, this will get recreated -    site_status::clear("upgrade_now"); -      // @todo this type of collation is questionable from an i18n perspective      if ($activated_names) {        message::success(t("Activated: %names", array("names" => join(", ", $activated_names)))); diff --git a/modules/gallery/controllers/admin_theme_options.php b/modules/gallery/controllers/admin_theme_options.php index 055e063c..d9323ea0 100644 --- a/modules/gallery/controllers/admin_theme_options.php +++ b/modules/gallery/controllers/admin_theme_options.php @@ -59,6 +59,7 @@ class Admin_Theme_Options_Controller extends Admin_Controller {        module::set_var("gallery", "footer_text", $form->edit_theme->footer_text->value);        module::set_var("gallery", "show_credits", $form->edit_theme->show_credits->value);        module::set_var("gallery", "favicon_url", $form->edit_theme->favicon_url->value); +      module::set_var("gallery", "apple_touch_icon_url", $form->edit_theme->apple_touch_icon_url->value);        module::event("theme_edit_form_completed", $form); @@ -77,8 +78,10 @@ class Admin_Theme_Options_Controller extends Admin_Controller {      $group = $form->group("edit_theme")->label(t("Theme layout"));      $group->input("page_size")->label(t("Items per page"))->id("g-page-size")        ->rules("required|valid_digit") +      ->callback(array($this, "_valididate_page_size"))        ->error_messages("required", t("You must enter a number"))        ->error_messages("valid_digit", t("You must enter a number")) +      ->error_messages("valid_min_value", t("The value must be greater than zero"))        ->value(module::get_var("gallery", "page_size"));      $group->input("thumb_size")->label(t("Thumbnail size (in pixels)"))->id("g-thumb-size")        ->rules("required|valid_digit") @@ -93,6 +96,9 @@ class Admin_Theme_Options_Controller extends Admin_Controller {      $group->input("favicon_url")->label(t("URL (or relative path) to your favicon.ico"))        ->id("g-favicon")        ->value(module::get_var("gallery", "favicon_url")); +    $group->input("apple_touch_icon_url")->label(t("URL (or relative path) to your Apple Touch icon")) +      ->id("g-apple-touch") +      ->value(module::get_var("gallery", "apple_touch_icon_url"));      $group->textarea("header_text")->label(t("Header text"))->id("g-header-text")        ->value(module::get_var("gallery", "header_text"));      $group->textarea("footer_text")->label(t("Footer text"))->id("g-footer-text") @@ -102,9 +108,15 @@ class Admin_Theme_Options_Controller extends Admin_Controller {      module::event("theme_edit_form", $form); -    $group = $form->group("buttons");      $group->submit("")->value(t("Save"));      return $form;    } + +  function _valididate_page_size($input) { +    if ($input->value < 1) { +      $input->add_error("valid_min_value", true); +    } + +  }  } diff --git a/modules/gallery/controllers/quick.php b/modules/gallery/controllers/quick.php index da4768fd..b6576ec0 100644 --- a/modules/gallery/controllers/quick.php +++ b/modules/gallery/controllers/quick.php @@ -36,8 +36,8 @@ class Quick_Controller extends Controller {      }      if ($degrees) { -      $tmpfile = tempnam(TMPPATH, "rotate") . "." . -        pathinfo($item->file_path(), PATHINFO_EXTENSION); +      $tmpfile = system::temp_filename("rotate", +        pathinfo($item->file_path(), PATHINFO_EXTENSION));        gallery_graphics::rotate($item->file_path(), $tmpfile, array("degrees" => $degrees), $item);        $item->set_data_file($tmpfile);        $item->save(); diff --git a/modules/gallery/css/gallery.css b/modules/gallery/css/gallery.css index 275a3d7d..ecf89565 100644 --- a/modules/gallery/css/gallery.css +++ b/modules/gallery/css/gallery.css @@ -29,12 +29,12 @@  #g-add-photos-canvas object,  #g-add-photos-button { -  left: 137px; -  margin: .5em  0; +  left: 90px; +  margin: .5em 0;    padding: .4em 1em;    position: absolute;    top: 0; -  width: 175px; +  width: 300px;  }  #g-add-photos-canvas object { diff --git a/modules/gallery/helpers/MY_num.php b/modules/gallery/helpers/MY_num.php index 9787044c..842a2ee3 100644 --- a/modules/gallery/helpers/MY_num.php +++ b/modules/gallery/helpers/MY_num.php @@ -37,4 +37,18 @@ class num extends num_Core {      return $val;    } + +  /** +   * Convert a size value as accepted by PHP's shorthand to bytes. +   * ref: http://us2.php.net/manual/en/function.ini-get.php +   * ref: http://us2.php.net/manual/en/faq.using.php#faq.using.shorthandbytes +   */ +  static function convert_to_human_readable($num) { +    foreach (array("G" => 1e9, "M" => 1e6, "K" => 1e3) as $k => $v) { +      if ($num > $v) { +        $num = round($num / $v) . $k; +      } +    } +    return $num; +  }  } diff --git a/modules/gallery/helpers/gallery_block.php b/modules/gallery/helpers/gallery_block.php index 0ba7c936..49d16246 100644 --- a/modules/gallery/helpers/gallery_block.php +++ b/modules/gallery/helpers/gallery_block.php @@ -82,9 +82,13 @@ class gallery_block_Core {        break;      case "block_adder": -      $block->css_id = "g-block-adder"; -      $block->title = t("Dashboard content"); -      $block->content = gallery_block::get_add_block_form(); +      if ($form = gallery_block::get_add_block_form()) { +        $block->css_id = "g-block-adder"; +        $block->title = t("Dashboard content"); +        $block->content = $form; +      } else { +        $block = ""; +      }        break;      case "language": @@ -118,11 +122,22 @@ class gallery_block_Core {    }    static function get_add_block_form() { +    $available_blocks = block_manager::get_available_admin_blocks(); + +    $active = array(); +    foreach (array_merge(block_manager::get_active("dashboard_sidebar"), +                         block_manager::get_active("dashboard_center")) as $b) { +      unset($available_blocks[implode(":", $b)]); +    } + +    if (!$available_blocks) { +      return; +    } +      $form = new Forge("admin/dashboard/add_block", "", "post",                        array("id" => "g-add-dashboard-block-form"));      $group = $form->group("add_block")->label(t("Add Block")); -    $group->dropdown("id")->label(t("Available Blocks")) -      ->options(block_manager::get_available_admin_blocks()); +    $group->dropdown("id")->label(t("Available blocks"))->options($available_blocks);      $group->submit("center")->value(t("Add to center"));      $group->submit("sidebar")->value(t("Add to sidebar"));      return $form; diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php index 01c59eaa..7a9af402 100644 --- a/modules/gallery/helpers/gallery_installer.php +++ b/modules/gallery/helpers/gallery_installer.php @@ -304,14 +304,16 @@ class gallery_installer {      module::set_var("gallery", "maintenance_mode", 0);      module::set_var("gallery", "visible_title_length", 15);      module::set_var("gallery", "favicon_url", "lib/images/favicon.ico"); +    module::set_var("gallery", "apple_touch_icon_url", "lib/images/apple-touch-icon.png");      module::set_var("gallery", "email_from", "");      module::set_var("gallery", "email_reply_to", "");      module::set_var("gallery", "email_line_length", 70);      module::set_var("gallery", "email_header_separator", serialize("\n"));      module::set_var("gallery", "show_user_profiles_to", "registered_users");      module::set_var("gallery", "extra_binary_paths", "/usr/local/bin:/opt/local/bin:/opt/bin"); +    module::set_var("gallery", "timezone", null); -    module::set_version("gallery", 46); +    module::set_version("gallery", 49);    }    static function upgrade($version) { @@ -677,6 +679,19 @@ class gallery_installer {        module::set_var("gallery", "upgrade_checker_auto_enabled", true);        module::set_version("gallery", $version = 46);      } + +    if ($version == 46) { +      module::set_var("gallery", "apple_touch_icon_url", "lib/images/apple-touch-icon.png"); +      module::set_version("gallery", $version = 47); +    } + +    if ($version == 47 || $version == 48) { +      // Add configuration variable to set timezone.  Defaults to the currently +      // used timezone (from PHP configuration).  Note that in v48 we werew +      // setting this value incorrectly, so we're going to stomp this value for v49. +      module::set_var("gallery", "timezone", null); +      module::set_version("gallery", $version = 49); +    }    }    static function uninstall() { diff --git a/modules/gallery/helpers/gallery_theme.php b/modules/gallery/helpers/gallery_theme.php index c4a82390..e07839d9 100644 --- a/modules/gallery/helpers/gallery_theme.php +++ b/modules/gallery/helpers/gallery_theme.php @@ -64,7 +64,7 @@ class gallery_theme_Core {      if ($session->get("l10n_mode", false)) {        $buf .= $theme->css("l10n_client.css");        $buf .= $theme->script("jquery.cookie.js"); -      $buf .=$theme->script("l10n_client.js"); +      $buf .= $theme->script("l10n_client.js");      }      return $buf;    } diff --git a/modules/gallery/helpers/graphics.php b/modules/gallery/helpers/graphics.php index 04501132..acb11bfb 100644 --- a/modules/gallery/helpers/graphics.php +++ b/modules/gallery/helpers/graphics.php @@ -316,10 +316,10 @@ class graphics_Core {        // ImageMagick & GraphicsMagick        $magick_kits = array(            "imagemagick" => array( -            "name" => "ImageMagick", "binary" => "convert", "version" => "convert -v", +            "name" => "ImageMagick", "binary" => "convert", "version_arg" => "-v",              "version_regex" => "/Version: \S+ (\S+)/"),            "graphicsmagick" => array( -            "name" => "GraphicsMagick", "binary" => "gm", "version" => "gm version", +            "name" => "GraphicsMagick", "binary" => "gm", "version_arg" => "version",              "version_regex" => "/\S+ (\S+)/"));        // Loop through the kits        foreach ($magick_kits as $index => $settings) { @@ -328,7 +328,8 @@ class graphics_Core {          $toolkits->$index->name = $settings["name"];          if ($path) {            if (@is_file($path) && -              preg_match($settings["version_regex"], shell_exec($settings["version"]), $matches)) { +              preg_match( +                $settings["version_regex"], shell_exec($path . " " . $settings["version_arg"]), $matches)) {              $version = $matches[1];              $toolkits->$index->installed = true; @@ -423,4 +424,23 @@ class graphics_Core {      return true;    } + +  /** +   * Return the max file size that this graphics toolkit can handle. +   */ +  static function max_filesize() { +    if (module::get_var("gallery", "graphics_toolkit") == "gd") { +      $memory_limit = trim(ini_get("memory_limit")); +      $memory_limit_bytes = num::convert_to_bytes($memory_limit); + +      // GD expands images in memory and uses 4 bytes of RAM for every byte +      // in the file. +      $max_filesize = $memory_limit_bytes / 4; +      $max_filesize_human_readable = num::convert_to_human_readable($max_filesize); +      return array($max_filesize, $max_filesize_human_readable); +    } + +    // Some arbitrarily large size +    return array(1000000000, "1G"); +  }  } diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php index 1a5c631e..7e779544 100644 --- a/modules/gallery/helpers/item.php +++ b/modules/gallery/helpers/item.php @@ -152,8 +152,18 @@ class item_Core {     * @param string $filename     */    static function convert_filename_to_slug($filename) { -    $result = pathinfo($filename, PATHINFO_FILENAME); +    $result = str_replace("&", "-and-", $filename); +    $result = str_replace(" ", "-", $result); + +    // It's not easy to extend the text helper since it's called by the Input class which is +    // referenced in hooks/init_gallery, so it's +    if (class_exists("transliterate")) { +      $result = transliterate::utf8_to_ascii($result); +    } else { +      $result = text::transliterate_to_ascii($result); +    }      $result = preg_replace("/[^A-Za-z0-9-_]+/", "-", $result); +    $result = preg_replace("/-+/", "-", $result);      return trim($result, "-");    } diff --git a/modules/gallery/helpers/module.php b/modules/gallery/helpers/module.php index 37f7f68a..4b7d4a5f 100644 --- a/modules/gallery/helpers/module.php +++ b/modules/gallery/helpers/module.php @@ -101,7 +101,7 @@ class module_Core {          $m->locked = false;          if ($m->active && $m->version != $m->code_version) { -          site_status::warning(t("Some of your modules are out of date.  <a href=\"%upgrader_url\">Upgrade now!</a>", array("upgrader_url" => url::site("upgrader"))), "upgrade_now"); +          site_status::warning(t("Some of your modules are out of date.  <a href=\"%upgrader_url\">Upgrade now!</a>", array("upgrader_url" => url::abs_site("upgrader"))), "upgrade_now");          }        } diff --git a/modules/gallery/helpers/random.php b/modules/gallery/helpers/random.php index 6016df7b..06542e8c 100644 --- a/modules/gallery/helpers/random.php +++ b/modules/gallery/helpers/random.php @@ -19,7 +19,7 @@   */  class random_Core {    /** -   * Return a random 32 bit hash value. +   * Return a random 32 byte hash value.     * @param string extra entropy data     */    static function hash($entropy="") { @@ -27,14 +27,6 @@ class random_Core {    }    /** -   * Return a random hexadecimal string of the given length. -   * @param int the desired length of the string -   */ -  static function string($length) { -    return substr(random::hash(), 0, $length); -  } - -  /**     * Return a random floating point number between 0 and 1     */    static function percent() { diff --git a/modules/gallery/helpers/system.php b/modules/gallery/helpers/system.php index c39c7227..4110b4ed 100644 --- a/modules/gallery/helpers/system.php +++ b/modules/gallery/helpers/system.php @@ -40,4 +40,25 @@ class system_Core {      }      return null;    } + +  /** +   * Create a file with a unique file name. +   * This helper is similar to the built-in tempnam. +   * It allows the caller to specify a prefix and an extension. +   * It always places the file in TMPPATH. +   */ +  static function temp_filename($prefix="", $extension="") { +    do { +      $basename = tempnam(TMPPATH, $prefix); +      if (!$basename) { +        return false; +      } +      $filename = "$basename.$extension"; +      $success = !file_exists($filename) && @rename($basename, $filename); +      if (!$success) { +        @unlink($basename); +      } +    } while (!$success); +    return $filename; +  }  }
\ No newline at end of file diff --git a/modules/gallery/libraries/Form_Uploadify.php b/modules/gallery/libraries/Form_Uploadify.php index 27ab9684..3e35e380 100644 --- a/modules/gallery/libraries/Form_Uploadify.php +++ b/modules/gallery/libraries/Form_Uploadify.php @@ -48,6 +48,20 @@ class Form_Uploadify_Core extends Form_Input {      $v->simultaneous_upload_limit = module::get_var("gallery", "simultaneous_upload_limit");      $v->movies_allowed = (bool) movie::find_ffmpeg();      $v->suhosin_session_encrypt = (bool) ini_get("suhosin.session.encrypt"); + +    list ($toolkit_max_filesize_bytes, $toolkit_max_filesize) = graphics::max_filesize(); + +    $upload_max_filesize = trim(ini_get("upload_max_filesize")); +    $upload_max_filesize_bytes = num::convert_to_bytes($upload_max_filesize); + +    if ($upload_max_filesize_bytes < $toolkit_max_filesize_bytes) { +      $v->size_limit_bytes = $upload_max_filesize_bytes; +      $v->size_limit = $upload_max_filesize; +    } else { +      $v->size_limit_bytes = $toolkit_max_filesize_bytes; +      $v->size_limit = $toolkit_max_filesize; +    } +      return $v;    } diff --git a/modules/gallery/libraries/Gallery_View.php b/modules/gallery/libraries/Gallery_View.php index 77e3d204..e04b9169 100644 --- a/modules/gallery/libraries/Gallery_View.php +++ b/modules/gallery/libraries/Gallery_View.php @@ -31,6 +31,52 @@ class Gallery_View_Core extends View {    }    /** +   * Set up the data and render a pager. +   * +   * See themes/wind/views/pager.html for documentation on the variables generated here. +   */ +  public function paginator() { +    $v = new View("paginator.html"); +    $v->page_type = $this->page_type; +    $v->page_subtype = $this->page_subtype; +    $v->first_page_url = null; +    $v->previous_page_url = null; +    $v->next_page_url = null; +    $v->last_page_url = null; + +    if ($this->page_type == "collection") { +      $v->page = $this->page; +      $v->max_pages = $this->max_pages; +      $v->total = $this->children_count; + +      if ($this->page != 1) { +        $v->first_page_url = url::site(url::merge(array("page" => 1))); +        $v->previous_page_url = url::site(url::merge(array("page" => $this->page - 1))); +      } + +      if ($this->page != $this->max_pages) { +        $v->next_page_url = url::site(url::merge(array("page" => $this->page + 1))); +        $v->last_page_url = url::site(url::merge(array("page" => $this->max_pages))); +      } + +      $v->first_visible_position = ($this->page - 1) * $this->page_size + 1; +      $v->last_visible_position = min($this->page * $this->page_size, $v->total); +    } else if ($this->page_type == "item") { +      $v->position = $this->position; +      $v->total = $this->sibling_count; +      if ($this->previous_item) { +        $v->previous_page_url = $this->previous_item->url(); +      } + +      if ($this->next_item) { +        $v->next_page_url = $this->next_item->url(); +      } +    } + +    return $v; +  } + +  /**     * Begin gather up scripts or css files so that they can be combined into a single request.     *     * @param $types  a comma separated list of types to combine, eg "script,css" @@ -136,6 +182,9 @@ class Gallery_View_Core extends View {      }      unset($this->combine_queue[$type][$group]); +    if (empty($this->combine_queue[$type])) { +      unset($this->combine_queue[$type]); +    }      if ($type == "css") {        return html::stylesheet("combined/css/$key", "screen,print,projection", true); diff --git a/modules/gallery/libraries/InPlaceEdit.php b/modules/gallery/libraries/InPlaceEdit.php index 88c30494..739cbb61 100644 --- a/modules/gallery/libraries/InPlaceEdit.php +++ b/modules/gallery/libraries/InPlaceEdit.php @@ -56,8 +56,12 @@ class InPlaceEdit_Core {    }    public function validate() { -    $post = Validation::factory($_POST) -      ->add_callbacks("input", $this->callback); +    $post = Validation::factory($_POST); + +    if (!empty($this->callback)) { +      $post->add_callbacks("input", $this->callback); +    } +      foreach ($this->rules as $rule) {        $post->add_rules("input", $rule);      } diff --git a/modules/gallery/libraries/Theme_View.php b/modules/gallery/libraries/Theme_View.php index a507e9c8..d6834464 100644 --- a/modules/gallery/libraries/Theme_View.php +++ b/modules/gallery/libraries/Theme_View.php @@ -38,6 +38,7 @@ class Theme_View_Core extends Gallery_View {      $this->item = null;      $this->tag = null;      $this->set_global(array("theme" => $this, +                            "theme_info" => theme::get_info($this->theme_name),                              "user" => identity::active_user(),                              "page_type" => $page_type,                              "page_subtype" => $page_subtype, @@ -138,52 +139,6 @@ class Theme_View_Core extends Gallery_View {    }    /** -   * Set up the data and render a pager. -   * -   * See themes/wind/views/pager.html for documentation on the variables generated here. -   */ -  public function paginator() { -    $v = new View("paginator.html"); -    $v->page_type = $this->page_type; -    $v->page_subtype = $this->page_subtype; -    $v->first_page_url = null; -    $v->previous_page_url = null; -    $v->next_page_url = null; -    $v->last_page_url = null; - -    if ($this->page_type == "collection") { -      $v->page = $this->page; -      $v->max_pages = $this->max_pages; -      $v->total = $this->children_count; - -      if ($this->page != 1) { -        $v->first_page_url = url::site(url::merge(array("page" => 1))); -        $v->previous_page_url = url::site(url::merge(array("page" => $this->page - 1))); -      } - -      if ($this->page != $this->max_pages) { -        $v->next_page_url = url::site(url::merge(array("page" => $this->page + 1))); -        $v->last_page_url = url::site(url::merge(array("page" => $this->max_pages))); -      } - -      $v->first_visible_position = ($this->page - 1) * $this->page_size + 1; -      $v->last_visible_position = min($this->page * $this->page_size, $v->total); -    } else if ($this->page_type == "item") { -      $v->position = $this->position; -      $v->total = $this->sibling_count; -      if ($this->previous_item) { -        $v->previous_page_url = $this->previous_item->url(); -      } - -      if ($this->next_item) { -        $v->next_page_url = $this->next_item->url(); -      } -    } - -    return $v; -  } - -  /**     * Print out any site wide status information.     */    public function site_status() { diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php index 8f4bc5e4..2a5e6894 100644 --- a/modules/gallery/models/item.php +++ b/modules/gallery/models/item.php @@ -336,9 +336,7 @@ class Item_Model_Core extends ORM_MPTT {          // 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, "-"); +          $this->slug = item::convert_filename_to_slug(pathinfo($this->name, PATHINFO_FILENAME));            // If the filename is all invalid characters, then the slug may be empty here.  Pick a            // random value. diff --git a/modules/gallery/module.info b/modules/gallery/module.info index 4c0c8866..42345531 100644 --- a/modules/gallery/module.info +++ b/modules/gallery/module.info @@ -1,3 +1,7 @@  name = "Gallery 3"  description = "Gallery core application" -version = 46 +version = 49 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:gallery" +discuss_url = "http://gallery.menalto.com/forum_module_gallery" diff --git a/modules/gallery/tests/Albums_Controller_Test.php b/modules/gallery/tests/Albums_Controller_Test.php index d9983cc2..2ff017d7 100644 --- a/modules/gallery/tests/Albums_Controller_Test.php +++ b/modules/gallery/tests/Albums_Controller_Test.php @@ -31,7 +31,7 @@ class Albums_Controller_Test extends Gallery_Unit_Test_Case {      $album = test::random_album();      // Randomize to avoid conflicts. -    $new_name = "new_name_" . random::string(6); +    $new_name = "new_name_" . test::random_string(6);      $_POST["name"] = $new_name;      $_POST["title"] = "new title"; diff --git a/modules/gallery/tests/File_Structure_Test.php b/modules/gallery/tests/File_Structure_Test.php index 69c4bbf9..1d1ff5ce 100644 --- a/modules/gallery/tests/File_Structure_Test.php +++ b/modules/gallery/tests/File_Structure_Test.php @@ -101,6 +101,7 @@ class File_Structure_Test extends Gallery_Unit_Test_Case {        $expected_4 = array("<?php defined('SYSPATH') or die('No direct script access.');\n");      } else if (strpos($path, MODPATH . "forge") === 0 ||                 strpos($path, MODPATH . "exif/lib") === 0 || +               strpos($path, MODPATH . "gallery_unit_test/vendor") === 0 ||                 strpos($path, MODPATH . "gallery/lib/HTMLPurifier") === 0 ||                 $path == MODPATH . "user/lib/PasswordHash.php" ||                 $path == DOCROOT . "var/database.php") { diff --git a/modules/gallery/tests/Gallery_Filters.php b/modules/gallery/tests/Gallery_Filters.php index e0208ed3..b008b593 100644 --- a/modules/gallery/tests/Gallery_Filters.php +++ b/modules/gallery/tests/Gallery_Filters.php @@ -38,6 +38,7 @@ class GalleryCodeFilterIterator extends FilterIterator {        strpos($path_name, MODPATH . "forge") !== false ||        strpos($path_name, MODPATH . "gallery/views/kohana_error_page.php") !== false ||        strpos($path_name, MODPATH . "gallery/views/kohana_profiler.php") !== false || +      strpos($path_name, MODPATH . "gallery_unit_test/vendor") !== false ||        strpos($path_name, MODPATH . "gallery_unit_test/views/kohana_error_page.php") !== false ||        strpos($path_name, MODPATH . "gallery_unit_test/views/kohana_unit_test_cli.php") !== false ||        strpos($path_name, MODPATH . "unit_test") !== false || diff --git a/modules/gallery/tests/Item_Helper_Test.php b/modules/gallery/tests/Item_Helper_Test.php index 4d5aed41..2fde7cc0 100644 --- a/modules/gallery/tests/Item_Helper_Test.php +++ b/modules/gallery/tests/Item_Helper_Test.php @@ -49,6 +49,10 @@ class Item_Helper_Test extends Gallery_Unit_Test_Case {    public function convert_filename_to_slug_test() {      $this->assert_equal("foo", item::convert_filename_to_slug("{[foo]}"));      $this->assert_equal("foo-bar", item::convert_filename_to_slug("{[foo!@#!$@#^$@($!(@bar]}")); +    $this->assert_equal("english-text", item::convert_filename_to_slug("english text")); +    $this->assert_equal("new-line", item::convert_filename_to_slug("new \n line")); +    $this->assert_equal("foo-and-bar", item::convert_filename_to_slug("foo&bar")); +    $this->assert_equal("special", item::convert_filename_to_slug("šṗëçîąļ"));    }    public function move_test() { diff --git a/modules/gallery/tests/Num_Helper_Test.php b/modules/gallery/tests/Num_Helper_Test.php new file mode 100644 index 00000000..a22f9359 --- /dev/null +++ b/modules/gallery/tests/Num_Helper_Test.php @@ -0,0 +1,32 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2011 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 Num_Helper_Test extends Gallery_Unit_Test_Case { +  public function convert_to_bytes_test() { +    $this->assert_equal(5 * 1024, num::convert_to_bytes("5K")); +    $this->assert_equal(3 * 1024*1024, num::convert_to_bytes("3M")); +    $this->assert_equal(4 * 1024*1024*1024, num::convert_to_bytes("4G")); +  } + +  public function convert_to_human_readable_test() { +    $this->assert_equal("6K", num::convert_to_human_readable(5615)); +    $this->assert_equal("1M", num::convert_to_human_readable(1205615)); +    $this->assert_equal("3G", num::convert_to_human_readable(3091205615)); +  } +}
\ No newline at end of file diff --git a/modules/gallery/libraries/MY_Pagination.php b/modules/gallery/tests/System_Helper_Test.php index e697c0bd..3d56c516 100644 --- a/modules/gallery/libraries/MY_Pagination.php +++ b/modules/gallery/tests/System_Helper_Test.php @@ -1,7 +1,7 @@  <?php defined("SYSPATH") or die("No direct script access.");  /**   * Gallery - a web based photo album viewer and editor - * Copyright (C) 2000-2011 Bharat Mediratta + * Copyright (C) 2011 Chad Parry   *   * 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 @@ -17,19 +17,11 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.   */ -class Pagination extends Pagination_Core { -  public function render($style=NULL) { -    // Hide single page pagination -    if ($this->auto_hide === TRUE AND $this->total_pages <= 1) { -      return ""; -    } - -    if ($style === NULL) { -      // Use default style -      $style = $this->style; -    } - -    // Return rendered pagination view -    return View::factory("pager.html", get_object_vars($this))->render(); +class System_Helper_Test extends Gallery_Unit_Test_Case { +  public function temp_filename_test() { +    $filename = system::temp_filename("file", "ext"); +    $this->assert_true(file_exists($filename), "File not created"); +    unlink($filename); +    $this->assert_pattern($filename, "|/file.*\\.ext$|");    }  } diff --git a/modules/gallery/tests/controller_auth_data.txt b/modules/gallery/tests/controller_auth_data.txt index f1192071..e35708c0 100644 --- a/modules/gallery/tests/controller_auth_data.txt +++ b/modules/gallery/tests/controller_auth_data.txt @@ -1,6 +1,7 @@  modules/comment/controllers/admin_manage_comments.php        queue                DIRTY_CSRF  modules/comment/helpers/comment_rss.php                      feed                 DIRTY_AUTH  modules/digibug/controllers/digibug.php                      print_proxy          DIRTY_CSRF|DIRTY_AUTH +modules/g2_import/controllers/admin_g2_import.php            autocomplete         DIRTY_CSRF  modules/g2_import/controllers/g2.php                         map                  DIRTY_CSRF  modules/gallery/controllers/admin.php                        __call               DIRTY_AUTH  modules/gallery/controllers/albums.php                       index                DIRTY_AUTH diff --git a/modules/gallery/tests/xss_data.txt b/modules/gallery/tests/xss_data.txt index 0c812fb4..7da79b23 100644 --- a/modules/gallery/tests/xss_data.txt +++ b/modules/gallery/tests/xss_data.txt @@ -42,7 +42,8 @@ modules/digibug/views/digibug_form.html.php                  4   DIRTY    form::  modules/digibug/views/digibug_form.html.php                  6   DIRTY    form::hidden($key,$value)  modules/exif/views/exif_dialog.html.php                      14  DIRTY    $details[$i]["caption"]  modules/exif/views/exif_dialog.html.php                      21  DIRTY    $details[$i]["caption"] -modules/g2_import/views/admin_g2_import.html.php             9   DIRTY    $form +modules/g2_import/views/admin_g2_import.html.php             7   DIRTY_JS url::site("__ARGS__") +modules/g2_import/views/admin_g2_import.html.php             52  DIRTY    $form  modules/gallery/views/admin_advanced_settings.html.php       21  DIRTY_ATTR text::alternate("g-odd","g-even")  modules/gallery/views/admin_advanced_settings.html.php       22  DIRTY    $var->module_name  modules/gallery/views/admin_block_log_entries.html.php       4   DIRTY_ATTR log::severity_class($entry->severity) @@ -77,30 +78,35 @@ modules/gallery/views/admin_languages.html.php               62  DIRTY    form::  modules/gallery/views/admin_languages.html.php               63  DIRTY    $display_name  modules/gallery/views/admin_languages.html.php               65  DIRTY    form::radio("default_locale",$code,($default_locale==$code),((isset($installed_locales[$code]))?'':'disabled="disabled"'))  modules/gallery/views/admin_languages.html.php               113 DIRTY    $share_translations_form -modules/gallery/views/admin_maintenance.html.php             40  DIRTY_ATTR text::alternate("g-odd","g-even") -modules/gallery/views/admin_maintenance.html.php             40  DIRTY_ATTR log::severity_class($task->severity) -modules/gallery/views/admin_maintenance.html.php             41  DIRTY_ATTR log::severity_class($task->severity) -modules/gallery/views/admin_maintenance.html.php             42  DIRTY    $task->name -modules/gallery/views/admin_maintenance.html.php             45  DIRTY    $task->description -modules/gallery/views/admin_maintenance.html.php             86  DIRTY_ATTR text::alternate("g-odd","g-even") -modules/gallery/views/admin_maintenance.html.php             86  DIRTY_ATTR $task->state=="stalled"?"g-warning":"" -modules/gallery/views/admin_maintenance.html.php             87  DIRTY_ATTR $task->state=="stalled"?"g-warning":"" -modules/gallery/views/admin_maintenance.html.php             88  DIRTY    gallery::date_time($task->updated) -modules/gallery/views/admin_maintenance.html.php             91  DIRTY    $task->name -modules/gallery/views/admin_maintenance.html.php             106 DIRTY    $task->status -modules/gallery/views/admin_maintenance.html.php             162 DIRTY_ATTR text::alternate("g-odd","g-even") -modules/gallery/views/admin_maintenance.html.php             162 DIRTY_ATTR $task->state=="success"?"g-success":"g-error" -modules/gallery/views/admin_maintenance.html.php             163 DIRTY_ATTR $task->state=="success"?"g-success":"g-error" -modules/gallery/views/admin_maintenance.html.php             164 DIRTY    gallery::date_time($task->updated) -modules/gallery/views/admin_maintenance.html.php             167 DIRTY    $task->name -modules/gallery/views/admin_maintenance.html.php             179 DIRTY    $task->status +modules/gallery/views/admin_maintenance.html.php             42  DIRTY_ATTR text::alternate("g-odd","g-even") +modules/gallery/views/admin_maintenance.html.php             42  DIRTY_ATTR log::severity_class($task->severity) +modules/gallery/views/admin_maintenance.html.php             43  DIRTY_ATTR log::severity_class($task->severity) +modules/gallery/views/admin_maintenance.html.php             44  DIRTY    $task->name +modules/gallery/views/admin_maintenance.html.php             47  DIRTY    $task->description +modules/gallery/views/admin_maintenance.html.php             88  DIRTY_ATTR text::alternate("g-odd","g-even") +modules/gallery/views/admin_maintenance.html.php             88  DIRTY_ATTR $task->state=="stalled"?"g-warning":"" +modules/gallery/views/admin_maintenance.html.php             89  DIRTY_ATTR $task->state=="stalled"?"g-warning":"" +modules/gallery/views/admin_maintenance.html.php             90  DIRTY    gallery::date_time($task->updated) +modules/gallery/views/admin_maintenance.html.php             93  DIRTY    $task->name +modules/gallery/views/admin_maintenance.html.php             108 DIRTY    $task->status +modules/gallery/views/admin_maintenance.html.php             164 DIRTY_ATTR text::alternate("g-odd","g-even") +modules/gallery/views/admin_maintenance.html.php             164 DIRTY_ATTR $task->state=="success"?"g-success":"g-error" +modules/gallery/views/admin_maintenance.html.php             165 DIRTY_ATTR $task->state=="success"?"g-success":"g-error" +modules/gallery/views/admin_maintenance.html.php             166 DIRTY    gallery::date_time($task->updated) +modules/gallery/views/admin_maintenance.html.php             169 DIRTY    $task->name +modules/gallery/views/admin_maintenance.html.php             181 DIRTY    $task->status  modules/gallery/views/admin_maintenance_show_log.html.php    8   DIRTY_JS url::site("admin/maintenance/save_log/$task->id?csrf=$csrf")  modules/gallery/views/admin_maintenance_show_log.html.php    13  DIRTY    $task->name  modules/gallery/views/admin_maintenance_task.html.php        75  DIRTY    $task->name  modules/gallery/views/admin_modules.html.php                 51  DIRTY    access::csrf_form_field() -modules/gallery/views/admin_modules.html.php                 60  DIRTY_ATTR text::alternate("g-odd","g-even") -modules/gallery/views/admin_modules.html.php                 63  DIRTY    form::checkbox($data,'1',module::is_active($module_name)) -modules/gallery/views/admin_modules.html.php                 65  DIRTY    $module_info->version +modules/gallery/views/admin_modules.html.php                 61  DIRTY_ATTR text::alternate("g-odd","g-even") +modules/gallery/views/admin_modules.html.php                 64  DIRTY    form::checkbox($data,'1',module::is_active($module_name)) +modules/gallery/views/admin_modules.html.php                 66  DIRTY    $module_info->version +modules/gallery/views/admin_modules.html.php                 74  DIRTY_JS $module_info->author_url +modules/gallery/views/admin_modules.html.php                 81  DIRTY_ATTR $module_info->author_name +modules/gallery/views/admin_modules.html.php                 85  DIRTY    $module_info->author_name +modules/gallery/views/admin_modules.html.php                 93  DIRTY_JS $module_info->info_url +modules/gallery/views/admin_modules.html.php                 106 DIRTY_JS $module_info->discuss_url  modules/gallery/views/admin_modules_confirm.html.php         11  DIRTY_ATTR $css_class  modules/gallery/views/admin_modules_confirm.html.php         11  DIRTY    $message  modules/gallery/views/admin_modules_confirm.html.php         16  DIRTY    access::csrf_form_field() @@ -114,12 +120,17 @@ modules/gallery/views/admin_themes.html.php                  3   DIRTY_JS url::s  modules/gallery/views/admin_themes.html.php                  5   DIRTY_JS $csrf  modules/gallery/views/admin_themes.html.php                  22  DIRTY    $themes[$site]->name  modules/gallery/views/admin_themes.html.php                  24  DIRTY    $themes[$site]->description -modules/gallery/views/admin_themes.html.php                  38  DIRTY    $info->name -modules/gallery/views/admin_themes.html.php                  40  DIRTY    $info->description -modules/gallery/views/admin_themes.html.php                  60  DIRTY    $themes[$admin]->name -modules/gallery/views/admin_themes.html.php                  62  DIRTY    $themes[$admin]->description -modules/gallery/views/admin_themes.html.php                  76  DIRTY    $info->name -modules/gallery/views/admin_themes.html.php                  78  DIRTY    $info->description +modules/gallery/views/admin_themes.html.php                  39  DIRTY    $info->name +modules/gallery/views/admin_themes.html.php                  41  DIRTY    $info->description +modules/gallery/views/admin_themes.html.php                  62  DIRTY    $themes[$admin]->name +modules/gallery/views/admin_themes.html.php                  64  DIRTY    $themes[$admin]->description +modules/gallery/views/admin_themes.html.php                  79  DIRTY    $info->name +modules/gallery/views/admin_themes.html.php                  81  DIRTY    $info->description +modules/gallery/views/admin_themes_buttonset.html.php        7   DIRTY_JS $info['author_url'] +modules/gallery/views/admin_themes_buttonset.html.php        14  DIRTY_ATTR $info['author_name'] +modules/gallery/views/admin_themes_buttonset.html.php        18  DIRTY    $info['author_name'] +modules/gallery/views/admin_themes_buttonset.html.php        26  DIRTY_JS $info['info_url'] +modules/gallery/views/admin_themes_buttonset.html.php        39  DIRTY_JS $info['discuss_url']  modules/gallery/views/admin_themes_preview.html.php          8   DIRTY_ATTR $url  modules/gallery/views/error_404.html.php                     14  DIRTY    $login_form  modules/gallery/views/error_admin.html.php                   178 DIRTY    @gallery_block::get("platform_info") @@ -174,7 +185,8 @@ modules/gallery/views/form_uploadify.html.php                28  DIRTY_JS url::f  modules/gallery/views/form_uploadify.html.php                29  DIRTY_JS url::site("uploader/add_photo/{$album->id}")  modules/gallery/views/form_uploadify.html.php                33  DIRTY_JS url::file("lib/uploadify/cancel.png")  modules/gallery/views/form_uploadify.html.php                34  DIRTY_JS $simultaneous_upload_limit -modules/gallery/views/form_uploadify.html.php                160 DIRTY_ATTR request::protocol() +modules/gallery/views/form_uploadify.html.php                35  DIRTY_JS $size_limit_bytes +modules/gallery/views/form_uploadify.html.php                162 DIRTY_ATTR request::protocol()  modules/gallery/views/in_place_edit.html.php                 2   DIRTY    form::open($action,array("method"=>"post","id"=>"g-in-place-edit-form","class"=>"g-short-form"))  modules/gallery/views/in_place_edit.html.php                 3   DIRTY    access::csrf_form_field()  modules/gallery/views/in_place_edit.html.php                 6   DIRTY    form::input("input",$form["input"]," class=\"textbox\"") @@ -248,7 +260,7 @@ modules/gallery/views/permissions_form.html.php              80  DIRTY_JS $permi  modules/gallery/views/permissions_form.html.php              80  DIRTY_JS $item->id  modules/gallery/views/quick_delete_confirm.html.php          11  DIRTY    $form  modules/gallery/views/reauthenticate.html.php                9   DIRTY    $form -modules/gallery/views/upgrade_checker_block.html.php         17  DIRTY    $new_version +modules/gallery/views/upgrade_checker_block.html.php         19  DIRTY    $new_version  modules/gallery/views/upgrader.html.php                      76  DIRTY_ATTR $done?"muted":""  modules/gallery/views/upgrader.html.php                      94  DIRTY_ATTR $done?"muted":""  modules/gallery/views/upgrader.html.php                      102 DIRTY_ATTR $module->version==$module->code_version?"current":"upgradeable" @@ -330,8 +342,9 @@ modules/search/views/search.html.php                         27  DIRTY_ATTR $ite  modules/search/views/search.html.php                         28  DIRTY_JS $item->url()  modules/search/views/search.html.php                         29  DIRTY    $item->thumb_img()  modules/search/views/search.html.php                         40  DIRTY    $theme->paginator() -modules/server_add/views/admin_server_add.html.php           5   DIRTY    $form -modules/server_add/views/admin_server_add.html.php           15  DIRTY_ATTR $id +modules/server_add/views/admin_server_add.html.php           8   DIRTY_JS url::site("__ARGS__") +modules/server_add/views/admin_server_add.html.php           19  DIRTY    $form +modules/server_add/views/admin_server_add.html.php           30  DIRTY_ATTR $id  modules/server_add/views/server_add_tree.html.php            20  DIRTY_ATTR is_dir($file)?"ui-icon-folder-collapsed":"ui-icon-document"  modules/server_add/views/server_add_tree.html.php            21  DIRTY_ATTR is_dir($file)?"g-directory":"g-file"  modules/server_add/views/server_add_tree_dialog.html.php     3   DIRTY_JS url::site("server_add/children?path=__PATH__") @@ -365,21 +378,21 @@ modules/watermark/views/admin_watermarks.html.php            20  DIRTY_ATTR $wid  modules/watermark/views/admin_watermarks.html.php            20  DIRTY_ATTR $height  modules/watermark/views/admin_watermarks.html.php            20  DIRTY_ATTR $url  themes/admin_wind/views/admin.html.php                       4   DIRTY    $theme->html_attributes() -themes/admin_wind/views/admin.html.php                       31  DIRTY    $theme->admin_head() -themes/admin_wind/views/admin.html.php                       40  DIRTY_JS $theme->url() -themes/admin_wind/views/admin.html.php                       45  DIRTY    $theme->get_combined("script") -themes/admin_wind/views/admin.html.php                       48  DIRTY    $theme->get_combined("css") -themes/admin_wind/views/admin.html.php                       52  DIRTY    $theme->admin_page_top() -themes/admin_wind/views/admin.html.php                       60  DIRTY    $theme->admin_header_top() -themes/admin_wind/views/admin.html.php                       61  DIRTY_JS item::root()->url() -themes/admin_wind/views/admin.html.php                       64  DIRTY    $theme->user_menu() -themes/admin_wind/views/admin.html.php                       67  DIRTY    $theme->admin_menu() -themes/admin_wind/views/admin.html.php                       70  DIRTY    $theme->admin_header_bottom() -themes/admin_wind/views/admin.html.php                       77  DIRTY    $content -themes/admin_wind/views/admin.html.php                       83  DIRTY    $sidebar -themes/admin_wind/views/admin.html.php                       88  DIRTY    $theme->admin_footer() -themes/admin_wind/views/admin.html.php                       91  DIRTY    $theme->admin_credits() -themes/admin_wind/views/admin.html.php                       96  DIRTY    $theme->admin_page_bottom() +themes/admin_wind/views/admin.html.php                       33  DIRTY    $theme->admin_head() +themes/admin_wind/views/admin.html.php                       42  DIRTY_JS $theme->url() +themes/admin_wind/views/admin.html.php                       47  DIRTY    $theme->get_combined("css") +themes/admin_wind/views/admin.html.php                       50  DIRTY    $theme->get_combined("script") +themes/admin_wind/views/admin.html.php                       54  DIRTY    $theme->admin_page_top() +themes/admin_wind/views/admin.html.php                       62  DIRTY    $theme->admin_header_top() +themes/admin_wind/views/admin.html.php                       63  DIRTY_JS item::root()->url() +themes/admin_wind/views/admin.html.php                       66  DIRTY    $theme->user_menu() +themes/admin_wind/views/admin.html.php                       69  DIRTY    $theme->admin_menu() +themes/admin_wind/views/admin.html.php                       72  DIRTY    $theme->admin_header_bottom() +themes/admin_wind/views/admin.html.php                       79  DIRTY    $content +themes/admin_wind/views/admin.html.php                       85  DIRTY    $sidebar +themes/admin_wind/views/admin.html.php                       90  DIRTY    $theme->admin_footer() +themes/admin_wind/views/admin.html.php                       93  DIRTY    $theme->admin_credits() +themes/admin_wind/views/admin.html.php                       98  DIRTY    $theme->admin_page_bottom()  themes/admin_wind/views/block.html.php                       3   DIRTY_ATTR $anchor  themes/admin_wind/views/block.html.php                       5   DIRTY    $id  themes/admin_wind/views/block.html.php                       5   DIRTY_ATTR $css_id @@ -414,19 +427,19 @@ themes/wind/views/page.html.php                              4   DIRTY    $theme  themes/wind/views/page.html.php                              10  DIRTY    $page_title  themes/wind/views/page.html.php                              13  DIRTY    $theme->item()->title  themes/wind/views/page.html.php                              17  DIRTY    item::root()->title -themes/wind/views/page.html.php                              31  DIRTY    $new_width -themes/wind/views/page.html.php                              32  DIRTY    $new_height -themes/wind/views/page.html.php                              33  DIRTY    $thumb_proportion -themes/wind/views/page.html.php                              70  DIRTY_JS $theme->url() -themes/wind/views/page.html.php                              75  DIRTY    $theme->get_combined("script") -themes/wind/views/page.html.php                              78  DIRTY    $theme->get_combined("css") -themes/wind/views/page.html.php                              88  DIRTY    $header_text -themes/wind/views/page.html.php                              90  DIRTY_JS item::root()->url() -themes/wind/views/page.html.php                              94  DIRTY    $theme->user_menu() -themes/wind/views/page.html.php                              115 DIRTY_JS $parent->url($parent->id==$theme->item()->parent_id?"show={$theme->item()->id}":null) -themes/wind/views/page.html.php                              136 DIRTY    $content -themes/wind/views/page.html.php                              142 DIRTY    newView("sidebar.html") -themes/wind/views/page.html.php                              149 DIRTY    $footer_text +themes/wind/views/page.html.php                              32  DIRTY    $new_width +themes/wind/views/page.html.php                              33  DIRTY    $new_height +themes/wind/views/page.html.php                              34  DIRTY    $thumb_proportion +themes/wind/views/page.html.php                              71  DIRTY_JS $theme->url() +themes/wind/views/page.html.php                              76  DIRTY    $theme->get_combined("css") +themes/wind/views/page.html.php                              79  DIRTY    $theme->get_combined("script") +themes/wind/views/page.html.php                              89  DIRTY    $header_text +themes/wind/views/page.html.php                              91  DIRTY_JS item::root()->url() +themes/wind/views/page.html.php                              95  DIRTY    $theme->user_menu() +themes/wind/views/page.html.php                              116 DIRTY_JS $parent->url($parent->id==$theme->item()->parent_id?"show={$theme->item()->id}":null) +themes/wind/views/page.html.php                              137 DIRTY    $content +themes/wind/views/page.html.php                              143 DIRTY    newView("sidebar.html") +themes/wind/views/page.html.php                              150 DIRTY    $footer_text  themes/wind/views/paginator.html.php                         33  DIRTY_JS $first_page_url  themes/wind/views/paginator.html.php                         42  DIRTY_JS $previous_page_url  themes/wind/views/paginator.html.php                         70  DIRTY_JS $next_page_url diff --git a/modules/gallery/views/admin_block_welcome.html.php b/modules/gallery/views/admin_block_welcome.html.php index d8c96187..d3765d19 100644 --- a/modules/gallery/views/admin_block_welcome.html.php +++ b/modules/gallery/views/admin_block_welcome.html.php @@ -2,7 +2,7 @@  <p>    <?= t("This is your administration dashboard and it provides a quick overview of status messages, recent updates, and frequently used options. Add or remove blocks and rearrange them to tailor to your needs. The admin menu provides quick access to all of Gallery 3's options and settings. Here are a few of the most used options to get you started.") ?>  </p> -<ul> +<ul class="g-text">    <li>      <?= t("General Settings - choose your <a href=\"%graphics_url\">graphics</a> and <a href=\"%language_url\">language</a> settings.",            array("graphics_url" => html::mark_clean(url::site("admin/graphics")), diff --git a/modules/gallery/views/admin_modules.html.php b/modules/gallery/views/admin_modules.html.php index 2cc81b0d..03993bb2 100644 --- a/modules/gallery/views/admin_modules.html.php +++ b/modules/gallery/views/admin_modules.html.php @@ -43,7 +43,7 @@    </script>    <h1> <?= t("Gallery Modules") ?> </h1>    <p> -    <?= t("Power up your Gallery by adding more modules! Each module provides new cool features.") ?> +    <?= t("Power up your Gallery by <a href=\"%url\">adding more modules</a>! Each module provides new cool features.", array("url" => "http://codex.gallery2.org/Category:Gallery_3:Modules")) ?>    </p>    <div class="g-block-content"> @@ -55,6 +55,7 @@            <th style="width: 8em"> <?= t("Name") ?> </th>            <th> <?= t("Version") ?> </th>            <th> <?= t("Description") ?> </th> +          <th style="width: 60px"> <?= t("Details") ?> </th>          </tr>          <? foreach ($available as $module_name => $module_info):  ?>          <tr class="<?= text::alternate("g-odd", "g-even") ?>"> @@ -64,6 +65,55 @@            <td> <?= t($module_info->name) ?> </td>            <td> <?= $module_info->version ?> </td>            <td> <?= t($module_info->description) ?> </td> +          <td style="white-space: nowrap"> +            <ul class="g-buttonset"> +              <li> +                <a target="_blank" +                   <? if (isset($module_info->author_url)): ?> +                   class="ui-state-default ui-icon ui-icon-person ui-corner-left" +                   href="<?= $module_info->author_url ?>" +                   <? else: ?> +                   class="ui-state-disabled ui-icon ui-icon-person ui-corner-left" +                   href="#" +                   <? endif ?> + +                   <? if (isset($module_info->author_name)): ?> +                   title="<?= $module_info->author_name ?>" +                   <? endif ?> +                   > +                   <? if (isset($module_info->author_name)): ?> +                   <?= $module_info->author_name ?> +                   <? endif ?> +                </a> +              </li> +              <li> +                <a target="_blank" +                   <? if (isset($module_info->info_url)): ?> +                   class="ui-state-default ui-icon ui-icon-info" +                   href="<?= $module_info->info_url ?>" +                   <? else: ?> +                   class="ui-state-disabled ui-icon ui-icon-info" +                   href="#" +                   <? endif ?> +                   > +                  <?= t("info") ?> +                </a> +              </li> +              <li> +                <a target="_blank" +                   <? if (isset($module_info->discuss_url)): ?> +                   class="ui-state-default ui-icon ui-icon-comment ui-corner-right" +                   href="<?= $module_info->discuss_url ?>" +                   <? else: ?> +                   class="ui-state-disabled ui-icon ui-icon-comment ui-corner-right" +                   href="#" +                   <? endif ?> +                   > +                  <?= t("discuss") ?> +                </a> +              </li> +            </ul> +          </td>          </tr>          <? endforeach ?>        </table> diff --git a/modules/gallery/views/admin_themes.html.php b/modules/gallery/views/admin_themes.html.php index d14e8bd4..7d947b28 100644 --- a/modules/gallery/views/admin_themes.html.php +++ b/modules/gallery/views/admin_themes.html.php @@ -10,7 +10,7 @@  <div class="g-block ui-helper-clearfix">    <h1> <?= t("Theme choice") ?> </h1>    <p> -    <?= t("Gallery allows you to choose a theme for browsing your Gallery, as well as a special theme for the administration interface.  Click a theme to preview and activate it.") ?> +    <?= t("Make your Gallery beautiful <a href=\"%url\">with a new theme</a>!  There are separate themes for the regular site and for the administration interface.  Click a theme below to preview and activate it.", array("url" => "http://codex.gallery2.org/Category:Gallery_3:Themes")) ?>    </p>    <div class="g-block-content"> @@ -23,6 +23,7 @@          <p>            <?= $themes[$site]->description ?>          </p> +        <? $v = new View("admin_themes_buttonset.html"); $v->info = $themes[$site]; print $v; ?>        </div>        <h2> <?= t("Available Gallery themes") ?> </h2> @@ -40,13 +41,14 @@                <?= $info->description ?>              </p>            </a> +          <? $v = new View("admin_themes_buttonset.html"); $v->info = $info; print $v; ?>          </div>          <? $count++ ?>          <? endforeach ?>          <? if (!$count): ?>          <p> -          <?= t("There are no other site themes available.") ?> +          <?= t("There are no other site themes available. <a href=\"%url\">Download one now!</a>", array("url" => "http://codex.gallery2.org/Category:Gallery_3:Modules")) ?>          </p>          <? endif ?>        </div> @@ -61,6 +63,7 @@          <p>            <?= $themes[$admin]->description ?>          </p> +        <? $v = new View("admin_themes_buttonset.html"); $v->info = $themes[$admin]; print $v; ?>        </div>        <h2> <?= t("Available admin themes") ?> </h2> @@ -78,17 +81,18 @@                <?= $info->description ?>              </p>            </a> +          <? $v = new View("admin_themes_buttonset.html"); $v->info = $info; print $v; ?>          </div>          <? $count++ ?>          <? endforeach ?>          <? if (!$count): ?>          <p> -          <?= t("There are no other admin themes available.") ?> +          <?= t("There are no other admin themes available. <a href=\"%url\">Download one now!</a>", array("url" => "http://codex.gallery2.org/Category:Gallery_3:Modules")) ?>          </p>          <? endif ?>        </div>      </div>    </div> -</div>
\ No newline at end of file +</div> diff --git a/modules/gallery/views/admin_themes_buttonset.html.php b/modules/gallery/views/admin_themes_buttonset.html.php new file mode 100644 index 00000000..bf474a26 --- /dev/null +++ b/modules/gallery/views/admin_themes_buttonset.html.php @@ -0,0 +1,48 @@ +<?php defined("SYSPATH") or die("No direct script access.") ?> +<ul class="g-buttonset"> +  <li> +    <a target="_blank" +       <? if (isset($info['author_url'])): ?> +       class="ui-state-default ui-icon ui-icon-person ui-corner-left" +       href="<?= $info['author_url'] ?>" +       <? else: ?> +       class="ui-state-disabled ui-icon ui-icon-person ui-corner-left" +       href="#" +       <? endif ?> + +       <? if (isset($info['author_name'])): ?> +       title="<?= $info['author_name'] ?>" +       <? endif ?> +       > +       <? if (isset($info['author_name'])): ?> +       <?= $info['author_name'] ?> +       <? endif ?> +    </a> +  </li> +  <li> +    <a target="_blank" +       <? if (isset($info['info_url'])): ?> +       class="ui-state-default ui-icon ui-icon-info" +       href="<?= $info['info_url'] ?>" +       <? else: ?> +       class="ui-state-disabled ui-icon ui-icon-info" +       href="#" +       <? endif ?> +       > +      <?= t("info") ?> +    </a> +  </li> +  <li> +    <a target="_blank" +       <? if (isset($info['discuss_url'])): ?> +       class="ui-state-default ui-icon ui-icon-comment ui-corner-right" +       href="<?= $info['discuss_url'] ?>" +       <? else: ?> +       class="ui-state-disabled ui-icon ui-icon-comment ui-corner-right" +       href="#" +       <? endif ?> +       > +      <?= t("discuss") ?> +    </a> +  </li> +</ul> diff --git a/modules/gallery/views/form_uploadify.html.php b/modules/gallery/views/form_uploadify.html.php index 77b6d493..83dfcc68 100644 --- a/modules/gallery/views/form_uploadify.html.php +++ b/modules/gallery/views/form_uploadify.html.php @@ -32,6 +32,7 @@          fileDesc: <?= t("Photos and movies")->for_js() ?>,          cancelImg: "<?= url::file("lib/uploadify/cancel.png") ?>",          simUploadLimit: <?= $simultaneous_upload_limit ?>, +        sizeLimit: <?= $size_limit_bytes ?>,          wmode: "transparent",          hideButton: true, /* should be true */          auto: true, @@ -66,26 +67,30 @@            return true;          },          onError: function(event, queueID, fileObj, errorObj) { -          var msg = " - ";            if (errorObj.type == "HTTP") {              if (errorObj.info == "500") { -              msg += <?= t("Unable to process this file")->for_js() ?>; -              // Server error - check server logs +              error_msg = <?= t("Unable to process this photo")->for_js() ?>;              } else if (errorObj.info == "404") { -              msg += <?= t("The upload script was not found.")->for_js() ?>; -              // Server script not found +              error_msg = <?= t("The upload script was not found")->for_js() ?>; +            } else if (errorObj.info == "400") { +              error_msg = <?= t("This photo is too large (max is %size bytes)", +                                array("size" => $size_limit))->for_js() ?>;              } else { -              // Server Error: status: errorObj.info -              msg += (<?= t("Server error: __INFO__")->for_js() ?>.replace("__INFO__", errorObj.info)); +              msg += (<?= t("Server error: __INFO__ (__TYPE__)")->for_js() ?> +                .replace("__INFO__", errorObj.info) +                .replace("__TYPE__", errorObj.type));              }            } else if (errorObj.type == "File Size") { -            var sizelimit = $("#g-uploadify").uploadifySettings(sizeLimit); -            msg += fileObj.name+' '+errorObj.type+' Limit: '+Math.round(d.sizeLimit/1024)+'KB'; +            error_msg = <?= t("This photo is too large (max is %size bytes)", +                              array("size" => $size_limit))->for_js() ?>;            } else { -            msg += (<?= t("Server error: __INFO__ (__TYPE__)")->for_js() ?> -              .replace("__INFO__", errorObj.info) -              .replace("__TYPE__", errorObj.type)); +            error_msg = <?= t("Server error: __INFO__ (__TYPE__)")->for_js() ?> +                        .replace("__INFO__", errorObj.info) +                        .replace("__TYPE__", errorObj.type);            } +          msg = " - <a target=\"_blank\" href=\"http://codex.gallery2.org/Gallery3:Troubleshooting:Uploading\">" + +            error_msg + "</a>"; +            $("#g-add-photos-status ul").append(              "<li id=\"q" + queueID + "\" class=\"g-error\">" + fileObj.name + msg + "</li>");            $("#g-uploadify").uploadifyCancel(queueID); @@ -131,10 +136,7 @@    <? endif ?>    <div> -    <p> -      <?= t("Photos will be uploaded to album: ") ?> -    </p> -    <ul class="g-breadcrumbs ui-helper-clearfix"> +    <ul class="g-breadcrumbs">        <? foreach ($album->parents() as $i => $parent): ?>        <li<? if ($i == 0) print " class=\"g-first\"" ?>> <?= html::clean($parent->title) ?> </li>        <? endforeach ?> @@ -143,7 +145,7 @@    </div>    <div id="g-add-photos-canvas"> -    <button id="g-add-photos-button" class="g-button ui-state-default ui-corner-all" href="#"><?= t("Select photos...") ?></button> +    <button id="g-add-photos-button" class="g-button ui-state-default ui-corner-all" href="#"><?= t("Select photos (%size max per file)...", array("size" => $size_limit)) ?></button>      <span id="g-uploadify"></span>    </div>    <div id="g-add-photos-status"> diff --git a/modules/gallery/views/movieplayer.html.php b/modules/gallery/views/movieplayer.html.php index 5c280a36..96d6532c 100644 --- a/modules/gallery/views/movieplayer.html.php +++ b/modules/gallery/views/movieplayer.html.php @@ -22,5 +22,5 @@          }        }      } -  ) +  ).ipad();  </script> diff --git a/modules/gallery/views/upgrader.html.php b/modules/gallery/views/upgrader.html.php index ad2e3421..70d37dd1 100644 --- a/modules/gallery/views/upgrader.html.php +++ b/modules/gallery/views/upgrader.html.php @@ -27,7 +27,7 @@            <div id="done" style="display: none">              <h1> <?= t("That's it!") ?> </h1>              <p> -              <?= t("Your <a href=\"%url\">Gallery</a> is up to date.", +              <?= t("Your Gallery is up to date.<br/><a href=\"%url\">Return to your Gallery</a>",                      array("url" => html::mark_clean(url::base()))) ?>              </p>            </div> diff --git a/modules/gallery_unit_test/helpers/test.php b/modules/gallery_unit_test/helpers/test.php index b6b0055a..633f023e 100644 --- a/modules/gallery_unit_test/helpers/test.php +++ b/modules/gallery_unit_test/helpers/test.php @@ -19,7 +19,7 @@   */  class test_Core {    static function random_album_unsaved($parent=null) { -    $rand = random::string(6); +    $rand = test::random_string(6);      $album = ORM::factory("item");      $album->type = "album"; @@ -34,7 +34,7 @@ class test_Core {    }    static function random_photo_unsaved($parent=null) { -    $rand = random::string(6); +    $rand = test::random_string(6);      $photo = ORM::factory("item");      $photo->type = "photo";      $photo->parent_id = $parent ? $parent->id : 1; @@ -49,16 +49,16 @@ class test_Core {    }    static function random_user($password="password") { -    $rand = "name_" . random::string(6); +    $rand = "name_" . test::random_string(6);      return identity::create_user($rand, $rand, $password, "$rand@rand.com");    }    static function random_group() { -    return identity::create_group(random::string(6)); +    return identity::create_group(test::random_string(6));    }    static function random_name($item=null) { -    $rand = "name_" . random::string(6); +    $rand = "name_" . test::random_string(6);      if ($item && $item->is_photo()) {        $rand .= ".jpg";      } @@ -77,7 +77,7 @@ class test_Core {    static function random_tag() {      $tag = ORM::factory("tag"); -    $tag->name = random::string(6); +    $tag->name = test::lorem_ipsum(rand(2, 4));      // Reload so that ORM coerces all fields into strings.      return $tag->save()->reload(); @@ -88,4 +88,22 @@ class test_Core {      fwrite(fopen($b_name = tempnam("/tmp", "test"), "w"), $b);      return `diff $a_name $b_name`;    } + +  static function random_string($length) { +    $buf = ""; +    do { +      $buf .= random::hash(); +    } while (strlen($buf) < $length); +    return substr($buf, 0, $length); +  } + +  static function lorem_ipsum($num) { +    static $lorem_ipsum = null; +    if (!$lorem_ipsum) { +      require_once(MODPATH . "gallery_unit_test/vendor/LoremIpsum.class.php"); +      $lorem_ipsum = new LoremIpsumGenerator(); +    } +    // skip past initial 'lorem ipsum' +    return substr($lorem_ipsum->getContent($num + 2, "txt"), 13); +  }  } diff --git a/modules/gallery_unit_test/vendor/LoremIpsum.class.php b/modules/gallery_unit_test/vendor/LoremIpsum.class.php new file mode 100644 index 00000000..07050fe5 --- /dev/null +++ b/modules/gallery_unit_test/vendor/LoremIpsum.class.php @@ -0,0 +1,461 @@ +<?php defined("SYSPATH") or die("No direct script access."); +class LoremIpsumGenerator { +	/** +	*	Copyright (c) 2009, Mathew Tinsley (tinsley@tinsology.net) +	*	All rights reserved. +	* +	*	Redistribution and use in source and binary forms, with or without +	*	modification, are permitted provided that the following conditions are met: +	*		* Redistributions of source code must retain the above copyright +	*		  notice, this list of conditions and the following disclaimer. +	*		* Redistributions in binary form must reproduce the above copyright +	*		  notice, this list of conditions and the following disclaimer in the +	*		  documentation and/or other materials provided with the distribution. +	*		* Neither the name of the organization nor the +	*		  names of its contributors may be used to endorse or promote products +	*		  derived from this software without specific prior written permission. +	* +	*	THIS SOFTWARE IS PROVIDED BY MATHEW TINSLEY ''AS IS'' AND ANY +	*	EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +	*	WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +	*	DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY +	*	DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +	*	(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +	*	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +	*	ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +	*	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +	*	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +	*/ +	 +	private $words, $wordsPerParagraph, $wordsPerSentence; +	 +	function __construct($wordsPer = 100) +	{ +		$this->wordsPerParagraph = $wordsPer; +		$this->wordsPerSentence = 24.460; +		$this->words = array( +		'lorem', +		'ipsum', +		'dolor', +		'sit', +		'amet', +		'consectetur', +		'adipiscing', +		'elit', +		'curabitur', +		'vel', +		'hendrerit', +		'libero', +		'eleifend', +		'blandit', +		'nunc', +		'ornare', +		'odio', +		'ut', +		'orci', +		'gravida', +		'imperdiet', +		'nullam', +		'purus', +		'lacinia', +		'a', +		'pretium', +		'quis', +		'congue', +		'praesent', +		'sagittis', +		'laoreet', +		'auctor', +		'mauris', +		'non', +		'velit', +		'eros', +		'dictum', +		'proin', +		'accumsan', +		'sapien', +		'nec', +		'massa', +		'volutpat', +		'venenatis', +		'sed', +		'eu', +		'molestie', +		'lacus', +		'quisque', +		'porttitor', +		'ligula', +		'dui', +		'mollis', +		'tempus', +		'at', +		'magna', +		'vestibulum', +		'turpis', +		'ac', +		'diam', +		'tincidunt', +		'id', +		'condimentum', +		'enim', +		'sodales', +		'in', +		'hac', +		'habitasse', +		'platea', +		'dictumst', +		'aenean', +		'neque', +		'fusce', +		'augue', +		'leo', +		'eget', +		'semper', +		'mattis', +		'tortor', +		'scelerisque', +		'nulla', +		'interdum', +		'tellus', +		'malesuada', +		'rhoncus', +		'porta', +		'sem', +		'aliquet', +		'et', +		'nam', +		'suspendisse', +		'potenti', +		'vivamus', +		'luctus', +		'fringilla', +		'erat', +		'donec', +		'justo', +		'vehicula', +		'ultricies', +		'varius', +		'ante', +		'primis', +		'faucibus', +		'ultrices', +		'posuere', +		'cubilia', +		'curae', +		'etiam', +		'cursus', +		'aliquam', +		'quam', +		'dapibus', +		'nisl', +		'feugiat', +		'egestas', +		'class', +		'aptent', +		'taciti', +		'sociosqu', +		'ad', +		'litora', +		'torquent', +		'per', +		'conubia', +		'nostra', +		'inceptos', +		'himenaeos', +		'phasellus', +		'nibh', +		'pulvinar', +		'vitae', +		'urna', +		'iaculis', +		'lobortis', +		'nisi', +		'viverra', +		'arcu', +		'morbi', +		'pellentesque', +		'metus', +		'commodo', +		'ut', +		'facilisis', +		'felis', +		'tristique', +		'ullamcorper', +		'placerat', +		'aenean', +		'convallis', +		'sollicitudin', +		'integer', +		'rutrum', +		'duis', +		'est', +		'etiam', +		'bibendum', +		'donec', +		'pharetra', +		'vulputate', +		'maecenas', +		'mi', +		'fermentum', +		'consequat', +		'suscipit', +		'aliquam', +		'habitant', +		'senectus', +		'netus', +		'fames', +		'quisque', +		'euismod', +		'curabitur', +		'lectus', +		'elementum', +		'tempor', +		'risus', +		'cras' ); +	} +		 +	function getContent($count, $format = 'html', $loremipsum = true) +	{ +		$format = strtolower($format); +		 +		if($count <= 0) +			return ''; + +		switch($format) +		{ +			case 'txt': +				return $this->getText($count, $loremipsum); +			case 'plain': +				return $this->getPlain($count, $loremipsum); +			default: +				return $this->getHTML($count, $loremipsum); +		} +	} +	 +	private function getWords(&$arr, $count, $loremipsum) +	{ +		$i = 0; +		if($loremipsum) +		{ +			$i = 2; +			$arr[0] = 'lorem'; +			$arr[1] = 'ipsum'; +		} +		 +		for($i; $i < $count; $i++) +		{ +			$index = array_rand($this->words); +			$word = $this->words[$index]; +			//echo $index . '=>' . $word . '<br />'; +			 +			if($i > 0 && $arr[$i - 1] == $word) +				$i--; +			else +				$arr[$i] = $word; +		} +	} +	 +	private function getPlain($count, $loremipsum, $returnStr = true) +	{ +		$words = array(); +		$this->getWords($words, $count, $loremipsum); +		//print_r($words); +		 +		$delta = $count; +		$curr = 0; +		$sentences = array(); +		while($delta > 0) +		{ +			$senSize = $this->gaussianSentence(); +			//echo $curr . '<br />'; +			if(($delta - $senSize) < 4) +				$senSize = $delta; + +			$delta -= $senSize; +			 +			$sentence = array(); +			for($i = $curr; $i < ($curr + $senSize); $i++) +				$sentence[] = $words[$i]; + +			$this->punctuate($sentence); +			$curr = $curr + $senSize; +			$sentences[] = $sentence; +		} +		 +		if($returnStr) +		{ +			$output = ''; +			foreach($sentences as $s) +				foreach($s as $w) +					$output .= $w . ' '; +					 +			return $output; +		} +		else +			return $sentences; +	} +	 +	private function getText($count, $loremipsum) +	{ +		$sentences = $this->getPlain($count, $loremipsum, false); +		$paragraphs = $this->getParagraphArr($sentences); +		 +		$paragraphStr = array(); +		foreach($paragraphs as $p) +		{ +			$paragraphStr[] = $this->paragraphToString($p); +		} +		 +		$paragraphStr[0] = "\t" . $paragraphStr[0]; +		return implode("\n\n\t", $paragraphStr); +	} +	 +	private function getParagraphArr($sentences) +	{ +		$wordsPer = $this->wordsPerParagraph; +		$sentenceAvg = $this->wordsPerSentence; +		$total = count($sentences); +		 +		$paragraphs = array(); +		$pCount = 0; +		$currCount = 0; +		$curr = array(); +		 +		for($i = 0; $i < $total; $i++) +		{ +			$s = $sentences[$i]; +			$currCount += count($s); +			$curr[] = $s; +			if($currCount >= ($wordsPer - round($sentenceAvg / 2.00)) || $i == $total - 1) +			{ +				$currCount = 0; +				$paragraphs[] = $curr; +				$curr = array(); +				//print_r($paragraphs); +			} +			//print_r($paragraphs); +		} +		 +		return $paragraphs; +	} +	 +	private function getHTML($count, $loremipsum) +	{ +		$sentences = $this->getPlain($count, $loremipsum, false); +		$paragraphs = $this->getParagraphArr($sentences); +		//print_r($paragraphs); +		 +		$paragraphStr = array(); +		foreach($paragraphs as $p) +		{ +			$paragraphStr[] = "<p>\n" . $this->paragraphToString($p, true) . '</p>'; +		} +		 +		//add new lines for the sake of clean code +		return implode("\n", $paragraphStr); +	} +	 +	private function paragraphToString($paragraph, $htmlCleanCode = false) +	{ +		$paragraphStr = ''; +		foreach($paragraph as $sentence) +		{ +			foreach($sentence as $word) +				$paragraphStr .= $word . ' '; +				 +			if($htmlCleanCode) +				$paragraphStr .= "\n"; +		}		 +		return $paragraphStr; +	} +	 +	/* +	* Inserts commas and periods in the given +	* word array. +	*/ +	private function punctuate(& $sentence) +	{ +		$count = count($sentence); +		$sentence[$count - 1] = $sentence[$count - 1] . '.'; +		 +		if($count < 4) +			return $sentence; +		 +		$commas = $this->numberOfCommas($count); +		 +		for($i = 1; $i <= $commas; $i++) +		{ +			$index = (int) round($i * $count / ($commas + 1)); +			 +			if($index < ($count - 1) && $index > 0) +			{ +				$sentence[$index] = $sentence[$index] . ','; +			} +		} +	} +	 +	/* +	* Determines the number of commas for a +	* sentence of the given length. Average and +	* standard deviation are determined superficially +	*/ +	private function numberOfCommas($len) +	{ +		$avg = (float) log($len, 6); +		$stdDev = (float) $avg / 6.000; +		 +		return (int) round($this->gauss_ms($avg, $stdDev)); +	} +	 +	/* +	* Returns a number on a gaussian distribution +	* based on the average word length of an english +	* sentence. +	* Statistics Source: +	*	http://hearle.nahoo.net/Academic/Maths/Sentence.html +	*	Average: 24.46 +	*	Standard Deviation: 5.08 +	*/ +	private function gaussianSentence() +	{ +		$avg = (float) 24.460; +		$stdDev = (float) 5.080; +		 +		return (int) round($this->gauss_ms($avg, $stdDev)); +	} +	 +	/* +	* The following three functions are used to +	* compute numbers with a guassian distrobution +	* Source: +	* 	http://us.php.net/manual/en/function.rand.php#53784 +	*/ +	private function gauss() +	{   // N(0,1) +		// returns random number with normal distribution: +		//   mean=0 +		//   std dev=1 +		 +		// auxilary vars +		$x=$this->random_0_1(); +		$y=$this->random_0_1(); +		 +		// two independent variables with normal distribution N(0,1) +		$u=sqrt(-2*log($x))*cos(2*pi()*$y); +		$v=sqrt(-2*log($x))*sin(2*pi()*$y); +		 +		// i will return only one, couse only one needed +		return $u; +	} + +	private function gauss_ms($m=0.0,$s=1.0) +	{ +		return $this->gauss()*$s+$m; +	} + +	private function random_0_1() +	{ +		return (float)rand()/(float)getrandmax(); +	} + +}
\ No newline at end of file diff --git a/modules/image_block/module.info b/modules/image_block/module.info index 6836fabc..6722cc8f 100644 --- a/modules/image_block/module.info +++ b/modules/image_block/module.info @@ -1,3 +1,7 @@  name = "Image Block"  description = "Display a random image in the sidebar"  version = 3 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:image_block" +discuss_url = "http://gallery.menalto.com/forum_module_image_block" diff --git a/modules/info/module.info b/modules/info/module.info index 5f84cbb9..f8964a78 100644 --- a/modules/info/module.info +++ b/modules/info/module.info @@ -1,3 +1,7 @@  name = "Info"  description = "Display extra information about photos and albums"  version = 2 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:info" +discuss_url = "http://gallery.menalto.com/forum_module_info" diff --git a/modules/notification/module.info b/modules/notification/module.info index 8c5e1162..84be8f99 100644 --- a/modules/notification/module.info +++ b/modules/notification/module.info @@ -1,3 +1,7 @@  name = "Notification"  description = "Send notifications to users when changes are made to watched albums."  version = 2 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:notification" +discuss_url = "http://gallery.menalto.com/forum_module_notification" diff --git a/modules/organize/module.info b/modules/organize/module.info index 0d16144d..07b9dc38 100644 --- a/modules/organize/module.info +++ b/modules/organize/module.info @@ -1,3 +1,7 @@  name = "Organize"  description = "Visually rearrange and move photos in your gallery"  version = 4 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:organize" +discuss_url = "http://gallery.menalto.com/forum_module_organize" diff --git a/modules/recaptcha/module.info b/modules/recaptcha/module.info index cfa1bf7a..ebaff7de 100644 --- a/modules/recaptcha/module.info +++ b/modules/recaptcha/module.info @@ -1,3 +1,7 @@  name = "reCAPTCHA"  description = "reCAPTCHA displays a graphical verification that protects the input form from abuse from 'bots,' or automated programs usually written to generate spam (http://recaptcha.net)."  version = 1 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:recaptcha" +discuss_url = "http://gallery.menalto.com/forum_module_recaptcha" diff --git a/modules/rest/module.info b/modules/rest/module.info index 5aaffc28..33c9f1cf 100644 --- a/modules/rest/module.info +++ b/modules/rest/module.info @@ -2,3 +2,7 @@ name = "REST API Module"  description = "A REST-based API that allows desktop clients and other apps to interact with Gallery 3"  version = 3 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:rest" +discuss_url = "http://gallery.menalto.com/forum_module_rest" diff --git a/modules/rss/module.info b/modules/rss/module.info index 48375da1..cd13c1b0 100644 --- a/modules/rss/module.info +++ b/modules/rss/module.info @@ -1,3 +1,7 @@  name = "RSS"  description = "Provides RSS feeds"  version = 1 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:rss" +discuss_url = "http://gallery.menalto.com/forum_module_rss" diff --git a/modules/search/module.info b/modules/search/module.info index f417c4fa..1389798d 100644 --- a/modules/search/module.info +++ b/modules/search/module.info @@ -1,3 +1,7 @@  name = "Search"  description = "Allows users to search their Gallery"  version = 1 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:search" +discuss_url = "http://gallery.menalto.com/forum_module_search" diff --git a/modules/server_add/helpers/server_add_theme.php b/modules/server_add/helpers/server_add_theme.php index 50c050a8..cfca5901 100644 --- a/modules/server_add/helpers/server_add_theme.php +++ b/modules/server_add/helpers/server_add_theme.php @@ -24,20 +24,4 @@ class server_add_theme_Core {          . $theme->script("server_add.js");      }    } - -  static function admin_head($theme) { -    $buf = ""; -    if (strpos(Router::$current_uri, "admin/server_add") !== false) { -      $buf .= $theme->css("server_add.css") -        . $theme->css("jquery.autocomplete.css"); -      $base = url::site("__ARGS__"); -      $csrf = access::csrf_token(); -      $buf .= "<script type=\"text/javascript\"> var base_url = \"$base\"; var csrf = \"$csrf\";</script>"; - -      $buf .= $theme->script("jquery.autocomplete.js") -        . $theme->script("admin.js"); -    } - -    return $buf; -  }  }
\ No newline at end of file diff --git a/modules/server_add/js/admin.js b/modules/server_add/js/admin.js deleted file mode 100644 index 9d7bd181..00000000 --- a/modules/server_add/js/admin.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Set up autocomplete on the server path list - * - */ -$("document").ready(function() { -  $("#g-path").autocomplete( -    base_url.replace("__ARGS__", "admin/server_add/autocomplete"), {max: 256}); -}); diff --git a/modules/server_add/module.info b/modules/server_add/module.info index 87b317b1..4ce0a97d 100644 --- a/modules/server_add/module.info +++ b/modules/server_add/module.info @@ -1,3 +1,7 @@  name = "Server Add"  description = "Allows authorized users to load images directly from your web server"  version = 4 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:server_add" +discuss_url = "http://gallery.menalto.com/forum_module_server_add" diff --git a/modules/server_add/views/admin_server_add.html.php b/modules/server_add/views/admin_server_add.html.php index 933ab7f8..474ad428 100644 --- a/modules/server_add/views/admin_server_add.html.php +++ b/modules/server_add/views/admin_server_add.html.php @@ -1,4 +1,18 @@  <?php defined("SYSPATH") or die("No direct script access.") ?> +<?= $theme->css("server_add.css") ?> +<?= $theme->css("jquery.autocomplete.css") ?> +<?= $theme->script("jquery.autocomplete.js") ?> +<script type="text/javascript"> +$("document").ready(function() { +  $("#g-path").autocomplete( +    "<?= url::site("__ARGS__") ?>".replace("__ARGS__", "admin/server_add/autocomplete"), +    { +      max: 256, +      loadingClass: "g-loading-small", +    }); +}); +</script> +  <div class="g-block">    <h1> <?= t("Add from server administration") ?> </h1>    <div class="g-block-content"> @@ -8,12 +22,17 @@        <? if (empty($paths)): ?>        <li class="g-module-status g-info"><?= t("No authorized image source paths defined yet") ?></li>        <? endif ?> +        <? foreach ($paths as $id => $path): ?>        <li>          <?= html::clean($path) ?> -        <a href="<?= url::site("admin/server_add/remove_path?path=" . urlencode($path) . "&csrf=$csrf") ?>" +        <a href="<?= url::site("admin/server_add/remove_path?path=" . urlencode($path) . "&csrf=<?= access::csrf_token() ?>") ?>"             id="icon_<?= $id ?>" -           class="g-remove-dir g-button"><span class="ui-icon ui-icon-trash"><?= t("delete") ?></span></a> +           class="g-remove-dir g-button"> +          <span class="ui-icon ui-icon-trash"> +            <?= t("delete") ?> +          </span> +        </a>        </li>        <? endforeach ?>      </ul> diff --git a/modules/slideshow/module.info b/modules/slideshow/module.info index b56eac81..8c9a3176 100644 --- a/modules/slideshow/module.info +++ b/modules/slideshow/module.info @@ -1,3 +1,7 @@  name = "Slideshow"  description = "Allows users to view a slideshow of photos"  version = 2 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:slideshow" +discuss_url = "http://gallery.menalto.com/forum_module_slideshow" diff --git a/modules/tag/controllers/admin_tags.php b/modules/tag/controllers/admin_tags.php index 73042a55..77b5f20a 100644 --- a/modules/tag/controllers/admin_tags.php +++ b/modules/tag/controllers/admin_tags.php @@ -81,17 +81,25 @@ class Admin_Tags_Controller extends Admin_Controller {      $in_place_edit = InPlaceEdit::factory($tag->name)        ->action("admin/tags/rename/$tag->id") -      ->rules(array("required", "length[1,64]")) -      ->messages(array("in_use" => t("There is already a tag with that name"))) -      ->callback(array($this, "check_for_duplicate")); +      ->rules(array("required", "length[1,64]"));      if ($in_place_edit->validate()) {        $old_name = $tag->name; -      $tag->name = $in_place_edit->value(); +      $new_name_or_list = $in_place_edit->value(); +      $tag_list = explode(",", $new_name_or_list); + +      $tag->name = array_shift($tag_list);        $tag->save(); -      $message = t("Renamed tag <b>%old_name</b> to <b>%new_name</b>", -                   array("old_name" => $old_name, "new_name" => $tag->name)); +      if (!empty($tag_list)) { +        $this->_copy_items_for_tags($tag, $tag_list); +        $message = t("Split tag <i>%old_name</i> into <i>%tag_list</i>", +                     array("old_name" => $old_name, "tag_list" => $new_name_or_list)); +      } else { +        $message = t("Renamed tag <i>%old_name</i> to <i>%new_name</i>", +                     array("old_name" => $old_name, "new_name" => $tag->name)); +      } +        message::success($message);        log::success("tags", $message); @@ -101,12 +109,11 @@ class Admin_Tags_Controller extends Admin_Controller {      }    } -  public function check_for_duplicate(Validation $post_data, $field) { -    $tag_exists = ORM::factory("tag")->where("name", "=", $post_data[$field])->count_all(); -    if ($tag_exists) { -      $post_data->add_error($field, "in_use"); +  private function _copy_items_for_tags($tag, $tag_list) { +    foreach ($tag->items() as $item) { +      foreach ($tag_list as $new_tag_name) { +        tag::add($item, trim($new_tag_name)); +      }      }    } -  } - diff --git a/modules/tag/controllers/tags.php b/modules/tag/controllers/tags.php index fe6d747b..bf41c4df 100644 --- a/modules/tag/controllers/tags.php +++ b/modules/tag/controllers/tags.php @@ -22,7 +22,8 @@ class Tags_Controller extends Controller {      // Far from perfection, but at least require view permission for the root album      $album = ORM::factory("item", 1);      access::required("view", $album); -    print tag::cloud(30); + +    print tag::cloud(module::get_var("tag", "tag_cloud_size", 30));    }    public function create($item_id) { diff --git a/modules/tag/helpers/tag.php b/modules/tag/helpers/tag.php index 733215b3..c21104ee 100644 --- a/modules/tag/helpers/tag.php +++ b/modules/tag/helpers/tag.php @@ -48,6 +48,7 @@ class tag_Core {     * @return ORM_Iterator of Tag_Model in descending tag count order     */    static function popular_tags($count) { +    $count = max($count, 1);      return ORM::factory("tag")        ->order_by("count", "DESC")        ->limit($count) diff --git a/modules/tag/helpers/tag_block.php b/modules/tag/helpers/tag_block.php index 0ee0f5f5..74656a0a 100644 --- a/modules/tag/helpers/tag_block.php +++ b/modules/tag/helpers/tag_block.php @@ -30,7 +30,7 @@ class tag_block_Core {        $block->css_id = "g-tag";        $block->title = t("Tags");        $block->content = new View("tag_block.html"); -      $block->content->cloud = tag::cloud(250); +      $block->content->cloud = tag::cloud(module::get_var("tag", "tag_cloud_size", 250));        if ($theme->item() && $theme->page_subtype() != "tag" && access::can("edit", $theme->item())) {          $controller = new Tags_Controller(); diff --git a/modules/tag/helpers/tag_installer.php b/modules/tag/helpers/tag_installer.php index 16ad1239..66a78b91 100644 --- a/modules/tag/helpers/tag_installer.php +++ b/modules/tag/helpers/tag_installer.php @@ -36,7 +36,8 @@ class tag_installer {                   KEY(`tag_id`, `id`),                   KEY(`item_id`, `id`))                 DEFAULT CHARSET=utf8;"); -    module::set_version("tag", 2); +    module::set_var("tag", "tag_cloud_size", 30); +    module::set_version("tag", 3);    }    static function upgrade($version) { @@ -45,6 +46,10 @@ class tag_installer {        $db->query("ALTER TABLE {tags} MODIFY COLUMN `name` VARCHAR(128)");        module::set_version("tag", $version = 2);      } +    if ($version == 2) { +      module::set_var("tag", "tag_cloud_size", 30); +      module::set_version("tag", $version = 3); +    }    }    static function uninstall() { diff --git a/modules/tag/models/tag.php b/modules/tag/models/tag.php index 6bc5350a..3dd71d8d 100644 --- a/modules/tag/models/tag.php +++ b/modules/tag/models/tag.php @@ -70,13 +70,23 @@ class Tag_Model_Core extends ORM {     * to this tag.     */    public function save() { -    $related_item_ids = array(); -    foreach (db::build() -             ->select("item_id") -             ->from("items_tags") -             ->where("tag_id", "=", $this->id) -             ->execute() as $row) { -      $related_item_ids[$row->item_id] = 1; +    // Check to see if another tag exists with the same name +    $duplicate_tag = ORM::factory("tag") +      ->where("name", "=", $this->name) +      ->where("id", "!=", $this->id) +      ->find(); +    if ($duplicate_tag->loaded()) { +      // If so, tag its items with this tag so as to merge it +      $duplicate_tag_items = ORM::factory("item") +        ->join("items_tags", "items.id", "items_tags.item_id") +        ->where("items_tags.tag_id", "=", $duplicate_tag->id) +        ->find_all(); +      foreach ($duplicate_tag_items as $item) { +        $this->add($item); +      } + +      // ... and remove the duplicate tag +      $duplicate_tag->delete();      }      if (isset($this->object_relations["items"])) { diff --git a/modules/tag/module.info b/modules/tag/module.info index 8851d119..75d16bf0 100644 --- a/modules/tag/module.info +++ b/modules/tag/module.info @@ -1,3 +1,7 @@  name = "Tags"  description = "Allows users to tag photos and albums" -version = 2 +version = 3 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:tag" +discuss_url = "http://gallery.menalto.com/forum_module_tag" diff --git a/modules/tag/tests/Tag_Test.php b/modules/tag/tests/Tag_Test.php index f5ccb3a2..9e10fa4a 100644 --- a/modules/tag/tests/Tag_Test.php +++ b/modules/tag/tests/Tag_Test.php @@ -18,18 +18,60 @@   * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.   */  class Tag_Test extends Gallery_Unit_Test_Case { +  public function teardown() { +    ORM::factory("tag")->delete_all(); +  } +    public function create_tag_test() {      $album = test::random_album();      tag::add($album, "tag1");      $tag = ORM::factory("tag")->where("name", "=", "tag1")->find(); -    $this->assert_true(1, $tag->count); +    $this->assert_equal(1, $tag->count);      // Make sure adding the tag again doesn't increase the count      tag::add($album, "tag1"); -    $this->assert_true(1, $tag->reload()->count); +    $this->assert_equal(1, $tag->reload()->count);      tag::add(test::random_album(), "tag1"); -    $this->assert_true(2, $tag->reload()->count); +    $this->assert_equal(2, $tag->reload()->count); +  } + +  public function rename_merge_tag_test() { +    $album1 = test::random_album(); +    $album2 = test::random_album(); + +    tag::add($album1, "tag1"); +    tag::add($album2, "tag2"); + +    $tag1 = ORM::factory("tag")->where("name", "=", "tag1")->find(); +    $tag1->name = "tag2"; +    $tag1->save(); + +    // Tags should be merged; $tag2 should be deleted +    $tag1->reload(); + +    $this->assert_equal(2, $tag1->count); +    $this->assert_true($tag1->has($album1)); +    $this->assert_true($tag1->has($album2)); +    $this->assert_equal(1, ORM::factory("tag")->count_all()); +  } + +  public function rename_merge_tag_with_same_items_test() { +    $album = test::random_album(); + +    tag::add($album, "tag1"); +    tag::add($album, "tag2"); + +    $tag1 = ORM::factory("tag")->where("name", "=", "tag1")->find(); +    $tag1->name = "tag2"; +    $tag1->save(); + +    // Tags should be merged +    $tag1->reload(); + +    $this->assert_equal(1, $tag1->count); +    $this->assert_true($tag1->has($album)); +    $this->assert_equal(1, ORM::factory("tag")->count_all());    } -}
\ No newline at end of file +} diff --git a/modules/user/controllers/admin_users.php b/modules/user/controllers/admin_users.php index a3633b52..41be6c03 100644 --- a/modules/user/controllers/admin_users.php +++ b/modules/user/controllers/admin_users.php @@ -21,6 +21,8 @@ class Admin_Users_Controller extends Admin_Controller {    public function index() {      $view = new Admin_View("admin.html");      $view->page_title = t("Users and groups"); +    $view->page_type = "collection"; +    $view->page_subtype = "admin_users";      $view->content = new View("admin_users.html");      // @todo: add this as a config option @@ -29,6 +31,12 @@ class Admin_Users_Controller extends Admin_Controller {      $builder = db::build();      $user_count = $builder->from("users")->count_records(); +    // Pagination info +    $view->page = $page; +    $view->page_size = $page_size; +    $view->children_count = $user_count; +    $view->max_pages = ceil($view->children_count / $view->page_size); +      $view->content->pager = new Pagination();      $view->content->pager->initialize(        array("query_string" => "page", diff --git a/modules/user/controllers/password.php b/modules/user/controllers/password.php index 4e93d5ce..cd46bbed 100644 --- a/modules/user/controllers/password.php +++ b/modules/user/controllers/password.php @@ -105,7 +105,7 @@ class Password_Controller extends Controller {      if (!empty($hash)) {        $hidden->value($hash);      } -    $minimum_length = module::get_var("user", "mininum_password_length", 5); +    $minimum_length = module::get_var("user", "minimum_password_length", 5);      $input_password = $group->password("password")->label(t("Password"))->id("g-password")        ->rules($minimum_length ? "required|length[$minimum_length, 40]" : "length[40]");      $group->password("password2")->label(t("Confirm Password"))->id("g-password2") diff --git a/modules/user/helpers/user_installer.php b/modules/user/helpers/user_installer.php index b889af49..9b582773 100644 --- a/modules/user/helpers/user_installer.php +++ b/modules/user/helpers/user_installer.php @@ -24,6 +24,7 @@ class user_installer {    static function install() {      IdentityProvider::change_provider("user"); +    // Set the latest version in initialize() below    }    static function upgrade($version) { @@ -44,6 +45,13 @@ class user_installer {          ->execute();        module::set_version("user", $version = 3);      } + +    if ($version == 3) { +      $password_length = module::get_var("user", "mininum_password_length", 5); +      module::set_var("user", "minimum_password_length", $password_length); +      module::clear_var("user", "mininum_password_length"); +      module::set_version("user", $version = 4); +    }    }    static function uninstall() { @@ -129,7 +137,7 @@ class user_installer {      access::allow($registered, "view", $root);      access::allow($registered, "view_full", $root); -    module::set_var("user", "mininum_password_length", 5); -    module::set_version("user", 3); +    module::set_var("user", "minimum_password_length", 5); +    module::set_version("user", 4);    }  }
\ No newline at end of file diff --git a/modules/user/models/user.php b/modules/user/models/user.php index 145738ca..a8a3a0e7 100644 --- a/modules/user/models/user.php +++ b/modules/user/models/user.php @@ -147,7 +147,7 @@ class User_Model_Core extends ORM implements User_Definition {      }      if (!$this->loaded() || isset($this->password_length)) { -      $minimum_length = module::get_var("user", "mininum_password_length", 5); +      $minimum_length = module::get_var("user", "minimum_password_length", 5);        if ($this->password_length < $minimum_length) {          $v->add_error("password", "min_length");        } diff --git a/modules/user/module.info b/modules/user/module.info index 185a3e3a..503bcd0d 100644 --- a/modules/user/module.info +++ b/modules/user/module.info @@ -1,4 +1,8 @@  name = "Users and Groups"  description = "Gallery 3 user and group management" -version = 3 +version = 4 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:user" +discuss_url = "http://gallery.menalto.com/forum_module_user" diff --git a/modules/user/views/admin_users.html.php b/modules/user/views/admin_users.html.php index a7bd6b27..033c9dae 100644 --- a/modules/user/views/admin_users.html.php +++ b/modules/user/views/admin_users.html.php @@ -110,7 +110,7 @@          </table>          <div class="g-paginator"> -          <?= $pager ?> +          <?= $theme->paginator() ?>          </div>        </div> diff --git a/modules/watermark/module.info b/modules/watermark/module.info index 41a871bd..58efa43f 100644 --- a/modules/watermark/module.info +++ b/modules/watermark/module.info @@ -1,3 +1,7 @@  name = "Watermarks"  description = "Allows users to watermark their photos"  version = 2 +author_name = "Gallery Team" +author_url = "http://codex.gallery2.org/Gallery:Team" +info_url = "http://codex.gallery2.org/Gallery3:Modules:watermark" +discuss_url = "http://gallery.menalto.com/forum_module_watermark" | 
