Getting Eventbrite API WordPress plugin to work on systems with 32-bit builds of PHP

Last week I had to use the Eventbrite API plugin to show upcoming events on a client’s website. The plugin does all the work out of the box; if you are happy with the default appearance, there is no need to write a single line of code to get it working. You just need to connect your Eventbrite account and create a page that uses the template that the plugin provides. It just works… as long as you are using a 64-bit build of PHP.

If you are using a 32-bit build of PHP, there are some features that don’t work:

  1. the_permalink()  and get_the_permalink()  return a broken URL.
  2. Pages for single events show none of the event’s information.
  3. The ticket form widget shows an error saying the event is not publicly available.

The three problems above have the same cause: the ID of Eventbrite’s events cannot be represented as 32-bit integers, but that’s exactly the data type that WordPress uses to store the ID of posts. Since Eventbrite API is designed to make events available as if they were instances of custom post types, WordPress applies the same sanitization procedures that it applies to posts found in the website’s database. However, every time WordPress converts the event’s ID from a string (as returned by the API) to an integer, the ID property ends up having a value of 2147483647 , which is the maximum value for a 32-bit signed integer.

The original event’s ID is lost in the sanitization process, causing every function that uses that value to return incorrect results.

In order to overcome the problems described above and knowing that it was all caused because the ID being used was not the event’s ID, I used several WordPress and Eventbrite API filters to insert the correct value in key places.

Depending on your needs, you may have additional issues, but I expect all of them to be caused by the same error: the event ID being used is not really the event’s ID. Hopefully the code below my inspire you to create similar workarounds to get your implementation working.

the_permalink()  and get_the_permalink()  return a broken URL

Eventbrite API uses the post_link  filter to provide a custom permalink. However, their functions uses the ID property of the post object, which we already know no longer holds the value we want.

I copied their function, edited the code to use a different property (event_id ) and created my own handler for the post_link  filter:

function wvega_850_filter_event_permalink( $url ) { // eg. http://mysite.com/events/july-test-drive-11829569561
    if ( function_exists( 'eventbrite_is_event' ) && eventbrite_is_event() ) {
        $url = sprintf( '%1$s/%2$s/%3$s-%4$s/',
            esc_url( home_url() ),                             // protocol://domain
            sanitize_title( get_queried_object()->post_name ), // page-with-eventbrite-template
            sanitize_title( get_post()->post_title ),          // event-title
            get_post()->event_id                               // event ID
        );
    }

    return $url;
}
add_filter( 'post_link', 'wvega_850_filter_event_permalink', 11 );

The event_id  property is a string that holds the value the ID property had before WordPress converted it to int. I created a handler for the_post action that grabs the original value and stores it in that property:

function wvega_850_eventbrite_workaround( $post ) {
    if ( ! is_a( $post, 'Eventbrite_Event' ) ) {
        return;
    }

    if ( ! is_integer( $post->ID ) ) {
        $post->event_id = $post->ID;
    }
}
add_action( 'the_post', 'wvega_850_eventbrite_workaround' );

Having the event’s ID stored as the event_id  property of the post object is what makes all my other workarounds possible.

Pages for single events show none of the event’s information

UPDATE (2015-09-13): The single event page will show information about the same event, no matter which event is being requested in the URL. This is an issue also caused by the real ID of the event not being available. Unfortunately, I don’t have a way to fix this using existing hooks. I’m currently trying to get a new hook added to the plugin so that I can create another workaround for this problem.

UPDATE (2015-09-14): The hook was accepted by Eventbrite API’s developers and will be included in the next release. I included a new function below (wvega_850_eventbrite_transient_name ) that uses that filter to make sure the information shown in single event pages always corresponds to the event being requested.

The single page for Eventbrite events uses a sub-class of WP_Query to retrieve the information of the event being shown. The page captures the event’s ID from the URL (the custom permalink generated in the previous step), moves the value into a query var using Rewrite rules and, finally, passes the value as the p  parameter of the query.

However, WordPress also converts that value to an integer. When the Eventbrite API plugin makes a request to retrieve the event’s information, the ID of the event is no longer available causing the request to return an empty object.

The code below uses the http_api_curl  action to capture all requests sent to http://www.eventbriteapi.com and replace the incorrect ID with the value we stored in event_id .

function wvega_850_http_api_curl( $handle, $r, $url ) {
    if ( false === strpos( $url, 'www.eventbriteapi.com' ) || false === strpos( $url, '2147483647' ) ) {
        return;
    }

    $eventbrite_id = get_query_var( 'eventbrite_id' );

    if ( empty( $eventbrite_id ) ) {
        return;
    }

    $new_url = str_replace( '2147483647', $eventbrite_id, $url );
    curl_setopt( $handle, CURLOPT_URL, $new_url);
}
add_action( 'http_api_curl', 'wvega_850_http_api_curl', 10, 3 );

Please note that the code above will work only if the HTTP requests are being made using cURL. If a different transport is used, the http_api_curl action won’t be fired.

Next, we need to filter the name of the transient Eventbrite API uses to cache query results. Otherwise our single event pages will start showing the same information, no matter what event was requested.

