J'ai un widget Instagram qui utilise un instagram-scrapper qui met en cache ses données dans un transitoire pour afficher des photos, en fonction d'un nom d'utilisateur entré dans le Customizer.
Malheureusement, lorsque je mets à jour mon nom d'utilisateur, le transitoire ne se met pas à jour. Il utilise l'ancien (de l'ancien nom d'utilisateur), cela ne me permet pas de rendre les photos du nouveau nom d'utilisateur, ce qui rend le widget un peu inutile après la première utilisation.
En bref, je cherche quelque chose comme:
if( is_updated($username) ? new_transient($username) : get_transient($username)
.
scrapper [passez au bloc suivant pour le bit transitoire]:
<?php
namespace Social_Space;
/**
* Interface to scrape most popular JSON-enabled social networks.
*/
interface Scrape_Interface {
/* Builds the end-point, or the link that will be queried */
public function build_endpoint();
/* Ingests the pure, non-altered JSON data */
public function get_json();
/* Handles and cleans the data */
public function get_data();
}
class Scrape_Instagram implements Scrape_Interface {
private $username;
public function set_username( $username ) {
$this->username = $username;
}
/**
* Builds the endpoint for the Instagram API, provided the username from constructor.
* @param $end_cursor Used in case the user wants more pictures to be scrapped.
*/
public function build_endpoint() {
return 'https://www.instagram.com/' . trim( strtolower( $this->username ) ) . '/?__a=1';
}
/**
* GETs the data from Instagram, provided the endpoint.
*/
public function get_json() {
if ( false === ( $data = get_transient( 'instagram_data' ) ) ) {
$request = wp_remote_get( $this->build_endpoint() );
if( is_wp_error( $request ) ) {
return new WP_Error( 'site-down', esc_html__( 'Instagram may be down. Unable to communicate.', '_s') );
}
elseif( wp_remote_retrieve_response_code( $request ) !== 200 ) {
return new WP_Error( 'invalid-response', esc_html__( 'Got an invalid response.', '_s') );
}
else {
set_transient( 'instagram_data', wp_remote_retrieve_body( $request ), 5 );
}
}
return $data;
}
/**
* Ingests the data from get_json() then converts / decodes into an array.
*/
public function get_data() {
$json = $this->get_json();
if( is_wp_error( $json ) ) {
return new WP_Error( 'invalid-json', esc_html__( 'Something is wrong. Did you enter the right username?', '_s' ) );
}
$data = json_decode( $json, true);
if( is_wp_error( $data ) ) {
return new WP_Error( 'invalid-data', esc_html__( 'Something is wrong. Did you enter the right username?', '_s' ) );
} else {
return $data;
}
}
}
class Generate_Instagram_Links {
private $instagram_object;
private $username;
public function __construct( $username, Scrape_Instagram $instagram_object = null ) {
$this->username = $username;
$this->instagram_object = $instagram_object === null ? new Scrape_Instagram : $instagram_object;
$this->instagram_object->set_username( $this->username );
}
/**
* Generates the link to the source image, as well as to the instagram post of each image
* requested by our script.
*/
public function get_links() {
$response = $this->instagram_object->get_data();
/**
* Based on the array generated from get_data(), some nodes have resulted that contain * information about
* each photo the user has, as such, we'll loop through each photo and access any data.
* @see ['user']['media']['nodes'] - individual node / image.
*/
if( is_wp_error( $response ) ) {
return new WP_Error( 'invalid-json', esc_html__( 'Ouch. The data was not parsed correctly. Cannot continue.' ) );
} else {
foreach( $response['user']['media']['nodes'] as $node ) {
$image = array('real_link' => 'src' );
$image['real_link'] = 'https://www.instagram.com/p/' . $node['code'] . '?taken-by=' . $this->username;
$image['src'] = $node['thumbnail_resources'][0]['src'];
$images_links[] = $image;
}
}
return $images_links;
}
/**
* Getter for the instagram links (non-local).
*/
public function get_instagram_photos_links() {
$links = $this->get_links();
if( is_wp_error( $links) ) {
return new WP_error( 'unknown-error', esc_html__( 'Something went wrong. Cannot get data. Check username or contact developer.') );
} else {
return $links;
}
}
/**
* Gets the local photo links of the newly added instagram photo links, or retrieves the
* links if they already exist(to not flood the media library).
* @todo Add an "expiry" date for each image, or remove if no longer used.
*/
private function get_local_links() {
// Requires loading of the wp-admin scripts.
require_once ('wp-load.php');
require_once ('wp-admin/includes/admin.php');
$urls = $this->get_instagram_photos_links();
$local_images = array();
foreach( $urls as $url ) {
$tmp = download_url( $url['src'] );
$file_array = array(
'name' => basename( $url['src'] ),
'tmp_name' => $tmp
);
$wp_upload_dir = wp_get_upload_dir();
$local_url = $wp_upload_dir['path'] . '/' . $file_array['name'];
if( file_exists( $local_url ) ) {
array_Push( $local_images, ($wp_upload_dir['url'] . '/' . $file_array['name']) );
} else {
if ( is_wp_error( $tmp ) ) {
@unlink( $file_array[ 'tmp_name' ] );
return $tmp;
}
$GLOBALS['post'] = null;
$post_id = '0';
$id = media_handle_sideload( $file_array, $post_id, $desc = null, $post_data = array('post_content' => 'insta_image' ) );
if ( is_wp_error( $id ) ) {
@unlink( $file_array['tmp_name'] );
return $id;
}
$value = wp_get_attachment_url( $id );
array_Push( $local_images, $value );
}
}
return $local_images;
}
/**
* Getter for the instagram links (local).
*/
public function get_instagram_local_photos_links() {
$links = $this->get_local_links();
if( is_wp_error( $links) ) {
return new WP_error( 'unknown-error', esc_html__( 'I cannot get the local links of the pictures. Check with the developer.' ) );
} else {
return $links;
}
}
}
à savoir la fonction "get_json":
public function get_json() {
if ( false === ( $data = get_transient( 'instagram_data' ) ) ) {
$request = wp_remote_get( $this->build_endpoint() );
if( is_wp_error( $request ) ) {
return new WP_Error( 'site-down', esc_html__( 'Instagram may be down. Unable to communicate.', '_s') );
}
elseif( wp_remote_retrieve_response_code( $request ) !== 200 ) {
return new WP_Error( 'invalid-response', esc_html__( 'Got an invalid response.', '_s') );
}
else {
set_transient( 'instagram_data', wp_remote_retrieve_body( $request ), 5 );
}
}
return $data;
}
Comme indiqué, cela ne fonctionnera pas. Voici mon widget où je recherche une mise à jour de $username
avant de faire quoi que ce soit, dans la fonction widget()
.
<?php
/**
* Plugin Name: Instagram Widget
*/
add_action( 'widget_init', 'custom_widget_instagram_pictures');
register_widget( 'custom_widget_instagram_pictures' );
class custom_widget_instagram_pictures extends Wp_Widget {
/**
* Setup the Widget
*/
public function __construct() {
$widget_ops = array('classname' => 'custom_widget_instagram_pictures',
'description' => esc_html__('A widget to display instagram photos.', '_s')
);
$control_ops = array('id_base' => 'custom_widget_instagram_pictures');
parent::__construct( 'custom_widget_instagram_pictures', __('_s: Instagram Widget', '_s_instagram_widget'), $widget_ops, $control_ops );
}
public function widget( $args, $instance ) {
extract( $args );
$title = isset( $instance['title'] ) ? apply_filters('widget_title', $instance['title'] ) : '';
$username = isset( $instance['username'] ) ? $instance['username'] : '';
$profile_link = isset( $instance['profile_link'] ) ? $instance['profile_link'] : '';
$columns = isset( $instance['columns'] ) ? $instance[ 'columns'] : '';
$save_local = isset( $instance['save_local'] ) ? $instance['save_local'] : '';
$number_of_photos = isset( $instance['number_of_photos'] ) ? $instance['number_of_photos'] : '';
echo ent2ncr( $before_widget );
if ( $title ) {
echo ent2ncr( $before_title . $title . $after_title );
}
?>
<div class="instagram-widget">
<?php
if( $username ) {
$instagram_object = new Social_Space\Generate_Instagram_Links( $username, new Social_Space\Scrape_Instagram );
if ( !$save_local ) {
$instagram_links = $instagram_object->get_instagram_photos_links();
if( is_wp_error( $instagram_links ) ) {
echo "Ouch. Something's wrong. Did you enter the right username?";
} else {
$instagram_links_parsed = 0;
?>
<ul class="instagram-widget-list">
<?php
foreach( $instagram_links as $link ) {
if ( $instagram_links_parsed < absint( $number_of_photos ) ) {
$instagram_links_parsed++;
?>
<li class="instagram-thumb instagram-thumb-<?php echo $columns ?>-col">
<a href="<?php echo $link['real_link']; ?>"><img src="<?php echo $link['src']; ?>"/></a>
</li>
<?php
}
else {
break;
}
}
?>
</ul>
<?php
}
}
elseif ( $save_local ) {
$instagram_links = $instagram_object->get_instagram_local_photos_links();
if( is_wp_error( $instagram_links ) ) {
echo "Ouch. Something's wrong. Did you enter the right username?";
} else {
$instagram_links_parsed = 0;
?>
<ul class="instagram-widget-list">
<?php
foreach( $instagram_links as $link ) {
if ( $instagram_links_parsed < absint( $number_of_photos ) ) {
$instagram_links_parsed++;
?>
<li class="instagram-thumb instagram-thumb-<?php echo $columns ?>-col">
<a href="<?php echo $link; ?>"><img src="<?php echo $link; ?>"/></a>
</li>
<?php
}
else {
break;
}
}
?>
</ul>
<?php
}
}
} else {
echo _s_setup_widget_notification();
} ?>
<?php if( 'on' == $profile_link ) : ?>
<button class="instagram-widget-profile-link"><a href="<?php echo 'https://www.instagram.com/' . $username; ?>"><i class="sf-4"></i><p><?php echo $username ?></p></a></button>
<?php endif; ?>
</div>
<?php
echo ent2ncr( $after_widget );
}
function update( $new_instance, $old_instance ) {
$instance['title'] = ( isset( $new_instance['title'] ) ) ? strip_tags($new_instance['title'] ) : '';
$instance['username'] = ( isset( $new_instance['username'] ) ) ? strip_tags( $new_instance['username'] ) : '';
$instance['profile_link'] = ( isset( $new_instance['profile_link'] ) ) ? strip_tags( $new_instance['profile_link'] ) : '';
$instance['columns'] = ( isset( $new_instance['columns'] ) ) ? strip_tags( $new_instance['columns'] ) : '';
$instance['save_local'] = ( isset( $new_instance['save_local'] ) ) ? strip_tags( $new_instance['save_local'] ) : '';
$instance['number_of_photos'] = ( isset( $new_instance['number_of_photos'] ) ) ? strip_tags( $new_instance['number_of_photos'] ) : '';
return $instance;
}
function form( $instance ) {
$defaults = array( 'title' => '',
'username' => '',
'profile_link' => '',
'columns' => '3',
'save_local' => '',
'number_of_photos' => '12',
);
$instance = wp_parse_args( (array) $instance, $defaults ); ?>
<!-- Custom Message -->
<div class="customizer-custom-message-1">
<p>Hey! Just one second. We strongly advise you keep an "even" number of images, 3 columns should have 3,6,9...photos. A 2 columns layout should have 2,4,6 and so on. Looks much better this way! </p>
</div>
<!-- Form for Title -->
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>">Widget Title:<strong>(Leave Blank to Hide)</strong></label>
<br>
<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title'];?>" />
</p>
<!-- Form for Username -->
<p>
<label for="<?php echo $this->get_field_id( 'username' ); ?>">Username:</label>
<br>
<input class="widefat" id="<?php echo $this->get_field_id( 'username' ); ?>" name="<?php echo $this->get_field_name( 'username' ); ?>" value="<?php echo $instance['username'];?>" />
</p>
<!-- Checkbox for Local -->
<p>
<input class="checkbox" type="checkbox" <?php checked( $instance[ 'save_local' ], 'on' ); ?> id="<?php echo $this->get_field_id( 'save_local' ); ?>" name="<?php echo $this->get_field_name( 'save_local' ); ?>" />
<label for="<?php echo $this->get_field_id( 'save_local' ); ?>">Save Images to Local</label>
</p>
<!-- Checkbox for Profile Link -->
<p>
<input class="checkbox" type="checkbox" <?php checked( $instance[ 'profile_link' ], 'on' ); ?> id="<?php echo $this->get_field_id( 'profile_link' ); ?>" name="<?php echo $this->get_field_name( 'profile_link' ); ?>" />
<label for="<?php echo $this->get_field_id( 'profile_link' ); ?>">Show Instagram Button?</label>
</p>
<!-- Columns -->
<p>
<label for="<?php echo $this->get_field_id( 'columns' ); ?>">How Many Columns to Display?<strong>(Leave Blank to Hide)</strong></label>
<br>
<input class="widefat" id="<?php echo $this->get_field_id( 'columns' ); ?>" name="<?php echo $this->get_field_name( 'columns' ); ?>" value="<?php echo $instance['columns'];?>" />
</p>
<!-- Number of Photos -->
<p>
<label for="<?php echo $this->get_field_id( 'number_of_photos' ); ?>">How Many Pictures?</label>
<br>
<input class="widefat" id="<?php echo $this->get_field_id( 'number_of_photos' ); ?>" name="<?php echo $this->get_field_name( 'number_of_photos' ); ?>" value="<?php echo $instance['number_of_photos'];?>" />
</p>
<?php
}
}
La chose la plus simple à faire est simplement de supprimer le transitoire lorsque le nom d'utilisateur est mis à jour. Ensuite, lors de la prochaine exécution de get_json()
, il constatera que le transitoire n'est pas défini, comme si elle avait expiré, puis récupérerait les données et enregistrerait à nouveau le transitoire.
Ainsi, dans la méthode update()
de votre classe de widgets, procédez comme suit:
if ( $new_instance['username'] !== $old_instance['username'] ) {
delete_transient( 'instagram_data' );
}
Cependant, un problème avec la façon dont vous définissez le transitoire est qu’il n’ya qu’un seul transitoire, instagram_data
, qui sera récupéré quel que soit le nom d’utilisateur pour lequel vous obtenez les données. Ainsi, même si vous supprimez le transitoire lors de la mise à jour du widget, si l'utilisateur ajoute plusieurs widgets avec des noms d'utilisateur différents, le transitoire ne contiendra jamais que les données du premier nom d'utilisateur ayant traversé get_json()
.
Vous pouvez résoudre ce problème en créant un transitoire pour chaque utilisateur. Cela impliquerait simplement d'incorporer le nom d'utilisateur dans le nom du transitoire en procédant ainsi dans votre méthode get_json()
:
$transient_name = $this->username . '_instagram_data';
if ( false === ( $data = get_transient( $transient_name ) ) ) {
// etc.
else {
set_transient( $transient_name, wp_remote_retrieve_body( $request ), 5 );
}
Et le code dans votre méthode de mise à jour de widget deviendrait:
if ( $new_instance['username'] !== $old_instance['username'] ) {
delete_transient( $old_instance['username'] . '_instagram_data' );
}
Ce n'est plus nécessaire cependant, car s'il y a un nouveau nom d'utilisateur, il y aura un nouveau transitoire, mais cela aidera à garder la base de données exempte de transitoires inutiles.