• I am facing a challenge after the plugin developer changed the markup in an update, the span with the class “customeradtitle” has been removed both from the parent div (with the class “clientad”), and from the link (with the class “advads-edit-button”).

    My goal is either to restore my layout via CSS, or to move back the span into the div and into the link at the time of page load by str_replace or by output buffering, or by a generic (WordPress level or Theme level) or plugin specific PHP filter.

    The “book title” is actually my image ads title.

    I replicated / isolated the issue in CodePen:

    Before the update (correct layout):
    https://codepen.io/any_formless/pen/WNpLyyj

    After the update (wrong layout):
    https://codepen.io/any_formless/pen/YzZdLMR

    I am not sure what is the difference between PHP output buffering and str_replace. I have only experience with str_replace. But I cannot use such a filter in my case:

    $string_to_replace = '</a></div><span class="customeradtitle">Lorem Ipsum is simply dummy text.</span>';
            $replace_with = '<span class="customeradtitle">Lorem Ipsum is simply dummy text.</span></a></div>';
    
            $html = str_replace( $string_to_replace, $replace_with, $html );
        }
    
        return $html;

    Because the span text is subject to change. If there would be a way for the str_replace to ignore the span text, then I could put it in such a plugin function, I am not sure it’s correct:

     function move_span_back ( $ad ){}
     add_filter( 'advanced-ads-output-final', 'move_span_back', 10, 1 );

    or I could put it in a theme function instead, or in a generic WP function for replacing sequences of HTML, those perhaps would look at the whole page markup, not only at that sequence.

    But the plugin function would probably not be able to see the outhanging span, only the “cientad” div, which is the AD div, is that right?

    Because the change is not supposed to be reverted for real on a deeper level, because it said to be a fix.

    The actual sequence of HTML in question, after the update (the out-hanging span need to be back into the div and into the link, or a CSS fix):

    <div class="clientad" id="utopi-1638227998">
    
         <div class="advads-edit-bar advads-edit-appear">
    
              <a href="https://mysite.com/wp-admin/post.php?post=9764&action=edit" class="advads-edit-button" title="Order #9763" rel="nofollow">
    
                    <span class="dashicons dashicons-edit"></span>
    
              </a>
    
         </div>
    
         <a href="https://x.com" rel="nofollow">
    
              <img src="https://mysite.com/wp-content/uploads/2021/05/d9b80977fdfa1dc7c54ab2f8a59667d4-scaled.jpg" alt="" width="1748" height="2560" style=" max-width: 100%; height: auto;">
    
         </a>
    
    </div>
    
    <span class="customeradtitle">Lorem Ipsum is simply dummy text.</span>

    With CSS it seems impossible to get the original layout back, I tried floating and clearing, changing positioning, and it didn’t work out.

    The clientad divs are yellow in the CodePens, those are the actual ads purchased (it’s a site in construction so nothing is purchased yet), and the purple blocks are pink, those are the dummy ads that can be purchased. It’s important that in the CSS fix if it exists the yellow and pink blocks maintain equal height, which is a fixed height, because their height need to match with elements in adjacent columns, and that the span gets back inot the yellow div, and that its height will be automatic, filling in all vertical space left in the yellow div, under the image.

    But the CSS fix doesn’t seem to exist.

    I don’t mind so much that there is no plugin-specific fix for this because I don’t want to alter the plugin code much, it seems easier to revert the HTML at page load, and it wouldn’t have the same implications than changing plugin code.

    Does anyone know a generic PHP or WordPress filtering solution either with str_replace or via php output buffering, or maybe other solutions that I don’t know about, that would work?

    I was told that developers change the markup quite often, how do people deal with that, usually, if it affects their original layout?

    Thanks!

    • This topic was modified 3 years, 9 months ago by berry metal.
