summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authormodela bitweaver <spiderr@bitweaver.org>2021-02-02 12:10:53 -0500
committermodela bitweaver <spiderr@bitweaver.org>2021-02-02 12:10:53 -0500
commit5c6319e71df90b5adf98d145c06095d64356c311 (patch)
tree5bf6435af4caed312727916a458df6474b0169c3 /includes
parent1086b09bdce0b69ea6bf1c931cc0b6f3967921da (diff)
downloadfisheye-5c6319e71df90b5adf98d145c06095d64356c311.tar.gz
fisheye-5c6319e71df90b5adf98d145c06095d64356c311.tar.bz2
fisheye-5c6319e71df90b5adf98d145c06095d64356c311.zip
move _inc and classes to includes/classes and use PKG_CLASS/INCLUDE_PATH constants
Diffstat (limited to 'includes')
-rw-r--r--includes/classes/FisheyeBase.php268
-rw-r--r--includes/classes/FisheyeGallery.php1120
-rw-r--r--includes/classes/FisheyeImage.php900
-rw-r--r--includes/classes/FisheyeRemote.php351
-rw-r--r--includes/display_fisheye_gallery_inc.php59
-rw-r--r--includes/display_fisheye_image_inc.php25
-rw-r--r--includes/gallery_lookup_inc.php25
-rw-r--r--includes/image_lookup_inc.php46
-rw-r--r--includes/upload_inc.php360
9 files changed, 3154 insertions, 0 deletions
diff --git a/includes/classes/FisheyeBase.php b/includes/classes/FisheyeBase.php
new file mode 100644
index 0000000..1519151
--- /dev/null
+++ b/includes/classes/FisheyeBase.php
@@ -0,0 +1,268 @@
+<?php
+/**
+ * @package fisheye
+ */
+
+/**
+ * required setup
+ */
+require_once( LIBERTY_PKG_CLASS_PATH.'LibertyMime.php' ); // FisheyeGallery base class
+
+/**
+ * @package fisheye
+ */
+abstract class FisheyeBase extends LibertyMime
+{
+ // Path of gallery images to get breadcrumbs
+ public $mGalleryPath;
+
+ abstract public static function getServiceKey();
+
+ public function __sleep() {
+ return array_merge( parent::__sleep(), array( 'mGalleryPath' ) );
+ }
+
+ function __construct() {
+ $this->mGalleryPath = '';
+ parent::__construct();
+ }
+
+ // regular expression to determine if the title was computer generated
+ function isMachineName( $pString ) {
+ return( preg_match( '/(^[0-9][-0-9 ]*$)|(^[-0-9 ]*(img|dsc|dscn|pict|htg|dscf|p)[-0-9 ][-0-9 ]*.*$)/i', trim( $pString ) ) );
+ }
+
+ // Gets a list of galleries which this item is attached to
+ function getParentGalleries( $pContentId=NULL ) {
+ if( !$this->verifyId( $pContentId ) ) {
+ $pContentId = $this->mContentId;
+ }
+ $ret = NULL;
+
+ if( is_numeric( $pContentId ) ) {
+ $sql = "SELECT fg.`gallery_id` AS `hash_key`, fg.*, lc.`title`
+ FROM `".BIT_DB_PREFIX."fisheye_gallery` fg, `".BIT_DB_PREFIX."liberty_content` lc, `".BIT_DB_PREFIX."fisheye_gallery_image_map` fgim
+ WHERE fgim.`item_content_id` = ? AND fgim.`gallery_content_id`=fg.`content_id` AND fg.`content_id`=lc.`content_id`";
+ $ret = $this->mDb->getAssoc( $sql, array( $pContentId ) );
+ }
+ return $ret;
+ }
+
+ function loadParentGalleries() {
+ if( $this->isValid() ) {
+ $this->mInfo['parent_galleries'] = $this->getParentGalleries();
+ }
+ }
+
+ function updatePosition($pGalleryContentId, $newPosition = NULL) {
+ if( $pGalleryContentId && $newPosition && $this->verifyId($this->mContentId) ) {
+ // SQL optimization to prevent stupid updates of identical data
+ if( $radixPosition = strpos( $newPosition, '.' ) ) {
+ // clean out newPosition to be a valid float, and nuke all extra . or extra crap
+ $significand = substr( $newPosition, 0, $radixPosition );
+ $mantissa = preg_replace( '/[^0-9]/', '', substr( $newPosition, $radixPosition + 1 ) );
+ $newPosition = $significand.'.'.$mantissa;
+ }
+ $cleanPosition = preg_replace( '/\./', '', $newPosition );
+ $sql = "UPDATE `".BIT_DB_PREFIX."fisheye_gallery_image_map` SET `item_position` = ?
+ WHERE `item_content_id` = ? AND `gallery_content_id` = ? AND (`item_position` IS NULL OR `item_position`!=?)";
+ $rs = $this->mDb->query($sql, array($newPosition, $this->mContentId, $pGalleryContentId, $newPosition));
+ }
+ }
+
+ function setGalleryPath( $pPath ) {
+ $this->setField( 'gallery_path', rtrim( $pPath, '/' ) );
+ }
+
+ function getThumbnailContentId() {
+ // PURE VIRTUAL
+ }
+
+ function loadThumbnail( $pSize='small', $pContentId=NULL ) {
+ // Default does nothing
+ }
+
+ // Possible derived read-only object such as Facebook, Instagram, etc.. default is TRUE
+ function isEditable() {
+ return TRUE;
+ }
+
+ // THis is a function that creates a mack daddy function to get a breadcrumb path with a single query.
+ // Do not muck with this query unless you really, truly understand what is going on.
+/*
+not ready for primetime
+ function getPaths() {
+ global $gBitDb;
+
+ $ret = NULL;
+ if( $this->isValid() ) {
+ if( $this->mDb->isAdvancedPostgresEnabled() ) {
+ $bindVars = array();
+ $containVars = array();
+ $selectSql = '';
+ $joinSql = '';
+ $whereSql = '';
+
+ $query = "SELECT fg.gallery_id, branch
+ FROM connectby('`".BIT_DB_PREFIX."fisheye_gallery_image_map`', '`gallery_content_id`', '`item_content_id`', ?, 0, '/') AS t(cb_item_content_id int,cb_gallery_content_id int, level int, branch text)
+ INNER JOIN `".BIT_DB_PREFIX."fisheye_gallery` fg ON (fg.`content_id`=cb_item_content_id)
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON(lc.`content_id`=fg.`content_id`)
+ ORDER BY level DESC, branch, lc.`title`";
+ if( $ret = $gBitDb->GetAssoc( $query, array( $this->mContentId ) ) ) {
+ }
+ }
+ }
+ return $ret;
+ }
+*/
+
+ function getBreadcrumbLinks( $pIncludeSelf = FALSE ) {
+ global $gBitSystem;
+ //$ret['fisheye'] = $gBitSystem->getConfig('site_title');
+ $ret = array();
+ if( !$this->getField( 'gallery_path' ) ) {
+ if( $this->isValid() && $parents = $this->getParentGalleries() ) {
+ $gal = current( $parents );
+ $this->setGalleryPath( '/'.$gal['gallery_id'] );
+ }
+ }
+ if( $this->getField( 'gallery_path' ) ) {
+ $path = explode( '/', ltrim( $this->getField( 'gallery_path' ), '/' ) );
+ $p = 0;
+ $c = 1;
+ $joinSql = '';
+ $selectSql = '';//AS title$g, fg$g.gallery_id AS gallery_id$g";
+ $whereSql = '';
+ $bindVars = array();
+ // We need to get min_content_status_id
+ $pListHash = array();
+ LibertyContent::prepGetList($pListHash);
+ foreach( $path as $galleryId ) {
+ if( $galleryId ) {
+ $p++; $c++;
+ $selectSql .= " lc$p.`title` AS `title$p`, fg$p.`gallery_id` AS `gallery_id$p`,";
+ $joinSql .= " `".BIT_DB_PREFIX."fisheye_gallery_image_map` fgim$p
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc$p ON(fgim$p.`gallery_content_id`=lc$p.`content_id`)
+ INNER JOIN `".BIT_DB_PREFIX."fisheye_gallery` fg$p ON(fg$p.`content_id`=lc$p.`content_id`),";
+ $whereSql .= " fg$p.`gallery_id`=? AND fgim$p.`item_content_id`=lc$c.`content_id` AND lc$p.`content_status_id` > ? AND";
+ array_push( $bindVars, $galleryId );
+ array_push( $bindVars, $pListHash['min_content_status_id']);
+ }
+ }
+// $selectSql .= " lc$c.title AS title$c ";//AS title$g, fg$g.gallery_id AS gallery_id$g";
+ $joinSql .= " `".BIT_DB_PREFIX."fisheye_gallery_image_map` fgim$c
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc$c ON(fgim$c.`item_content_id`=lc$c.`content_id`) ";
+ $whereSql .= " lc$c.`content_id`=? AND fgim$c.`gallery_content_id`=lc$p.`content_id` ";
+ array_push( $bindVars, $this->mContentId );
+ $rs = $this->mDb->query( "SELECT ".rtrim( $selectSql, ',')." FROM ".rtrim( $joinSql, ',')." WHERE $whereSql", $bindVars );
+ if( !empty( $rs->fields ) ) {
+ for( $i = 1; $i <= (count( $rs->fields ) / 2); $i++ ) {
+ $ret[$rs->fields['gallery_id'.$i]] = $rs->fields['title'.$i];
+ }
+ }
+ }
+
+ if( $this->isValid() && $pIncludeSelf && is_a( $this, 'FisheyeGallery' ) ) {
+ $ret[$this->mGalleryId] = $this->getTitle();
+ }
+
+ return $ret;
+ }
+
+
+ function addToGalleries( $pGalleryArray ) {
+ global $gBitSystem;
+ if( $this->isValid() ) {
+ $inGalleries = $this->mDb->getAssoc( "SELECT `gallery_id`,`gallery_content_id` FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` fgim INNER JOIN `".BIT_DB_PREFIX."fisheye_gallery` fg ON (fgim.`gallery_content_id`=fg.`content_id`) WHERE `item_content_id` = ?", array( $this->mContentId ) );
+ $galleries = array();
+ if( count( $pGalleryArray ) ) {
+ foreach( $pGalleryArray as $galleryId ) {
+ // image has been requested to be put in a new gallery
+ if( !is_numeric( $galleryId ) ) {
+ switch( $galleryId ) {
+ case 'newest':
+ $galleryId = $this->mDb->getAssoc( "SELECT `gallery_id` FROM `".BIT_DB_PREFIX."fisheye_gallery` fg INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (fg.`content_id`=lg.`content_id`) WHERE `user_id` = ? ORDER BY gallery_id DESC", array( $this->getField( 'user_id' ) ) );
+ break;
+
+ }
+ }
+ if( empty( $inGalleries[$galleryId] ) ) {
+ if( empty( $galleries[$galleryId] ) ) {
+ if( $galleries[$galleryId] = FisheyeGallery::lookup( array( 'gallery_id' => $galleryId ) ) ) {
+ $galleries[$galleryId]->load();
+ }
+ }
+ if( $galleries[$galleryId] && $galleries[$galleryId]->isValid() ) {
+ if( $galleries[$galleryId]->hasUserPermission( 'p_fisheye_upload', TRUE, FALSE ) || $galleries[$galleryId]->isPublic() ) {
+ if( $gBitSystem->isFeatureActive( 'fisheye_gallery_default_sort_mode' ) ) {
+ $pos = NULL;
+ } else {
+ $query = "SELECT MAX(`item_position`)
+ FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` fgim
+ INNER JOIN `".BIT_DB_PREFIX."fisheye_gallery` fg ON(fgim.`gallery_content_id`=fg.`content_id`)
+ WHERE fg.`gallery_id`=?";
+ $pos = $this->mDb->getOne( $query, array( $galleryId ) ) + 10;
+ }
+
+ $galleries[$galleryId]->addItem( $this->mContentId, $pos );
+ } else {
+ $this->mErrors[] = "You do not have permission to attach ".$this->getTitle()." to ".$galleries[$galleryId]->getTitle();
+ }
+ }
+ } else {
+ // image already in an existing gallery.
+ unset( $inGalleries[$galleryId] );
+ }
+ }
+ }
+ if( count( $inGalleries ) ) {
+ // if we have any left over in the inGalleries array, we should delete them. these were the "unchecked" boxes
+ foreach( $inGalleries as $galleryId ) {
+ $sql = "DELETE FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` WHERE `gallery_content_id` = ? AND `item_content_id` = ?";
+ $rs = $this->mDb->query($sql, array( $galleryId, $this->mContentId ) );
+ }
+ }
+ }
+ }
+
+ function isPublic() {
+ if( $this->isValid() ) {
+ return ( $this->getPreference( 'is_public' ) == 'y' );
+ }
+ }
+
+ function isInGallery( $pGalleryContentId, $pItemContentId = NULL) {
+ if( !$this->verifyId( $pItemContentId ) ) {
+ $pItemContentId = $this->mContentId;
+ }
+ $ret = FALSE;
+ if ( is_numeric( $this->mGalleryId ) && is_numeric( $pGalleryContentId ) ) {
+
+ if( $this->mDb->isAdvancedPostgresEnabled() ) {
+ global $gBitDb, $gBitSmarty;
+ // This code pulls all branches for the current node and determines if there is a path from this content to the root
+ // without hitting a security_id. If there is clear path it returns TRUE. If there is a security_id, then
+ // it determines if the current user has permission
+ $query = "SELECT branch,level,cb_item_content_id,cb_gallery_content_id
+ FROM connectby('`".BIT_DB_PREFIX."fisheye_gallery_image_map`', '`gallery_content_id`', '`item_content_id`', ?, 0, '/') AS t(`cb_gallery_content_id` int,`cb_item_content_id` int, `level` int, `branch` text)
+ WHERE `cb_gallery_content_id`=?
+ ORDER BY branch
+ ";
+ if ( $this->mDb->getOne($query, array( $pItemContentId, $pGalleryContentId ) ) ) {
+ $ret = TRUE;
+ }
+ } else {
+ $sql = "SELECT count(`item_content_id`) as `item_count`
+ FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map`
+ WHERE `gallery_content_id` = ? AND `item_content_id` = ?";
+ $rs = $this->mDb->query($sql, array($pGalleryContentId, $pItemContentId));
+ if ($rs->fields['item_count'] > 0) {
+ $ret = TRUE;
+ }
+ }
+ }
+ return $ret;
+ }
+
+}
+?>
diff --git a/includes/classes/FisheyeGallery.php b/includes/classes/FisheyeGallery.php
new file mode 100644
index 0000000..b0f710d
--- /dev/null
+++ b/includes/classes/FisheyeGallery.php
@@ -0,0 +1,1120 @@
+<?php
+/**
+ * @package fisheye
+ */
+
+/**
+ * required setup
+ */
+require_once( FISHEYE_PKG_CLASS_PATH.'FisheyeImage.php' ); // A gallery is composed of FisheyeImages
+
+define('FISHEYEGALLERY_CONTENT_TYPE_GUID', 'fisheyegallery' );
+
+define( 'FISHEYE_PAGINATION_FIXED_GRID', 'fixed_grid' );
+define( 'FISHEYE_PAGINATION_AUTO_FLOW', 'auto_flow' );
+define( 'FISHEYE_PAGINATION_POSITION_NUMBER', 'position_number' );
+define( 'FISHEYE_PAGINATION_SIMPLE_LIST', 'simple_list' );
+define( 'FISHEYE_PAGINATION_MATTEO', 'matteo' );
+define( 'FISHEYE_PAGINATION_GALLERIFFIC', 'galleriffic' );
+
+/**
+ * FisheyeBase extends LibertyMime, which this class doesn't need, but we need a common base class
+ *
+ * @package fisheye
+ */
+class FisheyeGallery extends FisheyeBase {
+ public $mGalleryId; // fisheye_gallery.gallery_id
+ public $mItems; // Array of FisheyeImage class instances which belong to this gallery
+
+ function __construct($pGalleryId = NULL, $pContentId = NULL) {
+ parent::__construct();
+ if( $this->verifyId( $pGalleryId ) ) {
+ $this->mGalleryId = (int)$pGalleryId; // Set member variables according to the parameters we were passed
+ }
+ if( $this->verifyId( $pContentId ) ) {
+ $this->mContentId = (int)$pContentId; // liberty_content.content_id which this gallery references
+ }
+ $this->mItems = array(); // Assume no images (if $pAutoLoad is TRUE we will populate this array later)
+ $this->mAdminContentPerm = 'p_fisheye_admin';
+
+ // This registers the content type for FishEye galleries
+ // FYI: Any class which uses a table which inherits from liberty_content should create their own content type(s)
+ $this->registerContentType(
+ FISHEYEGALLERY_CONTENT_TYPE_GUID, array( 'content_type_guid' => FISHEYEGALLERY_CONTENT_TYPE_GUID,
+ 'content_name' => 'Image Gallery',
+ 'content_name_plural' => 'Image Galleries',
+ 'handler_class' => 'FisheyeGallery',
+ 'handler_package' => 'fisheye',
+ 'handler_file' => 'FisheyeGallery.php',
+ 'maintainer_url' => 'http://www.bitweaver.org'
+ ));
+
+ // Permission setup
+ $this->mViewContentPerm = 'p_fisheye_view';
+ $this->mCreateContentPerm = 'p_fisheye_create';
+ $this->mUpdateContentPerm = 'p_fisheye_update';
+ $this->mAdminContentPerm = 'p_fisheye_admin';
+ }
+
+ public function __wakeup() {
+ return parent::__wakeup();
+ }
+
+ public function __sleep() {
+ return array_merge( parent::__sleep(), array( 'mGalleryId' ) );
+ }
+
+ function isValid() {
+ return( @$this->verifyId( $this->mGalleryId ) || @$this->verifyId( $this->mContentId ) );
+ }
+
+ public static function lookup( $pLookupHash, $pLoadFromCache=TRUE ) {
+ global $gBitDb;
+ $ret = NULL;
+
+ $lookupContentId = NULL;
+ if (!empty($pLookupHash['gallery_id']) && is_numeric($pLookupHash['gallery_id'])) {
+ if( $lookup = $gBitDb->getRow( "SELECT lc.`content_id`, lc.`content_type_guid` FROM `".BIT_DB_PREFIX."fisheye_gallery` fg INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON(lc.`content_id`=fg.`content_id`) WHERE `gallery_id`=?", array( $pLookupHash['gallery_id'] ) ) ) {
+ $lookupContentId = $lookup['content_id'];
+ $lookupContentGuid = $lookup['content_type_guid'];
+ }
+ } elseif (!empty($pLookupHash['content_id']) && is_numeric($pLookupHash['content_id'])) {
+ $lookupContentId = $pLookupHash['content_id'];
+ $lookupContentGuid = NULL;
+ }
+
+ if( static::verifyId( $lookupContentId ) ) {
+ $ret = parent::getLibertyObject( $lookupContentId, $lookupContentGuid, $pLoadFromCache );
+ }
+
+ return $ret;
+ }
+
+ function load( $pContentId = NULL, $pPluginParams = NULL ) {
+ global $gBitSystem;
+ $bindVars = array();
+ $selectSql = $joinSql = $whereSql = '';
+
+ if( @$this->verifyId( $this->mGalleryId ) ) {
+ $whereSql = " WHERE fg.`gallery_id` = ?";
+ $bindVars = array( $this->mGalleryId );
+ } elseif ( @$this->verifyId( $this->mContentId ) ) {
+ $whereSql = " WHERE fg.`content_id` = ?";
+ $bindVars = array($this->mContentId);
+ } else {
+ $whereSql = NULL;
+ }
+
+ if ($whereSql) { // If we have some way to know what fisheye_gallery row to load...
+ $this->getServicesSql( 'content_load_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
+
+ $query = "SELECT fg.*, lc.* $selectSql
+ , uue.`login` AS modifier_user, uue.`real_name` AS `modifier_real_name`
+ , uuc.`login` AS creator_user, uuc.`real_name` AS `creator_real_name`
+ FROM `".BIT_DB_PREFIX."fisheye_gallery` fg
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (fg.`content_id` = lc.`content_id`) $joinSql
+ LEFT JOIN `".BIT_DB_PREFIX."users_users` uue ON (uue.`user_id` = lc.`modifier_user_id`)
+ LEFT JOIN `".BIT_DB_PREFIX."users_users` uuc ON (uuc.`user_id` = lc.`user_id`)
+ $whereSql";
+
+ if( $rs = $this->mDb->query($query, $bindVars) ) {
+ $this->mInfo = $rs->fields;
+ $this->mContentId = $rs->fields['content_id'];
+ LibertyContent::load();
+ if( @$this->verifyId($this->mInfo['gallery_id'] ) ) {
+
+ $this->mGalleryId = $this->mInfo['gallery_id'];
+ $this->mContentId = $this->mInfo['content_id'];
+
+ $this->mInfo['creator'] = (isset( $rs->fields['creator_real_name'] ) ? $rs->fields['creator_real_name'] : $rs->fields['creator_user'] );
+ $this->mInfo['editor'] = (isset( $rs->fields['modifier_real_name'] ) ? $rs->fields['modifier_real_name'] : $rs->fields['modifier_user'] );
+
+ // Set some basic defaults for how to display a gallery if they're not already set
+ if (empty($this->mInfo['thumbnail_size'])) {
+ $this->mInfo['thumbnail_size'] = $this->getPreference( 'fisheye_gallery_default_thumbnail_size', NULL );
+ }
+ if (empty($this->mInfo['rows_per_page'])) {
+ $this->mInfo['rows_per_page'] = $this->getPreference('fisheye_gallery_default_rows_per_page', FISHEYE_DEFAULT_ROWS_PER_PAGE);
+ }
+ if (empty($this->mInfo['cols_per_page'])) {
+ $this->mInfo['cols_per_page'] = $this->getPreference('fisheye_gallery_default_cols_per_page', FISHEYE_DEFAULT_COLS_PER_PAGE);
+ }
+ if (empty($this->mInfo['access_answer'])) {
+ $this->mInfo['access_answer'] = '';
+ }
+ if ( $this->getPreference( 'gallery_pagination' ) == FISHEYE_PAGINATION_GALLERIFFIC and empty($this->mInfo['galleriffic_style'])) {
+ $this->mInfo['galleriffic_style'] = $this->getPreference('galleriffic_style', 1);
+ }
+
+ $this->mInfo['num_images'] = $this->getImageCount();
+ if( $this->getPreference( 'gallery_pagination' ) == FISHEYE_PAGINATION_POSITION_NUMBER ) {
+ $this->mInfo['num_pages'] = $this->mDb->getOne( "SELECT COUNT( distinct( floor(`item_position`) ) ) FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` WHERE gallery_content_id=?", array( $this->mContentId ) );
+ } else {
+ $this->mInfo['images_per_page'] = ($this->mInfo['cols_per_page'] * $this->mInfo['rows_per_page']);
+ $this->mInfo['num_pages'] = (int)($this->mInfo['num_images'] / $this->mInfo['images_per_page'] + ($this->mInfo['num_images'] % $this->mInfo['images_per_page'] == 0 ? 0 : 1));
+ }
+
+ } else {
+ unset( $this->mContentId );
+ unset( $this->mGalleryId );
+ }
+
+ }
+ }
+
+ return count($this->mInfo);
+ }
+
+ function loadCurrentImage( $pCurrentImageId ) {
+ if( $this->isValid() && @$this->verifyId( $pCurrentImageId ) ) {
+ // this code sucks but works - XOXO spiderr
+ $query = "SELECT fgim.*, fi.`image_id`, lf.`file_name`, lf.`user_id`, lf.`mime_type`, la.`attachment_id`
+ FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` fgim
+ INNER JOIN `".BIT_DB_PREFIX."fisheye_image` fi ON ( fi.`content_id`=fgim.`item_content_id` )
+ INNER JOIN `".BIT_DB_PREFIX."liberty_attachments` la ON ( fi.`content_id`=la.`content_id` )
+ INNER JOIN `".BIT_DB_PREFIX."liberty_files` lf ON ( lf.`file_id`=la.`foreign_id` )
+ WHERE fgim.`gallery_content_id` = ?
+ ORDER BY fgim.`item_position`, fi.`content_id` ";
+ if( $rs = $this->mDb->query($query, array( $this->mContentId ) ) ) {
+ $tempImage = new FisheyeImage();
+ $rows = $rs->getRows();
+ for( $i = 0; $i < count( $rows ); $i++ ) {
+ if( $rows[$i]['image_id'] == $pCurrentImageId ) {
+ if( $i > 0 ) {
+ $this->mInfo['previous_image_id'] = $rows[$i-1]['image_id'];
+ $this->mInfo['previous_image_avatar'] = liberty_fetch_thumbnail_url( array(
+ 'file_name' => $rows[$i-1]['file_name'],
+ 'source_file' => $tempImage->getSourceFile( $rows[$i-1] ),
+ 'mime_image' => TRUE,
+ 'size' => 'avatar',
+ ));
+ }
+ if( $i + 1 < count( $rows ) ) {
+ $this->mInfo['next_image_id'] = $rows[$i+1]['image_id'];
+ $this->mInfo['next_image_avatar'] = liberty_fetch_thumbnail_url( array(
+ 'file_name' => $rows[$i+1]['file_name'],
+ 'source_file' => $tempImage->getSourceFile( $rows[$i+1] ),
+ 'mime_image' => TRUE,
+ 'size' => 'avatar',
+ ));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public function loadImages( $pPage=-1, $pImagesPerPage=-1, $pRefresh=FALSE ) {
+ global $gLibertySystem, $gBitSystem, $gBitUser;
+ if( !$this->isValid() ) {
+ return NULL;
+ }
+ if( empty( $this->mItems ) || $pRefresh ) {
+ $bindVars = array($this->mContentId);
+ $whereSql = $selectSql = $joinSql = $orderSql = '';
+ $rowCount = $offset = NULL;
+ $this->getServicesSql( 'content_list_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
+
+ if( $gBitSystem->isFeatureActive( 'fisheye_gallery_default_sort_mode' ) ) {
+ $orderSql = ", ".$this->mDb->convertSortmode( $gBitSystem->getConfig( 'fisheye_gallery_default_sort_mode' ) );
+ } else {
+ $orderSql = ", fgim.`item_content_id`";
+ }
+
+ // load for just a single page
+ if( $pPage != -1 ) {
+ if( $this->getLayout() == FISHEYE_PAGINATION_POSITION_NUMBER ) {
+ $query = "SELECT DISTINCT(FLOOR(`item_position`))
+ FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map`
+ WHERE gallery_content_id=?
+ ORDER BY floor(item_position)";
+ $mantissa = $this->mDb->getOne( $query, array( $this->mContentId ), 1, ($pPage - 1) );
+ // gallery image order with no positions set will have NULL mantissa, and all images will be shown
+ if( !is_null( $mantissa ) ) {
+ $whereSql .= " AND floor(item_position)=? ";
+ array_push( $bindVars, $mantissa );
+ }
+ } elseif( $this->getLayout() == FISHEYE_PAGINATION_FIXED_GRID ) {
+ $rowCount = $this->getField( 'rows_per_page' ) * $this->getField( 'cols_per_page' );
+ $offset = $rowCount * ($pPage - 1);
+ } else {
+ $rowCount = $pImagesPerPage;
+ $offset = $rowCount * ($pPage - 1);
+ }
+ }
+
+ $this->mItems = array();
+
+ $query = "SELECT fgim.*, lc.`user_id`, lct.*, ufm.`favorite_content_id` AS is_favorite $selectSql
+ FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` fgim
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON ( lc.`content_id`=fgim.`item_content_id` )
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content_types` lct ON ( lct.`content_type_guid`=lc.`content_type_guid` )
+ $joinSql
+ LEFT OUTER JOIN `".BIT_DB_PREFIX."users_favorites_map` ufm ON ( ufm.`favorite_content_id`=lc.`content_id` AND lc.`user_id`=ufm.`user_id` )
+ WHERE fgim.`gallery_content_id` = ? $whereSql
+ ORDER BY fgim.`item_position` $orderSql";
+ $rs = $this->mDb->query($query, $bindVars, $rowCount, $offset);
+ $rows = $rs->getRows();
+ foreach ($rows as $row) {
+ $pass = TRUE;
+ if( $gBitSystem->isPackageActive( 'gatekeeper' ) ) {
+ $pass = $gBitUser->hasPermission( 'p_fisheye_admin' ) || !@$this->verifyId( $row['security_id'] ) || ( $row['user_id'] == $gBitUser->mUserId ) || @$this->verifyId( $_SESSION['gatekeeper_security'][$row['security_id']] );
+ }
+ if( $pass ) {
+ if( $item = parent::getLibertyObject( $row['item_content_id'], $row['content_type_guid'], $this->isCacheableObject() ) ) {
+ $item->loadThumbnail( $this->mInfo['thumbnail_size'] );
+ $item->setGalleryPath( $this->mGalleryPath.'/'.$this->mGalleryId );
+ $item->mInfo['item_position'] = $row['item_position'];
+ $this->mItems[$row['item_content_id']] = $item;
+ }
+ }
+ }
+ }
+ return count( $this->mItems );
+ }
+
+ function getImageList() {
+ global $gLibertySystem, $gBitSystem, $gBitUser;
+ $ret = NULL;
+ if( $this->isValid() ) {
+ $bindVars = array($this->mContentId);
+ $whereSql = $selectSql = $joinSql = $orderSql = '';
+ $rows = $offset = NULL;
+ $this->getServicesSql( 'content_list_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
+
+ if( $gBitSystem->isFeatureActive( 'fisheye_gallery_default_sort_mode' ) ) {
+ $orderSql = ", ".$this->mDb->convertSortmode( $gBitSystem->getConfig( 'fisheye_gallery_default_sort_mode' ) );
+ } else {
+ $orderSql = ", fgim.`item_content_id`";
+ }
+
+ $this->mItems = array();
+
+ $query = "SELECT lc.`content_id` AS `has_key`, fgim.*, lc.*, lct.*, fi.`image_id`, ufm.`favorite_content_id` AS is_favorite $selectSql
+ FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` fgim
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON ( lc.`content_id`=fgim.`item_content_id` )
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content_types` lct ON ( lct.`content_type_guid`=lc.`content_type_guid` )
+ LEFT OUTER JOIN `".BIT_DB_PREFIX."fisheye_image` fi ON ( fgim.`item_content_id`=fi.`content_id` )
+ $joinSql
+ LEFT OUTER JOIN `".BIT_DB_PREFIX."users_favorites_map` ufm ON ( ufm.`favorite_content_id`=lc.`content_id` AND lc.`user_id`=ufm.`user_id` )
+ WHERE fgim.`gallery_content_id` = ? $whereSql
+ ORDER BY fgim.`item_position` $orderSql";
+ $ret = $this->mDb->getAssoc($query, $bindVars, $rows, $offset);
+ }
+ return $ret;
+ }
+
+ function exportHash( $pPaginate = FALSE ) {
+ if( $ret = parent::exportHash() ) {
+ $ret['type'] = $this->getContentType();
+ if( $this->loadImages() ) {
+ foreach( array_keys( $this->mItems ) as $key ) {
+ if( $pPaginate ) {
+ if( $exp = $this->mItems[$key]->exportHash( $pPaginate ) ) {
+ $ret['content']['page'][$this->getItemPage($key)][] = $exp;
+ }
+ } else {
+ $ret['content'][] = $this->mItems[$key]->exportHash( $pPaginate );
+ }
+ }
+ }
+ }
+ return $ret;
+ }
+
+ function getItemPage( $pItemContentId ) {
+ $ret = NULL;
+ if( empty( $this->mPaginationLookup ) ) {
+ $this->mPaginationLookup = $this->mDb->getAssoc( "SELECT `item_content_id`, floor(`item_position`) FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` WHERE `gallery_content_id`=?", array( $this->mContentId ) );
+ }
+ if( !empty( $this->mPaginationLookup[$pItemContentId] ) ) {
+ $ret = $this->mPaginationLookup[$pItemContentId];
+ }
+ return $ret;
+ }
+
+ function getPreviewHash() {
+ $ret = array();
+ if( !empty( $this->mInfo['preview_content'] ) ) {
+ $ret = $this->mInfo['preview_content']->mInfo;
+ }
+ // override $this->mInfo['preview_content']->mInfo['display_url'] so we don't drive directly to the image
+ $ret['display_url'] = $this->getDisplayUrl();
+ return $ret;
+ }
+
+ function getImageCount() {
+ $ret = 0;
+
+ if ($this->mGalleryId) {
+ $bindVars = array($this->mContentId);
+ $whereSql = $selectSql = $joinSql = $orderSql = '';
+ $rows = $offset = NULL;
+ $paramHash['no_fatal'] = TRUE;
+ $this->getServicesSql( 'content_list_sql_function', $selectSql, $joinSql, $whereSql, $bindVars, NULL, $paramHash );
+ $query = 'SELECT COUNT(*) AS "count"
+ FROM `'.BIT_DB_PREFIX."fisheye_gallery_image_map` fgim
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON ( lc.`content_id`=fgim.`item_content_id` )
+ $joinSql WHERE `gallery_content_id` = ? $whereSql";
+ $rs = $this->mDb->query($query, $bindVars);
+ $ret = $rs->fields['count'];
+ }
+ return $ret;
+ }
+
+ function verifyGalleryData(&$pStorageHash) {
+ global $gBitSystem;
+
+ if (empty($pStorageHash['rows_per_page'])) {
+ $pStorageHash['rows_per_page'] = $gBitSystem->getConfig('fisheye_gallery_default_rows_per_page', (!empty($this->mInfo['rows_per_page']) ? $this->mInfo['rows_per_page'] : FISHEYE_DEFAULT_ROWS_PER_PAGE));
+ }
+
+ if (empty($pStorageHash['cols_per_page'])) {
+ $pStorageHash['cols_per_page'] = $gBitSystem->getConfig('fisheye_gallery_default_cols_per_page', (!empty($this->mInfo['cols_per_page']) ? $this->mInfo['cols_per_page'] : FISHEYE_DEFAULT_COLS_PER_PAGE));
+ }
+
+ if (empty($pStorageHash['thumbnail_size'])) {
+ $pStorageHash['thumbnail_size'] = $gBitSystem->getConfig('fisheye_gallery_default_thumbnail_size', (!empty($this->mInfo['thumbnail_size']) ? $this->mInfo['thumbnail_size'] : NULL ));
+ }
+
+ if (empty($pStorageHash['title'])) {
+ $this->mErrors[] = "You must specify a title for this image gallery";
+ }
+
+ $pStorageHash['content_type_guid'] = $this->getContentType();
+
+ return (count($this->mErrors) == 0);
+ }
+
+
+ function generateThumbnails() {
+ if( $this->isValid() ) {
+ if( $this->loadImages() ) {
+ foreach( array_keys( $this->mItems ) as $key ) {
+ $this->mItems[$key]->generateThumbnails();
+ }
+ }
+ }
+ }
+
+
+ function getThumbnailContentId() {
+ if( !$this->getField( 'thumbnail_content_id' ) ) {
+ $this->getThumbnailImage();
+ }
+ return( $this->getField( 'thumbnail_content_id' ) );
+ }
+
+ function getThumbnailUri( $pSize='small', $pInfoHash = NULL ) {
+ if( empty( $this->mInfo['preview_content'] ) ) {
+ $this->loadThumbnail();
+ }
+
+ if( is_object( $this->mInfo['preview_content'] ) ) {
+ return $this->mInfo['preview_content']->getThumbnailUri( $pSize );
+ }
+ }
+
+
+ function getThumbnailUrl( $pSize = 'small', $pInfoHash = NULL, $pSecondaryId = NULL, $pDefault=TRUE ) {
+ if( empty( $this->mInfo['preview_content'] ) ) {
+ $this->loadThumbnail();
+ }
+
+ if( is_object( $this->mInfo['preview_content'] ) ) {
+ return $this->mInfo['preview_content']->getThumbnailUrl( $pSize );
+ }
+ }
+
+
+ function getThumbnailImage( $pContentId=NULL, $pThumbnailContentId=NULL, $pThumbnailContentType=NULL ) {
+ global $gLibertySystem, $gBitUser;
+ $ret = NULL;
+
+ if( !@$this->verifyId( $pContentId ) && !empty( $this->mContentId ) ) {
+ $pContentId = $this->mContentId;
+ }
+
+ if( !@$this->verifyId( $pThumbnailContentId ) ) {
+ if( @$this->verifyId( $this->mInfo['preview_content_id'] ) ) {
+ $pThumbnailContentId = $this->mInfo['preview_content_id'];
+ } else {
+ if( $this->mDb->isAdvancedPostgresEnabled() ) {
+ $whereSql = '';
+ $bindVars = array( $pContentId );
+ if( !$gBitUser->isAdmin() ) {
+ $whereSql = " AND (cgm.`security_id` IS NULL OR lc.`user_id`=?) ";
+ $bindVars[] = $gBitUser->mUserId;
+ }
+ $query = "SELECT COALESCE( fg.`preview_content_id`, lc.`content_id` ) AS `content_id`, lc.`content_type_guid`
+ FROM connectby('`".BIT_DB_PREFIX."fisheye_gallery_image_map`', '`item_content_id`', '`gallery_content_id`', ?, 0, '/') AS t(`cb_item_content_id` int, `cb_parent_content_id` int, `level` int, `branch` text)
+ INNER JOIN liberty_content lc ON(content_id=cb_item_content_id)
+ LEFT OUTER JOIN `".BIT_DB_PREFIX."gatekeeper_security_map` cgm ON (cgm.`content_id`=lc.`content_id`), `".BIT_DB_PREFIX."fisheye_gallery` fg
+ WHERE `cb_parent_content_id`=fg.`content_id` $whereSql "; // ORDER BY RANDOM() is DOG slow (seq scans)
+ if( $row = $this->mDb->getRow( $query, $bindVars ) ) {
+ $pThumbnailContentType = $row['content_type_guid'];
+ $pThumbnailContentId = $row['content_id'];
+ }
+ } else {
+ $query = "SELECT fgim.`item_content_id`, lc.`content_type_guid`
+ FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` fgim INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON ( fgim.`item_content_id`=lc.`content_id` )
+ WHERE fgim.`gallery_content_id` = ?
+ ORDER BY ".$this->mDb->convertSortmode('random');
+ $rs = $this->mDb->query($query, array( $pContentId ), 1);
+ if( !empty( $rs->fields ) ) {
+ $pThumbnailContentId = $rs->fields['item_content_id'];
+ $pThumbnailContentType = $rs->fields['content_type_guid'];
+ }
+ }
+ }
+ }
+
+ if( @$this->verifyId( $pThumbnailContentId ) ) {
+ $ret = parent::getLibertyObject( $pThumbnailContentId, $pThumbnailContentType, $this->isCacheableObject() );
+ if( is_a( $ret, 'FisheyeGallery' ) ) {
+ //recurse down in to find the first image
+ if( $ret = $ret->getThumbnailImage() ) {
+ $this->mInfo['thumbnail_content_id'] = $ret->getField( 'content_id' );
+ }
+ } else {
+ $this->mInfo['thumbnail_content_id'] = $pThumbnailContentId;
+ }
+ }
+ return $ret;
+ }
+
+
+ function loadThumbnail( $pSize='small', $pContentId=NULL ) {
+ if( $this->mPreviewImage = $this->getThumbnailImage( $pContentId ) ) {
+ $this->mInfo['preview_content'] = &$this->mPreviewImage;
+ $this->mInfo['image_file'] = &$this->mPreviewImage->mInfo['image_file'];
+ }
+ }
+
+
+ function storeGalleryThumbnail($pContentId = NULL) {
+ $ret = FALSE;
+ if ($pContentId && !$this->isInGallery( $this->mContentId, $pContentId ) ) {
+ return FALSE;
+ }
+ if ($this->mGalleryId) {
+ if (!$pContentId)
+ $pContentId = NULL;
+ $query = "UPDATE `".BIT_DB_PREFIX."fisheye_gallery` SET `preview_content_id` = ? WHERE `gallery_id`= ?";
+ $rs = $this->mDb->query($query, array($pContentId, $this->mGalleryId));
+ $this->mInfo['preview_content_id'] = $pContentId;
+ $ret = TRUE;
+ }
+ return $ret;
+ }
+
+ function store(&$pStorageHash) {
+ if ($this->verifyGalleryData($pStorageHash)) {
+ $this->StartTrans();
+ if( LibertyContent::store($pStorageHash)) {
+ $this->mContentId = $pStorageHash['content_id'];
+ $this->mInfo['content_id'] = $this->mContentId;
+ if ($this->galleryExistsInDatabase()) {
+ $query = "UPDATE `".BIT_DB_PREFIX."fisheye_gallery`
+ SET `rows_per_page` = ?, `cols_per_page` = ?, `thumbnail_size` = ?
+ WHERE `gallery_id` = ?";
+ $bindVars = array($pStorageHash['rows_per_page'], $pStorageHash['cols_per_page'], $pStorageHash['thumbnail_size'], $this->mGalleryId);
+ } else {
+ $this->mGalleryId = $this->mDb->GenID('fisheye_gallery_id_seq');
+ $this->mInfo['gallery_id'] = $this->mGalleryId;
+ $query = "INSERT INTO `".BIT_DB_PREFIX."fisheye_gallery` (`gallery_id`, `content_id`, `rows_per_page`, `cols_per_page`, `thumbnail_size`) VALUES (?,?,?,?,?)";
+ $bindVars = array($this->mGalleryId, $this->mContentId, $pStorageHash['rows_per_page'], $pStorageHash['cols_per_page'], $pStorageHash['thumbnail_size']);
+ }
+ $rs = $this->mDb->query($query, $bindVars);
+ $this->CompleteTrans();
+ } else {
+ $this->mDb->RollbackTrans();
+ $this->mErrors[] = "There were errors while attempting to save this gallery";
+ }
+ } else {
+ $this->mErrors[] = "There were errors while attempting to save this gallery";
+ }
+
+ return (count($this->mErrors) == 0);
+ }
+
+ function removeItem( $pContentId ) {
+ $ret = FALSE;
+ if( $this->isValid() && @$this->verifyId( $pContentId ) ) {
+ $query = "DELETE FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map`
+ WHERE `item_content_id`=? AND `gallery_content_id`=?";
+ $rs = $this->mDb->query($query, array($pContentId, $this->mContentId ) );
+ $ret = TRUE;
+ }
+ return $ret;
+ }
+
+ /**
+ * Adds a new item (image or gallery) to this gallery. We check to make sure we are not a member
+ * of this gallery and this gallery is not a member of the new item to avoid infinite recursion scenarios
+ * @return boolean wheter or not the item was added
+ */
+ function addItem( $pContentId, $pPosition=NULL ) {
+ global $gBitSystem;
+ $ret = FALSE;
+ if( @$this->verifyId( $this->mContentId ) && @$this->verifyId( $pContentId ) && ( $this->mContentId != $pContentId ) && !$this->isInGallery( $this->mContentId, $pContentId ) && !$this->isInGallery( $pContentId, $this->mContentId ) ) {
+ $query = "INSERT INTO `".BIT_DB_PREFIX."fisheye_gallery_image_map` (`item_content_id`, `gallery_content_id`, `item_position`) VALUES (?,?,?)";
+ $rs = $this->mDb->query($query, array($pContentId, $this->mContentId, $pPosition ) );
+ $query = "UPDATE `".BIT_DB_PREFIX."liberty_content` SET `last_modified`=? WHERE `content_id`=?";
+ $rs = $this->mDb->query( $query, array( $gBitSystem->getUTCTime(), $this->mContentId ) );
+ $ret = TRUE;
+ }
+ return $ret;
+ }
+
+ function expunge( $pRecursiveDelete = FALSE ) {
+ if( $this->isValid() ) {
+ $this->StartTrans();
+
+ if( $this->loadImages() ) {
+ foreach( array_keys( $this->mItems ) as $key ) {
+ if( $pRecursiveDelete ) {
+ $this->mItems[$key]->expunge( $pRecursiveDelete );
+ } elseif( is_a( $this->mItems[$key], 'FisheyeImage' ) ) {
+ // make sure we have a valid content_id before we exec
+ if( is_numeric( $this->mItems[$key]->mContentId ) ) {
+ $query = "SELECT COUNT(`item_content_id`) AS `other_gallery`
+ FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map`
+ WHERE `item_content_id`=? AND `gallery_content_id`!=?";
+ if( !($inOtherGallery = $this->mDb->getOne($query, array($this->mItems[$key]->mContentId, $this->mContentId ) )) ) {
+ $this->mItems[$key]->expunge();
+ }
+ }
+ }
+ }
+ }
+
+ $query = "DELETE FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` WHERE `gallery_content_id`=?";
+ $rs = $this->mDb->query($query, array( $this->mContentId ) );
+ $query = "DELETE FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` WHERE `item_content_id`=?";
+ $rs = $this->mDb->query($query, array( $this->mContentId ) );
+ $query = "DELETE FROM `".BIT_DB_PREFIX."fisheye_gallery` WHERE `content_id`=?";
+ $rs = $this->mDb->query($query, array( $this->mContentId ) );
+ if( LibertyContent::expunge() ) {
+ $this->CompleteTrans();
+ } else {
+ $this->mDb->RollbackTrans();
+ error_log( "Error expunging fisheye gallery: " . vc($this->mErrors ) );
+ }
+ }
+ return( count( $this->mErrors ) == 0 );
+ }
+
+
+ function galleryExistsInDatabase() {
+ $ret = FALSE;
+
+ if( @$this->verifyId( $this->mGalleryId ) ) {
+ $query = "SELECT COUNT(`gallery_id`) AS `gcount`
+ FROM `".BIT_DB_PREFIX."fisheye_gallery`
+ WHERE `gallery_id` = ?";
+ $rs = $this->mDb->query($query, array($this->mGalleryId));
+ if ($rs->fields['gcount'] > 0)
+ $ret = TRUE;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Returns the layout of the gallery accounting for various defaults
+ * @return the layout string preference
+ */
+ function getLayout() {
+ global $gBitSystem;
+ return $this->getPreference( 'gallery_pagination', $gBitSystem->getConfig( 'default_gallery_pagination', FISHEYE_PAGINATION_GALLERIFFIC ) );
+ }
+
+ public static function getAllLayouts() {
+ return array(
+ FISHEYE_PAGINATION_GALLERIFFIC => 'Galleriffic',
+ FISHEYE_PAGINATION_FIXED_GRID => 'Fixed Grid',
+ FISHEYE_PAGINATION_AUTO_FLOW => 'Auto-Flow Images',
+ FISHEYE_PAGINATION_POSITION_NUMBER => 'Image Order Page Number',
+ FISHEYE_PAGINATION_SIMPLE_LIST => 'Simple List',
+// FISHEYE_PAGINATION_MATTEO => 'Matteo',
+ );
+ }
+
+ /**
+ * Returns include file that will setup the object for rendering
+ * @return the fully specified path to file to be included
+ */
+ function getRenderFile() {
+ return FISHEYE_PKG_INCLUDE_PATH.'display_fisheye_gallery_inc.php';
+ }
+
+ /**
+ * Returns template file used for display
+ * @return the fully specified path to file to be included
+ */
+ function getRenderTemplate() {
+ return 'bitpackage:fisheye/view_gallery.tpl';
+ }
+
+ /**
+ * Function that returns link to display a piece of content
+ * @param pGalleryId id of gallery to link
+ * @return the url to display the gallery.
+ */
+ public static function getDisplayUrlFromHash( &$pParamHash ) {
+ $path = NULL;
+
+ if( BitBase::verifyIdParameter( $pParamHash, 'gallery_id' ) ) {
+ $ret = FISHEYE_PKG_URL;
+ global $gBitSystem;
+ if( $gBitSystem->isFeatureActive( 'pretty_urls' ) ) {
+ $ret .= 'gallery'.$path.'/'.$pParamHash['gallery_id'];
+ } else {
+ $ret .= 'view.php?gallery_id='.$pParamHash['gallery_id'];
+ if( !empty( $pHash['path'] ) ) {
+ $ret .= '&gallery_path='.$pParamHash['path'];
+ }
+ }
+ } elseif( @BitBase::verifyId( $pParamHash['content_id'] ) ) {
+ $ret = FISHEYE_PKG_URL.'view.php?content_id='.$pParamHash['content_id'];
+ }
+ return $ret;
+ }
+
+ function getTree( $pListHash ) {
+ global $gBitDb;
+
+ $ret = array();
+ if( $this->mDb->isAdvancedPostgresEnabled() ) {
+ $bindVars = array();
+ $containVars = array();
+ $selectSql = '';
+ $joinSql = '';
+ $whereSql = '';
+ if( !empty( $pListHash['contain_item'] ) ) {
+ $selectSql = " , tfgim3.`item_content_id` AS `in_gallery` ";
+ $joinSql .= " LEFT OUTER JOIN `".BIT_DB_PREFIX."fisheye_gallery_image_map` tfgim3 ON (tfgim3.`gallery_content_id`=lc.`content_id`) AND tfgim3.`item_content_id`=? ";
+ $bindVars[] = $pListHash['contain_item'];
+ $containVars[] = $pListHash['contain_item'];
+ }
+ if( isset( $pListHash['contain_item'] ) ) {
+ // contain item might have squeaked in as 0, clear our from pListHash
+ unset( $pListHash['contain_item'] );
+ }
+ foreach( $pListHash as $key=>$val ) {
+ $whereSql .= " $key=? AND ";
+ $bindVars[] = $val;
+ }
+
+ $query = "SELECT lc.`content_id` AS `hash_key`, fg.*, lc.* $selectSql
+ FROM `".BIT_DB_PREFIX."fisheye_gallery` fg
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON(fg.`content_id`=lc.`content_id`)
+ $joinSql
+ WHERE $whereSql NOT EXISTS (SELECT gallery_content_id FROM fisheye_gallery_image_map tfgim2 WHERE tfgim2.item_content_id=lc.content_id)
+ ORDER BY lc.title";
+ $rootContent = $gBitDb->GetAssoc( $query, $bindVars );
+
+ foreach( array_keys( $rootContent ) as $conId ) {
+ $splitVars = array();
+ $query = "SELECT branch AS hash_key, * $selectSql
+ FROM connectby('`".BIT_DB_PREFIX."fisheye_gallery_image_map`', '`item_content_id`', '`gallery_content_id`', ?, 0, '/') AS t(cb_item_content_id int,cb_gallery_content_id int, level int, branch text)
+ INNER JOIN `".BIT_DB_PREFIX."fisheye_gallery` fg ON (fg.`content_id`=cb_item_content_id)
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON(lc.`content_id`=fg.`content_id`)
+ $joinSql
+ ORDER BY branch, lc.`title`";
+ $splitVars[] = $conId;
+ if( !empty( $containVars ) ) {
+ $splitVars[] = $containVars[0];
+ }
+
+ FisheyeGallery::splitConnectByTree( $ret, $gBitDb->GetAssoc( $query, $splitVars ) );
+ FisheyeGallery::getTreeSort( $ret );
+ }
+ } else if ( $this->mDb->mType == 'firebird' ) {
+ $bindVars = array();
+ $containVars = array();
+ $selectSql = '';
+ $joinSql = '';
+ $whereSql = '';
+
+ if( !empty( $pListHash['contain_item'] ) ) {
+ $selectSql = " , tfgim3.`item_content_id` AS `in_gallery` ";
+ $joinSql .= " LEFT OUTER JOIN `".BIT_DB_PREFIX."fisheye_gallery_image_map` tfgim3 ON (tfgim3.`gallery_content_id`=lc.`content_id`) AND tfgim3.`item_content_id`=? ";
+ $bindVars[] = $pListHash['contain_item'];
+ $containVars[] = $pListHash['contain_item'];
+ }
+ $this->getServicesSql( 'content_list_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
+
+ if( isset( $pListHash['contain_item'] ) ) {
+ // contain item might have squeaked in as 0, clear our from pListHash
+ unset( $pListHash['contain_item'] );
+ }
+ foreach( $pListHash as $key=>$val ) {
+ $whereSql .= " AND lc.$key=? ";
+ $bindVars[] = $val;
+ }
+
+ $splitVars = array();
+ $query = "WITH RECURSIVE
+ GALLERY_TREE AS (
+ SELECT B.`content_id` AS gallery_content_id, B.`content_id` AS item_content_id, 0 AS BLEVEL, CAST( lcp.`title` AS VARCHAR(255) ) AS BRANCH, 0 AS gallery_parent_id
+ FROM `".BIT_DB_PREFIX."fisheye_gallery` B
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lcp ON(lcp.`content_id`=B.`content_id`)
+ WHERE NOT EXISTS (SELECT gallery_content_id FROM fisheye_gallery_image_map tfgim2 WHERE tfgim2.item_content_id=B.content_id)
+
+ UNION ALL
+
+ SELECT `item_content_id` AS gallery_content_id, `item_content_id`, G.BLEVEL + 1, G.BRANCH || '/' || `item_content_id` AS BRANCH, `gallery_content_id` AS gallery_parent_id
+ FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` G1
+ JOIN GALLERY_TREE G
+ ON G1.`gallery_content_id` = G.`item_content_id`
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lcg1 ON(lcg1.`content_id`=`item_content_id`) and lcg1.`content_type_guid` = 'fisheyegallery'
+ )
+ SELECT T.BRANCH AS hash_key, T.BLEVEL, fg.*, lc.* $selectSql
+ FROM GALLERY_TREE T
+ INNER JOIN `".BIT_DB_PREFIX."fisheye_gallery` fg ON (fg.`content_id`=T.`gallery_content_id`)
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id`=T.`item_content_id`)
+ LEFT OUTER JOIN `".BIT_DB_PREFIX."fisheye_gallery_image_map` fgimo ON (fgimo.`gallery_content_id`=T.gallery_parent_id) AND fgimo.`item_content_id`=T.gallery_content_id
+ $joinSql
+ WHERE lc.`content_type_guid` = 'fisheyegallery' $whereSql
+ ORDER BY T.BRANCH, fgimo.`item_position`";
+
+
+
+ if( !empty( $bindVars ) ) {
+ FisheyeGallery::splitConnectByTree( $ret, $gBitDb->GetAssoc( $query, $bindVars ) );
+ } else {
+ FisheyeGallery::splitConnectByTree( $ret, $gBitDb->GetAssoc( $query ) );
+ }
+
+ } else {
+// this needs replacing with a more suitable list query ...
+ $pListHash['show_empty'] = TRUE;
+ $galList = $this->getList( $pListHash );
+ // index by content_id
+ foreach( $galList as $galId => $gal ) {
+ $ret[$gal['content_id']] = $gal;
+ }
+ FisheyeGallery::splitConnectByTree( $ret, $ret );
+ FisheyeGallery::getTreeSort( $ret );
+ }
+ return( $ret );
+ }
+
+ function getTreeSort( &$pTree ) {
+ if( $pTree ) {
+ foreach( array_keys( $pTree ) as $k ) {
+ if( !empty( $pTree[$k]['children'] ) ) {
+ FisheyeGallery::getTreeSort( $pTree[$k]['children'] );
+ }
+ }
+ uasort( $pTree, array( 'FisheyeGallery', 'getTreeSortCmp' ) );
+ }
+ }
+
+ static function getTreeSortCmp( $a, $b ) {
+ return strcmp( $a['content']['title'], $b['content']['title'] );
+ }
+
+ function splitConnectByTree( &$pRet, $pTreeHash ) {
+ if( $pTreeHash ) {
+ foreach( array_keys( $pTreeHash ) as $conId ) {
+ $path = explode( '/', $conId );
+ FisheyeGallery::recurseConnectByPath( $pRet, $pTreeHash[$conId], $path );
+ }
+ }
+ }
+
+ function recurseConnectByPath( &$pRet, $pTreeHash, $pPath ) {
+ $popId = array_shift( $pPath );
+ if( count( $pPath ) > 0 ) {
+ if( empty( $pRet[$popId]['children'] ) ) {
+ $pRet[$popId]['children'] = array();
+ }
+ FisheyeGallery::recurseConnectByPath( $pRet[$popId]['children'], $pTreeHash, $pPath );
+ } else {
+
+ $pRet[$popId]['content'] = $pTreeHash;
+ }
+ }
+
+ // Generate a nested ul list of listed galleries
+ function generateList( $pListHash, $pOptions, $pLocate = FALSE ) {
+ $ret = '';
+ if( $hash = FisheyeGallery::getTree( $pListHash ) ) {
+
+ $class = ' structure-toc';
+ $ret = "<ul ";
+ foreach( array( 'class', 'name', 'id', 'onchange' ) as $key ) {
+ if( !empty( $pOptions[$key] ) ) {
+ if( $key == 'class' ) {
+ $class .= ' '.$pOptions[$key];
+ } else {
+ $ret .= " $key=\"$pOptions[$key]\" ";
+ }
+ }
+ }
+ $ret .= ' class="'.$class.'">';
+ $ret .= self::generateListItems( $hash, $pOptions, $pLocate );
+ $ret .= "</ul>";
+ }
+ return $ret;
+ }
+
+ // Helper method for generateMenu. See that method. Is Recursive
+ function generateListItems( &$pHash, $pOptions, $pLocate ) {
+ $ret = '';
+ foreach( array_keys( $pHash ) as $conId ) {
+ $class = !empty( $pOptions['radio_checkbox'] ) ? 'checkbox' : '';
+ $ret .= '<li id="fisheyegallery'.$pHash[$conId]['content']['gallery_id'].'" gallery_id="'.$pHash[$conId]['content']['gallery_id'].'" ';
+ if( !empty( $pOptions['item_attributes'] ) ) {
+ foreach( $pOptions['item_attributes'] as $key=>$value ) {
+ if( $key == 'class' ) {
+ $class .= ' '.$value;
+ } else {
+ $ret .= " $key=\"$value\" ";
+ }
+ }
+ }
+ $ret .= ' class="'.$class.'"><label>';
+ if ( $pLocate || $pHash[$conId]['content']['content_id'] != $this->mContentId ) {
+ if( !empty( $pOptions['radio_checkbox'] ) ) {
+ $ret .= '<input type="checkbox" name="gallery_additions[]" value="'.$pHash[$conId]['content']['gallery_id'].'" ';
+ if( !empty( $pHash[$conId]['content']['in_gallery'] ) || $pHash[$conId]['content']['content_id'] == $this->mContentId ) {
+ $ret .= ' checked="checked" ';
+ }
+ $ret .= '/>';
+ }
+ }
+ if ( $pHash[$conId]['content']['content_id'] == $this->mContentId
+ or ( isset( $pHash[$conId]['content']['in_gallery'] ) and $pHash[$conId]['content']['in_gallery'] ) ) {
+ $ret .= '<span class="active">'.htmlspecialchars( $pHash[$conId]['content']['title'] ).'</span>';
+ } else {
+ $ret .= htmlspecialchars( $pHash[$conId]['content']['title'] );
+ }
+ $ret .= '</label></li>';
+ if( !empty( $pHash[$conId]['children'] ) ) {
+ $ret .= '<li><ul>'.FisheyeGallery::generateListItems( $pHash[$conId]['children'], $pOptions, $pLocate ).'</ul></li>';
+ }
+ }
+ return $ret;
+ }
+
+
+ // Generate a select drop menu of listed galleries
+ function generateMenu( $pListHash, $pOptions, $pLocate=NULL ) {
+ $ret = "<select class='form-control' ";
+ foreach( array( 'class', 'name', 'id', 'onchange' ) as $key ) {
+ if( !empty( $pOptions[$key] ) ) {
+ $ret .= " $key=\"$pOptions[$key]\" ";
+ }
+ }
+ $ret .= ">";
+ $ret .= !empty( $pOptions['first_option'] ) ? $pOptions['first_option'] : '';
+ if( $hash = FisheyeGallery::getTree( $pListHash ) ) {
+ $ret .= FisheyeGallery::generateMenuOptions( $hash, $pOptions, $pLocate );
+ }
+ $ret .= "</select>";
+ return $ret;
+ }
+
+ // Helper method for generateMenu. See that method. Is Recursive
+ function generateMenuOptions( &$pHash, $pOptions, $pLocate, $pPrefix='' ) {
+ $ret = '';
+ foreach( array_keys( $pHash ) as $conId ) {
+ $ret .= '<option gallery_id="'.$pHash[$conId]['content']['gallery_id'].'" value="'.$pHash[$conId]['content']['gallery_id'].'"';
+ if( !empty( $pOptions['item_attributes'] ) ) {
+ foreach( $pOptions['item_attributes'] as $key=>$value ) {
+ $ret .= " $key=\"$value\" ";
+ }
+ }
+ if ( $pLocate && $pLocate == $pHash[$conId]['content']['gallery_id'] ) {
+ $ret .= ' selected="selected" ';
+ }
+ $ret .= ' >'.($pPrefix?$pPrefix.'&raquo; ':'').htmlspecialchars( $pHash[$conId]['content']['title'] ).'</option>';
+
+ if( !empty( $pHash[$conId]['children'] ) ) {
+ $ret .= FisheyeGallery::generateMenuOptions( $pHash[$conId]['children'], $pOptions, $pLocate, ($pPrefix.'-') );
+ }
+ }
+ return $ret;
+ }
+
+ function getList( &$pListHash ) {
+ global $gBitUser,$gBitSystem, $gBitDbType;
+
+ $pListHash['valid_sort_modes'] = array( 'real_name', 'login', 'hits', 'title', 'created', 'last_modified', 'last_hit', 'event_time', 'ip' );
+
+ LibertyContent::prepGetList( $pListHash );
+ $bindVars = array();
+ $selectSql = $joinSql = $whereSql = $sortSql = '';
+
+ if( $gBitDbType == 'mysql' ) {
+ // loser mysql without subselects
+ if( !empty( $pListHash['root_only'] ) ) {
+ $joinSql .= " LEFT OUTER JOIN `".BIT_DB_PREFIX."fisheye_gallery_image_map` tfgim2 ON (tfgim2.`item_content_id`=lc.`content_id`)";
+ $whereSql .= ' AND tfgim2.`item_content_id` IS NULL ';
+ }
+ }
+
+ if( !empty( $pListHash['contain_item'] ) ) {
+ $selectSql = " , tfgim3.`item_content_id` AS `in_gallery` ";
+ $joinSql .= " LEFT OUTER JOIN `".BIT_DB_PREFIX."fisheye_gallery_image_map` tfgim3 ON (tfgim3.`gallery_content_id`=lc.`content_id`) AND tfgim3.`item_content_id`=? ";
+ $bindVars[] = $pListHash['contain_item'];
+ }
+
+ if( @$this->verifyId( $pListHash['user_id'] ) ) {
+ $whereSql .= " AND lc.`user_id` = ? ";
+ $bindVars[] = (int)$pListHash['user_id'];
+ }
+
+ if( !empty( $pListHash['find'] ) ) {
+ $whereSql .= " AND UPPER( lc.`title` ) LIKE ? ";
+ $bindVars[] = '%'.strtoupper( $pListHash['find'] ).'%';
+ }
+
+ if( !empty( $pListHash['show_public'] ) ) {
+ $joinSql .= " LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content_prefs` lcp ON( lcp.`content_id`=lc.`content_id` )";
+ $whereSql .= " OR ( lcp.`pref_name`=? AND lcp.`pref_value`=? ) ";
+ $bindVars[] = 'is_public';
+ $bindVars[] = 'y';
+ }
+
+ $mapJoin = "";
+ if( $gBitDbType != 'mysql' ) {
+ // weed out empty galleries if we don't need them. DO NOT get clever and change the IN and EXISTS choices here.
+ if( empty( $pListHash['show_empty'] ) ) {
+ $whereSql .= " AND fg.`content_id` IN (SELECT `gallery_content_id` FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` fgim WHERE fgim.`gallery_content_id`=fg.`content_id`)";
+ }
+ if( !empty( $pListHash['root_only'] ) ) {
+ $whereSql .= " AND NOT EXISTS (SELECT `gallery_content_id` FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` tfgim2 WHERE tfgim2.`item_content_id`=lc.`content_id`)";
+ }
+ } else {
+ // weed out empty galleries if we don't need them
+ if( empty( $pListHash['show_empty'] ) ) {
+ $mapJoin = "INNER JOIN `".BIT_DB_PREFIX."fisheye_gallery_image_map` fgim ON (fgim.`gallery_content_id`=lc.`content_id`)";
+ }
+ }
+
+ if ( !empty( $pListHash['sort_mode'] ) ) {
+ //converted in prepGetList()
+ $sortSql .= " ORDER BY ".$this->mDb->convertSortmode( $pListHash['sort_mode'] )." ";
+ }
+ // Putting in the below hack because mssql cannot select distinct on a text blob column.
+ $selectSql .= $gBitDbType == 'mssql' ? " ,CAST(lc.`data` AS VARCHAR(250)) as `data` " : " ,lc.`data` ";
+
+ $this->getServicesSql( 'content_list_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
+
+ if( !empty( $whereSql ) ) {
+ $whereSql = substr_replace( $whereSql, ' WHERE ', 0, 4 );
+ }
+
+ $query = "SELECT fg.`gallery_id` AS `hash_key`, fg.*,
+ lc.`user_id`, lc.`modifier_user_id`, lc.`created`, lc.`last_modified`,
+ lc.`content_type_guid`, lc.`format_guid`, lch.`hits`, lch.`last_hit`, lc.`event_time`, lc.`version`,
+ lc.`lang_code`, lc.`title`, lc.`ip`, uu.`login`, uu.`real_name`, plc.`content_type_guid` AS `preview_content_type_guid`
+ $selectSql
+ FROM `".BIT_DB_PREFIX."fisheye_gallery` fg
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (fg.`content_id` = lc.`content_id`)
+ INNER JOIN `".BIT_DB_PREFIX."users_users` uu ON (uu.`user_id` = lc.`user_id`)
+ LEFT JOIN `".BIT_DB_PREFIX."liberty_content_hits` lch ON (lch.`content_id` = lc.`content_id`)
+ $mapJoin $joinSql
+ LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content` plc ON (fg.`preview_content_id` = plc.`content_id`)
+ $whereSql $sortSql";
+ if( $rs = $this->mDb->query( $query, $bindVars, $pListHash['max_records'], $pListHash['offset'] ) ) {
+ $data = $rs->GetAssoc();
+ if( empty( $pListHash['no_thumbnails'] ) ) {
+ $thumbsize = !empty( $pListHash['thumbnail_size'] ) ? $pListHash['thumbnail_size'] : 'small';
+ foreach( array_keys( $data ) as $galleryId ) {
+ $data[$galleryId]['display_url'] = static::getDisplayUrlFromHash( $data[$galleryId] );
+ $data[$galleryId]['display_uri'] = static::getDisplayUriFromHash( $data[$galleryId] );
+ if( $thumbImage = $this->getThumbnailImage( $data[$galleryId]['content_id'], $data[$galleryId]['preview_content_id'], $data[$galleryId]['preview_content_type_guid'] ) ) {
+ $data[$galleryId]['thumbnail_url'] = $thumbImage->getThumbnailUrl( $thumbsize );
+ $data[$galleryId]['thumbnail_uri'] = $thumbImage->getThumbnailUri( $thumbsize );
+ } elseif( !empty( $pListHash['show_empty'] ) ) {
+ $data[$galleryId]['thumbnail_url'] = FISHEYE_PKG_URL.'image/no_image.png';
+ } else {
+ unset( $data[$galleryId] );
+ }
+ }
+ }
+ }
+
+ // count galleries
+ $query_c = "SELECT COUNT( fg.`gallery_id` )
+ FROM `".BIT_DB_PREFIX."fisheye_gallery` fg
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (fg.`content_id` = lc.`content_id` )
+ INNER JOIN `".BIT_DB_PREFIX."users_users` uu ON (uu.`user_id` = lc.`user_id`)
+ LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content` ptc ON( fg.`preview_content_id`=ptc.`content_id` )
+ $mapJoin $joinSql
+ $whereSql";
+ $cant = $this->mDb->getOne( $query_c, $bindVars );
+
+ // add all pagination info to $ret
+ $pListHash['cant'] = $cant;
+ LibertyContent::postGetList( $pListHash );
+ return $data;
+ }
+
+ function download(){
+ if($this->isValid()){
+ $zip = new ZipArchive();
+
+ $filename = tempnam(TEMP_PKG_PATH,"galleryzip");
+ $path = '/';
+
+ if( $zip->open ($filename, ZIPARCHIVE::OVERWRITE) !== TRUE ){
+ $this->mErrors['download'] = "Unable to create zip file";
+ }else{
+ addGalleryRecursive( $this->mGalleryId , $path, $zip);
+ }
+ $zip->close();
+
+ //escape backslashes
+ $outputFileTitle = str_replace("\\",'\\\\',$this->getTitle());
+ //escape double quotes
+ $outputFileTitle = str_replace('"','\\"',$outputFileTitle);
+
+ header('Content-Description: File Transfer');
+ header('Content-Type: application/octet-stream');
+ Header ("Content-disposition: attachment; filename=\"".$outputFileTitle.".zip\"");
+ header('Content-Transfer-Encoding: binary');
+ header('Expires: 0');
+ header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+ header('Pragma: public');
+ Header ("Content-Length: ".filesize( $filename ) );
+ ob_end_flush();
+ readfile($filename);
+ unlink($filename);
+ }
+ }
+
+ public static function getServiceIcon() {
+ return '<i class="icon-camera"></i>';
+ }
+
+ public static function getServiceKey() {
+ return 'fisheye';
+ }
+}
+
+function addGalleryRecursive( $pGalleryId , $pPath = '/', &$pZip ){
+
+ if( $gallery = FisheyeGallery::lookup( array( 'gallery_id' => $pGalleryId ) ) ) {
+ $gallery->load();
+ $gallery->loadImages();
+ $pPath .= $gallery->getTitle().'/';
+ foreach ( $gallery->mItems as $item ){
+ if( is_a( $item , 'FisheyeImage' ) ){
+ $sourcePath = $item->getSourceFile();
+ $title = $item->getTitle();
+ $pZip->addFile($sourcePath, $pPath.$title.substr($sourcePath,strrpos($sourcePath,'.')) );
+ } elseif ( is_a( $item , 'FisheyeGallery' ) ) {
+ addGalleryRecursive($item->mGalleryId,$pPath,$pZip);
+ }
+ }
+ }
+}
+
+?>
diff --git a/includes/classes/FisheyeImage.php b/includes/classes/FisheyeImage.php
new file mode 100644
index 0000000..84e08bf
--- /dev/null
+++ b/includes/classes/FisheyeImage.php
@@ -0,0 +1,900 @@
+<?php
+/**
+ * @package fisheye
+ */
+
+/**
+ * required setup
+ */
+require_once( FISHEYE_PKG_CLASS_PATH.'FisheyeBase.php' );
+// Needed for getting event_time and possible image title and data
+require_once( LIBERTY_PKG_PATH.'plugins/mime.image.php' );
+
+define('FISHEYEIMAGE_CONTENT_TYPE_GUID', 'fisheyeimage');
+
+/**
+ * @package fisheye
+ */
+class FisheyeImage extends FisheyeBase {
+ public $mImageId;
+
+ function __construct($pImageId = NULL, $pContentId = NULL) {
+ parent::__construct();
+ $this->mImageId = (int)$pImageId;
+ $this->mContentId = (int)$pContentId;
+
+ $this->registerContentType(
+ FISHEYEIMAGE_CONTENT_TYPE_GUID, array( 'content_type_guid' => FISHEYEIMAGE_CONTENT_TYPE_GUID,
+ 'content_name' => 'Image',
+ 'handler_class' => 'FisheyeImage',
+ 'handler_package' => 'fisheye',
+ 'handler_file' => 'FisheyeImage.php',
+ 'maintainer_url' => 'http://www.bitweaver.org'
+ ));
+
+ // Permission setup
+ $this->mViewContentPerm = 'p_fisheye_view';
+ $this->mUpdateContentPerm = 'p_fisheye_update';
+ $this->mAdminContentPerm = 'p_fisheye_admin';
+ }
+
+ public function __sleep() {
+ $ret = array_merge( parent::__sleep(), array( 'mImageId' ) );
+ return $ret;
+ }
+
+ public static function lookup( $pLookupHash ) {
+ global $gBitDb;
+ $ret = NULL;
+
+ $lookupContentId = NULL;
+ if (!empty($pLookupHash['image_id']) && is_numeric($pLookupHash['image_id'])) {
+ if( $lookup = $gBitDb->getRow( "SELECT lc.`content_id`, lc.`content_type_guid` FROM `".BIT_DB_PREFIX."fisheye_image` fi INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON(lc.`content_id`=fi.`content_id`) WHERE `image_id`=?", array( $pLookupHash['image_id'] ) ) ) {
+ $lookupContentId = $lookup['content_id'];
+ $lookupContentGuid = $lookup['content_type_guid'];
+ }
+ } elseif (!empty($pLookupHash['content_id']) && is_numeric($pLookupHash['content_id'])) {
+ $lookupContentId = $pLookupHash['content_id'];
+ $lookupContentGuid = NULL;
+ }
+
+ if( static::verifyId( $lookupContentId ) ) {
+ $ret = static::getLibertyObject( $lookupContentId, $lookupContentGuid );
+ }
+
+ return $ret;
+ }
+
+ public function load() {
+ if( $this->isValid() ) {
+ global $gBitSystem;
+ $gateSql = NULL;
+ $selectSql = $joinSql = $whereSql = '';
+ $bindVars = array();
+
+ if ( @$this->verifyId( $this->mImageId ) ) {
+ $whereSql = " WHERE fi.`image_id` = ?";
+ $bindVars[] = $this->mImageId;
+ } elseif ( @$this->verifyId( $this->mContentId ) ) {
+ $whereSql = " WHERE fi.`content_id` = ?";
+ $bindVars[] = $this->mContentId;
+ }
+
+ $this->getServicesSql( 'content_load_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
+
+ $sql = "SELECT fi.*, lc.* $gateSql $selectSql
+ , uue.`login` AS `modifier_user`, uue.`real_name` AS `modifier_real_name`
+ , uuc.`login` AS `creator_user`, uuc.`real_name` AS `creator_real_name`, ufm.`favorite_content_id` AS `is_favorite`
+ , lch.`hits`
+ FROM `".BIT_DB_PREFIX."fisheye_image` fi
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id` = fi.`content_id`)
+ LEFT JOIN `".BIT_DB_PREFIX."users_users` uue ON (uue.`user_id` = lc.`modifier_user_id`)
+ LEFT JOIN `".BIT_DB_PREFIX."users_users` uuc ON (uuc.`user_id` = lc.`user_id`)
+ LEFT JOIN `".BIT_DB_PREFIX."users_favorites_map` ufm ON (ufm.`favorite_content_id`=lc.`content_id` AND ufm.`user_id`=uuc.`user_id`)
+ LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content_hits` lch ON ( lch.`content_id` = lc.`content_id` ) $joinSql
+ $whereSql";
+ if( $this->mInfo = $this->mDb->getRow( $sql, $bindVars ) ) {
+ $this->mImageId = $this->mInfo['image_id'];
+ $this->mContentId = $this->mInfo['content_id'];
+
+ $this->mInfo['creator'] = (isset( $this->mInfo['creator_real_name'] ) ? $this->mInfo['creator_real_name'] : $this->mInfo['creator_user'] );
+ $this->mInfo['editor'] = (isset( $this->mInfo['modifier_real_name'] ) ? $this->mInfo['modifier_real_name'] : $this->mInfo['modifier_user'] );
+
+ if( $gBitSystem->isPackageActive( 'gatekeeper' ) && !@$this->verifyId( $this->mInfo['security_id'] ) ) {
+ // check to see if this image is in a protected gallery
+ // this burns an extra select but avoids an big and gnarly LEFT JOIN sequence that may be hard to optimize on all DB's
+ $query = "SELECT ls.* FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` fgim
+ INNER JOIN `".BIT_DB_PREFIX."gatekeeper_security_map` tsm ON(fgim.`gallery_content_id`=tsm.`content_id` )
+ INNER JOIN `".BIT_DB_PREFIX."gatekeeper_security` ls ON(tsm.`security_id`=ls.`security_id` )
+ WHERE fgim.`item_content_id`=?";
+ $grs = $this->mDb->query($query, array( $this->mContentId ) );
+ if( $grs && $grs->RecordCount() ) {
+ // order matters here
+ $this->mInfo = array_merge( $grs->fields, $this->mInfo );
+ }
+ }
+
+ // LibertyMime will load the attachment details in $this->mStorage
+ parent::load();
+
+ // Copy mStorage to mInfo['image_file'] for easy access
+ if( !empty( $this->mStorage ) && count( $this->mStorage ) > 0 ) {
+ // it seems that this is not necessary and causes confusing copies of the same stuff all over the place
+ $this->mInfo = array_merge( current( $this->mStorage ), $this->mInfo );
+ // copy the image data by reference to reduce memory
+ reset( $this->mStorage );
+ $this->mInfo['image_file'] = current( $this->mStorage );
+ // override original display_url that mime knows where we keep the image
+ $this->mInfo['image_file']['display_url'] = $this->getDisplayUrl();
+ } else {
+ $this->mInfo['image_file'] = NULL;
+ }
+
+ if( empty( $this->mInfo['width'] ) || empty( $this->mInfo['height'] ) ) {
+ $details = $this->getImageDetails();
+ // bounds checking on the width and height - corrupt photos can be ridiculously huge or negative
+ if( !empty($details) AND $details['width'] > 0 AND $details['width'] < 9999 AND $details['height'] > 0 AND $details['height'] < 9999 ) {
+ $this->mInfo['width'] = $details['width'];
+ $this->mInfo['height'] = $details['height'];
+ $this->mDb->query( "UPDATE `".BIT_DB_PREFIX."fisheye_image` SET `width`=?, `height`=? WHERE `content_id`=?", array( $this->mInfo['width'], $this->mInfo['height'], $this->mContentId ) );
+ }
+ }
+ }
+ $ret = count($this->mInfo);
+ } else {
+ // We don't have an image_id or a content_id so there is no way to know what to load
+ $ret = NULL;
+ }
+
+ return $ret;
+ }
+
+ function storeDimensions( $pDetails ) {
+ if( $this->isValid() && $this->mInfo['width'] != $pDetails['width'] || $this->mInfo['height'] != $pDetails['height'] ) {
+ // if our data got out of sync with the database, force an update
+ $query = "UPDATE `".BIT_DB_PREFIX."fisheye_image` SET `width`=?, `height`=? WHERE `content_id`=?";
+ $this->mDb->query( $query, array( $pDetails['width'], $pDetails['height'], $this->mContentId ) );
+ $this->mInfo['width'] = $pDetails['width'];
+ $this->mInfo['height'] = $pDetails['height'];
+ $this->clearFromCache();
+ }
+ }
+
+ function exportHash() {
+ $ret = NULL;
+ // make sure we have a valid image file.
+ if( ($ret = parent::exportHash()) && ($details = $this->getImageDetails() ) ) {
+ $ret = array_merge( $ret, array( 'type' => $this->getContentType(),
+ 'landscape' => $this->isLandscape(),
+ 'has_description' => !empty( $this->mInfo['data'] ),
+ 'is_favorite' => $this->getField('is_favorite'),
+ ) );
+ }
+ return $ret;
+ }
+
+ function isLandscape() {
+ return( !empty( $this->mInfo['width'] ) && !empty( $this->mInfo['height'] ) && ($this->mInfo['width'] > $this->mInfo['height']) );
+ }
+
+ function verifyImageData(&$pParamHash) {
+ $pParamHash['content_type_guid'] = $this->getContentType();
+
+ if ( empty($pParamHash['purge_from_galleries']) ) {
+ $pParamHash['purge_from_galleries'] = FALSE;
+ }
+
+ if( !empty( $pParamHash['resize'] ) ) {
+ $pParamHash['_files_override'][0]['max_height'] = $pParamHash['_files_override'][0]['max_width'] = $pParamHash['resize'];
+ }
+
+ // Make sure we know what to update
+ if( $this->isValid() ) {
+ // these 2 entries will inform LibertyContent and LibertyMime that this is an update
+ $pParamHash['content_id'] = $this->mContentId;
+ if( !empty( $this->mInfo['attachment_id'] ) ) {
+ $pParamHash['_files_override'][0]['attachment_id'] = $this->mInfo['attachment_id'];
+ }
+ }
+
+ if( function_exists( 'mime_image_get_exif_data' ) && !empty( $pParamHash['_files_override'][0]['tmp_name'] ) ) {
+ $exifFile['source_file'] = $pParamHash['_files_override'][0]['tmp_name'];
+ $exifFile['type'] = $pParamHash['_files_override'][0]['type'];
+ $exifHash = mime_image_get_exif_data( $exifFile );
+
+ // Set some default values based on the Exif data
+ if( !empty( $exifHash['IFD0']['ImageDescription'] ) ) {
+ if( empty( $pParamHash['title'] ) ) {
+ $exifTitle = trim( $exifHash['IFD0']['ImageDescription'] );
+ if( !empty( $exifTitle ) ) {
+ $pParamHash['title'] = $exifTitle;
+ }
+ } elseif( empty( $pParamHash['edit'] ) && !$this->getField( 'data' ) && $pParamHash['title'] != $exifHash['IFD0']['ImageDescription'] ) {
+ $pParamHash['edit'] = $exifHash['IFD0']['ImageDescription'];
+ }
+ }
+
+ // These come from Photoshop
+ if( !empty( $exifHash['headline'] ) ) {
+ if( empty( $pParamHash['title'] ) ) {
+ $pParamHash['title'] = $exifHash['headline'];
+ } elseif( empty( $pParamHash['edit'] ) && !$this->getField( 'data' ) && $pParamHash['title'] != $exifHash['headline'] ) {
+ $pParamHash['edit'] = $exifHash['headline'];
+ }
+ }
+ if( !empty( $exifFile['caption'] ) ) {
+ if( empty( $pParamHash['title'] ) ) {
+ $pParamHash['title'] = $exifFile['caption'];
+ } elseif( empty( $pParamHash['edit'] ) && !$this->getField( 'data' ) && $pParamHash['title'] != $exifFile['caption'] ) {
+ $pParamHash['edit'] = $exifFile['caption'];
+ }
+ }
+
+ if( empty( $pParamHash['event_time'] ) && !$this->getField( 'event_time' ) && !empty( $exifHash['EXIF']['DateTimeOriginal'] ) ) {
+ $pParamHash['event_time'] = strtotime( $exifHash['EXIF']['DateTimeOriginal'] );
+ }
+
+ }
+
+ // let's add a default title if we still don't have one or the user has chosen to use filename over exif data
+ if( (empty( $pParamHash['title'] ) || !empty($_REQUEST['use_filenames'])) && !empty( $pParamHash['_files_override'][0]['name'] ) ) {
+ if( preg_match( '/^[A-Z]:\\\/', $pParamHash['_files_override'][0]['name'] ) ) {
+ // MSIE shit file names if passthrough via gigaupload, etc.
+ // basename will not work - see http://us3.php.net/manual/en/function.basename.php
+ $tmp = preg_split("[\\\]", $pParamHash['_files_override'][0]['name'] );
+ $defaultName = $tmp[count($tmp) - 1];
+ $pParamHash['_files_override'][0]['name'] = $defaultName;
+ } else {
+ $defaultName = $pParamHash['_files_override'][0]['name'];
+ }
+
+ if( strpos( $pParamHash['_files_override'][0]['name'], '.' ) ) {
+ list( $defaultName, $ext ) = explode( '.', $pParamHash['_files_override'][0]['name'] );
+ }
+ $pParamHash['title'] = str_replace( '_', ' ', $defaultName );
+ }
+
+ if( count( $this->mErrors ) > 0 ){
+ parent::verify( $pParamHash );
+ }
+
+ return (count($this->mErrors) == 0);
+ }
+
+ function store(&$pParamHash) {
+ global $gBitSystem, $gLibertySystem;
+
+ if ($this->verifyImageData($pParamHash)) {
+ // Save the current attachment ID for the image attached to this FisheyeImage so we can
+ // delete it after saving the new one
+ if (!empty($this->mInfo['attachment_id']) && !empty($pParamHash['_files_override'][0])) {
+ $currentImageAttachmentId = $this->mInfo['attachment_id'];
+ $pParamHash['attachment_id'] = $currentImageAttachmentId;
+ } else {
+ $currentImageAttachmentId = NULL;
+ }
+
+ // we have already done all the permission checking needed for this user to upload an image
+ $pParamHash['no_perm_check'] = TRUE;
+
+ $this->StartTrans();
+ $pParamHash['thumbnail'] = !$gBitSystem->isFeatureActive( 'liberty_offline_thumbnailer' );
+ if( LibertyMime::store( $pParamHash ) ) {
+ if( $currentImageAttachmentId && $currentImageAttachmentId != $this->mInfo['attachment_id'] ) {
+ $this->expungeAttachment($currentImageAttachmentId);
+ }
+ // get storage format back from LibertyMime
+ $this->mContentId = $pParamHash['content_id'];
+ $this->mInfo['content_id'] = $this->mContentId;
+
+ if ( !empty( $this->mInfo['source_file'] ) && file_exists( $this->getSourceFile() )) {
+ $imageDetails = $this->getImageDetails( $this->getSourceFile() );
+ } else {
+ $imageDetails = NULL;
+ }
+
+ if (!$imageDetails) {
+ $imageDetails['width'] = (!empty($this->mInfo['width']) ? $this->mInfo['width'] : NULL);
+ $imageDetails['height'] = (!empty($this->mInfo['height']) ? $this->mInfo['height'] : NULL);
+ }
+
+ if ($this->imageExistsInDatabase()) {
+ $sql = "UPDATE `".BIT_DB_PREFIX."fisheye_image`
+ SET `content_id` = ?, `width` = ?, `height` = ?
+ WHERE `image_id` = ?";
+ $bindVars = array($this->mContentId, $imageDetails['width'], $imageDetails['height'], $this->mImageId);
+ } else {
+ $this->mImageId = defined( 'LINKED_ATTACHMENTS' ) ? $this->mContentId : $this->mDb->GenID('fisheye_image_id_seq');
+ $this->mInfo['image_id'] = $this->mImageId;
+ $sql = "INSERT INTO `".BIT_DB_PREFIX."fisheye_image` (`image_id`, `content_id`, `width`, `height`) VALUES (?,?,?,?)";
+ $bindVars = array($this->mImageId, $this->mContentId, $imageDetails['width'], $imageDetails['height']);
+ }
+
+ $rs = $this->mDb->query($sql, $bindVars);
+
+ // check to see if we need offline thumbnailing
+ if( $gBitSystem->isFeatureActive( 'liberty_offline_thumbnailer' ) ) {
+ $resize = !empty( $pParamHash['resize'] ) ? (int)$pParamHash['resize'] : NULL;
+ $this->generateThumbnails( $resize );
+ } else {
+ if( !empty( $pParamHash['resize'] ) && is_numeric( $pParamHash['resize'] ) ) {
+ $this->resizeOriginal( $pParamHash['resize'] );
+ }
+ }
+ $this->CompleteTrans();
+ } else {
+ $this->mDb->RollbackTrans();
+ }
+ $this->clearFromCache();
+ } else {
+ $this->mErrors[] = "There were errors while attempting to save this gallery image";
+ }
+ return (count($this->mErrors) == 0);
+ }
+
+ function getExifField( $pExifField ) {
+ $ret = NULL;
+ if( function_exists( 'exif_read_data' ) ) {
+ $pExifField = strtolower( $pExifField );
+ $file = $this->getSourceFile();
+ // only attempt to get exif data from jpg or tiff files - chokes otherwise
+ if( empty( $this->mExif ) && preg_match( "!\.(jpe?g|tif{1,2})$!", $file ) ) {
+ if( $exif = @exif_read_data( $file ) ) {
+ $this->mExif = array_change_key_case( $exif, CASE_LOWER );
+ }
+ }
+ if( !empty( $this->mExif[$pExifField] ) ) {
+ $ret = $this->mExif[$pExifField];
+ }
+ }
+ return $ret;
+ }
+
+ function rotateImage( $pDegrees, $pImmediateRender = FALSE ) {
+ global $gBitSystem;
+ if( $this->getField( 'file_name' ) || $this->load() ) {
+ $fileHash['source_file'] = $this->getSourceFile();
+ $fileHash['dest_base_name'] = preg_replace('/(.+)\..*$/', '$1', basename( $fileHash['source_file'] ) );
+ $fileHash['type'] = $gBitSystem->verifyMimeType( $fileHash['source_file'] );
+ $fileHash['size'] = filesize( $fileHash['source_file'] );
+ $fileHash['dest_branch'] = dirname( $this->getSourceFile() ).'/';
+ $fileHash['name'] = $this->getField( 'file_name' );
+ if( $pDegrees == 'auto' ) {
+ if( $exifOrientation = $this->getExifField( 'orientation' ) ) {
+ switch( $exifOrientation ) {
+ case 1: //) transform="";;
+ break;
+ case 2: //) transform="-flip horizontal";;
+ break;
+ case 3: //) transform="-rotate 180";;
+ $pDegrees = 180;
+ break;
+ case 4: //) transform="-flip vertical";;
+ break;
+ case 5: //) transform="-transpose";;
+ break;
+ case 6: //) transform="-rotate 90";;
+ // make sure image has not already been rotated
+ if( $this->isLandscape() ) {
+ $pDegrees = 90;
+ }
+ break;
+ case 7: //) transform="-transverse";;
+ break;
+ case 8: //) transform="-rotate 270";;
+ // make sure image has not already been rotated
+ if( $this->isLandscape() ) {
+ $pDegrees = 270;
+ }
+ break;
+ // *) transform="";;
+ }
+ }
+ }
+ if( is_numeric( $pDegrees ) ) {
+ $fileHash['degrees'] = $pDegrees;
+
+ if( ($rotateFunc = liberty_get_function( 'rotate' )) && $rotateFunc( $fileHash ) ) {
+ liberty_clear_thumbnails( $fileHash );
+ $this->mDb->query( "UPDATE `".BIT_DB_PREFIX."fisheye_image` SET `width`=`height`, `height`=`width` WHERE `content_id`=?", array( $this->mContentId ) );
+ $this->clearFromCache();
+ $this->generateThumbnails( FALSE, $pImmediateRender );
+ } else {
+ $this->mErrors['rotate'] = $fileHash['error'];
+ }
+ } elseif( $pDegrees == 'auto' ) {
+ $this->mErrors['rotate'] = "Image was not auto-rotated.";
+ }
+ }
+ return (count($this->mErrors) == 0);
+ }
+
+
+ /**
+ * convertColorspace
+ *
+ * @param string $pColorSpace - target color space, only 'grayscale' is currently supported, and only when using the MagickWand image processor
+ * @access public
+ * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
+ */
+ function convertColorspace( $pColorSpace ) {
+ global $gBitSystem;
+ $ret = FALSE;
+ if( $this->getField( 'file_name' ) || $this->load() ) {
+ $fileHash['source_file'] = $this->getSourceFile();
+ $fileHash['dest_base_name'] = preg_replace('/(.+)\..*$/', '$1', basename( $fileHash['source_file'] ) );
+ $fileHash['type'] = $gBitSystem->verifyMimeType( $fileHash['source_file'] );
+ $fileHash['size'] = filesize( $fileHash['source_file'] );
+ $fileHash['dest_branch'] = dirname( $this->getSourceFile() ).'/';
+ $fileHash['name'] = $this->getField( 'file_name' );
+ if( $convertFunc = liberty_get_function( 'convert_colorspace' ) ) {
+ if( $ret = $convertFunc( $fileHash, $pColorSpace ) ) {
+ liberty_clear_thumbnails( $fileHash );
+ $sql = "UPDATE `".BIT_DB_PREFIX."liberty_files SET `file_size`=? WHERE `file_id` = ?";
+ $this->mDb->query( $sql, array( filesize( $fileHash['dest_file'] ), $this->mInfo['file_id'] ) );
+ $this->generateThumbnails();
+ }
+ }
+ }
+ return $ret;
+ }
+
+
+ function resizeOriginal( $pResizeOriginal ) {
+ global $gBitSystem;
+ if( $this->getField( 'file_name' ) || $this->load() ) {
+ $fileHash['source_file'] = $this->getSourceFile();
+ $fileHash['dest_base_name'] = preg_replace('/(.+)\..*$/', '$1', basename( $fileHash['source_file'] ) );
+ $fileHash['type'] = $gBitSystem->verifyMimeType( $fileHash['source_file'] );
+ $fileHash['size'] = filesize( $fileHash['source_file'] );
+ $fileHash['dest_branch'] = $this->getStorageBranch();
+ $fileHash['name'] = $this->getField( 'file_name' );
+ $fileHash['max_height'] = $fileHash['max_width'] = $pResizeOriginal;
+ // make a copy of the fileHash that we can compare output after processing
+ $preResize = $fileHash;
+ if( ($resizeFunc = liberty_get_function( 'resize' )) && ($resizeFile = $resizeFunc( $fileHash )) ) {
+ clearstatcache();
+ // Ack this is evil direct bashing of the liberty tables! XOXO spiderr
+ // should be a cleaner way eventually
+
+ // we need to update the souce_file in case it's changed from a non jpg to a jpg
+ if( $fileHash['name'] != $preResize['name'] ) {
+ $fileHash['source_file'] = dirname( $fileHash['source_file'] ).'/'.$fileHash['name'];
+ // make absolutely certain that we have 2 image files and that they are different, then remove the original
+ if( $fileHash['source_file'] != $preResize['source_file'] && is_file( $fileHash['source_file'] ) && is_file( $preResize['source_file'] ) ) {
+ @unlink( $preResize['source_file'] );
+ }
+ }
+ $details = $this->getImageDetails( $resizeFile );
+ // store all the values that might have changed due to the resize
+ $storeHash = array(
+ 'file_size' => filesize( $resizeFile ),
+ 'mime_type' => $details['mime'],
+ );
+ $this->mDb->associateUpdate( BIT_DB_PREFIX."liberty_files", $storeHash, array( 'file_id' => $this->mInfo['file_id'] ) );
+ //$query = "UPDATE `".BIT_DB_PREFIX."liberty_files` SET `file_size`=? WHERE `file_id`=?";
+ //$this->mDb->query( $query, array( $details['size'], $this->mInfo['file_id'] ) );
+ $query = "UPDATE `".BIT_DB_PREFIX."fisheye_image` SET `width`=?, `height`=? WHERE `content_id`=?";
+ $this->mDb->query( $query, array( $details['width'], $details['height'], $this->mContentId ) );
+ // if we've come this far, we can try removing the original if it's different to the resized image
+ // make absolutely certain that we have 2 image files and that they are different, then remove the original
+ if( $fileHash['source_file'] != $preResize['source_file'] && is_file( $fileHash['source_file'] ) && is_file( $preResize['source_file'] ) ) {
+ @unlink( $preResize['source_file'] );
+ }
+ } else {
+ $this->mErrors['resize'] = $fileHash['error'];
+ }
+ }
+ return (count($this->mErrors) == 0);
+ }
+
+
+ function generateThumbnails( $pResizeOriginal=NULL, $pImmediateRender=FALSE ) {
+ global $gBitSystem;
+ $ret = FALSE;
+ // LibertyMime will take care of thumbnail generation of the offline thumbnailer is not active
+ if( $gBitSystem->isFeatureActive( 'liberty_offline_thumbnailer' ) && !$pImmediateRender ) {
+ $query = "DELETE FROM `".BIT_DB_PREFIX."liberty_process_queue`
+ WHERE `content_id`=?";
+ $this->mDb->query( $query, array( $this->mContentId ) );
+ $query = "INSERT INTO `".BIT_DB_PREFIX."liberty_process_queue`
+ (`content_id`, `queue_date`, `processor_parameters`) VALUES (?,?,?)";
+ $this->mDb->query( $query, array( $this->mContentId, $gBitSystem->getUTCTime(), serialize( array( 'resize_original' => $pResizeOriginal ) ) ) );
+ } else {
+ $ret = $this->renderThumbnails();
+ }
+ return $ret;
+ }
+
+
+ function renderThumbnails( $pThumbSizes=NULL ) {
+ global $gBitSystem;
+ if( $this->getField( 'file_name' ) || $this->load() ) {
+ $fileHash['source_file'] = $this->getSourceFile();
+ $fileHash['type'] = $gBitSystem->verifyMimeType( $fileHash['source_file'] );
+ $fileHash['size'] = filesize( $fileHash['source_file'] );
+ $fileHash['dest_branch'] = $this->getStorageBranch( $fileHash );
+ $fileHash['name'] = $this->getField( 'file_name' );
+ $fileHash['thumbnail_sizes'] = $pThumbSizes;
+ // just generate thumbnails
+ liberty_generate_thumbnails( $fileHash );
+ if( !empty( $fileHash['error'] ) ) {
+ $this->mErrors['thumbnail'] = $fileHash['error'];
+ }
+ }
+ return( count($this->mErrors) == 0 );
+ }
+
+ function getStorageUrl( $pParamHash = array() ) {
+ $pParamHash['sub_dir'] = $this->getParameter( $pParamHash, 'sub_dir', liberty_mime_get_storage_sub_dir_name( array( 'type'=>$this->getField( 'mime_type' ), 'name'=>$this->getField('file_name') ) ) );
+ $pParamHash['user_id'] = $this->getParameter( $pParamHash, 'user_id', $this->getField('user_id') );
+ return parent::getStorageUrl( $pParamHash ).$this->getParameter( $pParamHash, 'attachment_id', $this->getField('attachment_id') ).'/';
+ }
+
+ function getStorageBranch( $pParamHash = array() ) {
+ $pParamHash['sub_dir'] = $this->getParameter( $pParamHash, 'sub_dir', liberty_mime_get_storage_sub_dir_name( array( 'type'=>$this->getField( 'mime_type' ), 'name'=>$this->getField('file_name') ) ) );
+ $pParamHash['user_id'] = $this->getParameter( $pParamHash, 'user_id', $this->getField('user_id') );
+ return parent::getStorageBranch( $pParamHash ).$this->getParameter( $pParamHash, 'attachment_id', $this->getField('attachment_id') ).'/';
+ }
+
+ function getStoragePath( $pParamHash, $pRootDir=NULL ) {
+ $pParamHash['sub_dir'] = liberty_mime_get_storage_sub_dir_name( array( 'type'=>BitBase::getParameter( $pParamHash, 'mime_type', $this->getField( 'mime_type' ) ), 'name'=>BitBase::getParameter( $pParamHash, 'file_name', $this->getField('file_name') ) ) );
+ $pParamHash['user_id'] = $this->getParameter( $pParamHash, 'user_id', $this->getField('user_id') );
+ return parent::getStoragePath( $pParamHash ).$this->getParameter( $pParamHash, 'attachment_id', $this->getField('attachment_id') ).'/';
+ }
+
+ function getPreviewHash() {
+ return $this->mInfo;
+ }
+
+ // Get resolution, etc
+ function getImageDetails($pFilePath = NULL) {
+ $info = array();
+ if( file_exists( $pFilePath ) ) {
+ $checkFiles = array( $pFilePath, dirname( $pFilePath ).'/original.jpg' );
+ } else {
+ $sourceFile = $this->getSourceFile();
+ $checkFiles = array( $sourceFile );
+ // was an original file created?
+ $originalFile = dirname( $sourceFile ).'/original.jpg';
+ if( file_exists( $originalFile ) && !is_link( $originalFile ) ) {
+ $checkFiles[] = $originalFile;
+ }
+ }
+
+ foreach( $checkFiles as $cf ) {
+ if ($cf && file_exists( $cf ) && filesize( $cf ) ) {
+ if( $imageSize = getimagesize( rtrim( $cf ) ) ) {
+ $info = $imageSize;
+ $info['width'] = $info[0];
+ $info['height'] = $info[1];
+ $info['size'] = filesize( $cf );
+ break;
+ }
+ }
+ }
+ return $info;
+ }
+
+ function getWidth() {
+ if( !isset( $this->mInfo['width'] ) ) {
+ $this->mInfo = array_merge( $this->mInfo, $this->getImageDetails() );
+ }
+ return $this->getField('width');
+ }
+
+ function getHeight() {
+ if( !isset( $this->mInfo['width'] ) ) {
+ $this->mInfo = array_merge( $this->mInfo, $this->getImageDetails() );
+ }
+ return $this->getField('height');
+ }
+
+ /**
+ * Returns include file that will setup vars for display
+ * @return the fully specified path to file to be included
+ */
+ function getRenderFile() {
+ return FISHEYE_PKG_INCLUDE_PATH.'display_fisheye_image_inc.php';
+ }
+
+ /**
+ * Returns template file used for display
+ * @return the fully specified path to file to be included
+ */
+ function getRenderTemplate() {
+ return 'bitpackage:fisheye/view_image.tpl';
+ }
+
+ /**
+ * Function that returns link to display a piece of content
+ * @param pImageId id of gallery to link
+ * @param pParamHash if a string, it is assumed to be the size, if an array, it is assumed to be a mInfo hash
+ * @return the url to display the gallery.
+ */
+ public static function getDisplayUrlFromHash( &$pParamHash ) {
+ $ret = '';
+ $size = (!empty( $pParamHash['size'] ) && is_string( $pParamHash['size'] ) && isset( $pParamHash['thumbnail_url'][$pParamHash['size']] ) ) ? $pParamHash['size'] : NULL ;
+
+ global $gBitSystem;
+ if( @BitBase::verifyId( $pParamHash['image_id'] ) ) {
+ if( $gBitSystem->isFeatureActive( 'pretty_urls' ) ) {
+ $ret = FISHEYE_PKG_URL.'image/'.$pParamHash['image_id'];
+ if( !empty( $pParamHash['gallery_path'] ) ) {
+ $ret .= $pParamHash['gallery_path'];
+ }
+ if( $size ) {
+ $ret .= '/'.$size;
+ }
+ } else {
+ $ret = FISHEYE_PKG_URL.'view_image.php?image_id='.$pParamHash['image_id'];
+ if( !empty( $this ) && !empty( $pParamHash['gallery_path'] ) ) {
+ $ret .= '&gallery_path='.$pParamHash['gallery_path'];
+ }
+ if( $size ) {
+ $ret .= '&size='.$size;
+ }
+ }
+ } elseif( @BitBase::verifyId( $pParamHash['content_id'] ) ) {
+ $ret = FISHEYE_PKG_URL.'view_image.php?content_id='.$pParamHash['content_id'];
+ }
+ return $ret;
+ }
+
+ /**
+ * Function that returns link to display an image
+ * @return the url to display the gallery.
+ */
+ public function getDisplayUrl() {
+ $info = &$this->mInfo;
+ $info['image_id'] = $this->mImageId;
+ $info['gallery_path'] = $this->mGalleryPath;
+ return static::getDisplayUrlFromHash( $info );
+ }
+
+ /**
+ * Function that returns link to display an image
+ * Used to display thumbnails for navigation bar
+ * @param pImageId id of image to link
+ * @return the url to display the image.
+ */
+ public function getImageUrl( $pImageId ) {
+ $info = array( 'image_id' => $pImageId );
+ return static::getDisplayUrlFromHash( $info );
+ }
+
+ /**
+ * Generate a valid display link for the Blog
+ *
+ * @param object PostId of the item to use
+ * @param array Not used
+ * @return object Fully formatted html link for use by Liberty
+ */
+ static function getDisplayLinkFromHash( &$pParamHash, $pTitle=NULL, $pAnchor=NULL ) {
+ global $gBitSystem;
+
+ $pTitle = trim( $pTitle );
+
+ if( empty( $pTitle ) ) {
+ $pTitle = FisheyeImage::getTitleFromHash( $pParamHash );
+ }
+
+ $ret = $pTitle;
+ if( $gBitSystem->isPackageActive( 'fisheye' ) ) {
+ $ret = '<a title="'.$pTitle.'" href="'.FisheyeImage::getDisplayUrlFromHash( $pParamHash ).'">'.$pTitle.'</a>';
+ }
+ return $ret;
+ }
+
+ static public function getTitleFromHash( &$pHash, $pDefault=TRUE ) {
+ $ret = trim( parent::getTitleFromHash( $pHash, $pDefault ) );
+ if( empty( $ret ) && $pDefault ) {
+ $storage = (!empty( $this ) && !empty( $this->mStorage ) ? current( $this->mStorage ) : NULL);
+ if( !empty( $storage['file_name'] ) ) {
+ $ret = $storage['file_name'];
+ } else {
+ global $gLibertySystem;
+ $ret = $gLibertySystem->getContentTypeName( $pHash['content_type_guid'] );
+ if( !empty( $pHash['image_id'] ) ) {
+ $ret .= " ".$pHash['image_id'];
+ }
+ }
+ }
+ return $ret;
+ }
+
+ public function getTitle() {
+ $ret = NULL;
+ if( $this->isValid() ) {
+ $ret = self::getTitleFromHash( $this->mInfo );
+ }
+ return $ret;
+ }
+
+
+ function getThumbnailContentId() {
+ return( $this->mContentId );
+ }
+
+ function getThumbnailUrl( $pSize = 'small', $pInfoHash = NULL, $pSecondaryId = NULL, $pDefault=TRUE ) {
+ $ret = NULL;
+ if( $this->isValid() && isset( $this->mInfo['thumbnail_url'][$pSize] ) ) {
+ $ret = $this->mInfo['thumbnail_url'][$pSize];
+ }
+ return $ret;
+ }
+
+ public static function getThumbnailUrlFromHash( &$pParamHash, $pSize = 'small', $pSecondaryId = NULL, $pDefault=TRUE ) {
+ $ret = NULL;
+ if( isset( $pParamHash['thumbnail_url'][$pSize] ) ) {
+ $ret = $pParamHash['thumbnail_url'][$pSize];
+ }
+ return $ret;
+ }
+
+ function expunge($pExpungeAttachment = TRUE) {
+ if( $this->isValid() ) {
+ $this->StartTrans();
+ $query = "DELETE FROM `".BIT_DB_PREFIX."fisheye_gallery_image_map` WHERE `item_content_id` = ?";
+ $rs = $this->mDb->query($query, array( $this->mContentId ));
+ $query = "UPDATE `".BIT_DB_PREFIX."fisheye_gallery` SET `preview_content_id`=NULL WHERE `preview_content_id` = ?";
+ $rs = $this->mDb->query($query, array( $this->mContentId ));
+ $query = "DELETE FROM `".BIT_DB_PREFIX."fisheye_image` WHERE `content_id` = ?";
+ $rs = $this->mDb->query($query, array( $this->mContentId ));
+ if( LibertyMime::expunge($pExpungeAttachment) ) {
+ $this->CompleteTrans();
+ $this->mImageId = NULL;
+ $this->mContentId = NULL;
+ } else {
+ $this->mDb->RollbackTrans();
+ }
+ }
+ return( count( $this->mErrors ) == 0 );
+ }
+
+ function expungingAttachment($pAttachmentId, $pContentIdArray) {
+ foreach ($pContentIdArray as $id) {
+ $this->mContentId = $id;
+ // Vital that we call LibertyMime::expunge with false since the attachment is already being deleted.
+ $this->expunge(FALSE);
+ }
+ }
+
+ function isValid() {
+ return( @$this->verifyId( $this->mImageId ) || @$this->verifyId( $this->mContentId ) );
+ }
+
+ function imageExistsInDatabase() {
+ $ret = FALSE;
+ if( $this->isValid() && $this->mImageId ) {
+ $query = "SELECT COUNT(`image_id`)
+ FROM `".BIT_DB_PREFIX."fisheye_image`
+ WHERE `image_id` = ?";
+
+ $bindVars = array($this->mImageId);
+
+ if($this->mDb->getOne($query, $bindVars) > 0){
+ $ret = TRUE;
+ }
+
+ }
+ return $ret;
+ }
+
+
+ function getList( &$pListHash ) {
+ global $gBitUser,$gBitSystem;
+
+ LibertyContent::prepGetList( $pListHash );
+
+ $ret = $bindVars = array();
+ $distinct = '';
+ $select = '';
+ $whereSql = '';
+ $joinSql = '';
+
+ if( @$this->verifyId( $pListHash['user_id'] ) ) {
+ $whereSql .= " AND lc.`user_id` = ? ";
+ $bindVars[] = $pListHash['user_id'];
+ } elseif( !empty( $pListHash['recent_users'] )) {
+ $distinct = " DISTINCT ON ( lc.created/86400, uu.`user_id` ) ";
+ $pListHash['sort_mode'] = 'uu.user_id_desc';
+ }
+
+ if( @$this->verifyId( $pListHash['gallery_id'] ) ) {
+ $whereSql .= " AND fg.`gallery_id` = ? ";
+ $bindVars[] = $pListHash['gallery_id'];
+ }
+
+ if( !empty( $pListHash['search'] ) ) {
+ $whereSql .= " AND UPPER(lc.`title`) LIKE ? ";
+ $bindVars[] = '%'.strtoupper( $pListHash['search'] ).'%';
+ }
+
+ if( !empty( $pListHash['max_age'] ) && is_numeric( $pListHash['max_age'] ) ) {
+ $whereSql .= " AND lc.`created` > ? ";
+ $bindVars[] = $pListHash['max_age'];
+ }
+
+ $this->getServicesSql( 'content_user_collection_function', $selectSql, $joinSql, $whereSql, $bindVars, $this, $pListHash );
+
+ $orderby = '';
+ if( !empty( $pListHash['recent_images'] )) {
+ // get images from recent user truncated by day. This is necessary because DISTINCT ON expressions must match initial ORDER BY expressions
+ $distinct = " DISTINCT ON ( lc.`created`/86400, uu.`user_id` ) ";
+ $orderby = " ORDER BY lc.`created`/86400 DESC, uu.`user_id`";
+ } elseif ( !empty( $pListHash['sort_mode'] ) ) {
+ //converted in prepGetList()
+ $orderby = " ORDER BY ".$this->mDb->convertSortmode( $pListHash['sort_mode'] )." ";
+ }
+
+ $this->getServicesSql( 'content_list_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
+
+ if( !empty( $whereSql ) ) {
+ $whereSql = substr_replace( $whereSql, ' WHERE ', 0, 4 );
+ }
+
+ $thumbSize = (!empty( $pListHash['size'] ) ? $pListHash['size'] : 'avatar' );
+
+ $query = "SELECT $distinct fi.`image_id` AS `hash_key`, fi.*, lf.*, la.attachment_id, lc.*, fg.`gallery_id`, uu.`login`, uu.`real_name` $select $selectSql
+ FROM `".BIT_DB_PREFIX."fisheye_image` fi
+ INNER JOIN `".BIT_DB_PREFIX."liberty_attachments` la ON(la.`content_id`=fi.`content_id`)
+ INNER JOIN `".BIT_DB_PREFIX."liberty_files` lf ON(la.`foreign_id`=lf.`file_id`)
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON(fi.`content_id` = lc.`content_id`)
+ INNER JOIN `".BIT_DB_PREFIX."users_users` uu ON(uu.`user_id` = lc.`user_id`) $joinSql
+ LEFT OUTER JOIN `".BIT_DB_PREFIX."fisheye_gallery_image_map` tfgim2 ON(tfgim2.`item_content_id`=lc.`content_id`)
+ LEFT OUTER JOIN `".BIT_DB_PREFIX."fisheye_gallery` fg ON(fg.`content_id`=tfgim2.`gallery_content_id`)
+ $whereSql $orderby";
+ if( $rs = $this->mDb->query( $query, $bindVars, $pListHash['max_records'], $pListHash['offset'], $pListHash['query_cache_time'] ) ) {
+ while( $row = $rs->fetchRow() ) {
+ // legacy table data was named storage_path and included a partial path. strip out any path just in case
+ $row['file_name'] = basename( $row['file_name'] );
+ $ret[$row['hash_key']] = $row;
+ $imageId = $row['image_id'];
+ if( empty( $pListHash['no_thumbnails'] ) ) {
+ $ret[$imageId]['display_url'] = static::getDisplayUrlFromHash( $row );
+ $ret[$imageId]['has_machine_name'] = $this->isMachineName( $ret[$imageId]['title'] );
+ $ret[$imageId]['source_url'] = $this->getStorageUrl( $row ).$row['file_name'];
+ $ret[$imageId]['thumbnail_url'] = liberty_fetch_thumbnail_url( array(
+ 'source_file' => $this->getSourceFile( $row ),
+ 'default_image' => FISHEYE_PKG_URL.'image/generating_thumbnails.png',
+ 'size' => $thumbSize,
+ 'type' => $row['mime_type'],
+ ));
+ }
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * isCommentable
+ *
+ * @access public
+ * @return TRUE on success, FALSE on failure
+ */
+ function isCommentable() {
+ global $gGallery;
+
+ // if we have a loaded gallery, we just use that to work out if we can add comments to this image
+ if( is_object( $gGallery ) ) {
+ return $gGallery->isCommentable();
+ }
+
+ $ret = FALSE;
+ if( $parents = $this->getParentGalleries() ) {
+ // @TODO: No idea how to work out if you can add a comment to this image
+ // for now we'll take the mGalleryPath and use that gallery
+ $gal = current( $parents );
+ $query = "SELECT `pref_value` FROM `".BIT_DB_PREFIX."liberty_content_prefs` WHERE `content_id` = ? AND `pref_name` = ?";
+ $ret = ( $this->mDb->getOne( $query, array( $gal['content_id'], 'allow_comments' )) == 'y' );
+ }
+ return $ret;
+ }
+
+ public static function getServiceKey() {
+ return 'fisheye';
+ }
+}
+
+?>
diff --git a/includes/classes/FisheyeRemote.php b/includes/classes/FisheyeRemote.php
new file mode 100644
index 0000000..ec69114
--- /dev/null
+++ b/includes/classes/FisheyeRemote.php
@@ -0,0 +1,351 @@
+<?php
+/**
+ * Gallery2 Remote support for fisheye
+ *
+ * @package fisheye
+ * @version $Header$
+ * @author spider <spider@steelsun.com>
+ * @author tylerbello <tylerbello@gmail.com>
+ */
+
+// +----------------------------------------------------------------------+
+// | Copyright (c) 2004, bitweaver.org
+// +----------------------------------------------------------------------+
+// | All Rights Reserved. See below for details and a complete list of authors.
+// | Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See http://www.gnu.org/copyleft/lesser.html for details
+// |
+// | For comments, please use phpdocu.sourceforge.net documentation standards!!!
+// | -> see http://phpdocu.sourceforge.net/
+// +----------------------------------------------------------------------+
+// | Authors: spider <spider@steelsun.com>
+// +----------------------------------------------------------------------+
+
+define( 'FEG2REMOTE_SUCCESS', 0 );
+
+define( 'FEG2REMOTE_PROTOCOL_MAJOR_VERSION_INVALID', 101 );
+define( 'FEG2REMOTE_PROTOCOL_MINOR_VERSION_INVALID', 102 );
+define( 'FEG2REMOTE_PROTOCOL_VERSION_FORMAT_INVALID', 103 );
+define( 'FEG2REMOTE_PROTOCOL_VERSION_MISSING', 104 );
+
+define( 'FEG2REMOTE_PASSWORD_WRONG', 201 );
+define( 'FEG2REMOTE_LOGIN_MISSING', 202 );
+
+define( 'FEG2REMOTE_UNKNOWN_COMMAND', 301 );
+define( 'FEG2REMOTE_MISSING_ARGUMENTS', 302 );
+
+define( 'FEG2REMOTE_NO_ADD_PERMISSION', 401 );
+define( 'FEG2REMOTE_NO_FILENAME', 402 );
+define( 'FEG2REMOTE_UPLOAD_PHOTO_FAIL', 403 );
+define( 'FEG2REMOTE_NO_WRITE_PERMISSION', 404 );
+define( 'FEG2REMOTE_NO_VIEW PERMISSION', 405 );
+
+define( 'FEG2REMOTE_NO_CREATE_ALBUM_PERMISSION', 501 );
+define( 'FEG2REMOTE_CREATE_ALBUM_FAILED', 502 );
+define( 'FEG2REMOTE_MOVE_ALBUM_FAILED', 503 );
+define( 'FEG2REMOTE_ROTATE_IMAGE_FAILED', 504 );
+
+/**
+ * @package fisheye
+ */
+class FisheyeRemote {
+
+ public $mResponse = array();
+
+ public $mSubGalIdx = 1;
+
+ function getApiVersion() {
+ return '2.14';
+ }
+
+
+ // separate out pPostData and pParamhash data since some plugins can populate _POST['g2_form'] and _GET['g2_form'] differently.
+ // weird but true. ubermind is an example
+ function processRequest( $pGetData, $pPostData ) {
+ $pData = array_merge($pGetData, $pPostData); //Some programs (galleryexport) pass both post and get...and the cmd can be in either get or post
+
+ if(!empty($pData)){
+ switch ($pData['cmd']) {
+ case 'login':
+ $response = $this->cmdLogin( $pPostData );
+ break;
+
+ case 'fetch-albums':
+ $response = $this->cmdFetchAlbums( $pPostData );
+ break;
+
+ case 'fetch-albums-prune':
+ $response = $this->cmdFetchAlbums( $pPostData );
+ break;
+
+ case 'add-item':
+ $response = $this->cmdAddItem( $pPostData );
+ break;
+
+ case 'album-properties':
+ // not implemented yet
+ break;
+
+ case 'new-album':
+ $response = $this->cmdNewAlbum( $pPostData );
+ break;
+
+ case 'fetch-album-images':
+ // not implemented yet
+ break;
+
+ case 'move-album':
+ // not implemented yet
+ break;
+
+ case 'increment-view-count':
+ // not implemented yet
+ break;
+
+ case 'image-properties':
+ // not implemented yet
+ break;
+
+ case 'no-op':
+ $response = $this->cmdNoOp( $pPostData );
+ // not implemented yet
+ break;
+
+ default:
+ $response = $this->createResponse( FEG2REMOTE_UNKNOWN_COMMAND, "Command unknown: ".$pGetData['cmd'] );
+ break;
+ }
+ } else {
+ $response = $this->createResponse( FEG2REMOTE_UNKNOWN_COMMAND, "No command received." );
+ }
+
+ if( !empty( $response ) ) {
+ print $this->sendResponse( $response );
+ }
+ }
+
+
+ function cmdNoOp( $pParamHash ) {
+ global $gBitUser;
+
+ $response = $this->createResponse( FEG2REMOTE_SUCCESS, 'No-op successful' );
+ return $response;
+ }
+
+ function cmdLogin( $pParamHash ) {
+ global $gBitUser, $gBitSystem;
+ $url = $gBitUser->login( $pParamHash['uname'], $pParamHash['password'] );
+ if( $gBitUser->isRegistered() ) {
+ /*
+ $cookieTime = ( int )( time() + $gBitSystem->getConfig( 'users_remember_time', 86400 ));
+ $cookiePath = $gBitSystem->getConfig( 'cookie_path', BIT_ROOT_URL );
+ $cookieDomain = $gBitSystem->getConfig( 'cookie_domain', "" );
+ setcookie( 'GALLERYSID', session_id(), $cookieTime, $cookiePath, $cookieDomain );
+ */
+ $response = $this->createResponse( FEG2REMOTE_SUCCESS, 'Login successful.', array( 'server_version' => $this->getApiVersion() ) );
+ } else {
+ $response = $this->createResponse( FEG2REMOTE_PASSWORD_WRONG, 'Invalid username or password' );
+ }
+ return $response;
+ }
+
+ // Recursively traverses a multi-dimensional array of galleries
+ function traverseGalleries( &$pGalHash, &$pResponse ) {
+ global $gBitUser;
+
+ // Albums don't like being 0 indexed
+ $this->mSubGalIdx = 0;
+
+ // the lightroom client is dumb, and can only handle one 0 level parent
+ if( stripos( $_SERVER['HTTP_USER_AGENT'], 'lightroom' ) !== FALSE ) {
+ $this->mSubGalIdx++;
+ $pResponse['album.parent.' . $this->mSubGalIdx] = 0;
+ $pResponse['album.name.' . $this->mSubGalIdx] = 1;
+ $pResponse['album.title.' . $this->mSubGalIdx] = tra( 'Select a Gallery' );
+ $pResponse['album.perms.add.' . $this->mSubGalIdx] = 'false';
+ $pResponse['album.perms.write.' . $this->mSubGalIdx] = 'false';
+ $pResponse['album.perms.del_alb.' . $this->mSubGalIdx] = 'false';
+ $pResponse['album.perms.create_sub.' . $this->mSubGalIdx] = 'true';
+ }
+
+ return $this->traverseSubGalleries( $pGalHash, $pResponse, 1 );
+ }
+
+ /**
+ * Function that returns link to display a piece of content
+ * @param $pGalHash branch of gallery information from FisheyeGallery::getTree
+ * @param $pResponse aggregate string containing response array
+ * @param $pParentRandom depth of pGalHash - this is used to non-definitively uniquify album.parent and album.name entries
+ * @return the url to display the gallery.
+ */
+ function traverseSubGalleries( &$pGalHash, &$pResponse, $pParentRandom ) {
+ global $gBitUser;
+ foreach( $pGalHash as $key=>$gallery) {
+ $this->mSubGalIdx++;
+
+ // Any number greater than 2 digits crashes iPhoto2Gallery
+ $randomizer = str_pad( rand( 1, 99 ), 2, '0' );
+ if($gallery['content']['level'] != 0){
+ // Fisheye allows directories to below to multiple parents - not in gallery. This confuses some clients
+ // We pad with a random number for uniqueness
+ $pResponse['album.parent.' . $this->mSubGalIdx] = $gallery['content']['cb_gallery_content_id'].$pParentRandom;
+ } else {
+ // the lightroom client is dumb, and can only handle one 0 level parent
+ if( stripos( $_SERVER['HTTP_USER_AGENT'], 'lightroom' ) !== FALSE ) {
+ $pResponse['album.parent.' . $this->mSubGalIdx] = 1;
+ } else {
+ $pResponse['album.parent.' . $this->mSubGalIdx] = 0;
+ }
+ }
+ // append pParentRandom to make .name probably unique since Fisheye can handle one gallery linked to multiple parents
+ $pResponse['album.name.' . $this->mSubGalIdx] = $gallery['content']['content_id'].$randomizer;
+ $pResponse['album.title.' . $this->mSubGalIdx] = $this->cleanResponseValue( $gallery['content']['title'] );
+
+ if( !empty( $gallery['content']['data'] ) ) {
+ $pResponse['album.summary.' . $this->mSubGalIdx] = $gallery['content']['data'];
+ $pResponse['album.info.extrafields.' . $this->mSubGalIdx] = "Summary";
+ }
+
+ $pResponse['album.perms.add.' . $this->mSubGalIdx] = 'true';
+ $pResponse['album.perms.write.' . $this->mSubGalIdx] = 'true';
+ $pResponse['album.perms.del_alb.' . $this->mSubGalIdx] = 'true';
+ $pResponse['album.perms.create_sub.' . $this->mSubGalIdx] = 'true';
+
+ if( !empty( $gallery['children'] ) ) {
+ $this->traverseSubGalleries($gallery['children'],$pResponse, $randomizer );
+ }
+ }
+ $ret = $this->mSubGalIdx;
+ return $ret;
+ }
+
+ function cmdFetchAlbums( $pParamHash ) {
+ require_once( FISHEYE_PKG_CLASS_PATH.'FisheyeGallery.php' );
+ global $gBitUser;
+ if( $gBitUser->isRegistered() ) {
+ $treeGallery = new FisheyeGallery();
+ $listHash['user_id'] = $gBitUser->mUserId;
+ if( $galleryList = $treeGallery->getTree( $listHash, array( 'name' => "gallery_id", 'id' => "gallerylist", 'item_attributes' => array( 'class'=>'listingtitle' ) ) ) ) {
+ $galResponse = array();
+ $galleryCount = $this->traverseGalleries( $galleryList, $galResponse );
+ $galResponse['album_count'] = $galleryCount;
+ $galResponse['can_create_root'] = 'true';
+ $response = $this->createResponse( FEG2REMOTE_SUCCESS, 'Gallery list successful', $galResponse );
+ } else {
+ // perhaps we should make at least on gallery at this point?
+ $response = $this->createResponse( FEG2REMOTE_SUCCESS, 'No galleries', array( 'album_count' => 0 ) );
+ }
+ } else {
+ $response = $this->createResponse( FEG2REMOTE_PASSWORD_WRONG, 'Application not logged in' );
+ }
+ return $response;
+ }
+
+
+ function cmdAddItem( $pParamHash ) {
+ $response = array();
+
+ $uploadFile = (!empty( $_FILES['g2_userfile'] ) ? $_FILES['g2_userfile'] : NULL);
+
+ if( empty( $pParamHash['set_albumName'] ) ) {
+ $response = $this->createResponse( CREATE_ALBUM_FAILED , 'No gallery specified' );
+ } elseif( empty( $uploadFile ) || empty( $uploadFile['size'] ) ) {
+ $response = $this->createResponse( FEG2REMOTE_NO_FILENAME, 'No image uploaded' );
+ } else {
+ $storeHash['title'] = !empty( $pParamHash['force_filename'] ) ? $pParamHash['force_filename'] : NULL;
+ $storeHash['summary'] = !empty( $pParamHash['extrafield.Summary'] ) ? $pParamHash['extrafield.Summary'] : NULL;
+ $storeHash['edit'] = !empty( $pParamHash['extrafield.Description'] ) ? $pParamHash['extrafield.Description'] : NULL;
+
+ require_once (FISHEYE_PKG_INCLUDE_PATH.'upload_inc.php');
+
+ $parentGallery = new FisheyeGallery();
+ if( $parentGallery = $parentGallery->lookup(array('content_id' => $pParamHash['set_albumName'] ) ) ) {
+ $parentGallery->load();
+ $storeHash['gallery_additions'] = array($parentGallery->mGalleryId);
+ }
+ if( $errors = fisheye_store_upload( $uploadFile , $storeHash ) ){
+ $response = $this->createResponse( FEG2REMOTE_UPLOAD_PHOTO_FAIL, 'Export Failed' );
+ } else {
+ $response = $this->createResponse( FEG2REMOTE_SUCCESS, 'Image added', array( 'item_name'=>$uploadFile['name'] ) );
+ }
+ }
+
+ return $response;
+ }
+
+ function cmdNewAlbum( $pParamHash ) {
+ global $gBitUser;
+ $response = array();
+
+ if( empty( $pParamHash['newAlbumTitle'] ) ) {
+ $pParamHash['newAlbumTitle'] = $gBitUser->getTitle()."'s Gallery";
+ }
+
+ $storeHash['title'] = !empty($pParamHash['newAlbumTitle']) ? $pParamHash['newAlbumTitle'] : '';
+ $storeHash['edit'] = !empty($pParamHash['newAlbumDesc']) ? $pParamHash['newAlbumDesc'] : '';
+ $gallery = new FisheyeGallery();
+ $gallery->store( $storeHash );
+
+ if($pParamHash['set_albumName']){
+ $parentGallery = new FisheyeGallery();
+ if( $parentGallery = $parentGallery->lookup(array('content_id' => $pParamHash['set_albumName'] ) ) ) {
+ $parentGallery->load();
+ $gallery->addToGalleries(array($parentGallery->mGalleryId));
+ }
+ }
+
+ $response = $this->createResponse( FEG2REMOTE_SUCCESS, 'Gallery created', array( 'album_name' => $storeHash['title'] ) );
+
+ return $response;
+ }
+
+ function sendResponse( $pResponse ) {
+ global $gBitUser;
+ print "#__GR2PROTO__\n";
+//error_log( "#__GR2PROTO__".' : '.$gBitUser->mUserId );
+ foreach ($pResponse as $k => $value) {
+ print "$k=$value\n";
+//error_log( "$k=$value" );
+ }
+ // must be last
+ print "auth_token=".$gBitUser->mTicket;
+//error_log( "auth_token=".$gBitUser->mTicket );
+//error_log( "#__end__" );
+ }
+
+
+ function createResponse( $pStatus, $pStatusText, $pExtra = NULL ) {
+ $ret = array();
+
+ // Each response must contain at least the keys: status and status_text.
+ $ret['status'] = $this->cleanResponseValue( $pStatus );
+ // translate the text response for i18n
+ $ret['status_text'] = $this->cleanResponseValue( tra( $pStatusText ) );
+ // tack on any additional responses
+ if( !empty( $pExtra ) && is_array( $pExtra ) ) {
+ foreach( $pExtra as $k => $value ) {
+ $ret[$this->cleanResponseKey( $k )] = $this->cleanResponseValue( $value );
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * This will clean up the response value to make sure it is in an acceptable format for the remote client.
+ * Gallery apparently is very particular about the manner in which this data is cleaned up, and must be done
+ * in this specific order.
+ */
+ function cleanResponseValue( $pValue ) {
+ $pValue = str_replace('\\', '\\\\', $pValue);
+ $pValue = str_replace("\r\n", '\n', $pValue);
+ $pValue = str_replace(array("\r", "\n", "\t"), array('\n', '\n', '\t'), $pValue);
+ $pValue = str_replace(array('#', '!', '='), array('\\#', '\\!', '\\='), $pValue);
+ return $pValue;
+ }
+
+
+ function cleanResponseKey( $pKey ) {
+ return str_replace(array('#', '!', '=', ':'), array('\\#', '\\!', '\\=', '\\:'), $pKey);
+ }
+
+
+}
diff --git a/includes/display_fisheye_gallery_inc.php b/includes/display_fisheye_gallery_inc.php
new file mode 100644
index 0000000..f83d6e1
--- /dev/null
+++ b/includes/display_fisheye_gallery_inc.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * @package fisheye
+ * @subpackage functions
+ */
+
+$displayHash = array( 'perm_name' => 'p_fisheye_view' );
+$gContent->invokeServices( 'content_display_function', $displayHash );
+
+if (!empty($_REQUEST['page']) && is_numeric($_REQUEST['page'])) {
+ $page = $_REQUEST['page'];
+} else {
+ $page = 0;
+}
+
+if( $page > $gContent->getField( 'num_pages' ) ) {
+ $page = $gContent->getField( 'num_pages' );
+} elseif ($page < 1) {
+ $page = 1;
+}
+
+$imagesPerPage = $gContent->getField( 'rows_per_page' ) * $gContent->getField( 'cols_per_page', 10 );
+
+switch( $gContent->getLayout() ) {
+ case 'auto_flow':
+ $gBitThemes->loadCss( FISHEYE_PKG_PATH."css/div_layout.css", TRUE );
+ break;
+ case 'matteo':
+ $gBitThemes->loadCss( FISHEYE_PKG_PATH."gallery_view/matteo/mb_layout.css", TRUE );
+ $gBitThemes->loadAjax( 'jquery' );
+ $gBitThemes->loadJavascript( FISHEYE_PKG_PATH.'/gallery_views/matteo/mbGallery.js', FALSE, 500, FALSE );
+ $gBitThemes->loadJavascript( FISHEYE_PKG_PATH.'/gallery_views/matteo/mbGalleryBox.js', FALSE, 501, FALSE );
+ break;
+ case 'galleriffic':
+ $imagesPerPage = -1;
+ // Need to add options for different styles of layout
+ $gBitThemes->loadCss( FISHEYE_PKG_PATH."/gallery_views/galleriffic/css/galleriffic_style_1.css", TRUE );
+ $gBitThemes->loadAjax( 'jquery' );
+ $gBitThemes->loadJavascript( UTIL_PKG_PATH.'javascript/jquery/plugins/migrate/jquery.migrate.js', FALSE, 500, FALSE );
+ $gBitThemes->loadJavascript( FISHEYE_PKG_PATH.'/gallery_views/galleriffic/js/jquery.galleriffic.js', FALSE, 500, FALSE );
+ $gBitThemes->loadJavascript( FISHEYE_PKG_PATH.'/gallery_views/galleriffic/js/jquery.history.js', FALSE, 501, FALSE );
+ $gBitThemes->loadJavascript( FISHEYE_PKG_PATH.'/gallery_views/galleriffic/js/jquery.opacityrollover.js', FALSE, 502, FALSE );
+ $gBitThemes->loadJavascript( FISHEYE_PKG_PATH.'/gallery_views/galleriffic/gftop.js', FALSE, 503, FALSE );
+ break;
+}
+
+$imageOffset = $imagesPerPage * ($page-1);
+
+$gBitSmarty->assignByRef('pageCount', $page);
+$gBitSmarty->assignByRef('imagesPerPage', $imagesPerPage);
+$gBitSmarty->assignByRef('imageOffset', $imageOffset);
+$gBitSmarty->assignByRef('rows_per_page', $gContent->mInfo['rows_per_page']);
+$gBitSmarty->assign('cols_per_page', $gContent->getField( 'cols_per_page', 10 ) );
+
+$gContent->loadImages( $page, $imagesPerPage );
+$gContent->addHit();
+
+$gBitSystem->setBrowserTitle( $gContent->getTitle().' '.tra('Gallery') );
+$gBitSystem->display( $gContent->getRenderTemplate() , NULL, array( 'display_mode' => 'display' ));
diff --git a/includes/display_fisheye_image_inc.php b/includes/display_fisheye_image_inc.php
new file mode 100644
index 0000000..ae341e1
--- /dev/null
+++ b/includes/display_fisheye_image_inc.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * @package fisheye
+ * @subpackage functions
+ */
+
+if( !$gContent->isValid() ) {
+ $gBitSystem->fatalError( tra( "No image exists with the given ID" ) ,'error.tpl', '', HttpStatusCodes::HTTP_GONE );
+}
+
+$displayHash = array( 'perm_name' => 'p_fisheye_view' );
+$gContent->invokeServices( 'content_display_function', $displayHash );
+
+// Get the proper thumbnail size to display on this page
+if( empty( $_REQUEST['size'] )) {
+ $_REQUEST['size'] = $gBitSystem->getConfig( 'fisheye_image_default_thumbnail_size', FISHEYE_DEFAULT_THUMBNAIL_SIZE );
+}
+
+$gBitSystem->setBrowserTitle( $gContent->getTitle() );
+if( $gBitThemes->isAjaxRequest() ) {
+ $gBitSmarty->display( $gContent->getRenderTemplate() );
+} else {
+ $gBitSystem->display( $gContent->getRenderTemplate() , NULL, array( 'display_mode' => 'display' ));
+}
+
diff --git a/includes/gallery_lookup_inc.php b/includes/gallery_lookup_inc.php
new file mode 100644
index 0000000..b504585
--- /dev/null
+++ b/includes/gallery_lookup_inc.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * @package fisheye
+ * @subpackage functions
+ */
+
+global $gContent;
+
+$lookup = array();
+
+if( !$gContent = FisheyeGallery::lookup( $_REQUEST ) ) {
+ $gContent = new FisheyeGallery();
+ $galleryId = NULL;
+}
+
+if( !empty( $_REQUEST['gallery_path'] ) ) {
+ $gContent->setGalleryPath( $_REQUEST['gallery_path'] );
+} elseif( $gContent->isValid() && $parents = $gContent->getParentGalleries() ) {
+ $gal = current( $parents );
+ $gContent->setGalleryPath( '/'.$gal['gallery_id'] );
+}
+
+$gBitSmarty->assignByRef('gContent', $gContent);
+$gBitSmarty->assignByRef('galleryId', $gContent->mGalleryId);
+
diff --git a/includes/image_lookup_inc.php b/includes/image_lookup_inc.php
new file mode 100644
index 0000000..8de4b0e
--- /dev/null
+++ b/includes/image_lookup_inc.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * @version $Header$
+ * @package fisheye
+ * @subpackage functions
+ */
+
+global $gContent, $gGallery;
+
+
+if( $gContent = FisheyeImage::lookup( $_REQUEST ) ) {
+ // nothing to do. ::lookup will do a full load
+} else {
+ $gContent = new FisheyeImage();
+ $imageId = NULL;
+}
+
+if( !empty( $_REQUEST['gallery_path'] ) ) {
+ $_REQUEST['gallery_path'] = rtrim( $_REQUEST['gallery_path'], '/' );
+ $gContent->setGalleryPath( $_REQUEST['gallery_path'] );
+ $matches = array();
+ $tail = strrpos( $_REQUEST['gallery_path'], '/' );
+ $_REQUEST['gallery_id'] = substr( $_REQUEST['gallery_path'], $tail + 1 );
+}
+if( empty( $_REQUEST['gallery_id'] ) ) {
+ if( $parents = $gContent->getParentGalleries() ) {
+ $gal = current( $parents );
+ $gContent->setGalleryPath( '/'.$gal['gallery_id'] );
+ $_REQUEST['gallery_id'] = $gal['gallery_id'];
+ }
+}
+// the image is considered the primary content, however the gallery is useful
+if( !empty($_REQUEST['gallery_id']) && is_numeric($_REQUEST['gallery_id']) ) {
+ $gGallery = FisheyeGallery::lookup( $_REQUEST );
+ $gBitSmarty->assignByRef('gGallery', $gGallery);
+ $gBitSmarty->assignByRef('galleryId', $_REQUEST['gallery_id']);
+}
+
+// This user does not own this gallery and they have not been granted the permission to edit this gallery
+$gContent->verifyViewPermission();
+
+$gBitSmarty->assignByRef('gContent', $gContent);
+$gBitSmarty->assignByRef('imageId', $gContent->mImageId );
+
+
+?>
diff --git a/includes/upload_inc.php b/includes/upload_inc.php
new file mode 100644
index 0000000..90957fb
--- /dev/null
+++ b/includes/upload_inc.php
@@ -0,0 +1,360 @@
+<?php
+/**
+ * @package fisheye
+ * @subpackage functions
+ */
+
+
+
+/**
+ * fisheye_handle_upload
+ */
+function fisheye_handle_upload( &$pFiles ) {
+ global $gBitUser, $gContent, $gBitSystem, $fisheyeErrors, $fisheyeWarnings, $fisheyeSuccess, $gFisheyeUploads;
+
+ // first of all set the execution time for this process to unlimited
+ set_time_limit(0);
+
+ $upImages = array();
+ $upArchives = array();
+ $upErrors = array();
+ $upData = array();
+
+ $i = 0;
+ usort( $pFiles, 'fisheye_sort_uploads' );
+
+ foreach( array_keys( $pFiles ) as $key ) {
+ $pFiles[$key]['type'] = $gBitSystem->verifyMimeType( $pFiles[$key]['tmp_name'] );
+ if( preg_match( '/(^image|pdf|vnd)/i', $pFiles[$key]['type'] ) ) {
+ $upImages[$key] = $pFiles[$key];
+ // clone the request data so edit service values are passed into store process
+ $upData[$key] = $_REQUEST;
+ // add the form data for each upload
+ if( !empty( $_REQUEST['imagedata'][$i] ) ) {
+ array_merge( $upData[$key], $_REQUEST['imagedata'][$i] );
+ }
+ } elseif( !empty( $pFiles[$key]['tmp_name'] ) && !empty( $pFiles[$key]['name'] ) ) {
+ $upArchives[$key] = $pFiles[$key];
+ }
+ $i++;
+ }
+
+ $gallery_additions = array();
+
+ // No gallery was specified, let's try to find one or create one.
+ if( empty( $_REQUEST['gallery_additions'] ) ) {
+ if( $gBitUser->hasPermission( 'p_fisheye_create' )) {
+ $upData['gallery_additions'] = array( fisheye_get_default_gallery_id( $gBitUser->mUserId, $gBitUser->getDisplayName()."'s Gallery" ) );
+ } else {
+ $gBitSystem->fatalError( tra( "You don't have permissions to create a new gallery. Please select an existing one to insert your images to." ));
+ }
+ }
+
+ foreach( array_keys( $upArchives ) as $key ) {
+ $upErrors = fisheye_process_archive( $upArchives[$key], $gContent, TRUE );
+ }
+
+ foreach( array_keys( $upImages ) as $key ) {
+ // resize original if we the user requests it
+ if( !empty( $_REQUEST['resize'] ) ) {
+ $upImages[$key]['resize'] = $_REQUEST['resize'];
+ }
+ $upErrors = array_merge( $upErrors, fisheye_store_upload( $upImages[$key], $upData[$key], !empty( $_REQUEST['rotate_image'] )));
+ }
+
+ if( !is_object( $gContent ) || !$gContent->isValid() ) {
+ $gContent = new FisheyeGallery( $_REQUEST['gallery_additions'][0] );
+ $gContent->load();
+ }
+
+ if( !empty( $gFisheyeUploads ) ){
+ $_REQUEST['uploaded_objects'] = &$gFisheyeUploads;
+ $gContent->invokeServices( "content_post_upload_function", $_REQUEST );
+ }
+
+ return $upErrors;
+}
+
+
+/**
+ * fisheye_sort_upload
+ */
+function fisheye_sort_uploads( $a, $b ) {
+ return strnatcmp( $a['name'], $b['name'] );
+}
+
+/**
+ * fisheye_get_default_gallery_id
+ */
+function fisheye_get_default_gallery_id( $pUserId, $pNewName ) {
+ global $gBitUser;
+ $gal = new FisheyeGallery();
+ $getHash = array( 'user_id' => $pUserId, 'max_records' => 1, 'sort_mode' => 'created_desc', 'show_empty' => TRUE );
+ $upList = $gal->getList( $getHash );
+ if( !empty( $upList ) ) {
+ $ret = key( $upList );
+ } else {
+ $galleryHash = array( 'title' => $pNewName );
+ if( $gal->store( $galleryHash ) ) {
+ $ret = $gal->mGalleryId;
+ }
+ }
+
+ global $gContent;
+ if( $ret && (!is_object( $gContent ) || !$gContent->isValid()) ) {
+ $gContent = new FisheyeGallery( $ret );
+ $gContent->load();
+ }
+ return $ret;
+}
+
+/**
+ * fisheye_store_upload
+ */
+function fisheye_store_upload( &$pFileHash, $pImageData = array(), $pAutoRotate=TRUE ) {
+ global $gBitSystem, $gFisheyeUploads;
+ $ret = array();
+
+ // verifyMimeType to make sure we are working with the proper file type assumptions
+ $pFileHash['type'] = $gBitSystem->verifyMimeType($pFileHash['tmp_name']);
+ if( !empty( $pFileHash ) && ( $pFileHash['size'] > 0 ) && is_file( $pFileHash['tmp_name'] ) && fisheye_verify_upload_item( $pFileHash ) ) {
+ // make a copy for each image we need to store
+ $image = new FisheyeImage();
+ // Store/Update the image
+ $pImageData['_files_override'] = array( $pFileHash );
+ $pImageData['process_storage'] = STORAGE_IMAGE;
+ $pImageData['purge_from_galleries'] = TRUE;
+ // store the image
+ if( !$image->store( $pImageData ) ) {
+ $ret = $image->mErrors;
+ } else {
+ $pFileHash['content_id'] = $image->getField( 'content_id' );
+ $pFileHash['image_id'] = $image->getField( 'image_id' );
+ $image->load();
+ // play with image some more if user has requested it
+ if( $pAutoRotate ) {
+ $image->rotateImage( 'auto' );
+ }
+ $image->addToGalleries( BitBase::getParameter( $pImageData, 'gallery_additions' ) );
+ $gFisheyeUploads[] = $image;
+ }
+
+ // when we're using xupload, we need to remove temp files manually
+ @unlink( $pFileHash['tmp_name'] );
+ }
+ return $ret;
+}
+
+/**
+ * Recursively builds a tree where each directory represents a gallery, and files are assumed to be images.
+ */
+function fisheye_process_archive( &$pFileHash, &$pParentGallery, $pRoot=FALSE ) {
+ global $gBitSystem, $gBitUser;
+ $errors = array();
+
+ if( ( $destDir = liberty_process_archive( $pFileHash ) ) && ( !empty( $_REQUEST['process_archive'] ) || !$gBitUser->hasPermission( 'p_fisheye_upload_nonimages' ) ) ) {
+ if( empty( $pParentGallery ) && !is_file( $pFileHash['tmp_name'] ) ) {
+ $pParentGallery = new FisheyeGallery();
+ $galleryHash = array( 'title' => basename( $destDir ) );
+ if( !$pParentGallery->store( $galleryHash ) ) {
+ $errors = array_merge( $errors, array_values( $pParentGallery->mErrors ) );
+ }
+ global $gContent;
+ $gContent = &$pParentGallery;
+ }
+
+ if( !empty( $pParentGallery ) ) {
+ $pFileHash['gallery_id'] = $pParentGallery->getField( 'gallery_id' );
+ }
+ fisheye_process_directory( $destDir, $pParentGallery, $pRoot );
+ } else {
+ global $gBitUser;
+ if( $gBitUser->hasPermission( 'p_fisheye_upload_nonimages' ) ) {
+ $errors = array_merge( $errors, fisheye_store_upload( $pFileHash ));
+ } else {
+ $errors['upload'] = tra( 'Your upload could not be processed because it was determined to be a non-image and you only have permission to upload images.' );
+ }
+ }
+ return $errors;
+}
+
+if( !function_exists( 'fisheye_verify_upload_item' ) ) {
+// Possible override
+function fisheye_verify_upload_item( $pScanFile ) {
+ global $gBitUser;
+ return $gBitUser->hasPermission( 'p_fisheye_upload_nonimages' ) || preg_match( '/^video\/*/', $pScanFile['type'] ) || preg_match( '/^image\/*/', $pScanFile['type'] ) || preg_match( '/pdf/i', $pScanFile['type'] );
+}
+}
+
+/**
+ * Recursively builds a tree where each directory represents a gallery, and files are assumed to be images.
+ */
+function fisheye_process_directory( $pDestinationDir, &$pParentGallery, $pRoot=FALSE ) {
+ global $gBitSystem, $gBitUser;
+ $errors = array();
+ if( $archiveDir = opendir( $pDestinationDir ) ) {
+ $order = 100;
+ while( $fileName = readdir($archiveDir) ) {
+ $sortedNames[] = $fileName;
+ }
+ sort( $sortedNames );
+ foreach( $sortedNames as $fileName ) {
+ if( $fileName == 'Thumbs.db' ) {
+ unlink( "$pDestinationDir/$fileName" );
+ }
+ if( !preg_match( '/^\./', $fileName ) && ( $fileName != 'Thumbs.db' ) ) {
+ $mimeResults = $gBitSystem->verifyFileExtension( $pDestinationDir.'/'.$fileName );
+ $scanFile = array(
+ 'type' => $mimeResults[1],
+ 'name' => $fileName,
+ 'size' => filesize( "$pDestinationDir/$fileName" ),
+ 'tmp_name' => "$pDestinationDir/$fileName",
+ );
+
+ if( !empty( $_REQUEST['resize'] ) && is_numeric( $_REQUEST['resize'] ) ) {
+ $scanFile['max_height'] = $scanFile['max_width'] = $_REQUEST['resize'];
+ }
+
+ if( is_dir( $pDestinationDir.'/'.$fileName ) ) {
+ if( $fileName == '__MACOSX' ) {
+ // Mac OS resources file
+ unlink_r( $pDestinationDir.'/'.$fileName );
+ } else {
+ // We found a new Gallery!
+ $newGallery = new FisheyeGallery();
+ $galleryHash = array( 'title' => str_replace( '_', ' ', $fileName ) );
+ if( $newGallery->store( $galleryHash ) ) {
+ if( $pRoot ) {
+ $newGallery->addToGalleries( $_REQUEST['gallery_additions'] );
+ }
+ if( is_object( $pParentGallery ) ) {
+ $pParentGallery->addItem( $newGallery->mContentId, $order );
+ }
+ //recurse down in!
+ $errors = array_merge( $errors, fisheye_process_archive( $scanFile, $newGallery ) );
+ } else {
+ $errors = array_merge( $errors, array_values( $newGallery->mErrors ) );
+ }
+ }
+ } elseif( preg_match( '/.+\/*zip*/', $scanFile['type'] ) ) {
+ //recurse down in!
+ $errors = array_merge( $errors, fisheye_process_archive( $scanFile, $pParentGallery ) );
+ } elseif( fisheye_verify_upload_item( $scanFile ) ) {
+ $newImage = new FisheyeImage();
+ $imageHash = array( '_files_override' => array( $scanFile ) );
+ if( $newImage->store( $imageHash ) ) {
+ if( $pRoot ) {
+ $newImage->addToGalleries( $_REQUEST['gallery_additions'] );
+ }
+ if( !is_object( $pParentGallery ) ) {
+ global $gBitUser;
+ $pParentGallery = new FisheyeGallery( fisheye_get_default_gallery_id( $gBitUser->mUserId, $gBitUser->getDisplayName()."'s Gallery" ) );
+ $pParentGallery->load();
+ }
+ $pParentGallery->addItem( $newImage->mContentId );
+ } else {
+ $errors = array_merge( $errors, array_values( $newImage->mErrors ) );
+ }
+ } elseif( is_file( $scanFile['tmp_name'] ) ) {
+ // unknown file type, let's be tidy and clean it up
+ unlink( $scanFile['tmp_name'] );
+ }
+ $order += 10;
+ }
+ }
+ if ( !is_windows() ) {
+ unlink_r( $pDestinationDir );
+ }
+ }
+ return $errors;
+}
+
+
+// this function will process a directory and all it's sub directories without
+// making any assumptions. hierarchy of sub directories is maintained and
+// archives can be processed or simply added to the galleries.
+function fisheye_process_ftp_directory( $pProcessDir ) {
+ global $gBitSystem, $gBitUser;
+ if( empty( $_REQUEST['gallery_additions'] ) ) {
+ $_REQUEST['gallery_additions'] = array();
+ }
+
+ $errors = array();
+ if( $archiveDir = opendir( $pProcessDir ) ) {
+ $order = 100;
+ while( $fileName = readdir($archiveDir) ) {
+ $sortedNames[] = $fileName;
+ }
+
+ sort( $sortedNames );
+ $order = 100;
+
+ foreach( $sortedNames as $fileName ) {
+ if( !preg_match( '/^\./', $fileName ) && ( $fileName != 'Thumbs.db' ) ) {
+ $scanFile = array(
+ 'type' => $gBitSystem->lookupMimeType( substr( $fileName, ( strrpos( $fileName, '.' ) + 1 ) ) ),
+ 'name' => $fileName,
+ 'size' => filesize( "$pProcessDir/$fileName" ),
+ 'tmp_name' => "$pProcessDir/$fileName",
+ );
+
+ if( is_dir( $pProcessDir.'/'.$fileName ) ) {
+ // create a new gallery from directory
+ $dirGallery = new FisheyeGallery();
+ $galleryHash = array( 'title' => str_replace( '_', ' ', $fileName ) );
+ if( $dirGallery->store( $galleryHash ) ) {
+ $dirGallery->addToGalleries( $_REQUEST['gallery_additions'] );
+ $errors = array_merge( $errors, fisheye_process_directory( $pProcessDir.'/'.$fileName, $dirGallery ) );
+ } else {
+ $errors = array_merge( $errors, array_values( $dirGallery->mErrors ) );
+ }
+ unset( $dirGallery );
+ } else {
+ if( preg_match( '/(^image|pdf)/i', $scanFile['type'] ) ) {
+ // process image
+ $newImage = new FisheyeImage();
+ $imageHash = array( 'upload' => $scanFile );
+ if( $newImage->store( $imageHash ) ) {
+ $newImage->addToGalleries( $_REQUEST['gallery_additions'] );
+
+ // if we have a gallery to add these images to, load one of them
+ if( !empty( $_REQUEST['gallery_additions'][0] ) && @!is_object( $imageGallery ) ) {
+ $imageGallery = new FisheyeGallery();
+ $imageGallery->mGalleryId = $_REQUEST['gallery_additions'][0];
+ $imageGallery->load();
+ }
+
+ if( @!is_object( $imageGallery ) ) {
+ global $gBitUser;
+ $galleryHash = array( 'title' => $gBitUser->getDisplayName()."'s Gallery" );
+ $imageGallery = new FisheyeGallery();
+ if( $imageGallery->store( $galleryHash ) ) {
+ $imageGallery->load();
+ } else {
+ $errors = array_merge( $errors, array_values( $imageGallery->mErrors ) );
+ }
+ }
+
+ $imageGallery->addItem( $newImage->mContentId );
+ } else {
+ $errors = array_merge( $errors, array_values( $newImage->mErrors ) );
+ }
+ } else {
+ // create a new gallery from archive
+ $archiveGallery = new FisheyeGallery();
+ $galleryHash = array( 'title' => substr( $fileName, 0, ( str_replace( '_', ' ', strrpos( $fileName, '.' ) ) ) ) );
+ if( !$archiveGallery->store( $galleryHash ) ) {
+ $errors = array_merge( $errors, array_values( $archiveGallery->mErrors ) );
+ }
+
+ $errors = fisheye_process_archive( $scanFile, $archiveGallery, TRUE );
+ unset( $archiveGallery );
+ }
+ }
+ $order += 10;
+ }
+ }
+ }
+ return $errors;
+}
+?>