Source for file LibertyMime.php
Documentation is available at LibertyMime.php
* Manages liberty Uploads
require_once( LIBERTY_PKG_PATH. 'LibertyContent.php' );
// load the image processor plugin, check for loaded 'gd' since that is the default processor, and config might not be set.
require_once( LIBERTY_PKG_PATH. "plugins/processor.". $gBitSystem->getConfig( 'image_processor','gd' ). ".php" );
// maximum size of the 'original' image when converted to jpg
define( 'MAX_THUMBNAIL_DIMENSION', 99999 );
* load the attachments for a given content id and then stuff them in mStorage
* @param array $pContentId
* @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
public function load( $pContentId = NULL, $pPluginParams = NULL ) {
// assume a derived class has joined on the liberty_content table, and loaded it's columns already.
$contentId = ( @BitBase::verifyId( $pContentId ) ? $pContentId : $this->mContentId );
if( @BitBase::verifyId( $contentId )) {
// don't loadAttachmentPreferences() when we are forcing the installer since it breaks the login process before 2.1.0-beta
$query = "SELECT * FROM `". BIT_DB_PREFIX. "liberty_attachments` la WHERE la.`content_id`=? ORDER BY la.`pos` ASC, la.`attachment_id` ASC";
if( $result = $this->mDb->query( $query,array( (int) $contentId ))) {
$this->mStorage = array();
while( $row = $result->fetchRow() ) {
if( !empty( $row['is_primary'] ) ) {
// used by edit tpl's among other things
$this->mInfo['primary_attachment_id'] = $row['attachment_id'];
} elseif( !$this->getField( 'primary_attachment_id' ) && !empty( $row['attachment_id'] ) ) {
// primary was not set by the above, default to first row. might be reset by later iterations via if is_primary above
$this->mInfo['primary_attachment_id'] = $row['attachment_id'];
if( $func = $gLibertySystem->getPluginFunction( $row['attachment_plugin_guid'], 'load_function', 'mime' )) {
// we will pass the preferences by reference that the plugin can easily update them
$this->mStorage[$row['attachment_id']] = $func( $row, $this->mStoragePrefs[$row['attachment_id']], $pPluginParams );
print "No load_function for ". $row['attachment_plugin_guid'];
* @param array $pStoreHash contains all data to store the gallery
* @return bool TRUE on success, FALSE if store could not occur. If FALSE, $this->mErrors will have reason why
public function store( &$pStoreHash ) {
// make sure all the data is in order
$this->mDb->StartTrans();
// files have been uploaded
if( !empty( $pStoreHash['upload_store']['files'] ) && is_array( $pStoreHash['upload_store']['files'] )) {
foreach( $pStoreHash['upload_store']['files'] as $key => $upload ) {
// if we don't have an upload, we'll simply update the file settings using the mime plugins
if( empty( $upload['tmp_name'] )) {
if( @BitBase::verifyId( $upload['attachment_id'] )) {
// since the form might have all options unchecked, we need to call the update function regardless
// currently i can't think of a better way to get the plugin guid back when $pStoreHash[plugin] is
// empty. - xing - Friday Jul 11, 2008 20:21:18 CEST
if( !empty( $this->mStorage[$upload['attachment_id']] )) {
$attachment = $this->mStorage[$upload['attachment_id']];
if( !empty( $pStoreHash['plugin'][$upload['attachment_id']][$attachment['attachment_plugin_guid']] )) {
$data = $pStoreHash['plugin'][$upload['attachment_id']][$attachment['attachment_plugin_guid']];
if( !$this->updateAttachmentParams( $upload['attachment_id'], $attachment['attachment_plugin_guid'], $data )) {
$this->mErrors['attachment_update'] = "There was a problem updating the file settings.";
$storeRow = $pStoreHash['upload_store'];
unset ( $storeRow['files'] );
// copy by reference that filetype changes are made in lookupMimeHandler()
$storeRow['upload'] = &$upload;
if( isset ( $pStoreHash['thumbnail'] ) ) {
$storeRow['upload']['thumbnail'] = $pStoreHash['thumbnail'];
// when content is created the content_id is only available after LibertyContent::store()
$storeRow['content_id'] = $pStoreHash['content_id'];
// let the plugin do the rest
$guid = $gLibertySystem->lookupMimeHandler( $upload );
// finally, we need to update the original hash with the new values
$pStoreHash['upload_store']['files'][$key] = $storeRow;
// some mime plugins might not have file uploads - these plugins will tell us what mime handlers they are using
if( !empty( $pStoreHash['mimeplugin'] ) && is_array( $pStoreHash['mimeplugin'] )) {
foreach( $pStoreHash['mimeplugin'] as $guid => $storeRow ) {
// check to see if we have anything worth storing in the array
if( !empty( $plugin_store )) {
// when content is created the content_id is only available after LibertyContent::store()
$storeRow['content_id'] = $pStoreHash['content_id'];
// deal with the primary attachment after we've dealt with all the files
$pStoreHash['liberty_attachments']['primary'],
$pStoreHash['content_id'],
empty( $pStoreHash['liberty_attachments']['auto_primary'] ) || $pStoreHash['liberty_attachments']['auto_primary'] ? TRUE : FALSE
// Roll back if something went wrong
$this->mDb->CompleteTrans();
$this->mDb->RollbackTrans();
* pluginStore will use a given plugin to store uploaded file data
* @param string $pGuid GUID of plugin
* @param array $pStoreHash Data to be prcessed and stored by the plugin
* @param boolean $pUpdate set to TRUE if this is just an update
* @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
public function pluginStore( &$pStoreHash, $pGuid, $pUpdate = FALSE ) {
if( !empty( $pStoreHash ) && $verify_function = $gLibertySystem->getPluginFunction( $pGuid, 'verify_function' )) {
// pass along a pointer to the content object
$pStoreHash['this'] = &$this;
// verify the uploaded file using the plugin
if( $verify_function( $pStoreHash )) {
if( $process_function = $gLibertySystem->getPluginFunction( $pGuid, (( $pUpdate ) ? 'update_function' : 'store_function' ))) {
if( !$process_function( $pStoreHash )) {
$this->mErrors['store_function'] = tra( 'No suitable store function found.' );
$this->mErrors['verify_function'] = tra( 'No suitable verify function found.' );
* Verify content that is about to be stored
* @param array $pStoreHash hash of all data that needs to be stored in the database
* @return TRUE on success, FALSE on failure - mErrors will contain reason
* @todo If one of the uploaded files is an update, place the attachment_id with the upload hash in $_FILES or in _files_override
public function verify( &$pParamHash ) {
global $gBitUser, $gLibertySystem;
// check to see if we have any files to upload
if( isset ( $pParamHash['_files_override'] )) {
// we have been passed in a manually stuffed files attachment, such as a custom uploader would have done.
// process this, and skip over $_FILES
$uploads = $pParamHash['_files_override'];
} elseif( !empty( $_FILES )) {
// we have some _FILES hanging around we will gobble up. This is inherently dagnerous chewing up a _FILES like this as
// it can cause premature storing of a _FILE if you are trying to store multiple pieces of content at once.
foreach( $_FILES as $key => $file ) {
if( !empty( $file['name'] ) || !empty( $file['attachment_id'] )) {
if( !empty( $uploads ) ) {
// don't check for p_liberty_attach_attachments permission on bitpermuser class so registration with avatar upload works
$pParamHash['upload_store']['no_perm_check'] = TRUE;
// check for the required permissions to upload a file to the liberty attachments area
if( !empty( $uploads ) && empty( $pParamHash['no_perm_check'] )) {
$this->mErrors['permission'] = tra( 'You do not have permission to upload attachments.' );
// primary attachment. Allow 'none' to clear the primary.
if( !@BitBase::verifyId( $pParamHash['liberty_attachments']['primary'] ) && ( empty( $pParamHash['liberty_attachments']['primary'] ) || $pParamHash['liberty_attachments']['primary'] != 'none' ) ) {
$pParamHash['liberty_attachments']['primary'] = NULL;
// if we have an error we get them all by checking parent classes for additional errors
// check errors of LibertyContent since LibertyMime means to override the parent verify
* getThumbnailUrl will fetch the primary thumbnail for a given content. If nothing has been set, it will fetch the last thumbnail it can find.
* @param array $pInfoHash
* @return boolean TRUE on success, FALSE on failure - $this->mErrors will contain reason for failure
public function getThumbnailUrl( $pSize= 'small', $pInfoHash= NULL, $pSecondary= NULL, $pDefault= TRUE ) {
if( !empty( $pInfoHash ) ) {
// do some stuff if we are given a hash of stuff
} elseif( $this->isValid() && !empty( $this->mStorage ) ) {
foreach( array_keys( $this->mStorage ) as $attachmentId ) {
if( !empty( $this->mStorage[$attachmentId]['is_primary'] ) ) {
if( !empty( $this->mStorage[$attachmentId]['thumbnail_url'][$pSize] )) {
$ret = $this->mStorage[$attachmentId]['thumbnail_url'][$pSize];
if( $pDefault && empty( $ret ) ) {
$ret = parent::getThumbnailUrl( $pSize, $pInfoHash, $pSecondary );
* updateAttachmentParams will update attachment parameters
* @param numeric $pAttachmentId attachment_id of the item we want the prefs from (optional)
* @param string $pPluginGuid GUID of the plugin that should process the data
* @param array $pParamHash Data to be processed by the plugin
* @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
if( BitBase::verifyId( $pAttachmentId )) {
if( !empty( $this ) && !empty( $this->mStorage[$pAttachmentId] )) {
$file = $this->mStorage[$pAttachmentId];
if( @BitBase::verifyId( $file['attachment_id'] ) && !empty( $pPluginGuid ) && ( $update_function = $gLibertySystem->getPluginFunction( $pPluginGuid, 'update_function', 'mime' ))) {
if( $update_function( $file, $pParamHash )) {
if( !empty( $file['errors'] )) {
$this->mErrors['param_update'] = $file['errors'];
$this->mErrors['param_update'] = tra( 'There was an unspecified error while updating the file.' );
* verifyAttachment will perform a generic check if a file is valid for processing
* @param array $pFile file array from $_FILES
* @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
if( !empty( $pFile['tmp_name'] ) && is_file( $pFile['tmp_name'] ) && empty( $pFile['error'] ) || !empty( $pFile['attachment_id'] )) {
* Increment the item hit flag by 1
* @param numeric $pAttachmentId Attachment ID
* @return adodb query result or FALSE
* @note we're abusing the hits column for download count.
global $gBitUser, $gBitSystem;
if( @BitBase::verifyId( $pAttachmentId ) && $attachment = static::loadAttachment( $pAttachmentId )) {
if( !$gBitUser->isRegistered() || ( $gBitUser->isRegistered() && $gBitUser->mUserId != $attachment['user_id'] )) {
$bindVars = array( $pAttachmentId );
if( $gBitSystem->mDb->getOne( "SELECT `attachment_id` FROM `". BIT_DB_PREFIX. "liberty_attachments` WHERE `attachment_id` = ? AND `hits` IS NULL", $bindVars )) {
$query = "UPDATE `". BIT_DB_PREFIX. "liberty_attachments` SET `hits` = 1 WHERE `attachment_id` = ?";
$query = "UPDATE `". BIT_DB_PREFIX. "liberty_attachments` SET `hits` = `hits`+1 WHERE `attachment_id` = ?";
return $gBitSystem->mDb->query( $query, $bindVars );
// {{{ =================== Storage Directory Methods ====================
if( empty( $pParamHash ) && !empty( $this ) ) {
$pParamHash = $this->mInfo;
if( empty( $pParamHash ) && !empty( $this ) ) {
$pParamHash = $this->mInfo;
* getStoragePath - get path to store files for the feature site_upload_dir. It creates a calculable hierarchy of directories
* @author Christian Fowler<spider@steelsun.com>
* @param $pSubDir any desired directory below the StoragePath. this will be created if it doesn't exist
* @param $pCommon indicates not to use the 'common' branch, and not the 'users/.../<user_id>' branch
* @param $pRootDir override BIT_ROOT_DIR with a custom absolute path - useful for areas where no we access should be allowed
* @return string full path on local filsystem to store files.
* getStorageBranch - get url to store files for the feature site_upload_dir. It creates a calculable hierarchy of directories
* @author Christian Fowler<spider@steelsun.com>
* @param $pSubDir any desired directory below the StoragePath. this will be created if it doesn't exist
* @param $pUserId indicates the 'users/.../<user_id>' branch or use the 'common' branch if null
* @param $pRootDir **deprecated, unused, will be removed in future relase**.
* @return string full path on local filsystem to store files.
* getStorageSubDirName get a filename based on the uploaded file
* @param array $pFileHash File information provided in $_FILES
* @return appropriate sub dir name
if( !empty( $pFileHash['mime_type'] ) && strstr( $pFileHash['mime_type'], "/" )) {
// if we only got 'application' we will use the file extenstion
if( $ret == 'application' && !empty( $pFileHash['name'] ) && ( $pos = strrpos( $pFileHash['name'], "." )) !== FALSE ) {
// append an 's' to not create an image and images dir side by side (legacy reasons)
if( empty( $ret ) || $ret == 'image' ) {
* validateStoragePath make sure that the file/dir you are trying to delete is valid
* @param array $pPath absolute path to the file/dir we want to validate
* @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
// file_exists checks for file or directory
if( !empty( $pPath ) && $pPath = realpath( $pPath )) {
// {{{ =================== Attachment Methods ====================
* Get a list of all available attachments
* @param array $pListHash
* @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
global $gLibertySystem, $gBitUser, $gBitSystem;
// initialise some variables
$attachments = $ret = $bindVars = array();
$whereSql = $joinSql = $selectSql = '';
// only admin may view attachments from other users
$pListHash['user_id'] = $gBitUser->mUserId;
if( !empty( $pListHash['user_id'] ) ) {
$whereSql .= empty( $whereSql ) ? ' WHERE ' : ' AND ';
$whereSql .= " la.user_id = ? ";
$bindVars[] = $pListHash['user_id'];
if( !empty( $pListHash['content_id'] ) ) {
$whereSql .= empty( $whereSql ) ? ' WHERE ' : ' AND ';
$whereSql .= " la.`content_id` = ? ";
$selectSql .= " , la.`content_id` ";
$bindVars[] = $pListHash['content_id'];
$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";
$result = $this->mDb->query( $query, $bindVars, $pListHash['max_records'], $pListHash['offset'] );
while( $res = $result->fetchRow() ) {
foreach( $attachments as $attachment ) {
if( $loadFunc = $gLibertySystem->getPluginFunction( $attachment['attachment_plugin_guid'], 'load_function', 'mime' )) {
/* @$prefs - quick hack to stop LibertyMime plugins from breaking until migration to LibertyMime is complete
* see expected arguments of liberty/plugins/mime.default.php::mime_default_load -wjames5
$ret[$attachment['attachment_id']] = $loadFunc( $attachment, $prefs );
$query = "SELECT COUNT(*)
INNER JOIN `". BIT_DB_PREFIX. "users_users` uu ON(la.`user_id` = uu.`user_id`)
$pListHash['cant'] = $this->mDb->getOne( $query, $bindVars );
* Expunges the content deleting attached attachments
if( !empty( $this->mStorage ) && count( $this->mStorage )) {
* expunge attachment from the database (and file system via the plugin if required)
* @param numeric $pAttachmentId attachment id of the item that should be deleted
* @return TRUE on success, FALSE on failure
global $gLibertySystem, $gBitUser;
if( @$this->verifyId( $pAttachmentId ) ) {
$sql = "SELECT `attachment_plugin_guid`, `user_id` FROM `". BIT_DB_PREFIX. "liberty_attachments` WHERE `attachment_id` = ?";
if(( $row = $this->mDb->getRow( $sql, array( $pAttachmentId ))) && ( $this->isOwner( $row ) || $gBitUser->isAdmin() )) {
// check if we have the means available to remove this attachment
if(( $guid = $row['attachment_plugin_guid'] ) && $expungeFunc = $gLibertySystem->getPluginFunction( $guid, 'expunge_function', 'mime' )) {
// --- Do the final cleanup of liberty related tables ---
// there might be situations where we remove user images including portrait, avatar or logo
// This needs to happen before the plugin can do it's work due to constraints
$types = array( 'portrait', 'avatar', 'logo' );
foreach( $types as $type ) {
$sql = "UPDATE `". BIT_DB_PREFIX. "users_users` SET `{$type}_attachment_id` = NULL WHERE `{$type}_attachment_id` = ?";
$this->mDb->query( $sql, array( $pAttachmentId ));
if( $expungeFunc( $pAttachmentId )) {
// Delete the attachment meta data, prefs and record.
$sql = "DELETE FROM `". BIT_DB_PREFIX. "liberty_attachment_meta_data` WHERE `attachment_id` = ?";
$this->mDb->query( $sql, array( $pAttachmentId ));
$sql = "DELETE FROM `". BIT_DB_PREFIX. "liberty_attachment_prefs` WHERE `attachment_id` = ?";
$this->mDb->query( $sql, array( $pAttachmentId ));
$sql = "DELETE FROM `". BIT_DB_PREFIX. "liberty_attachments` WHERE `attachment_id`=?";
$this->mDb->query( $sql, array( $pAttachmentId ));
// Remove attachment from memory
unset ( $this->mStorage[$pAttachmentId] );
print ( "Expunge function not found for this content!" );
* loadAttachment will load details of a given attachment
* @param numeric $pAttachmentId Attachment ID of the attachment
* @param array $pParams optional parameters that might contain information like display thumbnail size
* @return attachment details
public static function loadAttachment( $pAttachmentId, $pParams = NULL ) {
global $gLibertySystem, $gBitSystem;
if( @BitBase::verifyId( $pAttachmentId )) {
$query = "SELECT * FROM `". BIT_DB_PREFIX. "liberty_attachments` la WHERE la.`attachment_id`=?";
if( $result = $gBitSystem->mDb->query( $query, array( (int) $pAttachmentId ))) {
if( $row = $result->fetchRow() ) {
if( $func = $gLibertySystem->getPluginFunction( $row['attachment_plugin_guid'], 'load_function', 'mime' )) {
$sql = "SELECT `pref_name`, `pref_value` FROM `". BIT_DB_PREFIX. "liberty_attachment_prefs` WHERE `attachment_id` = ?";
$prefs = $gBitSystem->mDb->getAssoc( $sql, array( $pAttachmentId ));
$ret = $func( $row, $prefs, $pParams );
* getAttachment will load details of a given attachment
* @param numeric $pAttachmentId Attachment ID of the attachment
* @param array $pParams optional parameters that might contain information like display thumbnail size
* @return attachment details
public function getAttachment( $pAttachmentId, $pParams = NULL ) {
global $gLibertySystem, $gBitSystem;
if( @BitBase::verifyId( $pAttachmentId )) {
$query = "SELECT * FROM `". BIT_DB_PREFIX. "liberty_attachments` la WHERE la.`attachment_id`=?";
if( $result = $gBitSystem->mDb->query( $query, array( (int) $pAttachmentId ))) {
if( $row = $result->fetchRow() ) {
if( $func = $gLibertySystem->getPluginFunction( $row['attachment_plugin_guid'], 'load_function', 'mime' )) {
// if the object is available, we'll copy the preferences by reference to allow the plugin to update them as needed
if( !empty( $this ) && !empty( $this->mStoragePrefs[$pAttachmentId] )) {
$prefs = static::getAttachmentPreferences( $pAttachmentId );
$ret = $func( $row, $prefs, $pParams );
* setPrimaryAttachment will set is_primary 'y' for the specified
* attachment and will ensure that all others are set to 'n'
* @param mixed $pAttachmentId attachment id of the item we want to
* set as the primary attachment. Use 'none' to clear.
* @param numeric $pContentId content id we are working with.
* @param boolean $pAutoPrimary automatically set primary if there is only
* one attachment. Defaults to true.
* @return TRUE on success, FALSE on failure
public function setPrimaryAttachment( $pAttachmentId = NULL, $pContentId = NULL, $pAutoPrimary = TRUE ) {
// If we are not given an attachment id but we where told the
// content_id and we are supposed to auto set the primary then
// figure out which one it is
if( !@BitBase::verifyId( $pAttachmentId ) && ( empty( $pAttachmentId ) || $pAttachmentId != 'none' ) && @BitBase::verifyId( $pContentId ) && $pAutoPrimary ) {
INNER JOIN `". BIT_DB_PREFIX. "liberty_attachments` la ON( lc.`content_id` = la.`content_id` )
WHERE lc.`content_id` = ?";
$pAttachmentId = $this->mDb->getOne( $query, array( $pContentId ));
// If we have an attachment_id we'll set it to this
if( @BitBase::verifyId( $pAttachmentId )) {
// get attachment we want to set primary
// Clear old primary. There can only be one!
// now update the attachment to is_primary
SET `is_primary` = ? WHERE `attachment_id` = ?";
$this->mDb->query( $query, array( 'y', $pAttachmentId ));
// Otherwise, are we supposed to clear the primary entirely?
} elseif( @BitBase::verifyId( $pContentId ) && !empty( $pAttachmentId ) && $pAttachmentId == 'none' ) {
* clearPrimaryAttachment will remove the primary flag for all attachments
* with the given content_id
* @param numeric the content_id for which primary should be unset.
if( @BitBase::verifyId( $pContentId )) {
SET `is_primary` = ? WHERE `content_id` = ?";
$this->mDb->query( $query, array( NULL, $pContentId ));
* === Attachment Preferences ===
* Returns the attachment preference value for the passed in key.
* @param string Hash key for the mPrefs value
* @param string Default value to return if the preference is empty
* @param int Optional content_id for arbitrary content preference
if( @BitBase::verifyId( $pAttachmentId ) && !empty( $pPrefName )) {
* Returns the attachment preferences for a given attachment id
* @param string Hash key for the mPrefs value
* @param string Default value to return if the preference is empty
* @param int Optional content_id for arbitrary content preference
// we're loading from within object
// if the object isn't loaded, we need to get the prefs from the database
$sql = "SELECT `pref_name`, `pref_value` FROM `". BIT_DB_PREFIX. "liberty_attachment_prefs` WHERE `attachment_id` = ?";
$ret = $gBitSystem->mDb->getAssoc( $sql, array( $pAttachmentId ));
* setAttachmentPreference will set an attachment preferences without storing it in the database
* @param array $pAttachmentId
* @param array $pPrefName
* @param array $pPrefValue
* @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
* Saves a preference to the liberty_content_prefs database table with the
* given pref name and value. If the value is NULL, the existing value will
* be delete and the value will not be saved. However, a zero will be
* @param string Hash key for the prefs value
* @param string Value for the prefs hash key
if( @BitBase::verifyId( $pAttachmentId ) && !empty( $pPrefName )) {
$query = "DELETE FROM `". BIT_DB_PREFIX. "liberty_attachment_prefs` WHERE `attachment_id` = ? AND `pref_name` = ?";
$bindvars = array( $pAttachmentId, $pPrefName );
$result = $gBitSystem->mDb->query( $query, $bindvars );
$query = "INSERT INTO `". BIT_DB_PREFIX. "liberty_attachment_prefs` (`attachment_id`,`pref_name`,`pref_value`) VALUES(?, ?, ?)";
$bindvars[] = substr( $pPrefValue, 0, 250 );
$result = $gBitSystem->mDb->query( $query, $bindvars );
// this function might be called statically
if( !empty( $this ) && $this->isValid() ) {
* loadPreferences of the currently loaded object or pass in to get preferences of a specific content_id
* @param numeric $pContentId content_id of the item we want the prefs from (optional)
* @param numeric $pAttachmentId attachment_id of the item we want the prefs from (optional)
* @return array of preferences if $pContentId or $pAttachmentId is set or pass preferences on to $this->mStoragePrefs
} elseif( @BitBase::verifyId( $pContentId )) {
SELECT lap.`attachment_id`, lap.`pref_name`, lap.`pref_value`
INNER JOIN `". BIT_DB_PREFIX. "liberty_attachments` la ON (la.`attachment_id` = lap.`attachment_id`)
WHERE la.`content_id` = ?";
$result = $gBitSystem->mDb->query( $sql, array( $pContentId ));
while( $aux = $result->fetchRow() ) {
$ret[$aux['attachment_id']][$aux['pref_name']] = $aux['pref_value'];
// if neither a content id nor an attachment id are given, we will place the results in mStoragePrefs
if( !empty( $store_prefs )) {
* expungeAttachmentPreferences will remove all attachment preferences of a given attachmtent
* @param array $pAttachmentId attachemnt we want to remove the prefs for
* @return TRUE on success, FALSE on failure
if( @BitBase::verifyId( $pAttachmentId ) ) {
$sql = "DELETE FROM `". BIT_DB_PREFIX. "liberty_attachment_prefs` WHERE `attachment_id` = ?";
$gBitSystem->mDb->query( $sql, array( $pAttachmentId ));
if( BitBase::verifyId( $pAttachmentId ) ) {
// {{{ =================== Meta Methods ====================
* @param numeric $pAttachmentId AttachmentID the data belongs to
* @param string $pType Type of data. e.g.: EXIF, ID3. This will default to "Meta Data"
* @param array $pStoreHash Data that needs to be stored in the database in an array. The key will be used as the meta_title.
* @return TRUE on success, FALSE on failure
function storeMetaData( $pAttachmentId, $pType = "Meta Data", $pStoreHash ) {
if( @BitBase::verifyId( $pAttachmentId ) && !empty( $pType ) && !empty( $pStoreHash )) {
foreach( $pStoreHash as $key => $data ) {
// store the data in the meta table
'attachment_id' => $pAttachmentId,
'meta_type_id' => LibertyMime::storeMetaId( $pType, 'type' ),
'meta_title_id' => LibertyMime::storeMetaId( $key, 'title' ),
// remove this entry from the database if it already exists
$gBitSystem->mDb->query( "DELETE FROM `". BIT_DB_PREFIX. "liberty_attachment_meta_data` WHERE `attachment_id` = ? AND `meta_type_id` = ? AND `meta_title_id` = ?", $meta );
// don't insert empty lines
$meta['meta_value'] = $data;
$gBitSystem->mDb->associateInsert( BIT_DB_PREFIX. "liberty_attachment_meta_data", $meta );
* @param string $pDescription Description of meta key. e.g.: Exif, ID3, Album, Artist
* @param string $pTable Table data is stored in - either 'type' or 'title'
* @return newly stored ID on success, FALSE on failure
function storeMetaId( $pDescription, $pTable = 'type' ) {
if( !empty( $pDescription )) {
if( !( $ret = LibertyMime::getMetaId( $pDescription, $pTable ))) {
"meta_{$pTable}_id" => $gBitSystem->mDb->GenID( "liberty_meta_{$pTable}s_id_seq" ),
"meta_{$pTable}" => LibertyMime::normalizeMetaDescription( $pDescription ),
$gBitSystem->mDb->associateInsert( BIT_DB_PREFIX. "liberty_meta_{$pTable}s", $store );
$ret = $store["meta_{$pTable}_id"];
* @param numeric $pAttachmentId AttachmentID the data belongs to
* @param string $pType Type of data. e.g.: EXIF, ID3.
* @param string $pTitle Title of data. e.g.: Artist, Album.
* @return array with meta data on success, FALSE on failure
* $note: Output format varies depending on requested data
public static function getMetaData( $pAttachmentId, $pType = NULL, $pTitle = NULL ) {
if( @BitBase::verifyId( $pAttachmentId )) {
$bindVars = array( $pAttachmentId );
if( !empty( $pType ) && !empty( $pTitle )) {
// we have a type and title - only one entry will be returned
$bindVars[] = LibertyMime::normalizeMetaDescription( $pType );
$bindVars[] = LibertyMime::normalizeMetaDescription( $pTitle );
INNER JOIN `". BIT_DB_PREFIX. "liberty_meta_types` lmtype ON( lmd.`meta_type_id` = lmtype.`meta_type_id` )
INNER JOIN `". BIT_DB_PREFIX. "liberty_meta_titles` lmtitle ON( lmd.`meta_title_id` = lmtitle.`meta_title_id` )
WHERE lmd.`attachment_id` = ? AND lmtype.`meta_type` = ? AND lmtitle.`meta_title` = ?";
$ret = $gBitSystem->mDb->getOne( $sql, $bindVars );
} elseif( !empty( $pType )) {
// only type given - return array with all vlues of this type
$bindVars[] = LibertyMime::normalizeMetaDescription( $pType );
SELECT lmtitle.`meta_title`, lmd.`meta_value`
INNER JOIN `". BIT_DB_PREFIX. "liberty_meta_types` lmtype ON( lmd.`meta_type_id` = lmtype.`meta_type_id` )
INNER JOIN `". BIT_DB_PREFIX. "liberty_meta_titles` lmtitle ON( lmd.`meta_title_id` = lmtitle.`meta_title_id` )
WHERE lmd.`attachment_id` = ? AND lmtype.`meta_type` = ?";
$ret = $gBitSystem->mDb->getAssoc( $sql, $bindVars );
} elseif( !empty( $pTitle )) {
// only title given - return array with all vlues with this title
$bindVars[] = LibertyMime::normalizeMetaDescription( $pTitle );
SELECT lmtype.`meta_type`, lmd.`meta_value`
INNER JOIN `". BIT_DB_PREFIX. "liberty_meta_types` lmtype ON( lmd.`meta_type_id` = lmtype.`meta_type_id` )
INNER JOIN `". BIT_DB_PREFIX. "liberty_meta_titles` lmtitle ON( lmd.`meta_title_id` = lmtitle.`meta_title_id` )
WHERE lmd.`attachment_id` = ? AND lmtitle.`meta_title` = ?";
$ret = $gBitSystem->mDb->getAssoc( $sql, $bindVars );
// nothing given - return nested array based on type and title
SELECT lmd.`attachment_id`, lmd.`meta_value`, lmtype.`meta_type`, lmtitle.`meta_title`
INNER JOIN `". BIT_DB_PREFIX. "liberty_meta_types` lmtype ON( lmd.`meta_type_id` = lmtype.`meta_type_id` )
INNER JOIN `". BIT_DB_PREFIX. "liberty_meta_titles` lmtitle ON( lmd.`meta_title_id` = lmtitle.`meta_title_id` )
WHERE lmd.`attachment_id` = ?";
$result = $gBitSystem->mDb->query( $sql, $bindVars );
while( $aux = $result->fetchRow() ) {
$ret[$aux['meta_type']][$aux['meta_title']] = $aux['meta_value'];
* expungeMetaData will remove the meta data for a given attachment
* @param array $pAttachmentId Attachment ID of attachment
if( @BitBase::verifyId( $pAttachmentId )) {
return $gBitSystem->mDb->query( "DELETE FROM `". BIT_DB_PREFIX. "liberty_attachment_meta_data` WHERE `attachment_id` = ?", array( $pAttachmentId ));
* @param string $pDescription Description of meta key. e.g.: Exif, ID3, Album, Artist
* @param string $pTable Table data is stored in - either 'type' or 'title'
* @return meta type or title id on sucess, FALSE on failure
function getMetaId( $pDescription, $pTable = 'type' ) {
if( !empty( $pDescription ) && ( $pTable == 'type' || $pTable == 'title' )) {
$ret = $gBitSystem->mDb->getOne( "SELECT `meta_{$pTable}_id` FROM `". BIT_DB_PREFIX. "liberty_meta_{$pTable}s` WHERE `meta_{$pTable}` = ?", array( LibertyMime::normalizeMetaDescription( $pDescription )));
* @param string $pId ID of type or title we want the description for
* @param string $pTable Table data is stored in - either 'type' or 'title'
* @return description on sucess, FALSE on failure
$ret = $gBitSystem->mDb->getOne( "SELECT `meta_{$pTable}` FROM `". BIT_DB_PREFIX. "liberty_meta_{$pTable}s` WHERE `meta_{$pTable}_id` = ?", array( $pId ));
* normalizeMetaDescription
* @param string $pDescription Description of meta key. e.g.: Exif, ID3, Album, Artist
* @return normalized meta description that can be used as a guid
* mime_get_storage_sub_dir_name get a filename based on the uploaded file
* @param array $pFileHash File information provided in $_FILES
* @return appropriate sub dir name
if( !empty( $pFileHash['type'] ) ) {
// type is from upload file hash
$mimeType = $pFileHash['type'];
} elseif( !empty( $pFileHash['mime_type'] ) ) {
// mime_type is from liberty_files
$mimeType = $pFileHash['mime_type'];
if( !empty( $mimeType ) && strstr( $mimeType, "/" )) {
// if we only got 'application' we will use the file extenstion
if( $ret == 'application' && !empty( $pFileHash['name'] ) && ( $pos = strrpos( $pFileHash['name'], "." )) !== FALSE ) {
// append an 's' to not create an image and images dir side by side (legacy reasons)
if( empty( $ret ) || $ret == 'image' ) {
* liberty_mime_get_storage_branch - get url to store files for the feature site_upload_dir. It creates a calculable hierarchy of directories
* @author Christian Fowler<spider@steelsun.com>
* @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
* @return string full path on local filsystem to store files.
// *PRIVATE FUNCTION. GO AWAY! DO NOT CALL DIRECTLY!!!
if( $pUserId = BitBase::getParameter( $pParamHash, 'user_id' ) ) {
$pathParts[] = (int) ($pUserId % 1000);
} elseif( $pAttachmentId = BitBase::getParameter( $pParamHash, 'attachment_id' ) ) {
$pathParts[] = 'attachments';
$pathParts[] = (int) ($pAttachmentId % 1000);
$pathParts[] = $pAttachmentId;
if( $pPackage = BitBase::getParameter( $pParamHash, 'package' ) ) {
$pathParts[] = $pPackage;
// In case $pSubDir is multiple levels deep we'll need to mkdir each directory if they don't exist
if( $pSubDir = BitBase::getParameter( $pParamHash, 'sub_dir' ) ){
foreach ($pSubDirParts as $subDir) {
$fullPath = implode( $pathParts, '/' ). '/';
if( BitBase::getParameter( $pParamHash, 'create_dir', TRUE ) ){
$fileName = BitBase::getParameter( $pParamHash, 'file_name' );
if( empty( $pParamHash['package'] ) ) {
if( empty( $pParamHash['sub_dir'] ) ) {
$pParamHash['sub_dir'] = BitBase::getParameter( $pParamHash, 'attachment_id' );
$ret = STORAGE_PKG_URL. $fileBranch. $defaultFileName;
$ret = STORAGE_PKG_URL. $fileBranch. basename( BitBase::getParameter( $pParamHash, 'file_name' ) );
$fileName = BitBase::getParameter( $pParamHash, 'file_name' );
if( empty( $pParamHash['package'] ) ) {
if( empty( $pParamHash['sub_dir'] ) ) {
$pParamHash['sub_dir'] = BitBase::getParameter( $pParamHash, 'attachment_id' );
$ret = 'original.'. $gBitSystem->getMimeExtension( $pMimeType );
/* vim: :set fdm=marker : */
|