Support

Account

Forum Replies Created

  • +100 (does it helps getting it faster? 😉
    Both programmatically and from UI

  • Hi folks,

    Surprisingly, with version 5.8.7, I’m experiencing the same issue with get_sub_field().
    Default value is outputted as an array while a set value outputs as string.

  • Ok, I’ve workaround my issue by creating a second shortcode :/

    function taz_embeddedFeatures_shortcode($atts, $content = null){
    	$a = shortcode_atts(array(
    		'id' => null
    		), $atts);
    
    	return '[taz_features id="' . $a['id'] . '"]';
    }
    add_shortcode('taz_embeddedFeatures', 'taz_embeddedFeatures_shortcode');

    I’ve also reverted back to my original taz_get_field_data function:

    function taz_get_field_data($shortcodeID){
    	if (class_exists('acf')){
    		$layouts = get_field('taz_features', false, true);
    		return $layouts[$shortcodeID - 1];
    	} else {
    		error_log("taz_get_field_data(): ACF Plugin is not available.");
    		return null;
    	}
    }

    So now, When I need for instance to insert a taz_features (like a gallery) into another one (like a carousel), I’m writing [taz_embeddedFeatures id=4] into my carousel slide.

    Thank you “Me” ^^

  • I’ve rewrote my function tax_get_field_data another way:

    function taz_get_field_data($shortcodeID){
    	if (class_exists('acf')){
    		if (have_rows('taz_features')){
    			$counter = 0;
    			while (have_rows('taz_features')){
    				the_row();
    				if ($counter === $shortcodeID){
    					return get_row(true);
    				}
    				$counter++;
    			}
    		}
    	} else {
    		error_log("taz_get_field_data(): ACF Plugin is not available.");
    		return null;
    	}
    }

    Since the_row is not formatted, I was hoping for the best and did my formatting only on the wanted row with get_row(true).
    Sadly, even if I don’t have an infinite loop anymore, the result is messed up.
    get_row(), as get_field() are parsing the included shortcodes [taz_features] shortcode! Why??? Why “format_value” cares of “do_shortcode”.
    I’m missing the ability to format the array, to get [content] key rather than [field_583b166074db8_field_57e024d987a79], but I don’t need the actual value to be parsed. This, I’ll take care later on my code.

    Any idea?

  • Line 3 of the above code, is there a way to first do
    $layouts = get_field('taz_features', false, false);
    and then only, ask for a formatting of the wanted layout only:
    –> format_value of $layouts[$shortcodeID - 1]

  • Update. I know where/when the infinite loop occurs.
    Now, I need to find how to solve it (and I’ve not yet found).

    Here’s an extract of my code:

    function taz_get_field_data($shortcodeID){
    	if (class_exists('acf')){
    		$layouts = get_field('taz_features', false, true);
    		return $layouts[$shortcodeID - 1];
    	} else {
    		error_log("taz_get_field_data(): ACF Plugin is not available.");
    		return null;
    	}
    }
    
    function taz_features($atts, $content = null){
    	$a = shortcode_atts(array(
    		'id' => null
    		), $atts);
    
    	$shortcodeID	= (int)$a['id'];
    	$rowData	= taz_get_field_data($shortcodeID);
    
    	switch ($rowData['acf_fc_layout']){
    		case 'gallery':
    			[…]
    			break;
    		case 'carousel':
    			[…]
    			break;
    		[…]
    	}
    }
    add_shortcode('taz_features', 'taz_features');

    Line 3 of the above code, we have: $layouts = get_field(‘taz_features’, false, true);
    When the last parameter is set to true, looks like the shortcode [taz_features id=4] is executed, thus entering again my shortcode function (taz_features), which will run taz_get_field_data(), which run get_field() again, and so on, thus generating the loop 🙁

    Setting false to the format value could solve my problem, but it would imply massive modifications of the rest of my code. I’d definitely like to avoid this.

  • A bit of informations:
    I’ve set two error_log on my code. The first one gives me the ID of the shortcode, the second, it’s ‘acf_fc_layout’ name.

    # Without [taz_features id=”4″] inside my carousel slide content: All is fine

    [06-Dec-2017 20:05:12 UTC] 1
    [06-Dec-2017 20:05:12 UTC] before_after
    [06-Dec-2017 20:05:12 UTC] 5
    [06-Dec-2017 20:05:12 UTC] carousel

    # With [taz_features id=”4″] inside my carousel slide content: Infinite loop?
    Note that the second error_log never passes…

    [06-Dec-2017 20:06:09 UTC] 1
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    [06-Dec-2017 20:06:09 UTC] 4
    […]

    Here’s the part of the code where I do those error_log

    $shortcodeID	= (int)$a['id'];
    error_log($shortcodeID);
    $rowData	= taz_get_field_data($shortcodeID);
    error_log($rowData['acf_fc_layout']);
  • Hi John,

    Thank you for the input.
    I’ll first contact the developper.

    Thanks again.

  • Thank you!
    Thank you Elliot!
    Thanks a —lot— for the new “group” feature you added on v5.6.0!
    This is —insanely— appreciated.

    All the best.

  • Hi John,

    Thanks a lot for your answer. I’ll instantly do this.

  • ybdigital, I’m not planning to integrate any modal thingy.
    The way it’s actually working is actually fine for my needs.

    Here’s the main part of my Javascript code, you guys are free to enhance it and share it back 😉

    jQuery(document).ready(function($){
    	// Make sure acf is loaded
    	if (typeof acf == 'undefined'){return;}
    
    	var
    		stylesheet	= '<style type="text/css">\
    							.taz_shortcodeOutput {\
    								background-color: rgb(226, 236, 251)!important;\
    								font-size: 1.4rem!important;\
    							}\
    						</style>',
    		textarea	= '<div class="acf-field acf-field-textarea">\
    							<div class="acf-label">\
    								<label for="taz_shortcodeOutput">Generated Shortcode</label>\
    							</div>\
    							<div class="acf-input">\
    								<textarea class="taz_shortcodeOutput" rows="8"></textarea>\
    							</div>\
    						</div>',
    		triggers	= '.acf-field[data-type=select] select,\
    						.acf-field[data-type=text] input,\
    						.acf-field[data-type=textarea] textarea,\
    						.acf-field[data-type=wysiwyg] textarea,\
    						.acf-field[data-type=number] input,\
    						.acf-field[data-type=radio] input,\
    						.acf-field[data-type=checkbox] .acf-checkbox-list input,\
    						.acf-field[data-type=true_false] .acf-input label input,\
    						.acf-field[data-type=color_picker] .acf-color_picker > input\
    					';
    
    	function taz_buildShortcode(currentLayoutName, triggersElements){
    		var
    			output			= '',
    			content			= '',
    			settingsValue	= {};
    
    		function taz_getSettingsValue(triggersElements){
    			triggersElements.each(function(index, elem){
    				var
    					settingType			= $(elem).parents('.acf-field').data('type'),
    					settingLabel		= $(elem).parents('.acf-field').data('name'),
    					checkboxesValues	= '',
    					isContent			= $(elem).parents('.acf-field').hasClass('taz_isShortcodeContent'); // The "content" is detected by the class "taz_isShortcodeContent"
    
    				if (isContent){
    					settingLabel = 'content';
    				}
    
    				switch(settingType){
    					case 'textarea':
    						settingsValue[settingLabel] = (!isContent) ? encodeURIComponent($(elem).val()) : $(elem).val();
    						break;
    					// Add as many cases you want to handle. Note that depending the type, the way to get values could change.
    					default:
    						break;
    				}
    			});
    			return settingsValue;
    		}
    
    		settingsValue = taz_getSettingsValue(triggersElements);
    		$.each(settingsValue, function(key, value){
    			if (value !== ''){
    				if (key !== 'content'){
    					output += ' ' + key + '="' + value + '"';
    				} else {
    					content = value;
    				}
    			}
    		});
    		output = '[taz_' + currentLayoutName + output + ']' + content + '[/taz_' + currentLayoutName + ']'
    		$('.taz_shortcodeOutput').html(output);
    	}
    
    	/* ================================================== */
    	/* ================================================== Everything starts here */
    	/* ================================================== */
    
    	acf.add_action('append', function($el){ // The user adds a new flexible content
    		var
    			currentLayout		= $el,
    			currentLayoutName	= currentLayout.data('layout'),
    			triggersElements	= null;
    
    		switch(currentLayoutName){
    			case 'shortcode_tester': // Name of the flexible content added
    				if (!$('.taz_shortcodeOutput').length){ // Only prepend once
    					currentLayout.parents('.inside.acf-fields').prepend(textarea);
    					currentLayout.parents('.inside.acf-fields').prepend(stylesheet);
    				}
    				triggersElements = currentLayout.find(triggers);
    
    				triggersElements.on('change keyup', function(){
    					taz_buildShortcode(currentLayoutName, triggersElements);
    				});
    				break;
    			default:
    				break;
    		}
    
    	});
    });
  • Ok, I think I’m about to be done for my needs 🙂

  • Hi folks,
    I’m getting somewhere… 😉

  • Output textarea is in place…
    This was the easy part I think ^^
    I’ll generate the shortcode into this textarea depending on the fields the user will set.

  • Brillant!
    Now, it’s time to start.
    I’ll let you know and share if it’s going in a nice direction.

  • Hey John,
    Thanks for the answer.
    I’ll try to dig around with it as side/fun project.

    First of all, do you know if there is a way trigger my function right after a layout have been added ?

  • Hi back,

    Ok, the 6 times slower thingy never happened again, so I’ll not take this in consideration.
    But what’s sure is the following:
    If I replace all $itemCustomFields['itemN'][0] thingy by get_field('itemN', $id), the page loading is about max 30% slower.
    So as you said before, get_post_meta($id) is indeed faster, but dealing with the returned data is way less easier then when using get_field.
    So I’ll decide depending the need.

    Sadly for the get_num_queries, I cannot see any difference since I’m calling my portfolio with Ajax. (or can I?)

  • Hi again,

    Just to make things clearer for my brain ^^
    We started the topic talking about two differents datas: the gallery one, and the per attachment ones (when I loop through each image of the gallery)

    This is my original code (before speed considerations):

    $portfolioItems		= get_field('gallery'); // Getting the gallery field
    $hiddenMetadata		= get_field('metadata_to_hide');
    $imagesPerPage		= get_field('images_per_page');
    $hiddenCategories	= get_field('categories_to_hide');
    foreach ($portfolioItems as $item) {
    	// Getting current image informations
    	$id					= $item['ID'];
    	$filename			= $item['filename'];
    	$width				= $item['width'];
    	$height				= $item['height'];
    	$url				= $item['url'];
    	$alt				= htmlentities(urldecode($item['alt']), ENT_QUOTES);
    
    	// Getting current image custom attachement fields
    	$itemCustomFields	= get_post_meta($id);
    	$description		= $itemCustomFields['portfolio_description'][0];
    	$versionName		= $itemCustomFields['version_name'][0];
    	$reference			= $itemCustomFields['reference'][0];
    	$maxWidth			= (int)$itemCustomFields['max_available_width'][0];
    	$maxHeight			= (int)$itemCustomFields['max_available_height'][0];
    	$copyright			= $itemCustomFields['copyright'][0];
    	$rating				= $itemCustomFields['rating'][0];
    	// […]
    
    	// Building my output code here
    }

    Would this one be the optimized? (basically, it’s exactly the same, but with your 4 lines added at the beginning.

    $portfolioItemsForCache = get_field('gallery', false, false);
    foreach ($portfolioItemsForCache as $itemID) {
    	get_post_meta($itemID); // 1 query for each image
    } // at this point all meta data for all images should be stored in the cache
    $portfolioItems		= get_field('gallery'); // Getting the gallery field
    $hiddenMetadata		= get_field('metadata_to_hide');
    $imagesPerPage		= get_field('images_per_page');
    $hiddenCategories	= get_field('categories_to_hide');
    foreach ($portfolioItems as $item) {
    	// Getting current image informations
    	$id					= $item['ID'];
    	$filename			= $item['filename'];
    	$width				= $item['width'];
    	$height				= $item['height'];
    	$url				= $item['url'];
    	$alt				= htmlentities(urldecode($item['alt']), ENT_QUOTES);
    
    	// Getting current image custom attachement fields
    	$itemCustomFields	= get_post_meta($id);
    	$description		= $itemCustomFields['portfolio_description'][0];
    	$versionName		= $itemCustomFields['version_name'][0];
    	$reference			= $itemCustomFields['reference'][0];
    	$maxWidth			= (int)$itemCustomFields['max_available_width'][0];
    	$maxHeight			= (int)$itemCustomFields['max_available_height'][0];
    	$copyright			= $itemCustomFields['copyright'][0];
    	$rating				= $itemCustomFields['rating'][0];
    	// […]
    
    	// Building my output code here
    }
    

    Edit: oh, BTW, the last loads 6x slower than the first, so I’ve obviously messed things up ^^

  • Thanks again John, appreciated.

  • Thanks a lot John!

    About the gallery fields, I’m telling ACF to return an array because I’m using others values than just the url (equivalent to wp_get_attachment_image_src()) like: filename, width, height.

  • Bumping this,
    The issue still exist, “Position” and “Style” do not apply.

  • Hi back,

    I made it, with your second solution $value []= array(…
    Thanks again.

  • Hi again James

    Some of my post have more than one before|after shortcode.
    I’ve built a huge array of hundreds of comparisons that I’ll loop through, like this:

    $BAcomparisonArray = array(
    array(
    	'postID'			=> 7651,
    	'beforeImage'		=> 'photo-7D-IMG_2201-RAW.jpg',
    	'afterImage'		=> 'photo-7D-IMG_2201.jpg'
    ),
    array(
    	'postID'			=> 7729,
    	'beforeImage'		=> 'photo-7D-IMG_2198-RAW.jpg',
    	'afterImage'		=> 'photo-7D-IMG_2198.jpg'
    ),
    array(
    	'postID'			=> 7729,
    	'beforeImage'		=> 'photo-7D-IMG_2201-RAW.jpg',
    	'afterImage'		=> 'photo-7D-IMG_2201.jpg'
    ),
    array(
    	'postID'			=> 7995,
    	'beforeImage'		=> 'photo-7D-IMG_2519-RAW.jpg',
    	'afterImage'		=> 'photo-7D-IMG_2519.jpg'
    ),
    array(
    	'postID'			=> 7995,
    	'beforeImage'		=> 'photo-7D-IMG_2822-RAW.jpg',
    	'afterImage'		=> 'photo-7D-IMG_2822.jpg'
    ),
    array(
    	'postID'			=> 8008,
    	'beforeImage'		=> 'photo-7D-IMG_2519-RAW.jpg',
    	'afterImage'		=> 'photo-7D-IMG_2519.jpg'
    ));

    But as you can see, for the posts where I have multiple before|after, the subarray appear multiple times with the same ID.

    With my actual code (see below), only one before|after is added to my flexible content, while I would obviously need as many as necessary:

    $value = array(
    	array('before_image' => $before_image, 'after_image' => $after_image, 'acf_fc_layout' => 'before_after')
    );
    update_field($field_key, $value, $postID);

    Is there a way to force the update field to create new entries?
    Example, for ID 7729, the first will act as today by creating a new layout and populating it, but when my loop run through another array with the same ID, I would like a new layout to be created, not just updating my previous one.

    I know that if I put as many arrays as necessary in my $value, the related layouts will be created for a same post (see below), but I don’t see quite well how to do this from $BAcomparisonArray.

    $value = array(
    	array('before_image' => $before_image, 'after_image' => $after_image, 'acf_fc_layout' => 'before_after'),
    	array('before_image' => $before_image, 'after_image' => $after_image, 'acf_fc_layout' => 'before_after'),
    	array('before_image' => $before_image, 'after_image' => $after_image, 'acf_fc_layout' => 'before_after'),
    	array('before_image' => $before_image, 'after_image' => $after_image, 'acf_fc_layout' => 'before_after')
    );
  • Hi James,

    Today, I had the time between two project to continue to work on this.
    Thanks to your help and guidance, I made it.
    As you can see with the selected solution, I use the first one as I’ve to “add” everything and have no “existing values”.

    My format sightly differs:

    $value = array(
    	array('before_image' => $before_image, 'after_image' => $after_image, 'acf_fc_layout' => 'before_after')
    );

    I’ll continue and hope everything will be ok!
    Thanks again.

Viewing 25 posts - 1 through 25 (of 49 total)