800,'m' => 400,'s' => 120,'b' => 40); static $default_heights = array('l' => 600,'m' => 300,'s' => 90,'b' => 30); static $display_to_thumb_size = array( 'display_backend_src' => 'b', 'display_small_src' => 's', 'display_medium_src' => 'm', 'display_large_src' => 'l', 'display_original_src' => 'o', 'display_backend_thumb' => 'b', 'display_small_thumb' => 's', 'display_medium_thumb' => 'm', 'display_large_thumb' => 'l', 'display_original_thumb' => 'o', ); static $index_to_thumb_size = array(-1 => 'b', 1 => 's', 2 => 'm', 3 => 'l', 4 => 'o'); static $thumb_only_displays = array('display_backend_thumb' => 0, 'display_small_thumb' => 1, 'display_medium_thumb' => 2, 'display_large_thumb' => 3, 'display_original_thumb' => 4); static $value_only_displays = array('display_backend_src' => 0, 'display_small_src' => 1, 'display_medium_src' => 2, 'display_large_src' => 3, 'display_original_src' => 4); static $single_displays = array('display_single' => 0, 'display_single_total' => 1, 'display_single_link' => 2, 'display_single_total_link' => 3); static $js_added = array(); // *** // *** CONSTRUCTOR // *** public function __construct( &$subject, $params ) { parent::__construct( $subject, $params ); } // *** // *** DISPLAY methods, item form & frontend views // *** // Method to create field's HTML display for item form public function onDisplayField(&$field, &$item) { if ( !in_array($field->field_type, static::$field_types) ) return; $field->label = $field->parameters->get('label_form') ? \Joomla\CMS\Language\Text::_($field->parameters->get('label_form')) : \Joomla\CMS\Language\Text::_($field->label); $use_ingroup = $field->parameters->get('use_ingroup', 0); if (!isset($field->formhidden_grp)) $field->formhidden_grp = $field->formhidden; if ($use_ingroup) $field->formhidden = 3; if ($use_ingroup && empty($field->ingroup)) return; $is_ingroup = !empty($field->ingroup); // Initialize framework objects and other variables $document = Factory::getDocument(); $cparams = ComponentHelper::getParams( 'com_flexicontent' ); $app = Factory::getApplication(); $user = Factory::getUser(); // Execute once static $initialized = null; if ( !$initialized ) { $initialized = 1; jimport('joomla.filesystem.file'); jimport('joomla.filesystem.folder'); jimport('joomla.filesystem.path'); $this->_load_phpthumb(); } $tooltip_class = 'hasTooltip'; $add_on_class = $cparams->get('bootstrap_ver', 2)==2 ? 'add-on' : 'input-group-addon'; $input_grp_class = $cparams->get('bootstrap_ver', 2)==2 ? 'input-append input-prepend' : 'input-group'; $btn_item_class = $cparams->get('bootstrap_ver', 2)==2 ? 'btn' : 'btn'; $btn_group_class = $cparams->get('bootstrap_ver', 2)==2 ? 'btn-group' : 'btn-group'; $form_font_icons = $cparams->get('form_font_icons', 1); $font_icon_class = $form_font_icons ? ' fcfont-icon' : ''; $font_icon_class .= FLEXI_J40GE ? ' icon icon- ' : ''; // Get a unique id to use as item id if current item is new $u_item_id = $item->id ? $item->id : substr(Factory::getApplication()->input->get('unique_tmp_itemid', '', 'string'), 0, 1000); // Check if using folder of original content being translated $of_usage = $field->untranslatable ? 1 : $field->parameters->get('of_usage', 0); $u_item_id = ($of_usage && $item->lang_parent_id && $item->lang_parent_id != $item->id) ? $item->lang_parent_id : $u_item_id; /** * Number of values */ $multiple = $use_ingroup || (int) $field->parameters->get('allow_multiple', 0); $max_values = $use_ingroup ? 0 : (int) $field->parameters->get('max_values', 0); $required = (int) $field->parameters->get('required', 0); $add_position = (int) $field->parameters->get('add_position', 3); // Classes for marking field required $required_class = $required ? ' required' : ''; // If we are multi-value and not inside fieldgroup then add the control buttons (move, delete, add before/after) $add_ctrl_btns = !$use_ingroup && $multiple; $fields_box_placing = (int) $field->parameters->get('fields_box_placing', 1); $target_dir = (int) $field->parameters->get('target_dir', 1); $image_source = (int) $field->parameters->get('image_source', 0); $image_source = $image_source > 1 ? $this->nonImplementedMode($image_source, $field) : $image_source; $media_params = ComponentHelper::getParams('com_media'); //$file_path = $media_params->get('file_path', 'images'); $image_path = $media_params->get('image_path', 'images'); $jmedia_topdir = $field->parameters->get('jmedia_topdir', $image_path); $jmedia_subpath = $field->parameters->get('jmedia_subpath', ''); $jmedia_filetypes = $field->parameters->get('jmedia_filetypes', array('folders', 'images')); if (version_compare(\Joomla\CMS\Version::MAJOR_VERSION, '4', 'ge')) { // 0: images, 1: audios, 2: videos, 3: documents * 'folders' is always included in J4 $mediaTypes = []; if (in_array('images', $jmedia_filetypes)) $mediaTypes[] = '0'; if (in_array('audios', $jmedia_filetypes)) $mediaTypes[] = '1'; if (in_array('videos', $jmedia_filetypes)) $mediaTypes[] = '2'; if (in_array('docs', $jmedia_filetypes)) $mediaTypes[] = '3'; $mediaTypes = implode(',', $mediaTypes); // * 'folders' is always included in J4 } else { $fileTypes = implode(',', $jmedia_filetypes); // Supported values: 'folders,images,docs,videos' * audios will be ignored in J3 } $all_media = $field->parameters->get('list_all_media_files', 0); $unique_thumb_method = $field->parameters->get('unique_thumb_method', 0); $dir = $field->parameters->get('dir'); $dir_url = str_replace('\\', '/', $dir); // FLAG to indicate if images are shared across fields, has the effect of adding field id to image thumbnails $multiple_image_usages = $image_source === 0 && $all_media && $unique_thumb_method == 0; $extra_prefix = $multiple_image_usages ? 'fld' . $field->id . '_' : ''; $autoassign = (int) $field->parameters->get( 'autoassign', 1 ); $thumb_size_resizer = (int) $field->parameters->get('thumb_size_resizer', 2); $thumb_size_default = (int) $field->parameters->get('thumb_size_default', 120); $thumb_method = (int) $field->parameters->get('thumb_method', 1); $preview_thumb_w = $preview_thumb_h = 600; // Optional properies configuration $linkto_url = (int) $field->parameters->get('linkto_url', 0); $usemediaurl = (int) $field->parameters->get('use_mediaurl', 0); $usealt = (int) $field->parameters->get('use_alt', 0); $usetitle = (int) $field->parameters->get('use_title', 0); $usedesc = (int) $field->parameters->get('use_desc', 1); $usecust1 = (int) $field->parameters->get('use_cust1', 0); $usecust2 = (int) $field->parameters->get('use_cust2', 0); $mediaurl_usage = (int) $field->parameters->get('mediaurl_usage', 0); $alt_usage = (int) $field->parameters->get('alt_usage', 0); $title_usage = (int) $field->parameters->get('title_usage', 0); $desc_usage = (int) $field->parameters->get('desc_usage', 0); $cust1_usage = (int) $field->parameters->get('cust1_usage', 0); $cust2_usage = (int) $field->parameters->get('cust2_usage', 0); $default_mediaurl = ($item->version == 0 || $mediaurl_usage > 0) ? $field->parameters->get( 'default_mediaurl', '' ) : ''; $default_alt = ($item->version == 0 || $alt_usage > 0) ? $field->parameters->get( 'default_alt', '' ) : ''; $default_title = ($item->version == 0 || $title_usage > 0) ? \Joomla\CMS\Language\Text::_($field->parameters->get( 'default_title', '' )) : ''; $default_desc = ($item->version == 0 || $desc_usage > 0) ? $field->parameters->get( 'default_desc', '' ) : ''; $default_cust1 = ($item->version == 0 || $cust1_usage > 0) ? $field->parameters->get( 'default_cust1', '' ) : ''; $default_cust2 = ($item->version == 0 || $cust2_usage > 0) ? $field->parameters->get( 'default_cust2', '' ) : ''; $use_jformfields = true; //FLEXI40GE // *** Calculate some configuration flags // Display properties box $none_props = !$linkto_url && !$usemediaurl && !$usealt && !$usetitle && !$usedesc && !$usecust1 && !$usecust2; // Inline uploaders flags $use_inline_uploaders = $image_source >= 0; $file_btns_position = (int) $field->parameters->get('file_btns_position', 0); // Intro / Full mode if ($image_source === -1) { $field->html = $use_ingroup ? array('
"; print_r($image_IF); echo ""; exit; } } // Check for deleted image files or image files that cannot be thumbnailed, // rebuilding thumbnails as needed, and then assigning checked values to a new array $usable_values = array(); if ($values) { // Handle file-ids as values $v = reset($values); if ((string)(int)$v == $v) { $files_data = $this->getFileData( $values, $published=false ); } /** * Iterate passing A REFERENCE of THE VALUE to rebuildThumbs() and other methods so that value can be modifled, and data like real image width, height can be added */ foreach ($values as $index => $value) { // Non-serialized values, e.g file ids as values (minigallery legacy field) if ((string)(int)$value == $value) { if (isset($files_data[$value])) { $value = array('originalname' => $files_data[$value]->filename); } else { $value = array('originalname' => null); } $values[$index] = serialize($value); } // Serialized value else { $array = $this->unserialize_array($value, $force_array=false, $force_value=false); $value = $array ?: array( 'originalname' => $value ); } // Try to check / rebuild thumbnails if (plgFlexicontent_fieldsImage::rebuildThumbs($field, $value, $item)) { $usable_values[$index] = $values[$index]; } // In case of failed thumbnailing, add empty value if in fieldgroup else if ($is_ingroup) { $usable_values[$index] = array('originalname' => null); } } } $values = & $usable_values; // Allow for thumbnailing of the default image $field->using_default_value = false; /** * Create default image to be used if (a) no image assigned OR (b) images assigned have been deleted */ if ( !count($values)) { //echo 'no values: '.$item->id.'
"; print_r($file); echo ""; $files = array(); if ($file) foreach( $file as $key => $all ) { foreach( $all as $i => $val ) { $files[$i][$key] = $val; } } //echo "
"; print_r($files); echo ""; // *** // *** Reformat the posted data & handle uploading / removing / deleting / replacing image files // *** // Make sure posted data is an array $post = !is_array($post) ? array($post) : $post; $new_filenames = array(); $newpost = array(); $new = 0; foreach ($post as $n => $v) { if (empty($v)) { // skip empty value, but allow empty (null) placeholder value if in fieldgroup if ($use_ingroup) $newpost[$new++] = null; continue; } // Support for serialized user data, e.g. basic CSV import / export. (Safety concern: objects code will abort unserialization!) if ( /*$is_importcsv &&*/ !is_array($v) && $v ) { $array = $this->unserialize_array($v, $force_array=false, $force_value=false); $v = $array ?: array( 'originalname' => $v ); } // Add system message if upload error $err_code = isset($files[$n]['error']) ? $files[$n]['error'] : UPLOAD_ERR_NO_FILE; if ( $err_code && $err_code !== UPLOAD_ERR_NO_FILE ) { $err_msg = array( UPLOAD_ERR_INI_SIZE => 'The uploaded file exceeds the upload_max_filesize directive in php.ini', UPLOAD_ERR_INI_SIZE => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form', UPLOAD_ERR_PARTIAL => 'The uploaded file was only partially uploaded', UPLOAD_ERR_NO_FILE => 'No file was uploaded', UPLOAD_ERR_NO_TMP_DIR => 'Missing a temporary folder', UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk', UPLOAD_ERR_EXTENSION => 'A PHP extension stopped the file upload' ); Factory::getApplication()->enqueueMessage("FILE FIELD: ".$err_msg[$err_code], 'warning' ); continue; } // Handle uploading a new original file $new_file = $err_code === 0; $new_file_uploaded = null; if ($new_file) { $new_file_uploaded = $this->uploadOriginalFile($field, $v, $files[$n]); } // Handle copying original files from a server folder during CSV import else if ($is_importcsv && $import_media_folder ) { $filename = basename($v['originalname']); $sub_folder = dirname($v['originalname']); $sub_folder = $sub_folder && $sub_folder!='.' ? DS.$sub_folder : ''; if ($image_source >= 1) { $src_file_path = Path::clean( $srcpath_original . $v['originalname'] ); $dest_file_path = Path::clean( $dest_path_original . $filename ); $result = false; if ( file_exists($src_file_path) ) { $result = File::copy( $src_file_path, $dest_file_path ); if ( $result && Path::canChmod($dest_file_path) ) { chmod($dest_file_path, 0644); } } elseif ( file_exists($dest_file_path) ) { $result = true; } $v['originalname'] = $result ? $filename // make sure filename is WITHOUT subfolder : ''; } elseif ($image_source == -2) { $src_file_path = Path::clean( $srcpath_original . $v['originalname'] ); $dest_file_path = Path::clean( $dest_path_media_full . $filename ); $result = false; if ( file_exists($src_file_path) ) { $result = File::copy( $src_file_path, $dest_file_path ); if ( $result && Path::canChmod($dest_file_path) ) { chmod($dest_file_path, 0644); } } elseif (file_exists($dest_file_path)) { $result = true; } $v['originalname'] = $result ? $dest_path_media . $filename // make sure filename is WITH subfolder : ''; } elseif ($image_source === 0) { if ($v['originalname'] == (int) $v['originalname'] && $id_col >= 2) { // Keep existing value } else { $fman = new FlexicontentControllerFilemanager(); $fman->runMode = 'interactive'; $app->input->set('return', null); $app->input->set('file-dir-path', DS.$import_media_folder . $sub_folder); $app->input->set('file-filter-re', preg_quote($filename)); $app->input->set('secure', 1); $app->input->set('keep', 1); $upload_err = null; $file_ids = $fman->addlocal(null, $upload_err); reset($file_ids); // Reset array to point to first element $v['originalname'] = key($file_ids); // The (first) key of file_ids array is the cleaned up filename } } else { // keep value only cleaning it $v['originalname'] = Path::clean( $v['originalname'] ); } } // Default values for unset required properties of values $v['originalname'] = isset($v['originalname']) ? $v['originalname'] : ''; $v['existingname'] = isset($v['existingname']) ? $v['existingname'] : ''; if ( $v['originalname'] || $v['existingname'] ) { // Handle replacing image with a new existing image if ( $v['existingname'] ) { // Handle value containing more than just the filepath if ($image_source == -2) { $_tmp = explode('#', $v['existingname']); $v['existingname'] = $_tmp[0]; } $v['originalname'] = $v['existingname']; $v['existingname'] = ''; } } else { // No new file posted and no existing selected: Skip current image row, but allow empty (null) placeholder value if in fieldgroup $v = $use_ingroup ? null : false; //$use_ingroup ? array('originalname'=>'') : null; } // Add image entry to a new array skipping empty image entries if ($v !== false) { if ($v) { $new_filenames[$v['originalname']] = 1; // Validate other value properties $v['urllink'] = $linkto_url ? flexicontent_html::dataFilter($v['urllink'], 4000, 'URL', 0) : null; $v['mediaurl'] = $usemediaurl ? flexicontent_html::dataFilter($v['mediaurl'], 4000, 'URL', 0) : null; if ($usemediaurl === 1 && strpos($v['mediaurl'], 'youtube') === false && strpos($v['mediaurl'], 'vimeo') === false) { $v['mediaurl'] = ''; } $v['alt'] = $usealt ? flexicontent_html::dataFilter($v['alt'], 400, 'STRING', 0) : null; $v['title'] = $usetitle ? flexicontent_html::dataFilter($v['title'], 400, 'STRING', 0) : null; $v['desc'] = $usedesc ? flexicontent_html::dataFilter($v['desc'], 4000, 'STRING', 0) : null; $v['cust1'] = $usecust1 ? flexicontent_html::dataFilter($v['cust1'], 4000, 'STRING', 0) : null; $v['cust2'] = $usecust2 ? flexicontent_html::dataFilter($v['cust2'], 4000, 'STRING', 0) : null; foreach($v as $propname => $propval) { if ($propval === null) { unset($v[$propname]); } } } $newpost[$new] = $v; $new++; } } $post = $newpost; // Remove no longer used files, if limiting existing image list to current field, or if existing image list is hidden/disabled if ($image_source === 0 && ($field->parameters->get('auto_delete_unused', 1) || !$field->parameters->get('list_all_media_files', 0))) { // Get existing field values, if (!isset($item->fieldvalues)) { $_fieldvalues = FlexicontentFields::getFieldValsById(null, array($item->id)); $item->fieldvalues = isset($_fieldvalues[$item->id]) ? $_fieldvalues[$item->id] : array(); } $db_values = !empty($item->fieldvalues[$field->id]) ? $item->fieldvalues[$field->id] : array(); //echo "
"; print_r($new_filenames); print_r($db_values);
// Remove unused files
foreach($db_values as $i => $v)
{
$array = $this->unserialize_array($v, $force_array=false, $force_value=false);
$v = $array ?: array(
'originalname' => $v
);
$filename = isset($v['originalname']) ? $v['originalname'] : false;
if ($filename && !isset($new_filenames[$filename]))
{
// Check if value is in use
$canDeleteImage = $this->canDeleteImage($field, $filename, $item);
if ($canDeleteImage)
{
$this->removeOriginalFile($field, $filename);
//$app->enqueueMessage('Field: ' . $field->label . ' ['.$n.'] : ' . 'Deleted image file: ' . $filename . ' from server storage');
}
}
}
}
// Serialize multi-property data before storing them into the DB,
// null indicates to increment valueorder without adding a value
foreach($post as $i => $v)
{
if ($v !== null)
{
$post[$i] = serialize($v);
}
}
}
// Method to take any actions/cleanups needed after field's values are saved into the DB
public function onAfterSaveField( &$field, &$post, &$file, &$item )
{
if ( empty($post) ) return;
$app = Factory::getApplication();
$is_importcsv = $app->input->get('task', '', 'cmd') == 'importcsv';
if ( !$is_importcsv ) return;
$values = array();
foreach($post as $i => $v)
{
if ( !is_array($v) )
{
$array = $this->unserialize_array($v, $force_array=false, $force_value=false);
$v = $array ?: array(
'originalname' => $v
);
}
$values[$i] = $v;
plgFlexicontent_fieldsImage::rebuildThumbs($field, $values[$i], $item);
}
//echo "{$field->field_type}:
".print_r($values, true)."
\n";
}
// Method called just before the item is deleted to remove custom item data related to the field
public function onBeforeDeleteField(&$field, &$item)
{
$app = Factory::getApplication();
$dir = $field->parameters->get('dir');
$image_source = (int) $field->parameters->get('image_source', 0);
$image_source = $image_source > 1 ? $this->nonImplementedMode($image_source, $field) : $image_source;
$target_dir = (int) $field->parameters->get('target_dir', 1);
if ($image_source >= 1)
{
jimport('joomla.filesystem.file');
jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.path');
// Delete image folder if it exists
$dest_path = Path::clean( JPATH_SITE .DS. $dir . DS. 'item_'.$item->id . '_field_'.$field->id .DS);
//if ( $image_source > 1 ) ; // TODO
if (file_exists($dest_path) && !Folder::delete($dest_path))
{
$app->enqueueMessage('Field: ' . $field->label . ': Notice: Unable to delete folder: ' . $dest_path, 'warning');
return false;
}
}
}
/**
* Method to do extra handling of field's values after all fields have validated their posted data, and are ready to be saved
* OVERRIDE Default implementation
*
* $item->fields['fieldname']->postdata contains values of other fields
* $item->fields['fieldname']->filedata contains files of other fields (normally this is empty due to using AJAX for file uploading)
*/
function onAllFieldsPostDataValidated( &$field, &$item )
{
$auto_intro_full = (int) $field->parameters->get('auto_intro_full', 0);
if ($auto_intro_full === 1)
{
try
{
if (is_string($item->images))
{
$item->images = json_decode($item->images ?: '{}');
}
}
catch (Exception $e)
{
$item->images = json_decode('{}');
}
//Factory::getApplication()->enqueueMessage('' . print_r($item->images, true) . '
' , 'notice');
$p = $item->fields[$field->name]->postdata;
//Factory::getApplication()->enqueueMessage('Field: ' . $field->name . '
' . print_r($p, true) . '
' , 'notice');
if ($p && reset($p))
{
$value = unserialize(reset($p));
//Factory::getApplication()->enqueueMessage(print_r($value, true), 'notice');
list($file_path, $src_path, $dest_path, $field_index, $extra_prefix) = $this->getThumbPaths($field, $item, $value, $relative = true);
$thumb_M = $dest_path . 'm_' . $extra_prefix . $value['originalname'];
$thumb_L = $dest_path . 'l_' . $extra_prefix . $value['originalname'];
/*Factory::getApplication()->enqueueMessage('Field: '
. $field->name . '
'
. $file_path . "\n"
. $dest_path . "\n"
. $field_index . "\n"
. $thumb_M . "\n"
. $thumb_L . "\n"
. '
'
, 'notice');*/
$item->images->image_intro = $thumb_M;
$item->images->image_fulltext = $thumb_L;
}
$item->images = json_encode($item->images);
}
}
// ***
// *** CATEGORY/SEARCH FILTERING METHODS
// ***
// Method to display a search filter for the advanced search view
public function onAdvSearchDisplayFilter(&$filter, $value = '', $formName = 'searchForm')
{
if ( !in_array($filter->field_type, static::$field_types) ) return;
$filter->parameters->set( 'display_filter_as_s', 1 ); // Only supports a basic filter of single text search input
FlexicontentFields::createFilter($filter, $value, $formName);
}
// Method to get the active filter result (an array of item ids matching field filter, or subquery returning item ids)
// This is for search view
public function getFilteredSearch(&$filter, $value, $return_sql = true)
{
if ( !in_array($filter->field_type, static::$field_types) ) return;
$filter->parameters->set( 'display_filter_as_s', 1 ); // Only supports a basic filter of single text search input
return FlexicontentFields::getFilteredSearch($filter, $value, $return_sql);
}
// ***
// *** SEARCH INDEX METHODS
// ***
// Method to create (insert) advanced search index DB records for the field values
public function onIndexAdvSearch(&$field, &$post, &$item)
{
if ( !in_array($field->field_type, static::$field_types) ) return;
if ( !$field->isadvsearch && !$field->isadvfilter ) return;
// a. Each of the values of $values array will be added to the advanced search index as searchable text (column value)
// b. Each of the indexes of $values will be added to the column 'value_id',
// and it is meant for fields that we want to be filterable via a drop-down select
// c. If $values is null then only the column 'value' will be added to the search index after retrieving
// the column value from table 'flexicontent_fields_item_relations' for current field / item pair will be used
// 'required_properties' is meant for multi-property fields, do not add to search index if any of these is empty
// 'search_properties' contains property fields that should be added as text
// 'properties_spacer' is the spacer for the 'search_properties' text
// 'filter_func' is the filtering function to apply to the final text
/*if ($post !== null)
{
$v = reset($post);
if ((string)(int)$v == $v)
{
$files_data = $this->getFileData( $post, $published=false );
}
foreach ($post as $index => $value)
{
// Compatibility for non-serialized values, e.g file ids as values (minigallery legacy field)
if ((string)(int)$value == $value)
{
if (isset($files_data[$value]))
{
$value = array('originalname' => $files_data[$value]->filename);
}
else $value = array('originalname' => null);
$post[$index] = serialize($value);
}
else
{
$array = $this->unserialize_array($value, $force_array=false, $force_value=false);
$value = $array ?: array(
'originalname' => $value
);
}
$post[$index] = $value;
}
}*/
FlexicontentFields::onIndexAdvSearch($field, $post, $item, $required_properties=array('originalname'), $search_properties=array('title','desc'), $properties_spacer=' ', $filter_func=null);
return true;
}
// Method to create basic search index (added as the property field->search)
public function onIndexSearch(&$field, &$post, &$item)
{
if ( !in_array($field->field_type, static::$field_types) ) return;
if ( !$field->issearch ) return;
// a. Each of the values of $values array will be added to the basic search index (one record per item)
// b. If $values is null then the column value from table 'flexicontent_fields_item_relations' for current field / item pair will be used
// 'required_properties' is meant for multi-property fields, do not add to search index if any of these is empty
// 'search_properties' contains property fields that should be added as text
// 'properties_spacer' is the spacer for the 'search_properties' text
// 'filter_func' is the filtering function to apply to the final text
/*if ($post !== null)
{
$v = reset($post);
if ((string)(int)$v == $v)
{
$files_data = $this->getFileData( $post, $published=false );
}
foreach ($post as $index => $value)
{
// Compatibility for non-serialized values, e.g file ids as values (minigallery legacy field)
if ((string)(int)$value == $value)
{
if (isset($files_data[$value]))
{
$value = array('originalname' => $files_data[$value]->filename);
}
else $value = array('originalname' => null);
$post[$index] = serialize($value);
}
else
{
$array = $this->unserialize_array($value, $force_array=false, $force_value=false);
$value = $array ?: array(
'originalname' => $value
);
}
$post[$index] = $value;
}
}*/
FlexicontentFields::onIndexSearch($field, $post, $item, $required_properties=array('originalname'), $search_properties=array('title','desc'), $properties_spacer=' ', $filter_func=null);
return true;
}
// ***
// *** VARIOUS HELPER METHODS
// ***
/**
* Method to handle the uploading of an image file (for 'DB-reusable' mode and not for 'folder' mode)
*/
function uploadOriginalFile($field, &$post, $file)
{
$app = Factory::getApplication();
$format = $app->input->get('format', 'html', 'cmd');
$err_text = null;
// Get the component configuration
$cparams = ComponentHelper::getParams( 'com_flexicontent' );
$params = clone($cparams);
// Merge field parameters into the global parameters
$fparams = $field->parameters;
$params->merge($fparams);
jimport('joomla.utilities.date');
jimport('joomla.filesystem.file');
jimport('joomla.client.helper');
// Set FTP credentials, if given
\Joomla\CMS\Client\ClientHelper::setCredentialsFromRequest('ftp');
// Make the filename safe
$file['name'] = File::makeSafe($file['name']);
$all_media = $field->parameters->get('list_all_media_files', 0);
$unique_thumb_method = $field->parameters->get('unique_thumb_method', 0);
// IMAGE SOURCE, should be always ZERO (DB-mode) inside this function
$image_source = (int) $field->parameters->get('image_source', 0);
$image_source = $image_source > 1 ? $this->nonImplementedMode($image_source, $field) : $image_source;
$target_dir = (int) $field->parameters->get('target_dir', 1);
// FLAG to indicate if images are shared across fields, has the effect of adding field id to image thumbnails
$multiple_image_usages = $image_source == 0 && $all_media && $unique_thumb_method == 0;
$extra_prefix = $multiple_image_usages ? 'fld' . $field->id . '_' : '';
if ( isset($file['name']) && $file['name'] != '' )
{
// Only handle the secure folder
$path = ($target_dir ? COM_FLEXICONTENT_FILEPATH : COM_FLEXICONTENT_MEDIAPATH).DS;
/**
* Check that file contents are safe, and make filename file-system safe
* transliterating it according to given language (this forces lowercase)
*/
$upload_check = flexicontent_upload::check($file, $err_text, $params);
/**
* Sanitize the file name (filesystem-safe, (this should have been done above already))
* and also return an unique filename for the given folder
*/
$filename = flexicontent_upload::sanitize($path, $file['name']);
$filepath = Path::clean($path.$filename);
//perform security check according
if (!$upload_check)
{
if ($format === 'json')
{
jimport('joomla.error.log');
$log = \Joomla\CMS\Log\Log::getInstance('com_flexicontent.error.php');
$log->addEntry(array(
'comment' => 'Invalid: ' . $filepath . ': ' . $err_text
));
header('HTTP/1.0 415 Unsupported Media Type');
die('Error. Unsupported Media Type!');
}
$app->enqueueMessage('Field: ' . $field->label . ' : ' . \Joomla\CMS\Language\Text::_($err_text), 'error');
return false;
}
//get the extension to record it in the DB
$ext = strtolower(flexicontent_upload::getExt($filename));
/**
* We allow Joomla default security to execute, if user really uploads an image file, it should not be trigger anyway
*/
$upload_success = File::upload($file['tmp_name'], $filepath);
if (!$upload_success)
{
if ($format === 'json')
{
jimport('joomla.error.log');
$log = \Joomla\CMS\Log\Log::getInstance('com_flexicontent.error.php');
$log->addEntry(array('comment' => 'Cannot upload: '.$filepath));
header('HTTP/1.0 409 Conflict');
jexit('Error. File already exists');
}
$app->enqueueMessage('Field: ' . $field->label . ' : ' . \Joomla\CMS\Language\Text::_('FLEXI_UNABLE_TO_UPLOAD_FILE'), 'error');
return false;
}
else
{
$db = Factory::getDbo();
$user = Factory::getUser();
$config = Factory::getConfig();
$timezone = $config->get('offset');
$date = Factory::getDate('now');
$date->setTimeZone( new DateTimeZone( $timezone ) );
$obj = new stdClass();
$obj->filename = $filename;
$obj->altname = $file['name'];
$obj->url = 0;
$obj->secure = 1;
$obj->access = 1; // public
$obj->ext = $ext;
$obj->hits = 0;
$obj->uploaded = $date->toSql();
$obj->uploaded_by = $user->get('id');
if ($format === 'json')
{
jimport('joomla.error.log');
$log = \Joomla\CMS\Log\Log::getInstance();
$log->addEntry(array('comment' => $filepath));
$db->insertObject('#__flexicontent_files', $obj);
jexit('FLEXI_UPLOAD_COMPLETE');
}
else
{
$db->insertObject('#__flexicontent_files', $obj);
$app->enqueueMessage($field->label . ' : ' . \Joomla\CMS\Language\Text::_('FLEXI_UPLOAD_COMPLETE'));
$sizes = array('l', 'm', 's', 'b');
foreach ($sizes as $size)
{
// create the thumbnail
$this->create_thumb( $field, $filename, $size, $src_path='', $dest_path='', $copy_original=0, $extra_prefix );
// set the filename for posting
$post['originalname'] = $filename;
}
return true;
}
}
}
else
{
$app->enqueueMessage('Field: ' . $field->label . ' : ' . \Joomla\CMS\Language\Text::_('FLEXI_UNABLE_TO_UPLOAD_FILE'), 'error');
return false;
}
}
/**
* Decide parameters for calling phpThumb library to create a thumbnail according to configuration
*/
function create_thumb( &$field, $filename, $size, $src_path='', $dest_path='', $copy_original=0, $extra_prefix='' )
{
$app = Factory::getApplication();
static $dest_paths_arr = array();
// Execute once
static $initialized = null;
if (!$initialized)
{
$initialized = 1;
jimport('joomla.filesystem.file');
jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.path');
}
// (DB/Folder/Other) Mode of image field
$image_source = (int) $field->parameters->get('image_source', 0);
$image_source = $image_source > 1 ? $this->nonImplementedMode($image_source, $field) : $image_source;
$target_dir = (int) $field->parameters->get('target_dir', 1);
// Image file paths
$dir = $field->parameters->get('dir');
$src_path = $src_path ? $src_path : Path::clean(($target_dir ? COM_FLEXICONTENT_FILEPATH : COM_FLEXICONTENT_MEDIAPATH).DS);
$dest_path = $dest_path ? $dest_path : Path::clean( JPATH_SITE .DS. $dir .DS );
$prefix = $size . '_' . $extra_prefix;
$filepath = $dest_path.$prefix.$filename;
// Parameters for phpthumb
$ext = strtolower(flexicontent_upload::getExt($filename));
$w = $field->parameters->get('w_' . $size, self::$default_widths[$size]);
$h = $field->parameters->get('h_' . $size, self::$default_heights[$size]);
$crop = $field->parameters->get('method_' . $size);
$quality= $field->parameters->get('quality');
$usewm = $field->parameters->get('use_watermark_' . $size);
$wmfile = Path::clean(JPATH_SITE . DS . $field->parameters->get('wm_' . $size));
$wmop = $field->parameters->get('wm_opacity');
$wmpos = $field->parameters->get('wm_position');
// Create destination folder if it does not exist
if (!file_exists($dest_path) && !Folder::create($dest_path))
{
$app->enqueueMessage('Field: ' . $field->label . ' : ' . \Joomla\CMS\Language\Text::_('Error. Unable to create folders'), 'error');
return false;
}
// Make sure folder is writtable by phpthumb
if (!isset($dest_paths_arr[$dest_path]) && Path::canChmod($dest_path))
{
/**
* Path::setPermissions() is VERY SLOW, because it does chmod() on all folder / subfolder files
*/
//Path::setPermissions($dest_path, '0644', '0755');
chmod($dest_path, 0755);
}
// Avoid trying to set folder permission multiple times
$dest_paths_arr[$dest_path] = 1;
// EITHER copy original image file as current thumbnail (FLAG 'copy_original' is set)
if ($copy_original)
{
$result = File::copy( $src_path.$filename, $filepath );
}
// OR Create the thumnail by calling phpthumb
else
{
$result = $this->imagePhpThumb(
$src_path, $dest_path,
$prefix, $filename, $ext,
$w, $h, $quality, $size, $crop,
$usewm, $wmfile, $wmop, $wmpos
);
}
// Make sure the created thumbnail has correct permissions
if ($result && Path::canChmod($filepath))
{
chmod($filepath, 0644);
}
return $result;
}
/**
* Load phpThumb if not already loaded
*/
private function _load_phpthumb()
{
static $loaded = null;
if ($loaded === null)
{
$loaded = 1;
require_once ( JPATH_SITE.DS.'components'.DS.'com_flexicontent'.DS.'librairies'.DS.'phpthumb'.DS.'phpthumb.class.php' );
// WE DO INCLUDE TO FORCE LOADING OF configuration AFTER the class
// WE HAVE PATCHED configuration not to double define CONSTANTS and FUNCTIONS
include ( JPATH_SITE.DS.'components'.DS.'com_flexicontent'.DS.'librairies'.DS.'phpthumb'.DS.'phpThumb.config.php' );
}
}
/**
* Call phpThumb library to create a thumbnail according to configuration
*/
function imagePhpThumb( $src_path, $dest_path, $prefix, $filename, $ext, $width, $height, $quality, $size, $crop, $usewm, $wmfile, $wmop, $wmpos )
{
static $initialized = null;
if ($initialized === null)
{
$initialized = 1;
$this->_load_phpthumb();
}
unset ($phpThumb);
$phpThumb = new phpThumb();
// Needed for file paths in windows
$filepath = str_replace('\\', '/', $src_path . $filename);
$phpThumb->setSourceFilename($filepath);
$phpThumb->setParameter('config_output_format', "$ext");
$phpThumb->setParameter('w', $width);
$phpThumb->setParameter('h', $height);
$phpThumb->setParameter('ar', 'x');
if ($usewm == 1)
{
$phpThumb->setParameter('fltr', 'wmi|'.$wmfile.'|'.$wmpos.'|'.$wmop);
}
$phpThumb->setParameter('q', $quality);
if ($crop == 1)
{
$phpThumb->setParameter('zc', 1);
}
$ext = strtolower(flexicontent_upload::getExt($filename));
/**
* Maintain image format for output file for specific file extensions
* this is needed to keep features like transparency support,
* for other formats use default (unless changed this is jpg)
*/
if ( in_array( $ext, array('png', 'gif', 'ico', 'webp') ) )
{
$phpThumb->setParameter('f', $ext);
}
$output_filename = $dest_path . $prefix . $filename ;
// Catch case of bad permission for thumbnail files but good permission for containing folder ...
if (file_exists($output_filename))
{
File::delete($output_filename);
}
if ($phpThumb->GenerateThumbnail())
{
if ($phpThumb->RenderToFile($output_filename))
{
return true;
}
//echo 'Failed:' . implode("\n\n", $phpThumb->debugmessages) . '
';
return false;
}
//echo 'Failed2:' . $phpThumb->fatalerror . "\n\n" . implode("\n\n", $phpThumb->debugmessages) . '
';
return false;
}
/**
* Removes an orignal image file and its thumbnails
*/
public function removeOriginalFile($field, $filename)
{
$app = Factory::getApplication();
$db = Factory::getDbo();
jimport('joomla.filesystem.file');
jimport('joomla.filesystem.path');
$image_source = (int) $field->parameters->get('image_source', 0);
$image_source = $image_source > 1 ? $this->nonImplementedMode($image_source, $field) : $image_source;
$target_dir = (int) $field->parameters->get('target_dir', 1);
// Folder-mode 1
if ($image_source >= 1)
{
$thumbfolder = Path::clean(JPATH_SITE .DS. $field->parameters->get('dir') .DS. 'item_'.$field->item_id . '_field_'.$field->id);
$origfolder = $thumbfolder .DS. 'original' .DS;
}
// DB-mode
elseif ($image_source === 0)
{
$thumbfolder = Path::clean( JPATH_SITE .DS. $field->parameters->get('dir') );
$origfolder = Path::clean( ($target_dir ? COM_FLEXICONTENT_FILEPATH : COM_FLEXICONTENT_MEDIAPATH) );
}
// Negative, intro-full mode, this should be unreachable, because
else
{
echo 'image field id: ' . $field->id . ' is in intro-full mode, removeOriginalFile() should not have been called';
}
// a. Delete the thumbnails
$errors = array();
$sizes = array('l','m','s','b');
foreach ($sizes as $size)
{
$dest_path = $thumbfolder . DS . $size . '_' . $filename;
if (file_exists($dest_path) && !File::delete($dest_path))
{
$app->enqueueMessage('Field: ' . $field->label . ' : ' . \Joomla\CMS\Language\Text::_('FLEXI_FIELD_UNABLE_TO_DELETE_FILE') .": ". $dest_path, 'warning');
}
}
// b. Delete the original image from file manager
$src_path = Path::clean($origfolder.DS.$filename);
if (!File::delete($src_path))
{
$app->enqueueMessage('Field: ' . $field->label . ' : ' . \Joomla\CMS\Language\Text::_('FLEXI_FIELD_UNABLE_TO_DELETE_FILE') . ': ' . $src_path, 'warning');
}
// For DB-mode, also delete file from database
if ($image_source === 0)
{
$query = 'DELETE FROM #__flexicontent_files WHERE ' . $db->quoteName('filename') . ' = ' . $db->Quote($filename);
$db->setQuery($query)->execute();
}
return true;
}
/**
* Smart image thumbnail size check and rebuilding
*/
function rebuildThumbs(&$field, &$value, &$item)
{
static $images_processed = array();
// Execute once
static $initialized = null;
if ( !$initialized )
{
$initialized = 1;
jimport('joomla.filesystem.file');
jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.path');
}
// Unseriaze value if not already done
if ( !is_array($value) )
{
$array = $this->unserialize_array($value, $force_array=false, $force_value=false);
$value = $array ?: array(
'originalname' => $value
);
}
// Check for empty filename
$value['originalname'] = isset($value['originalname']) ? trim($value['originalname']) : '';
if (!$value['originalname'])
{
return;
}
// Do not thumbnail URLs (we only check for absolute URLs)
if (preg_match("#^(?:[a-z]+:)?//#", $value['originalname']))
{
return true;
}
$filename = basename($value['originalname']);
// Extra thumbnails sub-folder
list($file_path, $src_path, $dest_path, $field_index, $extra_prefix) = $this->getThumbPaths($field, $item, $value);
// Return cached data, avoiding rechecking/recreating image thumbnails multiple times
if (isset($images_processed[$field_index][$file_path]))
{
return $images_processed[$field_index][$file_path];
}
// Check for original file have been deleted or is not being a file
if (!file_exists($file_path) || !is_file($file_path))
{
return ($images_processed[$field_index][$file_path] = false);
}
/**
* Enforce protection of original image files for any type of Folder-mode
* But do not try to protect folder of default image
*/
if (empty($value['default_image']))
{
$this->protectImagePath($field, $src_path);
}
/**
* Check dimension of thumbs and rebuild as needed
*/
$filesize = getimagesize($file_path);
$origsize_h = $filesize[1];
$origsize_w = $filesize[0];
$sizes = array('l', 'm', 's', 'b');
// Always create an unprefixed small thumb, it is needed when assigning preview
if ($extra_prefix)
{
$sizes[] = '_s';
}
$thumbres = true;
foreach ($sizes as $size)
{
$check_small = $size=='_s';
$size = $check_small ? 's' : $size;
$thumbname = $size . '_' . ($check_small ? '' : $extra_prefix) . $filename;
$path = Path::clean($dest_path .DS. $thumbname);
if (file_exists($path))
{
$filesize = getimagesize($path);
$filesize_w = $filesize[0];
$filesize_h = $filesize[1];
$thumbnail_exists = true;
// Set real sizes for using the with SRCSET
if (!$check_small)
{
$value['size_w_' . $size] = $filesize_w;
$value['size_h_' . $size] = $filesize_h;
}
}
else
{
$thumbnail_exists = false;
}
if ($thumbnail_exists && $check_small)
{
continue;
}
$param_w = $field->parameters->get('w_' . $size, self::$default_widths[$size]);
$param_h = $field->parameters->get('h_' . $size, self::$default_heights[$size]);
$crop = $field->parameters->get('method_' . $size);
$usewm = $field->parameters->get('use_watermark_' . $size);
$copyorg = $field->parameters->get('copy_original_' . $size, 1);
$copy_original = ($copyorg==2) || ($origsize_w == $param_w && $origsize_h == $param_h && !$usewm && $copyorg==1);
if (!$crop)
{
$check_w = $param_w > $origsize_w ? $origsize_w : $param_w;
$check_h = $param_h > $origsize_h ? $origsize_h : $param_h;
}
// Check if size of file is not same as parameters and recreate the thumbnail
if (
!$thumbnail_exists ||
( $crop==0 && (
(abs($filesize_w - $check_w)>1 ) && // scale width can be larger than it is currently
(abs($filesize_h - $check_h)>1 ) // scale height can be larger than it is currently
)
) ||
( $crop==1 && (
($param_w <= $origsize_w && abs($filesize_w - $param_w)>1 ) || // crop width can be smaller than it is currently
($param_h <= $origsize_h && abs($filesize_h - $param_h)>1 ) // crop height can be smaller than it is currently
)
)
)
{
/*if (Factory::getUser()->authorise('core.admin', 'root.1'))
{
echo "FILENAME: ".$thumbname.", ".($crop ? "CROP" : "SCALE").", ".($thumbnail_exists ? "OLDSIZE(w,h): $filesize_w,$filesize_h" : "")
." NEWSIZE(w,h): $param_w,$param_h
"
." ORIGSIZE(w,h): $origsize_w,$origsize_h
"
;
}*/
$was_thumbed = $this->create_thumb( $field, $filename, $size, $src_path, $dest_path, $copy_original, ($check_small ? '' : $extra_prefix) );
$thumbres = $thumbres && $was_thumbed;
}
}
return ($images_processed[$field_index][$file_path] = $thumbres);
}
/**
* Returns an array of images that can be deleted
* e.g. of a specific field, or a specific uploader
*/
function canDeleteImage( &$field, $record, &$item )
{
// Retrieve available (and appropriate) images from the DB
$db = Factory::getDbo();
$query = 'SELECT id'
. ' FROM #__flexicontent_files'
. ' WHERE filename='. $db->Quote($record)
;
$db->setQuery($query);
$file_id = $db->loadResult();
if (!$file_id) return true;
$ignored = array($item->id);
$fm = new FlexicontentModelFilemanager();
return $fm->candelete( array($file_id), $ignored );
}
/**
* Create a string that concatenates various image information
* (Function is not called anywhere, used only for debugging)
*/
function listImageUses($field, $record)
{
$db = Factory::getDbo();
$query = 'SELECT value, item_id'
. ' FROM #__flexicontent_fields_item_relations'
. ' WHERE field_id = '. (int) $field->id
;
$db->setQuery($query);
$db_data = $db->loadObjectList();
$itemids = array();
// Remove unused files
foreach($db_data as $i => $data)
{
$array = $this->unserialize_array($data->value, $force_array=false, $force_value=false);
$data->value = $array ?: array(
'originalname' => $data->value
);
$filename = isset($data->value['originalname']) ? $data->value['originalname'] : false;
if ($filename && $filename == $record)
{
$itemids[] = $data->item_id;
}
}
return implode(',' , $itemids);
}
/**
* Get message about upload information & upload limitations
* (Function is not called anywhere, used only for debugging)
*/
function getUploadLimitsTxt($field, $enable_multi_uploader = true)
{
$tooltip_class = 'hasTooltip';
$hint_image = \Joomla\CMS\HTML\HTMLHelper::image ( 'components/com_flexicontent/assets/images/comments.png', \Joomla\CMS\Language\Text::_( 'FLEXI_NOTES' ), '' );
$warn_image = \Joomla\CMS\HTML\HTMLHelper::image ( 'components/com_flexicontent/assets/images/warning.png', \Joomla\CMS\Language\Text::_( 'FLEXI_NOTES' ), '' );
\Joomla\CMS\HTML\HTMLHelper::addIncludePath(JPATH_SITE . '/components/com_flexicontent/helpers/html');
$upConf = \Joomla\CMS\HTML\HTMLHelper::_('fcuploader.getUploadConf', $field);
$phpUploadLimit = flexicontent_upload::getPHPuploadLimit();
$server_limit_exceeded = $phpUploadLimit['value'] < $upConf['upload_maxsize'];
$server_limit_active = $server_limit_exceeded && ! $enable_multi_uploader;
$conf_limit_class = $server_limit_active ? 'badge badge-box' : '';
$conf_limit_style = $server_limit_active ? 'text-decoration: line-through;' : '';
$conf_lim_image = $server_limit_active ? $warn_image.$hint_image : $hint_image;
$sys_limit_class = $server_limit_active ? 'badge badge-box badge-warning' : '';
return '
'.\Joomla\CMS\Language\Text::_( $server_limit_exceeded ? 'FLEXI_UPLOAD_LIMITS' : 'FLEXI_UPLOAD_LIMIT' ).'
'.$conf_lim_image.'
'.round($upConf['upload_maxsize'] / (1024*1024), 2).' M
'.($server_limit_exceeded ? '
'.$hint_image.'
'.round($phpUploadLimit['value'] / (1024*1024), 2).' M
' : '').'
';
}
/**
* Register a message about internal bug of not-implemented image source mode
*/
function nonImplementedMode($image_source, &$field)
{
$field->parameters->set('image_source', 1);
static $fc_folder_mode_err;
if (isset($fc_folder_mode_err[$field->id]))
{
return 1;
}
Factory::getApplication()->enqueueMessage("Error source-mode: ".$image_source." not implemented please change image-source mode in image/gallery field with id: ".$field->id, 'warning' );
$fc_folder_mode_err[$field->id] = 1;
return 1;
}
/**
* Get DB data for the given file IDs
*/
function getFileData($fid, $published = 1, $extra_select = '')
{
// Find which file data are already cached, and if no new file ids to query, then return cached only data
static $cached_data = array();
$return_data = array();
$new_ids = array();
$file_ids = (array) $fid;
foreach ($file_ids as $file_id)
{
$f = (int)$file_id;
if ( !isset($cached_data[$f]) && $f)
$new_ids[] = $f;
}
// Get file data not retrieved already
if ( count($new_ids) )
{
// Only query files that are not already cached
$db = Factory::getDbo();
$query = 'SELECT * '. $extra_select //filename, filename_original, altname, description, ext, id'
. ' FROM #__flexicontent_files'
. ' WHERE id IN ('. implode(',', $new_ids) . ')'
. ($published ? ' AND published = 1' : '')
;
$db->setQuery($query);
$new_data = $db->loadObjectList('id');
if ($new_data) foreach($new_data as $file_id => $file_data)
{
$cached_data[$file_id] = $file_data;
}
}
// Finally get file data in correct order
foreach($file_ids as $file_id)
{
$f = (int)$file_id;
if ( isset($cached_data[$f]) && $f)
{
$return_data[$file_id] = $cached_data[$f];
}
}
return !is_array($fid) ? @$return_data[(int)$fid] : $return_data;
}
/**
* Get folder path used by image thubmnails
*/
function getThumbPaths($field, $item, $value, $rel = false)
{
$image_source = (int) $field->parameters->get('image_source', 0);
$image_source = $image_source > 1 ? $this->nonImplementedMode($image_source, $field) : $image_source;
$target_dir = (int) $field->parameters->get('target_dir', 1);
$dir = $field->parameters->get('dir');
// Check if using folder of original content being translated
$of_usage = $field->untranslatable ? 1 : $field->parameters->get('of_usage', 0);
$u_item_id = ($of_usage && $item->lang_parent_id && $item->lang_parent_id != $item->id) ? $item->lang_parent_id : $item->id;
// Extract sub-folder pathfrom the (filepath) value (if it exists)
$subpath = dirname($value['originalname']);
$subpath = $subpath !== '.' ? $subpath . DS : '';
$filename = basename($value['originalname']);
/**
* Find extra thumbnails sub-folder
* Find original folder path
*/
// Default value, ('default_image' is a FILE path)
if (!empty($value['default_image']))
{
$extra_folder = '';
$src_path = Path::clean( (!$rel ? JPATH_SITE . DS : '') . dirname($value['default_image']) .DS );
}
// Intro-full image mode, ('image_path' is a FILE path of an intro / full image)
elseif ($image_source === -1)
{
$extra_folder = 'intro_full';
$src_path = Path::clean( (!$rel ? JPATH_SITE . DS : '') . dirname($value['image_path']) .DS );
}
// Media manager mode
elseif ($image_source === -2)
{
$extra_folder = 'mediaman';
$src_path = Path::clean( JPATH_SITE .DS );
}
// Folder-mode 1
elseif ($image_source >= 1)
{
$extra_folder = 'item_'.$u_item_id . '_field_'.$field->id;
$src_path = Path::clean( (!$rel ? JPATH_SITE . DS : '') . $dir .DS. $extra_folder .DS. 'original' .DS );
}
// DB-mode
else
{
$extra_folder = '';
$src_path = Path::clean( ($target_dir ? COM_FLEXICONTENT_FILEPATH : COM_FLEXICONTENT_MEDIAPATH).DS );
}
// Add value-extracted subpath to original folder
$src_path = Path::clean( $src_path . ($subpath ? $subpath . DS : '') );
// Full path of original file - and - Destination folder
$file_path = Path::clean( $src_path . $filename );
$dest_path = Path::clean( (!$rel ? JPATH_SITE . DS : '') . $dir .DS. ($extra_folder ? $extra_folder .DS : '') );
/**
* Create an index that differentiatiates same file in different fields
*/
// Folder-mode 1
if ($image_source >= 1)
{
// TODO other folder modes
$field_index = 'item_'.$u_item_id . '_field_'.$field->id;
}
// DB-mode or intro-full mode
else
{
$field_index = 'field_'.$field->id;
}
// Configuration
$image_source = (int) $field->parameters->get('image_source', 0);
$image_source = $image_source > 1 ? $this->nonImplementedMode($image_source, $field) : $image_source;
$all_media = $field->parameters->get('list_all_media_files', 0);
$unique_thumb_method = $field->parameters->get('unique_thumb_method', 0);
// *** FLAG to indicate if images are shared across fields, has the effect of adding field id to image thumbnails
$multiple_image_usages = $image_source == 0 && $all_media && $unique_thumb_method == 0;
$multiple_image_usages = $multiple_image_usages || !empty($value['default_image']);
$extra_prefix = $multiple_image_usages ? 'fld' . $field->id . '_' : '';
//echo 'file_path: ' . $file_path ."
" . 'dest_path: ' . $dest_path ."
";
return array($file_path, $src_path, $dest_path, $field_index, $extra_prefix);
}
/**
* Enforce protection of original image files any Folder-mode
*/
protected function protectImagePath($field, $src_path)
{
$image_source = (int) $field->parameters->get('image_source', 0);
$image_source = $image_source > 1 ? $this->nonImplementedMode($image_source, $field) : $image_source;
if ($image_source < 1 || !file_exists($src_path))
{
return;
}
$protect_original = $field->parameters->get('protect_original', 1);
$htaccess_file = Path::clean( $src_path . '.htaccess' );
$file_contents = $protect_original
?
'# do not allow direct access and also deny scripts'."\n".
''."\n".
' Order Allow,Deny'."\n".
' Deny from all'."\n".
' '."\n".
'OPTIONS -Indexes -ExecCGI'."\n"
:
'# allow direct access but deny script'."\n".
''."\n".
' Order Allow,Deny'."\n".
' Allow from all'."\n".
' '."\n".
'OPTIONS -Indexes -ExecCGI'."\n";
// write .htaccess file
$fh = @ fopen($htaccess_file, 'w');
if (!$fh)
{
Factory::getApplication()->enqueueMessage( 'Cannot create/write file:'.$htaccess_file, 'notice' );
}
else
{
fwrite($fh, $file_contents);
fclose($fh);
}
}
/**
* TODO move this method to parent field class or to helper class
*/
private function _get_custom_text($field, $item, $paramName, $paramNameCode = null)
{
// Check if using 'auto_value_code', clear 'auto_value', if function not set
$custom_text = (int) $field->parameters->get($paramName, 0);
if ($custom_text === 2)
{
$paramNameCode = $paramNameCode ?: $paramName . '_code';
$custom_text_code = $field->parameters->get($paramNameCode, '');
$custom_text_code = preg_replace('/^<\?php(.*)(\?>)?$/s', '$1', $custom_text_code);
}
$custom_text = $custom_text === 2 && !$custom_text_code ? 0 : $custom_text;
if (!$custom_text)
{
return;
}
$return = array();
switch($custom_text)
{
case 2: // AUTOMATIC value, via function
try {
ob_start();
$old_error_reporting = error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
$old_error_handler = set_error_handler(array($this, '_custom_error_handler'));
$return = eval($custom_text_code);
error_reporting($old_error_reporting);
set_error_handler($old_error_handler);
$errors = trim(ob_get_contents());
ob_clean();
if ($errors) Factory::getApplication()->enqueueMessage( 'Field \'' . $field->label . '\' :
' . $errors . '
', 'notice');
}
catch (ParseError $e) {
Factory::getApplication()->enqueueMessage( "Automatic value custom code, failed with: " . $e->getMessage() . '
', 'warning');
}
break;
}
return $return;
}
private function _custom_error_handler($errno, $errstr, $errfile, $errline)
{
if (!(error_reporting() & $errno))
{
// This error code is not included in error_reporting, so let it fall through to the standard PHP error handler
return false;
}
switch ($errno) {
case E_NOTICE:
case E_USER_NOTICE:
case E_DEPRECATED:
case E_USER_DEPRECATED:
case E_STRICT:
echo("NOTICE: $errstr at line: $errline \n");
break;
case E_WARNING:
case E_USER_WARNING:
echo("WARNING: $errstr at line: $errline \n");
break;
case E_ERROR:
case E_USER_ERROR:
case E_RECOVERABLE_ERROR:
echo("ERROR: $errstr at line: $errline \n");
default:
echo("UNKNOWN ERROR at line: $errline \n");
}
}
}