| Current Path : /home/cbequiperp/www/plugins/flexicontent_fields/image/ |
| Current File : /home/cbequiperp/www/plugins/flexicontent_fields/image/image.php |
<?php
/**
* @package FLEXIcontent
* @version 3.4
*
* @author Emmanuel Danan, Georgios Papadakis, Yannick Berges, others, see contributor page
* @link https://flexicontent.org
* @copyright Copyright © 2020, FLEXIcontent team, All Rights Reserved
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
*/
defined( '_JEXEC' ) or die( 'Restricted access' );
JLoader::register('FCField', JPATH_ADMINISTRATOR . '/components/com_flexicontent/helpers/fcfield/parentfield.php');
JLoader::register('FlexicontentControllerFilemanager', JPATH_ADMINISTRATOR.DS.'components'.DS.'com_flexicontent'.DS.'controllers'.DS.'filemanager.php'); // we use JPATH_BASE since controller exists in frontend too
JLoader::register('FlexicontentModelFilemanager', JPATH_ADMINISTRATOR.DS.'components'.DS.'com_flexicontent'.DS.'models'.DS.'filemanager.php'); // we use JPATH_BASE since model exists in frontend too
if (!defined('_FC_CONTINUE_')) define('_FC_CONTINUE_', 1);
if (!defined('_FC_BREAK_')) define('_FC_BREAK_', 2);
if (!defined('_FC_RETURN_')) define('_FC_RETURN_', 3);
class plgFlexicontent_fieldsImage extends FCField
{
static $field_types = null; // Automatic, do not remove since needed for proper late static binding, define explicitely when a field can render other field types
var $task_callable = null; // Field's methods allowed to be called via AJAX
static $default_widths = array('l' => 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') ? JText::_($field->parameters->get('label_form')) : JText::_($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 = JFactory::getDocument();
$cparams = JComponentHelper::getParams( 'com_flexicontent' );
$app = JFactory::getApplication();
$user = JFactory::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';
$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(JFactory::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);
$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);
$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) ? JText::_($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('<div class="alert alert-warning fc-small fc-iblock">Field is configured to use intro/full images, please disable use in group</div>') :
'_INTRO_FULL_IMAGES_HTML_';
return;
}
// Add JS /CSS for Media manager mode, and also check their PHP layouts overides exist
static $mm_mode_common_js_added = false;
if ($image_source === -2 && !$mm_mode_common_js_added)
{
// Check and if needed install Joomla template overrides into current Joomla template
flexicontent_html::install_template_overrides();
if (!$use_jformfields)
{
// We will use the mootools based media manager
JHtml::_('behavior.framework', true);
// Load the modal behavior script.
JHtml::_('behavior.modal'/*, '.fc_image_field_mm_modal'*/);
// Include media field JS, detecting different version of Joomla
if (file_exists($path = JPATH_ROOT.'/media/media/js/mediafield-mootools.min.js'))
{
$media_js = 'media/mediafield-mootools.min.js';
}
else
{
$media_js = file_exists($path = JPATH_ROOT.'/media/media/js/mediafield.min.js')
? 'media/mediafield.min.js'
: 'media/mediafield.js';
}
JHtml::_('script', $media_js, $mootools_framework = true, $media_folder_relative_path = true, false, false, true);
// Tooltips for image path and image popup preview
JHtml::_('behavior.tooltip', '.hasTipImgpath', array('onShow' => 'jMediaRefreshImgpathTip'));
JHtml::_('behavior.tooltip', '.hasTipPreview', array('onShow' => 'jMediaRefreshPreviewTip'));
}
else
{
jimport('joomla.form.helper'); // JFormHelper
JFormHelper::loadFieldClass('media'); // JFormFieldMedia
}
$mm_mode_common_js_added = true;
}
// ***
// *** Slider for files grid view
// ***
if ($use_inline_uploaders && $thumb_size_resizer)
{
flexicontent_html::loadFramework('nouislider');
$resize_cfg = new stdClass();
$resize_cfg->slider_name = 'fcfield-'.$field->id.'-uploader-thumb-size';
$resize_cfg->element_selector = 'div.fcfield-'.$field->id.'-uploader-thumb-box';
$resize_cfg->elem_container_selector = '.fcfieldval_container_'.$field->id.' div.fc-box';
$resize_cfg->element_selector = '.fcfieldval_container_'.$field->id.' div.fc_file_uploader ul.plupload_filelist > li';
$resize_cfg->element_class_prefix = 'thumb_';
$resize_cfg->values = array(90, 120, 150, 200, 250);
$resize_cfg->labels = array();
$thumb_size_default = $app->input->cookie->get($resize_cfg->slider_name . '-val', $thumb_size_default, 'int');
$resize_cfg->initial_pos = (int) array_search($thumb_size_default, $resize_cfg->values);
if ($resize_cfg->initial_pos === false)
{
$resize_cfg->initial_pos = 1;
}
$thumb_size_default = $resize_cfg->values[$resize_cfg->initial_pos];
$app->input->cookie->set($resize_cfg->slider_name . '-val', $thumb_size_default);
foreach($resize_cfg->values as $value) $resize_cfg->labels[] = $value .'x'. $value;
$element_classes = array();
foreach($resize_cfg->values as $value) $element_classes[] = $resize_cfg->element_class_prefix . $value;
$element_class_list = implode(' ', $element_classes);
$step_values = '[' . implode(', ', $resize_cfg->values) . ']';
$step_labels = '["' . implode('", "', $resize_cfg->labels) . '"]';
$thumb_size_slider_cfg = "{
name: '".$resize_cfg->slider_name."',
step_values: ".$step_values.",
step_labels: ".$step_labels.",
initial_pos: ".$resize_cfg->initial_pos.",
start_hidden: false,
element_selector: '".$resize_cfg->element_selector."',
element_class_list: '',
element_class_prefix: '',
elem_container_selector: '".$resize_cfg->elem_container_selector."',
elem_container_class: '".$element_class_list."',
elem_container_prefix: '".$resize_cfg->element_class_prefix."'
}";
$document->addScriptDeclaration("
jQuery(document).ready(function()
{
fc_attachSingleSlider(".$thumb_size_slider_cfg.", ".$thumb_size_resizer.");
});
");
}
// Flag that indicates if field has values
$has_values = count($field->value);
// Initialise property with default value
if (!$field->value || (count($field->value) === 1 && reset($field->value) === null))
{
$field->value = array();
$field->value[0]['originalname'] = '';
$field->value[0] = serialize($field->value[0]);
}
// CSS classes of value container
$value_classes_base = 'fcfieldval_container valuebox fcfieldval_container_'.$field->id;
$value_classes_single = $value_classes_base . ' fc-expanded' ;
$value_classes_multiple = $value_classes_base . ($fields_box_placing ? ' floated' : '');
// Field name and HTML TAG id
$fieldname = 'custom['.$field->name.']';
$elementid = 'custom_'.$field->name;
// JS safe Field name
$field_name_js = str_replace('-', '_', $field->name);
// URL for modal fileselement view
$filesElementURL =
JUri::base(true).'/index.php?option=com_flexicontent&view=fileselement&tmpl=component&layout=image'
.'&field='.$field->id.'&u_item_id='.$u_item_id.'&targetid=%s_existingname&thumb_w='.$preview_thumb_w.'&thumb_h='.$preview_thumb_h.'&autoassign='.$autoassign
.'&'.JSession::getFormToken().'=1';
$js = '
var fc_field_dialog_handle_'.$field->id.';
fcfield_image.debugToConsole["'.$field_name_js.'"] = 0;
fcfield_image.use_native_apis["'.$field_name_js.'"] = 0;
';
$css = '';
// Handle multiple records
//if ($multiple)
if (1) // This if contains more than multile record handlings, TODO: split it
{
// Add the drag and drop sorting feature
if ($add_ctrl_btns) $js .= "
jQuery(document).ready(function(){
jQuery('#sortables_".$field->id."').sortable({
handle: '.fcfield-drag-handle',
cancel: false,
/*containment: 'parent',*/
tolerance: 'pointer'
".($fields_box_placing ? "
,start: function(e) {
//jQuery(e.target).children().css('float', 'left');
//fc_setEqualHeights(jQuery(e.target), 0);
}
,stop: function(e) {
//jQuery(e.target).children().css({'float': 'none', 'min-height': '', 'height': ''});
}
" : '')."
});
});
";
if ($max_values) JText::script("FLEXI_FIELD_MAX_ALLOWED_VALUES_REACHED", true);
$js .= "
function addField".$field->id."(el, groupval_box, fieldval_box, params)
{
var insert_before = (typeof params!== 'undefined' && typeof params.insert_before !== 'undefined') ? params.insert_before : 0;
var remove_previous = (typeof params!== 'undefined' && typeof params.remove_previous !== 'undefined') ? params.remove_previous : 0;
var scroll_visible = (typeof params!== 'undefined' && typeof params.scroll_visible !== 'undefined') ? params.scroll_visible : 1;
var animate_visible = (typeof params!== 'undefined' && typeof params.animate_visible !== 'undefined') ? params.animate_visible : 1;
if(!remove_previous && (rowCount".$field->id." >= maxValues".$field->id.") && (maxValues".$field->id." != 0)) {
alert(Joomla.JText._('FLEXI_FIELD_MAX_ALLOWED_VALUES_REACHED') + maxValues".$field->id.");
return 'cancel';
}
// Find last container of fields and clone it to create a new container of fields
var lastField = fieldval_box ? fieldval_box : jQuery(el).prev().children().last();
var newField = lastField.clone();
newField.find('.fc-has-value').removeClass('fc-has-value');
// New element's field name and id
var uniqueRowN = uniqueRowNum" . $field->id . ";
var element_id = '" . $elementid . "_' + uniqueRowN;
// Destroy any select2 elements
var sel2_elements = newField.find('div.select2-container');
if (sel2_elements.length)
{
sel2_elements.remove();
newField.find('select.use_select2_lib').select2('destroy').show();
}
newField.find('input.hasvalue').val('');
newField.find('input.hasvalue').attr('name', element_id + '_hasvalue');
newField.find('input.hasvalue').attr('id', element_id);
newField.find('input.originalname').val('');
newField.find('input.originalname').attr('name','".$fieldname."['+uniqueRowN+'][originalname]');
newField.find('input.originalname').attr('id', element_id + '_originalname');
newField.find('.existingname').val('');
newField.find('.existingname').attr('name','".$fieldname."['+uniqueRowN+'][existingname]');
newField.find('.existingname').attr('id', element_id + '_existingname');
newField.find('.fc_preview_msg').html('');
newField.find('.fc_preview_msg').attr('name', element_id + '_fc_preview_msg');
newField.find('.fc_preview_msg').attr('id', element_id + '_fc_preview_msg');
// Update uploader related data
var fcUploader = newField.find('.fc_file_uploader');
var upBTN, mulupBTN, mulselBTN;
if (fcUploader.length)
{
// Update uploader attributes
fcUploader.empty().hide();
fcUploader.attr('id', fcUploader.attr('data-tagid-prefix') + uniqueRowN);
// Update button for toggling uploader
upBTN = newField.find('.fc_files_uploader_toggle_btn');
upBTN.attr('data-rowno', uniqueRowN);
mulupBTN = newField.find('.fc-files-modal-link.fc-up');
mulupBTN.attr('data-href', " . "'" . str_replace('&', '&', sprintf($filesElementURL, $elementid . "_' + uniqueRowNum".$field->id ." + '")) . "');
mulselBTN = newField.find('.fc-files-modal-link.fc-sel');
mulselBTN.attr('data-href', " . "'" . str_replace('&', '&', sprintf($filesElementURL, $elementid . "_' + uniqueRowNum".$field->id ." + '")) . "');
}
// COPY an preview box
var img_preview = newField.find('img.fc_preview_thumb');
if (img_preview.length)
{
var emptyImg = jQuery('<img class=\"fc_preview_thumb\" id=\"\" src=\"data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=\" alt=\"Preview image\" />');
emptyImg.attr('id', element_id + '_preview_image');
emptyImg.insertAfter( img_preview );
img_preview.remove();
}
newField.find('table.fcimg_dbfile_tbl').parent('display', 'none');
";
if ($linkto_url) $js .= "
newField.find('input.imgurllink').val('');
newField.find('input.imgurllink').attr('name','".$fieldname."['+uniqueRowN+'][urllink]');
newField.find('input.imgurllink').attr('id', element_id + '_urllink');
";
if ($usemediaurl)
{
$js .= "
var elements = ['img_mediaurl', 'img_fetch_btn', 'img_clear_btn'];
for (var i = 0; i < elements.length; i++)
{
theInput = newField.find('.' + elements[i]).first();
var el_name = elements[i].replace(/^img_/, '');
theInput.attr('name','".$fieldname."['+uniqueRowN+']['+el_name+']');
theInput.attr('id', element_id + '_' + el_name);
}
newField.find('input.img_mediaurl').attr('value', ".json_encode($default_mediaurl).");
newField.find('.fcfield-medialurlvalue').attr('onclick', 'fcfield_image.toggleMediaURL(\'' + element_id + '\', \'".$field_name_js."\');');
newField.find('.img_fetch_btn').attr('onclick', 'fcfield_image.fetchData(\'' + element_id + '\', \'".$field_name_js."\'); return false;');
newField.find('.img_clear_btn').attr('onclick', 'fcfield_image.clearData(\'' + element_id + '\', \'".$field_name_js."\'); return false;');
newField.find('.fcfield_message_box').attr('id','fcfield_message_box_' + element_id);
// Clear any existing message
jQuery('#fcfield_message_box_' + element_id).html('');
";
}
if ($usealt) $js .= "
newField.find('input.imgalt').attr('value', ".json_encode($default_alt).");
newField.find('input.imgalt').attr('name','".$fieldname."['+uniqueRowN+'][alt]');
newField.find('input.imgalt').attr('id', element_id + '_alt');
";
if ($usetitle) $js .= "
newField.find('input.imgtitle').attr('value', ".json_encode($default_title).");
newField.find('input.imgtitle').attr('name','".$fieldname."['+uniqueRowN+'][title]');
newField.find('input.imgtitle').attr('id', element_id + '_title');
";
if ($usedesc) $js .= "
newField.find('textarea.imgdesc').attr('value', ".json_encode($default_desc).");
newField.find('textarea.imgdesc').attr('name','".$fieldname."['+uniqueRowN+'][desc]');
";
if ($usecust1) $js .= "
newField.find('input.imgcust1').attr('value', ".json_encode($default_cust1).");
newField.find('input.imgcust1').attr('name','".$fieldname."['+uniqueRowN+'][cust1]');
";
if ($usecust2) $js .= "
newField.find('input.imgcust2').attr('value', ".json_encode($default_cust2).");
newField.find('input.imgcust2').attr('name','".$fieldname."['+uniqueRowN+'][cust2]');
";
// Add new field to DOM
$js .= "
lastField ?
(insert_before ? newField.insertBefore( lastField ) : newField.insertAfter( lastField ) ) :
newField.appendTo( jQuery('#sortables_".$field->id."') ) ;
if (remove_previous) lastField.remove();
// Attach form validation on new element
fc_validationAttach(newField);
// Re-init any select2 elements
fc_attachSelect2(newField);
" .
// Re-init joomla media form field element (J3 only)
($image_source === -2 && $use_jformfields && !FLEXI_J40GE ? "newField.find('.field-media-wrapper').fieldMedia();" : '') .
// Clear image preview
($image_source === -2 && $use_jformfields ? "newField.find('.field-media-wrapper').find('.button-clear').click();" : '')
;
// Add new element to sortable objects (if field not in group)
if ($add_ctrl_btns) $js .= "
//jQuery('#sortables_".$field->id."').sortable('refresh'); // Refresh was done appendTo ?
";
// Show new field, increment counters
$js .="
//newField.fadeOut({ duration: 400, easing: 'swing' }).fadeIn({ duration: 200, easing: 'swing' });
if (scroll_visible) fc_scrollIntoView(newField, 1);
if (animate_visible) newField.css({opacity: 0.1}).animate({ opacity: 1 }, 800, function() { jQuery(this).css('opacity', ''); });
// Set tooltip data placeholders
var _name = '_existingname';
newField.find('.media-preview').html('<span class=\"hasTipPreview\" title=\"<strong>" . JText::_('JLIB_FORM_MEDIA_PREVIEW_SELECTED_IMAGE', true)
. "</strong><br /><span style="display: block;" id="' + element_id + _name + '_preview_empty" style="display:none">" . JText::_('JLIB_FORM_MEDIA_PREVIEW_EMPTY', true)
. "</span><span style="display: block;" id="' + element_id + _name + '_preview_img"><img src="" alt="" . JText::_('JLIB_FORM_MEDIA_PREVIEW_SELECTED_IMAGE', true)
. "" id="' + element_id + _name + '_preview" class="media-preview" style=" style="max-width:480px; max-height:360" " /></span>\"><span class=\"icon-eye\" aria-hidden=\"true\"></span><span class=\"icon-image\" aria-hidden=\"true\"></span> "
. "</span>');
// Enable tooltips on new element
newField.find('.hasTooltip').tooltip({html: true, container: newField});
newField.find('.hasPopover').popover({html: true, container: newField, trigger : 'hover focus'});
// Show tooltips
var tipped_elements = newField.find('.hasTipImgpath, .hasTipPreview');
tipped_elements.each(function() {
var title = this.get('title');
if (title) {
var parts = title.split('::', 2);
this.store('tip:title', parts[0]);
this.store('tip:text', parts[1]);
}
});
if (tipped_elements.length)
{
var imgpath_JTooltips = new Tips(jQuery(newField).find('.hasTipImgpath').get(0), { \"maxTitleChars\": 50, \"fixed\": false, \"onShow\": jMediaRefreshImgpathTip});
var imgprev_JTooltips = new Tips(jQuery(newField).find('.hasTipPreview').get(0), { \"maxTitleChars\": 50, \"fixed\": false, \"onShow\": jMediaRefreshPreviewTip});
}
// Show uploader, if not 'animating visible' e.g. if not doing multi-add
if (animate_visible && fcUploader.length) upBTN.click();
rowCount".$field->id."++; // incremented / decremented
uniqueRowNum".$field->id."++; // incremented only
// return HTML Tag ID of field containing the file ID, needed when creating file rows to assign multi-fields at once
return '".$elementid."_' + (uniqueRowNum".$field->id." - 1) + '_existingname';
}
function deleteField".$field->id."(el, groupval_box, fieldval_box)
{
// Disable clicks on remove button, so that it is not reclicked, while we do the field value hide effect (before DOM removal of field value)
var btn = fieldval_box ? false : jQuery(el);
if (btn && rowCount".$field->id." > 1) btn.css('pointer-events', 'none').off('click');
// Find field value container
var row = fieldval_box ? fieldval_box : jQuery(el).closest('li');
// When removing a field value we need to check if it had value and decrement the value counter
var originalfftag = 'input.originalname';
var existingfftag = '".($image_source === 0 ? "select" : "input")."' + '.existingname';
var originalname = row.find( originalfftag ).val();
var existingname = row.find( existingfftag ).val();
var hasvalue = row.find( 'input.hasvalue').val();
var valcounter = document.getElementById('custom_".$field_name_js."');
// IF a non-empty container is being removed ... get counter (which is optionally used as 'required' form element and empty it if is 1, or decrement if 2 or more)
//if ( originalname != '' || existingname != '' )
if (hasvalue!='')
{
valcounter.value = ( !valcounter.value || valcounter.value=='1' ) ? '' : parseInt(valcounter.value) - 1;
//if(window.console) window.console.log ('valcounter.value: ' + valcounter.value);
}
// Add empty container if last element, instantly removing the given field value container
if(rowCount".$field->id." == 1)
addField".$field->id."(null, groupval_box, row, {remove_previous: 1, scroll_visible: 0, animate_visible: 0});
// Remove if not last one, if it is last one, we issued a replace (copy,empty new,delete old) above
if (rowCount".$field->id." > 1)
{
// Destroy the remove/add/etc buttons, so that they are not reclicked, while we do the field value hide effect (before DOM removal of field value)
row.find('.fcfield-delvalue').remove();
row.find('.fcfield-expand-view').remove();
row.find('.fcfield-insertvalue').remove();
row.find('.fcfield-drag-handle').remove();
// Do hide effect then remove from DOM
row.slideUp(400, function(){ jQuery(this).remove(); });
rowCount".$field->id."--;
}
//if (window.console) window.console.log('valcounter: ' + valcounter.value);
}
";
$css .= '';
$remove_button = '<span class="' . $add_on_class . ' fcfield-delvalue ' . $font_icon_class . '" title="'.JText::_( 'FLEXI_REMOVE_VALUE' ).'" onclick="deleteField'.$field->id.'(this);"></span>';
$move2 = '<span class="' . $add_on_class . ' fcfield-drag-handle ' . $font_icon_class . '" title="'.JText::_( 'FLEXI_CLICK_TO_DRAG' ).'"></span>';
$add_here = '';
$add_here .= $add_position==2 || $add_position==3 ? '<span class="' . $add_on_class . ' fcfield-insertvalue fc_before ' . $font_icon_class . '" onclick="addField'.$field->id.'(null, jQuery(this).closest(\'ul\'), jQuery(this).closest(\'li\'), {insert_before: 1});" title="'.JText::_( 'FLEXI_ADD_BEFORE' ).'"></span> ' : '';
$add_here .= $add_position==1 || $add_position==3 ? '<span class="' . $add_on_class . ' fcfield-insertvalue fc_after ' . $font_icon_class . '" onclick="addField'.$field->id.'(null, jQuery(this).closest(\'ul\'), jQuery(this).closest(\'li\'), {insert_before: 0});" title="'.JText::_( 'FLEXI_ADD_AFTER' ).'"></span> ' : '';
}
// Field not multi-value
if (!$multiple)
{
$remove_button = '';
$move2 = '';
$add_here = '';
$js .= '';
$css .= '';
}
// Add field's custom CSS / JS
$js .= "
/**
* Method Wrappers to class methods (used for compatibility)
*/
function fcfield_assignImage".$field->id."(tagid, file, preview_url, keep_modal, preview_caption)
{
fcfield_image.assignImage(tagid, file, preview_url, keep_modal, preview_caption, '".$field_name_js."');
}
/* Method used as callbacks of AJAX uploader */
function fcfield_FileFiltered_".$field->id."(uploader, file)
{
fcfield_image.fileFiltered(uploader, file, '".$field_name_js."');
}
function fcfield_FileUploaded_".$field->id."(uploader, file, result)
{
fcfield_image.fileUploaded(uploader, file, result, '".$field_name_js."');
}
";
$css .='';
/**
* Load form JS
*/
// Add needed JS/CSS
static $js_added = null;
if ( $js_added === null )
{
$js_added = true;
JText::script("FLEXI_FIELD_IMAGE_CLEAR_MEDIA_URL_FIRST", true);
JText::script("FLEXI_FIELD_IMAGE_ENTER_MEDIA_URL", true);
JText::script("FLEXI_FIELD_MEDIA_URL", true);
JText::script("FLEXI_ERROR", true);
flexicontent_html::loadFramework('flexi-lib');
JHtml::addIncludePath(JPATH_SITE . '/components/com_flexicontent/helpers/html');
$document->addScript(JUri::root(true) . '/plugins/flexicontent_fields/image/js/form.js', array('version' => FLEXI_VHASH));
}
// Add field's CSS / JS
if ($multiple) $js .= "
var uniqueRowNum".$field->id." = ".count($field->value)."; // Unique row number incremented only
var rowCount".$field->id." = ".count($field->value)."; // Counts existing rows to be able to limit a max number of values
var maxValues".$field->id." = ".$max_values.";
";
if ($js) $document->addScriptDeclaration($js);
if ($css) $document->addStyleDeclaration($css);
/**
* Create field's HTML display for item form
*/
$field->html = array();
$uploader_html_arr = array();
$formlayout = $field->parameters->get('formlayout', '');
$formlayout = $formlayout ? 'field_'.$formlayout : 'field_InlineBoxes';
//$this->setField($field);
//$this->setItem($item);
//$this->displayField( $formlayout );
include(self::getFormPath($this->fieldtypes[0], $formlayout));
// Do not convert the array to string if field is in a group
if ($use_ingroup);
// Handle multiple records
elseif ($multiple)
{
$field->html = !count($field->html) ? '' :
'<li class="' . $value_classes_multiple . '">'.
implode('</li><li class="' . $value_classes_multiple . '">', $field->html).
'</li>';
$field->html = '<ul class="fcfield-sortables" id="sortables_'.$field->id.'">' .$field->html. '</ul>';
if (!$add_position) $field->html .= '
<div class="input-append input-prepend fc-xpended-btns">
<span class="fcfield-addvalue ' . $font_icon_class . ' fccleared" onclick="addField'.$field->id.'(jQuery(this).closest(\'.fc-xpended-btns\').get(0));" title="'.JText::_( 'FLEXI_ADD_TO_BOTTOM' ).'">
'.JText::_( 'FLEXI_ADD_VALUE' ).'
</span>
</div>';
}
// Handle single values
else
{
// Because of JS seeking the parent containers, use UL/LI instead of DIV
$field->html = !count($field->html) ? '' :
'<li class="' . $value_classes_single . '">'.
implode('</li><li class="' . $value_classes_single . '">', $field->html).
'</li>';
$field->html = '<ul class="fcfield-sortables" id="sortables_'.$field->id.'">' .$field->html. '</ul>';
}
// This is field HTML that is created regardless of values
$non_value_html = '<input id="custom_'.$field_name_js.'" class="fc_hidden_value '.($use_ingroup ? '' : $required_class).'" type="text" name="__fcfld_valcnt__['.$field->name.']" value="'.($count_vals ? $count_vals : '').'" />';
if ($use_ingroup)
{
$field->html[-1] = $non_value_html;
if ($use_inline_uploaders && $uploader_html->thumbResizer)
{
$field->html[-1] = '<div class="label" style="float: left">' . $field->label . '</div>' . $uploader_html->thumbResizer . ' ' . $field->html[-1] . '<div class="clear"></div>';
}
}
else
{
$field->html .= $non_value_html;
if ($use_inline_uploaders && $uploader_html->thumbResizer)
{
$field->html = $uploader_html->thumbResizer . ' ' . $field->html;
}
}
if ( count($skipped_vals) )
{
$app->enqueueMessage( JText::sprintf('FLEXI_FIELD_IMAGE_EDIT_VALUES_SKIPPED', $field->label, implode(',',$skipped_vals)), 'notice' );
}
}
// Method to create field's HTML display for frontend views
public function onDisplayFieldValue(&$field, $item, $values = null, $prop = 'display')
{
if ( !in_array($field->field_type, static::$field_types) ) return;
$field->label = JText::_($field->label);
// Set field and item objects
$this->setField($field);
$this->setItem($item);
/**
* One time initialization
*/
static $initialized = null;
static $app, $document, $option, $format, $realview;
if ($initialized === null)
{
$initialized = 1;
$app = JFactory::getApplication();
$document = JFactory::getDocument();
$option = $app->input->getCmd('option', '');
$format = $app->input->getCmd('format', 'html');
$realview = $app->input->getCmd('view', '');
}
// For legacy layouts
$isItemsManager = static::$isItemsManager;
$isHtmlViewFE = static::$isHtmlViewFE;
// Current view variable
$view = $app->input->getCmd('flexi_callview', ($realview ?: 'item'));
$sfx = $view === 'item' ? '' : '_cat';
// Check if field should be rendered according to configuration
if (!$this->checkRenderConds($prop, $view))
{
return;
}
// The current view is a full item view of the item
$isMatchedItemView = static::$itemViewId === (int) $item->id;
// Some variables
$is_ingroup = !empty($field->ingroup);
$use_ingroup = $field->parameters->get('use_ingroup', 0);
$multiple = $use_ingroup || (int) $field->parameters->get( 'allow_multiple', 0 ) ;
$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);
// JS safe Field name
$field_name_js = str_replace('-', '_', $field->name);
$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);
// 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;
// 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 . '_' : '';
$usemediaurl = (int) $field->parameters->get('use_mediaurl', 0);
$mediaurl_usage = (int) $field->parameters->get('mediaurl_usage', 0);
$default_mediaurl = ($mediaurl_usage == 2) ? $field->parameters->get('default_mediaurl', '') : '';
$usealt = (int) $field->parameters->get('use_alt', 0);
$alt_usage = (int) $field->parameters->get('alt_usage', 0);
$default_alt = ($alt_usage == 2) ? $field->parameters->get('default_alt', '') : '';
$usetitle = (int) $field->parameters->get('use_title', 0);
$title_usage = (int) $field->parameters->get('title_usage', 0);
$default_title = ($title_usage == 2) ? JText::_($field->parameters->get('default_title', '')) : '';
$usedesc = (int) $field->parameters->get('use_desc', 1);
$desc_usage = (int) $field->parameters->get('desc_usage', 0);
$default_desc = ($desc_usage == 2) ? $field->parameters->get('default_desc', '') : '';
$usecust1 = (int) $field->parameters->get('use_cust1', 0);
$cust1_usage = (int) $field->parameters->get('cust1_usage', 0);
$default_cust1 = ($cust1_usage == 2) ? JText::_($field->parameters->get('default_cust1', '')) : '';
$usecust2 = (int) $field->parameters->get('use_cust2', 0);
$cust2_usage = (int) $field->parameters->get('cust2_usage', 0);
$default_cust2 = ($cust2_usage == 2) ? JText::_($field->parameters->get('default_cust2', '')) : '';
/**
* Get common parameters like: itemprop, value's prefix (pretext), suffix (posttext), separator, value list open/close text (opentag, closetag)
* This will replace other field values and item properties, if such are found inside the parameter texts
*/
$common_params_array = $this->getCommonParams();
extract($common_params_array);
// ***
// *** SETUP VALUES: retrieve, verify, load defaults, etc
// ***
$values = $values ? $values : $field->value;
// Intro-full mode get their values from item's parameters
if ($image_source === -1)
{
$values = array();
// Use 'intro' image in multi-item listings
switch ($view)
{
case 'item':
$_image_name = $field->parameters->get('img-if-for-itemlist', '2') === '1' ? 'intro' : 'fulltext';
break;
case 'category':
$_image_name = $field->parameters->get('img-if-for-catlist', '1') === '1' ? 'intro' : 'fulltext';
break;
case 'module':
case 'sublist':
default:
$_image_name = $field->parameters->get('img-if-for-modlist', '1') === '1' ? 'intro' : 'fulltext';
break;
}
if ($item->images)
{
if (!is_object($item->images))
{
try
{
$item->images = new JRegistry($item->images);
}
catch (Exception $e)
{
$item->images = flexicontent_db::check_fix_JSON_column('images', 'content', 'id', $item->id);
}
}
$_image_path = $item->images->get('image_' . $_image_name, '');
// Use 'fulltext' image if 'intro' image is empty
if (!$_image_path && $_image_name === 'intro')
{
$_image_name = 'fulltext';
$_image_path = $item->images->get('image_' . $_image_name, '');
}
$image_IF = array();
// field attributes (mode-specific)
$image_IF['image_size'] = $_image_name;
$image_IF['image_path'] = $_image_path;
// field attributes (value)
$image_IF['originalname'] = basename($_image_path);
$image_IF['alt'] = $item->images->get('image_' . $_image_name.'_alt', '');
$image_IF['title'] = $item->images->get('image_' . $_image_name.'_alt', '');
$image_IF['desc'] = $item->images->get('image_' . $_image_name.'_caption', '');
$image_IF['cust1'] = '';
$image_IF['cust2'] = '';
$image_IF['urllink'] = '';
$values = array(serialize($image_IF));
//echo "<pre>"; print_r($image_IF); echo "</pre>"; 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[] = $values[$index];
}
// In case of failed thumbnailing, add empty value if in fieldgroup
else if ($is_ingroup)
{
$usable_values[] = 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))
{
$image_DF = array();
// Holds complete relative path and indicates that it is default image for field
$default_image = '';
$default_image_custom = $field->parameters->get('default_image_custom', 0);
if ($default_image_custom)
{
$default_image = $this->_get_custom_text($field, $item, 'default_image_custom');
}
if (!$default_image)
{
$default_image = $field->parameters->get('default_image', '');
}
if ($default_image)
{
$image_DF['default_image'] = $default_image;
$image_DF['originalname'] = basename($default_image);
// Also default image can (possibly) be used across multiple fields, so set flag to add field id to filenames of thumbnails
$multiple_image_usages = true;
$extra_prefix = 'fld' . $field->id . '_';
$field->using_default_value = true;
// field attributes (value)
$image_DF['alt'] = $default_alt;
$image_DF['title'] = $default_title;
$image_DF['desc'] = $default_desc;
$image_DF['cust1'] = $default_cust1;
$image_DF['cust2'] = $default_cust2;
$image_DF['urllink'] = '';
// Create thumbnails for default image
if (plgFlexicontent_fieldsImage::rebuildThumbs($field, $image_DF, $item))
{
$values = array(serialize($image_DF));
}
}
}
// ***
// *** Check for no values and no default value, and return empty display
// ***
if (empty($values))
{
$field->{$prop} = $is_ingroup ? array() : '';
return;
}
// Assign (possibly) altered value array to back to the field
$field->value = $values; // This is not done for onDisplayFieldValue, TODO check if this is needed
// ***
// *** Default display method depends on view
// ***
if ($prop=='display' && ($view=='item' || $view=='category'))
{
$_method = $view === 'item'
? $field->parameters->get('default_method_item', 'display')
: $field->parameters->get('default_method_cat', 'display_single_total');
}
else
{
$_method = $prop;
}
$cat_link_single_to = $field->parameters->get( 'cat_link_single_to', 1) ;
// Calculate some flags, SINGLE image display and Link-to-Item FLAG
$isSingle = isset(self::$single_displays[$_method]);
$linkto_item = $_method == 'display_link' || $_method == 'display_single_link' || $_method == 'display_single_total_link' || ($view!='item' && $cat_link_single_to && $isSingle);
// ***
// *** JS gallery configuration
// ***
$usepopup = (int) $field->parameters->get( 'usepopup', 1 ) ; // use JS gallery
$popuptype = $field->parameters->get( 'popuptype', 1 ) ; // JS gallery type
if (is_numeric($popuptype))
{
$popuptype = (int) $popuptype;
}
// Different for mobile clients
$popuptype_mobile = $field->parameters->get( 'popuptype_mobile', $popuptype ) ; // this defaults to desktop when empty
if (is_numeric($popuptype_mobile))
{
$popuptype_mobile = (int) $popuptype_mobile;
}
$PPFX_ = static::$useMobile ? 'popuptype_mobile_' : 'popuptype_';
$popuptype = static::$useMobile
? $popuptype_mobile
: $popuptype;
// Enable/Disable GALLERY JS according to current view and according to other parameters
$popupinview = FLEXIUtilities::paramToArray($field->parameters->get('popupinview', array('item', 'category', 'module', 'backend')));
if (
($view=='item' && !in_array('item', $popupinview)) ||
($view=='category' && !in_array('category', $popupinview)) ||
($view=='module' && !in_array('module', $popupinview)) ||
(static::$isItemsManager && !in_array('backend', $popupinview)) ||
$linkto_item ||
$prop=='display_large' ||
$prop=='display_original' ||
$format !== 'html' ||
$realview=='itemcompare'
)
{
$usepopup = 0;
}
/**
* If using a non allowed gallery JS, then force fancybox
*/
// Only allow multibox and fancybox in items manager
$iManager_containers = array(1,4);
// Display types that need special container are not allowed when field in a group
$no_container_needed = array(1,2,3,4,6);
if (
(static::$isItemsManager && !in_array($popuptype, $iManager_containers)) ||
($is_ingroup && is_numeric($popuptype) && !in_array($popuptype, $no_container_needed))
)
{
$popuptype = 4;
}
// Optionally group images from all image fields of current item ... or of all items in view too
$grouptype = $field->parameters->get( 'grouptype', 1 ) ;
// Needed by some js galleries
$thumb_w_s = $field->parameters->get( 'w_s', 120);
$thumb_h_s = $field->parameters->get( 'h_s', 90);
$wl = $field->parameters->get( 'w_l', 800 );
$hl = $field->parameters->get( 'h_l', 600 );
// ***
// *** Hovering ToolTip configuration
// ***
$uselegend = $field->parameters->get( 'uselegend', 1 ) ;
$tooltip_class = 'hasTooltip';
// Enable/disable according to current view
$legendinview = FLEXIUtilities::paramToArray($field->parameters->get('legendinview', array('item', 'category')));
if (
($view=='item' && !in_array('item', $legendinview)) ||
($view=='category' && !in_array('category', $legendinview)) ||
(static::$isItemsManager && !in_array('backend', $legendinview))
)
{
$uselegend = 0;
}
// Check only once per field, if tooltip JS is both needed and has been loaded
static $tooltips_loaded = false;
static $tooltips_checked = array();
if ( !$tooltips_loaded && !isset($tooltips_checked[$field->id]) )
{
if ($uselegend)
{
$add_tooltips = JComponentHelper::getParams( 'com_flexicontent' )->get('add_tooltips', 1);
if ($add_tooltips)
{
JHtml::_('bootstrap.tooltip');
$tooltips_loaded = true;
}
}
$tooltips_checked[$field->id] = true;
}
// ***
// *** Title/Description in inline thumbnails
// ***
$showtitle = $field->parameters->get('showtitle', 0);
$showdesc = $field->parameters->get('showdesc', 0);
// ***
// *** Link to URL configuration
// ***
$linkto_url = (int) $field->parameters->get('linkto_url', 0);
if ($linkto_url && $realview !== 'itemcompare')
{
$url_target = $field->parameters->get('url_target','_self');
$isLinkToPopup = $format === 'html' && ($url_target=='multibox' || $url_target=='fancybox');
// Force opening in new window in backend, if URL target is _self
if (static::$isItemsManager && $url_target=='_self')
{
$url_target = "_blank";
}
// Linking to URL in popup, enable gallery JS and select appropriate gallery type
if ($isLinkToPopup)
{
$usepopup = 1;
if ($url_target === 'multibox') $popuptype = 1;
if ($url_target === 'fancybox') $popuptype = 4;
}
// Not linking in popup, disable adding gallery JS
else
{
$usepopup = 0;
}
}
// Force Fancybox if using Media embeeding, this is until we add support for more galleries ...
elseif ($usemediaurl)
{
$popuptype = 4;
}
// ***
// *** Social website sharing configuration
// ***
$useogp = (int) $field->parameters->get('useogp', 0);
$ogpthumbsize = (int) $field->parameters->get('ogpthumbsize', 2);
$ogplimit = (int) $field->parameters->get('ogplimit', 1);
// ***
// *** Create thumb paths and thumb base URL
// ***
// *** Extra thumbnails sub-folder for various
// Default value
if ($field->using_default_value)
{
$extra_folder = '';
}
// Intro-full image mode
elseif ($image_source === -1)
{
$extra_folder = 'intro_full';
}
// Media manager mode
elseif ($image_source === -2)
{
$extra_folder = 'mediaman';
}
// Various Folder-mode(s) ... TODO: $image_source > 1
elseif ($image_source >= 1)
{
$extra_folder = 'item_'.$u_item_id.'_field_'.$field->id; // Folder-mode 1
}
// DB-mode
else
{
$extra_folder = '';
}
// Create thumbs/image Folder and URL paths
$thumb_folder = JPATH_SITE .DS. JPath::clean( $dir .($extra_folder ? DS.$extra_folder : '') );
$thumb_urlpath = $dir_url .($extra_folder ? '/'. $extra_folder : '');
if ($field->using_default_value)
{
// default image of this field, these are relative paths up to site root
$orig_urlpath = str_replace('\\', '/', dirname($image_DF['default_image']));
}
// Intro-full image mode, image names are relative paths up to the site root
elseif ($image_source === -1)
{
$orig_urlpath = str_replace('\\', '/', dirname($image_IF['image_path']));
}
// Media manager mode, image names are paths relative to the site root
elseif ($image_source === -2)
{
$orig_urlpath = array(); // calculate later inside value loop
}
// Various Folder-mode(s) ... TODO: $image_source > 1
elseif ($image_source >= 1)
{
$orig_urlpath = $thumb_urlpath . '/original'; // Folder-mode 1
}
// DB-mode
else
{
$target_dir = (int) $field->parameters->get('target_dir', 1);
$orig_filepath = $target_dir
? static::$cparams->get('file_path', 'components/com_flexicontent/uploads')
: static::$cparams->get('media_path', 'components/com_flexicontent/medias');
$orig_urlpath = str_replace('\\', '/', $orig_filepath);
}
// ***
// *** Initialize value handling arrays and loop's common variables
// ***
$field->thumbs_src['backend'] = array();
$field->thumbs_src['small'] = array();
$field->thumbs_src['medium'] = array();
$field->thumbs_src['large'] = array();
$field->thumbs_src['original']= array();
$field->{"display_backend_src"} = array();
$field->{"display_small_src"} = array();
$field->{"display_medium_src"} = array();
$field->{"display_large_src"} = array();
$field->{"display_original_src"}= array();
$cust1_label = JText::_('FLEXI_FIELD_IMG_CUST1');
$cust2_label = JText::_('FLEXI_FIELD_IMG_CUST2');
// Decide thumbnail to use
$thumb_size = 0;
if (static::$isItemsManager)
{
$thumb_size = -1;
}
elseif ($view === 'category')
{
$thumb_size = $field->parameters->get('thumbincatview',1);
}
elseif ($view === 'item')
{
$thumb_size = $field->parameters->get('thumbinitemview',2);
}
// Cutoff title to a max length
$alt_image_prefix = flexicontent_html::striptagsandcut($item->title, 60) . ' ' . JText::_('FLEXI_IMAGE') . ' ';
// ***
// *** Get layout name
// ***
// CASE 0: Add single image display information (e.g. image count)
if ( $linkto_item )
{
$viewlayout = 'value_link_to_item';
}
// CASE 1: Handle linking to a URL instead of image zooming popup
elseif ( $linkto_url )
{
$viewlayout = 'value_link_to_url';
}
// CASE 2: // No gallery JS ... just append inline info and apply pretext, posttext
elseif ( !$usepopup )
{
$viewlayout = 'value_thumbnail_basic';
}
// CASE 3: // Built-in JS gallery
elseif ( is_numeric($popuptype) )
{
$built_in_gallery_names = array(
// Inline slideshow galleries
5 => 'galleriffic',
7 => 'elastislide',
// Popup galleries
1 => 'multibox',
2 => 'rokbox',
3 => 'jce_mediabox',
4 => 'fancybox',
6 => 'widgetkit',
8 => 'photoswipe',
9 => 'pannellum',
10 => 'juxtapose',
);
$viewlayout = isset($built_in_gallery_names[$popuptype])
? 'value_gallery_' . $built_in_gallery_names[$popuptype]
: 'value_thumbnail_basic';
}
// CASE 4: // Custom layout
else
{
$viewlayout = 'value_' . $popuptype;
}
// Create field's viewing HTML, using layout file
$field->{$prop} = array();
include(self::getViewPath($field->field_type, $viewlayout));
}
// ***
// *** METHODS HANDLING before & after saving / deleting field events
// ***
// Method to handle field's values before they are saved into the DB
public function onBeforeSaveField( &$field, &$post, &$file, &$item )
{
if ( !in_array($field->field_type, static::$field_types) ) return;
$use_ingroup = $field->parameters->get('use_ingroup', 0);
if ( !is_array($post) && !strlen($post) && !$use_ingroup ) return;
// Get configuration
$app = JFactory::getApplication();
$is_importcsv = $app->input->get('task', '', 'cmd') === 'importcsv';
$import_media_folder = $app->input->get('import_media_folder', '', 'string');
$id_col = $app->input->get('id_col', 0, 'int');
$unique_tmp_itemid = $app->input->get('unique_tmp_itemid', '', 'string');
$unique_tmp_itemid = substr($unique_tmp_itemid, 0, 1000);
$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);
// Set a warning message for overriden/changed files: form.php (frontend) or default.php (backend)
if (!$is_importcsv && empty($unique_tmp_itemid))
{
$app->enqueueMessage('Field: ' . $field->label . ' requires variable -unique_tmp_itemid- please update your ' . ($app->isClient('site') ? 'form.php' : 'default.php'), 'warning');
}
// Execute once
static $initialized = null;
static $srcpath_original = '';
if ( !$initialized )
{
$initialized = 1;
jimport('joomla.filesystem.file');
jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.path');
if ( $is_importcsv )
{
$srcpath_original = JPath::clean( JPATH_SITE .DS. $import_media_folder .DS );
}
}
// 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);
// ***
// *** Special steps for image field in Folder-mode(s)
// ***
if ($image_source >= 1)
{
$dir = $field->parameters->get('dir');
$unique_tmp_itemid = substr(JFactory::getApplication()->input->get('unique_tmp_itemid', '', 'string'), 0, 1000);
$dest_path = JPath::clean( JPATH_SITE .DS. $dir . DS. 'item_'.$item->id . '_field_'.$field->id .DS );
//if ( $image_source > 1 ) ; // TODO
/**
* Create original images folder if doing CSV import and folder does not exist, and there are images (values) for this field
*/
if ($is_importcsv)
{
if ($post)
{
$dest_path_original = $dest_path. 'original' .DS;
if (!JFolder::exists($dest_path_original) && !JFolder::create($dest_path_original))
{
// Cancel item creation
$app->enqueueMessage('Field: ' . $field->label . ' : Unable to create folder: ' . $dest_path_original, 'error');
return false;
}
}
}
/**
* New items have no item id during submission, thus we need to
* either rename the temporary name of the images upload folder (NEW ITEM SAVED)
* or copy the images upload folder (SAVE AS COPY)
*/
elseif ($unique_tmp_itemid && $item->id != $unique_tmp_itemid)
{
$temppath = JPath::clean(JPATH_SITE .DS. $dir .DS. 'item_' . $unique_tmp_itemid . '_field_' . $field->id .DS);
$save_as_copy = $unique_tmp_itemid == (int) $unique_tmp_itemid;
if (file_exists($temppath))
{
$save_as_copy
? JFolder::copy($temppath, $dest_path)
: JFolder::move($temppath, $dest_path);
}
}
}
// ***
// *** Special steps for image field in MM-mode
// ***
if ($image_source === -2)
{
$dest_path_media = 'images/';
$dest_path_media_full = JPath::clean( JPATH_SITE .DS. $dest_path_media );
}
// ***
// *** Rearrange file array so that file properties are groupped per value number
// ***
//echo "<pre>"; print_r($file); echo "</pre>";
$files = array();
if ($file) foreach( $file as $key => $all )
{
foreach( $all as $i => $val )
{
$files[$i][$key] = $val;
}
}
//echo "<pre>"; print_r($files); echo "</pre>";
// ***
// *** 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) )
{
$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'
);
JFactory::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 = JPath::clean( $srcpath_original . $v['originalname'] );
$dest_file_path = JPath::clean( $dest_path_original . $filename );
$result = false;
if ( JFile::exists($src_file_path) )
{
$result = JFile::copy( $src_file_path, $dest_file_path );
if ( $result && JPath::canChmod($dest_file_path) )
{
chmod($dest_file_path, 0644);
}
}
elseif ( JFile::exists($dest_file_path) )
{
$result = true;
}
$v['originalname'] = $result
? $filename // make sure filename is WITHOUT subfolder
: '';
}
elseif ($image_source == -2)
{
$src_file_path = JPath::clean( $srcpath_original . $v['originalname'] );
$dest_file_path = JPath::clean( $dest_path_media_full . $filename );
$result = false;
if ( JFile::exists($src_file_path) )
{
$result = JFile::copy( $src_file_path, $dest_file_path );
if ( $result && JPath::canChmod($dest_file_path) )
{
chmod($dest_file_path, 0644);
}
}
elseif (JFile::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'] = JPath::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 "<pre>"; 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 = JFactory::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 "<b>{$field->field_type}</b>: <br/> <pre>".print_r($values, true)."</pre>\n";
}
// Method called just before the item is deleted to remove custom item data related to the field
public function onBeforeDeleteField(&$field, &$item)
{
$app = JFactory::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 = JPath::clean( JPATH_SITE .DS. $dir . DS. 'item_'.$item->id . '_field_'.$field->id .DS);
//if ( $image_source > 1 ) ; // TODO
if (JFolder::exists($dest_path) && !JFolder::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('{}');
}
//JFactory::getApplication()->enqueueMessage('<pre>' . print_r($item->images, true) . '</pre>' , 'notice');
$p = $item->fields[$field->name]->postdata;
//JFactory::getApplication()->enqueueMessage('<pre>Field: ' . $field->name . '<br>' . print_r($p, true) . '</pre>' , 'notice');
if ($p && reset($p))
{
$value = unserialize(reset($p));
//JFactory::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'];
/*JFactory::getApplication()->enqueueMessage('<pre>Field: '
. $field->name . '<br>'
. $file_path . "\n"
. $dest_path . "\n"
. $field_index . "\n"
. $thumb_M . "\n"
. $thumb_L . "\n"
. '</pre>'
, '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 = JFactory::getApplication();
$format = $app->input->get('format', 'html', 'cmd');
$err_text = null;
// Get the component configuration
$cparams = JComponentHelper::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
JClientHelper::setCredentialsFromRequest('ftp');
// Make the filename safe
$file['name'] = JFile::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 = JPath::clean($path.$filename);
//perform security check according
if (!$upload_check)
{
if ($format === 'json')
{
jimport('joomla.error.log');
$log = JLog::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 . ' : ' . JText::_($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 = JFile::upload($file['tmp_name'], $filepath);
if (!$upload_success)
{
if ($format === 'json')
{
jimport('joomla.error.log');
$log = JLog::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 . ' : ' . JText::_('FLEXI_UNABLE_TO_UPLOAD_FILE'), 'error');
return false;
}
else
{
$db = JFactory::getDbo();
$user = JFactory::getUser();
$config = JFactory::getConfig();
$timezone = $config->get('offset');
$date = JFactory::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 = JLog::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 . ' : ' . JText::_('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 . ' : ' . JText::_('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 = JFactory::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 : JPath::clean(($target_dir ? COM_FLEXICONTENT_FILEPATH : COM_FLEXICONTENT_MEDIAPATH).DS);
$dest_path = $dest_path ? $dest_path : JPath::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 = JPath::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 (!JFolder::exists($dest_path) && !JFolder::create($dest_path))
{
$app->enqueueMessage('Field: ' . $field->label . ' : ' . JText::_('Error. Unable to create folders'), 'error');
return false;
}
// Make sure folder is writtable by phpthumb
if (!isset($dest_paths_arr[$dest_path]) && JPath::canChmod($dest_path))
{
/**
* JPath::setPermissions() is VERY SLOW, because it does chmod() on all folder / subfolder files
*/
//JPath::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 = JFile::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 && JPath::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();
$filepath = $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))
{
JFile::delete($output_filename);
}
if ($phpThumb->GenerateThumbnail())
{
if ($phpThumb->RenderToFile($output_filename))
{
return true;
}
//echo 'Failed:<pre>' . implode("\n\n", $phpThumb->debugmessages) . '</pre><br />';
return false;
}
//echo 'Failed2:<pre>' . $phpThumb->fatalerror . "\n\n" . implode("\n\n", $phpThumb->debugmessages) . '</pre><br />';
return false;
}
/**
* Removes an orignal image file and its thumbnails
*/
public function removeOriginalFile($field, $filename)
{
$app = JFactory::getApplication();
$db = JFactory::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 = JPath::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 = JPath::clean( JPATH_SITE .DS. $field->parameters->get('dir') );
$origfolder = JPath::clean( ($target_dir ? COM_FLEXICONTENT_FILEPATH : COM_FLEXICONTENT_MEDIAPATH) );
}
// Negative, intro-full mode, this should be unreachable, because
else
{
echo '<div class="alert alert-warning">image field id: ' . $field->id . ' is in intro-full mode, removeOriginalFile() should not have been called</div>';
}
// a. Delete the thumbnails
$errors = array();
$sizes = array('l','m','s','b');
foreach ($sizes as $size)
{
$dest_path = $thumbfolder . DS . $size . '_' . $filename;
if (JFile::exists($dest_path) && !JFile::delete($dest_path))
{
$app->enqueueMessage('Field: ' . $field->label . ' : ' . JText::_('FLEXI_FIELD_UNABLE_TO_DELETE_FILE') .": ". $dest_path, 'warning');
}
}
// b. Delete the original image from file manager
$src_path = JPath::clean($origfolder.DS.$filename);
if (!JFile::delete($src_path))
{
$app->enqueueMessage('Field: ' . $field->label . ' : ' . JText::_('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 = JPath::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 (JFactory::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 <br />"
." ORIGSIZE(w,h): $origsize_w,$origsize_h <br />"
;
}*/
$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 = JFactory::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 = JFactory::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 = JHtml::image ( 'components/com_flexicontent/assets/images/comments.png', JText::_( 'FLEXI_NOTES' ), '' );
$warn_image = JHtml::image ( 'components/com_flexicontent/assets/images/warning.png', JText::_( 'FLEXI_NOTES' ), '' );
JHtml::addIncludePath(JPATH_SITE . '/components/com_flexicontent/helpers/html');
$upConf = JHtml::_('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 '
<span class="fc-img-field-upload-limits-box">
<span class="label text-white bg-info label-info fc-upload-box-lbl">'.JText::_( $server_limit_exceeded ? 'FLEXI_UPLOAD_LIMITS' : 'FLEXI_UPLOAD_LIMIT' ).'</span>
<span class="fc-php-upload-limit-box">
<span class="'.$tooltip_class.'" style="margin-left:24px;" title="'.flexicontent_html::getToolTip('FLEXI_FIELD_CONF_UPLOAD_MAX_LIMIT', 'FLEXI_FIELD_CONF_UPLOAD_MAX_LIMIT_DESC', 1, 1).'">'.$conf_lim_image.'</span>
<span class="badge '.$conf_limit_class.'" style="'.$conf_limit_style.'">'.round($upConf['upload_maxsize'] / (1024*1024), 2).' M </span>
</span>
'.($server_limit_exceeded ? '
<span class="fc-sys-upload-limit-box">
<span class="'.$tooltip_class.'" style="margin-left:24px;" title="'.flexicontent_html::getToolTip(JText::_('FLEXI_SERVER_UPLOAD_MAX_LIMIT'), JText::sprintf('FLEXI_SERVER_UPLOAD_MAX_LIMIT_DESC', $phpUploadLimit['name']), 0, 1).'">'.$hint_image.'</span>
<span class="badge '.$sys_limit_class.'">'.round($phpUploadLimit['value'] / (1024*1024), 2).' M </span>
</span>' : '').'
</span>
';
}
/**
* 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;
}
JFactory::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 = JFactory::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 = JPath::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 = JPath::clean( (!$rel ? JPATH_SITE . DS : '') . dirname($value['image_path']) .DS );
}
// Media manager mode
elseif ($image_source === -2)
{
$extra_folder = 'mediaman';
$src_path = JPath::clean( JPATH_SITE .DS );
}
// Folder-mode 1
elseif ($image_source >= 1)
{
$extra_folder = 'item_'.$u_item_id . '_field_'.$field->id;
$src_path = JPath::clean( (!$rel ? JPATH_SITE . DS : '') . $dir .DS. $extra_folder .DS. 'original' .DS );
}
// DB-mode
else
{
$extra_folder = '';
$src_path = JPath::clean( ($target_dir ? COM_FLEXICONTENT_FILEPATH : COM_FLEXICONTENT_MEDIAPATH).DS );
}
// Add value-extracted subpath to original folder
$src_path = JPath::clean( $src_path . ($subpath ? $subpath . DS : '') );
// Full path of original file - and - Destination folder
$file_path = JPath::clean( $src_path . $filename );
$dest_path = JPath::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 ."<br/>" . 'dest_path: ' . $dest_path ."<br/><br/>";
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 || !JFolder::exists($src_path))
{
return;
}
$protect_original = $field->parameters->get('protect_original', 1);
$htaccess_file = JPath::clean( $src_path . '.htaccess' );
$file_contents = $protect_original
?
'# do not allow direct access and also deny scripts'."\n".
'<FilesMatch ".*">'."\n".
' Order Allow,Deny'."\n".
' Deny from all'."\n".
'</FilesMatch>'."\n".
'OPTIONS -Indexes -ExecCGI'."\n"
:
'# allow direct access but deny script'."\n".
'<FilesMatch ".*">'."\n".
' Order Allow,Deny'."\n".
' Allow from all'."\n".
'</FilesMatch>'."\n".
'OPTIONS -Indexes -ExecCGI'."\n";
// write .htaccess file
$fh = @ fopen($htaccess_file, 'w');
if (!$fh)
{
JFactory::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) JFactory::getApplication()->enqueueMessage( 'Field \'<b>' . $field->label . '</b>\' : <br/> <pre>' . $errors . '</pre>', 'notice');
}
catch (ParseError $e) {
JFactory::getApplication()->enqueueMessage( "Automatic value custom code, failed with: <pre>" . $e->getMessage() . '</pre>', '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");
}
}
}