Viewing 15 replies - 1 through 15 (of 15 total)
  • Thread Starter berry metal

    (@erikalleman)

    I forgot to mention that the span is output from a “custom code” (meaning additional custom code for the ad) meta box in my ad settings, I use that field to show ad titles, because that’s the only field or meta box available in the plugin, for use.

    I am not sure why isn’t that supposed to be in the ad div or in the ad link as it was previously, because it does belong to the ad, since it’s the output of a meta box from the ad settings with the purpose of adding additional code to image ads.

    Thread Starter berry metal

    (@erikalleman)

    This is how the custom code section is added, and the difference after the update, left is before update, right is after update:

    flameshot_screenshot

    But I am not sure that this part of the code is that causing the span position change, but maybe it could help in building a filter to revert the HTML.

    Thread Starter berry metal

    (@erikalleman)

    Finally I realized that I need to revert the

    .

    into

    .=

    in the code – hopefully this would work.

    But I have a question:

    Can I just take any PHP blocks out of plugins’ classes’ folders PHP files, and drop the modified version in my functions.php, and should it work and the change should be reverted?

    Is this a proper way to do it?

    Thanks in advance for any help provided!

    Thread Starter berry metal

    (@erikalleman)

    Should I put this code directly from the file into my functions.php?

    public function add_custom_code( $ad_content, Advanced_Ads_Ad $ad ) {
    		$custom_code = $this->get_custom_code($ad);
    
    		if ( ! empty( $custom_code ) ) {
    			return $ad_content .= $custom_code;
    		}
    		return $ad_content;
    	}

    Or I should rather put the file itself with the changes in my child theme?

    I am not sure which of the 2 should I do.

    Thanks!

    Moderator bcworkz

    (@bcworkz)

    You cannot generally copy code from elsewhere, then modify and place in your child theme, unless you also change the function name. Redefining functions is not allowed in PHP. There is one exception, if the original function is wrapped in something like if ( ! function_exists( 'the_function_name' ) ) :, you can do the same with your altered function and still keep the same name, assuming your code loads before the original function does. Such functions are called “pluggable”.

    If you change the function name, you’d still need to alter the calling code. If it’s template code, your child theme can override parent templates. But if it’s plugin or similar non-template code, you’ll run up against the “don’t modify other’s code” rule. The proper way to modify functionality is through action and filter hooks, but the original author needs to make such a provision ahead of time.

    Even if you buffered the output, you’s still need to do some sort of search and replace on the buffered content. Buffering just intercepts output for later use. To search/replace content that’s variable, you could probably use preg_replace() which matches by regular expression (or “regex”), which can match by a predefined relationship instead of specific content. For example, you could change the domain names of all img tag src URLs, regardless of what they are, because they are always preceded by src="https:// and terminated by either / or ".

    Finally, despite the HTML being changed, you should be able to arrive at some sort of CSS to achieve the desired layout. Unless the HTML has very dramatically changed anyway. For example, to “fix” the codepen layout, this will do it:

    span.title {
        position: relative;
        width: 870px;
        margin: -390px auto 100px;
    }

    The distance units would need adjustment to match what existing elements use for proper responsive behavior, but this corrects the specific codepen view that I’m seeing.

    Thread Starter berry metal

    (@erikalleman)

    Thank you!

    Until I am examining your solution, I will post the real deal, because the PHP I posted previosuly, was confusing and I don’t know why is it different at a second try, but here is the real deal, the actual change I observed in the plugin code, so maybe based on this you could help write a filter?

    So, before the update (correct layout):

    /**
    	 * Add custom code after the ad.
    	 *
    	 * Note: this won’t work for the Background ad placement. There is a custom solution for that in Advanced_Ads_Pro_Module_Background_Ads:ad_output
    	 *
    	 * @param string $ad_content Ad content.
    	 * @param Advanced_Ads_Ad $ad ad object.
    	 * @return string $ad_content Ad content.
    	 */
    	public function add_custom_code( $ad_content, Advanced_Ads_Ad $ad ) {
    		$options = $ad->options( 'output' );
    
    		$custom_code = isset( $options['custom-code'] ) ? $options['custom-code'] : '';
    		$custom_code = apply_filters( 'advanced_ads_pro_output_custom_code', $custom_code, $ad );
    
    		if ( ! empty( $custom_code ) ) {
    			return $ad_content .= $custom_code;
    		}
    		return $ad_content;
    	}

    And after the update (the wrong layout):

    /**
    	 * Add custom code after the ad.
    	 *
    	 * Note: this won’t work for the Background ad placement. There is a custom solution for that in Advanced_Ads_Pro_Module_Background_Ads:ad_output
    	 *
    	 * @param string          $ad_content Ad content.
    	 * @param Advanced_Ads_Ad $ad ad object.
    	 * @return string $ad_content Ad content.
    	 */
    	public function add_custom_code( $ad_content, Advanced_Ads_Ad $ad ) {
    		$custom_code = $this->get_custom_code($ad);
    
    		if ( ! empty( $custom_code ) ) {
    			return $ad_content .= $custom_code;
    		}
    		return $ad_content;
    	}
    
    	/**
    	 * If this ad has custom code, encode the output.
    	 *
    	 * @param string          $output The output string.
    	 * @param Advanced_Ads_Ad $ad     The ad object.
    	 *
    	 * @return string
    	 */
    	public function encode_ad_custom_code( $output, Advanced_Ads_Ad $ad ) {
    		$privacy = Advanced_Ads_Privacy::get_instance();
    		if (
    			// don't encode if AMP.
    			( function_exists( 'advads_is_amp' ) && advads_is_amp() )
    			// privacy module is either not enabled, or shows all ads without consent.
    			|| ( empty( $privacy->options()['enabled'] ) )
    			// Ad is already encoded.
    			|| ( ! method_exists( $privacy, 'is_ad_output_encoded' ) || $privacy->is_ad_output_encoded( $output ) )
    			// Consent is overridden, and this is not an AdSense ad, don't encode it.
    			|| ( $ad->type !== 'adsense' && isset( $ad->options()['privacy']['ignore-consent'] ) )
    		) {
    			return $output;
    		}
    
    		// If we have custom code, encode the ad.
    		if ( ! empty( $this->get_custom_code( $ad ) ) ) {
    			$output = $privacy->encode_ad( $output, $ad );
    		}
    
    		return $output;
    	}
    
    	/**
    	 * Get the custom code for this ad.
    	 *
    	 * @param Advanced_Ads_Ad $ad The ad object.
    	 *
    	 * @return string
    	 */
    	public function get_custom_code( Advanced_Ads_Ad $ad ) {
    		$options     = $ad->options( 'output' );
    		$custom_code = isset( $options['custom-code'] ) ? $options['custom-code'] : '';
    
    		return (string) apply_filters( 'advanced_ads_pro_output_custom_code', $custom_code, $ad );
    	}

    Sorry the previous PHP I posted was wrong, but I still don’t get it how was it magically wrong, because I diffed the exact same files at the second try to post this code.
    So this is the actual code change.

    Could you help figure a filter that would work in my functions.php, based on this code change?

    So now I will test the CSS solution you just wrote.
    Thanks!

    Thread Starter berry metal

    (@erikalleman)

    Thanks for the CSS suggestion, but the height of the span must be “automatic”, and must fill exactly the available vertical space from the bottom of the yellow container until the bottom of the image. (That’s why it’s originally set to flex:1;, but that only works if the span is part of the yellow container and also part of the link). And because the height of the span must be automatic, I cannot use fixed margins on it because it will create irregular gaps above and below it because the height of the image is auto-height.

    Its height must be automatic also because of the variable height of the text in it, but especially because the height of the image is variable.

    But indeed I could set a fixed height to the image and to the text span too, and in that case your code would work.

    But fixed height images cannot properly set to background: cover, isn’t it?
    I need backgorund:cover to achieve the auto width.

    I cannot use even vw for the margins you proposed unless both the image and the span has a fixed vw height, it won’t work.

    Yes but fixed image vw height and fixed span vw height might make your solution work because my yellow and pink divs have an equal fixed vw height as well, so I am going to experiment with it.

    If I cannot find an other solution, this will work indeed! Thanks.

    But I still hope for the PHP filter solution.

    Thread Starter berry metal

    (@erikalleman)

    Could you help me describe the PHP codes above, so that I could understand what they mean more exactly?

    Thanks!

    Thread Starter berry metal

    (@erikalleman)

    In the whole plugin this is the only relevant code that I found about the “custom code” section which is my title.

    So they don’t seem pluggable, is that right?

    Thread Starter berry metal

    (@erikalleman)

    I managed to fix it with your CSS help ?? amazing.

    I gave a fixed height for my ad image, basically I divided the height between the image and the span since the yellow wrapper is also fixed height (it’s more like fixed ratio height – in vw), and then I used your suggestion for the span:

    min-height: 8.5vw !important;
    max-height: 8.5vw !important;
    margin: -8.5vw auto 0vw !important;

    I needed to set the last margin to zero to make it work.

    And this is almost perfect, only one little problem as I suspected: if I set a fixed height image to “cover” sorry it’s not cover actually, it’s width:100% , (which is a must, isn’t it? otherwise how do I make sure that there will be no margins left on the left and right?) then small distortions are to be expected, is that right?

    But since my ad images are required to be uploaded with a fixed aspect ratio (book format, 1 : 1.5 width:height), the maximum distortion will be minor, maybe not even noticeable.

    Eventually if you know a fix for the distortion, I would be grateful for that.
    But I only notice the distortion if I give a much taller height to the image.

    Otherwise the distortion is not even noticeable.
    Thanks for this! (I couldn’t figure this because I was too stuck with my auto heights…)
    I hope you have a great day and happy coding!

    Thread Starter berry metal

    (@erikalleman)

    Oh, and thanks for the PHP explanations about the functions, I’ll try to digest that and make use of it..

    Thread Starter berry metal

    (@erikalleman)

    In your opinion, is a CSS fix the best for this case, or a PHP fix would be superior?

    Thread Starter berry metal

    (@erikalleman)

    I forgot to mention that my blue container the .wrapper has a fixed ratio width defined in vw, relative to other columns, hence the eventual image distortion with using a fixed height for the image. But I think now it’s solved. Thanks.

    Moderator bcworkz

    (@bcworkz)

    Background cover wouldn’t dictate the element size, rather it responds to the element’s size to always cover its background at any size. I agree that if you were relying upon flex box for layout and the HTML structure changes so flex box no longer works, it can be difficult to deal with an unknown, variable size in CSS. Fixing some dimension so it doesn’t affect the page layout may or may not be a reasonable solution, but may be necessary in some situations. OTOH, I’m not a super strong expert in CSS, there could easily be an approach I’m not seeing that would work.

    You’re right, no pluggable functions available. However, there is the ‘advanced_ads_pro_output_custom_code’ filter you could hook to alter or replace $custom code. The ad object $ad is also passed to your callback if that’s of any use. You could use the old version functions under new names to generate the desired HTML. Or use preg_replace() to seek out the relevant section and replace it with the desired version. All pertinent code can reside with your child theme.

    Another feature of the regexp used in preg_replace() is you can capture portions of what is matched, even if it varies in content, as long as the pattern is matched. Captured content can be reused in replacement content. Extending my previous img tag src attribute example, you could capture the old URL and use it in a newly inserted attribute like aria-data="old-url.com" or simiar.

    While regexp syntax can be very stilted and obtuse, it’s also a very powerful way to dynamically modify strings. It can be difficult to predict how any particular regexp will behave. I find helper sites like regexr.com very useful. They are sort of like codepen for regexp.

    • This reply was modified 3 years, 9 months ago by bcworkz.
    Thread Starter berry metal

    (@erikalleman)

    That was a lot of information for me, so now I will spend some time trying to write the function and to use preg_replace().

    Thank you for the help given.

Viewing 15 replies - 1 through 15 (of 15 total)
  • The topic ‘How do I restore my layout after markup update, without reverting the markup?’ is closed to new replies.