liberty
[ class tree: liberty ] [ index: liberty ] [ all elements ]

Source for file LibertyMime.php

Documentation is available at LibertyMime.php

  1. <?php
  2. /**
  3.  * Manages liberty Uploads
  4.  *
  5.  * @package  liberty
  6.  */
  7.  
  8. /**
  9.  * required setup
  10.  */
  11. require_once( LIBERTY_PKG_PATH.'LibertyContent.php' );
  12.  
  13. // load the image processor plugin, check for loaded 'gd' since that is the default processor, and config might not be set.
  14. if( $gBitSystem->isFeatureActive( 'image_processor' ) || extension_loaded( 'gd' ) ) {
  15.     require_once( LIBERTY_PKG_PATH."plugins/processor.".$gBitSystem->getConfig( 'image_processor','gd' ).".php" );
  16. }
  17.  
  18. // maximum size of the 'original' image when converted to jpg
  19. define( 'MAX_THUMBNAIL_DIMENSION', 99999 );
  20.  
  21. /**
  22.  * LibertyMime class
  23.  *
  24.  * @package liberty
  25.  */
  26. class LibertyMime extends LibertyContent {
  27.     var $mStoragePrefs = NULL;
  28.  
  29.     /**
  30.      * load the attachments for a given content id and then stuff them in mStorage
  31.      *
  32.      * @param array $pContentId 
  33.      * @access public
  34.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  35.      */
  36.     public function load( $pContentId = NULL, $pPluginParams = NULL ) {
  37.         global $gLibertySystem;
  38.         // assume a derived class has joined on the liberty_content table, and loaded it's columns already.
  39.         $contentId = ( @BitBase::verifyId( $pContentId ) ? $pContentId : $this->mContentId );
  40.  
  41.         if( @BitBase::verifyId( $contentId )) {
  42.             // load up the content
  43.             LibertyContent::load( $contentId );
  44.  
  45.             // don't loadAttachmentPreferences() when we are forcing the installer since it breaks the login process before 2.1.0-beta
  46.             if( !defined( 'INSTALLER_FORCE' ) && !defined( 'LOGIN_VALIDATE' )) {
  47.                 $this->loadAttachmentPreferences();
  48.             }
  49.  
  50.             $query = "SELECT * FROM `".BIT_DB_PREFIX."liberty_attachments` la WHERE la.`content_id`=? ORDER BY la.`pos` ASC, la.`attachment_id` ASC";
  51.             if( $result = $this->mDb->query( $query,array( (int)$contentId ))) {
  52.                 $this->mStorage = array();
  53.                 while( $row = $result->fetchRow() ) {
  54.                     if( !empty( $row['is_primary'] ) ) {
  55.                         // used by edit tpl's among other things
  56.                         $this->mInfo['primary_attachment_id'] = $row['attachment_id'];
  57.                     } elseif( !$this->getField( 'primary_attachment_id' ) && !empty( $row['attachment_id'] ) ) {
  58.                         // primary was not set by the above, default to first row. might be reset by later iterations via if is_primary above
  59.                         $this->mInfo['primary_attachment_id'] = $row['attachment_id'];
  60.                     }
  61.                     if( $func = $gLibertySystem->getPluginFunction( $row['attachment_plugin_guid'], 'load_function', 'mime' )) {
  62.                         // we will pass the preferences by reference that the plugin can easily update them
  63.                         if( empty( $this->mStoragePrefs[$row['attachment_id']] )) {
  64.                             $this->mStoragePrefs[$row['attachment_id']] = array();
  65.                         }
  66.                         $this->mStorage[$row['attachment_id']] = $func( $row, $this->mStoragePrefs[$row['attachment_id']], $pPluginParams );
  67.                     } else {
  68.                         print "No load_function for ".$row['attachment_plugin_guid'];
  69.                     }
  70.                 }
  71.             }
  72.         }
  73.         return( TRUE );
  74.     }
  75.  
  76.     /**
  77.      * Store a new upload
  78.      *
  79.      * @param array $pStoreHash contains all data to store the gallery
  80.      * @return bool TRUE on success, FALSE if store could not occur. If FALSE, $this->mErrors will have reason why
  81.      * @access public
  82.      ***/
  83.     public function store( &$pStoreHash ) {
  84.         global $gLibertySystem;
  85.         // make sure all the data is in order
  86.         if( LibertyMime::verify( $pStoreHash ) && ( !empty( $pStoreHash['skip_content_store'] ) || LibertyContent::store( $pStoreHash ) ) ) {
  87.             $this->mDb->StartTrans();
  88.             // files have been uploaded
  89.             if( !empty( $pStoreHash['upload_store']['files'] ) && is_array( $pStoreHash['upload_store']['files'] )) {
  90.  
  91.                 foreach( $pStoreHash['upload_store']['files'] as $key => $upload ) {
  92.                     // if we don't have an upload, we'll simply update the file settings using the mime plugins
  93.                     if( empty( $upload['tmp_name'] )) {
  94.                         if( @BitBase::verifyId( $upload['attachment_id'] )) {
  95.                             // since the form might have all options unchecked, we need to call the update function regardless
  96.                             // currently i can't think of a better way to get the plugin guid back when $pStoreHash[plugin] is
  97.                             // empty. - xing - Friday Jul 11, 2008   20:21:18 CEST
  98.                             if( !empty( $this->mStorage[$upload['attachment_id']] )) {
  99.                                 $attachment = $this->mStorage[$upload['attachment_id']];
  100.                                 $data = array();
  101.                                 if( !empty( $pStoreHash['plugin'][$upload['attachment_id']][$attachment['attachment_plugin_guid']] )) {
  102.                                     $data = $pStoreHash['plugin'][$upload['attachment_id']][$attachment['attachment_plugin_guid']];
  103.                                 }
  104.                                 if( !$this->updateAttachmentParams( $upload['attachment_id'], $attachment['attachment_plugin_guid'], $data )) {
  105.                                     $this->mErrors['attachment_update'] = "There was a problem updating the file settings.";
  106.                                 }
  107.                             }
  108.                         }
  109.                         // skip rest of process
  110.                         continue;
  111.                     }
  112.  
  113.                     $storeRow = $pStoreHash['upload_store'];
  114.                     unset( $storeRow['files'] );
  115.  
  116.                     // copy by reference that filetype changes are made in lookupMimeHandler()
  117.                     $storeRow['upload'] = &$upload;
  118.                     if( isset( $pStoreHash['thumbnail'] ) ) {
  119.                         $storeRow['upload']['thumbnail'] = $pStoreHash['thumbnail'];
  120.                     }
  121.  
  122.                     // when content is created the content_id is only available after LibertyContent::store()
  123.                     $storeRow['content_id'] = $pStoreHash['content_id'];
  124.  
  125.                     // let the plugin do the rest
  126.                     $guid = $gLibertySystem->lookupMimeHandler( $upload );
  127.                     $this->pluginStore( $storeRow, $guid, @BitBase::verifyId( $upload['attachment_id'] ));
  128.  
  129.                     // finally, we need to update the original hash with the new values
  130.                     $pStoreHash['upload_store']['files'][$key] = $storeRow;
  131.                 }
  132.             }
  133.  
  134.             // some mime plugins might not have file uploads - these plugins will tell us what mime handlers they are using
  135.             if( !empty( $pStoreHash['mimeplugin'] ) && is_array( $pStoreHash['mimeplugin'] )) {
  136.                 foreach( $pStoreHash['mimeplugin'] as $guid => $storeRow ) {
  137.                     // check to see if we have anything worth storing in the array
  138.                     $plugin_store = FALSE;
  139.                     foreach( array_values( $storeRow ) as $value ) {
  140.                         if( !empty( $value )) {
  141.                             $plugin_store = TRUE;
  142.                         }
  143.                     }
  144.  
  145.                     if( !empty( $plugin_store )) {
  146.                         // when content is created the content_id is only available after LibertyContent::store()
  147.                         $storeRow['content_id'] = $pStoreHash['content_id'];
  148.                         $this->pluginStore( $storeRow, $guid, @BitBase::verifyId( $upload['attachment_id'] ));
  149.                     }
  150.                 }
  151.             }
  152.  
  153.             // deal with the primary attachment after we've dealt with all the files
  154.             $this->setPrimaryAttachment(
  155.                 $pStoreHash['liberty_attachments']['primary'],
  156.                 $pStoreHash['content_id'],
  157.                 empty( $pStoreHash['liberty_attachments']['auto_primary'] ) || $pStoreHash['liberty_attachments']['auto_primary'] ? TRUE : FALSE
  158.             );
  159.  
  160.             // Roll back if something went wrong
  161.             if( empty( $this->mErrors )) {
  162.                 $this->mDb->CompleteTrans();
  163.             } else {
  164.                 $this->mDb->RollbackTrans();
  165.             }
  166.         }
  167.  
  168.         return( count( $this->mErrors ) == 0 );
  169.     }
  170.  
  171.     /**
  172.      * pluginStore will use a given plugin to store uploaded file data
  173.      *
  174.      * @param string $pGuid GUID of plugin
  175.      * @param array $pStoreHash Data to be prcessed and stored by the plugin
  176.      * @param boolean $pUpdate set to TRUE if this is just an update
  177.      * @access public
  178.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  179.      */
  180.     public function pluginStore( &$pStoreHash, $pGuid, $pUpdate = FALSE ) {
  181.         global $gLibertySystem;
  182.         if( !empty( $pStoreHash ) && $verify_function = $gLibertySystem->getPluginFunction( $pGuid, 'verify_function' )) {
  183.             // pass along a pointer to the content object
  184.             $pStoreHash['this'] = &$this;
  185.             // verify the uploaded file using the plugin
  186.             if( $verify_function( $pStoreHash )) {
  187.                 if( $process_function = $gLibertySystem->getPluginFunction( $pGuid, (( $pUpdate ) ? 'update_function' : 'store_function' ))) {
  188.                     if( !$process_function( $pStoreHash )) {
  189.                         $this->mErrors = array_merge( $this->mErrors, $pStoreHash['errors'] );
  190.                     }
  191.                 } else {
  192.                     $this->mErrors['store_function'] = tra( 'No suitable store function found.' );
  193.                 }
  194.             } else {
  195.                 $this->mErrors = array_merge( $this->mErrors, $pStoreHash['errors'] );
  196.             }
  197.         } else {
  198.             $this->mErrors['verify_function'] = tra( 'No suitable verify function found.' );
  199.         }
  200.  
  201.         return( count( $this->mErrors ) == 0 );
  202.     }
  203.  
  204.     /**
  205.      * Verify content that is about to be stored
  206.      *
  207.      * @param array $pStoreHash hash of all data that needs to be stored in the database
  208.      * @access public
  209.      * @return TRUE on success, FALSE on failure - mErrors will contain reason
  210.      * @todo If one of the uploaded files is an update, place the attachment_id with the upload hash in $_FILES or in _files_override
  211.      */
  212.     public function verify( &$pParamHash ) {
  213.         global $gBitUser, $gLibertySystem;
  214.  
  215.         // check to see if we have any files to upload
  216.         if( isset( $pParamHash['_files_override'] )) {
  217.             // we have been passed in a manually stuffed files attachment, such as a custom uploader would have done.
  218.             // process this, and skip over $_FILES
  219.             $uploads = $pParamHash['_files_override'];
  220.         } elseif( !empty( $_FILES )) {
  221.             // we have some _FILES hanging around we will gobble up. This is inherently dagnerous chewing up a _FILES like this as
  222.             // it can cause premature storing of a _FILE if you are trying to store multiple pieces of content at once.
  223.             foreach( $_FILES as $key => $file ) {
  224.                 if( !empty( $file['name'] ) || !empty( $file['attachment_id'] )) {
  225.                     $uploads[$key] = $file;
  226.                 }
  227.             }
  228.         }
  229.  
  230.         // verify uploads
  231.         if( !empty( $uploads ) ) {
  232.             foreach( array_keys( $uploads ) as $file ) {
  233.                 $pParamHash['upload_store']['files'][$file] = LibertyMime::verifyAttachment( $uploads[$file] );
  234.             }
  235.         }
  236.  
  237.         // don't check for p_liberty_attach_attachments permission on bitpermuser class so registration with avatar upload works
  238.         if( strtolower( get_class( $this )) == 'bitpermuser' ) {
  239.             $pParamHash['upload_store']['no_perm_check'] = TRUE;
  240.         }
  241.  
  242.         // check for the required permissions to upload a file to the liberty attachments area
  243.         if( !empty( $uploads ) && empty( $pParamHash['no_perm_check'] )) {
  244.             if( !$this->hasUserPermission( 'p_liberty_attach_attachments' )) {
  245.                 $this->mErrors['permission'] = tra( 'You do not have permission to upload attachments.' );
  246.             }
  247.         }
  248.  
  249.         // primary attachment. Allow 'none' to clear the primary.
  250.         if( !@BitBase::verifyId( $pParamHash['liberty_attachments']['primary'] ) && ( empty( $pParamHash['liberty_attachments']['primary'] ) || $pParamHash['liberty_attachments']['primary'] != 'none' ) ) {
  251.             $pParamHash['liberty_attachments']['primary'] = NULL;
  252.         }
  253.  
  254.         // if we have an error we get them all by checking parent classes for additional errors
  255.         if( count( $this->mErrors ) > 0 ){
  256.             // check errors of LibertyContent since LibertyMime means to override the parent verify
  257.             LibertyContent::verify( $pParamHash );
  258.         }
  259.  
  260.         return ( count( $this->mErrors ) == 0 );
  261.     }
  262.  
  263.     /**
  264.      * getThumbnailUrl will fetch the primary thumbnail for a given content. If nothing has been set, it will fetch the last thumbnail it can find.
  265.      *
  266.      * @param string $pSize 
  267.      * @param array $pInfoHash 
  268.      * @access public
  269.      * @return boolean TRUE on success, FALSE on failure - $this->mErrors will contain reason for failure
  270.      */
  271.     public function getThumbnailUrl( $pSize='small', $pInfoHash=NULL, $pSecondary=NULL, $pDefault=TRUE ) {
  272.         $ret = NULL;
  273.         if( !empty( $pInfoHash ) ) {
  274.             // do some stuff if we are given a hash of stuff
  275.         } elseif( $this->isValid() && !empty( $this->mStorage ) ) {
  276.             foreach( array_keys( $this->mStorage ) as $attachmentId ) {
  277.                 if( !empty( $this->mStorage[$attachmentId]['is_primary'] ) ) {
  278.                     break;
  279.                 }
  280.             }
  281.             if( !empty( $this->mStorage[$attachmentId]['thumbnail_url'][$pSize] )) {
  282.                 $ret = $this->mStorage[$attachmentId]['thumbnail_url'][$pSize];
  283.             }
  284.         }
  285.         if( $pDefault && empty( $ret ) ) {
  286.             $ret = parent::getThumbnailUrl( $pSize, $pInfoHash, $pSecondary );
  287.         }
  288.         return $ret;
  289.     }
  290.  
  291.     /**
  292.      * updateAttachmentParams will update attachment parameters
  293.      *
  294.      * @param numeric $pAttachmentId attachment_id of the item we want the prefs from (optional)
  295.      * @param string $pPluginGuid GUID of the plugin that should process the data
  296.      * @param array $pParamHash Data to be processed by the plugin
  297.      * @access public
  298.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  299.      */
  300.     public function updateAttachmentParams( $pAttachmentId, $pPluginGuid, $pParamHash = array() ) {
  301.         global $gLibertySystem;
  302.         $ret = FALSE;
  303.  
  304.         if( BitBase::verifyId( $pAttachmentId )) {
  305.             if( !empty( $this ) && !empty( $this->mStorage[$pAttachmentId] )) {
  306.                 $file = $this->mStorage[$pAttachmentId];
  307.             } else {
  308.                 $file = $this->getAttachment( $pAttachmentId );
  309.             }
  310.  
  311.             if( @BitBase::verifyId( $file['attachment_id'] ) && !empty( $pPluginGuid ) && ( $update_function = $gLibertySystem->getPluginFunction( $pPluginGuid, 'update_function', 'mime' ))) {
  312.                 if( $update_function( $file, $pParamHash )) {
  313.                     $ret = TRUE;
  314.                 } else {
  315.                     if( !empty( $file['errors'] )) {
  316.                         $this->mErrors['param_update'] = $file['errors'];
  317.                     } else {
  318.                         $this->mErrors['param_update'] = tra( 'There was an unspecified error while updating the file.' );
  319.                     }
  320.                 }
  321.             }
  322.         }
  323.         return $ret;
  324.     }
  325.  
  326.     /**
  327.      * verifyAttachment will perform a generic check if a file is valid for processing
  328.      *
  329.      * @param array $pFile file array from $_FILES
  330.      * @access public
  331.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  332.      */
  333.     public function verifyAttachment( $pFile ) {
  334.         if( !empty( $pFile['tmp_name'] ) && is_file( $pFile['tmp_name'] ) && empty( $pFile['error'] ) || !empty( $pFile['attachment_id'] )) {
  335.             return $pFile;
  336.         }
  337.     }
  338.  
  339.     /**
  340.      * Increment the item hit flag by 1
  341.      *
  342.      * @access public
  343.      * @param numeric $pAttachmentId Attachment ID
  344.      * @return adodb query result or FALSE
  345.      * @note we're abusing the hits column for download count.
  346.      */
  347.     public function addDownloadHit( $pAttachmentId = NULL ) {
  348.         global $gBitUser, $gBitSystem;
  349.         if( @BitBase::verifyId( $pAttachmentId ) && $attachment = static::loadAttachment( $pAttachmentId )) {
  350.             if( !$gBitUser->isRegistered() || ( $gBitUser->isRegistered() && $gBitUser->mUserId != $attachment['user_id'] )) {
  351.                 $bindVars = array( $pAttachmentId );
  352.                 if( $gBitSystem->mDb->getOne( "SELECT `attachment_id` FROM `".BIT_DB_PREFIX."liberty_attachments` WHERE `attachment_id` = ? AND `hits` IS NULL", $bindVars )) {
  353.                     $query = "UPDATE `".BIT_DB_PREFIX."liberty_attachments` SET `hits` = 1 WHERE `attachment_id` = ?";
  354.                 } else {
  355.                     $query = "UPDATE `".BIT_DB_PREFIX."liberty_attachments` SET `hits` = `hits`+1 WHERE `attachment_id` = ?";
  356.                 }
  357.                 return $gBitSystem->mDb->query( $query, $bindVars );
  358.             }
  359.         }
  360.         return FALSE;
  361.     }
  362.  
  363.     // {{{ =================== Storage Directory Methods ====================
  364.     function getSourceUrl( $pParamHash=array() ) {
  365.         $ret = NULL;
  366.         if( empty( $pParamHash ) && !empty( $this ) ) {
  367.             $pParamHash = $this->mInfo;
  368.         }
  369.         if( $fileName = $this->getParameter( $pParamHash, 'file_name', $this->getField( 'file_name' ) ) ) {
  370.             $defaultFileName = liberty_mime_get_default_file_name( $fileName, $pParamHash['mime_type'] );
  371.             if( file_exists( $this->getStoragePath( $pParamHash ).$defaultFileName ) ) {
  372.                 $ret = $this->getStorageUrl( $pParamHash ).$defaultFileName;
  373.             } else {
  374.                 $ret = $this->getStorageUrl( $pParamHash ).basename( $fileName );
  375.             }
  376.         }
  377.         return $ret;
  378.     }
  379.  
  380.     function getSourceFile( $pParamHash=array() ) {
  381.         $ret = NULL;
  382.         if( empty( $pParamHash ) && !empty( $this ) ) {
  383.             $pParamHash = $this->mInfo;
  384.         }
  385.         if( $fileName = $this->getParameter( $pParamHash, 'file_name', $this->getField( 'file_name' ) ) ) {
  386.             $defaultFileName = liberty_mime_get_default_file_name( $fileName, $pParamHash['mime_type'] );
  387.             $ret = $this->getStoragePath( $pParamHash ).$defaultFileName;
  388.             if( !file_exists( $ret ) ) {
  389.                 $ret = $this->getStoragePath( $pParamHash ).basename( $fileName );
  390.             }
  391.         }
  392.         return $ret;
  393.     }
  394.  
  395.  
  396.     /**
  397.      * getStoragePath - get path to store files for the feature site_upload_dir. It creates a calculable hierarchy of directories
  398.      *
  399.      * @access public
  400.      * @author Christian Fowler<spider@steelsun.com>
  401.      * @param $pSubDir any desired directory below the StoragePath. this will be created if it doesn't exist
  402.      * @param $pCommon indicates not to use the 'common' branch, and not the 'users/.../<user_id>' branch
  403.      * @param $pRootDir override BIT_ROOT_DIR with a custom absolute path - useful for areas where no we access should be allowed
  404.      * @return string full path on local filsystem to store files.
  405.      */
  406.     function getStoragePath( $pParamHash, $pRootDir=NULL ) {
  407.         $ret = null;
  408.  
  409.         if( $branch = liberty_mime_get_storage_branch( $pParamHash ) ) {
  410.             $ret = ( !empty( $pRootDir ) ? $pRootDir : STORAGE_PKG_PATH ).$branch;
  411.             mkdir_p($ret);
  412.         }
  413.         return $ret;
  414.     }
  415.  
  416.  
  417.     function getStorageUrl( $pParamHash ) {
  418.         return STORAGE_PKG_URL.liberty_mime_get_storage_branch( $pParamHash );
  419.     }
  420.  
  421.     /**
  422.      * getStorageBranch - get url to store files for the feature site_upload_dir. It creates a calculable hierarchy of directories
  423.      *
  424.      * @access public
  425.      * @author Christian Fowler<spider@steelsun.com>
  426.      * @param $pSubDir any desired directory below the StoragePath. this will be created if it doesn't exist
  427.      * @param $pUserId indicates the 'users/.../<user_id>' branch or use the 'common' branch if null
  428.      * @param $pRootDir **deprecated, unused, will be removed in future relase**.
  429.      * @return string full path on local filsystem to store files.
  430.      */
  431.     function getStorageBranch( $pParamHash ) {
  432.         return liberty_mime_get_storage_branch( $pParamHash );
  433.     }
  434.  
  435.     /**
  436.      * getStorageSubDirName get a filename based on the uploaded file
  437.      *
  438.      * @param array $pFileHash File information provided in $_FILES
  439.      * @access public
  440.      * @return appropriate sub dir name
  441.      */
  442.     function getStorageSubDirName( $pFileHash = NULL ) {
  443.         if( !empty( $pFileHash['mime_type'] ) && strstr( $pFileHash['mime_type'], "/" )) {
  444.             $ret = strtolower( preg_replace( "!/.*$!", "", $pFileHash['mime_type'] ));
  445.             // if we only got 'application' we will use the file extenstion
  446.             if( $ret == 'application' && !empty( $pFileHash['name'] ) && ( $pos = strrpos( $pFileHash['name'], "." )) !== FALSE ) {
  447.                 $ret = strtolower( substr( $pFileHash['name'], $pos + 1 ));
  448.             }
  449.         }
  450.  
  451.         // append an 's' to not create an image and images dir side by side (legacy reasons)
  452.         if( empty( $ret ) || $ret == 'image' ) {
  453.             $ret = 'images';
  454.         }
  455.  
  456.         return $ret;
  457.     }
  458.  
  459.     /**
  460.      * validateStoragePath make sure that the file/dir you are trying to delete is valid
  461.      *
  462.      * @param array $pPath absolute path to the file/dir we want to validate
  463.      * @access public
  464.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  465.      */
  466.     public static function validateStoragePath( $pPath ) {
  467.         // file_exists checks for file or directory
  468.         if( !empty( $pPath ) && $pPath = realpath( $pPath )) {
  469.             // ensure path sanity
  470.             if( preg_match( "#^".realpath( STORAGE_PKG_PATH )."/(users|common)/\d+/\d+/\w+/\d+#", $pPath )) {
  471.                 return $pPath;
  472.             }
  473.         }
  474.     }
  475.  
  476.     // }}}
  477.  
  478.  
  479.     // {{{ =================== Attachment Methods ====================
  480.     /**
  481.      * Get a list of all available attachments
  482.      *
  483.      * @param array $pListHash 
  484.      * @access public
  485.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  486.      */
  487.     function getAttachmentList( &$pListHash ) {
  488.         global $gLibertySystem, $gBitUser, $gBitSystem;
  489.  
  490.         LibertyContent::prepGetList( $pListHash );
  491.  
  492.         // initialise some variables
  493.         $attachments = $ret = $bindVars = array();
  494.         $whereSql = $joinSql = $selectSql = '';
  495.  
  496.         // only admin may view attachments from other users
  497.         if( !$gBitUser->isAdmin() ) {
  498.             $pListHash['user_id'] = $gBitUser->mUserId;
  499.         }
  500.  
  501.         if( !empty( $pListHash['user_id'] ) ) {
  502.             $whereSql .= empty( $whereSql ) ? ' WHERE ' : ' AND ';
  503.             $whereSql .= " la.user_id = ? ";
  504.             $bindVars[] = $pListHash['user_id'];
  505.         }
  506.  
  507.         if( !empty( $pListHash['content_id'] ) ) {
  508.             $whereSql .= empty( $whereSql ) ? ' WHERE ' : ' AND ';
  509.             $whereSql .= " la.`content_id` = ? ";
  510.             $selectSql .= " , la.`content_id` ";
  511.             $bindVars[] = $pListHash['content_id'];
  512.         }
  513.         $query = "SELECT la.* $selectSql FROM `".BIT_DB_PREFIX."liberty_attachments` la INNER JOIN `".BIT_DB_PREFIX."users_users` uu ON(la.`user_id` = uu.`user_id`) $joinSql $whereSql";
  514.         $result = $this->mDb->query( $query, $bindVars, $pListHash['max_records'], $pListHash['offset'] );
  515.         while( $res = $result->fetchRow() ) {
  516.             $attachments[] = $res;
  517.         }
  518.  
  519.         foreach( $attachments as $attachment ) {
  520.             if( $loadFunc = $gLibertySystem->getPluginFunction( $attachment['attachment_plugin_guid'], 'load_function', 'mime' )) {
  521.                 /* @$prefs - quick hack to stop LibertyMime plugins from breaking until migration to LibertyMime is complete
  522.                  * see expected arguments of liberty/plugins/mime.default.php::mime_default_load -wjames5
  523.                  */
  524.                 $prefs = array();
  525.                 $ret[$attachment['attachment_id']] = $loadFunc( $attachment, $prefs );
  526.             }
  527.         }
  528.  
  529.         // count all entries
  530.         $query = "SELECT COUNT(*)
  531.             FROM `".BIT_DB_PREFIX."liberty_attachments` la
  532.             INNER JOIN `".BIT_DB_PREFIX."users_users` uu ON(la.`user_id` = uu.`user_id`)
  533.             $joinSql $whereSql
  534.         ";
  535.  
  536.         $pListHash['cant'] = $this->mDb->getOne( $query, $bindVars );
  537.         $this->postGetList( $pListHash );
  538.  
  539.         return $ret;
  540.     }
  541.  
  542.     /**
  543.      * Expunges the content deleting attached attachments
  544.      */
  545.     function expunge() {
  546.         if( !empty( $this->mStorage ) && count( $this->mStorage )) {
  547.             foreach( array_keys( $this->mStorage ) as $i ) {
  548.                 $this->expungeAttachment( $this->mStorage[$i]['attachment_id'] );
  549.             }
  550.         }
  551.         return LibertyContent::expunge();
  552.     }
  553.  
  554.     /**
  555.      * expunge attachment from the database (and file system via the plugin if required)
  556.      *
  557.      * @param numeric $pAttachmentId attachment id of the item that should be deleted
  558.      * @access public
  559.      * @return TRUE on success, FALSE on failure
  560.      */
  561.     function expungeAttachment( $pAttachmentId ) {
  562.         global $gLibertySystem, $gBitUser;
  563.         $ret = NULL;
  564.         if( @$this->verifyId( $pAttachmentId ) ) {
  565.             $sql = "SELECT `attachment_plugin_guid`, `user_id` FROM `".BIT_DB_PREFIX."liberty_attachments` WHERE `attachment_id` = ?";
  566.             if(( $row = $this->mDb->getRow( $sql, array( $pAttachmentId ))) && ( $this->isOwner( $row ) || $gBitUser->isAdmin() )) {
  567.                 // check if we have the means available to remove this attachment
  568.                 if(( $guid = $row['attachment_plugin_guid'] ) && $expungeFunc = $gLibertySystem->getPluginFunction( $guid, 'expunge_function', 'mime' )) {
  569.                     // --- Do the final cleanup of liberty related tables ---
  570.  
  571.                     // there might be situations where we remove user images including portrait, avatar or logo
  572.                     // This needs to happen before the plugin can do it's work due to constraints
  573.                     $types = array( 'portrait', 'avatar', 'logo' );
  574.                     foreach( $types as $type ) {
  575.                         $sql = "UPDATE `".BIT_DB_PREFIX."users_users` SET `{$type}_attachment_id` = NULL WHERE `{$type}_attachment_id` = ?";
  576.                         $this->mDb->query( $sql, array( $pAttachmentId ));
  577.                     }
  578.  
  579.                     if( $expungeFunc( $pAttachmentId )) {
  580.                         // Delete the attachment meta data, prefs and record.
  581.                         $sql = "DELETE FROM `".BIT_DB_PREFIX."liberty_attachment_meta_data` WHERE `attachment_id` = ?";
  582.                         $this->mDb->query( $sql, array( $pAttachmentId ));
  583.                         $sql = "DELETE FROM `".BIT_DB_PREFIX."liberty_attachment_prefs` WHERE `attachment_id` = ?";
  584.                         $this->mDb->query( $sql, array( $pAttachmentId ));
  585.                         $sql = "DELETE FROM `".BIT_DB_PREFIX."liberty_attachments` WHERE `attachment_id`=?";
  586.                         $this->mDb->query( $sql, array( $pAttachmentId ));
  587.  
  588.                         // Remove attachment from memory
  589.                         unset( $this->mStorage[$pAttachmentId] );
  590.                         $ret = TRUE;
  591.                     }
  592.                 } else {
  593.                     print( "Expunge function not found for this content!" );
  594.                 }
  595.             }
  596.         }
  597.  
  598.         return $ret;
  599.     }
  600.  
  601.     /**
  602.      * loadAttachment will load details of a given attachment
  603.      *
  604.      * @param numeric $pAttachmentId Attachment ID of the attachment
  605.      * @param array $pParams optional parameters that might contain information like display thumbnail size
  606.      * @access public
  607.      * @return attachment details
  608.      */
  609.     public static function loadAttachment( $pAttachmentId, $pParams = NULL ) {
  610.         global $gLibertySystem, $gBitSystem;
  611.         $ret = NULL;
  612.  
  613.         if( @BitBase::verifyId( $pAttachmentId )) {
  614.             $query = "SELECT * FROM `".BIT_DB_PREFIX."liberty_attachments` la WHERE la.`attachment_id`=?";
  615.             if( $result = $gBitSystem->mDb->query( $query, array( (int)$pAttachmentId ))) {
  616.                 if( $row = $result->fetchRow() ) {
  617.                     if( $func = $gLibertySystem->getPluginFunction( $row['attachment_plugin_guid'], 'load_function', 'mime' )) {
  618.                         $sql = "SELECT `pref_name`, `pref_value` FROM `".BIT_DB_PREFIX."liberty_attachment_prefs` WHERE `attachment_id` = ?";
  619.                         $prefs = $gBitSystem->mDb->getAssoc( $sql, array( $pAttachmentId ));
  620.                         $ret = $func( $row, $prefs, $pParams );
  621.                     }
  622.                 }
  623.             }
  624.         }
  625.         return $ret;
  626.     }
  627.  
  628.     /**
  629.      * getAttachment will load details of a given attachment
  630.      *
  631.      * @param numeric $pAttachmentId Attachment ID of the attachment
  632.      * @param array $pParams optional parameters that might contain information like display thumbnail size
  633.      * @access public
  634.      * @return attachment details
  635.      */
  636.     public function getAttachment( $pAttachmentId, $pParams = NULL ) {
  637.         global $gLibertySystem, $gBitSystem;
  638.         $ret = NULL;
  639.  
  640.         if( @BitBase::verifyId( $pAttachmentId )) {
  641.             $query = "SELECT * FROM `".BIT_DB_PREFIX."liberty_attachments` la WHERE la.`attachment_id`=?";
  642.             if( $result = $gBitSystem->mDb->query( $query, array( (int)$pAttachmentId ))) {
  643.                 if( $row = $result->fetchRow() ) {
  644.                     if( $func = $gLibertySystem->getPluginFunction( $row['attachment_plugin_guid'], 'load_function', 'mime' )) {
  645.                         $prefs = array();
  646.                         // if the object is available, we'll copy the preferences by reference to allow the plugin to update them as needed
  647.                         if( !empty( $this ) && !empty( $this->mStoragePrefs[$pAttachmentId] )) {
  648.                             $prefs = &$this->mStoragePrefs[$pAttachmentId];
  649.                         } else {
  650.                             $prefs = static::getAttachmentPreferences( $pAttachmentId );
  651.                         }
  652.                         $ret = $func( $row, $prefs, $pParams );
  653.                     }
  654.                 }
  655.             }
  656.         }
  657.         return $ret;
  658.     }
  659.  
  660.     /**
  661.      * setPrimaryAttachment will set is_primary 'y' for the specified
  662.      * attachment and will ensure that all others are set to 'n'
  663.      *
  664.      * @param mixed   $pAttachmentId attachment id of the item we want to
  665.      *                   set as the primary attachment. Use 'none' to clear.
  666.      * @param numeric $pContentId content id we are working with.
  667.      * @param boolean $pAutoPrimary automatically set primary if there is only
  668.      *                   one attachment. Defaults to true.
  669.      * @access public
  670.      * @return TRUE on success, FALSE on failure
  671.      */
  672.     public function setPrimaryAttachment( $pAttachmentId = NULL, $pContentId = NULL, $pAutoPrimary = TRUE ) {
  673.         global $gBitSystem;
  674.  
  675.         $ret = FALSE;
  676.  
  677.         // If we are not given an attachment id but we where told the
  678.         // content_id and we are supposed to auto set the primary then
  679.         // figure out which one it is
  680.         if( !@BitBase::verifyId( $pAttachmentId ) && ( empty( $pAttachmentId ) || $pAttachmentId != 'none' ) && @BitBase::verifyId( $pContentId ) && $pAutoPrimary ) {
  681.             $query = "
  682.                 SELECT `attachment_id`
  683.                 FROM `".BIT_DB_PREFIX."liberty_content` lc
  684.                 INNER JOIN `".BIT_DB_PREFIX."liberty_attachments` la ON( lc.`content_id` = la.`content_id` )
  685.                 WHERE lc.`content_id` = ?";
  686.             $pAttachmentId = $this->mDb->getOne( $query, array( $pContentId ));
  687.         }
  688.  
  689.         // If we have an attachment_id we'll set it to this
  690.         if( @BitBase::verifyId( $pAttachmentId )) {
  691.             // get attachment we want to set primary
  692.             $attachment = $this->getAttachment( $pAttachmentId );
  693.  
  694.             // Clear old primary. There can only be one!
  695.             $this->clearPrimaryAttachment( $attachment['content_id'] );
  696.  
  697.             // now update the attachment to is_primary
  698.             $query = "
  699.                 UPDATE `".BIT_DB_PREFIX."liberty_attachments`
  700.                 SET `is_primary` = ? WHERE `attachment_id` = ?";
  701.             $this->mDb->query( $query, array( 'y', $pAttachmentId ));
  702.  
  703.             $ret = TRUE;
  704.         // Otherwise, are we supposed to clear the primary entirely?
  705.         } elseif( @BitBase::verifyId( $pContentId ) && !empty( $pAttachmentId ) && $pAttachmentId == 'none' ) {
  706.             // Okay then do the job
  707.             $this->clearPrimaryAttachment( $pContentId );
  708.         }
  709.  
  710.         return $ret;
  711.     }
  712.  
  713.     /**
  714.      * clearPrimaryAttachment will remove the primary flag for all attachments
  715.      * with the given content_id
  716.      *
  717.      * @param numeric the content_id for which primary should be unset.
  718.      * @return TRUE on succes
  719.      */
  720.     function clearPrimaryAttachment( $pContentId ) {
  721.         $ret = FALSE;
  722.  
  723.         if( @BitBase::verifyId( $pContentId )) {
  724.             $query = "
  725.                 UPDATE `".BIT_DB_PREFIX."liberty_attachments`
  726.                 SET `is_primary` = ? WHERE `content_id` = ?";
  727.             $this->mDb->query( $query, array( NULL, $pContentId ));
  728.             $ret = TRUE;
  729.         }
  730.  
  731.         return $ret;
  732.     }
  733.     // }}}
  734.  
  735.  
  736.     /**
  737.      * === Attachment Preferences ===
  738.      */
  739.  
  740.     /**
  741.      * Returns the attachment preference value for the passed in key.
  742.      *
  743.      * @param string Hash key for the mPrefs value
  744.      * @param string Default value to return if the preference is empty
  745.      * @param int Optional content_id for arbitrary content preference
  746.      */
  747.     function getAttachmentPreference( $pAttachmentId, $pPrefName, $pPrefDefault = NULL ) {
  748.         if( is_null( $this->mStoragePrefs ) ) {
  749.             $this->loadAttachmentPreferences();
  750.         }
  751.  
  752.         $ret = NULL;
  753.         if( @BitBase::verifyId( $pAttachmentId ) && !empty( $pPrefName )) {
  754.             if( isset( $this->mStoragePrefs ) && isset( $this->mStoragePrefs[$pAttachmentId][$pPrefName] )) {
  755.                 $ret = $this->mStoragePrefs[$pAttachmentId][$pPrefName];
  756.             } else {
  757.                 $ret = $pPrefDefault;
  758.             }
  759.         }
  760.  
  761.         return $ret;
  762.     }
  763.  
  764.     /**
  765.      * Returns the attachment preferences for a given attachment id
  766.      *
  767.      * @param string Hash key for the mPrefs value
  768.      * @param string Default value to return if the preference is empty
  769.      * @param int Optional content_id for arbitrary content preference
  770.      */
  771.     function getAttachmentPreferences( $pAttachmentId ) {
  772.         global $gBitSystem;
  773.  
  774.         $ret = array();
  775.         if( !empty( $this ) && is_subclass_of( $this, "LibertyMime" ) ) {
  776.             // we're loading from within object
  777.             if( is_null( $this->mStoragePrefs )) {
  778.                 $this->loadAttachmentPreferences();
  779.             }
  780.  
  781.             if( @BitBase::verifyId( $pAttachmentId ) && isset( $this->mStoragePrefs[$pAttachmentId] )) {
  782.                 $ret = $this->mStoragePrefs[$pAttachmentId];
  783.             }
  784.         } else {
  785.             // if the object isn't loaded, we need to get the prefs from the database
  786.             $sql = "SELECT `pref_name`, `pref_value` FROM `".BIT_DB_PREFIX."liberty_attachment_prefs` WHERE `attachment_id` = ?";
  787.             $ret = $gBitSystem->mDb->getAssoc( $sql, array( $pAttachmentId ));
  788.         }
  789.  
  790.         return $ret;
  791.     }
  792.  
  793.     /**
  794.      * setAttachmentPreference will set an attachment preferences without storing it in the database
  795.      *
  796.      * @param array $pAttachmentId 
  797.      * @param array $pPrefName 
  798.      * @param array $pPrefValue 
  799.      * @access public
  800.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  801.      */
  802.     function setAttachmentPreference( $pAttachmentId, $pPrefName, $pPrefValue ) {
  803.         $this->mStoragePrefs[$pAttachmentId][$pPrefName] = $pPrefValue;
  804.     }
  805.  
  806.     /**
  807.      * Saves a preference to the liberty_content_prefs database table with the
  808.      * given pref name and value. If the value is NULL, the existing value will
  809.      * be delete and the value will not be saved. However, a zero will be
  810.      * stored.
  811.      *
  812.      * @param string Hash key for the prefs value
  813.      * @param string Value for the prefs hash key
  814.      */
  815.     function storeAttachmentPreference( $pAttachmentId, $pPrefName, $pPrefValue = NULL ) {
  816.         global $gBitSystem;
  817.         $ret = FALSE;
  818.         if( @BitBase::verifyId( $pAttachmentId ) && !empty( $pPrefName )) {
  819.             $query    = "DELETE FROM `".BIT_DB_PREFIX."liberty_attachment_prefs` WHERE `attachment_id` = ? AND `pref_name` = ?";
  820.             $bindvars = array( $pAttachmentId, $pPrefName );
  821.             $result   = $gBitSystem->mDb->query( $query, $bindvars );
  822.             if( !is_null( $pPrefValue )) {
  823.                 $query      = "INSERT INTO `".BIT_DB_PREFIX."liberty_attachment_prefs` (`attachment_id`,`pref_name`,`pref_value`) VALUES(?, ?, ?)";
  824.                 $bindvars[] = substr( $pPrefValue, 0, 250 );
  825.                 $result     = $gBitSystem->mDb->query( $query, $bindvars );
  826.             }
  827.  
  828.             // this function might be called statically
  829.             if( !empty( $this ) && $this->isValid() ) {
  830.                 $this->mStoragePrefs[$pAttachmentId][$pPrefName] = $pPrefValue;
  831.             }
  832.  
  833.             $ret = TRUE;
  834.         }
  835.         return $ret;
  836.     }
  837.  
  838.     /**
  839.      * loadPreferences of the currently loaded object or pass in to get preferences of a specific content_id
  840.      *
  841.      * @param numeric $pContentId content_id of the item we want the prefs from (optional)
  842.      * @param numeric $pAttachmentId attachment_id of the item we want the prefs from (optional)
  843.      * @access public
  844.      * @return array of preferences if $pContentId or $pAttachmentId is set or pass preferences on to $this->mStoragePrefs
  845.      */
  846.     function loadAttachmentPreferences( $pContentId = NULL ) {
  847.         global $gBitSystem;
  848.  
  849.         if( !@BitBase::verifyId( $pContentId ) && $this->isValid() && @BitBase::verifyId( $this->mContentId )) {
  850.             $pContentId = $this->mContentId;
  851.             $store_prefs = TRUE;
  852.         }
  853.  
  854.         $ret = array();
  855.         if( !empty( $this ) && !is_null( $this->mStoragePrefs )) {
  856.             $ret = $this->mStoragePrefs;
  857.         } elseif( @BitBase::verifyId( $pContentId )) {
  858.             $sql = "
  859.                 SELECT lap.`attachment_id`, lap.`pref_name`, lap.`pref_value`
  860.                 FROM `".BIT_DB_PREFIX."liberty_attachment_prefs` lap
  861.                     INNER JOIN `".BIT_DB_PREFIX."liberty_attachments` la ON (la.`attachment_id` = lap.`attachment_id`)
  862.                 WHERE la.`content_id` = ?";
  863.             $result = $gBitSystem->mDb->query( $sql, array( $pContentId ));
  864.             if( !empty( $result )) {
  865.                 while( $aux = $result->fetchRow() ) {
  866.                     $ret[$aux['attachment_id']][$aux['pref_name']] = $aux['pref_value'];
  867.                 }
  868.             }
  869.         }
  870.  
  871.         // if neither a content id nor an attachment id are given, we will place the results in mStoragePrefs
  872.         if( !empty( $store_prefs )) {
  873.             $this->mStoragePrefs = $ret;
  874.         } else {
  875.             return $ret;
  876.         }
  877.     }
  878.  
  879.     /**
  880.      * expungeAttachmentPreferences will remove all attachment preferences of a given attachmtent
  881.      *
  882.      * @param array $pAttachmentId attachemnt we want to remove the prefs for
  883.      * @access public
  884.      * @return TRUE on success, FALSE on failure
  885.      */
  886.     function expungeAttachmentPreferences( $pAttachmentId ) {
  887.         global $gBitSystem;
  888.         $ret = FALSE;
  889.         if( @BitBase::verifyId( $pAttachmentId ) ) {
  890.             $sql = "DELETE FROM `".BIT_DB_PREFIX."liberty_attachment_prefs` WHERE `attachment_id` = ?";
  891.             $gBitSystem->mDb->query( $sql, array( $pAttachmentId ));
  892.             $ret = TRUE;
  893.         }
  894.         return $ret;
  895.     }
  896.  
  897.     public static function getAttachmentDownloadUrl( $pAttachmentId ) {
  898.         global $gBitSystem;
  899.         $ret = NULL;
  900.         if( BitBase::verifyId( $pAttachmentId ) ) {
  901.             if( $gBitSystem->isFeatureActive( "pretty_urls" ) || $gBitSystem->isFeatureActive( "pretty_urls_extended" )) {
  902.                 $ret = LIBERTY_PKG_URL."download/file/".$pAttachmentId;
  903.             } else {
  904.                 $ret = LIBERTY_PKG_URL."download_file.php?attachment_id=".$pAttachmentId;
  905.             }
  906.         }
  907.         return $ret;
  908.     }
  909.  
  910.     public function getDownloadUrl() {
  911.         $ret = "";
  912.         if( $this->isValid() && $this->getField( 'attachment_id' ) ) {
  913.             $ret = LibertyMime::getAttachmentDownloadUrl( $this->getField( 'attachment_id' ) );
  914.         }
  915.         return $ret;
  916.     }
  917.  
  918.     // {{{ =================== Meta Methods ====================
  919.     /**
  920.      * storeMetaData
  921.      *
  922.      * @param numeric $pAttachmentId AttachmentID the data belongs to
  923.      * @param string $pType Type of data. e.g.: EXIF, ID3. This will default to "Meta Data"
  924.      * @param array $pStoreHash Data that needs to be stored in the database in an array. The key will be used as the meta_title.
  925.      * @access public
  926.      * @return TRUE on success, FALSE on failure
  927.      */
  928.     function storeMetaData( $pAttachmentId, $pType = "Meta Data", $pStoreHash ) {
  929.         global $gBitSystem;
  930.         $ret = FALSE;
  931.         if( @BitBase::verifyId( $pAttachmentId ) && !empty( $pType ) && !empty( $pStoreHash )) {
  932.             if( is_array( $pStoreHash )) {
  933.                 foreach( $pStoreHash as $key => $data ) {
  934.                     if( !is_array( $data )) {
  935.                         // store the data in the meta table
  936.                         $meta = array(
  937.                             'attachment_id' => $pAttachmentId,
  938.                             'meta_type_id'  => LibertyMime::storeMetaId( $pType, 'type' ),
  939.                             'meta_title_id' => LibertyMime::storeMetaId( $key, 'title' ),
  940.                         );
  941.  
  942.                         // remove this entry from the database if it already exists
  943.                         $gBitSystem->mDb->query( "DELETE FROM `".BIT_DB_PREFIX."liberty_attachment_meta_data` WHERE `attachment_id` = ? AND `meta_type_id` = ? AND `meta_title_id` = ?", $meta );
  944.  
  945.                         // don't insert empty lines
  946.                         if( !empty( $data )) {
  947.                             $meta['meta_value'] = $data;
  948.                             $gBitSystem->mDb->associateInsert( BIT_DB_PREFIX."liberty_attachment_meta_data", $meta );
  949.                         }
  950.  
  951.                         $ret = TRUE;
  952.                     } else {
  953.                         // should we recurse?
  954.                     }
  955.                 }
  956.             }
  957.         }
  958.         return $ret;
  959.     }
  960.  
  961.     /**
  962.      * storeMetaId
  963.      *
  964.      * @param string $pDescription Description of meta key. e.g.: Exif, ID3, Album, Artist
  965.      * @param string $pTable Table data is stored in - either 'type' or 'title'
  966.      * @access public
  967.      * @return newly stored ID on success, FALSE on failure
  968.      */
  969.     function storeMetaId( $pDescription, $pTable = 'type' ) {
  970.         global $gBitSystem;
  971.         $ret = FALSE;
  972.         if( !empty( $pDescription )) {
  973.             if( !( $ret = LibertyMime::getMetaId( $pDescription, $pTable ))) {
  974.                 $store = array(
  975.                     "meta_{$pTable}_id" => $gBitSystem->mDb->GenID( "liberty_meta_{$pTable}s_id_seq" ),
  976.                     "meta_{$pTable}"    => LibertyMime::normalizeMetaDescription( $pDescription ),
  977.                 );
  978.                 $gBitSystem->mDb->associateInsert( BIT_DB_PREFIX."liberty_meta_{$pTable}s", $store );
  979.                 $ret = $store["meta_{$pTable}_id"];
  980.             }
  981.         }
  982.         return $ret;
  983.     }
  984.  
  985.     /**
  986.      * getMetaData
  987.      *
  988.      * @param numeric $pAttachmentId AttachmentID the data belongs to
  989.      * @param string $pType Type of data. e.g.: EXIF, ID3.
  990.      * @param string $pTitle Title of data. e.g.: Artist, Album.
  991.      * @access public
  992.      * @return array with meta data on success, FALSE on failure
  993.      *  $note: Output format varies depending on requested data
  994.      */
  995.     public static function getMetaData( $pAttachmentId, $pType = NULL, $pTitle = NULL ) {
  996.         global $gBitSystem;
  997.         $ret = array();
  998.         if( @BitBase::verifyId( $pAttachmentId )) {
  999.             $bindVars = array( $pAttachmentId );
  1000.             $whereSql = "";
  1001.             if( !empty( $pType ) && !empty( $pTitle )) {
  1002.  
  1003.                 // we have a type and title - only one entry will be returned
  1004.                 $bindVars[] = LibertyMime::normalizeMetaDescription( $pType );
  1005.                 $bindVars[] = LibertyMime::normalizeMetaDescription( $pTitle );
  1006.  
  1007.                 $sql = "
  1008.                     SELECT lmd.`meta_value`
  1009.                     FROM `".BIT_DB_PREFIX."liberty_attachment_meta_data` lmd
  1010.                         INNER JOIN `".BIT_DB_PREFIX."liberty_meta_types` lmtype ON( lmd.`meta_type_id` = lmtype.`meta_type_id` )
  1011.                         INNER JOIN `".BIT_DB_PREFIX."liberty_meta_titles` lmtitle ON( lmd.`meta_title_id` = lmtitle.`meta_title_id` )
  1012.                     WHERE lmd.`attachment_id` = ? AND lmtype.`meta_type` = ? AND lmtitle.`meta_title` = ?";
  1013.                 $ret = $gBitSystem->mDb->getOne( $sql, $bindVars );
  1014.  
  1015.             } elseif( !empty( $pType )) {
  1016.  
  1017.                 // only type given - return array with all vlues of this type
  1018.                 $bindVars[] = LibertyMime::normalizeMetaDescription( $pType );
  1019.  
  1020.                 $sql = "
  1021.                     SELECT lmtitle.`meta_title`, lmd.`meta_value`
  1022.                     FROM `".BIT_DB_PREFIX."liberty_attachment_meta_data` lmd
  1023.                         INNER JOIN `".BIT_DB_PREFIX."liberty_meta_types` lmtype ON( lmd.`meta_type_id` = lmtype.`meta_type_id` )
  1024.                         INNER JOIN `".BIT_DB_PREFIX."liberty_meta_titles` lmtitle ON( lmd.`meta_title_id` = lmtitle.`meta_title_id` )
  1025.                     WHERE lmd.`attachment_id` = ? AND lmtype.`meta_type` = ?";
  1026.                 $ret = $gBitSystem->mDb->getAssoc( $sql, $bindVars );
  1027.  
  1028.             } elseif( !empty( $pTitle )) {
  1029.  
  1030.                 // only title given - return array with all vlues with this title
  1031.                 $bindVars[] = LibertyMime::normalizeMetaDescription( $pTitle );
  1032.  
  1033.                 $sql = "
  1034.                     SELECT lmtype.`meta_type`, lmd.`meta_value`
  1035.                     FROM `".BIT_DB_PREFIX."liberty_attachment_meta_data` lmd
  1036.                         INNER JOIN `".BIT_DB_PREFIX."liberty_meta_types` lmtype ON( lmd.`meta_type_id` = lmtype.`meta_type_id` )
  1037.                         INNER JOIN `".BIT_DB_PREFIX."liberty_meta_titles` lmtitle ON( lmd.`meta_title_id` = lmtitle.`meta_title_id` )
  1038.                     WHERE lmd.`attachment_id` = ? AND lmtitle.`meta_title` = ?";
  1039.                 $ret = $gBitSystem->mDb->getAssoc( $sql, $bindVars );
  1040.  
  1041.             } else {
  1042.  
  1043.                 // nothing given - return nested array based on type and title
  1044.                 $sql = "
  1045.                     SELECT lmd.`attachment_id`, lmd.`meta_value`, lmtype.`meta_type`, lmtitle.`meta_title`
  1046.                     FROM `".BIT_DB_PREFIX."liberty_attachment_meta_data` lmd
  1047.                         INNER JOIN `".BIT_DB_PREFIX."liberty_meta_types` lmtype ON( lmd.`meta_type_id` = lmtype.`meta_type_id` )
  1048.                         INNER JOIN `".BIT_DB_PREFIX."liberty_meta_titles` lmtitle ON( lmd.`meta_title_id` = lmtitle.`meta_title_id` )
  1049.                     WHERE lmd.`attachment_id` = ?";
  1050.  
  1051.                 $result = $gBitSystem->mDb->query( $sql, $bindVars );
  1052.                 while( $aux = $result->fetchRow() ) {
  1053.                     $ret[$aux['meta_type']][$aux['meta_title']] = $aux['meta_value'];
  1054.                 }
  1055.             }
  1056.         }
  1057.         return $ret;
  1058.     }
  1059.  
  1060.     /**
  1061.      * expungeMetaData will remove the meta data for a given attachment
  1062.      *
  1063.      * @param array $pAttachmentId Attachment ID of attachment
  1064.      * @access public
  1065.      * @return query result
  1066.      */
  1067.     function expungeMetaData( $pAttachmentId ) {
  1068.         global $gBitSystem;
  1069.         if( @BitBase::verifyId( $pAttachmentId )) {
  1070.             return $gBitSystem->mDb->query( "DELETE FROM `".BIT_DB_PREFIX."liberty_attachment_meta_data` WHERE `attachment_id` = ?", array( $pAttachmentId ));
  1071.         }
  1072.     }
  1073.  
  1074.     /**
  1075.      * getMetaId
  1076.      *
  1077.      * @param string $pDescription Description of meta key. e.g.: Exif, ID3, Album, Artist
  1078.      * @param string $pTable Table data is stored in - either 'type' or 'title'
  1079.      * @access public
  1080.      * @return meta type or title id on sucess, FALSE on failure
  1081.      */
  1082.     function getMetaId( $pDescription, $pTable = 'type' ) {
  1083.         global $gBitSystem;
  1084.         $ret = FALSE;
  1085.         if( !empty( $pDescription ) && ( $pTable == 'type' || $pTable == 'title' )) {
  1086.             $ret = $gBitSystem->mDb->getOne( "SELECT `meta_{$pTable}_id` FROM `".BIT_DB_PREFIX."liberty_meta_{$pTable}s` WHERE `meta_{$pTable}` = ?", array( LibertyMime::normalizeMetaDescription( $pDescription )));
  1087.         }
  1088.         return $ret;
  1089.     }
  1090.  
  1091.     /**
  1092.      * getMetaDescription
  1093.      *
  1094.      * @param string $pId ID of type or title we want the description for
  1095.      * @param string $pTable Table data is stored in - either 'type' or 'title'
  1096.      * @access public
  1097.      * @return description on sucess, FALSE on failure
  1098.      */
  1099.     function getMetaDescription( $pId, $pTable = 'type' ) {
  1100.         global $gBitSystem;
  1101.         $ret = FALSE;
  1102.         if( @BitBase::verifyId( $pId )) {
  1103.             $ret = $gBitSystem->mDb->getOne( "SELECT `meta_{$pTable}` FROM `".BIT_DB_PREFIX."liberty_meta_{$pTable}s` WHERE `meta_{$pTable}_id` = ?", array( $pId ));
  1104.         }
  1105.         return $ret;
  1106.     }
  1107.  
  1108.     /**
  1109.      * normalizeMetaDescription
  1110.      *
  1111.      * @param string $pDescription Description of meta key. e.g.: Exif, ID3, Album, Artist
  1112.      * @access public
  1113.      * @return normalized meta description that can be used as a guid
  1114.      */
  1115.     public static function normalizeMetaDescription( $pDescription ) {
  1116.         return strtolower( substr( preg_replace( "![^a-zA-Z0-9]!", "", trim( $pDescription )), 0, 250 ));
  1117.     }
  1118.     // }}}
  1119. }
  1120.  
  1121. /**
  1122.  * mime_get_storage_sub_dir_name get a filename based on the uploaded file
  1123.  *
  1124.  * @param array $pFileHash File information provided in $_FILES
  1125.  * @access public
  1126.  * @return appropriate sub dir name
  1127.  */
  1128. if( !function_exists( 'liberty_mime_get_storage_sub_dir_name' )) {
  1129.     function liberty_mime_get_storage_sub_dir_name( $pFileHash = NULL ) {
  1130.         if( !empty( $pFileHash['type'] ) ) {
  1131.             // type is from upload file hash
  1132.             $mimeType = $pFileHash['type'];
  1133.         } elseif( !empty( $pFileHash['mime_type'] ) ) {
  1134.             // mime_type is from liberty_files
  1135.             $mimeType = $pFileHash['mime_type'];
  1136.         }
  1137.  
  1138.         if( !empty( $mimeType ) && strstr( $mimeType, "/" )) {
  1139.             $ret = strtolower( preg_replace( "!/.*$!", "", $mimeType ));
  1140.             // if we only got 'application' we will use the file extenstion
  1141.             if( $ret == 'application' && !empty( $pFileHash['name'] ) && ( $pos = strrpos( $pFileHash['name'], "." )) !== FALSE ) {
  1142.                 $ret = strtolower( substr( $pFileHash['name'], $pos + 1 ));
  1143.             }
  1144.         }
  1145.  
  1146.         // append an 's' to not create an image and images dir side by side (legacy reasons)
  1147.         if( empty( $ret ) || $ret == 'image' ) {
  1148.             $ret = 'images';
  1149.         }
  1150.         return $ret;
  1151.     }
  1152. }
  1153.  
  1154. /**
  1155.  * liberty_mime_get_storage_branch - get url to store files for the feature site_upload_dir. It creates a calculable hierarchy of directories
  1156.  *
  1157.  * @access public
  1158.  * @author Christian Fowler<spider@steelsun.com>
  1159.  * @param $pParamHash key=>value pairs to determine path. Possible keys in descending directory depth are: 'user_id' indicates the 'users/.../<user_id>' branch or use the 'common' branch if null, 'package' - any desired directory below the StoragePath. this will be created if it doesn't exist, 'sub_dir' -  the sub-directory in the package organization directory, this is often a primary id such as attachment_id
  1160.  * @return string full path on local filsystem to store files.
  1161.  */
  1162. if( !function_exists( 'liberty_mime_get_storage_branch' )) {
  1163.     function liberty_mime_get_storage_branch( $pParamHash ) {
  1164.         // *PRIVATE FUNCTION. GO AWAY! DO NOT CALL DIRECTLY!!!
  1165.         global $gBitSystem;
  1166.         $pathParts = array();
  1167.  
  1168.  
  1169.         if( $pUserId = BitBase::getParameter( $pParamHash, 'user_id' ) ) {
  1170.             $pathParts[] = 'users';
  1171.             $pathParts[] = (int)($pUserId % 1000);
  1172.             $pathParts[] = $pUserId;
  1173.         } elseif( $pAttachmentId = BitBase::getParameter( $pParamHash, 'attachment_id' ) ) {
  1174.             $pathParts[] = 'attachments';
  1175.             $pathParts[] = (int)($pAttachmentId % 1000);
  1176.             $pathParts[] = $pAttachmentId;
  1177.         } else {
  1178.             $pathParts[] = 'common';
  1179.         }
  1180.  
  1181.         if( $pPackage = BitBase::getParameter( $pParamHash, 'package' ) ) {
  1182.             $pathParts[] = $pPackage;
  1183.         }
  1184.         // In case $pSubDir is multiple levels deep we'll need to mkdir each directory if they don't exist
  1185.         if( $pSubDir = BitBase::getParameter( $pParamHash, 'sub_dir' ) ){
  1186.             $pSubDirParts = preg_split('#/#',$pSubDir);
  1187.             foreach ($pSubDirParts as $subDir) {
  1188.                 $pathParts[] = $subDir;
  1189.             }
  1190.         } else {
  1191.             $pSubDir = liberty_mime_get_storage_sub_dir_name( $pParamHash );
  1192.         }
  1193.  
  1194.         $fullPath = implode( $pathParts, '/' ).'/';
  1195.         if( BitBase::getParameter( $pParamHash, 'create_dir', TRUE ) ){
  1196.             if( !file_exists( STORAGE_PKG_PATH.$fullPath ) ) {
  1197.                 mkdir_p( STORAGE_PKG_PATH.$fullPath );
  1198.             }
  1199.         }
  1200.  
  1201.         return $fullPath;
  1202.     }
  1203. }
  1204.  
  1205. if( !function_exists( 'liberty_mime_get_storage_url' )) {
  1206.     function liberty_mime_get_storage_url( $pParamHash ) {
  1207.         return STORAGE_PKG_URL.liberty_mime_get_storage_branch( $pParamHash );
  1208.     }
  1209. }
  1210.  
  1211. if( !function_exists( 'liberty_mime_get_storage_path' )) {
  1212.     function liberty_mime_get_storage_path( $pParamHash ) {
  1213.         return STORAGE_PKG_PATH.liberty_mime_get_storage_branch( $pParamHash );
  1214.     }
  1215. }
  1216.  
  1217. if( !function_exists( 'liberty_mime_get_source_url' )) {
  1218.     function liberty_mime_get_source_url( $pParamHash ) {
  1219.         $fileName = BitBase::getParameter( $pParamHash, 'file_name' );
  1220.         if( empty( $pParamHash['package'] ) ) {
  1221.             $pParamHash['package'] = liberty_mime_get_storage_sub_dir_name( array( 'mime_type' => BitBase::getParameter( $pParamHash, 'mime_type' ), 'name' => $fileName ) );
  1222.         }
  1223.         if( empty( $pParamHash['sub_dir'] ) ) {
  1224.             $pParamHash['sub_dir'] = BitBase::getParameter( $pParamHash, 'attachment_id' );
  1225.         }
  1226.         $defaultFileName = liberty_mime_get_default_file_name( $fileName, $pParamHash['mime_type'] );
  1227.         $fileBranch = liberty_mime_get_storage_branch( $pParamHash );
  1228.         if( file_exists( STORAGE_PKG_PATH.$fileBranch.$defaultFileName ) ) {
  1229.             $ret = STORAGE_PKG_URL.$fileBranch.$defaultFileName;
  1230.         } else {
  1231.             $ret = STORAGE_PKG_URL.$fileBranch.basename( BitBase::getParameter( $pParamHash, 'file_name' ) );
  1232.         }
  1233.         return $ret;
  1234.     }
  1235. }
  1236.  
  1237. if( !function_exists( 'liberty_mime_get_source_file' )) {
  1238.     function liberty_mime_get_source_file( $pParamHash ) {
  1239.         $fileName = BitBase::getParameter( $pParamHash, 'file_name' );
  1240.         if( empty( $pParamHash['package'] ) ) {
  1241.             $pParamHash['package'] = liberty_mime_get_storage_sub_dir_name( array( 'mime_type' => BitBase::getParameter( $pParamHash, 'mime_type' ), 'name' => $fileName ) );
  1242.         }
  1243.         if( empty( $pParamHash['sub_dir'] ) ) {
  1244.             $pParamHash['sub_dir'] = BitBase::getParameter( $pParamHash, 'attachment_id' );
  1245.         }
  1246.         $defaultFileName = liberty_mime_get_default_file_name( $fileName, $pParamHash['mime_type'] );
  1247.         $ret = STORAGE_PKG_PATH.liberty_mime_get_storage_branch( $pParamHash ).$defaultFileName;
  1248.         if( !file_exists( $ret ) ) {
  1249.             $ret = STORAGE_PKG_PATH.liberty_mime_get_storage_branch( $pParamHash ).basename( BitBase::getParameter( $pParamHash, 'file_name' ) );
  1250.         }
  1251.         return $ret;
  1252.     }
  1253. }
  1254.  
  1255. if( !function_exists( 'liberty_mime_get_default_file_name' )) {
  1256.     function liberty_mime_get_default_file_name( $pFileName, $pMimeType ) {
  1257.         global $gBitSystem;
  1258.         if( $gBitSystem->isFeatureActive( 'liberty_originalize_file_names' ) ) {
  1259.             $ret = 'original.'.$gBitSystem->getMimeExtension( $pMimeType );
  1260.         } else {
  1261.             $ret = $pFileName;
  1262.         }
  1263.         return $ret;
  1264.     }
  1265. }
  1266.  
  1267. /* vim: :set fdm=marker : */
  1268.  
  1269. ?>

Documentation generated on Wed, 29 Jul 2015 13:56:55 +0000 by phpDocumentor 1.5.0-lsces