• Resolved conorseed

    (@conorseed)


    Hey team, I trust you’re having a great day!

    I’ve seen your ESI examples here but can’t quite wrap my head around how to do it

    It grabs a value from the database using get_option() and spits it out as a json variable to be used client side. If the value is more than an hour old, it updates the value through a series of API requests and update_option(). The shortcode also takes attributes in order for the output to be filtered on client side.

    Basically, it’s the “Upcoming Courses” section on the home page, and a number of other pages, but it will display differently depending on the shortcode attributes.

    Any advice? Would it be helpful to view the code? Thanks for your time.

    The page I need help with: [log in to see the link]

Viewing 15 replies - 1 through 15 (of 19 total)
  • Plugin Support Hai Zheng?

    (@hailite)

    Can you give the PHP snippet where you generated that json data?

    Thread Starter conorseed

    (@conorseed)

    Sure thing ?? This is the quick and dirty version of it at the moment:

    /* API CALL */
    function cd_acuity_getCoursesv2( $course = '', $id = FALSE ){
    
        // Vars
        $userID = 'XXXXXXX';
        $key = 'XXXXXXXX';
        $date = new DateTime(); $fdate = new DateTime();
        $fdate = ($course !== 'DDC') ? $fdate->modify('+4 month') : $fdate->modify('+6 month');
    
        // URL
        if( $id ){
            $url = 'https://acuityscheduling.com/api/v1/availability/classes?appointmentTypeID='.$id;
        } else{
            $url = 'https://acuityscheduling.com/api/v1/availability/classes?minDate='.$date->format('Y-m-d').'&maxDate='.$fdate->format('Y-m-d'); //includeUnavailable=true&
        }
    
        // Initiate curl:
        // GET request, so no need to worry about setting post vars:
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
    
        // Grab response as string:
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
        // HTTP auth:
        curl_setopt($ch, CURLOPT_USERPWD, "$userID:$key");
    
        // Execute request:
        $result = curl_exec($ch); 
    
        // Don't forget to close the connection!
        curl_close($ch);
    
        // Catch Error or Return JSON
        return json_decode($result, true);
    }
    
    /* SHORTCODE */
    function cd_acuityShortcodev2($atts){
    
        // Set Atts
        $atts = shortcode_atts(
            array(
                'course' => '',
            ),
            $atts
        );
        
        $current_time = current_time('timestamp');
    
        // Get Saved Option
        $resultArr = json_decode( get_option('2ds_courses'), true );
    
        // If Saved json older than 1 hour, get updated courses
        if( $current_time - $resultArr['updated'] > 3599 ){
            // Vars
            $resultArr = array( 
                'data'      => [],
                'updated'   => ''
            );
            $ddcArr = [];
    
            // Get RF Courses
            $rfcourses = cd_acuity_getCoursesv2();
    
            // Error Check
            if (isset($rfcourses['error'])){
                return 'Uh oh. Something Went Wrong.';
            }
    
            // Output RF Courses
            foreach ($rfcourses as $rf){
    
                // Filter out DDC
                if ( strpos( $rf['name'], 'DDC' ) === FALSE ){
    
                    // Get Vars
                    $rfcourse = [];
                    $rfcourse['name'] = $rf['name'];
                    $rfcourse['date'] = cd_acuityGetDate($rf['time']);
                    $rfcourse['id'] = $rf['appointmentTypeID'];
                    $rfcourse['slots'] = $rf['slotsAvailable']; 
    
                    // Push to final array
                    array_push($resultArr['data'], $rfcourse);
                }
            }
    
            // Get DDC Courses
            $ddccourses = cd_acuity_getCoursesv2('DDC');
    
            // Error Check
            if (isset($ddccourses['error'])){
                return 'Uh oh. Something Went Wrong.';
            }
    
            // Output DDC Courses
            foreach ($ddccourses as $ddc){
                if ( strpos( $ddc['name'], 'DDC' ) !== FALSE ){
    
                    // Get Vars
                    $ddccourse = [];
                    $ddccourse['name'] = $ddc['name'];
                    $ddccourse['id'] = $ddc['appointmentTypeID'];
                    $ddccourse['slots'] = $ddc['slotsAvailable']; 
    
                    // Test
                    foreach ($ddcArr as $test){
                        if ($test === $ddccourse['id']){ continue 2;}
                    }
    
                    // Get Dates
                    $ddcdates = cd_acuity_getCoursesv2('', $ddccourse['id']);
                    $ddccourse['date'] = cd_acuityGetDate($ddcdates[0]['time']);
                    $ddccourse['date2'] = cd_acuityGetDate($ddcdates[1]['time']);
                    $ddccourse['date3'] = cd_acuityGetDate($ddcdates[2]['time']);
                    $ddccourse['date4'] = cd_acuityGetDate($ddcdates[3]['time']);
    
                    // Push to final array
                    array_push($resultArr['data'], $ddccourse);
    
                    // Push ID to ddcArr for testing
                    array_push($ddcArr, $ddccourse['id']);
                }
            }
    
            // Sort Final Array
            usort($resultArr['data'], function($a, $b){
                $t1 = strtotime($a['date']);
                $t2 = strtotime($b['date']);
                return $t1 - $t2;
            });
    
            // Add DateTime to Array
            $resultArr['updated'] = $current_time;
        } 
    
        // Change Final Array to JSON
        $json = json_encode($resultArr);
    
        // Update JSON in Database
        if( $current_time - $resultArr['updated'] > 3599 ){
            update_option( '2ds_courses', $json );
            error_log('UPDATED');
        }
        
    
        // Output
        $result = '<div class="acuity-courses-wrapper owl-carousel owl-theme"></div>';
        $result.= '<script type="text/javascript">var acuityCoursesArr = ' . $json . ';';
        $result.= 'var acuityCoursesFilter = "'.$atts['course'].'";';
        $result.= <<<EOT
        jQuery(function(a){acuityCoursesArr.data.length>0?(a.each(acuityCoursesArr.data,function(e,s){var t=s.name,p=~t.indexOf("DDC")?s.date+", "+s.date2+", "+s.date3+", "+s.date4:s.date,r=s.id,n=s.slots;acuityCoursesFilter?~t.indexOf(acuityCoursesFilter)&&a(".acuity-courses-wrapper").append('<div class="course" type="'+t+'"><span class="acuity-name">'+t+'</span><span class="acuity-date">'+p+'</span><a target="_blank" href="https://2drivesafe.as.me/?appointmentType='+r+'">Book Now<span>'+n+" Spots Left</span></a></div>"):a(".acuity-courses-wrapper").append('<div class="course" type="'+t+'"><span class="acuity-name">'+t+'</span><span class="acuity-date">'+p+'</span><a target="_blank" href="https://2drivesafe.as.me/?appointmentType='+r+'">Book Now<span>'+n+" Seats Left</span></a></div>")}),a(".acuity-courses-wrapper").owlCarousel({loop:!0,margin:10,nav:!0,navText:["< Prev","Next >"],responsive:{0:{items:1},600:{items:2},1e3:{items:3}}})):(a(".acuity-courses-wrapper").append("No courses found."),a(".acuity-courses-wrapper").owlCarousel())});
    EOT;
    
        $result.= '</script>';
    
        return $result;
    }
    add_shortcode('acuitycourses', 'cd_acuityShortcodev2');
    
    function cd_acuityGetDate($time){
        $date = new DateTime($time);
        return $date->format('D j M, g:ia');
    }
    Plugin Support Hai Zheng?

    (@hailite)

    Just create a new “middleware” function.

    e.g.

    
    add_shortcode('acuitycourses', 'esi_block') ;
    function esi_block( $params ) {
        return LiteSpeed_Cache_API::esi_url( 'my_plugin_esi', 'My Plugin Name', $params ) ;
    }
    
    LiteSpeed_Cache_API::hook_tpl_esi('my_plugin_esi', 'hook_esi' ) ;
    function hook_esi( $params ) {
        echo cd_acuityShortcodev2( $params ) ;
        exit ;
    }
    
    • This reply was modified 6 years, 7 months ago by Hai Zheng?.
    Thread Starter conorseed

    (@conorseed)

    Brilliant idea.

    I assume that the $params would be the shortcode $atts? I don’t need to include any other parameters in there?

    Plugin Support Hai Zheng?

    (@hailite)

    You can pass any parameters into ESI API. It will give them back to you anyways. You can even encode in your way first before give to ESI, just don’t forget to decode it when use it.

    Thread Starter conorseed

    (@conorseed)

    Ok thanks! I’ll give it a go and come back if I have any issues ??

    Thread Starter conorseed

    (@conorseed)

    Hey, I get the below error. How do I include the api in my plugin? ??

    Uncaught Error: Class 'LiteSpeed_Cache_API' not found in path/to/my/plugin

    Plugin Support Hai Zheng?

    (@hailite)

    You should call them after after_setup_theme.

    Thread Starter conorseed

    (@conorseed)

    Sorry @hailite, I don’t quite understand. Can you expand on that please?

    Plugin Support Hai Zheng?

    (@hailite)

    It is a hook. When you get that error that means you try to use our class before its included by WP. If your plugin loads earlier than LSCWP, and you directly used LiteSpeed_Cache_API, it will happen.

    I don’t think you should run LiteSpeed_Cache_API when your plugin is included by WP in wp-settings.php line 301 // Load active plugins.

    Thread Starter conorseed

    (@conorseed)

    That makes sense now thank you! ?? I got it working by using the `after_setup_theme’ action as you suggested.

    I do have another question though: does an ESI block load fresh every time, even for logged out users?

    Thread Starter conorseed

    (@conorseed)

    Ok, so I found in the documentation to set the below but it’s still caching the block in the public cache. Any ideas?

    LiteSpeed_Cache_API::esi_url($block_id, $wrapper, $params = array(), $control = 'private,no-vary')

    Set $control = 'no-cache' to set the ESI block as non-cacheable.

    Plugin Support Hai Zheng?

    (@hailite)

    Do you want it to be no cache? if its no cache, it will hit php each time even the main page is cached, that will slow down the main page loading. That will make the cache of main page is not that useful.

    Private cache has a separate cache TTL, default to 1800s in General setting. If you want to short that particular ESI TTL, just use API to set TTL in hook_esi() before echo.

    Thread Starter conorseed

    (@conorseed)

    @hailite Thanks for the response.

    I thought no cache would be the best option in terms of making sure the block always shows the most recent information. It is linked into a booking system via API: it shows upcoming courses, as well as how many spots are left on each course.

    Currently (even with the esi block set to “no-cache”), the whole page is cached. Which means it’s outdated after an hour – often showing the wrong number of spots left, or a course which is no longer available to book.

    If I set it to “private”, will the block always show the most recent info for ANY user (logged in or not)?

    • This reply was modified 6 years, 7 months ago by conorseed.
    Plugin Support LiteSpeed Lisa

    (@lclarke)

    Hi, @conorseed

    If I set it to “private”, will the block always show the most recent info for ANY user (logged in or not)?

    Not exactly. Here’s what the different ESI block settings mean:

    • Public: there is one copy of the ESI block stored in cache, and that same copy is served to anyone who requests it.
    • Private: there is a separate copy of the ESI block stored in the cache for each person who requests it. So, for example, if there are 300 visitors to your site, there are 300 individual copies of the ESI block cached.
    • No Cache: the block is not cached at all, and PHP must run each time the ESI block is requested.

    As to which one you should use? It’s tempting to choose “No Cache” when you want up-to-the-minute information, but this can slow down your site considerably. The biggest benefit to caching is that PHP does not have to be invoked when a page is served. If you have uncached blocks on your page, you lose that benefit.

    Rather than setting your ESI block to “no Cache” it is better to make it either Public or Private, and then set a very small TTL, say 10 minutes. Then, the data will never be more than 10 minutes old, and any visitors in that time period will get the speed benefits of having the entire page served from cache. If you can go longer than 10 minutes, all the better.

    Now, as far as whether it should be Public or Private? That depends on the content of the block. Does everyone who visits the page see the same content in that block? If so, then it can be Public. Is the block somehow personalized for individual users? Then it should be Private.

    I hope that clears it up! If you’d like more information on this topic, along with some examples, take a look at our blog. We’ve got a few different posts that explain the concepts involved in Private/Public/ESI caching, but this one is probably the most relevant to your situation.

    Let us know if you have any more questions!

Viewing 15 replies - 1 through 15 (of 19 total)
  • The topic ‘ESI API Help <3’ is closed to new replies.