function wvega_850_eventbrite_transient_name( $transient_name, $endpoint, $params ) {
    if ( $endpoint == 'event_details' ) {
        $params['p'] = get_query_var( 'eventbrite_id' );
        $transient_name = 'eventbrite_' . md5( $endpoint . implode( $params ) );
    }

    return $transient_name;
}
add_filter( 'eventbrite_transient_name', 'wvega_850_eventbrite_transient_name', 10, 3 );

The problem with the default implementation is that the value stored in $params[‘p’]  is always 2147483647 . The code above replaces that value with the real event ID and then creates the transient name using the same expression used in the original function.

The eventbrite_transient_name  filter does not exists in Eventbrite API 1.0.8 or below, but it will be available in future versions. If version 1.0.8 is still the latest  version when you are reading this post, then you need to update the get_transient_name()  method in Eventbrite Manager class, replacing the following code:

protected function get_transient_name( $endpoint, $params ) {
    // Results in 62 characters for the timeout option name (maximum is 64).
    return 'eventbrite_' . md5( $endpoint . implode( $params ) );
}

with this one:

protected function get_transient_name( $endpoint, $params ) {
    // Results in 62 characters for the timeout option name (maximum is 64).
    $transient_name = 'eventbrite_' . md5( $endpoint . implode( $params ) );
    return apply_filters( 'eventbrite_transient_name', $transient_name, $endpoint, $params );
}

In this case is ok to edit a plugin’s code. The changes we are introducing are exactly the same ones that will be available in the next release.

If you ever need to change how a plugin works, please consider sending a patch to the author first. That way others benefit from your modifications and you don’t need to keep applying your modifications every time a new version of the affected plugin is released.

The ticket form widget shows an error saying the event is not publicly available

The problem here is similar to the one above. The widget generated by the Eventbrite API plugin points to the wrong URL because it uses the an incorrect value for the event’s ID.

Luckily, the plugin has a filter that we can use to modify the code used to generate the widget before is sent to the browser. I created a handler for the eventbrite_ticket_form_widget filter and used a simple regular expression to find the incorrect value and replace it with the one stored in event_id .

function wvega_850_eventbrite_ticket_form_widget( $form_widget ) {
    $event_id = get_post()->event_id;

    if ( empty( $event_id ) ) {
        return $form_widget;
    }

    return preg_replace( '/eid=d+/', 'eid=' . urlencode( $event_id ), $form_widget );
}
add_filter( 'eventbrite_ticket_form_widget', 'wvega_850_eventbrite_ticket_form_widget' );

Conclusion

Many other functions that use the ID property of the current post object are probably broken as well; I just didn’t need those to be working in this case. The above are just workarounds and a are far from a real solution.

If you really want to solve all those problems, the solution is to start using a 64-bit version of PHP, but if you can’t do that and you still want to use the Eventbrite API plugin to bring Eventbrite events to your WordPress website, I hope the code above helps you.

How to add a subpages menu to WordPress pages

WordPress allows the creation of nested pages. That’s a great feature when you need to split a rather long content into several parts and give them some structure. However, the problem is you’ll have to manually add links to the additional pages in order to make it easy for the user to navigate through all the content. Wouldn’t it be great if you could automatically add a menu, right inside the content of your pages, with links to the subpages or parent of current page? I think it would, and I’ll show you how… Continue reading

JSFiddle Shortcode

JSFiddle Shortcode is a WordPress plugin to help you to easily embed Fiddles in your posts.

I was working on a post and wanted to embed a Fiddle to show an example. I’m currently using GitHub Gist Shortcode plugin to embed gists and tough there maybe something similar for JSFiddle, but after a quick search I couldn’t find anything available in the Plugin Directory. I decided to created it my self and this the result.

Continue reading

Deshabilitar WP-SynHighlight en el contenido mostrado en los feeds

WP-SynHighlight es un plugin para WordPress que permite mostrar codigo fuente con sintaxis resaltada en el contenido de los posts. Este plugin hace uso de GeShi para resaltar el código y por tanto soporta todos los lenguajes soportados por GeShi.

Hoy estaba revisando como se ven los posts  en este blog cuando son leidos desde un  FeedReader como Google Reader o Liferea. El problema con resaltar el código con una solución del lado del servidor como WP-SynHighlight es que no importa como se acceda el contenido, WordPress siempre va a incluir en la respuesta una cantidad de elementos HTML con el mero objetivo de mejorar la presentación. Creo que cuando un usuario está leyendo el contenido a través de un FeedReader está mas interesado en la estructura y el contenido, no tanto su presentación, de otro modo iría directamente a la fuente. Así, enviar contenido con código fuente resaltado a quienes usan FeedReaders me parece innecesario porque a) sin las hojas de estilo utilizadas en el sitio fuente el contenido no aparece realmente resaltado y b) los elementos HTML que antes permitían resaltar el código ahora dificultan que el lector lo manipule: un simple copy-paste da como resultado código mal formado y numeros de línea entre las linea de código. Vea como evitarlo…